Skip to content

Commit

Permalink
Fix caravans
Browse files Browse the repository at this point in the history
  • Loading branch information
Zetrith committed Jul 14, 2024
1 parent 93d3dfb commit 331fe5a
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 63 deletions.
11 changes: 7 additions & 4 deletions Source/Client/Patches/UniqueIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ public static class UniqueIdsPatch
// Start at -2 because -1 is sometimes used as the uninitialized marker
private static int localIds = -2;

public static bool useLocalIdsOverride;

private static bool UseLocalIds =>
Multiplayer.Client != null && (useLocalIdsOverride || Multiplayer.InInterface || Current.ProgramState == ProgramState.Entry);

static bool Prefix()
{
return Multiplayer.Client == null || (!Multiplayer.InInterface && Current.ProgramState != ProgramState.Entry);
return !UseLocalIds;
}

static void Postfix(ref int __result)
{
if (Multiplayer.Client == null) return;

if (Multiplayer.InInterface || Current.ProgramState == ProgramState.Entry)
if (UseLocalIds)
__result = localIds--;
}
}
Expand Down
65 changes: 61 additions & 4 deletions Source/Client/Persistent/CaravanFormingPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using RimWorld;
using RimWorld.Planet;
using System;
using Multiplayer.API;
using Multiplayer.Client.Patches;
using UnityEngine;
using Verse;
using static Verse.Widgets;
Expand Down Expand Up @@ -147,29 +149,84 @@ static class CancelDialogFormCaravan
{
static bool Prefix(Window window)
{
if (Multiplayer.MapContext != null && window.GetType() == typeof(Dialog_FormCaravan))
if (Multiplayer.Client != null && window.GetType() == typeof(Dialog_FormCaravan))
return false;

return true;
}
}

[HarmonyPatch(typeof(Dialog_FormCaravan), MethodType.Constructor)]
[HarmonyPatch(new[] { typeof(Map), typeof(bool), typeof(Action), typeof(bool), typeof(IntVec3) })]
[HarmonyPatch(new[] { typeof(Map), typeof(bool), typeof(Action), typeof(bool), typeof(IntVec3?) })]
static class DialogFormCaravanCtorPatch
{
static void Prefix(Dialog_FormCaravan __instance, Map map, bool reform, Action onClosed, bool mapAboutToBeRemoved)
static void Prefix(Dialog_FormCaravan __instance, Map map, bool reform, Action onClosed, bool mapAboutToBeRemoved, IntVec3? designatedMeetingPoint)
{
if (Multiplayer.Client == null)
return;

if (__instance.GetType() != typeof(Dialog_FormCaravan))
return;

// Handles showing the dialog from TimedForcedExit.CompTick -> TimedForcedExit.ForceReform
// (note TimedForcedExit is obsolete)
if (Multiplayer.ExecutingCmds || Multiplayer.Ticking)
{
var comp = map.MpComp();
if (comp.sessionManager.GetFirstOfType<CaravanFormingSession>() == null)
comp.CreateCaravanFormingSession(reform, onClosed, mapAboutToBeRemoved);
comp.CreateCaravanFormingSession(reform, onClosed, mapAboutToBeRemoved, designatedMeetingPoint);
}
else // Handles opening from the interface: forming gizmos, reforming gizmos and caravan hitching spots
{
StartFormingCaravan(map, reform, designatedMeetingPoint);
}
}

[SyncMethod]
internal static void StartFormingCaravan(Map map, bool reform = false, IntVec3? designatedMeetingPoint = null, int? routePlannerWaypoint = null)
{
var comp = map.MpComp();
var session = comp.CreateCaravanFormingSession(reform, null, false, designatedMeetingPoint);

if (TickPatch.currentExecutingCmdIssuedBySelf)
{
var dialog = session.OpenWindow();
if (routePlannerWaypoint is { } tile)
{
try
{
UniqueIdsPatch.useLocalIdsOverride = true;

// Just to be safe
// RNG shouldn't be invoked but TryAddWaypoint is quite complex and calls pathfinding
Rand.PushState();

var worldRoutePlanner = Find.WorldRoutePlanner;
worldRoutePlanner.Start(dialog);
worldRoutePlanner.TryAddWaypoint(tile);
}
finally
{
Rand.PopState();
UniqueIdsPatch.useLocalIdsOverride = false;
}
}
}
}
}

[HarmonyPatch(typeof(FormCaravanGizmoUtility), nameof(FormCaravanGizmoUtility.DialogFromToSettlement))]
static class HandleFormCaravanShowRoutePlanner
{
static bool Prefix(Map origin, int tile)
{
if (Multiplayer.Client == null)
return true;

// Override behavior in multiplayer
DialogFormCaravanCtorPatch.StartFormingCaravan(origin, routePlannerWaypoint: tile);

return false;
}
}

Expand Down
5 changes: 4 additions & 1 deletion Source/Client/Persistent/CaravanFormingProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ public class CaravanFormingProxy : Dialog_FormCaravan, ISwitchToMap

public CaravanFormingSession Session => map.MpComp().sessionManager.GetFirstOfType<CaravanFormingSession>();

public CaravanFormingProxy(Map map, bool reform = false, Action onClosed = null, bool mapAboutToBeRemoved = false, IntVec3? meetingSpot = null) : base(map, reform, onClosed, mapAboutToBeRemoved, meetingSpot)
public int originalSessionId;

public CaravanFormingProxy(int originalSessionId, Map map, bool reform = false, Action onClosed = null, bool mapAboutToBeRemoved = false, IntVec3? meetingSpot = null) : base(map, reform, onClosed, mapAboutToBeRemoved, meetingSpot)
{
this.originalSessionId = originalSessionId;
}

public override void DoWindowContents(Rect inRect)
Expand Down
14 changes: 8 additions & 6 deletions Source/Client/Persistent/CaravanFormingSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ public CaravanFormingSession(Map map, bool reform, Action onClosed, bool mapAbou

private void AddItems()
{
var dialog = new CaravanFormingProxy(map, reform, null, mapAboutToBeRemoved, meetingSpot)
var dialog = new CaravanFormingProxy(sessionId, map, reform, null, mapAboutToBeRemoved, meetingSpot)
{
autoSelectTravelSupplies = autoSelectTravelSupplies
};
dialog.CalculateAndRecacheTransferables();
transferables = dialog.transferables;
}

public void OpenWindow(bool sound = true)
public CaravanFormingProxy OpenWindow(bool sound = true)
{
var dialog = PrepareDummyDialog();
if (!sound)
Expand All @@ -72,13 +72,14 @@ public void OpenWindow(bool sound = true)
);

dialog.Notify_TransferablesChanged();

Find.WindowStack.Add(dialog);

return dialog;
}

private CaravanFormingProxy PrepareDummyDialog()
{
var dialog = new CaravanFormingProxy(map, reform, null, mapAboutToBeRemoved, meetingSpot)
var dialog = new CaravanFormingProxy(sessionId, map, reform, null, mapAboutToBeRemoved, meetingSpot)
{
transferables = transferables,
startingTile = startingTile,
Expand Down Expand Up @@ -142,7 +143,9 @@ public void Cancel()
private void Remove()
{
map.MpComp().sessionManager.RemoveSession(this);
Find.WorldRoutePlanner.Stop();

if (Find.WorldRoutePlanner.currentFormCaravanDialog is CaravanFormingProxy proxy && proxy.originalSessionId == sessionId)
Find.WorldRoutePlanner.Stop();
}

[SyncMethod]
Expand Down Expand Up @@ -186,7 +189,6 @@ public override FloatMenuOption GetBlockingWindowOptions(ColonistBar.Entry entry
{
return new FloatMenuOption("MpCaravanFormingSession".Translate(), () =>
{
SwitchToMapOrWorld(entry.map);
OpenWindow();
});
}
Expand Down
48 changes: 0 additions & 48 deletions Source/Client/Syncing/Game/SyncDelegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -468,54 +468,6 @@ static void GeneUIUtilityTarget(Thing target)
geneUIUtilityTarget = target;
}

[MpPrefix(typeof(FormCaravanComp), nameof(FormCaravanComp.GetGizmos), lambdaOrdinal: 0)]
static bool GizmoFormCaravan(MapParent ___mapParent)
{
if (Multiplayer.Client == null) return true;
GizmoFormCaravan(___mapParent.Map, false);
return false;
}

[MpPrefix(typeof(FormCaravanComp), nameof(FormCaravanComp.GetGizmos), lambdaOrdinal: 1)]
static bool GizmoReformCaravan(MapParent ___mapParent)
{
if (Multiplayer.Client == null) return true;
GizmoFormCaravan(___mapParent.Map, true);
return false;
}

[MpPrefix(typeof(CompHitchingSpot), nameof(CompHitchingSpot.CompGetGizmosExtra), 0)]
static bool GizmoFormCaravan(CompHitchingSpot __instance)
{
if (Multiplayer.Client == null) return true;
GizmoFormCaravan(__instance.parent.Map, false, __instance.parent.Position);
return false;
}

private static void GizmoFormCaravan(Map map, bool reform, IntVec3? meetingSpot = null)
{
var comp = map.MpComp();

if (comp.sessionManager.GetFirstOfType<CaravanFormingSession>() is { } session)
session.OpenWindow();
else
CreateCaravanFormingSession(comp, reform, meetingSpot);
}

[SyncMethod]
private static void CreateCaravanFormingSession(MultiplayerMapComp comp, bool reform, IntVec3? meetingSpot = null)
{
var session = comp.CreateCaravanFormingSession(reform, null, false, meetingSpot);

if (TickPatch.currentExecutingCmdIssuedBySelf)
{
session.OpenWindow();
AsyncTimeComp.keepTheMap = true;
Current.Game.CurrentMap = comp.map;
Find.World.renderer.wantedMode = WorldRenderMode.None;
}
}

[MpPostfix(typeof(CaravanVisitUtility), nameof(CaravanVisitUtility.TradeCommand))]
static void ReopenTradingWindowLocally(Caravan caravan, Command __result)
{
Expand Down

0 comments on commit 331fe5a

Please sign in to comment.