From ac4daa7e4c1021d7ace061dabfea082e7d3f4d7b Mon Sep 17 00:00:00 2001 From: Sakura-TA Date: Thu, 16 Apr 2026 03:32:43 +0800 Subject: [PATCH 1/2] Implement faction context API methods in bridge --- Source/Client/MultiplayerAPIBridge.cs | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Source/Client/MultiplayerAPIBridge.cs b/Source/Client/MultiplayerAPIBridge.cs index 9e1d39edf..128961bb6 100644 --- a/Source/Client/MultiplayerAPIBridge.cs +++ b/Source/Client/MultiplayerAPIBridge.cs @@ -5,6 +5,7 @@ using Multiplayer.API; using Multiplayer.Client; using Verse; +using Multiplayer.Client.Factions; using Multiplayer.Client.Patches; using RimWorld; @@ -199,5 +200,43 @@ public void SetThingFilterContext(ThingFilterContext context) { ThingFilterMarkers.DrawnThingFilter = context; } + + public bool IsMultifaction => Client.Multiplayer.GameComp.multifaction; + + public Faction SpectatorFaction => Client.Multiplayer.WorldComp.spectatorFaction; + + public void PushFaction(Map map, Faction faction) => FactionExtensions.PushFaction(map, faction); + + public void PopFaction(Map map = null) => FactionExtensions.PopFaction(map); + + public void RepeatForWorldFactions(Action action) + { + if (Client.Multiplayer.game == null) return; + var worldComp = Client.Multiplayer.game.worldComp; + var spectatorId = worldComp.spectatorFaction.loadID; + foreach (var id in worldComp.factionData.Keys) + { + if (id == spectatorId) continue; + FactionExtensions.PushFaction(null, id); + try { action(); } + catch (Exception e) { Log.Error($"[MultiplayerAPIBridge] Exception in RepeatForWorldFactions for faction {id}: {e}"); } + finally { FactionExtensions.PopFaction(null); } + } + } + + public void RepeatForMapFactions(Map map, Action action) + { + if (map == null) throw new ArgumentNullException(nameof(map)); + if (Client.Multiplayer.game == null) return; + var spectatorId = Client.Multiplayer.game.worldComp.spectatorFaction.loadID; + foreach (var id in map.MpComp().factionData.Keys) + { + if (id == spectatorId) continue; + FactionExtensions.PushFaction(map, id); + try { action(); } + catch (Exception e) { Log.Error($"[MultiplayerAPIBridge] Exception in RepeatForMapFactions for faction {id}: {e}"); } + finally { FactionExtensions.PopFaction(map); } + } + } } } From 824a4d4003d961d046b166e7e2f44db6c40fb0e4 Mon Sep 17 00:00:00 2001 From: Sakura-TA Date: Fri, 17 Apr 2026 19:39:27 +0800 Subject: [PATCH 2/2] fix null spectatorFaction in FactionRepeater and bridge RepeatFor methods --- Source/Client/Factions/FactionRepeater.cs | 2 +- Source/Client/MultiplayerAPIBridge.cs | 25 ++++------------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/Source/Client/Factions/FactionRepeater.cs b/Source/Client/Factions/FactionRepeater.cs index 7fd1a8110..9d2aa709f 100644 --- a/Source/Client/Factions/FactionRepeater.cs +++ b/Source/Client/Factions/FactionRepeater.cs @@ -16,7 +16,7 @@ public static bool Template(IDictionary factionIdToData, Action da { if (Multiplayer.Client == null || ignore) return true; - var spectatorId = Multiplayer.WorldComp.spectatorFaction.loadID; + var spectatorId = Multiplayer.WorldComp.spectatorFaction?.loadID; ignore = true; foreach (var (id, data) in factionIdToData) { diff --git a/Source/Client/MultiplayerAPIBridge.cs b/Source/Client/MultiplayerAPIBridge.cs index 128961bb6..cd65acaee 100644 --- a/Source/Client/MultiplayerAPIBridge.cs +++ b/Source/Client/MultiplayerAPIBridge.cs @@ -211,32 +211,15 @@ public void SetThingFilterContext(ThingFilterContext context) public void RepeatForWorldFactions(Action action) { - if (Client.Multiplayer.game == null) return; - var worldComp = Client.Multiplayer.game.worldComp; - var spectatorId = worldComp.spectatorFaction.loadID; - foreach (var id in worldComp.factionData.Keys) - { - if (id == spectatorId) continue; - FactionExtensions.PushFaction(null, id); - try { action(); } - catch (Exception e) { Log.Error($"[MultiplayerAPIBridge] Exception in RepeatForWorldFactions for faction {id}: {e}"); } - finally { FactionExtensions.PopFaction(null); } - } + bool ignore = false; + FactionRepeater.Template(Client.Multiplayer.game?.worldComp.factionData, _ => action(), null, ref ignore); } public void RepeatForMapFactions(Map map, Action action) { if (map == null) throw new ArgumentNullException(nameof(map)); - if (Client.Multiplayer.game == null) return; - var spectatorId = Client.Multiplayer.game.worldComp.spectatorFaction.loadID; - foreach (var id in map.MpComp().factionData.Keys) - { - if (id == spectatorId) continue; - FactionExtensions.PushFaction(map, id); - try { action(); } - catch (Exception e) { Log.Error($"[MultiplayerAPIBridge] Exception in RepeatForMapFactions for faction {id}: {e}"); } - finally { FactionExtensions.PopFaction(map); } - } + bool ignore = false; + FactionRepeater.Template(map.MpComp()?.factionData, _ => action(), map, ref ignore); } } }