Skip to content

Commit

Permalink
Updated Biomes! Core compat (#416)
Browse files Browse the repository at this point in the history
Dropped patches for special terrain (it no longer uses the stopwatch) and hash code calls (the method that was unsafe got dropped, replaced with 2 safe ones).

Added extra System RNG patch. The method had System RNG before, but it was unused... It still is unused, but they added a second RNG usage.

Updated DebugActions to check Biomes! Core and VFE Core special terrain update methods.
  • Loading branch information
SokyranTheDragon authored Jan 15, 2024
1 parent 8846a4a commit c4d9bbf
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 55 deletions.
6 changes: 6 additions & 0 deletions Source/DebugActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ internal enum StuffToSearch
AccessTools.DeclaredMethod("HugsLib.ModBase:Update"),
AccessTools.DeclaredMethod("HugsLib.ModBase:FixedUpdate"),
AccessTools.DeclaredMethod("HugsLib.ModBase:OnGUI"),
AccessTools.DeclaredMethod("BiomesCore.TerrainInstance:Update"),
AccessTools.DeclaredMethod("BiomesCore.TerrainComp:CompUpdate"),
AccessTools.DeclaredMethod("BiomesCore.DefExtensionActive:DoWork", new [] { AccessTools.TypeByName("Verse.TerrainDef") }),
AccessTools.DeclaredMethod("VFECore.TerrainInstance:Update"),
AccessTools.DeclaredMethod("VFECore.TerrainComp:CompUpdate"),
AccessTools.DeclaredMethod("VFECore.DefExtensionActive:DoWork", new [] { AccessTools.TypeByName("Verse.TerrainDef") }),
}.Where(x => x != null).ToHashSet();

private static readonly HashSet<MethodInfo> NonTickingUpdateMethodCalls = new[]
Expand Down
60 changes: 5 additions & 55 deletions Source/Mods/BiomesCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,8 @@ namespace Multiplayer.Compat
[MpCompatFor("BiomesTeam.BiomesCore")]
public class BiomesCore
{
private static Type terrainCompType;
private static AccessTools.FieldRef<object, object> terrainCompParentField;
private static AccessTools.FieldRef<object, IntVec3> terrainInstancePositionField;

public BiomesCore(ModContentPack mod)
{
LongEventHandler.ExecuteWhenFinished(LatePatch);

// Gizmos (only dev mode gizmos)
{
var typeNames = new[]
Expand Down Expand Up @@ -51,62 +45,18 @@ public BiomesCore(ModContentPack mod)

// RNG + GenView.ShouldSpawnMotesAt
{
// BiomesCore.GenSteps.ValleyPatch:Postfix - System RNG called, but never used
PatchingUtilities.PatchSystemRand(new[]
{
// Two 'new Random()' calls, one is never used
"BiomesCore.GenSteps.ValleyPatch:Postfix",
}, false);

PatchingUtilities.PatchPushPopRand(new[]
{
"BiomesCore.CompPlantReleaseSpore:ThrowPoisonSmoke",
"BiomesCore.TerrainComp_MoteSpawner:ThrowMote",
});
}

// Stopwatch
{
MpCompat.harmony.Patch(AccessTools.DeclaredMethod("BiomesCore.SpecialTerrainList:TerrainUpdate"),
prefix: new HarmonyMethod(typeof(BiomesCore), nameof(RemoveTerrainUpdateTimeBudget)));
}
}

private static void LatePatch()
{
// HashCode on unsafe type
{
// Some extra setup for stuff that will be used by the patch
terrainCompType = AccessTools.TypeByName("BiomesCore.TerrainComp");
terrainCompParentField = AccessTools.FieldRefAccess<object>(terrainCompType, "parent");
terrainInstancePositionField = AccessTools.FieldRefAccess<IntVec3>("BiomesCore.TerrainInstance:positionInt");

// Patch the method using hash code to use different object if it's unsupported
MpCompat.harmony.Patch(AccessTools.DeclaredMethod("BiomesCore.ActiveTerrainUtility:HashCodeToMod"),
prefix: new HarmonyMethod(typeof(BiomesCore), nameof(HashCodeOnSafeObject)));
}
}

private static void RemoveTerrainUpdateTimeBudget(ref long timeBudget)
{
if (MP.IsInMultiplayer)
timeBudget = long.MaxValue; // Basically limitless time

// The method is limited in updating a max of 1/3 of all active special terrains.
// If we'd want to work on having a performance option of some sort, we'd have to
// base it around amount of terrain updates per tick, instead of basing it on actual time.
}

private static void HashCodeOnSafeObject(ref object obj)
{
// We don't care out of MP
if (!MP.IsInMultiplayer)
return;

if (obj is ThingComp comp)
obj = comp.parent;
else if (obj.GetType().IsAssignableFrom(terrainCompType))
{
// Get the parent field (TerrainInstance)
obj = terrainCompParentField(obj);
// Get the IntVec3 and use that for hash code (since it's safe for MP)
obj = terrainInstancePositionField(obj);
}
}
}
}

0 comments on commit c4d9bbf

Please sign in to comment.