static void ShowModDebugInfo() { var info = new RemoteData(); JoinData.ReadServerData(JoinData.WriteServerData(true), info); for (int i = 0; i < 200; i++) { info.remoteMods.Add(info.remoteMods.Last()); } info.remoteFiles.Add("rwmt.multiplayer", new ModFile() { relPath = "/Test/Test.xml" }); //info.remoteFiles.Add("ludeon.rimworld", new ModFile() { relPath = "/Test/Test.xml" }); Find.WindowStack.Add(new JoinDataWindow(info)); }
public void HandleJoinData(ByteReader data) { Multiplayer.session.gameName = data.ReadString(); Multiplayer.session.playerId = data.ReadInt32(); var remoteInfo = new RemoteData { remoteRwVersion = data.ReadString(), remoteMpVersion = data.ReadString(), remoteAddress = Multiplayer.session.address, remotePort = Multiplayer.session.port, remoteSteamHost = Multiplayer.session.steamHost }; var defDiff = false; var defsData = new ByteReader(data.ReadPrefixedBytes()); foreach (var local in MultiplayerData.localDefInfos) { var status = (DefCheckStatus)defsData.ReadByte(); local.Value.status = status; if (status != DefCheckStatus.Ok) { defDiff = true; } } JoinData.ReadServerData(data.ReadPrefixedBytes(), remoteInfo); OnMainThread.Schedule(Complete, 0.3f); void Complete() { if (JoinData.CompareToLocal(remoteInfo) && !defDiff) { StartDownloading(); return; } if (defDiff) { Multiplayer.StopMultiplayer(); } var connectingWindow = Find.WindowStack.WindowOfType <BaseConnectingWindow>(); MpUI.ClearWindowStack(); var defDiffStr = "\n\n" + MultiplayerData.localDefInfos .Where(kv => kv.Value.status != DefCheckStatus.Ok) .Take(10) .Join(kv => $"{kv.Key}: {kv.Value.status}", "\n"); Find.WindowStack.Add(new JoinDataWindow(remoteInfo) { connectAnywayDisabled = defDiff ? "MpMismatchDefsDiff".Translate() + defDiffStr : null, connectAnywayCallback = () => { Find.WindowStack.Add(connectingWindow); StartDownloading(); } }); void StartDownloading() { connection.Send(Packets.Client_WorldRequest); subState = JoiningState.Waiting; } } }
public static void HostServer(ServerSettings settings, bool fromReplay, bool hadSimulation, bool asyncTime) { Log.Message($"Starting the server"); var session = new MultiplayerSession(); if (Multiplayer.session != null) // This is the case when hosting from a replay { session.dataSnapshot = Multiplayer.session.dataSnapshot; } Multiplayer.session = session; session.myFactionId = Faction.OfPlayer.loadID; session.localServerSettings = settings; session.gameName = settings.gameName; // Server already pre-inited in HostWindow var localServer = Multiplayer.LocalServer; MultiplayerServer.instance = Multiplayer.LocalServer; if (hadSimulation) { localServer.savedGame = GZipStream.CompressBuffer(session.dataSnapshot.gameData); localServer.semiPersistent = GZipStream.CompressBuffer(session.dataSnapshot.semiPersistentData); localServer.mapData = session.dataSnapshot.mapData.ToDictionary(kv => kv.Key, kv => GZipStream.CompressBuffer(kv.Value)); localServer.mapCmds = session.dataSnapshot.mapCmds.ToDictionary(kv => kv.Key, kv => kv.Value.Select(ScheduledCommand.Serialize).ToList()); } localServer.commands.debugOnlySyncCmds = Sync.handlers.Where(h => h.debugOnly).Select(h => h.syncId).ToHashSet(); localServer.commands.hostOnlySyncCmds = Sync.handlers.Where(h => h.hostOnly).Select(h => h.syncId).ToHashSet(); localServer.hostUsername = Multiplayer.username; localServer.coopFactionId = Faction.OfPlayer.loadID; localServer.rwVersion = VersionControl.CurrentVersionString; localServer.mpVersion = MpVersion.Version; localServer.defInfos = MultiplayerData.localDefInfos; localServer.serverData = JoinData.WriteServerData(settings.syncConfigs); if (settings.steam) { localServer.TickEvent += SteamIntegration.ServerSteamNetTick; } if (fromReplay) { localServer.gameTimer = TickPatch.Timer; } if (!fromReplay) { SetupGameFromSingleplayer(); } 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 any issues with the mod and would like some help resolving them, then please reach out to us on our Discord server:", false); Multiplayer.session.AddMsg(new ChatMsg_Url("https://discord.gg/S4bxXpv"), false); if (hadSimulation) { StartServerThread(); } else { Multiplayer.WorldComp.TimeSpeed = TimeSpeed.Paused; foreach (var map in Find.Maps) { map.AsyncTime().TimeSpeed = TimeSpeed.Paused; } Multiplayer.WorldComp.UpdateTimeSpeed(); Multiplayer.GameComp.asyncTime = asyncTime; Multiplayer.GameComp.debugMode = settings.debugMode; Multiplayer.GameComp.logDesyncTraces = settings.desyncTraces; LongEventHandler.QueueLongEvent(() => { Multiplayer.session.dataSnapshot = SaveLoad.CreateGameDataSnapshot(SaveLoad.SaveAndReload()); SaveLoad.SendGameData(Multiplayer.session.dataSnapshot, false); StartServerThread(); }, "MpSaving", false, null); } void StartServerThread() { localServer.running = true; Multiplayer.LocalServer.serverThread = new Thread(localServer.Run) { Name = "Local server thread" }; Multiplayer.LocalServer.serverThread.Start(); const string text = "Server started."; Messages.Message(text, MessageTypeDefOf.SilentInput, false); Log.Message(text); } }
static MultiplayerStatic() { Native.InitLmfPtr(); // UnityEngine.Debug.Log instead of Verse.Log.Message because the server runs on its own thread ServerLog.info = str => UnityEngine.Debug.Log($"MpServerLog: {str}"); ServerLog.error = str => UnityEngine.Debug.Log($"MpServerLog Error: {str}"); NetDebug.Logger = new ServerLog(); SetUsername(); if (SteamManager.Initialized) { SteamIntegration.InitCallbacks(); } Log.Message($"Multiplayer version {MpVersion.Version}"); Log.Message($"Player's username: {Multiplayer.username}"); var persistentObj = new GameObject(); persistentObj.AddComponent <OnMainThread>(); UnityEngine.Object.DontDestroyOnLoad(persistentObj); MpConnectionState.SetImplementation(ConnectionStateEnum.ClientSteam, typeof(ClientSteamState)); MpConnectionState.SetImplementation(ConnectionStateEnum.ClientJoining, typeof(ClientJoiningState)); MpConnectionState.SetImplementation(ConnectionStateEnum.ClientPlaying, typeof(ClientPlayingState)); MultiplayerData.CollectCursorIcons(); PersistentDialog.BindAll(typeof(Multiplayer).Assembly); using (DeepProfilerWrapper.Section("Multiplayer MpPatches")) Multiplayer.harmony.DoAllMpPatches(); using (DeepProfilerWrapper.Section("Multiplayer patches")) DoPatches(); Log.messageQueue.maxMessages = 1000; DoubleLongEvent(() => { MultiplayerData.CollectDefInfos(); Sync.PostInitHandlers(); }, "Loading"); // Right before the events from HandleCommandLine HandleRestartConnect(); HandleCommandLine(); if (Multiplayer.arbiterInstance) { RuntimeHelpers.RunClassConstructor(typeof(Text).TypeHandle); } using (DeepProfilerWrapper.Section("Multiplayer TakeModDataSnapshot")) JoinData.TakeModDataSnapshot(); using (DeepProfilerWrapper.Section("MultiplayerData PrecacheMods")) MultiplayerData.PrecacheMods(); if (GenCommandLine.CommandLineArgPassed("profiler")) { SimpleProfiler.Print("mp_prof_out.txt"); } }