public void LoadScenarioDataIntoGame() { lock (scenarioQueue) { while (scenarioQueue.Count > 0) { ScenarioEntry scenarioEntry = scenarioQueue.Dequeue(); if (scenarioEntry.scenarioName == "ProgressTracking") { CreateMissingKerbalsInProgressTrackingSoTheGameDoesntBugOut(scenarioEntry.scenarioNode); } CheckForBlankSceneSoTheGameDoesntBugOut(scenarioEntry); ProtoScenarioModule psm = new ProtoScenarioModule(scenarioEntry.scenarioNode); if (psm != null) { if (IsScenarioModuleAllowed(psm.moduleName)) { DarkLog.Debug("Loading " + psm.moduleName + " scenario data"); HighLogic.CurrentGame.scenarios.Add(psm); ByteArray scenarioHashBytes = configNodeSerializer.Serialize(scenarioEntry.scenarioNode); checkData[scenarioEntry.scenarioName] = Common.CalculateSHA256Hash(scenarioHashBytes); ByteRecycler.ReleaseObject(scenarioHashBytes); } else { DarkLog.Debug("Skipping " + psm.moduleName + " scenario data in " + dmpGame.gameMode + " mode"); } } } } }
public void ProcessWarpMessages() { lock (newWarpMessages) { while (newWarpMessages.Count > 0) { ByteArray queueByteArray = newWarpMessages.Dequeue(); HandleWarpMessage(queueByteArray.data); ByteRecycler.ReleaseObject(queueByteArray); } } }
private void ProcessMessages() { lock (messageQueue) { while (messageQueue.Count > 0) { ByteArray queueByteArray = messageQueue.Dequeue(); HandleMessage(queueByteArray.data); ByteRecycler.ReleaseObject(queueByteArray); } } }
private bool DidScenarioChange(ScenarioEntry scenarioEntry) { string previousScenarioHash = null; ByteArray scenarioBytes = configNodeSerializer.Serialize(scenarioEntry.scenarioNode); string currentScenarioHash = Common.CalculateSHA256Hash(scenarioBytes); ByteRecycler.ReleaseObject(scenarioBytes); if (checkData.TryGetValue(scenarioEntry.scenarioName, out previousScenarioHash)) { return(previousScenarioHash != currentScenarioHash); } return(true); }
private void ProcessingThreadMain() { while (true) { if (incomingQueue.Count == 0) { incomingEvent.WaitOne(500); } else { ByteArray incomingBytes; lock (incomingQueue) { incomingBytes = incomingQueue.Dequeue(); } SaveToCache(incomingBytes); ByteRecycler.ReleaseObject(incomingBytes); } } }
public void Update() { if (playback) { DisplayUpdateVesselOffset(); if (Planetarium.GetUniversalTime() > (lastTime)) { playback = false; ScreenMessages.RemoveMessage(screenMessage); screenMessage = null; } else { int timeLeft = (int)(lastTime - Planetarium.GetUniversalTime()); ScreenMessages.RemoveMessage(screenMessage); screenMessage = ScreenMessages.PostScreenMessage("Playback time left: " + timeLeft + " / " + (int)(lastTime - firstTime) + " seconds", float.MaxValue, ScreenMessageStyle.UPPER_CENTER); } } if (active) { VesselUpdate vu = Recycler <VesselUpdate> .GetObject(); vu.SetVesselWorker(vesselWorker); vu.CopyFromVessel(FlightGlobals.fetch.activeVessel); ClientMessage updateBytes = networkWorker.GetVesselUpdateMessage(vu); byte[] lengthBytes = BitConverter.GetBytes(updateBytes.data.Length); if (BitConverter.IsLittleEndian) { Array.Reverse(lengthBytes); } recordingVector.Write(lengthBytes, 0, lengthBytes.Length); recordingVector.Write(updateBytes.data.data, 0, updateBytes.data.Length); ByteRecycler.ReleaseObject(updateBytes.data); Recycler <VesselUpdate> .ReleaseObject(vu); } }
public void StartPlayback() { int messagesLoaded = 0; bool firstMessage = true; ByteArray headerBytes = ByteRecycler.GetObject(8); using (FileStream fs = new FileStream(recordPath, FileMode.Open)) { while (fs.Position < fs.Length) { messagesLoaded++; fs.Read(headerBytes.data, 0, 8); using (MessageReader mr = new MessageReader(headerBytes.data)) { ClientMessageType messageType = (ClientMessageType)mr.Read <int>(); int length = mr.Read <int>(); ByteArray dataBytes = ByteRecycler.GetObject(length); fs.Read(dataBytes.data, 0, length); using (MessageReader timeReader = new MessageReader(dataBytes.data)) { //Planet time is the first part of the message for the three types we care about here double planetTime = timeReader.Read <double>(); lastTime = planetTime; if (firstMessage) { firstTime = planetTime; firstMessage = false; Planetarium.SetUniversalTime(planetTime - 5d); warpWorker.SendNewSubspace(); } } using (MessageReader mrignore = new MessageReader(dataBytes.data)) { //Planet time, don't care here mrignore.Read <double>(); string vesselID = mrignore.Read <string>(); vesselWorker.IgnoreVessel(new Guid(vesselID)); } switch (messageType) { case ClientMessageType.VESSEL_PROTO: HandleProtoUpdate(dataBytes); break; case ClientMessageType.VESSEL_UPDATE: HandleVesselUpdate(dataBytes, false); break; case ClientMessageType.VESSEL_REMOVE: HandleVesselRemove(dataBytes); break; default: break; } ByteRecycler.ReleaseObject(dataBytes); } } ByteRecycler.ReleaseObject(headerBytes); } playbackQueue = new Queue <VesselUpdate>(); using (FileStream fs = new FileStream(recordVectorPath, FileMode.Open)) { while (fs.Position < fs.Length) { fs.Read(headerBytesInt, 0, 4); if (BitConverter.IsLittleEndian) { Array.Reverse(headerBytesInt); } int updateLength = BitConverter.ToInt32(headerBytesInt, 0); ByteArray updateBytes = ByteRecycler.GetObject(updateLength); fs.Read(updateBytes.data, 0, updateLength); VesselUpdate vu = networkWorker.VeselUpdateFromBytes(updateBytes.data, false); playbackQueue.Enqueue(vu); ByteRecycler.ReleaseObject(updateBytes); } } ScreenMessages.PostScreenMessage("Loaded " + messagesLoaded + " saved updates.", 5f, ScreenMessageStyle.UPPER_CENTER); screenMessage = ScreenMessages.PostScreenMessage("Playback 0 / " + (int)(lastTime - firstTime) + " seconds.", float.MaxValue, ScreenMessageStyle.UPPER_CENTER); playback = true; }
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); } } }
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()); } } }
private void RealHandleMessage(ByteArray messageData) { using (MessageReader mr = new MessageReader(messageData.data)) { ModpackDataMessageType type = (ModpackDataMessageType)mr.Read <int>(); switch (type) { case ModpackDataMessageType.CKAN: { modpackMode = ModpackMode.CKAN; ByteArray receiveData = mr.Read <ByteArray>(); ByteArray oldData = null; if (File.Exists(ckanDataPath)) { using (FileStream fs = new FileStream(ckanDataPath, FileMode.Open)) { oldData = ByteRecycler.GetObject((int)fs.Length); fs.Read(oldData.data, 0, oldData.Length); } } if (!BytesMatch(oldData, receiveData)) { missingWarnFile = true; DarkLog.Debug("Ckan file changed"); File.Delete(ckanDataPath); using (FileStream fs = new FileStream(ckanDataPath, FileMode.OpenOrCreate)) { fs.Write(receiveData.data, 0, receiveData.Length); } } if (!registeredChatCommand) { registeredChatCommand = true; chatWorker.RegisterChatCommand("upload", UploadCKANToServer, "Upload DarkMultiPlayer.ckan to the server"); } if (oldData != null) { ByteRecycler.ReleaseObject(oldData); } ByteRecycler.ReleaseObject(receiveData); } break; case ModpackDataMessageType.MOD_LIST: { modFilesToHash = null; modFilesToHashPos = 0; serverPathCache.Clear(); noWarnSha.Clear(); modpackMode = ModpackMode.GAMEDATA; string[] files = mr.Read <string[]>(); string[] sha = mr.Read <string[]>(); if (File.Exists(gameDataServerCachePath)) { File.Delete(gameDataServerCachePath); } using (StreamWriter sw = new StreamWriter(gameDataServerCachePath)) { for (int i = 0; i < files.Length; i++) { bool skipFile = false; foreach (string ignoreString in ignoreList) { if (files[i].ToLower().StartsWith(ignoreString, StringComparison.Ordinal)) { skipFile = true; } } foreach (string ignoreString in containsIgnoreList) { if (files[i].ToLower().Contains(ignoreString)) { skipFile = true; } } if (skipFile) { continue; } sw.WriteLine("{0}={1}", files[i], sha[i]); serverPathCache.Add(files[i], sha[i]); } } LoadAuto(); if (!registeredChatCommand) { registeredChatCommand = true; chatWorker.RegisterChatCommand("upload", UploadToServer, "Upload GameData to the server"); } } break; case ModpackDataMessageType.REQUEST_OBJECT: { modFilesToUpload = mr.Read <string[]>(); modFilesToUploadPos = 0; DarkLog.Debug("Server requested " + modFilesToUpload.Length + " files"); } break; case ModpackDataMessageType.RESPONSE_OBJECT: { string sha256sum = mr.Read <string>(); filesDownloaded++; if (mr.Read <bool>()) { syncString = "Syncing files " + filesDownloaded + "/" + requestList.Count + " (" + (serverPathCache.Count - requestList.Count) + " cached)"; ByteArray fileBytes = mr.Read <ByteArray>(); string filePath = Path.Combine(cacheDataPath, sha256sum + ".bin"); if (!File.Exists(filePath)) { using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate)) { fs.Write(fileBytes.data, 0, fileBytes.Length); } } ByteRecycler.ReleaseObject(fileBytes); } else { ScreenMessages.PostScreenMessage("DMP Server has an out of date hash list. Tell the admin to run /reloadmods", float.PositiveInfinity, ScreenMessageStyle.UPPER_CENTER); networkWorker.Disconnect("Syncing files error"); } if (filesDownloaded == requestList.Count) { if (missingWarnFile) { networkWorker.Disconnect("Syncing files " + filesDownloaded + "/" + requestList.Count + " (" + (serverPathCache.Count - requestList.Count) + " cached)"); ScreenMessages.PostScreenMessage("Please run DMPModpackUpdater or reconnect to ignore", float.PositiveInfinity, ScreenMessageStyle.UPPER_CENTER); } else { synced = true; } } } break; case ModpackDataMessageType.MOD_DONE: { if ((!missingWarnFile && requestList.Count == 0) || secondModSync) { synced = true; } else { if (modpackMode == ModpackMode.CKAN) { ScreenMessages.PostScreenMessage("Please install CKAN update at KSP/DarkMultiPlayer.ckan or reconnect to ignore", float.PositiveInfinity, ScreenMessageStyle.UPPER_CENTER); networkWorker.Disconnect("Synced DarkMultiPlayer.ckan"); } if (modpackMode == ModpackMode.GAMEDATA && requestList.Count == 0) { ScreenMessages.PostScreenMessage("Please run DMPModpackUpdater or reconnect to ignore", float.PositiveInfinity, ScreenMessageStyle.UPPER_CENTER); syncString = "Synced files (" + serverPathCache.Count + " cached)"; networkWorker.Disconnect(syncString); } } secondModSync = true; } break; } } }
private void Update() { //Don't process incoming files or MOD_COMPLETE if we are hashing our gamedata folder if (hashingThreads == null) { lock (messageQueue) { while (messageQueue.Count > 0) { ByteArray queueByteArray = messageQueue.Dequeue(); RealHandleMessage(queueByteArray); ByteRecycler.ReleaseObject(queueByteArray); //Don't process incoming files or MOD_COMPLETE if we are hashing our gamedata folder if (hashingThreads != null) { syncString = "Hashing 0/" + modFilesToHash.Length + " files"; break; } } if (networkWorker.state == ClientState.RUNNING) { while (modFilesToUpload != null && networkWorker.GetStatistics("QueuedOutBytes") < 1000000) { RealSendToServer(); if (modFilesToUpload != null) { syncString = "Uploading " + modFilesToUploadPos + "/" + modFilesToUpload.Length + " files"; DarkLog.Debug(syncString); if (screenMessage != null && DateTime.UtcNow.Ticks > nextScreenMessageUpdate) { nextScreenMessageUpdate = DateTime.UtcNow.Ticks + (TimeSpan.TicksPerMillisecond * 100); screenMessage.duration = 0f; screenMessage = ScreenMessages.PostScreenMessage(syncString); } } } } } } else { long stopTime = DateTime.UtcNow.Ticks + (TimeSpan.TicksPerMillisecond * 100); CheckHashingThreads(); if (hashingThreads == null) { using (StreamWriter sw = new StreamWriter(gameDataClientCachePath)) { foreach (KeyValuePair <string, string> kvp in clientPathCache) { sw.WriteLine("{0}={1}", kvp.Key, kvp.Value); } } syncString = "Hashed " + clientPathCache.Count + " files"; DarkLog.Debug("Hashed " + clientPathCache.Count + " files"); if (screenMessage != null && DateTime.UtcNow.Ticks > nextScreenMessageUpdate) { nextScreenMessageUpdate = DateTime.UtcNow.Ticks + (TimeSpan.TicksPerMillisecond * 100); screenMessage.duration = 0f; screenMessage = ScreenMessages.PostScreenMessage(syncString); } if (uploadAfterHashing) { uploadAfterHashing = false; using (MessageWriter mw = new MessageWriter()) { List <string> uploadfiles = new List <string>(clientPathCache.Keys); List <string> uploadsha = new List <string>(clientPathCache.Values); mw.Write <int>((int)ModpackDataMessageType.MOD_LIST); mw.Write <string[]>(uploadfiles.ToArray()); mw.Write <string[]>(uploadsha.ToArray()); networkWorker.SendModpackMessage(mw.GetMessageBytes()); } } } else { syncString = "Hashing " + modFilesToHashPos + "/" + modFilesToHash.Length + " files"; if (screenMessage != null && DateTime.UtcNow.Ticks > nextScreenMessageUpdate) { nextScreenMessageUpdate = DateTime.UtcNow.Ticks + (TimeSpan.TicksPerMillisecond * 100); screenMessage.duration = 0f; screenMessage = ScreenMessages.PostScreenMessage(syncString); } DarkLog.Debug("Hashing " + modFilesToHashPos + "/" + modFilesToHash.Length + " files"); } } }