Try to fix grave/sarcophagus etc. not working

1. Added new prepatch `TryFindBestBetterStorageForPatch`
2. Rebuilt for realse so that changes take effect

`TryFindBestBetterStoreCellForPatch` had been deciding which item should be removed from `listerHaulables`, which improves performance.
But it had been checking `SlotGroup`s only.
Patching `TryFindBestBetterStorageForPatch` to cancel the removal if the best storage is non-cell could solve the issue of grave/armor rack etc. not working.

Tried several things. Nothing broke, and it solved said problem.
This commit is contained in:
Foxtr0t1337
2024-12-28 08:20:29 +08:00
parent 3fe7b864b9
commit eda1f302b7
5 changed files with 89 additions and 128 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -233,7 +233,7 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
{ {
public override string? Description { get; } public override string? Description { get; }
= "Optimizes a loop in the method to treat storage groups as proper groups without duplicate checks and to " = "Optimizes a loop in the method to treat storage groups as proper groups without duplicate checks and to "
+ "make use of cached storage priorities for fewer comparisons against those. Also flags haulables for removal from " + "make use of cached storage priorities for fewer comparisons against those. Also removes haulables from "
+ "ListerHaulables if the found best store cell turns out to be the current cell"; + "ListerHaulables if the found best store cell turns out to be the current cell";
public override MethodBase TargetMethodBase { get; } = methodof(StoreUtility.TryFindBestBetterStoreCellFor); public override MethodBase TargetMethodBase { get; } = methodof(StoreUtility.TryFindBestBetterStoreCellFor);
@@ -260,7 +260,6 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
var foundPriority = currentPriority; var foundPriority = currentPriority;
var closestDistSquared = (float)int.MaxValue; var closestDistSquared = (float)int.MaxValue;
var closestSlot = IntVec3.Invalid; var closestSlot = IntVec3.Invalid;
var alreadyBest = false;
var hadToFixCache = false; var hadToFixCache = false;
@@ -277,7 +276,7 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
if ((StoragePriority)priorityGroupIndex <= currentPriority) // current storage is highest valid priority if ((StoragePriority)priorityGroupIndex <= currentPriority) // current storage is highest valid priority
{ {
alreadyBest = true; TryRemoveFromListerHaulables(t, currentPriority);
break; break;
} }
@@ -330,7 +329,7 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
Result: Result:
if (!closestSlot.IsValid) if (!closestSlot.IsValid)
{ {
foundCell = alreadyBest ? IntVec3.Zero : IntVec3.Invalid; foundCell = IntVec3.Invalid;
return false; return false;
} }
@@ -356,11 +355,7 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
public static void LogErrorForFailedTryFindBestBetterStoreCellForAttempt(Thing t, Pawn carrier, Map? map, public static void LogErrorForFailedTryFindBestBetterStoreCellForAttempt(Thing t, Pawn carrier, Map? map,
StoragePriority currentPriority, Faction faction, IntVec3 closestSlot) StoragePriority currentPriority, Faction faction, IntVec3 closestSlot)
=> Log.Error($"Performance Fish's TryFindBestBetterStoreCellFor patch failed to compute accurate " => Log.Error($"Performance Fish's TryFindBestBetterStoreCellFor patch failed to compute accurate "
+ $"results after a recache attempt for thing '{t}', pawn '{carrier}', map '{ + $"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)}");
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)}");
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
public static void UpdateCache(HaulDestinationManager haulDestinationManager) public static void UpdateCache(HaulDestinationManager haulDestinationManager)
@@ -392,6 +387,30 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
public static int[] GetCachedGroupCountByPriority(HaulDestinationManager haulDestinationManager) public static int[] GetCachedGroupCountByPriority(HaulDestinationManager haulDestinationManager)
=> haulDestinationManager.Cache().GroupCountByPriority; => haulDestinationManager.Cache().GroupCountByPriority;
[MethodImpl(MethodImplOptions.NoInlining)]
public static void TryRemoveFromListerHaulables(Thing t, StoragePriority currentPriority)
{
if (ModCompatibility.ActiveMods.Multiplayer | !HaulablesTickPatchActive)
return;
if (t.IsInAnyStorage() /*t.IsInValidStorage()*/ && t.TryGetMapHeld() is { } map)
map.listerHaulables.Cache().ThingsQueuedToRemove.Add(t);
// remove for any storage instead of only valid storage to prevent further haul attempts until the next
// automatic ListerHaulablesTick cycle
}
private static int _haulablesTickPatchActive = int.MaxValue;
private static bool HaulablesTickPatchActive
=> _haulablesTickPatchActive != int.MaxValue
? _haulablesTickPatchActive.AsBool()
: UpdateHaulablesTickPatchActive();
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool UpdateHaulablesTickPatchActive()
=> (_haulablesTickPatchActive = Get<Haulables.TickPatch>().IsActive.AsInt()).AsBool();
public static class Debug public static class Debug
{ {
[Conditional("STORAGE_GROUP_DEBUG")] [Conditional("STORAGE_GROUP_DEBUG")]
@@ -404,9 +423,7 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
if (otherSlotGroup.StorageGroup == storageGroup) if (otherSlotGroup.StorageGroup == storageGroup)
continue; continue;
Log.Error($"Incorrect haul destination order! Storage '{ Log.Error($"Incorrect haul destination order! Storage '{otherSlotGroup.parent}' was expected to have Storage group '{storageGroup}', but had '{otherSlotGroup.StorageGroup.ToStringSafe()}' instead");
otherSlotGroup.parent}' was expected to have Storage group '{storageGroup}', but had '{
otherSlotGroup.StorageGroup.ToStringSafe()}' instead");
} }
} }
@@ -425,9 +442,7 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
var storageGroups = haulDestinationManager!.map.storageGroups.groups; var storageGroups = haulDestinationManager!.map.storageGroups.groups;
return StringHelper.Resolve($"SlotGroup count: { return StringHelper.Resolve($"SlotGroup count: {slotGroupsInPriorityOrder.Count}, StorageGroup count: {storageGroups.Count}, slotGroups in storage groups: {storageGroups
slotGroupsInPriorityOrder.Count}, StorageGroup count: {
storageGroups.Count}, slotGroups in storage groups: {storageGroups
.Select(static group => group!.SpawnedMemberCount()) .Select(static group => group!.SpawnedMemberCount())
.Sum()}, outside of storage groups: {slotGroupsInPriorityOrder .Sum()}, outside of storage groups: {slotGroupsInPriorityOrder
.Select(static slotGroup => slotGroup.StorageGroup) .Select(static slotGroup => slotGroup.StorageGroup)
@@ -438,89 +453,35 @@ public sealed class StoreUtilityPrepatches : ClassWithFishPrepatches
} }
} }
public sealed class TryFindBestBetterStorageForPatch : FishPrepatch public sealed class TryFindBestBetterStorageForPatch : FishPrepatch
{ {
public override string? Description { get; }
= "Cancel the removal of haulables if there is a better non-cell storage. "
+ "Only needed when TryFindBestBetterStoreCellFor is enabled.";
public override string? Description { get; } public override MethodBase TargetMethodBase { get; } = methodof(StoreUtility.TryFindBestBetterStorageFor);
= "Removes haulables from ListerHaulables if the found best store cell turns out to be the current cell. "
+ "Need TryFindBestBetterStoreCellFor to work.";
public override MethodBase TargetMethodBase { get; } = methodof(StoreUtility.TryFindBestBetterStorageFor); public static void Postfix(Thing t, Pawn carrier, Map map, StoragePriority currentPriority, Faction faction, ref IntVec3 foundCell, ref IHaulDestination haulDestination, bool needAccurateResult, ref bool __result)
{
if (StoreCellForPatchActive && __result && foundCell == IntVec3.Invalid && t.TryGetMapHeld() is { } m)
{
var cache = m.listerHaulables.Cache();
cache.ThingsQueuedToRemove.Remove(t);
}
}
public override void Transpiler(ILProcessor ilProcessor, ModuleDefinition module) private static int _storeCellForPatchActive = int.MaxValue;
=> ilProcessor.ReplaceBodyWith(ReplacementBody);
public static bool ReplacementBody(Thing t, Pawn carrier, Map map, private static bool StoreCellForPatchActive
StoragePriority currentPriority, Faction faction, out IntVec3 foundCell, out IHaulDestination haulDestination, bool needAccurateResult = true) => _storeCellForPatchActive != int.MaxValue
{ ? _storeCellForPatchActive.AsBool()
if (!StoreUtility.TryFindBestBetterNonSlotGroupStorageFor(t, carrier, map, currentPriority, faction, out haulDestination)) : UpdateStoreCellForPatchActive();
{
haulDestination = null!;
}
if (StoreUtility.TryFindBestBetterStoreCellFor(t, carrier, map, currentPriority, faction, out foundCell, needAccurateResult)) [MethodImpl(MethodImplOptions.NoInlining)]
{ private static bool UpdateStoreCellForPatchActive()
if (haulDestination != null && haulDestination.GetStoreSettings().Priority > foundCell.GetSlotGroup(map).Settings.Priority) => (_storeCellForPatchActive = (Get<TryFindBestBetterStoreCellForPatch>().IsActive
{ && Get<Haulables.TickPatch>().IsActive).AsInt()).AsBool();
foundCell = IntVec3.Invalid; }
}
else
{
haulDestination = foundCell.GetSlotGroup(map).parent;
}
return true;
}
else
{
if (haulDestination == null)
{
if (StoreCellForPatchActive && foundCell != IntVec3.Invalid) // TryFindBestBetterStoreCellForPatch says it's already in best cell
{
foundCell = IntVec3.Invalid;
TryRemoveFromListerHaulables(t, currentPriority);
}
return false;
}
foundCell = IntVec3.Invalid;
return true;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void TryRemoveFromListerHaulables(Thing t, StoragePriority currentPriority)
{
if (ModCompatibility.ActiveMods.Multiplayer | !HaulablesTickPatchActive)
return;
if (t.IsInAnyStorage() /*t.IsInValidStorage()*/ && t.TryGetMapHeld() is { } map)
map.listerHaulables.Cache().ThingsQueuedToRemove.Add(t);
// remove for any storage instead of only valid storage to prevent further haul attempts until the next
// automatic ListerHaulablesTick cycle
}
private static int _storeCellForPatchActive = int.MaxValue;
public static bool StoreCellForPatchActive
=> _storeCellForPatchActive != int.MaxValue
? _storeCellForPatchActive.AsBool()
: UpdateStoreCellForPatchActive();
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool UpdateStoreCellForPatchActive()
=> (_haulablesTickPatchActive = Get<TryFindBestBetterStoreCellForPatch>().IsActive.AsInt()).AsBool();
private static int _haulablesTickPatchActive = int.MaxValue;
private static bool HaulablesTickPatchActive
=> _haulablesTickPatchActive != int.MaxValue
? _haulablesTickPatchActive.AsBool()
: UpdateHaulablesTickPatchActive();
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool UpdateHaulablesTickPatchActive()
=> (_haulablesTickPatchActive = Get<Haulables.TickPatch>().IsActive.AsInt()).AsBool();
}
public sealed class GetSlotGroupPatch : FishPrepatch public sealed class GetSlotGroupPatch : FishPrepatch
{ {