Skip to content
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 modified References/VanillaGravshipExpanded.dll
Binary file not shown.
13 changes: 0 additions & 13 deletions Source/Mods/VanillaExpandedFramework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public VanillaExpandedFramework(ModContentPack mod)
(PatchWeatherOverlayEffects, "Weather Overlay Effects", false),
(PatchExtraPregnancyApproaches, "Extra Pregnancy Approaches", false),
(PatchWorkGiverDeliverResources, "Building stuff requiring non-construction skill", false),
(PatchStaticCaches, "Static caches", false),
(PatchGraphicCustomizationDialog, "Graphic Customization Dialog", true),
(PatchDraftedAi, "Drafted AI", true),
(PatchMapObjectGeneration, "Thing spawning on map generation (ObjectSpawnsDef)", false),
Expand Down Expand Up @@ -1802,18 +1801,6 @@ private static void PostIsConstruction(WorkGiver w, ref bool __result)

#endregion

#region Caches

private static void PatchStaticCaches()
{
// TODO: Go through Vanilla Expanded Framework's VanillaGenesExpanded.StaticCollectionsClass and clean some of those on join.
// While not critical for fixing MP desyncs, it should help with RAM usage as many of those have data unique to a specific
// game, and leaving it will just leave garbage data. In the context of MP it could be especially useful in case of
// frequent (unrelated) desyncs, as the players joining in would gain more and more garbage data each time they join.
}

#endregion

#region Graphic Customization Dialog

// Dialog_GraphicCustomization
Expand Down
68 changes: 68 additions & 0 deletions Source/Mods/VanillaGravshipExpanded2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using HarmonyLib;
using Multiplayer.API;
using RimWorld;
using Verse;

namespace Multiplayer.Compat;

/// <summary>Vanilla Gravship Expanded 2 by Oskar Potocki and the Vanilla Expanded team</summary>
/// <see href="https://github.com/Vanilla-Expanded/VanillaGravshipExpanded2"/>
/// <see href="https://steamcommunity.com/sharedfiles/filedetails/?id=3799737423"/>
[MpCompatFor("vanillaexpanded.gravship2")]
public class VanillaGravshipExpanded2
{
public VanillaGravshipExpanded2(ModContentPack mod)
{
// Patching these methods can initialize DefOf caches and load gizmo textures.
LongEventHandler.ExecuteWhenFinished(LatePatch);
}

private static void LatePatch()
{
var worldComponentType = AccessTools.TypeByName("VanillaGravshipExpanded2.WorldComponent_GravshipCombat");
var warpodType = AccessTools.TypeByName("VanillaGravshipExpanded2.CompLaunchable_Warpod");
var vacuumLightType = AccessTools.TypeByName("VanillaGravshipExpanded2.CompVacuumWarningLight");
var escapePodType = AccessTools.TypeByName("VanillaGravshipExpanded2.CompEscapePod");

// Escape pods
MP.RegisterSyncMethod(AccessTools.TypeByName("VanillaGravshipExpanded2.VGE2_MapComponent"), "EvacuationActive");
MP.RegisterSyncMethod(escapePodType, "ClaimIfNeeded");
MpCompat.RegisterLambdaMethod(escapePodType, nameof(ThingComp.CompGetGizmosExtra), 1);
MpCompat.RegisterLambdaDelegate(escapePodType, nameof(ThingComp.CompFloatMenuOptions), 0, 2, 3);

// Vacuum warning lights
MP.RegisterSyncMethod(vacuumLightType, "ConcerningVacuumLevel");
MP.RegisterSyncMethod(vacuumLightType, "EvacuatePawns");

// Salvager tribute dialog
MP.RegisterSyncMethod(worldComponentType, "PayTribute");
MP.RegisterSyncMethod(worldComponentType, "SpawnActiveWarplatform");
MpCompat.RegisterLambdaDelegate(worldComponentType, "ShowTributeDemandDialog", 0);

// Salvager station comms job
MpCompat.RegisterLambdaDelegate(
"VanillaGravshipExpanded2.Building_CommsConsole_GetFloatMenuOptions_Patch", "Postfix", 0);

MP.RegisterSyncMethod(warpodType, "LaunchWarpodTo");
MP.RegisterSyncMethod(warpodType, "LaunchHellpodTo");

// ProcessInput creates the map directly; MP reconstructs the designator and ignores its unused Event.
MP.RegisterSyncMethod(AccessTools.TypeByName("VanillaGravshipExpanded2.Designator_GenerateEmptyOrbit"), nameof(Designator.ProcessInput))
.SetContext(SyncContext.CurrentMap);

// Developer gizmos
// These callbacks capture no comp; their target is the compiler-generated singleton.
MpCompat.RegisterLambdaDelegate(
"VanillaGravshipExpanded2.CompPowerEmergencyGravshipGenerator", nameof(ThingComp.CompGetGizmosExtra), 0, 1, 2)
.SetDebugOnly();
MpCompat.RegisterLambdaMethod(
"VanillaGravshipExpanded2.CompGravshipShieldGeneratorWithHeat", nameof(ThingComp.CompGetGizmosExtra), 0, 1, 2)
.SetDebugOnly();
MpCompat.RegisterLambdaMethod(
"VanillaGravshipExpanded2.CompPower_InputOnlyBattery", nameof(ThingComp.CompGetGizmosExtra), 0, 1, 2)
.SetDebugOnly();
MpCompat.RegisterLambdaMethod(
"VanillaGravshipExpanded2.CompApparelVerbOwner_Oxygen", "CompGetWornGizmosExtra", 0)
.SetDebugOnly();
}
}
34 changes: 8 additions & 26 deletions Source_Referenced/VanillaGravshipExpanded.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class VanillaGravshipExpanded
// Flag to preserve VGE state during our SyncedGravshipTileSelected flow
private static bool inSyncedTileSelectedFlow;

// Gizmo_OxygenProvider sync field (#880 workaround)
private static ISyncField oxygenTargetValuePctField;
// Gizmo_OxygenProvider refill threshold
private static ISyncField oxygenRechargeThresholdField;

// VGE launch flow — MP internals (not publicized, reached via reflection)
private static Action<PlanetTile> closeGravshipSession;
Expand Down Expand Up @@ -286,17 +286,10 @@ private static void LatePatch()
#region Gizmo_OxygenProvider

{
MP.RegisterSyncMethod(AccessTools.PropertySetter(typeof(CompApparelOxygenProvider), nameof(CompApparelOxygenProvider.AutomaticRechargeEnabled)));
MP.RegisterSyncMethod(typeof(CompApparelOxygenProvider), nameof(CompApparelOxygenProvider.AutomaticRechargeEnabled));

oxygenTargetValuePctField = MP.RegisterSyncField(typeof(Gizmo_OxygenProvider), "targetValuePct").SetBufferChanges();

// MP issue #880 workaround: RegisterSyncField resolves targetType via ReflectedType,
// which returns Gizmo_Slider (the base declaring "targetValuePct"), not Gizmo_OxygenProvider.
// Rewrite the private targetType field so Watch() matches our subclass instance.
AccessTools.Field(oxygenTargetValuePctField.GetType(), "targetType")
.SetValue(oxygenTargetValuePctField, typeof(Gizmo_OxygenProvider));

MP.RegisterSyncWorker<Gizmo_Slider>(SyncOxygenGizmo, typeof(Gizmo_OxygenProvider));
// The released mod recreates this gizmo; sync its persistent comp instead.
oxygenRechargeThresholdField = MP.RegisterSyncField(typeof(CompApparelOxygenProvider), nameof(CompApparelOxygenProvider.rechargeAtCharges)).SetBufferChanges();

MpCompat.harmony.Patch(
AccessTools.DeclaredMethod(typeof(Gizmo_Slider), nameof(Gizmo_Slider.GizmoOnGUI)),
Expand Down Expand Up @@ -611,7 +604,9 @@ private static void PreOxygenGizmoOnGUI(Gizmo_Slider __instance)
return;

MP.WatchBegin();
oxygenTargetValuePctField.Watch(__instance);
oxygenRechargeThresholdField.Watch(((Gizmo_OxygenProvider)__instance).oxygenProvider);
// Refresh the vanilla slider cache after Watch restores any pending local value.
__instance.targetValuePct = ((Gizmo_OxygenProvider)__instance).Target;
}

private static void PostOxygenGizmoOnGUI(Gizmo_Slider __instance)
Expand All @@ -622,19 +617,6 @@ private static void PostOxygenGizmoOnGUI(Gizmo_Slider __instance)
MP.WatchEnd();
}

private static void SyncOxygenGizmo(SyncWorker sync, ref Gizmo_Slider gizmo)
{
if (sync.isWriting)
{
sync.Write<ThingComp>(((Gizmo_OxygenProvider)gizmo).oxygenProvider);
}
else
{
var comp = (CompApparelOxygenProvider)sync.Read<ThingComp>();
gizmo = comp.oxygenConfigurationGizmo;
}
}

/// <summary>
/// Intercept the paste color gizmo action. ColorClipboard is per-client
/// state, so we capture the color value and sync per-barrier.
Expand Down