Skip to content

Commit

Permalink
Merge branch 'master' of github.com:SokyranTheDragon/Multiplayer into…
Browse files Browse the repository at this point in the history
… session-rework

# Conflicts:
#	Source/Client/Comp/World/MultiplayerWorldComp.cs
  • Loading branch information
SokyranTheDragon committed Dec 19, 2023
2 parents 08600e8 + d03a1b8 commit 2523da6
Show file tree
Hide file tree
Showing 41 changed files with 569 additions and 334 deletions.
6 changes: 4 additions & 2 deletions Source/Client/AsyncTime/AsyncTimeComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,11 @@ public void PreContext()
{
if (Multiplayer.GameComp.multifaction)
{
map.PushFaction(map.ParentFaction is { IsPlayer: true }
map.PushFaction(
map.ParentFaction is { IsPlayer: true }
? map.ParentFaction
: Multiplayer.WorldComp.spectatorFaction);
: Multiplayer.WorldComp.spectatorFaction,
force: true);
}

prevTime = TimeSnapshot.GetAndSetFromMap(map);
Expand Down
12 changes: 10 additions & 2 deletions Source/Client/AsyncTime/AsyncWorldTimeComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,21 @@ public void PreContext()
Rand.StateCompressed = randState;

if (Multiplayer.GameComp.multifaction)
FactionExtensions.PushFaction(null, Multiplayer.WorldComp.spectatorFaction);
{
FactionExtensions.PushFaction(null, Multiplayer.WorldComp.spectatorFaction, force: true);
foreach (var map in Find.Maps)
map.MpComp().SetFaction(Multiplayer.WorldComp.spectatorFaction);
}
}

public void PostContext()
{
if (Multiplayer.GameComp.multifaction)
FactionExtensions.PopFaction();
{
var f = FactionExtensions.PopFaction();
foreach (var map in Find.Maps)
map.MpComp().SetFaction(f);
}

randState = Rand.StateCompressed;
Rand.PopState();
Expand Down
6 changes: 3 additions & 3 deletions Source/Client/Comp/Game/MultiplayerGameComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Multiplayer.Client.Comp
{
public class MultiplayerGameComp : IExposable, IHasSemiPersistentData
public class MultiplayerGameComp : IExposable, IHasSessionData
{
public bool asyncTime;
public bool multifaction;
Expand Down Expand Up @@ -40,12 +40,12 @@ public void ExposeData()
Scribe_Values.Look(ref idBlockBase64, "globalIdBlock");
}

public void WriteSemiPersistent(ByteWriter writer)
public void WriteSessionData(ByteWriter writer)
{
SyncSerialization.WriteSync(writer, playerData);
}

public void ReadSemiPersistent(ByteReader reader)
public void ReadSessionData(ByteReader reader)
{
playerData = SyncSerialization.ReadSync<Dictionary<int, PlayerData>>(reader);
DebugSettings.godMode = LocalPlayerDataOrNull?.godMode ?? false;
Expand Down
20 changes: 10 additions & 10 deletions Source/Client/Comp/Map/MultiplayerMapComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@

namespace Multiplayer.Client
{
public class MultiplayerMapComp : IExposable, IHasSemiPersistentData
public class MultiplayerMapComp : IExposable, IHasSessionData
{
public static bool tickingFactions;

public Map map;

public Dictionary<int, FactionMapData> factionData = new();
public Dictionary<int, CustomFactionMapData> customFactionData = new();
// SortedDictionary to ensure determinism
public SortedDictionary<int, FactionMapData> factionData = new();
public SortedDictionary<int, CustomFactionMapData> customFactionData = new();

public SessionManager sessionManager;
public List<PersistentDialog> mapDialogs = new();
Expand Down Expand Up @@ -156,10 +157,10 @@ private void ExposeFactionData()
{
if (Scribe.mode == LoadSaveMode.Saving)
{
int currentFactionId =GetFactionId(map.zoneManager);
int currentFactionId = GetFactionId(map.zoneManager);
Scribe_Custom.LookValue(currentFactionId, "currentFactionId");

var savedFactionData = new Dictionary<int, FactionMapData>(factionData);
var savedFactionData = new SortedDictionary<int, FactionMapData>(factionData);
savedFactionData.Remove(currentFactionId);
Scribe_Custom.LookValueDeep(ref savedFactionData, "factionMapData", map);
}
Expand All @@ -169,8 +170,7 @@ private void ExposeFactionData()
Scribe_Values.Look(ref currentFactionId, "currentFactionId");

Scribe_Custom.LookValueDeep(ref factionData, "factionMapData", map);
if (factionData == null)
factionData = new Dictionary<int, FactionMapData>();
factionData ??= new SortedDictionary<int, FactionMapData>();
}

if (Scribe.mode == LoadSaveMode.LoadingVars)
Expand All @@ -182,17 +182,17 @@ private void ExposeFactionData()
private void ExposeCustomFactionData()
{
Scribe_Custom.LookValueDeep(ref customFactionData, "customFactionMapData", map);
customFactionData ??= new Dictionary<int, CustomFactionMapData>();
customFactionData ??= new SortedDictionary<int, CustomFactionMapData>();
}

public void WriteSemiPersistent(ByteWriter writer)
public void WriteSessionData(ByteWriter writer)
{
writer.WriteInt32(autosaveCounter);

sessionManager.WriteSemiPersistent(writer);
}

public void ReadSemiPersistent(ByteReader reader)
public void ReadSessionData(ByteReader reader)
{
autosaveCounter = reader.ReadInt32();

Expand Down
18 changes: 10 additions & 8 deletions Source/Client/Comp/World/MultiplayerWorldComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ namespace Multiplayer.Client;

public class MultiplayerWorldComp : IHasSemiPersistentData

Check failure on line 12 in Source/Client/Comp/World/MultiplayerWorldComp.cs

View workflow job for this annotation

GitHub Actions / Builds

The type or namespace name 'IHasSemiPersistentData' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 12 in Source/Client/Comp/World/MultiplayerWorldComp.cs

View workflow job for this annotation

GitHub Actions / Builds

The type or namespace name 'IHasSemiPersistentData' could not be found (are you missing a using directive or an assembly reference?)
{
public Dictionary<int, FactionWorldData> factionData = new();
// SortedDictionary to ensure determinism
public SortedDictionary<int, FactionWorldData> factionData = new();

public World world;

Expand All @@ -34,8 +35,6 @@ public void ExposeData()
{
ExposeFactionData();

Scribe_References.Look(ref spectatorFaction, "spectatorFaction");

sessionManager.ExposeSessions();
// Ensure a pause lock session exists if there's any pause locks registered
if (!PauseLockSession.pauseLocks.NullOrEmpty())
Expand Down Expand Up @@ -83,28 +82,31 @@ void RemoveOpponentFaction()

private void ExposeFactionData()
{
Scribe_References.Look(ref spectatorFaction, "spectatorFaction");

if (Scribe.mode == LoadSaveMode.Saving)
{
int currentFactionId = GetFactionId(Find.ResearchManager);
Scribe_Custom.LookValue(currentFactionId, "currentFactionId");

var savedFactionData = new Dictionary<int, FactionWorldData>(factionData);
var savedFactionData = new SortedDictionary<int, FactionWorldData>(factionData);
savedFactionData.Remove(currentFactionId);

Scribe_Collections.Look(ref savedFactionData, "factionData", LookMode.Value, LookMode.Deep);
Scribe_Custom.LookValueDeep(ref savedFactionData, "factionData");
}
else
{
// The faction whose data is currently set
Scribe_Values.Look(ref currentFactionId, "currentFactionId");

Scribe_Collections.Look(ref factionData, "factionData", LookMode.Value, LookMode.Deep);
factionData ??= new Dictionary<int, FactionWorldData>();
Scribe_Custom.LookValueDeep(ref factionData, "factionData");
factionData ??= new SortedDictionary<int, FactionWorldData>();
}

if (Scribe.mode == LoadSaveMode.LoadingVars && Multiplayer.session != null && Multiplayer.game != null)
{
Multiplayer.game.myFactionLoading = Find.FactionManager.GetById(Multiplayer.session.myFactionId);
Multiplayer.game.myFactionLoading =
Find.FactionManager.GetById(Multiplayer.session.myFactionId) ?? spectatorFaction;
}

if (Scribe.mode == LoadSaveMode.LoadingVars)
Expand Down
6 changes: 0 additions & 6 deletions Source/Client/Debug/DebugActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,6 @@ static void MultiplayerMethodCallLogger(MethodBase __originalMethod)
Debug.Log(__originalMethod.FullDescription());
}

[DebugAction(MultiplayerCategory, allowedGameStates = AllowedGameStates.Playing)]
static void Add1000TicksToTime()
{
Find.TickManager.ticksGameInt += 1000;
}

#if DEBUG

[DebugOutput]
Expand Down
42 changes: 41 additions & 1 deletion Source/Client/Desyncs/DeferredStackTracing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
using System.Reflection;
using HarmonyLib;
using Multiplayer.Client.Patches;
using Multiplayer.Common;
using RimWorld;
using Verse;
using Verse.AI;

namespace Multiplayer.Client.Desyncs
{
Expand All @@ -19,7 +21,6 @@ static IEnumerable<MethodBase> TargetMethods()
{
yield return AccessTools.PropertyGetter(typeof(Rand), nameof(Rand.Value));
yield return AccessTools.PropertyGetter(typeof(Rand), nameof(Rand.Int));
//yield return AccessTools.Method(typeof(Thing), nameof(Thing.DeSpawn));
}

public static int acc;
Expand Down Expand Up @@ -57,6 +58,45 @@ public static bool ShouldAddStackTraceForDesyncLog()
}
}

[HarmonyPatch(typeof(UniqueIDsManager), nameof(UniqueIDsManager.GetNextID))]
public static class UniqueIdsPatch
{
static void Postfix()
{
DeferredStackTracing.Postfix();
}
}

[HarmonyPatch(typeof(Thing), nameof(Thing.SpawnSetup))]
public static class ThingSpawnPatch
{
static void Postfix(Thing __instance)
{
if (__instance.def.HasThingIDNumber)
DeferredStackTracing.Postfix();
}
}

[HarmonyPatch(typeof(Thing), nameof(Thing.DeSpawn))]
public static class ThingDeSpawnPatch
{
static void Postfix(Thing __instance)
{
if (__instance.def.HasThingIDNumber)
DeferredStackTracing.Postfix();
}
}

[HarmonyPatch(typeof(Pawn_JobTracker), nameof(Pawn_JobTracker.EndCurrentJob))]
public static class EndCurrentJobPatch
{
static void Prefix(Pawn_JobTracker __instance)
{
if (MpVersion.IsDebug && __instance.curJob != null && DeferredStackTracing.ShouldAddStackTraceForDesyncLog())
Multiplayer.game.sync.TryAddInfoForDesyncLog($"EndCurrentJob for {__instance.pawn}: {__instance.curJob}", "");
}
}

[HarmonyPatch(typeof(WildAnimalSpawner), nameof(WildAnimalSpawner.WildAnimalSpawnerTick))]
static class WildAnimalSpawnerTickTraceIgnore
{
Expand Down
3 changes: 2 additions & 1 deletion Source/Client/Desyncs/SyncCoordinator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ public void TryAddMapRandomState(int map, ulong state)
/// <summary>
/// Logs an item to aid in desync debugging.
/// </summary>
/// <param name="info">Information to be logged</param>
/// <param name="info1">Information to be logged</param>
/// <param name="info2">Information to be logged</param>
public void TryAddInfoForDesyncLog(string info1, string info2)
{
if (!ShouldCollect) return;
Expand Down
4 changes: 2 additions & 2 deletions Source/Client/Factions/FactionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ public static class FactionContext
{
public static Stack<Faction> stack = new();

public static Faction Push(Faction newFaction)
public static Faction Push(Faction newFaction, bool force = false)
{
if (newFaction == null || Find.FactionManager.ofPlayer == newFaction || !newFaction.def.isPlayer)
if (newFaction == null || !force && Find.FactionManager.ofPlayer == newFaction || !newFaction.def.isPlayer)
{
stack.Push(null);
return null;
Expand Down
118 changes: 118 additions & 0 deletions Source/Client/Factions/FactionContextSetters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System;
using HarmonyLib;
using RimWorld;
using RimWorld.Planet;
using Verse;

namespace Multiplayer.Client.Factions;

[HarmonyPatch(typeof(SettlementUtility), nameof(SettlementUtility.AttackNow))]
static class AttackNowPatch
{
static void Prefix(Caravan caravan)
{
FactionContext.Push(caravan.Faction);
}

static void Finalizer()
{
FactionContext.Pop();
}
}

[HarmonyPatch(typeof(GetOrGenerateMapUtility), nameof(GetOrGenerateMapUtility.GetOrGenerateMap), new []{ typeof(int), typeof(IntVec3), typeof(WorldObjectDef) })]
static class MapGenFactionPatch
{
static void Prefix(int 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");

FactionContext.Push(mapParent?.Faction);
}

static void Finalizer()
{
FactionContext.Pop();
}
}

[HarmonyPatch(typeof(CaravanEnterMapUtility), nameof(CaravanEnterMapUtility.Enter), new[] { typeof(Caravan), typeof(Map), typeof(Func<Pawn, IntVec3>), typeof(CaravanDropInventoryMode), typeof(bool) })]
static class CaravanEnterFactionPatch
{
static void Prefix(Caravan caravan)
{
FactionContext.Push(caravan.Faction);
}

static void Finalizer()
{
FactionContext.Pop();
}
}

[HarmonyPatch(typeof(WealthWatcher), nameof(WealthWatcher.ForceRecount))]
static class WealthRecountFactionPatch
{
static void Prefix(WealthWatcher __instance)
{
FactionContext.Push(__instance.map.ParentFaction);
}

static void Finalizer()
{
FactionContext.Pop();
}
}

[HarmonyPatch(typeof(FactionIdeosTracker), nameof(FactionIdeosTracker.RecalculateIdeosBasedOnPlayerPawns))]
static class RecalculateFactionIdeosContext
{
static void Prefix(FactionIdeosTracker __instance)
{
FactionContext.Push(__instance.faction);
}

static void Finalizer()
{
FactionContext.Pop();
}
}

[HarmonyPatch(typeof(Bill), nameof(Bill.ValidateSettings))]
static class BillValidateSettingsPatch
{
static void Prefix(Bill __instance)
{
if (Multiplayer.Client == null) return;
FactionContext.Push(__instance.pawnRestriction?.Faction); // todo HostFaction, SlaveFaction?
}

static void Finalizer()
{
if (Multiplayer.Client == null) return;
FactionContext.Pop();
}
}

[HarmonyPatch(typeof(Bill_Production), nameof(Bill_Production.ValidateSettings))]
static class BillProductionValidateSettingsPatch
{
static void Prefix(Bill_Production __instance, ref Map __state)
{
if (Multiplayer.Client == null) return;

var zoneManager = __instance.storeZone?.zoneManager ?? __instance.includeFromZone?.zoneManager;
if (__instance.Map != null && zoneManager != null)
{
__instance.Map.PushFaction(zoneManager.map.MpComp().GetFactionId(zoneManager));
__state = __instance.Map;
}
}

static void Finalizer(Map __state)
{
__state?.PopFaction();
}
}
Loading

0 comments on commit 2523da6

Please sign in to comment.