private void UpdateVessels() { iterateVessels.Clear(); iterateVessels.AddRange(loadingFlyingVessels.Keys); foreach (Guid vesselID in iterateVessels) { if (!loadingFlyingVessels.ContainsKey(vesselID)) { continue; } HackyFlyingVesselLoad hfvl = loadingFlyingVessels[vesselID]; if (hfvl.flyingVessel == null || hfvl.flyingVessel.state == Vessel.State.DEAD) { DarkLog.Debug("Hacky load failed: Vessel destroyed"); loadingFlyingVessels.Remove(vesselID); continue; } if (!FlightGlobals.fetch.vessels.Contains(hfvl.flyingVessel)) { DarkLog.Debug("Hacky load failed: Vessel destroyed"); loadingFlyingVessels.Remove(vesselID); continue; } if (!LockSystem.fetch.LockExists("update-" + vesselID) || LockSystem.fetch.LockIsOurs("update-" + vesselID)) { DarkLog.Debug("Hacky load removed: Vessel stopped being controlled by another player"); loadingFlyingVessels.Remove(vesselID); VesselWorker.fetch.KillVessel(hfvl.flyingVessel); continue; } if (hfvl.flyingVessel.loaded) { if ((Client.realtimeSinceStartup - hfvl.lastUnpackTime) > UNPACK_INTERVAL) { DarkLog.Debug("Hacky load attempting to take loaded vessel off rails"); hfvl.lastUnpackTime = Client.realtimeSinceStartup; try { hfvl.flyingVessel.GoOffRails(); } catch (Exception e) { //Just in case, I don't think this can throw but you never really know with KSP. DarkLog.Debug("Hacky load failed to take vessel of rails: " + e.Message); } continue; } } if (!hfvl.flyingVessel.packed) { DarkLog.Debug("Hacky load successful: Vessel is off rails"); loadingFlyingVessels.Remove(vesselID); hfvl.flyingVessel.Landed = false; hfvl.flyingVessel.Splashed = false; hfvl.flyingVessel.landedAt = string.Empty; hfvl.flyingVessel.situation = Vessel.Situations.FLYING; hfvl.flyingVessel.vesselRanges.landed.load = LANDED_LOAD_DISTANCE_DEFAULT; hfvl.flyingVessel.vesselRanges.landed.unload = LANDED_UNLOAD_DISTANCE_DEFAULT; continue; } double atmoPressure = hfvl.flyingVessel.mainBody.GetPressure(hfvl.flyingVessel.altitude); if (atmoPressure < 0.01d) { DarkLog.Debug("Hacky load successful: Vessel is now safe from atmo"); loadingFlyingVessels.Remove(vesselID); hfvl.flyingVessel.Landed = false; hfvl.flyingVessel.Splashed = false; hfvl.flyingVessel.landedAt = string.Empty; hfvl.flyingVessel.situation = Vessel.Situations.FLYING; hfvl.flyingVessel.vesselRanges.landed.load = LANDED_LOAD_DISTANCE_DEFAULT; hfvl.flyingVessel.vesselRanges.landed.unload = LANDED_UNLOAD_DISTANCE_DEFAULT; continue; } if (hfvl.lastVesselUpdate != null) { hfvl.lastVesselUpdate.Apply(); } } }
public void Awake() { DarkLog.SetMainThread(); if (!CompatibilityChecker.IsCompatible() || !InstallChecker.IsCorrectlyInstalled()) { modDisabled = true; } if (Settings.fetch.disclaimerAccepted != 1) { modDisabled = true; DisclaimerWindow.SpawnDialog(); } Profiler.DMPReferenceTime.Start(); DontDestroyOnLoad(this); // Prevents symlink warning for development. SetupDirectoriesIfNeeded(); // UniverseSyncCache needs to run expiry here UniverseSyncCache.fetch.ExpireCache(); // Register events needed to bootstrap the workers. lock (eventLock) { resetEvent.Add(LockSystem.Reset); resetEvent.Add(AdminSystem.Reset); resetEvent.Add(AsteroidWorker.Reset); resetEvent.Add(ChatWorker.Reset); resetEvent.Add(CraftLibraryWorker.Reset); resetEvent.Add(DebugWindow.Reset); resetEvent.Add(DynamicTickWorker.Reset); resetEvent.Add(FlagSyncer.Reset); resetEvent.Add(HackyInAtmoLoader.Reset); resetEvent.Add(KerbalReassigner.Reset); resetEvent.Add(PlayerColorWorker.Reset); resetEvent.Add(PlayerStatusWindow.Reset); resetEvent.Add(PlayerStatusWorker.Reset); resetEvent.Add(PartKiller.Reset); resetEvent.Add(ScenarioWorker.Reset); resetEvent.Add(ScreenshotWorker.Reset); resetEvent.Add(TimeSyncer.Reset); resetEvent.Add(ToolbarSupport.Reset); resetEvent.Add(VesselWorker.Reset); resetEvent.Add(WarpWorker.Reset); GameEvents.onHideUI.Add(() => { showGUI = false; }); GameEvents.onShowUI.Add(() => { showGUI = true; }); } FireResetEvent(); HandleCommandLineArgs(); long testTime = Compression.TestSysIOCompression(); DarkLog.Debug("System.IO compression works: " + Compression.sysIOCompressionWorks + ", test time: " + testTime + " ms."); DarkLog.Debug("DarkMultiPlayer " + Common.PROGRAM_VERSION + ", protocol " + Common.PROTOCOL_VERSION + " Initialized!"); }
public void Update() { long startClock = Profiler.DMPReferenceTime.ElapsedTicks; lastClockTicks = DateTime.UtcNow.Ticks; lastRealTimeSinceStartup = Time.realtimeSinceStartup; DarkLog.Update(); if (modDisabled) { return; } try { if (HighLogic.LoadedScene == GameScenes.MAINMENU) { if (!modWorker.dllListBuilt) { modWorker.dllListBuilt = true; modWorker.BuildDllFileList(); } if (!dmpSaveChecked) { dmpSaveChecked = true; SetupBlankGameIfNeeded(); } } //Handle GUI events if (!connectionWindow.renameEventHandled) { dmpSettings.SaveSettings(); connectionWindow.renameEventHandled = true; } if (!connectionWindow.addEventHandled) { dmpSettings.servers.Add(connectionWindow.addEntry); connectionWindow.addEntry = null; dmpSettings.SaveSettings(); connectionWindow.addingServer = false; connectionWindow.addEventHandled = true; } if (!connectionWindow.editEventHandled) { dmpSettings.servers[connectionWindow.selected].name = connectionWindow.editEntry.name; dmpSettings.servers[connectionWindow.selected].address = connectionWindow.editEntry.address; dmpSettings.servers[connectionWindow.selected].port = connectionWindow.editEntry.port; connectionWindow.editEntry = null; dmpSettings.SaveSettings(); connectionWindow.addingServer = false; connectionWindow.editEventHandled = true; } if (!connectionWindow.removeEventHandled) { dmpSettings.servers.RemoveAt(connectionWindow.selected); connectionWindow.selected = -1; dmpSettings.SaveSettings(); connectionWindow.removeEventHandled = true; } if (!connectionWindow.connectEventHandled) { connectionWindow.connectEventHandled = true; dmpGame = new DMPGame(dmpSettings, universeSyncCache, modWorker, connectionWindow, dmpModInterface, toolbarSupport, optionsWindow); dmpGame.networkWorker.ConnectToServer(dmpSettings.servers[connectionWindow.selected].address, dmpSettings.servers[connectionWindow.selected].port); } if (commandLineConnect != null && HighLogic.LoadedScene == GameScenes.MAINMENU && Time.timeSinceLevelLoad > 1f) { dmpGame = new DMPGame(dmpSettings, universeSyncCache, modWorker, connectionWindow, dmpModInterface, toolbarSupport, optionsWindow); dmpGame.networkWorker.ConnectToServer(commandLineConnect.address, commandLineConnect.port); commandLineConnect = null; } if (!connectionWindow.disconnectEventHandled) { connectionWindow.disconnectEventHandled = true; if (dmpGame != null) { if (dmpGame.networkWorker.state == ClientState.CONNECTING) { dmpGame.networkWorker.Disconnect("Cancelled connection to server"); } else { dmpGame.networkWorker.SendDisconnect("Quit during initial sync"); } dmpGame.Stop(); dmpGame = null; } } connectionWindow.Update(); modWindow.Update(); optionsWindow.Update(); universeConverterWindow.Update(); dmpModInterface.Update(); if (dmpGame != null) { foreach (Action updateAction in dmpGame.updateEvent) { try { updateAction(); } catch (Exception e) { DarkLog.Debug("Threw in UpdateEvent, exception: " + e); if (dmpGame.networkWorker.state != ClientState.RUNNING) { if (dmpGame.networkWorker.state != ClientState.DISCONNECTED) { dmpGame.networkWorker.SendDisconnect("Unhandled error while syncing!"); } else { dmpGame.networkWorker.Disconnect("Unhandled error while syncing!"); } } } } } //Force quit if (dmpGame != null && dmpGame.forceQuit) { dmpGame.forceQuit = false; dmpGame.Stop(); dmpGame = null; StopGame(); } if (displayDisconnectMessage) { if (HighLogic.LoadedScene != GameScenes.MAINMENU) { if ((Client.realtimeSinceStartup - lastDisconnectMessageCheck) > 1f) { lastDisconnectMessageCheck = Client.realtimeSinceStartup; if (disconnectMessage != null) { disconnectMessage.duration = 0; } disconnectMessage = ScreenMessages.PostScreenMessage("You have been disconnected!", 2f, ScreenMessageStyle.UPPER_CENTER); } } else { displayDisconnectMessage = false; } } //Normal quit if (dmpGame != null && dmpGame.running) { if (!dmpGame.playerStatusWindow.disconnectEventHandled) { dmpGame.playerStatusWindow.disconnectEventHandled = true; dmpGame.forceQuit = true; dmpGame.scenarioWorker.SendScenarioModules(true); // Send scenario modules before disconnecting dmpGame.networkWorker.SendDisconnect("Quit"); } if (dmpGame.screenshotWorker.uploadScreenshot) { dmpGame.screenshotWorker.uploadScreenshot = false; StartCoroutine(UploadScreenshot()); } if (HighLogic.CurrentGame.flagURL != dmpSettings.selectedFlag) { DarkLog.Debug("Saving selected flag"); dmpSettings.selectedFlag = HighLogic.CurrentGame.flagURL; dmpSettings.SaveSettings(); dmpGame.flagSyncer.flagChangeEvent = true; } // save every GeeASL from each body in FlightGlobals if (HighLogic.LoadedScene == GameScenes.FLIGHT && bodiesGees.Count == 0) { foreach (CelestialBody body in FlightGlobals.fetch.bodies) { bodiesGees.Add(body, body.GeeASL); } } //handle use of cheats if (!dmpGame.serverAllowCheats) { CheatOptions.InfinitePropellant = false; CheatOptions.NoCrashDamage = false; CheatOptions.IgnoreAgencyMindsetOnContracts = false; CheatOptions.IgnoreMaxTemperature = false; CheatOptions.InfiniteElectricity = false; CheatOptions.NoCrashDamage = false; CheatOptions.UnbreakableJoints = false; foreach (KeyValuePair <CelestialBody, double> gravityEntry in bodiesGees) { gravityEntry.Key.GeeASL = gravityEntry.Value; } } if (HighLogic.LoadedScene == GameScenes.FLIGHT && FlightGlobals.ready) { HighLogic.CurrentGame.Parameters.Flight.CanLeaveToSpaceCenter = !dmpGame.vesselWorker.isSpectating && dmpSettings.revertEnabled || (PauseMenu.canSaveAndExit == ClearToSaveStatus.CLEAR); } else { HighLogic.CurrentGame.Parameters.Flight.CanLeaveToSpaceCenter = true; } if (HighLogic.LoadedScene == GameScenes.MAINMENU) { dmpGame.networkWorker.SendDisconnect("Quit to main menu"); dmpGame.Stop(); dmpGame = null; } } if (dmpGame != null && dmpGame.startGame) { dmpGame.startGame = false; StartGame(); } } catch (Exception e) { if (dmpGame != null) { DarkLog.Debug("Threw in Update, state " + dmpGame.networkWorker.state.ToString() + ", exception: " + e); if (dmpGame.networkWorker.state != ClientState.RUNNING) { if (dmpGame.networkWorker.state != ClientState.DISCONNECTED) { dmpGame.networkWorker.SendDisconnect("Unhandled error while syncing!"); } else { dmpGame.networkWorker.Disconnect("Unhandled error while syncing!"); } } } else { DarkLog.Debug("Threw in Update, state NO_NETWORKWORKER, exception: " + e); } } Profiler.updateData.ReportTime(startClock); }
public void GenerateModControlFile(bool whitelistMode) { string gameDataDir = Client.dmpClient.gameDataDir; string[] topLevelFiles = Directory.GetFiles(gameDataDir); string[] modDirectories = Directory.GetDirectories(gameDataDir); List <string> requiredFiles = new List <string>(); List <string> optionalFiles = new List <string>(); List <string> partsList = Common.GetStockParts(); //If whitelisting, add top level dll's to required (It's usually things like modulemanager) foreach (string dllFile in topLevelFiles) { if (Path.GetExtension(dllFile).ToLower() == ".dll") { requiredFiles.Add(Path.GetFileName(dllFile)); } } foreach (string modDirectory in modDirectories) { string lowerDirectoryName = modDirectory.Substring(modDirectory.ToLower().IndexOf("gamedata", StringComparison.Ordinal) + 9).ToLower(); if (lowerDirectoryName.StartsWith("squad", StringComparison.Ordinal)) { continue; } if (lowerDirectoryName.StartsWith("nasamission", StringComparison.Ordinal)) { continue; } if (lowerDirectoryName.StartsWith("darkmultiplayer", StringComparison.Ordinal)) { continue; } bool modIsRequired = false; string[] partFiles = Directory.GetFiles(Path.Combine(gameDataDir, modDirectory), "*", SearchOption.AllDirectories); List <string> modDllFiles = new List <string>(); List <string> modPartCfgFiles = new List <string>(); foreach (string partFile in partFiles) { bool fileIsPartFile = false; string relativeFileName = partFile.Substring(partFile.ToLower().IndexOf("gamedata", StringComparison.Ordinal) + 9).Replace(@"\", "/"); if (Path.GetExtension(partFile).ToLower() == ".cfg") { ConfigNode cn = ConfigNode.Load(partFile); if (cn == null) { continue; } foreach (ConfigNode partNode in cn.GetNodes("PART")) { string partName = partNode.GetValue("name"); if (partName != null) { DarkLog.Debug("Part detected in " + relativeFileName + " , name: " + partName); partName = partName.Replace('_', '.'); modIsRequired = true; fileIsPartFile = true; partsList.Add(partName); } } } if (fileIsPartFile) { modPartCfgFiles.Add(relativeFileName); } if (Path.GetExtension(partFile).ToLower() == ".dll") { modDllFiles.Add(relativeFileName); } } if (modIsRequired) { if (modDllFiles.Count > 0) { //If the mod as a plugin, just require that. It's clear enough. requiredFiles.AddRange(modDllFiles); } else { //If the mod does *not* have a plugin (Scoop-o-matic is an example), add the part files to required instead. requiredFiles.AddRange(modPartCfgFiles); } } else { if (whitelistMode) { optionalFiles.AddRange(modDllFiles); } } } string modFileData = Common.GenerateModFileStringData(requiredFiles.ToArray(), optionalFiles.ToArray(), whitelistMode, new string[0], partsList.ToArray()); string saveModFile = Path.Combine(Client.dmpClient.kspRootPath, "mod-control.txt"); using (StreamWriter sw = new StreamWriter(saveModFile, false)) { sw.Write(modFileData); } ScreenMessages.PostScreenMessage("mod-control.txt file generated in your KSP folder\nMove it to DMPServer/Config/", 5f, ScreenMessageStyle.UPPER_CENTER); }
public void ExpireCache() { DarkLog.Debug("Expiring cache!"); //No folder, no delete. if (!Directory.Exists(Path.Combine(cacheDirectory, "Incoming"))) { DarkLog.Debug("No sync cache folder, skipping expire."); return; } //Delete partial incoming files string[] incomingFiles = Directory.GetFiles(Path.Combine(cacheDirectory, "Incoming")); foreach (string incomingFile in incomingFiles) { DarkLog.Debug("Deleting partially cached object " + incomingFile); File.Delete(incomingFile); } //Delete old files string[] cacheObjects = GetCachedObjects(); currentCacheSize = 0; foreach (string cacheObject in cacheObjects) { if (!string.IsNullOrEmpty(cacheObject)) { string cacheFile = Path.Combine(cacheDirectory, cacheObject + ".txt"); //If the file is older than a week, delete it. if (File.GetCreationTime(cacheFile).AddDays(7d) < DateTime.Now) { DarkLog.Debug("Deleting cached object " + cacheObject + ", reason: Expired!"); File.Delete(cacheFile); } else { FileInfo fi = new FileInfo(cacheFile); fileCreationTimes[cacheObject] = fi.CreationTime; fileLengths[cacheObject] = fi.Length; currentCacheSize += fi.Length; } } } //While the directory is over (cacheSize) MB while (currentCacheSize > (dmpSettings.cacheSize * 1024 * 1024)) { string deleteObject = null; //Find oldest file foreach (KeyValuePair <string, DateTime> testFile in fileCreationTimes) { if (deleteObject == null) { deleteObject = testFile.Key; } if (testFile.Value < fileCreationTimes[deleteObject]) { deleteObject = testFile.Key; } } if (deleteObject == null) { return; } DarkLog.Debug("Deleting cached object " + deleteObject + ", reason: Cache full!"); string deleteFile = Path.Combine(cacheDirectory, deleteObject + ".txt"); File.Delete(deleteFile); currentCacheSize -= fileLengths[deleteObject]; if (fileCreationTimes.ContainsKey(deleteObject)) { fileCreationTimes.Remove(deleteObject); } if (fileLengths.ContainsKey(deleteObject)) { fileLengths.Remove(deleteObject); } } }
private void DeleteAllTheControlLocksSoTheSpaceCentreBugGoesAway() { DarkLog.Debug("Clearing " + InputLockManager.lockStack.Count + " control locks"); InputLockManager.ClearControlLocks(); }
public void LoadSettings() { try { if (File.Exists(backupOldSettingsFile) || File.Exists(oldSettingsFile)) { DarkLog.Debug("[Settings]: Loading old settings"); LoadOldSettings(); SaveSettings(); File.Delete(backupOldSettingsFile); File.Delete(oldSettingsFile); } bool saveAfterLoad = false; ConfigNode mainNode = new ConfigNode(); if (File.Exists(backupSettingsFile) && !File.Exists(settingsFile)) { DarkLog.Debug("[Settings]: Restoring backup file"); File.Copy(backupSettingsFile, settingsFile); } if (!File.Exists(settingsFile)) { mainNode = GetDefaultSettings(); playerName = DEFAULT_PLAYER_NAME; mainNode.Save(settingsFile); } if (!File.Exists(backupSettingsFile)) { DarkLog.Debug("[Settings]: Backing up settings"); File.Copy(settingsFile, backupSettingsFile); } mainNode = ConfigNode.Load(settingsFile); ConfigNode settingsNode = mainNode.GetNode("SETTINGS"); ConfigNode playerNode = settingsNode.GetNode("PLAYER"); ConfigNode bindingsNode = settingsNode.GetNode("KEYBINDINGS"); playerName = playerNode.GetValue("name"); if (!int.TryParse(settingsNode.GetValue("cacheSize"), out cacheSize)) { DarkLog.Debug("[Settings]: Adding cache size to settings file"); cacheSize = DEFAULT_CACHE_SIZE; saveAfterLoad = true; } if (!int.TryParse(settingsNode.GetValue("disclaimer"), out disclaimerAccepted)) { DarkLog.Debug("[Settings]: Adding disclaimer to settings file"); disclaimerAccepted = 0; saveAfterLoad = true; } if (!int.TryParse(settingsNode.GetValue("serverlist-mode"), out serverlistMode)) { DarkLog.Debug("[Settings]: Adding serverlist-mode to settings file"); serverlistMode = 0; saveAfterLoad = true; } if (!playerNode.TryGetValue("color", ref playerColor)) { DarkLog.Debug("[Settings]: Adding color to settings file"); playerColor = PlayerColorWorker.GenerateRandomColor(); saveAfterLoad = true; } int chatKey = (int)KeyCode.BackQuote, screenshotKey = (int)KeyCode.F8; if (!int.TryParse(bindingsNode.GetValue("chat"), out chatKey)) { DarkLog.Debug("[Settings]: Adding chat key to settings file"); this.chatKey = KeyCode.BackQuote; saveAfterLoad = true; } else { this.chatKey = (KeyCode)chatKey; } if (!int.TryParse(bindingsNode.GetValue("screenshot"), out screenshotKey)) { DarkLog.Debug("[Settings]: Adding screenshot key to settings file"); this.screenshotKey = KeyCode.F8; saveAfterLoad = true; } else { this.screenshotKey = (KeyCode)screenshotKey; } if (!playerNode.TryGetValue("flag", ref selectedFlag)) { DarkLog.Debug("[Settings]: Adding selected flag to settings file"); selectedFlag = "Squad/Flags/default"; saveAfterLoad = true; } if (!settingsNode.TryGetValue("compression", ref compressionEnabled)) { DarkLog.Debug("[Settings]: Adding compression flag to settings file"); compressionEnabled = true; saveAfterLoad = true; } if (!settingsNode.TryGetValue("revert", ref revertEnabled)) { DarkLog.Debug("[Settings]: Adding revert flag to settings file"); revertEnabled = true; saveAfterLoad = true; } string interpolatorString = null; int interpolatorInt = 0; try { //Make sure we haven't saved to the old int type if (settingsNode.TryGetValue("interpolation", ref interpolatorString) && !int.TryParse(interpolatorString, out interpolatorInt)) { interpolatorType = (InterpolatorType)Enum.Parse(typeof(InterpolatorType), interpolatorString); } else { DarkLog.Debug("[Settings]: Adding interpolation flag to settings file"); interpolatorType = InterpolatorType.INTERPOLATE1S; saveAfterLoad = true; } } catch { interpolatorType = InterpolatorType.INTERPOLATE1S; saveAfterLoad = true; } int toolbarType; if (!int.TryParse(settingsNode.GetValue("toolbar"), out toolbarType)) { DarkLog.Debug("[Settings]: Adding toolbar flag to settings file"); this.toolbarType = DMPToolbarType.BLIZZY_IF_INSTALLED; saveAfterLoad = true; } else { this.toolbarType = (DMPToolbarType)toolbarType; } ConfigNode serversNode = settingsNode.GetNode("SERVERS"); servers.Clear(); if (serversNode.HasNode("SERVER")) { foreach (ConfigNode serverNode in serversNode.GetNodes("SERVER")) { ServerEntry newServer = new ServerEntry(); newServer.name = serverNode.GetValue("name"); newServer.address = serverNode.GetValue("address"); serverNode.TryGetValue("port", ref newServer.port); servers.Add(newServer); } } if (saveAfterLoad) { SaveSettings(); } } catch (Exception e) { DarkLog.Debug("Error while loading settings:"); DarkLog.Debug(e.ToString()); } //Read player token try { //Restore backup if needed if (File.Exists(backupPublicKeyFile) && File.Exists(backupPrivateKeyFile) && (!File.Exists(publicKeyFile) || !File.Exists(privateKeyFile))) { DarkLog.Debug("[Settings]: Restoring backed up keypair!"); File.Copy(backupPublicKeyFile, publicKeyFile, true); File.Copy(backupPrivateKeyFile, privateKeyFile, true); } //Load or create token file if (File.Exists(privateKeyFile) && File.Exists(publicKeyFile)) { playerPublicKey = File.ReadAllText(publicKeyFile); playerPrivateKey = File.ReadAllText(privateKeyFile); } else { DarkLog.Debug("[Settings]: Creating new keypair!"); GenerateNewKeypair(); } //Save backup token file if needed if (!File.Exists(backupPublicKeyFile) || !File.Exists(backupPrivateKeyFile)) { DarkLog.Debug("[Settings]: Backing up keypair"); File.Copy(publicKeyFile, backupPublicKeyFile, true); File.Copy(privateKeyFile, backupPrivateKeyFile, true); } } catch { DarkLog.Debug("Error processing keypair, creating new keypair"); GenerateNewKeypair(); DarkLog.Debug("[Settings]: Backing up keypair"); File.Copy(publicKeyFile, backupPublicKeyFile, true); File.Copy(privateKeyFile, backupPrivateKeyFile, true); } }
private void HandleWarpMessage(byte[] messageData) { using (MessageReader mr = new MessageReader(messageData)) { WarpMessageType messageType = (WarpMessageType)mr.Read <int>(); switch (messageType) { case WarpMessageType.REQUEST_VOTE: { voteMaster = mr.Read <string>(); long expireTime = mr.Read <long>(); voteExpireTime = Client.realtimeSinceStartup + ((expireTime - timeSyncer.GetServerClock()) / 10000000d); } break; case WarpMessageType.REPLY_VOTE: { int incomingVoteYesCount = mr.Read <int>(); int incomingVoteNoCount = mr.Read <int>(); HandleReplyVote(incomingVoteYesCount, incomingVoteNoCount); } break; case WarpMessageType.SET_CONTROLLER: { string newController = mr.Read <string>(); long expireTime = mr.Read <long>(); HandleSetController(newController, expireTime); } break; case WarpMessageType.CHANGE_WARP: { string fromPlayer = mr.Read <string>(); bool isPhysWarp = mr.Read <bool>(); int rateIndex = mr.Read <int>(); long serverClock = mr.Read <long>(); double planetTime = mr.Read <double>(); HandleChangeWarp(fromPlayer, isPhysWarp, rateIndex, serverClock, planetTime); } break; case WarpMessageType.NEW_SUBSPACE: { int newSubspaceID = mr.Read <int>(); long serverTime = mr.Read <long>(); double planetariumTime = mr.Read <double>(); float gameSpeed = mr.Read <float>(); timeSyncer.AddNewSubspace(newSubspaceID, serverTime, planetariumTime, gameSpeed); } break; case WarpMessageType.CHANGE_SUBSPACE: { string fromPlayer = mr.Read <string>(); if (fromPlayer != dmpSettings.playerName) { int changeSubspaceID = mr.Read <int>(); clientSubspaceList[fromPlayer] = changeSubspaceID; if (changeSubspaceID != -1) { if (clientWarpList.ContainsKey(fromPlayer)) { clientWarpList.Remove(fromPlayer); } } } } break; case WarpMessageType.RELOCK_SUBSPACE: { int subspaceID = mr.Read <int>(); long serverTime = mr.Read <long>(); double planetariumTime = mr.Read <double>(); float gameSpeed = mr.Read <float>(); timeSyncer.RelockSubspace(subspaceID, serverTime, planetariumTime, gameSpeed); } break; case WarpMessageType.REPORT_RATE: { string fromPlayer = mr.Read <string>(); clientSkewList[fromPlayer] = mr.Read <float>(); } break; default: { DarkLog.Debug("Unhandled WARP_MESSAGE type: " + messageType); break; } } } }
private void Update() { //Switch to new subspace if told to - this needs to be before the workerEnabled check as it fires during the initial sync if (newSetSubspace != -1) { DarkLog.Debug("Sent to subspace: " + newSetSubspace); timeSyncer.LockSubspace(newSetSubspace); newSetSubspace = -1; } if (!workerEnabled) { return; } //Reset warp if we need to CheckWarp(); //Process new warp messages ProcessWarpMessages(); //Write the screen message if needed if ((Client.realtimeSinceStartup - lastScreenMessageCheck) > SCREEN_MESSAGE_UPDATE_INTERVAL) { lastScreenMessageCheck = Client.realtimeSinceStartup; UpdateScreenMessage(); } //Send a CHANGE_WARP message if needed if ((warpMode == WarpMode.MCW_FORCE) || (warpMode == WarpMode.MCW_VOTE) || (warpMode == WarpMode.SUBSPACE) || warpMode == WarpMode.SUBSPACE_SIMPLE) { if (!clientWarpList.ContainsKey(dmpSettings.playerName)) { clientWarpList[dmpSettings.playerName] = new PlayerWarpRate(); } PlayerWarpRate ourRate = clientWarpList[dmpSettings.playerName]; if ((ourRate.rateIndex != TimeWarp.CurrentRateIndex) || (ourRate.isPhysWarp != (TimeWarp.WarpMode == TimeWarp.Modes.LOW))) { ourRate.isPhysWarp = (TimeWarp.WarpMode == TimeWarp.Modes.LOW); ourRate.rateIndex = TimeWarp.CurrentRateIndex; ourRate.serverClock = timeSyncer.GetServerClock(); ourRate.planetTime = Planetarium.GetUniversalTime(); using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.CHANGE_WARP); mw.Write <bool>(ourRate.isPhysWarp); mw.Write <int>(ourRate.rateIndex); mw.Write <long>(ourRate.serverClock); mw.Write <double>(ourRate.planetTime); networkWorker.SendWarpMessage(mw.GetMessageBytes()); } } } if ((Client.realtimeSinceStartup - lastWarpSet) > WARP_SET_THROTTLE) { //Follow the warp master into warp if needed (MCW_FORCE/MCW_VOTE) if (warpMode == WarpMode.MCW_FORCE || warpMode == WarpMode.MCW_VOTE) { if ((warpMaster != "") && (warpMaster != dmpSettings.playerName)) { if (clientWarpList.ContainsKey(warpMaster)) { //Get master warp rate PlayerWarpRate masterWarpRate = clientWarpList[warpMaster]; SetTimeFromWarpEntry(masterWarpRate); lastWarpSet = Client.realtimeSinceStartup; } else { TimeWarp.SetRate(0, true); } } } if (warpMode == WarpMode.MCW_LOWEST) { if ((warpMaster != "") && clientWarpList.ContainsKey(warpMaster)) { //Get master warp rate PlayerWarpRate masterWarpRate = clientWarpList[warpMaster]; SetTimeFromWarpEntry(masterWarpRate); lastWarpSet = Client.realtimeSinceStartup; } } } //Report our timeSyncer skew if ((Client.realtimeSinceStartup - lastReportRate) > REPORT_SKEW_RATE_INTERVAL && timeSyncer.locked) { lastReportRate = Client.realtimeSinceStartup; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.REPORT_RATE); mw.Write <float>(timeSyncer.requestedRate); networkWorker.SendWarpMessage(mw.GetMessageBytes()); } } //Handle warp keys HandleInput(); }
public void Start() { //Set buffered UDPMesh UDPMeshLib.UdpMeshCommon.USE_BUFFERS = true; //Set pool sizes for ByteRecycler ByteRecycler.AddPoolSize(SMALL_MESSAGE_SIZE); ByteRecycler.AddPoolSize(MEDIUM_MESSAGE_SIZE); ByteRecycler.AddPoolSize(LARGE_MESSAGE_SIZE); MessageWriter.RegisterType <ByteArray>(WriteByteArrayToStream); MessageReader.RegisterType <ByteArray>(ReadByteArrayFromStream); //Prevent loads if multiple copies of DMP are installed. KSP will instantate us twice. if (dmpClient != null) { warnDuplicateInstall = true; return; } if (!CompatibilityChecker.IsCompatible() || !InstallChecker.IsCorrectlyInstalled()) { modDisabled = true; enabled = false; return; } TimingManager.FixedUpdateAdd(TimingManager.TimingStage.BetterLateThanNever, TimingManagerFixedUpdate); dmpDir = Path.Combine(Path.Combine(Path.Combine(KSPUtil.ApplicationRootPath, "GameData"), "DarkMultiPlayer"), "Plugins"); dmpDataDir = Path.Combine(dmpDir, "Data"); gameDataDir = Path.Combine(KSPUtil.ApplicationRootPath, "GameData"); kspRootPath = KSPUtil.ApplicationRootPath; //Fix DarkLog time/thread marker in the log during init. DarkLog.SetMainThread(); lastClockTicks = DateTime.UtcNow.Ticks; lastRealTimeSinceStartup = 0f; dmpClient = this; profiler = new Profiler(); kspTime = profiler.GetCurrentTime; kspMemory = profiler.GetCurrentMemory; dmpSettings = new Settings(); toolbarSupport = new ToolbarSupport(dmpSettings); universeSyncCache = new UniverseSyncCache(dmpSettings); modWindow = new ModWindow(); modWorker = new ModWorker(modWindow); modWindow.SetDependenices(modWorker); universeConverter = new UniverseConverter(dmpSettings); universeConverterWindow = new UniverseConverterWindow(universeConverter); serverListDisclaimerWindow = new ServerListDisclaimerWindow(dmpSettings); optionsWindow = new OptionsWindow(dmpSettings, universeSyncCache, modWorker, universeConverterWindow, toolbarSupport, serverListDisclaimerWindow); serverListConnection = new ServerListConnection(dmpSettings); serversWindow = new ServersWindow(dmpSettings, optionsWindow, serverListConnection); serverListConnection.SetDependancy(serversWindow); connectionWindow = new ConnectionWindow(dmpSettings, optionsWindow, serversWindow, serverListDisclaimerWindow); disclaimerWindow = new DisclaimerWindow(dmpSettings); dmpModInterface = new DMPModInterface(); //SafetyBubble.RegisterDefaultLocations(); if (dmpSettings.disclaimerAccepted != 1) { modDisabled = true; disclaimerWindow.SpawnDialog(); } Application.wantsToQuit += WantsToQuit; DontDestroyOnLoad(this); // Prevents symlink warning for development. SetupDirectoriesIfNeeded(); // UniverseSyncCache needs to run expiry here universeSyncCache.ExpireCache(); GameEvents.onHideUI.Add(() => { showGUI = false; }); GameEvents.onShowUI.Add(() => { showGUI = true; }); HandleCommandLineArgs(); DarkLog.Debug("DarkMultiPlayer " + Common.PROGRAM_VERSION + ", protocol " + Common.PROTOCOL_VERSION + " Initialized!"); }
private void FixedUpdate() { if (workerEnabled) { if (scenarioController == null) { foreach (ProtoScenarioModule psm in HighLogic.CurrentGame.scenarios) { if (psm != null) { if (psm.moduleName == "ScenarioDiscoverableObjects") { if (psm.moduleRef != null) { DarkLog.Debug("Found reference to asteroid spawner"); scenarioController = (ScenarioDiscoverableObjects)psm.moduleRef; scenarioController.spawnInterval = float.MaxValue; } } } } } } if (workerEnabled && scenarioController != null) { if ((UnityEngine.Time.realtimeSinceStartup - lastAsteroidCheck) > ASTEROID_CHECK_INTERVAL) { List <Vessel> asteroidList = GetAsteroidList(); lastAsteroidCheck = UnityEngine.Time.realtimeSinceStartup; //Try to acquire the asteroid-spawning lock if nobody else has it. if (!LockSystem.fetch.LockExists("asteroid-spawning")) { LockSystem.fetch.AcquireLock("asteroid-spawning", false); } //We have the spawn lock, lets do stuff. if (LockSystem.fetch.LockIsOurs("asteroid-spawning")) { if (FlightGlobals.fetch.vessels != null ? FlightGlobals.fetch.vessels.Count > 0 : false) { lock (serverAsteroidListLock) { if (asteroidList.Count < maxNumberOfUntrackedAsteroids) { DarkLog.Debug("Spawning asteroid, have " + asteroidList.Count + ", need " + maxNumberOfUntrackedAsteroids); scenarioController.SpawnAsteroid(); } foreach (Vessel asteroid in asteroidList) { if (!serverAsteroids.Contains(asteroid.id.ToString())) { DarkLog.Debug("Spawned in new server asteroid!"); serverAsteroids.Add(asteroid.id.ToString()); VesselWorker.fetch.RegisterServerVessel(asteroid.id.ToString()); NetworkWorker.fetch.SendVesselProtoMessage(asteroid.protoVessel, false); } } } } } //Check for changes to tracking foreach (Vessel asteroid in asteroidList) { if (!serverAsteroidTrackStatus.ContainsKey(asteroid.id.ToString())) { serverAsteroidTrackStatus.Add(asteroid.id.ToString(), asteroid.DiscoveryInfo.trackingStatus.Value); } else { if (asteroid.DiscoveryInfo.trackingStatus.Value != serverAsteroidTrackStatus[asteroid.id.ToString()]) { DarkLog.Debug("Sending changed asteroid, new state: " + asteroid.DiscoveryInfo.trackingStatus.Value + "!"); serverAsteroidTrackStatus[asteroid.id.ToString()] = asteroid.DiscoveryInfo.trackingStatus.Value; NetworkWorker.fetch.SendVesselProtoMessage(asteroid.protoVessel, false); } } } } } }
public void OnGUI() { profiler.Report("KSP", kspTime, kspMemory); long profilerStartTime = profiler.GetCurrentTime; long profilerStartMemory = profiler.GetCurrentMemory; //Window ID's - Doesn't include "random" offset. //Connection window: 6702 //Status window: 6703 //Chat window: 6704 //Debug window: 6705 //Mod windw: 6706 //Craft library window: 6707 //Craft upload window: 6708 //Screenshot window: 6710 //Options window: 6711 //Converter window: 6712 //Disclaimer window: 6713 if (showGUI) { if (connectionWindow != null) { connectionWindow.Draw(); } if (modWindow != null) { modWindow.Draw(); } if (optionsWindow != null) { optionsWindow.Draw(); } if (serversWindow != null) { serversWindow.Draw(); } if (universeConverterWindow != null) { universeConverterWindow.Draw(); } if (dmpGame != null) { foreach (NamedAction drawAction in dmpGame.drawEvent) { #if !DEBUG try { #endif // Don't hide the connectionWindow if we disabled DMP GUI if (toolbarShowGUI || (!toolbarShowGUI && drawAction.name == "DarkMultiPlayer.ConnectionWindow.Draw")) { drawAction.action(); } #if !DEBUG } catch (Exception e) { DarkLog.Debug("Threw in OnGUI event, exception: " + e); } #endif } } } profiler.Report("Draw", profilerStartTime, profilerStartMemory); kspTime = profiler.GetCurrentTime; kspMemory = profiler.GetCurrentMemory; }
public void Update() { profiler.Report("KSP", kspTime, kspMemory); DarkLog.Update(); ByteRecycler.GarbageCollect(50, 100); Recycler <VesselUpdate> .GarbageCollect(50, 100); long profilerStartTime = profiler.GetCurrentTime; long profilerStartMemory = profiler.GetCurrentMemory; lastClockTicks = DateTime.UtcNow.Ticks; lastRealTimeSinceStartup = Time.realtimeSinceStartup; if (warnDuplicateInstall && HighLogic.LoadedScene == GameScenes.MAINMENU) { warnDuplicateInstall = false; string message = "Please remove the duplicate install of DarkMultiPlayer."; PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "InstallChecker", "Incorrect Install Detected", message, "OK", true, HighLogic.UISkin); } if (modDisabled) { return; } try { if (HighLogic.LoadedScene == GameScenes.MAINMENU) { if (!dmpSaveChecked) { dmpSaveChecked = true; SetupBlankGameIfNeeded(); } } if (HighLogic.LoadedScene == GameScenes.SPACECENTER && PSystemSetup.Instance != null && Time.timeSinceLevelLoad > 1f) { if (PSystemSetup.Instance.SpaceCenterFacilities.Length != facilitiesAdded) { facilitiesAdded = PSystemSetup.Instance.SpaceCenterFacilities.Length; foreach (PSystemSetup.SpaceCenterFacility spaceCenterFacility in PSystemSetup.Instance.SpaceCenterFacilities) { foreach (PSystemSetup.SpaceCenterFacility.SpawnPoint spawnPoint in spaceCenterFacility.spawnPoints) { if (spawnPoint.latitude != 0 && spawnPoint.longitude != 0 && spawnPoint.altitude != 0) { DarkLog.Debug("Adding facility spawn point: " + spaceCenterFacility.name + ":" + spawnPoint.name); SafetyBubble.RegisterLocation(spawnPoint.latitude, spawnPoint.longitude, spawnPoint.altitude, spaceCenterFacility.hostBody.name); DarkLog.Debug("LLA: [" + spawnPoint.latitude + ", " + spawnPoint.longitude + ", " + spawnPoint.altitude + "]"); } } } } if (PSystemSetup.Instance.LaunchSites.Count != modSitesAdded) { modSitesAdded = PSystemSetup.Instance.LaunchSites.Count; foreach (LaunchSite launchSite in PSystemSetup.Instance.LaunchSites) { foreach (LaunchSite.SpawnPoint spawnPoint in launchSite.spawnPoints) { if (spawnPoint.latitude != 0 && spawnPoint.longitude != 0 && spawnPoint.altitude != 0) { DarkLog.Debug("Adding mod spawn point: " + launchSite.name + ":" + spawnPoint.name); SafetyBubble.RegisterLocation(spawnPoint.latitude, spawnPoint.longitude, spawnPoint.altitude, launchSite.Body.name); DarkLog.Debug("LLA: [" + spawnPoint.latitude + ", " + spawnPoint.longitude + ", " + spawnPoint.altitude + "]"); } } } } if (PSystemSetup.Instance.StockLaunchSites.Length != stockSitesAdded) { stockSitesAdded = PSystemSetup.Instance.StockLaunchSites.Length; foreach (LaunchSite launchSite in PSystemSetup.Instance.StockLaunchSites) { foreach (LaunchSite.SpawnPoint spawnPoint in launchSite.spawnPoints) { if (spawnPoint.latitude != 0 && spawnPoint.longitude != 0 && spawnPoint.altitude != 0) { DarkLog.Debug("Adding stock spawn point: " + launchSite.name + ":" + spawnPoint.name); SafetyBubble.RegisterLocation(spawnPoint.latitude, spawnPoint.longitude, spawnPoint.altitude, launchSite.Body.name); DarkLog.Debug("LLA: [" + spawnPoint.latitude + ", " + spawnPoint.longitude + ", " + spawnPoint.altitude + "]"); } } } } } //Handle GUI events if (!connectionWindow.renameEventHandled) { dmpSettings.SaveSettings(); connectionWindow.renameEventHandled = true; } if (!connectionWindow.addEventHandled) { dmpSettings.servers.Add(connectionWindow.addEntry); connectionWindow.addEntry = null; dmpSettings.SaveSettings(); connectionWindow.addingServer = false; connectionWindow.addEventHandled = true; } if (!connectionWindow.editEventHandled) { dmpSettings.servers[connectionWindow.selected].name = connectionWindow.editEntry.name; dmpSettings.servers[connectionWindow.selected].address = connectionWindow.editEntry.address; dmpSettings.servers[connectionWindow.selected].port = connectionWindow.editEntry.port; connectionWindow.editEntry = null; dmpSettings.SaveSettings(); connectionWindow.addingServer = false; connectionWindow.editEventHandled = true; } if (!connectionWindow.removeEventHandled) { dmpSettings.servers.RemoveAt(connectionWindow.selected); connectionWindow.selected = -1; dmpSettings.SaveSettings(); connectionWindow.removeEventHandled = true; } if (!connectionWindow.connectEventHandled) { connectionWindow.connectEventHandled = true; ConnectToServer(dmpSettings.servers[connectionWindow.selected].address, dmpSettings.servers[connectionWindow.selected].port); } if (commandLineConnect != null && HighLogic.LoadedScene == GameScenes.MAINMENU && Time.timeSinceLevelLoad > 1f) { ConnectToServer(commandLineConnect.address, commandLineConnect.port); commandLineConnect = null; } if (!connectionWindow.disconnectEventHandled) { connectionWindow.disconnectEventHandled = true; if (dmpGame != null) { if (dmpGame.networkWorker.state == ClientState.CONNECTING) { dmpGame.networkWorker.Disconnect("Cancelled connection to server"); } else { dmpGame.networkWorker.SendDisconnect("Quit during initial sync"); } dmpGame.Stop(); dmpGame = null; } } connectionWindow.Update(); serverListConnection.Update(); serversWindow.Update(); modWindow.Update(); optionsWindow.Update(); universeConverterWindow.Update(); profiler.Update(); dmpModInterface.Update(); if (dmpGame != null) { foreach (NamedAction updateAction in dmpGame.updateEvent) { #if !DEBUG try { #endif long profilerUpdateStartTime = profiler.GetCurrentTime; long profilerUpdateStartMemory = profiler.GetCurrentMemory; updateAction.action(); profiler.Report(updateAction.name, profilerUpdateStartTime, profilerUpdateStartMemory); #if !DEBUG } catch (Exception e) { DarkLog.Debug("Threw in UpdateEvent, exception: " + e); if (dmpGame.networkWorker.state != ClientState.RUNNING) { if (dmpGame.networkWorker.state != ClientState.DISCONNECTED) { dmpGame.networkWorker.SendDisconnect("Unhandled error while syncing!"); } else { dmpGame.networkWorker.Disconnect("Unhandled error while syncing!"); } } } #endif } } //Force quit if (dmpGame != null && dmpGame.forceQuit) { dmpGame.forceQuit = false; dmpGame.Stop(); dmpGame = null; StopGame(); } if (displayDisconnectMessage) { if (HighLogic.LoadedScene != GameScenes.MAINMENU) { if ((Client.realtimeSinceStartup - lastDisconnectMessageCheck) > 1f) { lastDisconnectMessageCheck = Client.realtimeSinceStartup; if (disconnectMessage != null) { disconnectMessage.duration = 0; } disconnectMessage = ScreenMessages.PostScreenMessage("You have been disconnected!", 2f, ScreenMessageStyle.UPPER_CENTER); } } else { displayDisconnectMessage = false; } } //Normal quit if (dmpGame != null && dmpGame.running) { if (!dmpGame.playerStatusWindow.disconnectEventHandled) { dmpGame.playerStatusWindow.disconnectEventHandled = true; dmpGame.forceQuit = true; dmpGame.scenarioWorker.SendScenarioModules(true); // Send scenario modules before disconnecting dmpGame.networkWorker.SendDisconnect("Quit"); } if (dmpGame.screenshotWorker.uploadScreenshot) { dmpGame.screenshotWorker.uploadScreenshot = false; StartCoroutine(UploadScreenshot()); } if (HighLogic.CurrentGame.flagURL != dmpSettings.selectedFlag) { DarkLog.Debug("Saving selected flag"); dmpSettings.selectedFlag = HighLogic.CurrentGame.flagURL; dmpSettings.SaveSettings(); dmpGame.flagSyncer.flagChangeEvent = true; } // save every GeeASL from each body in FlightGlobals if (HighLogic.LoadedScene == GameScenes.FLIGHT && bodiesGees.Count == 0) { foreach (CelestialBody body in FlightGlobals.fetch.bodies) { bodiesGees.Add(body, body.GeeASL); } } //handle use of cheats if (!dmpGame.serverAllowCheats) { CheatOptions.InfinitePropellant = false; CheatOptions.NoCrashDamage = false; CheatOptions.IgnoreAgencyMindsetOnContracts = false; CheatOptions.IgnoreMaxTemperature = false; CheatOptions.InfiniteElectricity = false; CheatOptions.NoCrashDamage = false; CheatOptions.UnbreakableJoints = false; foreach (KeyValuePair <CelestialBody, double> gravityEntry in bodiesGees) { gravityEntry.Key.GeeASL = gravityEntry.Value; } } if (HighLogic.LoadedScene == GameScenes.FLIGHT && FlightGlobals.ready) { HighLogic.CurrentGame.Parameters.Flight.CanLeaveToSpaceCenter = !dmpGame.vesselWorker.isSpectating && dmpSettings.revertEnabled || (PauseMenu.canSaveAndExit == ClearToSaveStatus.CLEAR); } else { HighLogic.CurrentGame.Parameters.Flight.CanLeaveToSpaceCenter = true; } if (HighLogic.LoadedScene == GameScenes.MAINMENU) { dmpGame.networkWorker.SendDisconnect("Quit to main menu"); dmpGame.Stop(); dmpGame = null; } } if (dmpGame != null && dmpGame.startGame) { dmpGame.startGame = false; StartGame(); } } catch (Exception e) { if (dmpGame != null) { DarkLog.Debug("Threw in Update, state " + dmpGame.networkWorker.state.ToString() + ", exception: " + e); if (dmpGame.networkWorker.state != ClientState.RUNNING) { if (dmpGame.networkWorker.state != ClientState.DISCONNECTED) { dmpGame.networkWorker.SendDisconnect("Unhandled error while syncing!"); } else { dmpGame.networkWorker.Disconnect("Unhandled error while syncing!"); } } } else { DarkLog.Debug("Threw in Update, state NO_NETWORKWORKER, exception: " + e); } } DarkLog.Update(); profiler.Report("Update", profilerStartTime, profilerStartMemory); kspTime = profiler.GetCurrentTime; kspMemory = profiler.GetCurrentMemory; }
public void HandleChatInput(string input) { if (!input.StartsWith("/") || input.StartsWith("//")) { //Handle chat messages if (input.StartsWith("//")) { input = input.Substring(1); } if (selectedChannel == null && selectedPMChannel == null) { //Sending a global chat message using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.CHANNEL_MESSAGE); mw.Write <string>(dmpSettings.playerName); //Global channel name is empty string. mw.Write <string>(""); mw.Write <string>(input); networkWorker.SendChatMessage(mw.GetMessageBytes()); } } if (selectedChannel != null && selectedChannel != consoleIdentifier) { using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.CHANNEL_MESSAGE); mw.Write <string>(dmpSettings.playerName); mw.Write <string>(selectedChannel); mw.Write <string>(input); networkWorker.SendChatMessage(mw.GetMessageBytes()); } } if (selectedChannel == consoleIdentifier) { using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.CONSOLE_MESSAGE); mw.Write <string>(dmpSettings.playerName); mw.Write <string>(input); networkWorker.SendChatMessage(mw.GetMessageBytes()); DarkLog.Debug("Server Command: " + input); } } if (selectedPMChannel != null) { using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.PRIVATE_MESSAGE); mw.Write <string>(dmpSettings.playerName); mw.Write <string>(selectedPMChannel); mw.Write <string>(input); networkWorker.SendChatMessage(mw.GetMessageBytes()); } } } else { string commandPart = input.Substring(1); string argumentPart = ""; if (commandPart.Contains(" ")) { if (commandPart.Length > commandPart.IndexOf(' ') + 1) { argumentPart = commandPart.Substring(commandPart.IndexOf(' ') + 1); } commandPart = commandPart.Substring(0, commandPart.IndexOf(' ')); } if (commandPart.Length > 0) { if (registeredChatCommands.ContainsKey(commandPart)) { try { DarkLog.Debug("Chat Command: " + input.Substring(1)); registeredChatCommands[commandPart].func(argumentPart); } catch (Exception e) { DarkLog.Debug("Error handling chat command " + commandPart + ", Exception " + e); PrintToSelectedChannel("Error handling chat command: " + commandPart); } } else { PrintToSelectedChannel("Unknown chat command: " + commandPart); } } } }
private void Update() { safeDisplay = display; if (workerEnabled) { while (newScreenshotNotifiyQueue.Count > 0) { string notifyPlayer = newScreenshotNotifiyQueue.Dequeue(); if (!display) { screenshotButtonHighlighted = true; } if (selectedPlayer != notifyPlayer) { if (!highlightedPlayers.Contains(notifyPlayer)) { highlightedPlayers.Add(notifyPlayer); } } ChatWorker.fetch.QueueChannelMessage("Server", "", notifyPlayer + " shared screenshot"); } //Update highlights if (screenshotButtonHighlighted && display) { screenshotButtonHighlighted = false; } if (highlightedPlayers.Contains(selectedPlayer)) { highlightedPlayers.Remove(selectedPlayer); } while (newScreenshotQueue.Count > 0) { ScreenshotEntry se = newScreenshotQueue.Dequeue(); Texture2D screenshotTexture = new Texture2D(4, 4, TextureFormat.RGB24, false, true); if (screenshotTexture.LoadImage(se.screenshotData)) { screenshotTexture.Apply(); //Make sure screenshots aren't bigger than 2/3rds of the screen. ResizeTextureIfNeeded(ref screenshotTexture); //Save the texture in memory screenshots[se.fromPlayer] = screenshotTexture; DarkLog.Debug("Loaded screenshot from " + se.fromPlayer); } else { DarkLog.Debug("Error loading screenshot from " + se.fromPlayer); } } while (newScreenshotWatchQueue.Count > 0) { ScreenshotWatchEntry swe = newScreenshotWatchQueue.Dequeue(); if (swe.watchPlayer != "") { watchPlayers[swe.fromPlayer] = swe.watchPlayer; } else { if (watchPlayers.ContainsKey(swe.fromPlayer)) { watchPlayers.Remove(swe.fromPlayer); } } } if (safeSelectedPlayer != selectedPlayer) { windowRect.height = 0; windowRect.width = 0; safeSelectedPlayer = selectedPlayer; WatchPlayer(selectedPlayer); } if (Input.GetKey(Settings.fetch.screenshotKey)) { uploadEventHandled = false; } if (!uploadEventHandled) { uploadEventHandled = true; if ((UnityEngine.Time.realtimeSinceStartup - lastScreenshotSend) > MIN_SCREENSHOT_SEND_INTERVAL) { lastScreenshotSend = UnityEngine.Time.realtimeSinceStartup; screenshotTaken = false; finishedUploadingScreenshot = false; uploadScreenshot = true; displayScreenshotUploadingMessage = true; } } if ((UnityEngine.Time.realtimeSinceStartup - lastScreenshotMessageCheck) > SCREENSHOT_MESSAGE_CHECK_INTERVAL) { if (screenshotTaken && displayScreenshotUploadingMessage) { lastScreenshotMessageCheck = UnityEngine.Time.realtimeSinceStartup; if (screenshotUploadMessage != null) { screenshotUploadMessage.duration = 0f; } if (finishedUploadingScreenshot) { displayScreenshotUploadingMessage = false; screenshotUploadMessage = ScreenMessages.PostScreenMessage("Screenshot uploaded!", 2f, ScreenMessageStyle.UPPER_CENTER); } else { screenshotUploadMessage = ScreenMessages.PostScreenMessage("Uploading screenshot...", 1f, ScreenMessageStyle.UPPER_CENTER); } } if (downloadingScreenshotFromPlayer != null) { if (screenshotDownloadMessage != null) { screenshotDownloadMessage.duration = 0f; } screenshotDownloadMessage = ScreenMessages.PostScreenMessage("Downloading screenshot...", 1f, ScreenMessageStyle.UPPER_CENTER); } } if (downloadingScreenshotFromPlayer == null && screenshotDownloadMessage != null) { screenshotDownloadMessage.duration = 0f; screenshotDownloadMessage = null; } } }
private void HandleMCWVoteInput(bool startWarpKey, bool stopWarpKey) { if (warpMaster == "") { if (voteMaster == "") { if (startWarpKey) { if (PlayerStatusWorker.fetch.playerStatusList.Count > 0) { //Start a warp vote using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.REQUEST_VOTE); mw.Write <string>(Settings.fetch.playerName); NetworkWorker.fetch.SendWarpMessage(mw.GetMessageBytes()); } voteMaster = Settings.fetch.playerName; //To win: //1 other clients = 1 vote needed. //2 other clients = 1 vote needed. //3 other clients = 2 votes neeed. //4 other clients = 2 votes neeed. //5 other clients = 3 votes neeed. //To fail: //1 other clients = 1 vote needed. //2 other clients = 2 vote needed. //3 other clients = 2 votes neeed. //4 other clients = 3 votes neeed. //5 other clients = 3 votes neeed. voteNeededCount = (PlayerStatusWorker.fetch.playerStatusList.Count + 1) / 2; voteFailedCount = voteNeededCount + (1 - (voteNeededCount % 2)); DarkLog.Debug("Started warp vote"); } else { //Nobody else is online, Let's just take the warp master. warpMasterOwnerTime = UnityEngine.Time.realtimeSinceStartup; warpMaster = Settings.fetch.playerName; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.SET_CONTROLLER); mw.Write <string>(Settings.fetch.playerName); mw.Write <string>(Settings.fetch.playerName); NetworkWorker.fetch.SendWarpMessage(mw.GetMessageBytes()); } } } } else { if (voteMaster != Settings.fetch.playerName) { //Send a vote if we haven't voted yet if (!voteSent) { using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.REPLY_VOTE); mw.Write <string>(Settings.fetch.playerName); mw.Write <bool>(startWarpKey); NetworkWorker.fetch.SendWarpMessage(mw.GetMessageBytes()); voteSent = true; } DarkLog.Debug("Send warp reply with vote of " + startWarpKey); } } else { if (stopWarpKey) { //Cancel our vote ReleaseWarpMaster(); DisplayMessage("Cancelled vote!", 2f); DarkLog.Debug("Cancelled warp vote"); } } } } else { if (warpMaster == Settings.fetch.playerName) { if (stopWarpKey && (TimeWarp.CurrentRate < 1.1f)) { //Release control of the warp master instead of waiting for the timeout ReleaseWarpMaster(); } } } }
public void Update() { long startClock = Profiler.DMPReferenceTime.ElapsedTicks; DarkLog.Update(); if (modDisabled) { return; } try { if (HighLogic.LoadedScene == GameScenes.MAINMENU) { if (!ModWorker.fetch.dllListBuilt) { ModWorker.fetch.dllListBuilt = true; ModWorker.fetch.BuildDllFileList(); } if (!dmpSaveChecked) { dmpSaveChecked = true; SetupBlankGameIfNeeded(); } } //Handle GUI events if (!PlayerStatusWindow.fetch.disconnectEventHandled) { PlayerStatusWindow.fetch.disconnectEventHandled = true; forceQuit = true; NetworkWorker.fetch.SendDisconnect("Quit"); } if (!ConnectionWindow.fetch.renameEventHandled) { PlayerStatusWorker.fetch.myPlayerStatus.playerName = Settings.fetch.playerName; Settings.fetch.SaveSettings(); ConnectionWindow.fetch.renameEventHandled = true; } if (!ConnectionWindow.fetch.addEventHandled) { Settings.fetch.servers.Add(ConnectionWindow.fetch.addEntry); ConnectionWindow.fetch.addEntry = null; Settings.fetch.SaveSettings(); ConnectionWindow.fetch.addingServer = false; ConnectionWindow.fetch.addEventHandled = true; } if (!ConnectionWindow.fetch.editEventHandled) { Settings.fetch.servers[ConnectionWindow.fetch.selected].name = ConnectionWindow.fetch.editEntry.name; Settings.fetch.servers[ConnectionWindow.fetch.selected].address = ConnectionWindow.fetch.editEntry.address; Settings.fetch.servers[ConnectionWindow.fetch.selected].port = ConnectionWindow.fetch.editEntry.port; ConnectionWindow.fetch.editEntry = null; Settings.fetch.SaveSettings(); ConnectionWindow.fetch.addingServer = false; ConnectionWindow.fetch.editEventHandled = true; } if (!ConnectionWindow.fetch.removeEventHandled) { Settings.fetch.servers.RemoveAt(ConnectionWindow.fetch.selected); ConnectionWindow.fetch.selected = -1; Settings.fetch.SaveSettings(); ConnectionWindow.fetch.removeEventHandled = true; } if (!ConnectionWindow.fetch.connectEventHandled) { ConnectionWindow.fetch.connectEventHandled = true; NetworkWorker.fetch.ConnectToServer(Settings.fetch.servers[ConnectionWindow.fetch.selected].address, Settings.fetch.servers[ConnectionWindow.fetch.selected].port); } if (commandLineConnect != null && HighLogic.LoadedScene == GameScenes.MAINMENU && Time.timeSinceLevelLoad > 1f) { NetworkWorker.fetch.ConnectToServer(commandLineConnect.address, commandLineConnect.port); commandLineConnect = null; } if (!ConnectionWindow.fetch.disconnectEventHandled) { ConnectionWindow.fetch.disconnectEventHandled = true; gameRunning = false; fireReset = true; if (NetworkWorker.fetch.state == ClientState.CONNECTING) { NetworkWorker.fetch.Disconnect("Cancelled connection to server"); } else { NetworkWorker.fetch.SendDisconnect("Quit during initial sync"); } } foreach (Action updateAction in updateEvent) { try { updateAction(); } catch (Exception e) { DarkLog.Debug("Threw in UpdateEvent, exception: " + e); if (NetworkWorker.fetch.state != ClientState.RUNNING) { if (NetworkWorker.fetch.state != ClientState.DISCONNECTED) { NetworkWorker.fetch.SendDisconnect("Unhandled error while syncing!"); } else { NetworkWorker.fetch.Disconnect("Unhandled error while syncing!"); } } } } //Force quit if (forceQuit) { forceQuit = false; gameRunning = false; fireReset = true; StopGame(); } if (displayDisconnectMessage) { if (HighLogic.LoadedScene != GameScenes.MAINMENU) { if ((UnityEngine.Time.realtimeSinceStartup - lastDisconnectMessageCheck) > 1f) { lastDisconnectMessageCheck = UnityEngine.Time.realtimeSinceStartup; if (disconnectMessage != null) { disconnectMessage.duration = 0; } disconnectMessage = ScreenMessages.PostScreenMessage("You have been disconnected!", 2f, ScreenMessageStyle.UPPER_CENTER); } } else { displayDisconnectMessage = false; } } //Normal quit if (gameRunning) { if (HighLogic.LoadedScene == GameScenes.MAINMENU) { gameRunning = false; fireReset = true; NetworkWorker.fetch.SendDisconnect("Quit to main menu"); } if (ScreenshotWorker.fetch.uploadScreenshot) { ScreenshotWorker.fetch.uploadScreenshot = false; StartCoroutine(UploadScreenshot()); } if (HighLogic.CurrentGame.flagURL != Settings.fetch.selectedFlag) { DarkLog.Debug("Saving selected flag"); Settings.fetch.selectedFlag = HighLogic.CurrentGame.flagURL; Settings.fetch.SaveSettings(); FlagSyncer.fetch.flagChangeEvent = true; } // save every GeeASL from each body in FlightGlobals if (HighLogic.LoadedScene == GameScenes.FLIGHT && bodiesGees.Count == 0) { foreach (CelestialBody body in FlightGlobals.fetch.bodies) { bodiesGees.Add(body, body.GeeASL); } } //handle use of cheats if (!serverAllowCheats) { CheatOptions.InfiniteFuel = false; CheatOptions.InfiniteEVAFuel = false; CheatOptions.InfiniteRCS = false; CheatOptions.NoCrashDamage = false; foreach (KeyValuePair <CelestialBody, double> gravityEntry in bodiesGees) { gravityEntry.Key.GeeASL = gravityEntry.Value; } } if (HighLogic.LoadedScene == GameScenes.FLIGHT && FlightGlobals.ready) { HighLogic.CurrentGame.Parameters.Flight.CanLeaveToSpaceCenter = Settings.fetch.revertEnabled || (PauseMenu.canSaveAndExit == ClearToSaveStatus.CLEAR); } else { HighLogic.CurrentGame.Parameters.Flight.CanLeaveToSpaceCenter = true; } } if (fireReset) { fireReset = false; FireResetEvent(); } if (startGame) { startGame = false; StartGame(); } } catch (Exception e) { DarkLog.Debug("Threw in Update, state " + NetworkWorker.fetch.state.ToString() + ", exception" + e); if (NetworkWorker.fetch.state != ClientState.RUNNING) { if (NetworkWorker.fetch.state != ClientState.DISCONNECTED) { NetworkWorker.fetch.SendDisconnect("Unhandled error while syncing!"); } else { NetworkWorker.fetch.Disconnect("Unhandled error while syncing!"); } } } Profiler.updateData.ReportTime(startClock); }
private void HandleWarpMessage(byte[] messageData) { using (MessageReader mr = new MessageReader(messageData, false)) { WarpMessageType messageType = (WarpMessageType)mr.Read <int>(); string fromPlayer = mr.Read <string>(); switch (messageType) { case WarpMessageType.REQUEST_VOTE: { if (warpMode == WarpMode.MCW_VOTE) { if (voteMaster == "") { voteMaster = fromPlayer; } else { //Freak out and tell everyone to reset their warp votes - This can happen if 2 clients start a vote at the exact same time. ReleaseWarpMaster(); } } } break; case WarpMessageType.REPLY_VOTE: { if (warpMode == WarpMode.MCW_VOTE) { if (voteMaster == Settings.fetch.playerName && warpMaster == "") { if (!voteList.ContainsKey(fromPlayer)) { bool vote = mr.Read <bool>(); DarkLog.Debug(fromPlayer + " voted " + vote); voteList.Add(fromPlayer, vote); } voteNoCount = 0; voteYesCount = 0; foreach (KeyValuePair <string, bool> vote in voteList) { if (vote.Value) { voteYesCount++; } else { voteNoCount++; } } //We have enough votes if (voteYesCount >= voteNeededCount) { //Vote has passed. warpMasterOwnerTime = UnityEngine.Time.realtimeSinceStartup; warpMaster = Settings.fetch.playerName; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.SET_CONTROLLER); mw.Write <string>(Settings.fetch.playerName); mw.Write <string>(Settings.fetch.playerName); NetworkWorker.fetch.SendWarpMessage(mw.GetMessageBytes()); } } //We have enough votes if (voteNoCount >= voteFailedCount) { //Vote has failed. ReleaseWarpMaster(); DisplayMessage("Vote failed!", 5f); } } } } break; case WarpMessageType.SET_CONTROLLER: { if (warpMode == WarpMode.MCW_FORCE || warpMode == WarpMode.MCW_VOTE || warpMode == WarpMode.MCW_LOWEST) { string newController = mr.Read <string>(); warpMaster = newController; if (warpMode == WarpMode.MCW_FORCE && newController == "") { warpMasterOwnerTime = 0f; } if (warpMode == WarpMode.MCW_VOTE && newController == "") { TimeWarp.SetRate(0, true); CancelVote(); } } } break; case WarpMessageType.CHANGE_WARP: { if (warpMode == WarpMode.MCW_FORCE || warpMode == WarpMode.MCW_VOTE || warpMode == WarpMode.MCW_LOWEST || warpMode == WarpMode.SUBSPACE) { bool newPhysWarp = mr.Read <bool>(); int newRateIndex = mr.Read <int>(); if (clientWarpList.ContainsKey(fromPlayer)) { clientWarpList[fromPlayer].isPhysWarp = newPhysWarp; clientWarpList[fromPlayer].rateIndex = newRateIndex; } else { PlayerWarpRate newPlayerWarpRate = new PlayerWarpRate(); newPlayerWarpRate.isPhysWarp = newPhysWarp; newPlayerWarpRate.rateIndex = newRateIndex; clientWarpList.Add(fromPlayer, newPlayerWarpRate); } //DarkLog.Debug(fromPlayer + " warp rate changed, Physwarp: " + newPhysWarp + ", Index: " + newRateIndex); } } break; case WarpMessageType.NEW_SUBSPACE: { int newSubspaceID = mr.Read <int>(); long serverTime = mr.Read <long>(); double planetariumTime = mr.Read <double>(); float gameSpeed = mr.Read <float>(); TimeSyncer.fetch.LockNewSubspace(newSubspaceID, serverTime, planetariumTime, gameSpeed); if (((warpMode == WarpMode.MCW_VOTE) || (warpMode == WarpMode.MCW_FORCE)) && (warpMaster == fromPlayer)) { TimeSyncer.fetch.LockSubspace(newSubspaceID); } if (!TimeSyncer.fetch.locked && TimeSyncer.fetch.currentSubspace == newSubspaceID) { TimeSyncer.fetch.LockSubspace(newSubspaceID); } } break; case WarpMessageType.CHANGE_SUBSPACE: { int changeSubspaceID = mr.Read <int>(); clientSubspaceList[fromPlayer] = changeSubspaceID; } break; case WarpMessageType.RELOCK_SUBSPACE: { if (fromPlayer == "Server") { int subspaceID = mr.Read <int>(); long serverTime = mr.Read <long>(); double planetariumTime = mr.Read <double>(); float gameSpeed = mr.Read <float>(); TimeSyncer.fetch.RelockSubspace(subspaceID, serverTime, planetariumTime, gameSpeed); } } break; case WarpMessageType.REPORT_RATE: { //Not interested in subspace. mr.Read <int>(); clientSkewList[fromPlayer] = mr.Read <float>(); } break; default: { DarkLog.Debug("Unhandled WARP_MESSAGE type: " + messageType); break; } } } }
public void Awake() { Profiler.DMPReferenceTime.Start(); GameObject.DontDestroyOnLoad(this); assemblyPath = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).FullName; string kspPath = new DirectoryInfo(KSPUtil.ApplicationRootPath).FullName; //I find my abuse of Path.Combine distrubing. UnityEngine.Debug.Log("KSP installed at " + kspPath); UnityEngine.Debug.Log("DMP installed at " + assemblyPath); //Prevents symlink warning for development. if (Settings.fetch.disclaimerAccepted != 1) { modDisabled = true; DisclaimerWindow.Enable(); } if (!CompatibilityChecker.IsCompatible()) { modDisabled = true; } #if !DEBUG if (!InstallChecker.IsCorrectlyInstalled()) { modDisabled = true; } #endif SetupDirectoriesIfNeeded(); //UniverseSyncCache needs to run expiry here UniverseSyncCache.fetch.ExpireCache(); //Register events needed to bootstrap the workers. lock (eventLock) { resetEvent.Add(LockSystem.Reset); resetEvent.Add(AdminSystem.Reset); resetEvent.Add(AsteroidWorker.Reset); resetEvent.Add(ChatWorker.Reset); resetEvent.Add(CraftLibraryWorker.Reset); resetEvent.Add(DebugWindow.Reset); resetEvent.Add(DynamicTickWorker.Reset); resetEvent.Add(FlagSyncer.Reset); resetEvent.Add(HackyInAtmoLoader.Reset); resetEvent.Add(PlayerColorWorker.Reset); resetEvent.Add(PlayerStatusWindow.Reset); resetEvent.Add(PlayerStatusWorker.Reset); resetEvent.Add(PartKiller.Reset); resetEvent.Add(ScenarioWorker.Reset); resetEvent.Add(ScreenshotWorker.Reset); resetEvent.Add(TimeSyncer.Reset); resetEvent.Add(ToolbarSupport.Reset); resetEvent.Add(VesselWorker.Reset); resetEvent.Add(WarpWorker.Reset); GameEvents.onHideUI.Add(() => { showGUI = false; }); GameEvents.onShowUI.Add(() => { showGUI = true; }); } FireResetEvent(); HandleCommandLineArgs(); long testTime = Compression.TestSysIOCompression(); DarkLog.Debug("System.IO compression works: " + Compression.sysIOCompressionWorks + ", test time: " + testTime + " ms."); DarkLog.Debug("DarkMultiPlayer " + Common.PROGRAM_VERSION + ", protocol " + Common.PROTOCOL_VERSION + " Initialized!"); }
public void LoadSettings() { //Read XML settings try { bool saveXMLAfterLoad = false; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(backupSettingsFile) && !File.Exists(settingsFile)) { DarkLog.Debug("Restoring player settings file!"); File.Copy(backupSettingsFile, settingsFile); } if (!File.Exists(settingsFile)) { xmlDoc.LoadXml(newXMLString()); playerName = DEFAULT_PLAYER_NAME; xmlDoc.Save(settingsFile); } if (!File.Exists(backupSettingsFile)) { DarkLog.Debug("Backing up player token and settings file!"); File.Copy(settingsFile, backupSettingsFile); } xmlDoc.Load(settingsFile); playerName = xmlDoc.SelectSingleNode("/settings/global/@username").Value; try { cacheSize = Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@cache-size").Value); } catch { DarkLog.Debug("Adding cache size to settings file"); saveXMLAfterLoad = true; cacheSize = DEFAULT_CACHE_SIZE; } try { disclaimerAccepted = Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@disclaimer").Value); } catch { DarkLog.Debug("Adding disclaimer to settings file"); saveXMLAfterLoad = true; } try { string floatArrayString = xmlDoc.SelectSingleNode("/settings/global/@player-color").Value; string[] floatArrayStringSplit = floatArrayString.Split(','); float redColor = float.Parse(floatArrayStringSplit[0].Trim()); float greenColor = float.Parse(floatArrayStringSplit[1].Trim()); float blueColor = float.Parse(floatArrayStringSplit[2].Trim()); //Bounds checking - Gotta check up on those players :) if (redColor < 0f) { redColor = 0f; } if (redColor > 1f) { redColor = 1f; } if (greenColor < 0f) { greenColor = 0f; } if (greenColor > 1f) { greenColor = 1f; } if (blueColor < 0f) { blueColor = 0f; } if (blueColor > 1f) { blueColor = 1f; } playerColor = new Color(redColor, greenColor, blueColor, 1f); } catch { DarkLog.Debug("Adding player color to settings file"); saveXMLAfterLoad = true; playerColor = PlayerColorWorker.GenerateRandomColor(); } try { chatKey = (KeyCode)Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@chat-key").Value); } catch { DarkLog.Debug("Adding chat key to settings file"); saveXMLAfterLoad = true; chatKey = KeyCode.BackQuote; } try { screenshotKey = (KeyCode)Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@screenshot-key").Value); } catch { DarkLog.Debug("Adding screenshot key to settings file"); saveXMLAfterLoad = true; chatKey = KeyCode.F8; } try { selectedFlag = xmlDoc.SelectSingleNode("/settings/global/@selected-flag").Value; } catch { DarkLog.Debug("Adding selected flag to settings file"); saveXMLAfterLoad = true; selectedFlag = "Squad/Flags/default"; } try { compressionEnabled = Boolean.Parse(xmlDoc.SelectSingleNode("/settings/global/@compression").Value); } catch { DarkLog.Debug("Adding compression flag to settings file"); compressionEnabled = true; } try { revertEnabled = Boolean.Parse(xmlDoc.SelectSingleNode("/settings/global/@revert").Value); } catch { DarkLog.Debug("Adding revert flag to settings file"); revertEnabled = true; } try { toolbarType = (DMPToolbarType)Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@toolbar").Value); } catch { DarkLog.Debug("Adding toolbar flag to settings file"); toolbarType = DMPToolbarType.BLIZZY_IF_INSTALLED; } XmlNodeList serverNodeList = xmlDoc.GetElementsByTagName("server"); servers = new List <ServerEntry>(); foreach (XmlNode xmlNode in serverNodeList) { ServerEntry newServer = new ServerEntry(); newServer.name = xmlNode.Attributes["name"].Value; newServer.address = xmlNode.Attributes["address"].Value; Int32.TryParse(xmlNode.Attributes["port"].Value, out newServer.port); servers.Add(newServer); } if (saveXMLAfterLoad) { SaveSettings(); } } catch (Exception e) { DarkLog.Debug("XML Exception: " + e); } //Read player token try { //Restore backup if needed if (File.Exists(backupPublicKeyFile) && File.Exists(backupPrivateKeyFile) && (!File.Exists(publicKeyFile) || !File.Exists(privateKeyFile))) { DarkLog.Debug("Restoring backed up keypair!"); File.Copy(backupPublicKeyFile, publicKeyFile, true); File.Copy(backupPrivateKeyFile, privateKeyFile, true); } //Load or create token file if (File.Exists(privateKeyFile) && File.Exists(publicKeyFile)) { playerPublicKey = File.ReadAllText(publicKeyFile); playerPrivateKey = File.ReadAllText(privateKeyFile); } else { DarkLog.Debug("Creating new keypair!"); GenerateNewKeypair(); } //Save backup token file if needed if (!File.Exists(backupPublicKeyFile) || !File.Exists(backupPrivateKeyFile)) { DarkLog.Debug("Backing up keypair"); File.Copy(publicKeyFile, backupPublicKeyFile, true); File.Copy(privateKeyFile, backupPrivateKeyFile, true); } } catch { DarkLog.Debug("Error processing keypair, creating new keypair"); GenerateNewKeypair(); DarkLog.Debug("Backing up keypair"); File.Copy(publicKeyFile, backupPublicKeyFile, true); File.Copy(privateKeyFile, backupPrivateKeyFile, true); } }
public void LoadOldSettings() { //Read XML settings try { XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(backupOldSettingsFile) && !File.Exists(oldSettingsFile)) { DarkLog.Debug("[Settings]: Restoring old player settings file!"); File.Move(backupOldSettingsFile, oldSettingsFile); } xmlDoc.Load(oldSettingsFile); playerName = xmlDoc.SelectSingleNode("/settings/global/@username").Value; cacheSize = int.Parse(xmlDoc.SelectSingleNode("/settings/global/@cache-size").Value); disclaimerAccepted = Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@disclaimer").Value); string floatArrayString = xmlDoc.SelectSingleNode("/settings/global/@player-color").Value; string[] floatArrayStringSplit = floatArrayString.Split(','); float redColor = float.Parse(floatArrayStringSplit[0].Trim()); float greenColor = float.Parse(floatArrayStringSplit[1].Trim()); float blueColor = float.Parse(floatArrayStringSplit[2].Trim()); //Bounds checking - Gotta check up on those players :) if (redColor < 0f) { redColor = 0f; } if (redColor > 1f) { redColor = 1f; } if (greenColor < 0f) { greenColor = 0f; } if (greenColor > 1f) { greenColor = 1f; } if (blueColor < 0f) { blueColor = 0f; } if (blueColor > 1f) { blueColor = 1f; } playerColor = new Color(redColor, greenColor, blueColor, 1f); chatKey = (KeyCode)Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@chat-key").Value); screenshotKey = (KeyCode)Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@screenshot-key").Value); selectedFlag = xmlDoc.SelectSingleNode("/settings/global/@selected-flag").Value; compressionEnabled = Boolean.Parse(xmlDoc.SelectSingleNode("/settings/global/@compression").Value); revertEnabled = Boolean.Parse(xmlDoc.SelectSingleNode("/settings/global/@revert").Value); toolbarType = (DMPToolbarType)Int32.Parse(xmlDoc.SelectSingleNode("/settings/global/@toolbar").Value); XmlNodeList serverNodeList = xmlDoc.GetElementsByTagName("server"); servers.Clear(); foreach (XmlNode xmlNode in serverNodeList) { ServerEntry newServer = new ServerEntry(); newServer.name = xmlNode.Attributes["name"].Value; newServer.address = xmlNode.Attributes["address"].Value; Int32.TryParse(xmlNode.Attributes["port"].Value, out newServer.port); servers.Add(newServer); } SaveSettings(); } catch (Exception e) { DarkLog.Debug("Error loading old settings: " + e); } }
private void Update() { if (!workerEnabled) { return; } InitializeScenario(); if (scenario == null) { return; } if (lastAsteroidCheck + ASTEROID_CHECK_INTERVAL > Client.realtimeSinceStartup) { return; } lastAsteroidCheck = Client.realtimeSinceStartup; //Try to acquire the asteroid-spawning lock if nobody else has it. if (!lockSystem.LockExists("asteroid-spawning")) { lockSystem.AcquireLock("asteroid-spawning", false); } //We have the spawn lock, lets do stuff. if (lockSystem.LockIsOurs("asteroid-spawning")) { if (HighLogic.LoadedSceneIsFlight && !FlightGlobals.ready) { return; } if (HighLogic.CurrentGame.flightState.protoVessels == null) { return; } if (FlightGlobals.fetch.vessels == null) { return; } if (HighLogic.CurrentGame.flightState.protoVessels.Count == 0) { return; } if (FlightGlobals.fetch.vessels.Count == 0) { return; } int beforeSpawn = GetAsteroidCount(); if (beforeSpawn < maxNumberOfUntrackedAsteroids) { ProtoVessel asty = SpawnAsteroid(); DarkLog.Debug("Spawned asteroid " + asty.vesselName + ", have " + (beforeSpawn) + ", need " + maxNumberOfUntrackedAsteroids); } } //Check for changes to tracking lock (serverAsteroids) { foreach (Vessel asteroid in GetCurrentAsteroids()) { if (asteroid.state != Vessel.State.DEAD) { if (!serverAsteroidTrackStatus.ContainsKey(asteroid.id)) { serverAsteroidTrackStatus.Add(asteroid.id, asteroid.DiscoveryInfo.trackingStatus.Value); } else { if (asteroid.DiscoveryInfo.trackingStatus.Value != serverAsteroidTrackStatus[asteroid.id]) { ProtoVessel pv = asteroid.BackupVessel(); DarkLog.Debug("Sending changed asteroid, new state: " + asteroid.DiscoveryInfo.trackingStatus.Value + "!"); serverAsteroidTrackStatus[asteroid.id] = asteroid.DiscoveryInfo.trackingStatus.Value; networkWorker.SendVesselProtoMessage(pv, false, false); } } } } } }
public bool ParseModFile(string modFileData) { if (modControl == ModControlMode.DISABLED) { return(true); } bool modCheckOk = true; //Save mod file so we can recheck it. lastModFileData = modFileData; //Err... string tempModFilePath = Path.Combine(Client.dmpClient.dmpDataDir, "mod-control.txt"); using (StreamWriter sw = new StreamWriter(tempModFilePath)) { sw.WriteLine("#This file is downloaded from the server during connection. It is saved here for convenience."); sw.WriteLine(lastModFileData); } //Parse Dictionary <string, string> parseRequired = new Dictionary <string, string>(); Dictionary <string, string> parseOptional = new Dictionary <string, string>(); List <string> parseWhiteBlackList = new List <string>(); List <string> parsePartsList = new List <string>(); bool isWhiteList = false; string readMode = ""; using (StringReader sr = new StringReader(modFileData)) { while (true) { string currentLine = sr.ReadLine(); if (currentLine == null) { //Done reading break; } //Remove tabs/spaces from the start & end. string trimmedLine = currentLine.Trim(); if (trimmedLine.StartsWith("#", StringComparison.Ordinal) || String.IsNullOrEmpty(trimmedLine)) { //Skip comments or empty lines. continue; } if (trimmedLine.StartsWith("!", StringComparison.Ordinal)) { //New section switch (trimmedLine.Substring(1)) { case "required-files": case "optional-files": case "partslist": readMode = trimmedLine.Substring(1); break; case "resource-blacklist": readMode = trimmedLine.Substring(1); isWhiteList = false; break; case "resource-whitelist": readMode = trimmedLine.Substring(1); isWhiteList = true; break; default: break; } } else { switch (readMode) { case "required-files": { string lowerFixedLine = trimmedLine.ToLowerInvariant().Replace('\\', '/'); if (lowerFixedLine.Contains("=")) { string[] splitLine = lowerFixedLine.Split('='); if (splitLine.Length == 2) { if (!parseRequired.ContainsKey(splitLine[0])) { parseRequired.Add(splitLine[0], splitLine[1].ToLowerInvariant()); } } else { if (splitLine.Length == 1) { if (!parseRequired.ContainsKey(splitLine[0])) { parseRequired.Add(splitLine[0], ""); } } } } else { if (!parseRequired.ContainsKey(lowerFixedLine)) { parseRequired.Add(lowerFixedLine, ""); } } } break; case "optional-files": { string lowerFixedLine = trimmedLine.ToLowerInvariant().Replace('\\', '/'); if (lowerFixedLine.Contains("=")) { string[] splitLine = lowerFixedLine.Split('='); if (splitLine.Length == 2) { if (!parseOptional.ContainsKey(splitLine[0])) { parseOptional.Add(splitLine[0], splitLine[1]); } } else { if (splitLine.Length == 1) { if (!parseOptional.ContainsKey(splitLine[0])) { parseOptional.Add(splitLine[0], ""); } } } } else { if (!parseOptional.ContainsKey(lowerFixedLine)) { parseOptional.Add(lowerFixedLine, ""); } } } break; case "resource-whitelist": case "resource-blacklist": { string lowerFixedLine = trimmedLine.ToLowerInvariant().Replace('\\', '/'); //Resource is dll's only. if (lowerFixedLine.ToLowerInvariant().EndsWith(".dll", StringComparison.Ordinal)) { if (parseWhiteBlackList.Contains(lowerFixedLine)) { parseWhiteBlackList.Add(lowerFixedLine); } } } break; case "partslist": if (!parsePartsList.Contains(trimmedLine)) { parsePartsList.Add(trimmedLine); } break; default: break; } } } } string[] currentGameDataFiles = Directory.GetFiles(Client.dmpClient.gameDataDir, "*", SearchOption.AllDirectories); List <string> currentGameDataFilesNormal = new List <string>(); List <string> currentGameDataFilesLower = new List <string>(); foreach (string currentFile in currentGameDataFiles) { string relativeFilePath = currentFile.Substring(currentFile.ToLowerInvariant().IndexOf("gamedata", StringComparison.Ordinal) + 9).Replace('\\', '/'); currentGameDataFilesNormal.Add(relativeFilePath); currentGameDataFilesLower.Add(relativeFilePath.ToLowerInvariant()); } //Check StringBuilder sb = new StringBuilder(); //Check Required foreach (KeyValuePair <string, string> requiredEntry in parseRequired) { if (!requiredEntry.Key.EndsWith("dll", StringComparison.Ordinal)) { //Protect against windows-style entries in mod-control.txt. Also use case insensitive matching. if (!currentGameDataFilesLower.Contains(requiredEntry.Key)) { modCheckOk = false; DarkLog.Debug("Required file " + requiredEntry.Key + " is missing!"); sb.AppendLine("Required file " + requiredEntry.Key + " is missing!"); continue; } //If the entry has a SHA sum, we need to check it. if (requiredEntry.Value != "") { string normalCaseFileName = currentGameDataFilesNormal[currentGameDataFilesLower.IndexOf(requiredEntry.Key)]; string fullFileName = Path.Combine(Client.dmpClient.gameDataDir, normalCaseFileName); if (!CheckFile(fullFileName, requiredEntry.Value)) { modCheckOk = false; DarkLog.Debug("Required file " + requiredEntry.Key + " does not match hash " + requiredEntry.Value + "!"); sb.AppendLine("Required file " + requiredEntry.Key + " does not match hash " + requiredEntry.Value + "!"); continue; } } } else { //DLL entries are cached from startup. if (!dllList.ContainsKey(requiredEntry.Key)) { modCheckOk = false; DarkLog.Debug("Required file " + requiredEntry.Key + " is missing!"); sb.AppendLine("Required file " + requiredEntry.Key + " is missing!"); continue; } if (requiredEntry.Value != "") { if (dllList[requiredEntry.Key] != requiredEntry.Value) { modCheckOk = false; DarkLog.Debug("Required file " + requiredEntry.Key + " does not match hash " + requiredEntry.Value + "!"); sb.AppendLine("Required file " + requiredEntry.Key + " does not match hash " + requiredEntry.Value + "!"); continue; } } } } //Check Optional foreach (KeyValuePair <string, string> optionalEntry in parseOptional) { if (!optionalEntry.Key.EndsWith("dll", StringComparison.Ordinal)) { //Protect against windows-style entries in mod-control.txt. Also use case insensitive matching. if (!currentGameDataFilesLower.Contains(optionalEntry.Key)) { //File is optional, nothing to check if it doesn't exist. continue; } //If the entry has a SHA sum, we need to check it. if (optionalEntry.Value != "") { string normalCaseFileName = currentGameDataFilesNormal[currentGameDataFilesLower.IndexOf(optionalEntry.Key)]; string fullFileName = Path.Combine(Client.dmpClient.gameDataDir, normalCaseFileName); if (!CheckFile(fullFileName, optionalEntry.Value)) { modCheckOk = false; DarkLog.Debug("Optional file " + optionalEntry.Key + " does not match hash " + optionalEntry.Value + "!"); sb.AppendLine("Optional file " + optionalEntry.Key + " does not match hash " + optionalEntry.Value + "!"); continue; } } } else { //DLL entries are cached from startup. if (!dllList.ContainsKey(optionalEntry.Key)) { //File is optional, nothing to check if it doesn't exist. continue; } if (optionalEntry.Value != "") { if (dllList[optionalEntry.Key] != optionalEntry.Value) { modCheckOk = false; DarkLog.Debug("Optional file " + optionalEntry.Key + " does not match hash " + optionalEntry.Value + "!"); sb.AppendLine("Optional file " + optionalEntry.Key + " does not match hash " + optionalEntry.Value + "!"); continue; } } } } if (isWhiteList) { //Check Resource whitelist List <string> autoAllowed = new List <string>(); autoAllowed.Add("darkmultiplayer/plugins/darkmultiplayer.dll"); autoAllowed.Add("darkmultiplayer/plugins/darkmultiplayer-common.dll"); //Leave the old one there if the user forgets to delete it. autoAllowed.Add("darkmultiplayer/plugins/messagewriter.dll"); autoAllowed.Add("darkmultiplayer/plugins/messagewriter2.dll"); //Compression autoAllowed.Add("darkmultiplayer/plugins/icsharpcode.sharpziplib.dll"); foreach (KeyValuePair <string, string> dllResource in dllList) { //Allow DMP files if (autoAllowed.Contains(dllResource.Key)) { continue; } //Ignore squad plugins if (dllResource.Key.StartsWith("squad/plugins", StringComparison.Ordinal)) { continue; } //Check required (Required implies whitelist) if (parseRequired.ContainsKey(dllResource.Key)) { continue; } //Check optional (Optional implies whitelist) if (parseOptional.ContainsKey(dllResource.Key)) { continue; } //Check whitelist if (parseWhiteBlackList.Contains(dllResource.Key)) { continue; } modCheckOk = false; DarkLog.Debug("Non-whitelisted resource " + dllResource.Key + " exists on client!"); sb.AppendLine("Non-whitelisted resource " + dllResource.Key + " exists on client!"); } } else { //Check Resource blacklist foreach (string blacklistEntry in parseWhiteBlackList) { if (dllList.ContainsKey(blacklistEntry.ToLowerInvariant())) { modCheckOk = false; DarkLog.Debug("Banned resource " + blacklistEntry + " exists on client!"); sb.AppendLine("Banned resource " + blacklistEntry + " exists on client!"); } } } if (!modCheckOk) { failText = sb.ToString(); modWindow.display = true; return(false); } allowedParts = parsePartsList; DarkLog.Debug("Mod check passed!"); return(true); }
public void SendScenarioModules(bool highPriority) { lastScenarioSendTime = Client.realtimeSinceStartup; List <string> scenarioName = new List <string>(); List <ByteArray> scenarioData = new List <ByteArray>(); foreach (ScenarioModule sm in ScenarioRunner.GetLoadedModules()) { string scenarioType = sm.GetType().Name; if (!IsScenarioModuleAllowed(scenarioType)) { continue; } try { ConfigNode scenarioNode = new ConfigNode(); sm.Save(scenarioNode); ByteArray scenarioBytes = configNodeSerializer.Serialize(scenarioNode); string scenarioHash = Common.CalculateSHA256Hash(scenarioBytes); if (scenarioBytes.Length == 0) { DarkLog.Debug("Error writing scenario data for " + scenarioType); ByteRecycler.ReleaseObject(scenarioBytes); continue; } if (checkData.ContainsKey(scenarioType) ? (checkData[scenarioType] == scenarioHash) : false) { //Data is the same since last time - Skip it. ByteRecycler.ReleaseObject(scenarioBytes); continue; } else { checkData[scenarioType] = scenarioHash; } scenarioName.Add(scenarioType); scenarioData.Add(scenarioBytes); } catch (Exception e) { string fullName = sm.GetType().FullName; if (!warnedModules.Contains(fullName)) { DarkLog.Debug("Unable to save module data from " + fullName + ", skipping upload of this module. Exception: " + e); warnedModules.Add(fullName); if (!fullName.Contains("Expansions.Serenity.DeployedScience")) { ScreenMessages.PostScreenMessage("DMP was unable to save " + fullName + ", this module data will be lost.", 30f, ScreenMessageStyle.UPPER_CENTER); } } } } if (scenarioName.Count > 0) { if (highPriority) { networkWorker.SendScenarioModuleDataHighPriority(scenarioName.ToArray(), scenarioData.ToArray()); } else { networkWorker.SendScenarioModuleData(scenarioName.ToArray(), scenarioData.ToArray()); } } }
public void HandleSyncTime(long clientSend, long serverReceive, long serverSend) { long clientReceive = DateTime.UtcNow.Ticks; long clientLatency = (clientReceive - clientSend) - (serverSend - serverReceive); long clientOffset = ((serverReceive - clientSend) + (serverSend - clientReceive)) / 2; clockOffset[clockOffsetPos] = clientOffset; clockOffsetPos++; networkLatency[networkLatencyPos] = clientLatency; networkLatencyPos++; serverLag = serverSend - serverReceive; if (clockOffsetPos >= clockOffset.Length) { clockOffsetPos = 0; clockOffsetFull = true; } if (networkLatencyPos >= networkLatency.Length) { networkLatencyPos = 0; networkLatencyFull = true; } long clockOffsetTotal = 0; int clockOffsetEndPos = clockOffsetPos; if (clockOffsetFull) { clockOffsetEndPos = clockOffset.Length; } for (int i = 0; i < clockOffsetEndPos; i++) { clockOffsetTotal += clockOffset[i]; } clockOffsetAverage = clockOffsetTotal / clockOffsetEndPos; long networkLatencyTotal = 0; int networkLatencyEndPos = clockOffsetPos; if (networkLatencyFull) { networkLatencyEndPos = networkLatency.Length; } for (int i = 0; i < networkLatencyEndPos; i++) { networkLatencyTotal += networkLatency[i]; } networkLatencyAverage = networkLatencyTotal / networkLatencyEndPos; //Check if we are now synced if ((clockOffsetFull || clockOffsetPos > SYNC_TIME_VALID) && !synced) { synced = true; float clockOffsetAverageMs = clockOffsetAverage / 10000f; float networkLatencyMs = networkLatencyAverage / 10000f; DarkLog.Debug("Initial clock syncronized, offset " + clockOffsetAverageMs + "ms, latency " + networkLatencyMs + "ms"); } //Ask for another time sync if we aren't synced yet. if (!synced) { lastSyncTime = Client.realtimeSinceStartup; networkWorker.SendTimeSync(); } }
public void LoadScenarioData(ScenarioEntry entry) { if (!IsScenarioModuleAllowed(entry.scenarioName)) { DarkLog.Debug("Skipped '" + entry.scenarioName + "' scenario data in " + dmpGame.gameMode + " mode"); return; } //Load data from DMP if (entry.scenarioNode == null) { DarkLog.Debug(entry.scenarioName + " scenario data failed to create a ConfigNode!"); ScreenMessages.PostScreenMessage("Scenario " + entry.scenarioName + " failed to load, blocking scenario uploads.", 10f, ScreenMessageStyle.UPPER_CENTER); blockScenarioDataSends = true; return; } //Load data into game if (DidScenarioChange(entry)) { bool loaded = false; ByteArray scenarioBytes = configNodeSerializer.Serialize(entry.scenarioNode); checkData[entry.scenarioName] = Common.CalculateSHA256Hash(scenarioBytes); ByteRecycler.ReleaseObject(scenarioBytes); foreach (ProtoScenarioModule psm in HighLogic.CurrentGame.scenarios) { if (psm.moduleName == entry.scenarioName) { DarkLog.Debug("Loading existing " + entry.scenarioName + " scenario module"); try { if (psm.moduleRef == null) { DarkLog.Debug("Fixing null scenario module!"); psm.moduleRef = new ScenarioModule(); } bool skipLoad = false; if (beforeCallback.ContainsKey(psm.moduleName)) { skipLoad = beforeCallback[psm.moduleName](entry.scenarioNode); } if (!skipLoad) { psm.moduleRef.Load(entry.scenarioNode); } if (afterCallback.ContainsKey(psm.moduleName)) { afterCallback[psm.moduleName](entry.scenarioNode); } } catch (Exception e) { DarkLog.Debug("Error loading " + entry.scenarioName + " scenario module, Exception: " + e); blockScenarioDataSends = true; } loaded = true; } } if (!loaded) { DarkLog.Debug("Loading new " + entry.scenarioName + " scenario module"); LoadNewScenarioData(entry.scenarioNode); } } }
private void HandleCommandLineArgs() { bool nextLineIsAddress = false; bool valid = false; string address = null; int port = 6702; foreach (string commandLineArg in Environment.GetCommandLineArgs()) { //Supporting IPv6 is FUN! if (nextLineIsAddress) { valid = true; nextLineIsAddress = false; if (commandLineArg.Contains("dmp://")) { if (commandLineArg.Contains("[") && commandLineArg.Contains("]")) { //IPv6 literal address = commandLineArg.Substring("dmp://[".Length); address = address.Substring(0, address.LastIndexOf("]")); if (commandLineArg.Contains("]:")) { //With port string portString = commandLineArg.Substring(commandLineArg.LastIndexOf("]:") + 1); if (!Int32.TryParse(portString, out port)) { valid = false; } } } else { //IPv4 literal or hostname if (commandLineArg.Substring("dmp://".Length).Contains(":")) { //With port address = commandLineArg.Substring("dmp://".Length); address = address.Substring(0, address.LastIndexOf(":")); string portString = commandLineArg.Substring(commandLineArg.LastIndexOf(":") + 1); if (!Int32.TryParse(portString, out port)) { valid = false; } } else { //Without port address = commandLineArg.Substring("dmp://".Length); } } } else { valid = false; } } if (commandLineArg == "-dmp") { nextLineIsAddress = true; } } if (valid) { commandLineConnect = new ServerEntry(); commandLineConnect.address = address; commandLineConnect.port = port; DarkLog.Debug("Connecting via command line to: " + address + ", port: " + port); } else { DarkLog.Debug("Command line address is invalid: " + address + ", port: " + port); } }
private void OnContractAccepted(Contract contract) { DarkLog.Debug("Contract accepted, state: " + contract.ContractState); ConfigNode contractNode = new ConfigNode(); contract.Save(contractNode); if (contractNode.GetValue("type") == "RecoverAsset") { string kerbalName = contractNode.GetValue("kerbalName").Trim(); int kerbalGender = int.Parse(contractNode.GetValue("gender")); uint partID = uint.Parse(contractNode.GetValue("partID")); if (!string.IsNullOrEmpty(kerbalName)) { ProtoCrewMember rescueKerbal = null; if (!HighLogic.CurrentGame.CrewRoster.Exists(kerbalName)) { DarkLog.Debug("Generating missing kerbal " + kerbalName + " for rescue contract"); rescueKerbal = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned); rescueKerbal.ChangeName(kerbalName); rescueKerbal.gender = (ProtoCrewMember.Gender)kerbalGender; rescueKerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; } else { rescueKerbal = HighLogic.CurrentGame.CrewRoster[kerbalName]; DarkLog.Debug("Kerbal " + kerbalName + " already exists, skipping respawn"); } if (rescueKerbal != null) { vesselWorker.SendKerbalIfDifferent(rescueKerbal); } } if (partID != 0) { Vessel contractVessel = FinePrint.Utilities.VesselUtilities.FindVesselWithPartIDs(new List <uint> { partID }); if (contractVessel != null) { vesselWorker.SendVesselUpdateIfNeeded(contractVessel); } } } else if (contractNode.GetValue("type") == "TourismContract") { string tourists = contractNode.GetValue("tourists"); if (tourists != null) { string[] touristsNames = tourists.Split(new char[] { '|' }); foreach (string touristName in touristsNames) { ProtoCrewMember pcm = null; if (!HighLogic.CurrentGame.CrewRoster.Exists(touristName)) { DarkLog.Debug("Spawning missing tourist " + touristName + " for tourism contract"); pcm = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Tourist); pcm.rosterStatus = ProtoCrewMember.RosterStatus.Available; pcm.ChangeName(touristName); } else { DarkLog.Debug("Skipped respawn of existing tourist " + touristName); pcm = HighLogic.CurrentGame.CrewRoster[touristName]; } if (pcm != null) { vesselWorker.SendKerbalIfDifferent(pcm); } } } } }
public void GenerateUniverse(string saveName) { string universeFolder = Path.Combine(Client.dmpClient.kspRootPath, "Universe"); if (Directory.Exists(universeFolder)) { Directory.Delete(universeFolder, true); } string saveFolder = Path.Combine(savesFolder, saveName); if (!Directory.Exists(saveFolder)) { DarkLog.Debug("Failed to generate a DMP universe for '" + saveName + "', Save directory doesn't exist"); ScreenMessages.PostScreenMessage("Failed to generate a DMP universe for '" + saveName + "', Save directory doesn't exist", 5f, ScreenMessageStyle.UPPER_CENTER); return; } string persistentFile = Path.Combine(saveFolder, "persistent.sfs"); if (!File.Exists(persistentFile)) { DarkLog.Debug("Failed to generate a DMP universe for '" + saveName + "', persistent.sfs doesn't exist"); ScreenMessages.PostScreenMessage("Failed to generate a DMP universe for '" + saveName + "', persistent.sfs doesn't exist", 5f, ScreenMessageStyle.UPPER_CENTER); return; } Directory.CreateDirectory(universeFolder); string vesselFolder = Path.Combine(universeFolder, "Vessels"); Directory.CreateDirectory(vesselFolder); string scenarioFolder = Path.Combine(universeFolder, "Scenarios"); Directory.CreateDirectory(scenarioFolder); string playerScenarioFolder = Path.Combine(scenarioFolder, dmpSettings.playerName); Directory.CreateDirectory(playerScenarioFolder); string kerbalFolder = Path.Combine(universeFolder, "Kerbals"); Directory.CreateDirectory(kerbalFolder); //Load game data ConfigNode persistentData = ConfigNode.Load(persistentFile); if (persistentData == null) { DarkLog.Debug("Failed to generate a DMP universe for '" + saveName + "', failed to load persistent data"); ScreenMessages.PostScreenMessage("Failed to generate a DMP universe for '" + saveName + "', failed to load persistent data", 5f, ScreenMessageStyle.UPPER_CENTER); return; } ConfigNode gameData = persistentData.GetNode("GAME"); if (gameData == null) { DarkLog.Debug("Failed to generate a DMP universe for '" + saveName + "', failed to load game data"); ScreenMessages.PostScreenMessage("Failed to generate a DMP universe for '" + saveName + "', failed to load game data", 5f, ScreenMessageStyle.UPPER_CENTER); return; } //Save vessels ConfigNode flightState = gameData.GetNode("FLIGHTSTATE"); if (flightState == null) { DarkLog.Debug("Failed to generate a DMP universe for '" + saveName + "', failed to load flight state data"); ScreenMessages.PostScreenMessage("Failed to generate a DMP universe for '" + saveName + "', failed to load flight state data", 5f, ScreenMessageStyle.UPPER_CENTER); return; } ConfigNode[] vesselNodes = flightState.GetNodes("VESSEL"); if (vesselNodes != null) { foreach (ConfigNode cn in vesselNodes) { string vesselID = Common.ConvertConfigStringToGUIDString(cn.GetValue("pid")); DarkLog.Debug("Saving vessel " + vesselID + ", name: " + cn.GetValue("name")); cn.Save(Path.Combine(vesselFolder, vesselID + ".txt")); } } //Save scenario data ConfigNode[] scenarioNodes = gameData.GetNodes("SCENARIO"); if (scenarioNodes != null) { foreach (ConfigNode cn in scenarioNodes) { string scenarioName = cn.GetValue("name"); DarkLog.Debug("Saving scenario: " + scenarioName); cn.Save(Path.Combine(playerScenarioFolder, scenarioName + ".txt")); } } //Save kerbal data ConfigNode[] kerbalNodes = gameData.GetNode("ROSTER").GetNodes("CREW"); if (kerbalNodes != null) { int kerbalIndex = 0; foreach (ConfigNode cn in kerbalNodes) { DarkLog.Debug("Saving kerbal " + kerbalIndex + ", name: " + cn.GetValue("name")); cn.Save(Path.Combine(kerbalFolder, kerbalIndex + ".txt")); kerbalIndex++; } } DarkLog.Debug("Generated KSP_folder/Universe from " + saveName); ScreenMessages.PostScreenMessage("Generated KSP_folder/Universe from " + saveName, 5f, ScreenMessageStyle.UPPER_CENTER); }
public void DodgeKerbals(ConfigNode inputNode, Guid protovesselID) { List <string> takenKerbals = new List <string>(); foreach (ConfigNode partNode in inputNode.GetNodes("PART")) { int crewIndex = 0; foreach (string currentKerbalName in partNode.GetValues("crew")) { if (kerbalToVessel.ContainsKey(currentKerbalName) ? kerbalToVessel[currentKerbalName] != protovesselID : false) { ProtoCrewMember newKerbal = null; ProtoCrewMember.Gender newKerbalGender = GetKerbalGender(currentKerbalName); string newExperienceTrait = null; if (HighLogic.CurrentGame.CrewRoster.Exists(currentKerbalName)) { ProtoCrewMember oldKerbal = HighLogic.CurrentGame.CrewRoster[currentKerbalName]; newKerbalGender = oldKerbal.gender; newExperienceTrait = oldKerbal.experienceTrait.TypeName; } foreach (ProtoCrewMember possibleKerbal in HighLogic.CurrentGame.CrewRoster.Crew) { bool kerbalOk = true; if (kerbalOk && kerbalToVessel.ContainsKey(possibleKerbal.name) && (takenKerbals.Contains(possibleKerbal.name) || kerbalToVessel[possibleKerbal.name] != protovesselID)) { kerbalOk = false; } if (kerbalOk && possibleKerbal.gender != newKerbalGender) { kerbalOk = false; } if (kerbalOk && newExperienceTrait != null && possibleKerbal.experienceTrait != null && newExperienceTrait != possibleKerbal.experienceTrait.TypeName) { kerbalOk = false; } if (kerbalOk) { newKerbal = possibleKerbal; break; } } int kerbalTries = 0; while (newKerbal == null) { bool kerbalOk = true; ProtoCrewMember.KerbalType kerbalType = ProtoCrewMember.KerbalType.Crew; if (newExperienceTrait == "Tourist") { kerbalType = ProtoCrewMember.KerbalType.Tourist; } if (newExperienceTrait == "Unowned") { kerbalType = ProtoCrewMember.KerbalType.Unowned; } ProtoCrewMember possibleKerbal = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(kerbalType); if (kerbalTries < 200 && possibleKerbal.gender != newKerbalGender) { kerbalOk = false; } if (kerbalTries < 100 && newExperienceTrait != null && newExperienceTrait != possibleKerbal.experienceTrait.TypeName) { kerbalOk = false; } if (kerbalOk) { newKerbal = possibleKerbal; } kerbalTries++; } DarkLog.Debug("Generated dodged kerbal with " + kerbalTries + " tries"); partNode.SetValue("crew", newKerbal.name, crewIndex); newKerbal.seatIdx = crewIndex; newKerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; takenKerbals.Add(newKerbal.name); } else { takenKerbals.Add(currentKerbalName); CreateKerbalIfMissing(currentKerbalName, protovesselID); HighLogic.CurrentGame.CrewRoster[currentKerbalName].rosterStatus = ProtoCrewMember.RosterStatus.Assigned; HighLogic.CurrentGame.CrewRoster[currentKerbalName].seatIdx = crewIndex; } crewIndex++; } } vesselToKerbal[protovesselID] = takenKerbals; foreach (string name in takenKerbals) { kerbalToVessel[name] = protovesselID; } }