Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update 0.9, multifaction #399

Merged
merged 5 commits into from
Oct 18, 2023
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,6 @@ __pycache__/
/Multiplayer
Multiplayer*.zip

!Source/Client/Debug/
!Source/Client/Debug/

/Source/mpdb
57 changes: 10 additions & 47 deletions Source/Client/AsyncTime/AsyncTimeComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Multiplayer.API;
using Verse;
using Multiplayer.Client.Comp;
using Multiplayer.Client.Factions;
using Multiplayer.Client.Patches;
using Multiplayer.Client.Saving;
using Multiplayer.Client.Util;
Expand Down Expand Up @@ -67,7 +68,7 @@ public void SetDesiredTimeSpeed(TimeSpeed speed)

public float TimeToTickThrough { get; set; }

public Queue<ScheduledCommand> Cmds { get => cmds; }
public Queue<ScheduledCommand> Cmds => cmds;

public int TickableId => map.uniqueID;

Expand Down Expand Up @@ -148,10 +149,7 @@ public void TickMapTrading()
if (session.playerNegotiator.Map != map) continue;

if (session.ShouldCancel())
{
Multiplayer.WorldComp.RemoveTradeSession(session);
continue;
}
}
}

Expand Down Expand Up @@ -183,9 +181,6 @@ public void PreContext()
Current.Game.storyteller = storyteller;
Current.Game.storyWatcher = storyWatcher;

//UniqueIdsPatch.CurrentBlock = map.MpComp().mapIdBlock;
UniqueIdsPatch.CurrentBlock = Multiplayer.GlobalIdBlock;

Rand.PushState();
Rand.StateCompressed = randState;

Expand All @@ -195,8 +190,6 @@ public void PreContext()

public void PostContext()
{
UniqueIdsPatch.CurrentBlock = null;

Current.Game.storyteller = prevStoryteller;
Current.Game.storyWatcher = prevStoryWatcher;

Expand Down Expand Up @@ -276,11 +269,6 @@ public void ExecuteCmd(ScheduledCommand cmd)
MpDebugTools.HandleCmd(data);
}

if (cmdType == CommandType.CreateMapFactionData)
{
HandleMapFactionData(cmd, data);
}

if (cmdType == CommandType.MapTimeSpeed && Multiplayer.GameComp.asyncTime)
{
TimeSpeed speed = (TimeSpeed)data.ReadByte();
Expand All @@ -289,19 +277,9 @@ public void ExecuteCmd(ScheduledCommand cmd)
MpLog.Debug("Set map time speed " + speed);
}

if (cmdType == CommandType.MapIdBlock)
{
IdBlock block = IdBlock.Deserialize(data);

if (map != null)
{
//map.MpComp().mapIdBlock = block;
}
}

if (cmdType == CommandType.Designator)
{
HandleDesignator(cmd, data);
HandleDesignator(data);
}

UpdateManagers();
Expand Down Expand Up @@ -357,28 +335,11 @@ private static void TrySetCurrentMap(Map map)
}
}

private void HandleMapFactionData(ScheduledCommand cmd, ByteReader data)
{
int factionId = data.ReadInt32();

Faction faction = Find.FactionManager.GetById(factionId);
MultiplayerMapComp comp = map.MpComp();

if (!comp.factionData.ContainsKey(factionId))
{
BeforeMapGeneration.InitNewMapFactionData(map, faction);
MpLog.Log($"New map faction data for {faction.GetUniqueLoadID()}");
}
}

private void HandleDesignator(ScheduledCommand command, ByteReader data)
private void HandleDesignator(ByteReader data)
{
var mode = SyncSerialization.ReadSync<DesignatorMode>(data);
var designator = SyncSerialization.ReadSync<Designator>(data);

Container<Area>? prevArea = null;

bool SetState(Designator designator, ByteReader data)
bool SetState(Designator designator)
{
if (designator is Designator_AreaAllowed)
{
Expand Down Expand Up @@ -415,9 +376,12 @@ void RestoreState()
DesignatorInstall_SetThingToInstall.thingToInstall = null;
}

var mode = SyncSerialization.ReadSync<DesignatorMode>(data);
var designator = SyncSerialization.ReadSync<Designator>(data);

try
{
if (!SetState(designator, data)) return;
if (!SetState(designator)) return;

if (mode == DesignatorMode.SingleCell)
{
Expand Down Expand Up @@ -454,9 +418,8 @@ private void CacheNothingHappening()
nothingHappeningCached = true;
var list = map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer);

for (int j = 0; j < list.Count; j++)
foreach (var pawn in list)
{
Pawn pawn = list[j];
if (pawn.HostFaction == null && pawn.RaceProps.Humanlike && pawn.Awake())
nothingHappeningCached = false;
}
Expand Down
61 changes: 17 additions & 44 deletions Source/Client/AsyncTime/AsyncWorldTimeComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using HarmonyLib;
using Multiplayer.Client.Comp;
using Multiplayer.Client.Desyncs;
using Multiplayer.Client.Patches;
using Multiplayer.Client.Factions;
using Multiplayer.Client.Saving;
using Multiplayer.Client.Util;
using Multiplayer.Common;
Expand Down Expand Up @@ -45,10 +45,12 @@ public float TickRateMultiplier(TimeSpeed speed)
};
}

// Run at the speed of the fastest map
public TimeSpeed DesiredTimeSpeed => Find.Maps.Select(m => m.AsyncTime())
// Run at the speed of the fastest map or at chosen speed if there are no maps
public TimeSpeed DesiredTimeSpeed => !Find.Maps.Any() ?
timeSpeedInt :
Find.Maps.Select(m => m.AsyncTime())
.Where(a => a.ActualRateMultiplier(a.DesiredTimeSpeed) != 0f)
.Max(a => a?.DesiredTimeSpeed) ?? timeSpeedInt;
.Max(a => a?.DesiredTimeSpeed) ?? TimeSpeed.Paused;

public void SetDesiredTimeSpeed(TimeSpeed speed)
{
Expand Down Expand Up @@ -137,16 +139,20 @@ public void Tick()
public void PreContext()
{
Find.TickManager.CurTimeSpeed = DesiredTimeSpeed;
UniqueIdsPatch.CurrentBlock = Multiplayer.GlobalIdBlock;
Rand.PushState();
Rand.StateCompressed = randState;

if (Multiplayer.GameComp.multifaction)
FactionExtensions.PushFaction(null, Multiplayer.WorldComp.spectatorFaction);
}

public void PostContext()
{
if (Multiplayer.GameComp.multifaction)
FactionExtensions.PopFaction();

randState = Rand.StateCompressed;
Rand.PopState();
UniqueIdsPatch.CurrentBlock = null;
}

public void ExecuteCmd(ScheduledCommand cmd)
Expand All @@ -159,7 +165,7 @@ public void ExecuteCmd(ScheduledCommand cmd)
TickPatch.currentExecutingCmdIssuedBySelf = cmd.issuedBySelf && !TickPatch.Simulating;

PreContext();
Extensions.PushFaction(null, cmd.GetFaction());
FactionExtensions.PushFaction(null, cmd.GetFaction());

bool prevDevMode = Prefs.data.devMode;
var prevGodMode = DebugSettings.godMode;
Expand Down Expand Up @@ -195,14 +201,9 @@ public void ExecuteCmd(ScheduledCommand cmd)
SetTimeEverywhere(TimeSpeed.Paused);
}

if (cmdType == CommandType.SetupFaction)
{
HandleSetupFaction(cmd, data);
}

if (cmdType == CommandType.CreateJoinPoint)
{
LongEventHandler.QueueLongEvent(CreateJoinPoint, "MpCreatingJoinPoint", false, null);
LongEventHandler.QueueLongEvent(CreateJoinPointAndSendIfHost, "MpCreatingJoinPoint", false, null);
}

if (cmdType == CommandType.InitPlayerData)
Expand All @@ -224,7 +225,7 @@ public void ExecuteCmd(ScheduledCommand cmd)
MpLog.Debug($"rand calls {DeferredStackTracing.randCalls - randCalls1}");
MpLog.Debug("rand state " + Rand.StateCompressed);

Extensions.PopFaction();
FactionExtensions.PopFaction();
PostContext();
TickPatch.currentExecutingCmdIssuedBySelf = false;
executingCmdWorld = false;
Expand All @@ -236,9 +237,9 @@ public void ExecuteCmd(ScheduledCommand cmd)
}
}

private static void CreateJoinPoint()
private static void CreateJoinPointAndSendIfHost()
{
Multiplayer.session.dataSnapshot = SaveLoad.CreateGameDataSnapshot(SaveLoad.SaveAndReload());
Multiplayer.session.dataSnapshot = SaveLoad.CreateGameDataSnapshot(SaveLoad.SaveAndReload(), Multiplayer.GameComp.multifaction);

if (!TickPatch.Simulating && !Multiplayer.IsReplay &&
(Multiplayer.LocalServer != null || Multiplayer.arbiterInstance))
Expand Down Expand Up @@ -288,34 +289,6 @@ private void HandleTimeVote(ScheduledCommand cmd, ByteReader data)
tickable.SetDesiredTimeSpeed(Multiplayer.GameComp.GetLowestTimeVote(tickableId));
}

private void HandleSetupFaction(ScheduledCommand command, ByteReader data)
{
int factionId = data.ReadInt32();
Faction faction = Find.FactionManager.GetById(factionId);

if (faction == null)
{
faction = new Faction
{
loadID = factionId,
def = FactionDefOf.PlayerColony,
Name = "Multiplayer faction",
};

Find.FactionManager.Add(faction);

foreach (Faction current in Find.FactionManager.AllFactionsListForReading)
{
if (current == faction) continue;
current.TryMakeInitialRelationsWith(faction);
}

Multiplayer.WorldComp.factionData[factionId] = FactionWorldData.New(factionId);

MpLog.Log($"New faction {faction.GetUniqueLoadID()}");
}
}

public void FinalizeInit()
{
Multiplayer.game.SetThingMakerSeed((int)(randState >> 32));
Expand Down
3 changes: 1 addition & 2 deletions Source/Client/AsyncTime/StorytellerPatches.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HarmonyLib;
Expand Down
19 changes: 6 additions & 13 deletions Source/Client/Comp/Game/MultiplayerGameComp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,31 @@ namespace Multiplayer.Client.Comp
public class MultiplayerGameComp : IExposable, IHasSemiPersistentData
{
public bool asyncTime;
public bool multifaction;
public bool debugMode;
public bool logDesyncTraces;
public PauseOnLetter pauseOnLetter;
public TimeControl timeControl;
public Dictionary<int, PlayerData> playerData = new(); // player id to player data

public IdBlock globalIdBlock = new(int.MaxValue / 2, 1_000_000_000);
public string idBlockBase64;

public bool IsLowestWins => timeControl == TimeControl.LowestWins;

public PlayerData LocalPlayerDataOrNull => playerData.GetValueOrDefault(Multiplayer.session.playerId);

public MultiplayerGameComp(Game game)
{
}

public void ExposeData()
{
Scribe_Values.Look(ref asyncTime, "asyncTime", true, true);
Scribe_Values.Look(ref multifaction, "multifaction", false, true);
Scribe_Values.Look(ref debugMode, "debugMode");
Scribe_Values.Look(ref logDesyncTraces, "logDesyncTraces");
Scribe_Values.Look(ref pauseOnLetter, "pauseOnLetter");
Scribe_Values.Look(ref timeControl, "timeControl");

Scribe_Custom.LookIdBlock(ref globalIdBlock, "globalIdBlock");

if (globalIdBlock == null)
{
// todo globalIdBlock was previously in WorldComp, this is a quick hack to make old saves compatible
Log.Warning("Global id block was null, fixing...");
globalIdBlock = new IdBlock(int.MaxValue / 2, 1_000_000_000);
}
// Store for back-compat conversion in GameExposeComponentsPatch
if (Scribe.mode == LoadSaveMode.LoadingVars)
Scribe_Values.Look(ref idBlockBase64, "globalIdBlock");
}

public void WriteSemiPersistent(ByteWriter writer)
Expand Down
2 changes: 1 addition & 1 deletion Source/Client/Comp/Map/ExposeActor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void ExposeData()
// This depends on the fact that the implementation of HashSet RimWorld currently uses
// "preserves" insertion order (as long as elements are only added and not removed
// [which is the case for Scribe managers])
public static void Register(Action action)
public static void OnPostInit(Action action)
{
if (Scribe.mode == LoadSaveMode.LoadingVars)
Scribe.loader.initer.RegisterForPostLoadInit(new ExposeActor(action));
Expand Down
5 changes: 3 additions & 2 deletions Source/Client/Comp/Map/FactionMapData.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Multiplayer.Client.Factions;
using RimWorld;
using Verse;

Expand Down Expand Up @@ -46,14 +47,14 @@ private FactionMapData(int factionId, Map map) : this(map)

public void ExposeData()
{
ExposeActor.Register(() => map.PushFaction(factionId));
ExposeActor.OnPostInit(() => map.PushFaction(factionId));

Scribe_Values.Look(ref factionId, "factionId");
Scribe_Deep.Look(ref designationManager, "designationManager", map);
Scribe_Deep.Look(ref areaManager, "areaManager", map);
Scribe_Deep.Look(ref zoneManager, "zoneManager", map);

ExposeActor.Register(() => map.PopFaction());
ExposeActor.OnPostInit(() => map.PopFaction());
}

public static FactionMapData New(int factionId, Map map)
Expand Down
Loading
Loading