public void SendVesselMessage(Vessel vessel) { if (vessel == null) { return; } //Update the protovessel definition! vessel.BackupVessel(); //Defend against NaN orbits if (VesselHasNaNPosition(vessel.protoVessel)) { LunaLog.Log($"[LMP]: Vessel {vessel.id} has NaN position"); return; } foreach (var pps in vessel.protoVessel.protoPartSnapshots) { //Remove tourists from the vessel //TODO: Probably this can be done in the CleanUpVesselNode method foreach (var pcm in pps.protoModuleCrew.Where(pcm => pcm.type == ProtoCrewMember.KerbalType.Tourist).ToArray()) { pps.protoModuleCrew.Remove(pcm); } } var vesselNode = new ConfigNode(); try { vessel.protoVessel.Save(vesselNode); } catch (Exception) { LunaLog.LogError("[LMP]: Error while saving vessel"); return; } //Clean up the vessel so we send only the important data CleanUpVesselNode(vesselNode, vessel.id); var vesselBytes = ConfigNodeSerializer.Serialize(vesselNode); if (vesselBytes.Length > 0) { UniverseSyncCache.QueueToCache(vesselBytes); SendMessage(new VesselProtoMsgData { VesselId = vessel.id, VesselData = vesselBytes }); } else { LunaLog.LogError($"[LMP]: Failed to create byte[] data for {vessel.id}"); } }
/// <summary> /// Convert a byte array to a ConfigNode and then to a ProgressNode. /// If anything goes wrong it will return null. /// </summary> /// <param name="data">The byte array that represents the configNode</param> /// <param name="numBytes">The length of the byte array</param> /// <param name="progressNodeId">The Id of the ProgressNode</param> /// <returns></returns> private static ProgressNode ConvertByteArrayToAchievement(byte[] data, int numBytes, string progressNodeId) { ConfigNode node; try { node = ConfigNodeSerializer.Deserialize(data, numBytes); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error while deserializing achievement configNode: {e}"); return(null); } if (node == null) { LunaLog.LogError("[LMP]: Error, the achievement configNode was null."); return(null); } ProgressNode achievement; try { achievement = new ProgressNode(progressNodeId, false); achievement.Load(node); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error while deserializing achievement: {e}"); return(null); } return(achievement); }
/// <summary> /// Send a request to the master server to introduce us and do the nat punchtrough to the selected server /// </summary> public static void IntroduceToServer(long serverId) { if (Servers.TryGetValue(serverId, out var serverInfo)) { if (ServerIsInLocalLan(serverInfo.ExternalEndpoint)) { LunaLog.Log("Server is in LAN. Skipping NAT punch"); NetworkConnection.ConnectToServer(serverInfo.InternalEndpoint, Password); } else { try { var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <MsIntroductionMsgData>(); msgData.Id = serverId; msgData.Token = MainSystem.UniqueIdentifier; msgData.InternalEndpoint = new IPEndPoint(LunaNetUtils.GetOwnInternalIpAddress(), NetworkMain.Config.Port); var introduceMsg = NetworkMain.MstSrvMsgFactory.CreateNew <MainMstSrvMsg>(msgData); MainSystem.Singleton.Status = string.Empty; LunaLog.Log($"[LMP]: Sending NAT introduction to server. Token: {MainSystem.UniqueIdentifier}"); NetworkSender.QueueOutgoingMessage(introduceMsg); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error connecting to server: {e}"); } } } }
private static bool PrefixSetStartupNewVessel() { if (MainSystem.NetworkState < ClientState.Connected || string.IsNullOrEmpty(FlightDriver.newShipToLoadPath)) { return(true); } var configNode = ConfigNode.Load(FlightDriver.newShipToLoadPath); var shipName = configNode.GetValue("ship"); var partNames = configNode.GetNodes("PART").Select(n => n.GetValue("part").Substring(0, n.GetValue("part").IndexOf('_'))).ToList(); var partCount = configNode.GetNodes("PART").Count(); if (ModSystem.Singleton.ModControl) { var bannedParts = ModSystem.Singleton.GetBannedPartsFromPartNames(partNames.Distinct()).ToArray(); if (bannedParts.Any()) { LunaLog.LogError($"Vessel {shipName} Contains the following banned parts: {string.Join(", ", bannedParts)}"); BannedPartsWindow.Singleton.DisplayBannedPartsDialog(shipName, bannedParts); HighLogic.LoadScene(GameScenes.SPACECENTER); return(false); } } if (partCount > SettingsSystem.ServerSettings.MaxVesselParts) { LunaLog.LogError($"Vessel {shipName} has {partCount} parts and the max allowed in the server is: {SettingsSystem.ServerSettings.MaxVesselParts}"); BannedPartsWindow.Singleton.DisplayBannedPartsDialog(shipName, partCount); HighLogic.LoadScene(GameScenes.SPACECENTER); return(false); } return(true); }
public void HandleMessage(IMessageData messageData) { var msgData = messageData as VesselBaseMsgData; if (msgData == null) { return; } switch (msgData.VesselMessageType) { case VesselMessageType.ListReply: HandleVesselList((VesselListReplyMsgData)messageData); break; case VesselMessageType.VesselsReply: HandleVesselResponse((VesselsReplyMsgData)messageData); break; case VesselMessageType.Proto: HandleVesselProto((VesselProtoMsgData)messageData); break; default: LunaLog.LogError($"[LMP]: Cannot handle messages of type: {msgData.VesselMessageType} in VesselProtoMessageHandler"); break; } }
/// <summary> /// Call this method to set a new time using the planetarium /// </summary> public static void StepClock(double targetTick) { if (HighLogic.LoadedScene == GameScenes.LOADING) { LunaLog.Log("[LMP] Skipping StepClock in loading screen"); return; } if (HighLogic.LoadedSceneIsFlight) { if (FlightGlobals.fetch.activeVessel == null || !FlightGlobals.ready) { LunaLog.Log("[LMP] Skipping StepClock (active vessel is null or not ready)"); return; } try { OrbitPhysicsManager.HoldVesselUnpack(5); } catch { LunaLog.LogError("[LMP] Failed to hold vessel unpack"); return; } PutVesselsInPhysicsRangeOnRails(targetTick); } Planetarium.SetUniversalTime(targetTick); }
/// <summary> /// Send the definition of our own vessel and the secondary vessels. /// </summary> private void SendVesselDefinition() { try { if (ProtoSystemReady) { if (FlightGlobals.ActiveVessel.parts.Count != FlightGlobals.ActiveVessel.protoVessel.protoPartSnapshots.Count) { MessageSender.SendVesselMessage(FlightGlobals.ActiveVessel); } foreach (var vessel in VesselCommon.GetSecondaryVessels()) { if (vessel.parts.Count != vessel.protoVessel.protoPartSnapshots.Count) { MessageSender.SendVesselMessage(vessel); } } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in SendVesselDefinition {e}"); } }
/// <summary> /// Check all part modules that inherit from PartModule. Then it gets all the fields of those classes that have the "ispersistent" as true. /// </summary> public static void ReadLoadedPartModules() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { var partModules = assembly.GetTypes().Where(myType => myType.IsClass && myType.IsSubclassOf(typeof(PartModule))); foreach (var partModule in partModules) { var persistentFields = partModule.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) .Where(f => f.GetCustomAttributes(typeof(KSPField), true).Any(attr => ((KSPField)attr).isPersistant)).ToArray(); if (persistentFields.Any()) { ModuleFieldsDictionary.Add(partModule.Name, new FieldModuleDefinition(partModule, persistentFields)); } InheritanceTypeChain.Add(partModule.Name, GetInheritChain(partModule)); } } catch (Exception ex) { LunaLog.LogError($"Exception loading types from assembly {assembly.FullName}: {ex.Message}"); } } LunaLog.Log($"Loaded {ModuleFieldsDictionary.Keys.Count} modules and a total of {ModuleFieldsDictionary.Values.Count} fields"); }
public ProtoVessel CreateProtoVessel() { var configNode = ConfigNodeSerializer.Deserialize(RawData, NumBytes); if (configNode == null || VesselCommon.VesselHasNaNPosition(configNode)) { LunaLog.LogError($"Received a malformed vessel from SERVER. Id {VesselId}"); VesselRemoveSystem.Singleton.KillVessel(VesselId, "Malformed vessel"); VesselRemoveSystem.Singleton.AddToKillList(VesselId, "Malformed vessel"); return(null); } var newProto = VesselSerializer.CreateSafeProtoVesselFromConfigNode(configNode, VesselId); if (newProto == null) { LunaLog.LogError($"Received a malformed vessel from SERVER. Id {VesselId}"); VesselRemoveSystem.Singleton.KillVessel(VesselId, "Malformed vessel"); VesselRemoveSystem.Singleton.AddToKillList(VesselId, "Malformed vessel"); return(null); } if (VesselCommon.ProtoVesselHasInvalidParts(newProto)) { return(null); } return(newProto); }
/// <summary> /// Call this method to apply a vessel update using interpolation /// </summary> public void ApplyInterpolatedVesselUpdate() { if (Body == null) { return; } if (InterpolationFinished && VesselPositionSystem.TargetVesselUpdateQueue.TryGetValue(VesselId, out var queue) && queue.TryDequeue(out var targetUpdate)) { if (Target == null) { //We enter in this clause when it's the first iteration GameTimeStamp = targetUpdate.GameTimeStamp - TimeSpan.FromMilliseconds(SettingsSystem.ServerSettings.SecondaryVesselUpdatesMsInterval).TotalSeconds; PingMs = 0; CopyFrom(Vessel); } else { CopyFrom(Target); } CurrentFrame = 0; if (Target != null) { Target.CopyFrom(targetUpdate); VesselPositionSystem.TargetVesselUpdateQueue[VesselId].Recycle(targetUpdate); } else { Target = targetUpdate; } AdjustExtraInterpolationTimes(); if (Vessel) { Vessel.protoVessel?.UpdatePositionValues(Target); } InitializeOrbits(); } if (Target == null) { return; } try { //ALWAYS set the position of the vessel even if we don't have anything in the queue. Otherwise its position will shake Vessel.SetVesselPosition(this, Target, LerpPercentage); } catch (Exception e) { LunaLog.LogError($"ApplyInterpolations: {e}"); } finally { CurrentFrame++; } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is ScenarioBaseMsgData msgData)) { return; } if (msgData.ScenarioMessageType == ScenarioMessageType.Data) { var data = (ScenarioDataMsgData)msgData; for (var i = 0; i < data.ScenarioCount; i++) { var scenarioNode = ConfigNodeSerializer.Deserialize(data.ScenariosData[i].Data, data.ScenariosData[i].NumBytes); if (scenarioNode != null) { var entry = new ScenarioEntry { ScenarioName = data.ScenariosData[i].Module, ScenarioNode = scenarioNode }; System.ScenarioQueue.Enqueue(entry); } else { LunaLog.LogError($"[LMP]: Scenario data has been lost for {data.ScenariosData[i].Module}"); ScreenMessages.PostScreenMessage($"Scenario data has been lost for {data.ScenariosData[i].Module}", 5f, ScreenMessageStyle.UPPER_CENTER); } } MainSystem.NetworkState = ClientState.ScenariosSynced; } }
public static void IntroduceToServer(long currentEntryId) { var token = RandomString(10); var ownEndpoint = new IPEndPoint(LunaNetUtils.GetMyAddress(), NetworkMain.Config.Port); LunaLog.Log($"[LMP]: Sending NAT introduction to server. Token: {token}"); var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <MsIntroductionMsgData>(); msgData.Id = currentEntryId; msgData.Token = token; msgData.InternalEndpoint = Common.StringFromEndpoint(ownEndpoint); var introduceMsg = MstSrvMsgFactory.CreateNew <MainMstSrvMsg>(msgData); foreach (var masterServer in MasterServerEndpoints.Values.ToArray()) { try { var lidgrenMsg = masterServer.CreateMessage((int)introduceMsg.GetMessageSize()); introduceMsg.Serialize(lidgrenMsg); masterServer.SendMessage(lidgrenMsg, introduceMsg.NetDeliveryMethod); masterServer.FlushSendQueue(); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error connecting to server: {e}"); } } introduceMsg.Recycle(); }
private static bool PreSerializationChecks(ProtoVessel protoVessel, out ConfigNode configNode) { configNode = new ConfigNode(); if (protoVessel == null) { LunaLog.LogError("[LMP]: Cannot serialize a null protovessel"); return(false); } try { protoVessel.Save(configNode); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error while saving vessel: {e}"); return(false); } var vesselId = new Guid(configNode.GetValue("pid")); //Defend against NaN orbits if (VesselCommon.VesselHasNaNPosition(configNode)) { LunaLog.LogError($"[LMP]: Vessel {vesselId} has NaN position"); return(false); } //Do not send the maneuver nodes RemoveManeuverNodesFromProtoVessel(configNode); return(true); }
public void SendKerbal(ProtoCrewMember pcm) { if (pcm == null) { return; } if (VesselCommon.IsSpectating) { return; } if (pcm.type == ProtoCrewMember.KerbalType.Tourist) { //Don't send tourists LunaLog.Log($"[LMP]: Skipping sending of tourist: {pcm.name}"); return; } ConfigNode.ClearData(); pcm.Save(ConfigNode); var kerbalBytes = ConfigNodeSerializer.Serialize(ConfigNode); if (kerbalBytes == null || kerbalBytes.Length == 0) { LunaLog.LogError("[LMP]: Error sending kerbal - bytes are null or 0"); return; } SendKerbalProtoMessage(pcm.name, kerbalBytes); }
/// <summary> /// Send the definition of our own vessel and the secondary vessels. We only send them after an interval specified. /// If the other player vessels are far we don't send them very often. /// </summary> private void SendVesselDefinition() { try { if (ProtoSystemReady) { if (!VesselCommon.ActiveVesselIsInSafetyBubble()) { MessageSender.SendVesselMessage(FlightGlobals.ActiveVessel); } foreach (var vessel in VesselCommon.GetSecondaryVessels()) { MessageSender.SendVesselMessage(vessel); } ChangeRoutineExecutionInterval("SendVesselDefinition", VesselCommon.PlayerVesselsNearby() ? SettingsSystem.ServerSettings.VesselDefinitionSendMsInterval : SettingsSystem.ServerSettings.VesselDefinitionSendFarMsInterval); } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in SendVesselDefinition {e}"); } }
public void HandleMessage(IMessageData messageData) { var msgData = messageData as KerbalBaseMsgData; if (msgData == null) { return; } switch (msgData.KerbalMessageType) { case KerbalMessageType.Reply: HandleKerbalReply(msgData as KerbalReplyMsgData); break; case KerbalMessageType.Proto: //TODO: If a player connects and sends this type of message while still starting the game, the game crashes. //There should be a buffer for this messages so they are processed once the system is enabled HandleKerbalProto(msgData as KerbalProtoMsgData); break; default: LunaLog.LogError("[LMP]: Invalid Kerbal message type"); break; } }
/// <summary> /// Prints the banned parts message /// </summary> private void UpdateBannedPartsMessage() { try { if (ProtoSystemReady && !string.IsNullOrEmpty(BannedPartsStr)) { if (BannedPartsMessage != null) { BannedPartsMessage.duration = 0; } if (SystemsContainer.Get <ModSystem>().ModControl == ModControlMode.EnabledStopInvalidPartSync) { BannedPartsMessage = ScreenMessages.PostScreenMessage($"Active vessel contains the following banned parts, it will not be saved to the server:\n{BannedPartsStr}", 2f, ScreenMessageStyle.UPPER_CENTER); } if (SystemsContainer.Get <ModSystem>().ModControl == ModControlMode.EnabledStopInvalidPartLaunch) { BannedPartsMessage = ScreenMessages.PostScreenMessage($"Active vessel contains the following banned parts, you will be unable to launch on this server:\n{BannedPartsStr}", 2f, ScreenMessageStyle.UPPER_CENTER); } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in UpdateBannedPartsMessage {e}"); } }
/// <summary> /// Patches the methods defined in the XML with the transpiler /// </summary> public static void PatchFieldsAndMethods(Type partModule) { //If PartModule does not have any customization skip it if (!FieldModuleStore.CustomizedModuleBehaviours.TryGetValue(partModule.Name, out var customizationModule) || !customizationModule.CustomizedFields.Any()) { return; } foreach (var partModuleMethod in partModule.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) .Where(m => m.Name == "OnUpdate" || m.Name == "OnFixedUpdate" || m.Name == "FixedUpdate" || m.Name == "Update" || m.Name == "LateUpdate" || m.GetCustomAttributes(typeof(KSPAction), false).Any() || m.GetCustomAttributes(typeof(KSPEvent), false).Any(a => ((KSPEvent)a).guiActive))) { if (partModuleMethod.GetMethodBody() != null) { try { LunaLog.Log($"Patching method {partModuleMethod.Name} for field changes in module {partModule.Name} of assembly {partModule.Assembly.GetName().Name}"); HarmonyPatcher.HarmonyInstance.Patch(partModuleMethod, null, null, BackupAndCallTranspilerMethod); } catch (Exception ex) { LunaLog.LogError($"Could not patch method {partModuleMethod.Name} for field changes in module {partModule.Name} " + $"of assembly {partModule.Assembly.GetName().Name}. Details: {ex}"); HarmonyPatcher.HarmonyInstance.Patch(partModuleMethod, null, null, RestoreTranspilerMethod); } } } }
/// <summary> /// Loads/reloads a vessel into game /// </summary> public static bool LoadVessel(ProtoVessel vesselProto) { try { if (ProtoVesselValidationsPassed(vesselProto)) { CurrentlyLoadingVesselId = vesselProto.vesselID; FixProtoVesselFlags(vesselProto); GetLatestProtoVesselPosition(vesselProto); return(LoadVesselIntoGame(vesselProto)); } return(false); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error loading vessel: {e}"); return(false); } finally { CurrentlyLoadingVesselId = Guid.Empty; } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is KerbalBaseMsgData msgData)) { return; } switch (msgData.KerbalMessageType) { case KerbalMessageType.Remove: System.KerbalsToRemove.Enqueue(((KerbalRemoveMsgData)msgData).KerbalName); break; case KerbalMessageType.Reply: HandleKerbalReply(msgData as KerbalReplyMsgData); break; case KerbalMessageType.Proto: HandleKerbalProto(msgData as KerbalProtoMsgData); break; default: LunaLog.LogError("[LMP]: Invalid Kerbal message type"); break; } }
/// <summary> /// Convert a byte array to a ConfigNode. /// If anything goes wrong it will return null. /// </summary> private static ConfigNode ConvertByteArrayToConfigNode(byte[] data, int numBytes) { ConfigNode node; try { node = ConfigNodeSerializer.Deserialize(data, numBytes); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error while deserializing strategy configNode: {e}"); return(null); } if (node == null) { LunaLog.LogError("[LMP]: Error, the strategy configNode was null."); return(null); } if (!node.HasValue("isActive")) { LunaLog.LogError("[LMP]: Error, the strategy configNode is invalid (isActive missing)."); return(null); } return(node); }
/// <summary> /// Check vessels that must be loaded /// </summary> private void CheckVesselsToLoad() { try { if (ProtoSystemBasicReady && !VesselCommon.ActiveVesselIsInSafetyBubble()) { //Load vessels that don't exist, are in our subspace and out of safety bubble var vesselsToLoad = VesselsProtoStore.AllPlayerVessels .Where(v => !v.Value.VesselExist && v.Value.ShouldBeLoaded && !v.Value.IsInSafetyBubble); foreach (var vesselProto in vesselsToLoad) { if (VesselRemoveSystem.VesselWillBeKilled(vesselProto.Key)) { continue; } LunaLog.Log($"[LMP]: Loading vessel {vesselProto.Key}"); CurrentlyUpdatingVesselId = vesselProto.Key; if (VesselLoader.LoadVessel(vesselProto.Value.ProtoVessel)) { LunaLog.Log($"[LMP]: Vessel {vesselProto.Key} loaded"); } CurrentlyUpdatingVesselId = Guid.Empty; } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToLoad {e}"); } }
/// <summary> /// Call this method to scan all the PartModules and patch the methods /// </summary> public static void Awake() { if (_awakeTask != null) { return; } _awakeTask = Task.Run(() => { var partModules = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes() .Where(myType => myType.IsClass && myType.IsSubclassOf(typeof(PartModule)))) .ToArray(); Parallel.ForEach(partModules, partModule => { try { PartModulePatcher.PatchFieldsAndMethods(partModule); IncreasePercentage(1d / partModules.Length); } catch (Exception ex) { LunaLog.LogError($"Exception patching module {partModule.Name} from assembly {partModule.Assembly.GetName().Name}: {ex.Message}"); } }); }); _awakeTask.ConfigureAwait(false); }
public bool ParseModFile(ModControlStructure modFileData) { if (!ModSystem.Singleton.ModControl) { return(true); } System.ModControlData = modFileData; Sb.Length = 0; SaveCurrentModConfigurationFile(); SetAllPathsToLowercase(modFileData); if (!CheckFilesAndExpansions(modFileData)) { LunaLog.LogError("[LMP]: Mod check failed!"); LunaLog.LogError(Sb.ToString()); ModWindow.Singleton.Display = true; return(false); } System.AllowedParts = modFileData.AllowedParts; System.AllowedResources = modFileData.AllowedResources; LunaLog.Log("[LMP]: Mod check passed!"); return(true); }
/// <summary> /// Sends a mod Message. /// </summary> /// <param name="modName">Mod Name</param> /// <param name="messageData">The message payload</param> /// <param name="numBytes">Number of bytes to take from the array</param> /// <param name="relay">If set to <c>true</c>, The server will relay the Message to all other authenticated clients</param> public void SendModMessage(string modName, byte[] messageData, int numBytes, bool relay) { if (modName == null) { return; } if (messageData == null) { LunaLog.LogError($"[LMP]: {modName} attemped to send a null Message"); return; } var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <ModMsgData>(); if (msgData.Data.Length < numBytes) { msgData.Data = new byte[numBytes]; } Array.Copy(messageData, msgData.Data, numBytes); msgData.NumBytes = numBytes; msgData.Relay = relay; msgData.ModName = modName; MessageSender.SendMessage(msgData); }
public void SendKerbal(ProtoCrewMember pcm) { if (pcm == null) { return; } if (VesselCommon.IsSpectating) { return; } ConfigNode.ClearData(); pcm.Save(ConfigNode); var kerbalBytes = ConfigNode.Serialize(); if (kerbalBytes == null || kerbalBytes.Length == 0) { LunaLog.LogError("[LMP]: Error sending kerbal - bytes are null or 0"); return; } SendKerbalProtoMessage(pcm.name, kerbalBytes); }
/// <summary> /// Do some basic validations over the protovessel /// </summary> private static bool ProtoVesselValidationsPassed(ProtoVessel vesselProto) { if (vesselProto == null) { LunaLog.LogError("[LMP]: protoVessel is null!"); return(false); } if (vesselProto.vesselID == Guid.Empty) { LunaLog.LogError("[LMP]: protoVessel id is null!"); return(false); } if (vesselProto.situation == Vessel.Situations.FLYING) { if (vesselProto.orbitSnapShot == null) { LunaLog.LogWarning("[LMP]: Skipping flying vessel load - Protovessel does not have an orbit snapshot"); return(false); } if (FlightGlobals.Bodies == null || FlightGlobals.Bodies.Count < vesselProto.orbitSnapShot.ReferenceBodyIndex) { LunaLog.LogWarning($"[LMP]: Skipping flying vessel load - Could not find celestial body index {vesselProto.orbitSnapShot.ReferenceBodyIndex}"); return(false); } } return(true); }
/// <summary> /// Here we handle an unloaded flag and we load it into the game /// </summary> private void HandleFlag(ExtendedFlagInfo flagInfo) { //We have a flag with the same name! if (FlagExists(flagInfo.FlagName)) { return; } var flagTexture = new Texture2D(4, 4); if (flagTexture.LoadImage(flagInfo.FlagData)) { //Flags have names like: Squad/Flags/default flagTexture.name = flagInfo.FlagName; var textureInfo = new GameDatabase.TextureInfo(null, flagTexture, true, true, false) { name = flagInfo.FlagName }; GameDatabase.Instance.databaseTexture.Add(textureInfo); LunaLog.Log($"[LMP]: Loaded flag {flagTexture.name}"); } else { LunaLog.LogError($"[LMP]: Failed to load flag {flagInfo.FlagName}"); } }
/// <summary> /// Send a request to the master server to introduce us and do the nat punchtrough to the selected server /// </summary> public static void IntroduceToServer(long serverId) { if (Servers.TryGetValue(serverId, out var serverInfo)) { var serverEndpoint = Common.CreateEndpointFromString(serverInfo.ExternalEndpoint); if (ServerIsInLocalLan(serverEndpoint)) { LunaLog.Log("Server is in LAN. Skipping NAT punch"); NetworkConnection.ConnectToServer(serverEndpoint.Address.ToString(), serverEndpoint.Port, Password); } else { try { var token = RandomString(10); var ownEndpoint = new IPEndPoint(LunaNetUtils.GetMyAddress(), NetworkMain.Config.Port); var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <MsIntroductionMsgData>(); msgData.Id = serverId; msgData.Token = token; msgData.InternalEndpoint = Common.StringFromEndpoint(ownEndpoint); var introduceMsg = NetworkMain.MstSrvMsgFactory.CreateNew <MainMstSrvMsg>(msgData); LunaLog.Log($"[LMP]: Sending NAT introduction to server. Token: {token}"); NetworkSender.QueueOutgoingMessage(introduceMsg); } catch (Exception e) { LunaLog.LogError($"[LMP]: Error connecting to server: {e}"); } } } }
/// <summary> /// Check vessels that must be reloaded /// </summary> private void CheckVesselsToReload() { try { if (ProtoSystemBasicReady && !VesselCommon.ActiveVesselIsInSafetyBubble()) { //Reload vessels that exist var vesselsToReLoad = AllPlayerVessels .Where(pv => !pv.Value.Loaded && pv.Value.VesselExist) .ToArray(); foreach (var vesselProto in vesselsToReLoad) { if (SystemsContainer.Get <VesselRemoveSystem>().VesselWillBeKilled(vesselProto.Key)) { continue; } LunaLog.Log($"[LMP]: Reloading vessel {vesselProto.Key}"); if (VesselLoader.ReloadVessel(vesselProto.Value.ProtoVessel)) { vesselProto.Value.Loaded = true; LunaLog.Log($"[LMP]: Vessel {vesselProto.Key} reloaded"); UpdateVesselProtoInDictionary(vesselProto.Value); } } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToReload {e}"); } }