public override void ExposeData() { Scribe_Values.Look(ref username, "username"); Scribe_Values.Look(ref showCursors, "showCursors", true); Scribe_Values.Look(ref autoAcceptSteam, "autoAcceptSteam"); Scribe_Values.Look(ref transparentChat, "transparentChat"); Scribe_Values.Look(ref autosaveSlots, "autosaveSlots", 5); Scribe_Values.Look(ref aggressiveTicking, "aggressiveTicking", true); Scribe_Values.Look(ref syncModConfigs, "syncModConfigs", true); Scribe_Values.Look(ref showDevInfo, "showDevInfo"); Scribe_Values.Look(ref serverAddress, "serverAddress", "127.0.0.1"); Scribe_Values.Look(ref pauseAutosaveCounter, "pauseAutosaveCounter", true); Scribe_Values.Look(ref showModCompatibility, "showModCompatibility", true); Scribe_Deep.Look(ref serverSettings, "serverSettings"); if (serverSettings == null) { serverSettings = new ServerSettings(); } if (Scribe.mode == LoadSaveMode.Saving && showModCompatibility && Multiplayer.modsCompatibility.Count == 0) { ModManagement.UpdateModCompatibilityDb(); } }
public void HandleModList(ByteReader data) { Multiplayer.session.mods.remoteRwVersion = data.ReadString(); Multiplayer.session.mods.remoteModNames = data.ReadPrefixedStrings(); Multiplayer.session.mods.remoteModIds = data.ReadPrefixedStrings(); Multiplayer.session.mods.remoteWorkshopModIds = data.ReadPrefixedULongs(); var modConfigsCompressed = data.ReadPrefixedBytes(); Multiplayer.session.mods.remoteModConfigs = SimpleJson.DeserializeObject <Dictionary <string, string> >(GZipStream.UncompressString(modConfigsCompressed)); Multiplayer.session.mods.defInfo = Multiplayer.localDefInfos; var modsMatch = ModManagement.ModsMatch(Multiplayer.session.mods.remoteModIds); var modConfigsMatch = ModManagement.CheckModConfigsMatch(Multiplayer.session.mods.remoteModConfigs); if (!modsMatch || !modConfigsMatch) { if (!modConfigsMatch) { Log.Message($"MP Connect: client mod configs don't match server: {ModManagement.GetMismatchedModConfigs(Multiplayer.session.mods.remoteModConfigs).ToCommaList()}"); } Find.WindowStack.windows.Clear(); Find.WindowStack.Add(new ModsMismatchWindow( Multiplayer.session.mods, SendClientDefs )); return; } SendClientDefs(); }
public static Dictionary <string, string> GetSyncableConfigFiles() { return(new DirectoryInfo(GenFilePaths.ConfigFolderPath) .GetFiles("*.xml", SearchOption.AllDirectories) .Concat(new DirectoryInfo(GenFilePaths.FolderUnderSaveData("HugsLib")).GetFiles("*.xml", SearchOption.AllDirectories)) .Where(FilterNonSyncedConfigFiles) .ToDictionary( file => ModManagement.ModConfigFileRelative(file.FullName, true), file => file.OpenText().ReadToEnd() )); }
public ModsMismatchWindow(SessionModInfo mods, Action continueConnecting) : base("MpWrongDefs".Translate(), "MpWrongDefsInfo".Translate()) { this.mods = mods; this.continueConnecting = continueConnecting; returnToServerBrowser = true; modsMatch = ModManagement.ModsMatch(mods.remoteModIds); modConfigsMatch = ModManagement.CheckModConfigsMatch(mods.remoteModConfigs); if (modsMatch) { reason = "MpWrongModConfigs".Translate(); desc = "MpWrongModConfigsInfo".Translate(); } }
public override void DrawButtons(Rect inRect) { var btnWidth = 90f; var gap = 10f; Rect btnRect = new Rect(gap, inRect.height - ButtonHeight - 10f, btnWidth, ButtonHeight); if (Widgets.ButtonText(btnRect, "Details".Translate())) { var defs = mods.defInfo.Where(kv => kv.Value.status != DefCheckStatus.OK).Join(kv => $"{kv.Key}: {kv.Value.status}", delimiter: "\n"); Find.WindowStack.Add(new TextAreaWindow($"Mismatches:\n\n{defs}")); } btnRect.x += btnWidth + gap; if (Widgets.ButtonText(btnRect, "MpModList".Translate())) { ShowModList(mods); } btnRect.x += btnWidth + gap; btnRect.width = 140f; if (Widgets.ButtonText(btnRect, "MpSyncModList".Translate())) { Log.Message("MP remote host's modIds: " + string.Join(", ", mods.remoteModIds)); Log.Message("MP remote host's workshopIds: " + string.Join(", ", mods.remoteWorkshopModIds)); LongEventHandler.QueueLongEvent(() => { ModManagement.DownloadWorkshopMods(mods.remoteWorkshopModIds); try { ModManagement.RebuildModsList(); ModsConfig.SetActiveToList(mods.remoteModIds.ToList()); ModsConfig.Save(); ModManagement.PromptRestartAndReconnect(mods.remoteAddress, mods.remotePort); } catch (Exception e) { Log.Error($"MP mod sync error: {e.GetType()} {e.Message}"); } }, "MpDownloadingWorkshopMods", true, null); } btnRect.x += btnRect.width + gap; btnRect.width = btnWidth; if (Widgets.ButtonText(btnRect, "CloseButton".Translate())) { Close(); } }
private void SyncModsAndConfigs(bool syncConfigs) { Log.Message("MP remote host's modIds: " + string.Join(", ", mods.remoteModIds)); Log.Message("MP remote host's workshopIds: " + string.Join(", ", mods.remoteWorkshopModIds)); LongEventHandler.QueueLongEvent(() => { try { ModManagement.DownloadWorkshopMods(mods.remoteWorkshopModIds); } catch (InvalidOperationException e) { Log.Warning($"MP Workshop mod download error: {e.Message}"); var missingMods = ModManagement.GetNotInstalledMods(mods.remoteModIds).ToList(); if (missingMods.Any()) { Find.WindowStack.Add(new DebugTextWindow( $"Failed to connect to Workshop.\nThe following mods are missing, please install them:\n" + missingMods.Join(s => $"- {s}", "\n") )); return; } } try { ModManagement.RebuildModsList(); ModsConfig.SetActiveToList(mods.remoteModIds.ToList()); ModsConfig.Save(); if (syncConfigs) { ModManagement.ApplyHostModConfigFiles(mods.remoteModConfigs); } ModManagement.PromptRestartAndReconnect(mods.remoteAddress, mods.remotePort); } catch (Exception e) { Log.Error($"MP mod sync error: {e.GetType()} {e.Message}"); Find.WindowStack.Add(new DebugTextWindow($"Failed to sync mods: {e.GetType()} {e.Message}")); } }, "MpDownloadingWorkshopMods", true, null); }
public static void HostServer(ServerSettings settings, bool fromReplay, bool withSimulation = false, bool debugMode = false, bool logDesyncTraces = false) { Log.Message($"Starting the server"); var session = Multiplayer.session = new MultiplayerSession(); session.myFactionId = Faction.OfPlayer.loadID; session.localSettings = settings; session.gameName = settings.gameName; var localServer = new MultiplayerServer(settings); if (withSimulation) { localServer.savedGame = GZipStream.CompressBuffer(OnMainThread.cachedGameData); localServer.mapData = OnMainThread.cachedMapData.ToDictionary(kv => kv.Key, kv => GZipStream.CompressBuffer(kv.Value)); localServer.mapCmds = OnMainThread.cachedMapCmds.ToDictionary(kv => kv.Key, kv => kv.Value.Select(c => c.Serialize()).ToList()); } else { OnMainThread.ClearCaches(); } localServer.debugMode = debugMode; localServer.debugOnlySyncCmds = new HashSet <int>(Sync.handlers.Where(h => h.debugOnly).Select(h => h.syncId)); localServer.hostOnlySyncCmds = new HashSet <int>(Sync.handlers.Where(h => h.hostOnly).Select(h => h.syncId)); localServer.hostUsername = Multiplayer.username; localServer.coopFactionId = Faction.OfPlayer.loadID; localServer.rwVersion = session.mods.remoteRwVersion = VersionControl.CurrentVersionString; localServer.modNames = session.mods.remoteModNames = LoadedModManager.RunningModsListForReading.Select(m => m.Name).ToArray(); localServer.modIds = session.mods.remoteModIds = LoadedModManager.RunningModsListForReading.Select(m => m.PackageId).ToArray(); localServer.workshopModIds = session.mods.remoteWorkshopModIds = ModManagement.GetEnabledWorkshopMods().ToArray(); localServer.defInfos = session.mods.defInfo = Multiplayer.localDefInfos; Log.Message($"MP Host modIds: {string.Join(", ", localServer.modIds)}"); Log.Message($"MP Host workshopIds: {string.Join(", ", localServer.workshopModIds)}"); if (settings.steam) { localServer.NetTick += SteamIntegration.ServerSteamNetTick; } if (fromReplay) { localServer.gameTimer = TickPatch.Timer; } MultiplayerServer.instance = localServer; session.localServer = localServer; if (!fromReplay) { SetupGame(); } foreach (var tickable in TickPatch.AllTickables) { tickable.Cmds.Clear(); } Find.PlaySettings.usePlanetDayNightSystem = false; Multiplayer.RealPlayerFaction = Faction.OfPlayer; localServer.playerFactions[Multiplayer.username] = Faction.OfPlayer.loadID; SetupLocalClient(); Find.MainTabsRoot.EscapeCurrentTab(false); Multiplayer.session.AddMsg("If you are having a issue with the mod and would like some help resolving it, then please reach out to us on our discord server:", false); Multiplayer.session.AddMsg(new ChatMsg_Url("https://discord.gg/S4bxXpv"), false); if (withSimulation) { StartServerThread(); } else { var timeSpeed = TimeSpeed.Paused; Multiplayer.WorldComp.TimeSpeed = timeSpeed; foreach (var map in Find.Maps) { map.AsyncTime().TimeSpeed = timeSpeed; } Multiplayer.WorldComp.UpdateTimeSpeed(); Multiplayer.WorldComp.debugMode = debugMode; Multiplayer.WorldComp.logDesyncTraces = logDesyncTraces; LongEventHandler.QueueLongEvent(() => { SaveLoad.CacheGameData(SaveLoad.SaveAndReload()); SaveLoad.SendCurrentGameData(false); StartServerThread(); }, "MpSaving", false, null); } void StartServerThread() { var netStarted = localServer.StartListeningNet(); var lanStarted = localServer.StartListeningLan(); string text = "Server started."; if (netStarted != null) { text += (netStarted.Value ? $" Direct at {settings.bindAddress}:{localServer.NetPort}." : " Couldn't bind direct."); } if (lanStarted != null) { text += (lanStarted.Value ? $" LAN at {settings.lanAddress}:{localServer.LanPort}." : " Couldn't bind LAN."); } session.serverThread = new Thread(localServer.Run) { Name = "Local server thread" }; session.serverThread.Start(); Messages.Message(text, MessageTypeDefOf.SilentInput, false); Log.Message(text); } }
private static void ShowConfigsList(SessionModInfo mods) { var mismatchedModConfigs = ModManagement.GetMismatchedModConfigs(mods.remoteModConfigs); Find.WindowStack.Add(new DebugTextWindow($"Mismatched mod configs:\n\n{mismatchedModConfigs.Join(file => "+ " + file, "\n")}")); }