diff --git a/1.5/Assemblies/CleanPathfinding.dll b/1.5/Assemblies/CleanPathfinding.dll
new file mode 100644
index 0000000..e4294c1
Binary files /dev/null and b/1.5/Assemblies/CleanPathfinding.dll differ
diff --git a/1.5/Assemblies/CleanPathfinding.pdb b/1.5/Assemblies/CleanPathfinding.pdb
new file mode 100644
index 0000000..ceae249
Binary files /dev/null and b/1.5/Assemblies/CleanPathfinding.pdb differ
diff --git a/1.5/Patches/patch.owlchemist.cleanpathfinding.xml b/1.5/Patches/patch.owlchemist.cleanpathfinding.xml
new file mode 100644
index 0000000..c676457
--- /dev/null
+++ b/1.5/Patches/patch.owlchemist.cleanpathfinding.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ Defs/TerrainDef[tags]/tags[li/text()="Road" or li/text()="FineFloor"]
+
+ CleanPath
+
+
+
+ Always
+ Defs/TerrainTemplateDef[tags]/tags[li/text()="FineFloor"]
+
+ CleanPath
+
+
+
+ Defs/TerrainDef[defName="PavedTile" or defName="Concrete" or @Name="TileStoneBase"][not(tags)]
+
+
+
+
+
+ Defs/TerrainDef[defName="PavedTile" or defName="Concrete" or @Name="TileStoneBase"]/tags
+
+ CleanPath
+
+
+
+
+
\ No newline at end of file
diff --git a/About/About.xml b/About/About.xml
index ad75689..4d9e0de 100644
--- a/About/About.xml
+++ b/About/About.xml
@@ -6,6 +6,7 @@
1.4
+ 1.5
When pathfinding costs are calculated, any terrain tiles that generate filth are taken into account and given some degree of avoidance. Also, roads can be given a bonus attraction, and the overall pathfinding range can be adjusted. Other features such as light attraction and extra range can also be enabled.
diff --git a/Source/CleanPathfinding.csproj b/Source/CleanPathfinding.csproj
index 3c44b8d..2e2f7b4 100644
--- a/Source/CleanPathfinding.csproj
+++ b/Source/CleanPathfinding.csproj
@@ -9,18 +9,17 @@
net48
preview
false
+ 1.4;1.5
-
- ..\..\..\Mods\$(Product)\$(Version)\Assemblies
- TRACE;NDEBUG
- 4
- false
- None
-
-
+
..\..\..\Mods\$(Product)\$(Version)\Assemblies
TRACE;DEBUG;NETFRAMEWORK;NET48;
+
+ ..\..\..\Mods\Clean Pathfinding\1.5\Assemblies
+ NETFRAMEWORK;NET48;v1_5
+ true
+
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -31,7 +30,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
diff --git a/Source/CleanPathfinding.sln b/Source/CleanPathfinding.sln
new file mode 100644
index 0000000..811372b
--- /dev/null
+++ b/Source/CleanPathfinding.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.34601.136
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CleanPathfinding", "CleanPathfinding.csproj", "{580CD268-7D44-402D-9FBE-76A743993959}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ 1.4|Any CPU = 1.4|Any CPU
+ 1.5|Any CPU = 1.5|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {580CD268-7D44-402D-9FBE-76A743993959}.1.4|Any CPU.ActiveCfg = 1.4|Any CPU
+ {580CD268-7D44-402D-9FBE-76A743993959}.1.4|Any CPU.Build.0 = 1.4|Any CPU
+ {580CD268-7D44-402D-9FBE-76A743993959}.1.5|Any CPU.ActiveCfg = 1.5|Any CPU
+ {580CD268-7D44-402D-9FBE-76A743993959}.1.5|Any CPU.Build.0 = 1.5|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {058A7526-2742-491F-B717-AC7BC5D88641}
+ EndGlobalSection
+EndGlobal
diff --git a/Source/CleanPathfindingUtility.cs b/Source/CleanPathfindingUtility.cs
index dc09058..8f56e5b 100644
--- a/Source/CleanPathfindingUtility.cs
+++ b/Source/CleanPathfindingUtility.cs
@@ -4,6 +4,7 @@
using Verse.AI;
using System;
using System.Collections.Generic;
+using System.Reflection;
using System.Reflection.Emit;
using System.Linq;
using static CleanPathfinding.ModSettings_CleanPathfinding;
@@ -11,15 +12,100 @@
namespace CleanPathfinding
{
#region Harmony
- [HarmonyPatch(typeof(PathFinder), nameof(PathFinder.FindPath), new Type[] {
- typeof(IntVec3),
- typeof(LocalTargetInfo),
- typeof(TraverseParms),
- typeof(PathEndMode),
- typeof(PathFinderCostTuning) })]
- static class Patch_PathFinder
- {
- static IEnumerable Transpiler(IEnumerable instructions)
+
+
+ [HarmonyPatch(typeof(PathFinder))]
+
+ static class Patch_PathFinder_Finalize
+ {
+ /* here to trouble shoot memory leaks
+ * Soyuz caught this error. Please don't report this to the RocketMan team unless you're certain RocketMan caused this error. with error System.OutOfMemoryException: Out of memory
+[Ref 3B9F4383]
+ at (wrapper managed-to-native) System.Object.__icall_wrapper_ves_icall_array_new_specific(intptr,int)
+ at System.Collections.Generic.List`1[T].set_Capacity (System.Int32 value) [0x00021] in :0
+ at System.Collections.Generic.List`1[T].EnsureCapacity (System.Int32 min) [0x00036] in :0
+ at System.Collections.Generic.List`1[T].Add (T item) [0x00010] in :0
+ at Verse.AI.PawnPath.AddNode (Verse.IntVec3 nodePosition) [0x00000] in <957a20e0be784a65bc32cf449445b937>:0
+ at Verse.AI.PathFinder.FinalizedPath (System.Int32 finalIndex, System.Boolean usedRegionHeuristics) [0x00036] in <957a20e0be784a65bc32cf449445b937>:0
+ at Verse.AI.PathFinder.FindPath (Verse.IntVec3 start, Verse.LocalTargetInfo dest, Verse.TraverseParms traverseParms, Verse.AI.PathEndMode peMode, Verse.AI.PathFinderCostTuning tuning) [0x005a5] in <957a20e0be784a65bc32cf449445b937>:0
+ - TRANSPILER Owlchemist.CleanPathfinding.tmp: IEnumerable`1 CleanPathfinding.Patch_PathFinder:Transpiler(IEnumerable`1 instructions)
+ - TRANSPILER OskarPotocki.VanillaFurnitureExpanded.Security: IEnumerable`1 VFESecurity.Patch_PathFinder+FindPath:Transpiler(IEnumerable`1 instructions)
+ at Verse.AI.PathFinder.FindPath (Verse.IntVec3 start, Verse.LocalTargetInfo dest, Verse.Pawn pawn, Verse.AI.PathEndMode peMode, Verse.AI.PathFinderCostTuning tuning) [0x0003e] in <957a20e0be784a65bc32cf449445b937>:0
+ at Verse.AI.Pawn_PathFollower.GenerateNewPath () [0x0005e] in <957a20e0be784a65bc32cf449445b937>:0
+ - PREFIX OskarPotocki.VFECore: Boolean VFECore.PhasingPatches:GenerateNewPath_Prefix(Pawn_PathFollower __instance, Pawn ___pawn, LocalTargetInfo ___destination, PathEndMode ___peMode, PawnPath& __result)
+ at Verse.AI.Pawn_PathFollower.TrySetNewPath () [0x00000] in <957a20e0be784a65bc32cf449445b937>:0
+ at Verse.AI.Pawn_PathFollower.TryEnterNextPathCell () [0x00303] in <957a20e0be784a65bc32cf449445b937>:0
+ - PREFIX juanlopez2008.LightsOut: Void LightsOut.Patches.Lights.DetectPawnRoomChange:Prefix(Pawn ___pawn, Room& __state)
+ - POSTFIX OskarPotocki.VFECore: Void VFECore.PhasingPatches:UnfogEnteredCells(Pawn_PathFollower __instance, Pawn ___pawn)
+ - POSTFIX juanlopez2008.LightsOut: Void LightsOut.Patches.Lights.DetectPawnRoomChange:Postfix(Pawn ___pawn, Room& __state)
+ at Verse.AI.Pawn_PathFollower.PatherTick () [0x00404] in <957a20e0be784a65bc32cf449445b937>:0
+ - PREFIX Krkr.RocketMan.Soyuz: Void Soyuz.Patches.Pawn_PathFollower_Patch+Pawn_PathFollower_PatherTick:Prefix(Pawn_PathFollower __instance)
+ - POSTFIX Krkr.RocketMan.Soyuz: Void Soyuz.Patches.Pawn_PathFollower_Patch+Pawn_PathFollower_PatherTick:Postfix(Pawn_PathFollower __instance)
+ - FINALIZER Krkr.RocketMan.Soyuz: Void Soyuz.Patches.Pawn_PathFollower_Patch+Pawn_PathFollower_PatherTick:Finalizer(Exception __exception)
+ at Verse.Pawn.Tick () [0x000d8] in <957a20e0be784a65bc32cf449445b937>:0
+ - TRANSPILER Krkr.RocketMan.Soyuz: IEnumerable`1 Soyuz.Patches.Pawn_Tick_Patch:Transpiler(IEnumerable`1 instructions, ILGenerator generator)
+ - POSTFIX Roolo.DualWield: Void DualWield.HarmonyInstance.Pawn_Tick:Postfix(Pawn __instance)
+ - FINALIZER Krkr.RocketMan.Soyuz: Void Soyuz.Patches.Pawn_Tick_Patch:Finalizer(Pawn __instance, Exception __exception)
+UnityEngine.StackTraceUtility:ExtractStackTrace ()
+(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:Verse.Log.Error_Patch7 (string)
+RocketMan.Logger:Debug (string,System.Exception,string)
+Soyuz.Patches.Pawn_Tick_Patch:Finalizer (Verse.Pawn,System.Exception)
+(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:Verse.Pawn.Tick_Patch2 (Verse.Pawn)
+(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:Verse.TickList.Tick_Patch2 (Verse.TickList)
+(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:Verse.TickManager.DoSingleTick_Patch4 (Verse.TickManager)
+Verse.TickManager:TickManagerUpdate ()
+(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:Verse.Game.UpdatePlay_Patch2 (Verse.Game)
+Verse.Root_Play:Update ()
+ */
+ static MethodBase TargetMethod()
+ {
+ return typeof(PathFinder).GetMethod("FinalizedPath", BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+
+ [HarmonyPrefix]
+ static bool FinalizedPath_Prefix(ref PathFinder __instance, ref PawnPath __result, int finalIndex, bool usedRegionHeuristics)
+ {
+ PawnPath emptyPawnPath = __instance.map.pawnPathPool.GetEmptyPawnPath();
+ int num = finalIndex;
+
+ int max = 0;
+ for (; ; )
+ {
+ int parentIndex = PathFinder.calcGrid[num].parentIndex;
+ emptyPawnPath.AddNode(__instance.map.cellIndices.IndexToCell(num));
+ if (num == parentIndex)
+ {
+ break;
+ }
+ if (max>1000)
+ {
+
+ TraverseParms traverse = __instance.traverseParms;
+ Log.Warning("bailing out of path calculation for "+traverse.pawn+" with "+traverse.pawn.TicksPerMoveCardinal+"/"+traverse.pawn.TicksPerMoveDiagonal+" TicksPerMoveCardinal/Diagonal after 1000 path nodes added to prevent mem leaks, on num " + num + " aiming for " + parentIndex);
+ __result = PawnPath.NotFound;
+
+ return false;
+ }
+ num = parentIndex;
+ max++;
+ }
+ emptyPawnPath.SetupFound((float)PathFinder.calcGrid[finalIndex].knownCost, usedRegionHeuristics);
+ __result = emptyPawnPath;
+
+ return false;
+ }
+
+ }
+ [HarmonyPatch(typeof(PathFinder), nameof(PathFinder.FindPath), new Type[] {
+ typeof(IntVec3),
+ typeof(LocalTargetInfo),
+ typeof(TraverseParms),
+ typeof(PathEndMode),
+ typeof(PathFinderCostTuning) })]
+ static class Patch_PathFinder
+ {
+
+ static IEnumerable Transpiler(IEnumerable instructions)
{
int offset = -1, objectsFound = 0;
bool ran = false, searchForObjects = false, thresholdReplaced = false;
@@ -48,7 +134,7 @@ static IEnumerable Transpiler(IEnumerable inst
if (searchForObjects && objectsFound < 3 && code.opcode == OpCodes.Ldloc_S)
{
objects[objectsFound++] = code.operand;
- //As of 12/5, object 0 should be 48, object 1 should be 12, and object 2 should be 45
+ //As of 4/2024, object 0 should be 46, object 1 should be 12, and object 2 should be 43
}
if (offset == -1 && code.opcode == OpCodes.Ldfld && code.OperandIs(field_extraNonDraftedPerceivedPathCost))
@@ -56,21 +142,22 @@ static IEnumerable Transpiler(IEnumerable inst
offset = 0;
continue;
}
+
if (offset > -1 && ++offset == 2)
{
- yield return new CodeInstruction(OpCodes.Ldloc_0);
+ yield return new CodeInstruction(OpCodes.Ldloc_0); //pawn
yield return new CodeInstruction(OpCodes.Ldloc_S, objects[1]); //topGrid
- yield return new CodeInstruction(OpCodes.Ldloc_S, objects[2]); //TerrainDef within the grid
- yield return new CodeInstruction(OpCodes.Ldelem_Ref);
- yield return new CodeInstruction(OpCodes.Ldloc_S, objects[0]); //Pathcost total
- yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldloc_S, objects[2]); //topGrid index number
+ yield return new CodeInstruction(OpCodes.Ldelem_Ref); //TerrainDef within the grid
+ yield return new CodeInstruction(OpCodes.Ldloc_S, objects[0]); //Pathcost total
+ yield return new CodeInstruction(OpCodes.Ldarg_0); //start position (not used by adjust cost?)
yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), nameof(PathFinder.map)));
yield return new CodeInstruction(OpCodes.Ldloc_S, objects[2]); //cell location
yield return new CodeInstruction(OpCodes.Call, typeof(CleanPathfindingUtility).GetMethod(nameof(CleanPathfindingUtility.AdjustCosts)));
yield return new CodeInstruction(OpCodes.Stloc_S, objects[0]);
ran = true;
- }
+ }
}
if (!ran) Log.Warning("[Clean Pathfinding] Transpiler could not find target. There may be a mod conflict, or RimWorld updated?");
@@ -164,7 +251,7 @@ public static void UpdatePathCosts()
Log.Error("[Clean Pathfinding] Error processing settings, skipping...\n" + ex);
}
}
- static public int AdjustCosts(Pawn pawn, TerrainDef def, int cost, Map map, int index)
+ static public float AdjustCosts(Pawn pawn, TerrainDef def, float cost, Map map, int index)
{
if (pawn == null) goto skipAdjustment;
@@ -267,13 +354,18 @@ float GameGlowAtFast(Map map, int index)
daylight = map.skyManager.curSkyGlowInt;
if (daylight == 1f) return 1f;
}
+#if v1_5
+
+#else
ColorInt color = map.glowGrid.glowGrid[index];
+#endif
+ UnityEngine.Color32 color = map.glowGrid.VisualGlowAt(index);
if (color.a == 1) return 1;
return (float)(color.r + color.g + color.b) * 0.0047058823529412f; //n / 3f / 255f * 3.6f pre-computed, since I guess the assembler doesn't optimize this
}
- #endregion
+#endregion
}
}
}
\ No newline at end of file
diff --git a/Source/DoorPathingUtility.cs b/Source/DoorPathingUtility.cs
index a72cd3d..26f5ca0 100644
--- a/Source/DoorPathingUtility.cs
+++ b/Source/DoorPathingUtility.cs
@@ -13,6 +13,15 @@
namespace CleanPathfinding
{
+ static class Area_Assit
+ {
+ public static void SetLabel(this Area_Allowed self, string label)
+ {
+
+ }
+ }
+
+
//Add gizmos to the doors
[HarmonyPatch(typeof(Building_Door), nameof(Building_Door.GetGizmos))]
static class Patch_Building_Door_GetGizmos
@@ -81,6 +90,9 @@ public static void Prefix(Area __instance)
}
}
+#if v1_5
+ //SetLabel removed in 1.5
+#else
[HarmonyPatch(typeof(Area_Allowed), nameof(Area_Allowed.SetLabel))]
static class Patch_Area_Allowed_SetLabel
{
@@ -100,6 +112,7 @@ public static void Postfix(Area_Allowed __instance)
else if (__instance.Label == "Avoid" && compCache.TryGetValue(__instance.Map.uniqueID, out MapComponent_DoorPathing mapComp)) mapComp.RegisterAvoidArea(__instance);
}
}
+#endif
[HarmonyPatch(typeof(World), nameof(World.FinalizeInit))]
static class Patch_FinalizeInit
diff --git a/Source/Mod_CleanPathfinding.cs b/Source/Mod_CleanPathfinding.cs
index d5a827c..5d9a400 100644
--- a/Source/Mod_CleanPathfinding.cs
+++ b/Source/Mod_CleanPathfinding.cs
@@ -86,7 +86,10 @@ public class Mod_CleanPathfinding : Mod
public Mod_CleanPathfinding(ModContentPack content) : base(content)
{
base.GetSettings();
- new Harmony(this.Content.PackageIdPlayerFacing).PatchAll();
+
+ Harmony harmony = new Harmony(this.Content.PackageIdPlayerFacing);
+ Harmony.DEBUG = true;
+ harmony.PatchAll();
}
public override void DoSettingsWindowContents(Rect inRect)