Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update to 1.5 #4

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added 1.5/Assemblies/CleanPathfinding.dll
Binary file not shown.
Binary file added 1.5/Assemblies/CleanPathfinding.pdb
Binary file not shown.
32 changes: 32 additions & 0 deletions 1.5/Patches/patch.owlchemist.cleanpathfinding.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationSequence">
<operations>
<li Class="PatchOperationAdd">
<xpath>Defs/TerrainDef[tags]/tags[li/text()="Road" or li/text()="FineFloor"]</xpath>
<value>
<li>CleanPath</li>
</value>
</li>
<li Class="PatchOperationAdd">
<success>Always</success> <!-- No idea, but why this fails for some people. It's not that important of a patch though, so skip I guess -->
<xpath>Defs/TerrainTemplateDef[tags]/tags[li/text()="FineFloor"]</xpath>
<value>
<li>CleanPath</li>
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/TerrainDef[defName="PavedTile" or defName="Concrete" or @Name="TileStoneBase"][not(tags)]</xpath>
<value>
<tags />
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/TerrainDef[defName="PavedTile" or defName="Concrete" or @Name="TileStoneBase"]/tags</xpath>
<value>
<li>CleanPath</li>
</value>
</li>
</operations>
</Operation>
</Patch>
1 change: 1 addition & 0 deletions About/About.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<supportedVersions>

<li>1.4</li>
<li>1.5</li>
</supportedVersions>
<description>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.</description>
<modDependencies>
Expand Down
17 changes: 8 additions & 9 deletions Source/CleanPathfinding.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@
<TargetFramework>net48</TargetFramework>
<LangVersion>preview</LangVersion>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Configurations>1.4;1.5</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>..\..\..\Mods\$(Product)\$(Version)\Assemblies</OutputPath>
<DefineConstants>TRACE;NDEBUG</DefineConstants>
<WarningLevel>4</WarningLevel>
<DebugSymbols>false</DebugSymbols>
<DebugType>None</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='1.4|AnyCPU'">
<OutputPath>..\..\..\Mods\$(Product)\$(Version)\Assemblies</OutputPath>
<DefineConstants>TRACE;DEBUG;NETFRAMEWORK;NET48;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='1.5|AnyCPU'">
<OutputPath>..\..\..\Mods\Clean Pathfinding\1.5\Assemblies</OutputPath>
<DefineConstants>NETFRAMEWORK;NET48;v1_5</DefineConstants>
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Krafs.Publicizer" Version="2.*">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand All @@ -31,7 +30,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.4.*" />
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.5.4069" />
</ItemGroup>
<ItemGroup>
<Publicize Include="Assembly-CSharp" />
Expand Down
25 changes: 25 additions & 0 deletions Source/CleanPathfinding.sln
Original file line number Diff line number Diff line change
@@ -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
128 changes: 110 additions & 18 deletions Source/CleanPathfindingUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,108 @@
using Verse.AI;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Linq;
using static CleanPathfinding.ModSettings_CleanPathfinding;

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<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> 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 <eae584ce26bc40229c1b1aa476bfa589>:0
at System.Collections.Generic.List`1[T].EnsureCapacity (System.Int32 min) [0x00036] in <eae584ce26bc40229c1b1aa476bfa589>:0
at System.Collections.Generic.List`1[T].Add (T item) [0x00010] in <eae584ce26bc40229c1b1aa476bfa589>: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<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
int offset = -1, objectsFound = 0;
bool ran = false, searchForObjects = false, thresholdReplaced = false;
Expand Down Expand Up @@ -48,29 +134,30 @@ static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> 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))
{
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?");
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
}
}
}
13 changes: 13 additions & 0 deletions Source/DoorPathingUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
{
Expand All @@ -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
Expand Down
5 changes: 4 additions & 1 deletion Source/Mod_CleanPathfinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ public class Mod_CleanPathfinding : Mod
public Mod_CleanPathfinding(ModContentPack content) : base(content)
{
base.GetSettings<ModSettings_CleanPathfinding>();
new Harmony(this.Content.PackageIdPlayerFacing).PatchAll();

Harmony harmony = new Harmony(this.Content.PackageIdPlayerFacing);
Harmony.DEBUG = true;
harmony.PatchAll();
}

public override void DoSettingsWindowContents(Rect inRect)
Expand Down