Skip to content
Merged
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
21 changes: 17 additions & 4 deletions Source/Client/Factions/FactionContextSetters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ static class MapGenFactionPatch
{
static void Prefix(PlanetTile tile)
{
var mapParent = Find.WorldObjects.MapParentAt(tile);
if (Multiplayer.Client != null && mapParent == null)
Log.Warning($"Couldn't set the faction context for map gen at {tile}: no world object");
MapParent mapParent = Find.WorldObjects.MapParentAt(tile);
Faction factionToSet = mapParent?.Faction ?? TileFactionContext.GetFactionForTile(tile);

FactionContext.Push(mapParent?.Faction);
if (Multiplayer.Client != null && factionToSet == null)
Log.Warning($"Couldn't set the faction context for map gen at {tile.tileId}: no world object and no stored faction.");

FactionContext.Push(factionToSet);
}

static void Finalizer()
Expand Down Expand Up @@ -116,3 +118,14 @@ static void Finalizer(Map __state)
__state?.PopFaction();
}
}

// Clean up after map generation is complete
[HarmonyPatch(typeof(MapGenerator), nameof(MapGenerator.GenerateMap))]
static class CleanupTileFactionContext
{
static void Finalizer(MapParent parent)
{
if (parent != null)
TileFactionContext.ClearTile(parent.Tile);
}
}
36 changes: 36 additions & 0 deletions Source/Client/Factions/TileFactionContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Collections.Generic;
using RimWorld;
using RimWorld.Planet;

namespace Multiplayer.Client.Factions
{
public static class TileFactionContext
{
private static readonly Dictionary<PlanetTile, Faction> tileFactions = [];
private static readonly object lockObject = new();

public static void SetFactionForTile(PlanetTile tile, Faction faction)
{
lock (lockObject)
{
tileFactions[tile] = faction;
}
}

public static Faction GetFactionForTile(PlanetTile tile)
{
lock (lockObject)
{
return tileFactions.TryGetValue(tile, out Faction faction) ? faction : null;
}
}

public static void ClearTile(PlanetTile tile)
{
lock (lockObject)
{
tileFactions.Remove(tile);
}
}
}
}
51 changes: 51 additions & 0 deletions Source/Client/Persistent/CampCreationPatches.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using HarmonyLib;
using Multiplayer.API;
using Multiplayer.Client.Factions;
using Multiplayer.Client.Util;
using RimWorld;
using RimWorld.Planet;
using System;
using Verse;

namespace Multiplayer.Client.Persistent
{
[HarmonyPatch(typeof(SettleInEmptyTileUtility), nameof(SettleInEmptyTileUtility.SetupCamp))]
internal static class SetupCampPatch
{
static void Postfix(Command __result, Caravan caravan)
{
if (Multiplayer.Client == null || __result is not Command_Action cmd)
return;

cmd.action = () => Sync_Camp(caravan);
}

[SyncMethod]
private static void Sync_Camp(Caravan caravan)
{
if (caravan == null || caravan.Faction == null)
{
MpLog.Error("[SettleInEmptyTileUtility.SetupCamp] Null caravan or faction in Sync_Camp");
return;
}

// Create the camp using the vanilla logic exactly as in SetupCamp
LongEventHandler.QueueLongEvent(delegate
{
TileFactionContext.SetFactionForTile(caravan.Tile, caravan.Faction);

Map map = GetOrGenerateMapUtility.GetOrGenerateMap(caravan.Tile, Find.World.info.initialMapSize, WorldObjectDefOf.Camp);

// Set the faction on the camp world object (this is what vanilla does)
map.Parent.SetFaction(caravan.Faction);

// Enter the caravan into the map
Pawn pawn = caravan.PawnsListForReading[0];
CaravanEnterMapUtility.Enter(caravan, map, CaravanEnterMode.Center, CaravanDropInventoryMode.DoNotDrop, draftColonists: false, (IntVec3 x) => x.GetRoom(map).CellCount >= 600);
map.Parent.GetComponent<TimedDetectionRaids>()?.StartDetectionCountdown(240000, 60000);
CameraJumper.TryJump(pawn);

}, "GeneratingMap", doAsynchronously: true, GameAndMapInitExceptionHandlers.ErrorWhileGeneratingMap);
}
}
}
44 changes: 22 additions & 22 deletions Source/Client/Persistent/CaravanFormingPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Multiplayer.Client.Persistent
{
[HarmonyPatch(typeof(Widgets), nameof(Widgets.ButtonText), new[] { typeof(Rect), typeof(string), typeof(bool), typeof(bool), typeof(bool), typeof(TextAnchor) })]
[HarmonyPatch(typeof(Widgets), nameof(ButtonText), [typeof(Rect), typeof(string), typeof(bool), typeof(bool), typeof(bool), typeof(TextAnchor)])]
static class MakeCancelFormingButtonRed
{
static void Prefix(string label, ref bool __state)
Expand All @@ -36,7 +36,7 @@ static void Postfix(bool __state, ref bool __result)
}
}

[HarmonyPatch(typeof(Widgets), nameof(Widgets.ButtonTextWorker))]
[HarmonyPatch(typeof(Widgets), nameof(ButtonTextWorker))]
static class FormCaravanHandleReset
{
static void Prefix(string label, ref bool __state)
Expand Down Expand Up @@ -185,33 +185,33 @@ static void Prefix(Dialog_FormCaravan __instance, Map map, bool reform, Action o
}

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

if (TickPatch.currentExecutingCmdIssuedBySelf)
{
var dialog = session.OpenWindow();
if (routePlannerWaypoint is { } tile)
CaravanFormingProxy dialog = session.OpenWindow();
if (!routePlannerWaypoint.HasValue)
return;

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(routePlannerWaypoint.Value);
}
finally
{
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;
}
Rand.PopState();
UniqueIdsPatch.useLocalIdsOverride = false;
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions Source/Client/Persistent/CaravanFormingSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public class CaravanFormingSession : ExposableSession, ISessionWithTransferables
public bool reform;
public Action onClosed;
public bool mapAboutToBeRemoved;
public int startingTile = -1;
public int destinationTile = -1;
public PlanetTile startingTile = -1;
public PlanetTile destinationTile = -1;
public List<TransferableOneWay> transferables;
public bool autoSelectTravelSupplies;
public IntVec3? meetingSpot;
Expand Down Expand Up @@ -98,7 +98,7 @@ private CaravanFormingProxy PrepareDummyDialog()
}

[SyncMethod]
public void ChooseRoute(int destination)
public void ChooseRoute(PlanetTile destination)
{
var dialog = PrepareDummyDialog();
dialog.Notify_ChoseRoute(destination);
Expand Down
Loading