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

Fix Vehicle Framework issues with upgrade overlays #500

Merged
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
42 changes: 42 additions & 0 deletions Source_Referenced/VehicleFramework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ static ISyncMethod TrySyncDeclaredMethod(Type targetType, string targetMethodNam
// so this exists here as an extra safety in case those ever get removed later on.
MpCompatPatchLoader.LoadPatch<VehicleFramework>();

// Needed for overlay fix.
PatchingUtilities.PatchLongEventMarkers();

#endregion

#region VehicleFramework
Expand Down Expand Up @@ -2602,5 +2605,44 @@ private static void RestoreLocalRoadType()
}

#endregion

#region Upgrade Fixes

private static bool ShouldExecuteWhenFinished()
{
// If not on main thread we always need to
// execute when finished, both in MP and in SP.
if (!UnityData.IsInMainThread)
return false;
// If main thread and not in MP, leave current behavior.
if (!MP.IsInMultiplayer)
return true;

// If in MP and on main thread, ensure that we call it in
// ExecuteWhenFinished during game loading as it's
// unsafe there and will cause errors for the host.
// AllowedToRunLongEvents is false only for host during
// loading
return PatchingUtilities.AllowedToRunLongEvents;
}

[MpCompatTranspiler(typeof(UpgradeNode), nameof(UpgradeNode.AddOverlays))]
private static IEnumerable<CodeInstruction> FixHostOverlayInit(IEnumerable<CodeInstruction> instr, MethodBase baseMethod)
{
// The mod fails to initialize the overlays for the host when (re)loading the game.
// It fails to initialize the second time as the initialization method is not called
// inside "LongEventHandler.ExecuteWhenFinished" call (this only happens when not on
// the main thread, the code checks UnityData.IsInMainThread). The issue is that likely
// due to the way MP handles loading some of the data required for overlay initialization
// is not yet initialized. We need to ensure that the execution is delayed until it's
// safe to initialize them.

var target = AccessTools.DeclaredPropertyGetter(typeof(UnityData), nameof(UnityData.IsInMainThread));
var replacement = MpMethodUtil.MethodOf(ShouldExecuteWhenFinished);

return instr.ReplaceMethod(target, replacement, baseMethod, expectedReplacements: 1);
}

#endregion
}
}