public static void DisconnectClient(ClientStructure client, string reason = "")
        {
            if (!string.IsNullOrEmpty(reason))
            {
                LunaLog.Debug($"{client.PlayerName} sent Connection end message, reason: {reason}");
            }

            //Remove Clients from list
            if (ServerContext.Clients.ContainsKey(client.Endpoint))
            {
                ServerContext.Clients.TryRemove(client.Endpoint, out client);
                LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ServerContext.Clients.Count}");
            }

            if (client.ConnectionStatus != ConnectionStatus.Disconnected)
            {
                client.ConnectionStatus = ConnectionStatus.Disconnected;
                LmpPluginHandler.FireOnClientDisconnect(client);
                if (client.Authenticated)
                {
                    var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <PlayerConnectionLeaveMsgData>();
                    msgData.PlayerName = client.PlayerName;

                    MessageQueuer.RelayMessage <PlayerConnectionSrvMsg>(client, msgData);
                    LockSystem.ReleasePlayerLocks(client);

                    if (!ServerContext.Clients.Any(c => c.Value.Subspace == client.Subspace))
                    {
                        WarpSystem.RemoveSubspace(client.Subspace);
                        VesselRelaySystem.RemoveSubspace(client.Subspace);
                    }
                }

                try
                {
                    client.Connection?.Disconnect(reason);
                }
                catch (Exception e)
                {
                    LunaLog.Debug($"Error closing client Connection: {e.Message}");
                }
                ServerContext.LastPlayerActivity = ServerContext.ServerClock.ElapsedMilliseconds;
            }
        }
        public static void DisconnectClient(ClientStructure client, string reason = "")
        {
            if (!string.IsNullOrEmpty(reason))
            {
                LunaLog.Debug($"{client.PlayerName} sent Connection end message, reason: {reason}");
            }

            //Remove Clients from list
            if (ServerContext.Clients.ContainsKey(client.Endpoint))
            {
                ServerContext.Clients.TryRemove(client.Endpoint, out client);
                LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ServerContext.Clients.Count}");
            }

            if (client.ConnectionStatus != ConnectionStatus.Disconnected)
            {
                client.ConnectionStatus = ConnectionStatus.Disconnected;
                LmpPluginHandler.FireOnClientDisconnect(client);
                if (client.Authenticated)
                {
                    var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <PlayerConnectionLeaveMsgData>();
                    msgData.PlayerName = client.PlayerName;

                    MessageQueuer.RelayMessage <PlayerConnectionSrvMsg>(client, msgData);
                    LockSystem.ReleasePlayerLocks(client);
                    WarpSystem.RemoveSubspace(client.Subspace);
                }

                try
                {
                    client.Connection?.Disconnect(reason);
                }
                catch (Exception e)
                {
                    LunaLog.Error($"Error closing client Connection: {e.Message}");
                }
            }

            //As this is the last client that is connected to the server, run a safety backup once they disconnect
            if (ServerContext.Clients.Count == 0)
            {
                BackupSystem.RunBackup();
            }
        }
        /// <summary>
        /// This method should be called in a thread.
        /// It runs over the old messages and sends them once the subspace time matches the message send time.
        /// </summary>
        public static async void RelayOldVesselMessages()
        {
            while (ServerContext.ServerRunning)
            {
                var messagesByGroup = DbCollection.FindAll().GroupBy(m => m.SubspaceId);
                foreach (var subspace in messagesByGroup)
                {
                    var subspaceTime = WarpSystem.GetCurrentSubspaceTime(subspace.Key);
                    var msgToSend    = subspace.Where(m => subspaceTime >= m.Msg.SentTime).ToList();
                    msgToSend.ForEach(m =>
                    {
                        MessageQueuer.SendMessageToSubspace <VesselSrvMsg>(m.Msg, m.SubspaceId);
                        DbCollection.Delete(m.Id);
                    });
                }

                DataBase.Shrink();
                await Task.Delay(IntervalSettings.SettingsStore.SendReceiveThreadTickMs);
            }
        }
Example #4
0
        /// <summary>
        /// This method relays a message to the other clients in the same subspace.
        /// In case there are other players in OLDER subspaces it stores it in their queue for further processing
        /// </summary>
        public static void HandleVesselMessage(ClientStructure client, dynamic msg)
        {
            if (client.Subspace == -1)
            {
                return;
            }

            var vesselId = (Guid)msg.VesselId;
            var gameTime = (double)msg.GameTime;

            MessageQueuer.RelayMessageToSubspace <VesselSrvMsg>(client, msg);

            if (GeneralSettings.SettingsStore.ShowVesselsInThePast)
            {
                //Here we send this update to all the players in the FUTURE
                foreach (var subspace in WarpSystem.GetFutureSubspaces(client.Subspace))
                {
                    MessageQueuer.RelayMessageToSubspace <VesselSrvMsg>(client, msg, subspace);
                }
            }

            //In case the client is running in the future here we adjust the real sent time of the message
            msg.SentTime += WarpSystem.GetSubspaceTimeDifference(client.Subspace);
            foreach (var subspace in WarpSystem.GetPastSubspaces(client.Subspace))
            {
                var vesselsAndQueues = OldSubspaceVesselMessages.GetOrAdd(subspace, new ConcurrentDictionary <Guid, ConcurrentQueue <VesselRelayItem> >());
                var vesselQueue      = vesselsAndQueues.GetOrAdd(vesselId, new ConcurrentQueue <VesselRelayItem>());

                //This is the case when a user reverted (the message received has a game time LOWER than the last message received).
                //To handle this, we remove all the messages that we received UNTIL this revert.
                if (vesselQueue.LastOrDefault()?.GameTime > gameTime)
                {
                    while (vesselQueue.TryPeek(out var peekValue) && peekValue.GameTime > gameTime)
                    {
                        vesselQueue.TryDequeue(out _);
                    }
                }

                vesselQueue.Enqueue(new VesselRelayItem(subspace, vesselId, gameTime, msg));
            }
        }
Example #5
0
        /// <summary>
        /// This method should be called in a thread.
        /// It runs over the old messages and sends them once the subspace time matches the message send time.
        /// </summary>
        public static async void RelayOldVesselMessages()
        {
            while (ServerContext.ServerRunning)
            {
                foreach (var subspaceVessels in OldSubspaceVesselMessages.Where(m => !m.Value.IsEmpty))
                {
                    var subspaceTime = WarpSystem.GetCurrentSubspaceTime(subspaceVessels.Key);

                    foreach (var queue in subspaceVessels.Value)
                    {
                        while (queue.Value.TryPeek(out var relayItem) && subspaceTime >= relayItem.Msg.SentTime)
                        {
                            queue.Value.TryDequeue(out relayItem);
                            MessageQueuer.SendMessageToSubspace <VesselSrvMsg>(relayItem?.Msg, subspaceVessels.Key);
                        }
                    }
                }

                await Task.Delay(GeneralSettings.SettingsStore.SendReceiveThreadTickMs);
            }
        }
Example #6
0
        public void HandleMessage(IServerMessageBase msg)
        {
            if (!(msg.Data is VesselDockMsgData msgData))
            {
                return;
            }

            LunaLog.Log("Docking message received!");

            if (msgData.WeakVesselId == CurrentDockEvent.WeakVesselId && msgData.DominantVesselId == CurrentDockEvent.DominantVesselId &&
                (LunaNetworkTime.UtcNow - CurrentDockEvent.DockingTime) < TimeSpan.FromSeconds(5))
            {
                LunaLog.Log("Docking message received was detected so ignore it");
                return;
            }

            var dominantProto = VesselSerializer.DeserializeVessel(msgData.FinalVesselData, msgData.NumBytes);

            VesselLoader.LoadVessel(dominantProto);

            WarpSystem.WarpIfSubspaceIsMoreAdvanced(msgData.SubspaceId);

            if (FlightGlobals.ActiveVessel && FlightGlobals.ActiveVessel.id == msgData.WeakVesselId)
            {
                LunaLog.Log($"Docking NOT detected. We DON'T OWN the dominant vessel. Switching to {msgData.DominantVesselId}");
                if (dominantProto.vesselRef != null)
                {
                    dominantProto.vesselRef.Load();
                    dominantProto.vesselRef.GoOffRails();
                    FlightGlobals.ForceSetActiveVessel(dominantProto.vesselRef);
                }
            }
            else if (FlightGlobals.ActiveVessel && FlightGlobals.ActiveVessel.id == msgData.DominantVesselId)
            {
                LunaLog.Log("Docking NOT detected. We OWN the dominant vessel");
            }

            VesselRemoveSystem.Singleton.KillVessel(msgData.WeakVesselId, "Killing weak (active) vessel during a docking that was not detected");
            CurrentDockEvent.Reset();
        }
Example #7
0
        /// <summary>
        /// This method relays a message to the other clients in the same subspace.
        /// In case there are other players in OLDER subspaces it stores it in their queue for further processing
        /// </summary>
        public static void HandleVesselMessage(ClientStructure client, dynamic msg)
        {
            if (client.Subspace == -1)
            {
                return;
            }

            var vesselId = (Guid)msg.VesselId;
            var gameTime = (double)msg.GameTime;

            MessageQueuer.RelayMessageToSubspace <VesselSrvMsg>(client, msg);

            if (GeneralSettings.SettingsStore.ShowVesselsInThePast)
            {
                foreach (var subspace in WarpSystem.GetFutureSubspaces(client.Subspace))
                {
                    MessageQueuer.RelayMessageToSubspace <VesselSrvMsg>(client, msg, subspace);
                }
            }

            //The client is running in the future so here we adjust the real sent time of the message
            msg.SentTime += WarpSystem.GetSubspaceTimeDifference(client.Subspace);
            foreach (var subspace in WarpSystem.GetPastSubspaces(client.Subspace))
            {
                //This is the case when a user reverted (the message received has a game time LOWER than the last message received).
                //To handle this, we remove all the messages that we received UNTIL this revert.
                if (DbCollection.Exists(x => x.VesselId == vesselId && x.GameTime > gameTime))
                {
                    DbCollection.Delete(x => x.VesselId == vesselId && x.GameTime > gameTime);
                    DataBase.Shrink();
                }

                DbCollection.Insert(new VesselRelayDbItem(subspace, vesselId, gameTime, msg));
            }

            DbCollection.EnsureIndex(x => x.Id);
            DbCollection.EnsureIndex(x => x.SubspaceId);
            DbCollection.EnsureIndex(x => x.VesselId);
            DbCollection.EnsureIndex(x => x.GameTime);
        }
Example #8
0
        public static void Main()
        {
            try
            {
                Console.Title = $"LMP {LmpVersioning.CurrentVersion}";

                Console.OutputEncoding  = Encoding.Unicode;
                ServerContext.StartTime = LunaNetworkTime.UtcNow.Ticks;

                LunaLog.Info("Remember! Quit the server by using 'Control + C' so a backup is properly made before closing!");

                if (Common.PlatformIsWindows())
                {
                    ExitSignal.Exit += (sender, args) => Exit();
                }
                else
                {
                    //Register the ctrl+c event and exit signal if we are on linux
                    Console.CancelKeyPress += (sender, args) => Exit();
                }

                //We disable quick edit as otherwise when you select some text for copy/paste then you can't write to the console and server freezes
                //This just happens on windows....
                if (Common.PlatformIsWindows())
                {
                    ConsoleUtil.DisableConsoleQuickEdit();
                }

                //We cannot run more than 6 instances ofd servers + clients as otherwise the sync time will fail (30 seconds / 5 seconds = 6) but we use 3 for safety
                if (GetRunningInstances() > 3)
                {
                    throw new HandledException("Cannot run more than 3 servers at a time!");
                }

                //Start the server clock
                ServerContext.ServerClock.Start();

                ServerContext.ServerStarting = true;

                //Set day for log change
                ServerContext.Day = LunaNetworkTime.Now.Day;

                LunaLog.Normal($"Luna Server version: {LmpVersioning.CurrentVersion} ({Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)})");

                Universe.CheckUniverse();
                LoadSettingsAndGroups();
                VesselStoreSystem.LoadExistingVessels();
                var scenariosCreated = ScenarioSystem.GenerateDefaultScenarios();
                ScenarioStoreSystem.LoadExistingScenarios(scenariosCreated);
                LmpPluginHandler.LoadPlugins();
                WarpSystem.Reset();

                LunaLog.Normal($"Starting '{GeneralSettings.SettingsStore.ServerName}' on Port {ConnectionSettings.SettingsStore.Port}... ");

                LidgrenServer.SetupLidgrenServer();
                LmpPortMapper.OpenLmpPort().Wait();
                LmpPortMapper.OpenWebPort().Wait();
                ServerContext.ServerRunning = true;
                WebServer.StartWebServer();

                //Do not add the command handler thread to the TaskContainer as it's a blocking task
                LongRunTaskFactory.StartNew(CommandHandler.ThreadMain, CancellationTokenSrc.Token);

                TaskContainer.Add(LongRunTaskFactory.StartNew(WebServer.RefreshWebServerInformation, CancellationTokenSrc.Token));

                TaskContainer.Add(LongRunTaskFactory.StartNew(LmpPortMapper.RefreshUpnpPort, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(LogThread.RunLogThread, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(ClientMainThread.ThreadMain, CancellationTokenSrc.Token));

                TaskContainer.Add(LongRunTaskFactory.StartNew(() => BackupSystem.PerformBackups(CancellationTokenSrc.Token), CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenServer.StartReceivingMessages, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenMasterServer.RegisterWithMasterServer, CancellationTokenSrc.Token));

                TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.RefreshLatestVersion, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.DisplayNewVersionMsg, CancellationTokenSrc.Token));

                while (ServerContext.ServerStarting)
                {
                    Thread.Sleep(500);
                }

                LunaLog.Normal("All systems up and running. Поехали!");
                LmpPluginHandler.FireOnServerStart();

                QuitEvent.WaitOne();

                LmpPluginHandler.FireOnServerStop();

                LunaLog.Normal("So long and thanks for all the fish!");
            }
            catch (Exception e)
            {
                LunaLog.Fatal(e is HandledException ? e.Message : $"Error in main server thread, Exception: {e}");
                Console.ReadLine(); //Avoid closing automatically
            }
        }
Example #9
0
        public static void Main()
        {
            try
            {
                Console.Title = $"LMPServer {LmpVersioning.CurrentVersion}";
#if DEBUG
                Console.Title += " DEBUG";
#endif
                Console.OutputEncoding  = Encoding.Unicode;
                ServerContext.StartTime = LunaTime.UtcNow.Ticks;

                if (!Common.PlatformIsWindows())
                {
                    LunaLog.Warning("Remember! Quit the server by using Control+C so the vessels are saved to the hard drive!");
                }


                if (Common.PlatformIsWindows())
                {
                    ExitSignal.Exit += (sender, args) => Exit();
                }
                else
                {
                    //Register the ctrl+c event and exit signal if we are on linux
                    Console.CancelKeyPress += (sender, args) => Exit();
                }

                //We disable quick edit as otherwise when you select some text for copy/paste then you can't write to the console and server freezes
                //This just happens on windows....
                if (Common.PlatformIsWindows())
                {
                    ConsoleUtil.DisableConsoleQuickEdit();
                }

                //We cannot run more than 6 instances ofd servers + clients as otherwise the sync time will fail (30 seconds / 5 seconds = 6) but we use 3 for safety
                if (GetRunningInstances() > 3)
                {
                    throw new HandledException("Cannot run more than 3 servers at a time!");
                }

                //Start the server clock
                ServerContext.ServerClock.Start();

                //Set the last player activity time to server start
                ServerContext.LastPlayerActivity = ServerContext.ServerClock.ElapsedMilliseconds;

                ServerContext.ServerStarting = true;

                //Set day for log change
                ServerContext.Day = LunaTime.Now.Day;

                LunaLog.Normal($"Starting Luna Server version: {LmpVersioning.CurrentVersion}");

                Universe.CheckUniverse();
                LoadSettingsAndGroups();
                VesselStoreSystem.LoadExistingVessels();
                ScenarioSystem.GenerateDefaultScenarios();
                ScenarioStoreSystem.LoadExistingScenarios();
                LmpPluginHandler.LoadPlugins();
                WarpSystem.Reset();

                LunaLog.Normal($"Starting {GeneralSettings.SettingsStore.WarpMode} server on Port {GeneralSettings.SettingsStore.Port}... ");
                LunaLog.Normal($"Server name: '{GeneralSettings.SettingsStore.ServerName}'...");
                LunaLog.Normal($"Server location: '{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}'...");

                ServerContext.ServerRunning = true;
                LidgrenServer.SetupLidgrenServer();

                //Do not add the command handler thread to the TaskContainer as it's a blocking task
                LongRunTaskFactory.StartNew(() => new CommandHandler().ThreadMain(), CancellationTokenSrc.Token);

                TaskContainer.Add(LongRunTaskFactory.StartNew(LogThread.RunLogThread, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(() => new ClientMainThread().ThreadMain(), CancellationTokenSrc.Token));

                TaskContainer.Add(LongRunTaskFactory.StartNew(() => BackupSystem.PerformBackups(CancellationTokenSrc.Token), CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenServer.StartReceiveingMessages, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenMasterServer.RefreshMasterServersList, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenMasterServer.RegisterWithMasterServer, CancellationTokenSrc.Token));

                TaskContainer.Add(LongRunTaskFactory.StartNew(VesselRelaySystem.RelayOldVesselMessages, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.RefreshLatestVersion, CancellationTokenSrc.Token));
                TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.DisplayNewVersionMsg, CancellationTokenSrc.Token));

                while (ServerContext.ServerStarting)
                {
                    Thread.Sleep(500);
                }

                LunaLog.Normal("All systems up and running. Поехали!");
                LmpPluginHandler.FireOnServerStart();

                QuitEvent.WaitOne();

                LmpPluginHandler.FireOnServerStop();

                LunaLog.Normal("So long and thanks for all the fish!");
            }
            catch (Exception e)
            {
                if (e is HandledException)
                {
                    LunaLog.Fatal(e.Message);
                }
                else
                {
                    LunaLog.Fatal($"Error in main server thread, Exception: {e}");
                }
                Console.ReadLine(); //Avoid closing automatically
            }
        }
Example #10
0
        public static void Main()
        {
            try
            {
                Console.Title = $"LMPServer {LmpVersioning.CurrentVersion}";
#if DEBUG
                Console.Title += " DEBUG";
#endif
                Console.OutputEncoding  = Encoding.Unicode;
                ServerContext.StartTime = LunaTime.UtcNow.Ticks;

                //We disable quick edit as otherwise when you select some text for copy/paste then you can't write to the console and server freezes
                //This just happens on windows....
                if (Common.PlatformIsWindows())
                {
                    ConsoleUtil.DisableConsoleQuickEdit();
                }

                //We cannot run more than 6 instances ofd servers + clients as otherwise the sync time will fail (30 seconds / 5 seconds = 6) but we use 3 for safety
                if (GetRunningInstances() > 3)
                {
                    throw new HandledException("Cannot run more than 3 servers at a time!");
                }

                //Start the server clock
                ServerContext.ServerClock.Start();

                //Set the last player activity time to server start
                ServerContext.LastPlayerActivity = ServerContext.ServerClock.ElapsedMilliseconds;

                //Register the ctrl+c event
                Console.CancelKeyPress      += CatchExit;
                ServerContext.ServerStarting = true;

                //Set day for log change
                ServerContext.Day = LunaTime.Now.Day;

                LunaLog.Normal($"Starting Luna Server version: {LmpVersioning.CurrentVersion}");

                Universe.CheckUniverse();
                LoadSettingsAndGroups();
                LmpPluginHandler.LoadPlugins();
                WarpSystem.Reset();
                ChatSystem.Reset();

                LunaLog.Normal($"Starting {GeneralSettings.SettingsStore.WarpMode} server on Port {GeneralSettings.SettingsStore.Port}... ");

                ServerContext.ServerRunning = true;
                ServerContext.LidgrenServer.SetupLidgrenServer();

                Task.Run(() => new CommandHandler().ThreadMain());
                Task.Run(() => new ClientMainThread().ThreadMain());

                Task.Run(() => ServerContext.LidgrenServer.StartReceiveingMessages());
                Task.Run(() => ServerContext.LidgrenServer.RefreshMasterServersList());
                Task.Run(() => ServerContext.LidgrenServer.RegisterWithMasterServer());
                Task.Run(() => LogThread.RunLogThread());

                Task.Run(() => VesselRelaySystem.RelayOldVesselMessages());
                Task.Run(() => VesselUpdateRelaySystem.RelayToFarPlayers());
                Task.Run(() => VesselUpdateRelaySystem.RelayToMediumDistancePlayers());
                Task.Run(() => VesselUpdateRelaySystem.RelayToClosePlayers());
                Task.Run(() => VersionChecker.CheckForNewVersions());

                while (ServerContext.ServerStarting)
                {
                    Thread.Sleep(500);
                }

                LunaLog.Normal("All systems up and running. Поехали!");
                LmpPluginHandler.FireOnServerStart();

                QuitEvent.WaitOne();

                WarpSystem.SaveSubspacesToFile();
                LmpPluginHandler.FireOnServerStop();

                LunaLog.Normal("Goodbye and thanks for all the fish!");
            }
            catch (Exception e)
            {
                if (e is HandledException)
                {
                    LunaLog.Fatal(e.Message);
                }
                else
                {
                    LunaLog.Fatal($"Error in main server thread, Exception: {e}");
                }
                Console.ReadLine(); //Avoid closing automatically
            }
        }
        public void HandleMessage(IServerMessageBase msg)
        {
            if (!(msg.Data is VesselDockMsgData msgData))
            {
                return;
            }

            LunaLog.Log("Docking message received!");

            //Add the new vessel data to the store
            VesselsProtoStore.HandleVesselProtoData(msgData.FinalVesselData, msgData.NumBytes, msgData.DominantVesselId, false);

            if (FlightGlobals.ActiveVessel?.id == msgData.WeakVesselId)
            {
                LunaLog.Log($"Docking NOT detected. We DON'T OWN the dominant vessel. Switching to {msgData.DominantVesselId}");

                VesselRemoveSystem.Singleton.AddToKillList(FlightGlobals.ActiveVessel.id, "Killing weak (active) vessel during a docking that was not detected");
                VesselSwitcherSystem.Singleton.SwitchToVessel(msgData.DominantVesselId);

                WarpSystem.WarpIfSubspaceIsMoreAdvanced(msgData.SubspaceId);
            }
            if (FlightGlobals.ActiveVessel?.id == msgData.DominantVesselId && !VesselCommon.IsSpectating)
            {
                var newProto = VesselSerializer.DeserializeVessel(msgData.FinalVesselData, msgData.NumBytes);

                /* This is a strange case were we didn't detect the docking on time and the weak vessel send the new definition...
                 * Usually it happens when a vessel in a future subspace docks with a vessel in the past and the vessel in the past is the dominant vessel
                 * The reason why is bad is because the ModuleDockingNode sent by the WEAK vessel will tell us that we are
                 * NOT the dominant (because we received the vesselproto from the WEAK vessel) so we won't be able to undock properly...
                 * This will be fixed if we go to the space center and reload again the vessel...
                 */
                LunaLog.Log("Docking NOT detected. We OWN the dominant vessel");

                //This is the case when the user that docked with us has invalid parts
                if (VesselCommon.ProtoVesselHasInvalidParts(newProto))
                {
                    return;
                }

                if (FlightGlobals.FindVessel(msgData.WeakVesselId) != null)
                {
                    LunaLog.Log($"Weak vessel {msgData.WeakVesselId} still exists in our game. Removing it now");
                    VesselRemoveSystem.Singleton.AddToKillList(msgData.WeakVesselId, "Killing weak vessel during a docking that was not detected");
                    VesselRemoveSystem.Singleton.KillVessel(msgData.WeakVesselId, "Weak vessel in a docking");
                }

                /* We own the dominant vessel and dind't detected the docking event so we need to reload our OWN vessel
                 * so if we send our own protovessel later, we send the updated definition
                 */
                LunaLog.Log($"Creating the missing parts in our own vessel. Current: {FlightGlobals.ActiveVessel.parts.Count} Expected: {newProto.protoPartSnapshots.Count}");
                //ProtoToVesselRefresh.CreateMissingPartsInCurrentProtoVessel(FlightGlobals.ActiveVessel, newProto);
                VesselLoader.ReloadVessel(newProto);

                LunaLog.Log("Force sending the new proto vessel");
                VesselProtoSystem.Singleton.MessageSender.SendVesselMessage(FlightGlobals.ActiveVessel, true, false);

                WarpSystem.WarpIfSubspaceIsMoreAdvanced(msgData.SubspaceId);
                return;
            }

            //Some other 2 players docked so just remove the weak vessel.
            VesselRemoveSystem.Singleton.AddToKillList(msgData.WeakVesselId, "Killing weak vessel during a docking of 2 far players");
        }