Additional safety checks in StoreUtilityPrepatches:TryFindBestBetterStoreCellFor for better mod compatibility

It was reported to be throwing index out of range exceptions, with unknown cause
This commit is contained in:
bbradson
2024-02-02 14:37:52 +01:00
parent d394d31f05
commit a4ee95fde1
4 changed files with 62 additions and 7 deletions
Binary file not shown.
Binary file not shown.
@@ -257,6 +257,10 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
var closestDistSquared = (float)int.MaxValue; var closestDistSquared = (float)int.MaxValue;
var closestSlot = IntVec3.Invalid; var closestSlot = IntVec3.Invalid;
var hadToFixCache = false;
StartOfLoop:
var listInPriorityOrderCount = listInPriorityOrder.Count;
var groupCountByPriority = GetCachedGroupCountByPriority(haulDestinationManager); var groupCountByPriority = GetCachedGroupCountByPriority(haulDestinationManager);
var i = 0; var i = 0;
for (var priorityGroupIndex = groupCountByPriority.Length; priorityGroupIndex-- > 0;) for (var priorityGroupIndex = groupCountByPriority.Length; priorityGroupIndex-- > 0;)
@@ -274,6 +278,9 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
while (groupsOfPriorityCount-- > 0) while (groupsOfPriorityCount-- > 0)
{ {
if (i >= listInPriorityOrderCount)
goto FixCache;
var slotGroup = listInPriorityOrder[i++]; var slotGroup = listInPriorityOrder[i++];
int otherGroupMembers; int otherGroupMembers;
var storageGroup = slotGroup.TryGetStorageGroup(); var storageGroup = slotGroup.TryGetStorageGroup();
@@ -303,12 +310,16 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
if (otherGroupMembers <= 0) if (otherGroupMembers <= 0)
break; break;
if (i >= listInPriorityOrderCount)
goto FixCache;
otherGroupMembers--; otherGroupMembers--;
slotGroup = listInPriorityOrder[i++]; slotGroup = listInPriorityOrder[i++];
} }
} }
} }
Result:
if (!closestSlot.IsValid) if (!closestSlot.IsValid)
{ {
foundCell = IntVec3.Invalid; foundCell = IntVec3.Invalid;
@@ -317,6 +328,39 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
foundCell = closestSlot; foundCell = closestSlot;
return true; return true;
FixCache:
if (hadToFixCache)
{
LogErrorForFailedTryFindBestBetterStoreCellForAttempt(t, carrier, map, currentPriority, faction,
closestSlot);
goto Result;
}
else
{
hadToFixCache = true;
}
UpdateCache(haulDestinationManager);
goto StartOfLoop;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void LogErrorForFailedTryFindBestBetterStoreCellForAttempt(Thing t, Pawn carrier, Map? map,
StoragePriority currentPriority, Faction faction, IntVec3 closestSlot)
=> Log.Error($"Performance Fish's TryFindBestBetterStoreCellFor patch failed to compute accurate "
+ $"results after a recache attempt for thing '{t}', pawn '{carrier}', map '{
map}', currentPriority '{currentPriority}', faction '{
faction}'. The last found cell was '{
closestSlot}'. It is most likely incompatible with something in the mod list.\n{
Debug.GetStorageGroupInfo(map?.haulDestinationManager?.AllGroupsListInPriorityOrder)}");
[MethodImpl(MethodImplOptions.NoInlining)]
public static void UpdateCache(HaulDestinationManager haulDestinationManager)
{
haulDestinationManager.AllGroupsListInPriorityOrder.InsertionSort(HaulDestinationManager
.CompareSlotGroupPrioritiesDescending);
haulDestinationManager.Cache().OnPriorityChanged(haulDestinationManager);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -355,13 +399,24 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
public static void LogStuff(List<SlotGroup> listInPriorityOrder) public static void LogStuff(List<SlotGroup> listInPriorityOrder)
{ {
LoggedOnce = true; LoggedOnce = true;
var storageGroups = listInPriorityOrder.Select(static slotGroup => slotGroup.TryGetStorageGroup()) Log.Message(GetStorageGroupInfo(listInPriorityOrder));
}
public static string GetStorageGroupInfo(List<SlotGroup>? slotGroupsInPriorityOrder)
{
if (slotGroupsInPriorityOrder is null)
return string.Empty;
var storageGroups = slotGroupsInPriorityOrder.Select(static slotGroup => slotGroup.TryGetStorageGroup())
.Where(Is.NotNull).Distinct().ToList(); .Where(Is.NotNull).Distinct().ToList();
Log.Message($"SlotGroup count: {listInPriorityOrder.Count}, StorageGroup count: {
storageGroups.Count}, slotGroups in storage groups: { return StringHelper.Resolve($"SlotGroup count: {
storageGroups.Select(static group => group!.MemberCount).Sum()}, outside of storage groups: { slotGroupsInPriorityOrder.Count}, StorageGroup count: {
listInPriorityOrder.Select(static slotGroup => slotGroup.TryGetStorageGroup()) storageGroups.Count}, slotGroups in storage groups: {storageGroups
.Where(Is.Null).Count()}"); .Select(static group => group!.MemberCount)
.Sum()}, outside of storage groups: {slotGroupsInPriorityOrder
.Select(static slotGroup => slotGroup.TryGetStorageGroup())
.Where(Is.Null).Count()}");
} }
public static bool LoggedOnce; public static bool LoggedOnce;
@@ -17,7 +17,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<Configurations>v1.4</Configurations> <Configurations>v1.4</Configurations>
<Version>0.3.999.91</Version> <Version>0.3.999.92</Version>
<NoWarn> <NoWarn>
1701;1702;IL2121;CS8500;CS9082;CA1000;CA1002;CA1003;CA1707;CA1010;CA1715;CA1716;CA1724;CA1031;CA1033; 1701;1702;IL2121;CS8500;CS9082;CA1000;CA1002;CA1003;CA1707;CA1010;CA1715;CA1716;CA1724;CA1031;CA1033;
CA1034;CA1043;CA1051;CA1305;CA1310;CA1710;CA1711;CA1810;CA1812;CA1819;CA1851;CA2002;CA5394;CA1725;CA1062 CA1034;CA1043;CA1051;CA1305;CA1310;CA1710;CA1711;CA1810;CA1812;CA1819;CA1851;CA2002;CA5394;CA1725;CA1062