public void ProcessPacket(PlanetDataResponse packet, NebulaConnection conn) { // We have to track the offset we are currently at in the flattened jagged array as we decode int currentOffset = 0; for (int i = 0; i < packet.PlanetDataIDs.Length; i++) { PlanetData planet = GameMain.galaxy.PlanetById(packet.PlanetDataIDs[i]); Log.Info($"Parsing {packet.PlanetDataBytesLengths[i]} bytes of data for planet {planet.name} (ID: {planet.id})"); byte[] planetData = packet.PlanetDataBytes.Skip(currentOffset).Take(packet.PlanetDataBytesLengths[i]).ToArray(); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(planetData)) { planet.ImportRuntime(reader.BinaryReader); } lock (PlanetModelingManager.genPlanetReqList) { PlanetModelingManager.genPlanetReqList.Enqueue(planet); } currentOffset += packet.PlanetDataBytesLengths[i]; } }
public override void ProcessPacket(StatisticsDataPacket packet, NebulaConnection conn) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.StatisticsBinaryData)) { Multiplayer.Session.Statistics.ImportAllData(reader.BinaryReader); } }
public void ProcessPacket(StorageSyncResponsePacket packet, NebulaConnection conn) { StorageComponent storageComponent = GameMain.galaxy.PlanetById(packet.PlanetId)?.factory?.factoryStorage?.storagePool[packet.StorageIndex]; if (storageComponent != null) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.StorageComponent)) { storageComponent.Import(reader.BinaryReader); } ItemProto itemProto = LDB.items.Select((int)GameMain.galaxy.PlanetById(packet.PlanetId)?.factory?.entityPool[storageComponent.entityId].protoId); //Imitation of UIStorageWindow.OnStorageIdChange() StorageManager.ActiveWindowTitle.text = itemProto.name; StorageManager.ActiveUIStorageGrid._Free(); StorageManager.ActiveUIStorageGrid._Init(storageComponent); StorageManager.ActiveStorageComponent = storageComponent; MethodInvoker.GetHandler(AccessTools.Method(typeof(UIStorageGrid), "SetStorageData")).Invoke(StorageManager.ActiveUIStorageGrid, StorageManager.ActiveStorageComponent); StorageManager.ActiveUIStorageGrid._Open(); StorageManager.ActiveUIStorageGrid.OnStorageDataChanged(); StorageManager.ActiveBansSlider.maxValue = (float)storageComponent.size; StorageManager.ActiveBansSlider.value = (float)(storageComponent.size - storageComponent.bans); StorageManager.ActiveBansValueText.text = StorageManager.ActiveBansSlider.value.ToString(); GameMain.galaxy.PlanetById(packet.PlanetId).factory.factoryStorage.storagePool[packet.StorageIndex] = storageComponent; } }
public override void ProcessPacket(DysonSphereData packet, NebulaConnection conn) { if (IsHost) { return; } //Failsafe, if client does not have instantiated sphere for the star, it will create dummy one that will be replaced during import if (GameMain.data.dysonSpheres[packet.StarIndex] == null) { GameMain.data.dysonSpheres[packet.StarIndex] = new DysonSphere(); GameMain.data.statistics.production.Init(GameMain.data); //Another failsafe, DysonSphere import requires initialized factory statistics if (GameMain.data.statistics.production.factoryStatPool[0] == null) { GameMain.data.statistics.production.factoryStatPool[0] = new FactoryProductionStat(); GameMain.data.statistics.production.factoryStatPool[0].Init(); } GameMain.data.dysonSpheres[packet.StarIndex].Init(GameMain.data, GameMain.data.galaxy.stars[packet.StarIndex]); } using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.BinaryData)) { GameMain.data.dysonSpheres[packet.StarIndex].Import(reader.BinaryReader); } }
public override void ProcessPacket(StatisticsDataPacket packet, NebulaConnection conn) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.StatisticsBinaryData)) { StatisticsManager.ImporAllHistorytData(reader.BinaryReader); } }
public void ProcessPacket(TrashSystemResponseDataPacket packet, NebulaConnection conn) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.TrashSystemData)) { GameMain.data.trashSystem.Import(reader.BinaryReader); } }
public override void ProcessPacket(HandshakeResponse packet, NebulaConnection conn) { using (BinaryUtils.Reader p = new BinaryUtils.Reader(packet.ModsSettings)) { for (int i = 0; i < packet.ModsSettingsCount; i++) { string guid = p.BinaryReader.ReadString(); PluginInfo info = Chainloader.PluginInfos[guid]; if (info.Instance is IMultiplayerModWithSettings mod) { mod.Import(p.BinaryReader); } } } // overwrite local setting with host setting, but dont save it as its a temp setting for this session Config.Options.SyncSoil = packet.SyncSoil; ((LocalPlayer)Multiplayer.Session.LocalPlayer).IsHost = false; ((LocalPlayer)Multiplayer.Session.LocalPlayer).SetPlayerData(packet.LocalPlayerData, packet.IsNewPlayer); Multiplayer.Session.IsInLobby = false; Multiplayer.ShouldReturnToJoinMenu = false; GameDesc gameDesc = new GameDesc(); gameDesc.SetForNewGame(packet.AlgoVersion, packet.GalaxySeed, packet.StarCount, 1, packet.ResourceMultiplier); DSPGame.StartGameSkipPrologue(gameDesc); InGamePopup.ShowInfo("Loading", "Loading state from server, please wait", null); }
public override void ProcessPacket(LobbyResponse packet, NebulaConnection conn) { using (BinaryUtils.Reader p = new BinaryUtils.Reader(packet.ModsSettings)) { for (int i = 0; i < packet.ModsSettingsCount; i++) { string guid = p.BinaryReader.ReadString(); PluginInfo info = Chainloader.PluginInfos[guid]; if (info.Instance is IMultiplayerModWithSettings mod) { mod.Import(p.BinaryReader); } } } ((LocalPlayer)Multiplayer.Session.LocalPlayer).IsHost = false; Multiplayer.Session.NumPlayers = packet.NumPlayers; Multiplayer.Session.IsInLobby = true; DiscordManager.UpdateRichPresence(partyId: packet.DiscordPartyId); UIRoot.instance.galaxySelect._Open(); UIRoot.instance.uiMainMenu._Close(); GameDesc gameDesc = new GameDesc(); gameDesc.SetForNewGame(packet.GalaxyAlgo, packet.GalaxySeed, packet.StarCount, 1, packet.ResourceMultiplier); gameDesc.savedThemeIds = packet.SavedThemeIds; UIRoot.instance.galaxySelect.gameDesc = gameDesc; UIRoot.instance.galaxySelect.SetStarmapGalaxy(); }
public override void ProcessPacket(StorageSyncResponsePacket packet, NebulaConnection conn) { if (IsHost) { return; } StorageComponent storageComponent = GameMain.galaxy.PlanetById(packet.PlanetId)?.factory?.factoryStorage?.storagePool[packet.StorageIndex]; if (storageComponent != null) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.StorageComponent)) { storageComponent.Import(reader.BinaryReader); } ItemProto itemProto = LDB.items.Select((int)GameMain.galaxy.PlanetById(packet.PlanetId)?.factory?.entityPool[storageComponent.entityId].protoId); //Imitation of UIStorageWindow.OnStorageIdChange() Multiplayer.Session.Storage.ActiveWindowTitle.text = itemProto.name; Multiplayer.Session.Storage.ActiveUIStorageGrid._Free(); Multiplayer.Session.Storage.ActiveUIStorageGrid._Init(storageComponent); Multiplayer.Session.Storage.ActiveStorageComponent = storageComponent; Multiplayer.Session.Storage.ActiveUIStorageGrid.SetStorageData(Multiplayer.Session.Storage.ActiveStorageComponent); Multiplayer.Session.Storage.ActiveUIStorageGrid._Open(); Multiplayer.Session.Storage.ActiveUIStorageGrid.OnStorageDataChanged(); Multiplayer.Session.Storage.ActiveBansSlider.maxValue = storageComponent.size; Multiplayer.Session.Storage.ActiveBansSlider.value = storageComponent.size - storageComponent.bans; Multiplayer.Session.Storage.ActiveBansValueText.text = Multiplayer.Session.Storage.ActiveBansSlider.value.ToString(); GameMain.galaxy.PlanetById(packet.PlanetId).factory.factoryStorage.storagePool[packet.StorageIndex] = storageComponent; } }
public static void GS2ApplySettings(byte[] compressedSettings) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(compressedSettings)) { GS2_GSSettings.GetMethod("DeSerialize").Invoke(GS2_GSSettings.GetProperty("Instance"), new object[] { reader.BinaryReader.ReadString() }); } }
public override void ProcessPacket(WarningDataPacket packet, NebulaConnection conn) { Multiplayer.Session.Warning.TickData = packet.Tick; using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.BinaryData)) { Multiplayer.Session.Warning.ImportBinaryData(reader.BinaryReader, packet.ActiveWarningCount); } }
public TrashData GetTrashData() { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(TrashDataByte)) { TrashData result = new TrashData(); result.Import(reader.BinaryReader); return(result); } }
public PrebuildData GetPrebuildData() { PrebuildData prebuild = new PrebuildData(); using (BinaryUtils.Reader writer = new BinaryUtils.Reader(PrebuildDataRaw)) { prebuild.Import(writer.BinaryReader); } return(prebuild); }
public TrashObject GetTrashObject() { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(TrashObjectByte)) { TrashObject result = new TrashObject(); result.Import(reader.BinaryReader); result.count = Count; return(result); } }
public void ProcessPacket(GameHistoryDataResponse packet, NebulaConnection conn) { //Reset all current values GameMain.data.history.Init(GameMain.data); Log.Info($"Parsing History data from the server."); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.HistoryBinaryData)) { GameMain.data.history.Import(reader.BinaryReader); } }
public void ProcessPacket(StatisticUpdateDataPacket packet, NebulaConnection conn) { StatisticalSnapShot snapshot; using (StatisticsManager.IsIncomingRequest.On()) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.StatisticsBinaryData)) { ref FactoryProductionStat[] productionStats = ref GameMain.statistics.production.factoryStatPool; int numOfSnapshots = reader.BinaryReader.ReadInt32(); for (int i = 0; i < numOfSnapshots; i++) { //Clear all current statistical data for (int a = 0; a < GameMain.statistics.production.factoryStatPool.Length; a++) { GameMain.statistics.production.factoryStatPool[a]?.ClearRegisters(); } //Load new snapshot snapshot = new StatisticalSnapShot(reader.BinaryReader); for (int factoryId = 0; factoryId < snapshot.ProductionChangesPerFactory.Length; factoryId++) { if (productionStats[factoryId] == null) { productionStats[factoryId] = new FactoryProductionStat(); productionStats[factoryId].Init(); } for (int changeId = 0; changeId < snapshot.ProductionChangesPerFactory[factoryId].Count; changeId++) { if (snapshot.ProductionChangesPerFactory[factoryId][changeId].IsProduction) { productionStats[factoryId].productRegister[snapshot.ProductionChangesPerFactory[factoryId][changeId].ProductId] += snapshot.ProductionChangesPerFactory[factoryId][changeId].Amount; } else { productionStats[factoryId].consumeRegister[snapshot.ProductionChangesPerFactory[factoryId][changeId].ProductId] += snapshot.ProductionChangesPerFactory[factoryId][changeId].Amount; } } //Import power system statistics productionStats[factoryId].powerGenRegister = snapshot.PowerGenerationRegister[factoryId]; productionStats[factoryId].powerConRegister = snapshot.PowerConsumptionRegister[factoryId]; productionStats[factoryId].powerChaRegister = snapshot.PowerChargingRegister[factoryId]; productionStats[factoryId].powerDisRegister = snapshot.PowerDischargingRegister[factoryId]; //Import fake energy stored values StatisticsManager.PowerEnergyStoredData = snapshot.EnergyStored; //Import Research statistics productionStats[factoryId].hashRegister = snapshot.HashRegister[factoryId]; } GameMain.statistics.production.GameTick(snapshot.CapturedGameTick); } } }
public override void ProcessPacket(MilestoneDataResponse packet, NebulaConnection conn) { if (IsHost) { return; } //Reset all current values GameMain.data.milestoneSystem.Init(GameMain.data); Log.Info($"Parsing Milstone data from the server."); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.BinaryData)) { GameMain.data.milestoneSystem.Import(reader.BinaryReader); } }
public static bool GetOrCreateFactory_Prefix(GameData __instance, PlanetFactory __result, PlanetData planet) { // We want the original method to run on the host client or in single player games if (!SimulatedWorld.Initialized || LocalPlayer.IsMasterClient) { return(true); } // Get the recieved bytes from the remote server that we will import byte[] factoryBytes; if (!LocalPlayer.PendingFactories.TryGetValue(planet.id, out factoryBytes)) { // We messed up, just defer to the default behaviour on the client (will cause desync but not outright crash) Log.Error($"PendingFactories did not have value we wanted, factory will not be synced!"); return(true); } // Take it off the list, as we will process it now LocalPlayer.PendingFactories.Remove(planet.id); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(factoryBytes)) { GameMain.data.factoryCount = reader.BinaryReader.ReadInt32(); int factoryIndex = reader.BinaryReader.ReadInt32(); // Import the factory from the given bytes, which will have been gotten or created on the host by the original function __instance.factories[factoryIndex] = new PlanetFactory(); if (planet.factory == null) { __instance.factories[factoryIndex].Import(factoryIndex, __instance, reader.BinaryReader); planet.factory = __instance.factories[factoryIndex]; planet.factoryIndex = factoryIndex; } else { __instance.factories[planet.factoryIndex].Import(planet.factoryIndex, __instance, reader.BinaryReader); planet.factory = __instance.factories[planet.factoryIndex]; } } // Assign the factory to the result __result = __instance.factories[planet.factoryIndex]; // Do not run the original method return(false); }
public List <BuildPreview> GetBuildPreviews() { List <BuildPreview> result = new List <BuildPreview>(); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(BuildPreviewData)) { int previewCount = reader.BinaryReader.ReadInt32(); for (int i = 0; i < previewCount; i++) { result.Add(new BuildPreview()); } for (int i = 0; i < previewCount; i++) { DeserializeBuildPreview(result[i], result, reader.BinaryReader); } } return(result); }
public override void ProcessPacket(PlanetDataResponse packet, NebulaConnection conn) { if (IsHost) { return; } PlanetData planet = null; if (Multiplayer.Session.IsInLobby) { planet = UIRoot.instance.galaxySelect.starmap._galaxyData.PlanetById(packet.PlanetDataID); } else { planet = GameMain.galaxy.PlanetById(packet.PlanetDataID); } Log.Info($"Parsing {packet.PlanetDataByte.Length} bytes of data for planet {planet.name} (ID: {planet.id})"); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.PlanetDataByte)) { planet.ImportRuntime(reader.BinaryReader); } if (Multiplayer.Session.IsInLobby) { // Pretend planet is loaded to make planetDetail show resources planet.loaded = true; UIRoot.instance.uiGame.planetDetail.RefreshDynamicProperties(); } else { lock (PlanetModelingManager.genPlanetReqList) { PlanetModelingManager.genPlanetReqList.Enqueue(planet); } } }
public void ProcessPacket(DysonSphereData packet, NebulaConnection conn) { //Failsafe, if client does not have instantiated sphere for the star, it will create dummy one that will be replaced during import if (GameMain.data.dysonSpheres[packet.StarIndex] == null) { GameMain.data.dysonSpheres[packet.StarIndex] = new DysonSphere(); GameMain.data.statistics.production.Init(GameMain.data); //Another failsafe, DysonSphere import requires initialized factory statistics if (GameMain.data.statistics.production.factoryStatPool[0] == null) { GameMain.data.statistics.production.factoryStatPool[0] = new FactoryProductionStat(); GameMain.data.statistics.production.factoryStatPool[0].Init(); } GameMain.data.dysonSpheres[packet.StarIndex].Init(GameMain.data, GameMain.data.galaxy.stars[packet.StarIndex]); } //Log.Info($"Parsing {packet.BinaryData.Length} bytes of data for DysonSphere in system {GameMain.data.galaxy.stars[packet.StarIndex].name} (Index: {GameMain.data.galaxy.stars[packet.StarIndex].index})"); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.BinaryData)) { GameMain.data.dysonSpheres[packet.StarIndex].Import(reader.BinaryReader); } }
public override void ProcessPacket(DysonSphereData packet, NebulaConnection conn) { if (IsHost) { return; } switch (packet.Event) { case DysonSphereRespondEvent.List: //Overwrite content assigned by UIDETopFunction.SetDysonComboBox() UIComboBox dysonBox = UIRoot.instance.uiGame.dysonEditor.controlPanel.topFunction.dysonBox; using (BinaryReader br = new BinaryUtils.Reader(packet.BinaryData).BinaryReader) { dysonBox.Items = new List <string>(); dysonBox.ItemsData = new List <int>(); int count = br.ReadInt32(); for (int i = 0; i < count; i++) { int starIndex = br.ReadInt32(); dysonBox.Items.Add(GameMain.galaxy.stars[starIndex].displayName); dysonBox.ItemsData.Add(starIndex); } } int index = dysonBox.ItemsData.FindIndex(x => x == UIRoot.instance.uiGame.dysonEditor.selection.viewStar?.index); dysonBox.itemIndex = index >= 0 ? index : 0; break; case DysonSphereRespondEvent.Load: //Failsafe, if client does not have instantiated sphere for the star, it will create dummy one that will be replaced during import GameMain.data.dysonSpheres[packet.StarIndex] = new DysonSphere(); GameMain.data.statistics.production.Init(GameMain.data); //Another failsafe, DysonSphere import requires initialized factory statistics if (GameMain.data.statistics.production.factoryStatPool[0] == null) { GameMain.data.statistics.production.factoryStatPool[0] = new FactoryProductionStat(); GameMain.data.statistics.production.factoryStatPool[0].Init(); } GameMain.data.dysonSpheres[packet.StarIndex].Init(GameMain.data, GameMain.data.galaxy.stars[packet.StarIndex]); StarData star = GameMain.galaxy.stars[packet.StarIndex]; Log.Info($"Parsing {packet.BinaryData.Length} bytes of data for DysonSphere {star.name} (INDEX: {star.id})"); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.BinaryData)) { GameMain.data.dysonSpheres[packet.StarIndex].Import(reader.BinaryReader); } if (UIRoot.instance.uiGame.dysonEditor.active) { UIRoot.instance.uiGame.dysonEditor.selection.SetViewStar(GameMain.galaxy.stars[packet.StarIndex]); UIComboBox dysonBox2 = UIRoot.instance.uiGame.dysonEditor.controlPanel.topFunction.dysonBox; int index2 = dysonBox2.ItemsData.FindIndex(x => x == UIRoot.instance.uiGame.dysonEditor.selection.viewStar?.index); dysonBox2.itemIndex = index2 >= 0 ? index2 : 0; } if (Multiplayer.Session.IsGameLoaded) { // Don't fade out when client is still joining InGamePopup.FadeOut(); } Multiplayer.Session.DysonSpheres.RequestingIndex = -1; Multiplayer.Session.DysonSpheres.IsNormal = true; break; case DysonSphereRespondEvent.Desync: Multiplayer.Session.DysonSpheres.HandleDesync(packet.StarIndex, conn); break; } }
public override void ProcessPacket(StatisticUpdateDataPacket packet, NebulaConnection conn) { StatisticalSnapShot snapshot; using (Multiplayer.Session.Statistics.IsIncomingRequest.On()) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.StatisticsBinaryData)) { bool itemChanged = false; ref FactoryProductionStat[] productionStats = ref GameMain.statistics.production.factoryStatPool; int numOfSnapshots = reader.BinaryReader.ReadInt32(); for (int i = 0; i < numOfSnapshots; i++) { //Load new snapshot snapshot = new StatisticalSnapShot(reader.BinaryReader); for (int factoryId = 0; factoryId < snapshot.ProductionChangesPerFactory.Length; factoryId++) { if (productionStats[factoryId] == null) { productionStats[factoryId] = new FactoryProductionStat(); productionStats[factoryId].Init(); } //Clear current statistical data productionStats[factoryId].PrepareTick(); for (int changeId = 0; changeId < snapshot.ProductionChangesPerFactory[factoryId].Count; changeId++) { StatisticalSnapShot.ProductionChangeStruct productionChange = snapshot.ProductionChangesPerFactory[factoryId][changeId]; if (productionChange.IsProduction) { productionStats[factoryId].productRegister[productionChange.ProductId] += productionChange.Amount; } else { productionStats[factoryId].consumeRegister[productionChange.ProductId] += productionChange.Amount; } } //Import power system statistics productionStats[factoryId].powerGenRegister = snapshot.PowerGenerationRegister[factoryId]; productionStats[factoryId].powerConRegister = snapshot.PowerConsumptionRegister[factoryId]; productionStats[factoryId].powerChaRegister = snapshot.PowerChargingRegister[factoryId]; productionStats[factoryId].powerDisRegister = snapshot.PowerDischargingRegister[factoryId]; //Import fake energy stored values Multiplayer.Session.Statistics.PowerEnergyStoredData = snapshot.EnergyStored; //Import Research statistics productionStats[factoryId].hashRegister = snapshot.HashRegister[factoryId]; //Processs changed registers. FactoryProductionStat.AfterTick() is empty currently so we ignore it. productionStats[factoryId].GameTick(snapshot.CapturedGameTick); itemChanged |= productionStats[factoryId].itemChanged; } } //Trigger GameMain.statistics.production.onItemChange() event when itemChanged is true if (itemChanged) { UIRoot.instance.uiGame.statWindow.OnItemChange(); NebulaModel.Logger.Log.Debug("StatisticsUpdateProcessor: itemChanged"); } } }
public override void ProcessPacket(PlayerMechaArmor packet, NebulaConnection conn) { INebulaPlayer player = null; if (IsHost) { // broadcast to other players player = playerManager.GetPlayer(conn); if (player != null) { playerManager.SendPacketToOtherPlayers(packet, player); } } using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.AppearanceData)) { if (Multiplayer.Session.LocalPlayer.Id == packet.PlayerId) { GameMain.mainPlayer.mecha.appearance.Import(reader.BinaryReader); GameMain.mainPlayer.mechaArmorModel.RefreshAllPartObjects(); GameMain.mainPlayer.mechaArmorModel.RefreshAllBoneObjects(); GameMain.mainPlayer.mecha.appearance.NotifyAllEvents(); GameMain.mainPlayer.mechaArmorModel._Init(GameMain.mainPlayer); GameMain.mainPlayer.mechaArmorModel._OnOpen(); // and also load it in the mecha editor UIMechaEditor editor = UIRoot.instance.uiMechaEditor; if (editor != null) { editor.selection.ClearSelection(); editor.saveGroup._Close(); if (editor.mecha.diyAppearance == null) { editor.mecha.diyAppearance = new MechaAppearance(); editor.mecha.diyAppearance.Init(); } GameMain.mainPlayer.mecha.appearance.CopyTo(editor.mecha.diyAppearance); editor.mechaArmorModel.RefreshAllPartObjects(); editor.mechaArmorModel.RefreshAllBoneObjects(); editor.mecha.diyAppearance.NotifyAllEvents(); editor._left_content_height_max = 0f; editor.SetLeftScrollTop(); editor.saveGroup._Open(); } } else { using (Multiplayer.Session.World.GetRemotePlayersModels(out Dictionary <ushort, RemotePlayerModel> remotePlayersModels)) { if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel playerModel)) { playerModel.MechaInstance.appearance.Import(reader.BinaryReader); playerModel.PlayerInstance.mechaArmorModel.RefreshAllPartObjects(); playerModel.PlayerInstance.mechaArmorModel.RefreshAllBoneObjects(); playerModel.MechaInstance.appearance.NotifyAllEvents(); playerModel.PlayerInstance.mechaArmorModel._Init(playerModel.PlayerInstance); playerModel.PlayerInstance.mechaArmorModel._OnOpen(); // and store the appearance on the server if (IsHost && player != null) { if (player.Data.Appearance == null) { player.Data.Appearance = new MechaAppearance(); player.Data.Appearance.Init(); } playerModel.MechaInstance.appearance.CopyTo(player.Data.Appearance); } } } } } }
public override void ProcessPacket(LobbyRequest packet, NebulaConnection conn) { if (IsClient) { return; } INebulaPlayer player; using (playerManager.GetPendingPlayers(out Dictionary <INebulaConnection, INebulaPlayer> pendingPlayers)) { if (!pendingPlayers.TryGetValue(conn, out player)) { conn.Disconnect(DisconnectionReason.InvalidData); Log.Warn("WARNING: Player tried to enter lobby without being in the pending list"); return; } if (GameMain.isFullscreenPaused) { conn.Disconnect(DisconnectionReason.HostStillLoading); pendingPlayers.Remove(conn); return; } Dictionary <string, string> clientMods = new Dictionary <string, string>(); using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.ModsVersion)) { for (int i = 0; i < packet.ModsCount; i++) { string guid = reader.BinaryReader.ReadString(); string version = reader.BinaryReader.ReadString(); if (!BepInEx.Bootstrap.Chainloader.PluginInfos.ContainsKey(guid)) { conn.Disconnect(DisconnectionReason.ModIsMissingOnServer, guid); pendingPlayers.Remove(conn); return; } clientMods.Add(guid, version); } } foreach (KeyValuePair <string, BepInEx.PluginInfo> pluginInfo in BepInEx.Bootstrap.Chainloader.PluginInfos) { if (pluginInfo.Value.Instance is IMultiplayerMod mod) { if (!clientMods.ContainsKey(pluginInfo.Key)) { conn.Disconnect(DisconnectionReason.ModIsMissing, pluginInfo.Key); pendingPlayers.Remove(conn); return; } string version = clientMods[pluginInfo.Key]; if (mod.CheckVersion(mod.Version, version)) { continue; } conn.Disconnect(DisconnectionReason.ModVersionMismatch, $"{pluginInfo.Key};{version};{mod.Version}"); pendingPlayers.Remove(conn); return; } else { foreach (BepInEx.BepInDependency dependency in pluginInfo.Value.Dependencies) { if (dependency.DependencyGUID == NebulaModAPI.API_GUID) { string hostVersion = pluginInfo.Value.Metadata.Version.ToString(); if (!clientMods.ContainsKey(pluginInfo.Key)) { conn.Disconnect(DisconnectionReason.ModIsMissing, pluginInfo.Key); pendingPlayers.Remove(conn); return; } if (clientMods[pluginInfo.Key] != hostVersion) { conn.Disconnect(DisconnectionReason.ModVersionMismatch, $"{pluginInfo.Key};{clientMods[pluginInfo.Key]};{hostVersion}"); pendingPlayers.Remove(conn); return; } } } } } if (packet.GameVersionSig != GameConfig.gameVersion.sig) { conn.Disconnect(DisconnectionReason.GameVersionMismatch, $"{ packet.GameVersionSig };{ GameConfig.gameVersion.sig }"); pendingPlayers.Remove(conn); return; } } bool isNewUser = false; //TODO: some validation of client cert / generating auth challenge for the client // Load old data of the client string clientCertHash = CryptoUtils.Hash(packet.ClientCert); using (playerManager.GetSavedPlayerData(out Dictionary <string, IPlayerData> savedPlayerData)) { if (savedPlayerData.TryGetValue(clientCertHash, out IPlayerData value)) { using (playerManager.GetConnectedPlayers(out Dictionary <INebulaConnection, INebulaPlayer> connectedPlayers)) { IPlayerData playerData = value; foreach (INebulaPlayer connectedPlayer in connectedPlayers.Values) { if (connectedPlayer.Data == playerData) { playerData = value.CreateCopyWithoutMechaData(); Log.Warn($"Copy playerData for duplicated player{playerData.PlayerId} {playerData.Username}"); } } player.LoadUserData(playerData); } } else { // store player data once he fully loaded into the game (SyncCompleteProcessor) isNewUser = true; } } // Add the username to the player data player.Data.Username = !string.IsNullOrWhiteSpace(packet.Username) ? packet.Username : $"Player {player.Id}"; // Add the Mecha Color to the player data player.Data.MechaColors = packet.MechaColors; Multiplayer.Session.NumPlayers += 1; DiscordManager.UpdateRichPresence(); // if user is known and host is ingame dont put him into lobby but let him join the game if (!isNewUser && Multiplayer.Session.IsGameLoaded) { // Remove the new player from pending list using (playerManager.GetPendingPlayers(out Dictionary <INebulaConnection, INebulaPlayer> pendingPlayers)) { pendingPlayers.Remove(conn); } // Add the new player to the list using (playerManager.GetSyncingPlayers(out Dictionary <INebulaConnection, INebulaPlayer> syncingPlayers)) { syncingPlayers.Add(conn, player); } Multiplayer.Session.World.OnPlayerJoining(player.Data.Username); NebulaModAPI.OnPlayerJoinedGame?.Invoke(player.Data); // Make sure that each player that is currently in the game receives that a new player as join so they can create its RemotePlayerCharacter PlayerJoining pdata = new PlayerJoining((PlayerData)player.Data.CreateCopyWithoutMechaData(), Multiplayer.Session.NumPlayers); // Remove inventory from mecha data using (playerManager.GetConnectedPlayers(out Dictionary <INebulaConnection, INebulaPlayer> connectedPlayers)) { foreach (KeyValuePair <INebulaConnection, INebulaPlayer> kvp in connectedPlayers) { kvp.Value.SendPacket(pdata); } } //Add current tech bonuses to the connecting player based on the Host's mecha ((MechaData)player.Data.Mecha).TechBonuses = new PlayerTechBonuses(GameMain.mainPlayer.mecha); using (BinaryUtils.Writer p = new BinaryUtils.Writer()) { int count = 0; foreach (KeyValuePair <string, BepInEx.PluginInfo> pluginInfo in BepInEx.Bootstrap.Chainloader.PluginInfos) { if (pluginInfo.Value.Instance is IMultiplayerModWithSettings mod) { p.BinaryWriter.Write(pluginInfo.Key); mod.Export(p.BinaryWriter); count++; } } GameDesc gameDesc = GameMain.data.gameDesc; player.SendPacket(new HandshakeResponse(gameDesc.galaxyAlgo, gameDesc.galaxySeed, gameDesc.starCount, gameDesc.resourceMultiplier, gameDesc.savedThemeIds, isNewUser, (PlayerData)player.Data, p.CloseAndGetBytes(), count, Config.Options.SyncSoil, Multiplayer.Session.NumPlayers, DiscordManager.GetPartyId())); } } else { GameDesc gameDesc = Multiplayer.Session.IsGameLoaded ? GameMain.data.gameDesc : UIRoot.instance.galaxySelect.gameDesc; using (BinaryUtils.Writer p = new BinaryUtils.Writer()) { int count = 0; foreach (KeyValuePair <string, BepInEx.PluginInfo> pluginInfo in BepInEx.Bootstrap.Chainloader.PluginInfos) { if (pluginInfo.Value.Instance is IMultiplayerModWithSettings mod) { p.BinaryWriter.Write(pluginInfo.Key); mod.Export(p.BinaryWriter); count++; } } player.SendPacket(new LobbyResponse(gameDesc.galaxyAlgo, gameDesc.galaxySeed, gameDesc.starCount, gameDesc.resourceMultiplier, gameDesc.savedThemeIds, p.CloseAndGetBytes(), count, Multiplayer.Session.NumPlayers, DiscordManager.GetPartyId())); } // Send overriden Planet and Star names player.SendPacket(new NameInputPacket(GameMain.galaxy, Multiplayer.Session.LocalPlayer.Id)); } }
public override void ProcessPacket(PlayerMechaDIYArmor packet, NebulaConnection conn) { // store DIYAppearance and items to serve them when player connects again if (IsHost) { using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.DIYAppearanceData)) { INebulaPlayer player = playerManager.GetPlayer(conn); if (player != null) { if (player.Data.DIYAppearance == null) { player.Data.DIYAppearance = new MechaAppearance(); player.Data.DIYAppearance.Init(); } player.Data.DIYAppearance.Import(reader.BinaryReader); player.Data.DIYItemId = packet.DIYItemId; player.Data.DIYItemValue = packet.DIYItemValue; } } } else { // load DIYAppearance received from host to display in mecha appearance editor using (BinaryUtils.Reader reader = new BinaryUtils.Reader(packet.DIYAppearanceData)) { Player player = GameMain.mainPlayer; UIMechaEditor editor = UIRoot.instance.uiMechaEditor; if (player.mecha.diyAppearance == null) { player.mecha.diyAppearance = new MechaAppearance(); player.mecha.diyAppearance.Init(); } player.mecha.diyAppearance.Import(reader.BinaryReader); if (packet.DIYItemId.Length > 0) { player.mecha.diyItems.Clear(); for (int i = 0; i < packet.DIYItemId.Length; i++) { player.mecha.diyItems.items[packet.DIYItemId[i]] = packet.DIYItemValue[i]; } } if (editor != null) { editor.selection.ClearSelection(); editor.saveGroup._Close(); if (editor.mecha.diyAppearance == null) { editor.mecha.diyAppearance = new MechaAppearance(); editor.mecha.diyAppearance.Init(); } GameMain.mainPlayer.mecha.diyAppearance.CopyTo(editor.mecha.diyAppearance); editor.mechaArmorModel.RefreshAllPartObjects(); editor.mechaArmorModel.RefreshAllBoneObjects(); editor.mecha.diyAppearance.NotifyAllEvents(); editor._left_content_height_max = 0f; editor.SetLeftScrollTop(); editor.saveGroup._Open(); } } } }