public static void SendGameData(GameDataSnapshot data, bool async) { var cache = Multiplayer.session.dataSnapshot; var mapsData = new Dictionary <int, byte[]>(cache.mapData); var gameData = cache.gameData; var semiPersistent = cache.semiPersistentData; void Send() { var writer = new ByteWriter(); writer.WriteInt32(mapsData.Count); foreach (var mapData in mapsData) { writer.WriteInt32(mapData.Key); writer.WritePrefixedBytes(GZipStream.CompressBuffer(mapData.Value)); } writer.WritePrefixedBytes(GZipStream.CompressBuffer(gameData)); writer.WritePrefixedBytes(GZipStream.CompressBuffer(semiPersistent)); byte[] data = writer.ToArray(); OnMainThread.Enqueue(() => Multiplayer.Client?.SendFragmented(Packets.Client_WorldDataUpload, data)); }; if (async) { ThreadPool.QueueUserWorkItem(c => Send()); } else { Send(); } }
public void WriteData(GameDataSnapshot gameData) { string sectionId = info.sections.Count.ToString("D3"); using var zip = ZipFile; foreach (var(mapId, mapData) in gameData.mapData) { zip.AddEntry($"maps/{sectionId}_{mapId}_save", mapData); } foreach (var(mapId, mapCmdData) in gameData.mapCmds) { if (mapId >= 0) { zip.AddEntry($"maps/{sectionId}_{mapId}_cmds", SerializeCmds(mapCmdData)); } } if (gameData.mapCmds.TryGetValue(ScheduledCommand.Global, out var worldCmds)) { zip.AddEntry($"world/{sectionId}_cmds", SerializeCmds(worldCmds)); } zip.AddEntry($"world/{sectionId}_save", gameData.gameData); info.sections.Add(new ReplaySection(gameData.cachedAtTime, TickPatch.Timer)); zip.UpdateEntry("info", DirectXmlSaver.XElementFromObject(info, typeof(ReplayInfo)).ToString()); zip.Save(); }
public static GameDataSnapshot CreateGameDataSnapshot(TempGameData data) { XmlNode gameNode = data.SaveData.DocumentElement["game"]; XmlNode mapsNode = gameNode["maps"]; var dataSnapshot = new GameDataSnapshot(); foreach (XmlNode mapNode in mapsNode) { int id = int.Parse(mapNode["uniqueID"].InnerText); byte[] mapData = ScribeUtil.XmlToByteArray(mapNode); dataSnapshot.mapData[id] = mapData; dataSnapshot.mapCmds[id] = new List <ScheduledCommand>(Find.Maps.First(m => m.uniqueID == id).AsyncTime().cmds); } gameNode["currentMapIndex"].RemoveFromParent(); mapsNode.RemoveAll(); byte[] gameData = ScribeUtil.XmlToByteArray(data.SaveData); dataSnapshot.cachedAtTime = TickPatch.Timer; dataSnapshot.gameData = gameData; dataSnapshot.semiPersistentData = data.SemiPersistent; dataSnapshot.mapCmds[ScheduledCommand.Global] = new List <ScheduledCommand>(Multiplayer.WorldComp.cmds); return(dataSnapshot); }
public void LoadCurrentData(int sectionId) { var dataSnapshot = new GameDataSnapshot(); string sectionIdStr = sectionId.ToString("D3"); using var zip = ZipFile; foreach (var mapCmds in zip.SelectEntries($"name = maps/{sectionIdStr}_*_cmds")) { int mapId = int.Parse(mapCmds.FileName.Split('_')[1]); dataSnapshot.mapCmds[mapId] = DeserializeCmds(mapCmds.GetBytes()); } foreach (var mapSave in zip.SelectEntries($"name = maps/{sectionIdStr}_*_save")) { int mapId = int.Parse(mapSave.FileName.Split('_')[1]); dataSnapshot.mapData[mapId] = mapSave.GetBytes(); } var worldCmds = zip[$"world/{sectionIdStr}_cmds"]; if (worldCmds != null) { dataSnapshot.mapCmds[ScheduledCommand.Global] = DeserializeCmds(worldCmds.GetBytes()); } dataSnapshot.gameData = zip[$"world/{sectionIdStr}_save"].GetBytes(); dataSnapshot.semiPersistentData = new byte[0]; Multiplayer.session.dataSnapshot = dataSnapshot; }
public void HandleWorldData(ByteReader data) { connection.State = ConnectionStateEnum.ClientPlaying; Log.Message("Game data size: " + data.Length); int factionId = data.ReadInt32(); Multiplayer.session.myFactionId = factionId; int tickUntil = data.ReadInt32(); var dataSnapshot = new GameDataSnapshot(); byte[] worldData = GZipStream.UncompressBuffer(data.ReadPrefixedBytes()); dataSnapshot.gameData = worldData; byte[] semiPersistentData = GZipStream.UncompressBuffer(data.ReadPrefixedBytes()); dataSnapshot.semiPersistentData = semiPersistentData; List <int> mapsToLoad = new List <int>(); int mapCmdsCount = data.ReadInt32(); for (int i = 0; i < mapCmdsCount; i++) { int mapId = data.ReadInt32(); int mapCmdsLen = data.ReadInt32(); List <ScheduledCommand> mapCmds = new List <ScheduledCommand>(mapCmdsLen); for (int j = 0; j < mapCmdsLen; j++) { mapCmds.Add(ScheduledCommand.Deserialize(new ByteReader(data.ReadPrefixedBytes()))); } dataSnapshot.mapCmds[mapId] = mapCmds; } int mapDataCount = data.ReadInt32(); for (int i = 0; i < mapDataCount; i++) { int mapId = data.ReadInt32(); byte[] rawMapData = data.ReadPrefixedBytes(); byte[] mapData = GZipStream.UncompressBuffer(rawMapData); dataSnapshot.mapData[mapId] = mapData; mapsToLoad.Add(mapId); } Session.dataSnapshot = dataSnapshot; Multiplayer.session.localCmdId = data.ReadInt32(); TickPatch.shouldPause = data.ReadBool(); TickPatch.tickUntil = tickUntil; TickPatch.SetSimulation( toTickUntil: true, onFinish: () => Multiplayer.Client.Send(Packets.Client_WorldReady), cancelButtonKey: "Quit", onCancel: GenScene.GoToMainMenu // Calls StopMultiplayer through a patch ); ReloadGame(mapsToLoad, true, false); }