Skip to content

Commit

Permalink
Update Vehicle Framework to sync designators, remove redundant patch (#…
Browse files Browse the repository at this point in the history
…460)

First, the patch to remove red cells being drawn in some specific situations. This was fixed in the mod itself, so the patch is now redundant.

Second, 2 patches and syncing was added to road area designators. The mod has 2 designators (add/remove area), and the add designator has 2 modes (prioritize/avoid, stored as a static field). Changing the mode was not synced previously, so this change should handle it:
- The road mode (prioritize/avoid) is stored by MP Compat whenever the player changes it
- Whenever the player interacts with the designator, their selected value is restored from the value stored by MP Compat
- When syncing the designator, that player's value will be synced and applied to any interaction that will use it
  • Loading branch information
SokyranTheDragon authored Aug 16, 2024
1 parent 5afcb0c commit 98faa5e
Showing 1 changed file with 33 additions and 44 deletions.
77 changes: 33 additions & 44 deletions Source_Referenced/VehicleFramework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public class VehicleFramework

// VehiclePawn.<>c__DisplayClass250_0
private static AccessTools.FieldRef<object, VehiclePawn> vehiclePawnInnerClassParentField;

// Designator_AreaRoad
private static Designator_AreaRoad.RoadType localRoadType = Designator_AreaRoad.RoadType.Prioritize;

#endregion

Expand Down Expand Up @@ -90,11 +93,6 @@ static ISyncMethod TrySyncDeclaredMethod(Type targetType, string targetMethodNam
foreach (var m in methods.Where(m => m != null))
MpCompat.harmony.Patch(m, transpiler: transpiler);

// Disable an issue where a lot of red regions pop-up for 50 ticks when hosting,
// or when the `PathingHelper.ThingAffectingRegionsStateChange` method is called for things that spawned.
MpCompat.harmony.Patch(AccessTools.DeclaredMethod(typeof(VehicleRegionDirtyer), nameof(VehicleRegionDirtyer.Notify_ThingAffectingRegionsSpawned)),
transpiler: new HarmonyMethod(typeof(VehicleFramework), nameof(DisableDebugFlashing)));

// // Slightly replace how pathfinding is handled by the mod.
// // Currently, the vehicle will wait before moving for as long as the path is being calculated.
// // We need to make sure it's ready on the same tick for all players, as otherwise a desync will happen.
Expand Down Expand Up @@ -681,45 +679,6 @@ private static IEnumerable<CodeInstruction> ReplaceThreadAvailable(IEnumerable<C

#endregion

#region Other fixes

private static IEnumerable<CodeInstruction> DisableDebugFlashing(IEnumerable<CodeInstruction> instr, MethodBase baseMethod)
{
var target = AccessTools.DeclaredMethod(typeof(Ext_Map), nameof(Ext_Map.DrawCell_ThreadSafe));
var replacement = AccessTools.DeclaredMethod(typeof(VehicleFramework), nameof(NoCellDrawing));
var replacedAnything = false;

foreach (var ci in instr)
{
if (ci.Calls(target))
{
ci.opcode = OpCodes.Call;
ci.operand = replacement;
replacedAnything = true;
}

yield return ci;
}

if (!replacedAnything)
{
var name = (baseMethod.DeclaringType?.Namespace).NullOrEmpty() ? baseMethod.Name : $"{baseMethod.DeclaringType!.Name}:{baseMethod.Name}";
Log.Warning($"Failed to patch {nameof(Ext_Map)}.{nameof(Ext_Map.DrawCell_ThreadSafe)} calls (patch most likely no longer needed) for method {name}");
}
}

private static void NoCellDrawing(Map map, IntVec3 cell, float colorPct, string text, int duration)
{
// Do nothing in MP.
// We could prefix the method that we patch instead and prevent it from running, but
// it would prevent it from running it from other places in the mod.

if (!MP.IsInMultiplayer)
map.DrawCell_ThreadSafe(cell, colorPct, text, duration);
}

#endregion

#region MP safe pathfinding

// private static bool PrePathTicker(Vehicle_PathFollower __instance)
Expand Down Expand Up @@ -1396,6 +1355,18 @@ private static void SyncFlightNode(SyncWorker sync, ref FlightNode node)
node = sync.Read<FlightNode>(type);
}

[MpCompatSyncWorker(typeof(Designator_AreaRoadExpand), shouldConstruct = true)]
private static void SyncAreaRoadDesignator(SyncWorker sync, ref Designator_AreaRoadExpand designator)
{
// We need to sync the road type (prioritize/avoid) to properly sync the designator.
// Sync the local player's road type, as the normal one may become overwritten by
// this specific sync worker delegate.
if (sync.isWriting)
sync.Write(localRoadType);
else
Designator_AreaRoad.roadType = sync.Read<Designator_AreaRoad.RoadType>();
}

#endregion

#region Sessions
Expand Down Expand Up @@ -2613,5 +2584,23 @@ private static IEnumerable<CodeInstruction> LogResult(IEnumerable<CodeInstructio
}

#endregion

#region Designator

[MpCompatPrefix(typeof(Designator_AreaRoad), nameof(Designator_AreaRoad.ProcessInput), 1)]
private static void StoreNewLocalRoadType(Designator_AreaRoad.RoadType ___roadType)
=> localRoadType = ___roadType;

[MpCompatPrefix(typeof(Designator_AreaRoad), nameof(Designator_AreaRoad.DesignateSingleCell))]
[MpCompatPrefix(typeof(Designator_AreaRoad), nameof(Designator_AreaRoad.CanDesignateCell))]
private static void RestoreLocalRoadType()
{
// If in MP and not executing synced commands, restore the current player's road type.
// It may become overwritten by a different value when syncing.
if (MP.IsInMultiplayer && !MP.IsExecutingSyncCommand)
Designator_AreaRoad.roadType = localRoadType;
}

#endregion
}
}

0 comments on commit 98faa5e

Please sign in to comment.