Esempio n. 1
0
        /// <summary>
        /// Runs the restart logic
        /// </summary>
        public static void Restart()
        {
            //Perform Backups
            BackupSystem.PerformBackups(CancellationTokenSrc.Token);
            LunaLog.Normal("Restarting...  Please wait until all threads are finished");

            ServerContext.Shutdown("Server is restarting");
            CancellationTokenSrc.Cancel();

            Task.WaitAll(TaskContainer.ToArray());
            QuitEvent.Set();

            //Start new server
            var serverExePath    = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\Server.exe";
            var newProcLmpServer = new ProcessStartInfo {
                FileName = serverExePath
            };

            Process.Start(newProcLmpServer);
        }
Esempio n. 2
0
        /// <summary>
        /// We receive the console inputs with a pipe
        /// </summary>
        public static async void ThreadMain()
        {
            try
            {
                while (ServerContext.ServerRunning)
                {
                    var input = Console.ReadLine();
                    if (input == null)
                    {
                        LunaLog.Normal("End of stdin, stopping command listener");
                        break;
                    }
                    if (!string.IsNullOrEmpty(input))
                    {
                        LunaLog.Normal($"Command input: {input}");
                        if (!string.IsNullOrEmpty(input))
                        {
                            if (input.StartsWith("/"))
                            {
                                HandleServerInput(input.Substring(1));
                            }
                            else
                            {
                                Commands["say"].Func(input);
                            }
                        }
                    }

                    //We only accept a command once every 500ms
                    await Task.Delay(500);
                }
            }
            catch (Exception e)
            {
                if (ServerContext.ServerRunning && !(e is ThreadAbortException))
                {
                    LunaLog.Fatal($"Error in command handler thread, Exception: {e}");
                    throw;
                }
            }
        }
Esempio n. 3
0
        //Changes selected server option
        private static void ChangeServerSettings(string settingName, string newValue, StreamReader streamReader, XmlDocument document, string settingsPath)
        {
            //Set message
            var msgSettingNameInfo = Environment.NewLine + "Setting name error:"
                                     + Environment.NewLine + "'" + settingName + "'"
                                     + Environment.NewLine + "is not a valid setting name."
                                     + Environment.NewLine + "Setting name is case sensitive.";

            //Load document
            document.Load(streamReader);
            //Try to find the xml node and save the new value to setting file
            try
            {
                //Get node
                var nodeSetting = document.SelectSingleNode("//" + settingName);
                //Return if null
                if (nodeSetting == null)
                {
                    LunaLog.Error(msgSettingNameInfo);
                    return;
                }
                //Change node inner text
                if (newValue == "-")
                {
                    nodeSetting.InnerText = "";
                }
                else
                {
                    nodeSetting.InnerText = newValue;
                }
                //Save document
                SaveDocument(streamReader, document, settingsPath);
                //Send info message that setting has changed
                LunaLog.Normal(Environment.NewLine + "Setting changes saved." + Environment.NewLine + "You may need to restart the server for the changes to take effect.");
            }
            catch (Exception)
            {
                LunaLog.Error(msgSettingNameInfo);
                return;
            }
        }
Esempio n. 4
0
        public void HandleHandshakeResponse(ClientStructure client, HandshakeResponseMsgData data)
        {
            var valid = CheckServerFull(client);

            valid &= valid && CheckUsernameLength(client, data.PlayerName);
            valid &= valid && CheckUsernameCharacters(client, data.PlayerName);
            valid &= valid && CheckWhitelist(client, data.PlayerName);
            valid &= valid && CheckPlayerIsAlreadyConnected(client, data.PlayerName);
            valid &= valid && CheckUsernameIsReserved(client, data.PlayerName);
            valid &= valid && CheckPlayerIsBanned(client, data.PlayerName, client.Endpoint.Address.ToString(), data.PublicKey);
            valid &= valid && CheckKey(client, data.PlayerName, data.PublicKey, data.ChallengeSignature);

            if (!valid)
            {
                LunaLog.Normal($"Client {data.PlayerName} failed to handshake: {Reason}. Disconnecting");
                client.DisconnectClient = true;
                ClientConnectionHandler.DisconnectClient(client, Reason);
            }
            else
            {
                client.PlayerName    = data.PlayerName;
                client.PublicKey     = data.PublicKey;
                client.Id            = Guid.NewGuid();
                client.Authenticated = true;

                LmpPluginHandler.FireOnClientAuthenticated(client);

                LunaLog.Normal($"Client {data.PlayerName} handshook successfully, Version: {data.MajorVersion}.{data.MinorVersion}.{data.BuildVersion}");

                CreatePlayerScenarioFiles(client, data.PlayerName);

                HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.HandshookSuccessfully, "success");

                var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <PlayerConnectionJoinMsgData>();
                msgData.PlayerName = client.PlayerName;

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

                LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ClientRetriever.GetClients().Length}");
            }
        }
Esempio n. 5
0
        private static void SendNetworkMessage(ClientStructure client, IServerMessageBase message)
        {
            if (client.ConnectionStatus == ConnectionStatus.CONNECTED)
            {
                try
                {
                    ServerContext.LidgrenServer.SendMessageToClient(client, message);
                }
                catch (Exception e)
                {
                    ClientException.HandleDisconnectException("Send network message error: ", client, e);
                    return;
                }
            }
            else
            {
                LunaLog.Normal($"Tried to send a message to client {client.PlayerName}, with connection status: {client.ConnectionStatus}");
            }

            LmpPluginHandler.FireOnMessageSent(client, message);
        }
Esempio n. 6
0
        private static void CheckMasterServerListed()
        {
            var ownAddress = LunaNetUtils.GetOwnExternalIpAddress();

            if (ownAddress != null)
            {
                var ownEndpoint = new IPEndPoint(ownAddress, Port);
                if (!MasterServerRetriever.MasterServers.Contains(ownEndpoint))
                {
                    LunaLog.Error($"You're not listed in the master servers list ({RepoConstants.MasterServersListShortUrl}). Clients/Servers won't see you");
                }
                else
                {
                    LunaLog.Normal("You're correctly listed in the master servers list");
                }
            }
            else
            {
                LunaLog.Error("Could not retrieve own external IP address, master server likely won't function properly");
            }
        }
Esempio n. 7
0
        private static void RemoveExpiredServers()
        {
            Task.Run(async() =>
            {
                while (RunServer)
                {
                    var serversIdsToRemove = ServerDictionary
                                             .Where(s => LunaNetworkTime.UtcNow.Ticks - s.Value.LastRegisterTime >
                                                    TimeSpan.FromMilliseconds(ServerMsTimeout).Ticks ||
                                                    BannedIpsRetriever.IsBanned(s.Value.ExternalEndpoint))
                                             .ToArray();

                    foreach (var serverId in serversIdsToRemove)
                    {
                        LunaLog.Normal($"REMOVING SERVER: {serverId.Value.ExternalEndpoint}");
                        ServerDictionary.TryRemove(serverId.Key, out _);
                    }

                    await Task.Delay(ServerRemoveMsCheckInterval);
                }
            });
        }
        public override void HandleMessage(ClientStructure client, IClientMessageBase message)
        {
            var data = (FacilityBaseMsgData)message.Data;
            switch (data.FacilityMessageType)
            {
                case FacilityMessageType.Upgrade:
                    var upgradeMsg = (FacilityUpgradeMsgData)message.Data;
                    LunaLog.Normal($"{client.PlayerName} UPGRADED facility {upgradeMsg.ObjectId} to level: {upgradeMsg.Level}");
                    break;
                case FacilityMessageType.Repair:
                    LunaLog.Normal($"{client.PlayerName} REPAIRED facility {data.ObjectId}");
                    break;
                case FacilityMessageType.Collapse:
                    LunaLog.Normal($"{client.PlayerName} DESTROYED facility {data.ObjectId}");
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            //We don't do anything on the server side with this messages so just relay them.
            MessageQueuer.RelayMessage<FacilitySrvMsg>(client, message.Data);
        }
Esempio n. 9
0
        public override void Execute(string commandArgs)
        {
            CommandSystemHelperMethods.SplitCommand(commandArgs, out var ip, out var reason);
            reason = string.IsNullOrEmpty(reason) ? "No reason specified" : reason;

            if (IPAddress.TryParse(ip, out var ipAddress))
            {
                var player = ClientRetriever.GetClientByIp(ipAddress);

                if (player != null)
                {
                    MessageQueuer.SendConnectionEnd(player, $"You were banned from the server: {reason}");
                }

                Add(ipAddress.ToString());
                LunaLog.Normal($"IP Address '{ip}' was banned from the server: {reason}");
            }
            else
            {
                LunaLog.Normal($"{ip} is not a valid IP address");
            }
        }
Esempio n. 10
0
        public override void Execute(string commandArgs)
        {
            CommandSystemHelperMethods.SplitCommand(commandArgs, out var playerName, out var reason);
            reason = string.IsNullOrEmpty(reason) ? "No reason specified" : reason;

            if (!string.IsNullOrEmpty(playerName))
            {
                var player = ClientRetriever.GetClientByName(playerName);

                if (player != null)
                {
                    MessageQueuer.SendConnectionEnd(player, $"You were banned from the server: {reason}");
                }

                Add(playerName);
                LunaLog.Normal($"Player '{playerName}' was banned from the server: {reason}");
            }
            else
            {
                LunaLog.Normal($"Player: {playerName} not found");
            }
        }
        public override void HandleMessage(ClientStructure client, IClientMessageBase message)
        {
            var data = (FacilityBaseMsgData)message.Data;

            switch (data.FacilityMessageType)
            {
            case FacilityMessageType.Repair:
                LunaLog.Normal($"{client.PlayerName} REPAIRED facility {data.ObjectId}");
                ScenarioDataUpdater.WriteRepairedDestroyedDataToFile(data.ObjectId, true);
                break;

            case FacilityMessageType.Collapse:
                LunaLog.Normal($"{client.PlayerName} DESTROYED facility {data.ObjectId}");
                ScenarioDataUpdater.WriteRepairedDestroyedDataToFile(data.ObjectId, false);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            //We don't do anything on the server side with this messages so just relay them.
            MessageQueuer.RelayMessage <FacilitySrvMsg>(client, message.Data);
        }
Esempio n. 12
0
        private static void LoadSettingsAndGroups()
        {
            LunaLog.Normal("Loading groups...");
            GroupSystem.LoadGroups();
            LunaLog.Normal("Loading settings...");
            SettingsHandler.LoadSettings();
            ServerContext.ConfigsLoaded = true;
            SettingsHandler.ValidateDifficultySettings();

            if (GeneralSettings.SettingsStore.ModControl)
            {
                LunaLog.Normal("Loading mod control...");
                ModFileSystem.LoadModFile();
            }

            if (Common.PlatformIsWindows())
            {
                Console.Title += $" ({GeneralSettings.SettingsStore.ServerName})";
#if DEBUG
                Console.Title += " DEBUG";
#endif
            }
        }
Esempio n. 13
0
        public override void HandleCommand(string commandArgs)
        {
            CommandSystemHelperMethods.SplitCommand(commandArgs, out var func, out var playerName);

            switch (func)
            {
            default:
                LunaLog.Normal("Undefined function. Usage: /admin [add|del] playername or /admin show");
                break;

            case "add":
                AdminAddCommand.Execute(playerName);
                break;

            case "del":
                AdminRemoveCommand.Execute(playerName);
                break;

            case "show":
                AdminShowCommand.Execute("");
                break;
            }
        }
Esempio n. 14
0
        public override void Execute(string commandArgs)
        {
            CommandSystemHelperMethods.SplitCommand(commandArgs, out var playerName, out var reason);
            reason = string.IsNullOrEmpty(reason) ? "No reason specified" : reason;

            if (playerName != "")
            {
                var player = ClientRetriever.GetClientByName(playerName);
                if (player != null)
                {
                    LunaLog.Normal($"Kicking {playerName} from the server");
                    MessageQueuer.SendConnectionEnd(player, $"Kicked from the server: {reason}");
                }
                else
                {
                    LunaLog.Normal($"Player: {playerName} not found");
                }
            }
            else
            {
                LunaLog.Error("Syntax error. Usage: /kick playername [reason]");
            }
        }
Esempio n. 15
0
        public override void HandleCommand(string commandArgs)
        {
            SplitCommand(commandArgs, out var type, out var data, out var reason);

            switch (type)
            {
            default:
                LunaLog.Normal("Undefined function. Usage: /ban [key|ip|username] Data [reason]");
                break;

            case "ip":
                BanIpCommand.Execute($"{data} {reason}");
                break;

            case "key":
                BanKeyCommand.Execute($"{data} {reason}");
                break;

            case "username":
                BanPlayerCommand.Execute($"{data} {reason}");
                break;
            }
        }
Esempio n. 16
0
        //Removes all matching vessels
        private static void RunRemove(string vesselType, string vesselSituation, string vesselSplashed, string vesselName, string orbName)
        {
            //Declare variables
            var removalCount = 0;
            var vesselList   = VesselStoreSystem.CurrentVesselsInXmlFormat.ToArray();

            //Cycle vesselList
            foreach (var vesselKeyVal in vesselList)
            {
                //Check if vessel can be found
                if (IsVesselFound(vesselKeyVal.Value, vesselType, vesselSituation, vesselSplashed, vesselName, orbName))
                {
                    //Send a vessel remove server console message
                    LunaLog.Normal($"Removing vessel: {vesselKeyVal.Key}");

                    //Remove vessel from universe
                    VesselStoreSystem.RemoveVessel(vesselKeyVal.Key);

                    //Send a vessel remove message to all clients
                    var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <VesselRemoveMsgData>();
                    msgData.VesselId = vesselKeyVal.Key;
                    MessageQueuer.SendToAllClients <VesselSrvMsg>(msgData);

                    //Increase counter
                    removalCount++;
                }
            }
            //Send message remove info
            if (removalCount > 0)
            {
                LunaLog.Normal($"Removed {removalCount} vessel(s) ...");
            }
            else
            {
                LunaLog.Normal($"Removed nothing ...");
            }
        }
Esempio n. 17
0
        public override void Execute(string commandArgs)
        {
            var splittedCommand = commandArgs.Trim().Split(' ');

            if (splittedCommand.Length == 2)
            {
                var playerName = splittedCommand[0];
                var client     = ClientRetriever.GetAuthenticatedClients().FirstOrDefault(p => p.PlayerName == playerName);

                if (client != null)
                {
                    var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <ChatPrivateMsgData>();
                    msgData.From = GeneralSettings.SettingsStore.ConsoleIdentifier;
                    msgData.To   = client.PlayerName;
                    msgData.Text = commandArgs.Substring(client.PlayerName.Length + 1);

                    MessageQueuer.SendToClient <ChatSrvMsg>(client, msgData);
                }
                else
                {
                    LunaLog.Normal("Player not found!");
                }
            }
        }
Esempio n. 18
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
            }
        }
Esempio n. 19
0
        public static void Main()
        {
            try
            {
                ServerContext.StartTime = DateTime.UtcNow.Ticks;

                //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;

                LunaLog.Debug("Loading settings...");
                if (GeneralSettings.SettingsStore.GameDifficulty == GameDifficulty.Custom)
                {
                    GameplaySettings.Reset();
                    GameplaySettings.Load();
                }

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

                //Load plugins
                LmpPluginHandler.LoadPlugins();

                Console.Title = $"LMPServer v{VersionInfo.VersionNumber}";

                while (ServerContext.ServerStarting || ServerContext.ServerRestarting)
                {
                    if (ServerContext.ServerRestarting)
                    {
                        LunaLog.Debug("Reloading settings...");
                        GeneralSettings.Reset();
                        GeneralSettings.Load();
                        if (GeneralSettings.SettingsStore.GameDifficulty == GameDifficulty.Custom)
                        {
                            LunaLog.Debug("Reloading gameplay settings...");
                            GameplaySettings.Reset();
                            GameplaySettings.Load();
                        }
                    }

                    ServerContext.ServerRestarting = false;
                    LunaLog.Normal($"Starting Luna Server v{VersionInfo.FullVersionNumber}");

                    if (GeneralSettings.SettingsStore.GameDifficulty == GameDifficulty.Custom)
                    {
                        //Generate the config file by accessing the object.
                        LunaLog.Debug("Loading gameplay settings...");
                        GameplaySettings.Load();
                    }

                    //Load universe
                    LunaLog.Normal("Loading universe... ");
                    Universe.CheckUniverse();

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

                    ServerContext.ServerRunning = true;

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

                    ServerContext.LidgrenServer.SetupLidgrenServer();
                    Task.Run(() => ServerContext.LidgrenServer.StartReceiveingMessages());
                    Task.Run(() => ServerContext.LidgrenServer.RegisterWithMasterServer());

                    var vesselRelayThread = Task.Run(() => VesselRelaySystem.RelayOldVesselMessages());

                    var vesselRelayFarThread    = Task.Run(() => VesselUpdateRelaySystem.RelayToFarPlayers());
                    var vesselRelayMediumThread = Task.Run(() => VesselUpdateRelaySystem.RelayToMediumDistancePlayers());
                    var vesselRelayCloseThread  = Task.Run(() => VesselUpdateRelaySystem.RelayToClosePlayers());

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

                    LunaLog.Normal("Ready!");
                    LmpPluginHandler.FireOnServerStart();
                    while (ServerContext.ServerRunning)
                    {
                        //Run the log expire function every 10 minutes
                        if (ServerContext.ServerClock.ElapsedMilliseconds - _lastLogExpiredCheck > 600000)
                        {
                            _lastLogExpiredCheck = ServerContext.ServerClock.ElapsedMilliseconds;
                            LogExpire.ExpireLogs();
                        }

                        // Check if the day has changed, every minute
                        if (ServerContext.ServerClock.ElapsedMilliseconds - _lastDayCheck > 60000)
                        {
                            _lastDayCheck = ServerContext.ServerClock.ElapsedMilliseconds;
                            if (ServerContext.Day != DateTime.Now.Day)
                            {
                                LunaLog.LogFilename = Path.Combine(LunaLog.LogFolder, $"lmpserver {DateTime.Now:yyyy-MM-dd HH-mm-ss}.log");
                                LunaLog.WriteToLog($"Continued from logfile {DateTime.Now:yyyy-MM-dd HH-mm-ss}.log");
                                ServerContext.Day = DateTime.Now.Day;
                            }
                        }

                        Thread.Sleep(500);
                    }

                    LmpPluginHandler.FireOnServerStop();
                    commandThread.Wait();
                    clientThread.Wait();
                    vesselRelayThread.Wait();

                    vesselRelayFarThread.Wait();
                    vesselRelayMediumThread.Wait();
                    vesselRelayCloseThread.Wait();
                }
                LunaLog.Normal("Goodbye and thanks for all the fish!");
                Environment.Exit(0);
            }
            catch (Exception e)
            {
                LunaLog.Fatal($"Error in main server thread, Exception: {e}");
                throw;
            }
        }
Esempio n. 20
0
        public static void StartReceivingMessages()
        {
            while (ServerContext.ServerRunning)
            {
                var msg = Server.WaitMessage(ServerContext.PlayerCount > 0 ? IntervalSettings.SettingsStore.SendReceiveThreadTickMs : int.MaxValue);
                if (msg != null)
                {
                    try
                    {
                        ClientStructure client = null;
                        if (msg.SenderConnection != null)
                        {
                            ServerContext.Clients.TryGetValue(msg.SenderConnection.RemoteEndPoint, out client);
                        }
                        switch (msg.MessageType)
                        {
                        case NetIncomingMessageType.ConnectionApproval:
                            if (ServerContext.UsePassword)
                            {
                                if (msg.ReadString() != GeneralSettings.SettingsStore.Password)
                                {
                                    msg.SenderConnection.Deny("Invalid password");
                                    break;
                                }
                            }
                            msg.SenderConnection.Approve();
                            break;

                        case NetIncomingMessageType.Data:
                            MessageReceiver.ReceiveCallback(client, msg);
                            if (client == null)
                            {
                                break;
                            }
                            client.BytesReceived += (uint)msg.LengthBytes;
                            break;

                        case NetIncomingMessageType.WarningMessage:
                            LunaLog.Warning(msg.ReadString());
                            break;

                        case NetIncomingMessageType.DebugMessage:
                            LunaLog.NetworkDebug(msg.ReadString());
                            break;

                        case NetIncomingMessageType.ConnectionLatencyUpdated:
                        case NetIncomingMessageType.VerboseDebugMessage:
                            LunaLog.NetworkVerboseDebug(msg.ReadString());
                            break;

                        case NetIncomingMessageType.ErrorMessage:
                        case NetIncomingMessageType.Error:
                            LunaLog.Error(msg.ReadString());
                            break;

                        case NetIncomingMessageType.StatusChanged:
                            switch ((NetConnectionStatus)msg.ReadByte())
                            {
                            case NetConnectionStatus.Connected:
                                var endpoint = msg.SenderConnection.RemoteEndPoint;
                                LunaLog.Normal($"New client Connection from {endpoint.Address}:{endpoint.Port}");
                                ClientConnectionHandler.ConnectClient(msg.SenderConnection);
                                break;

                            case NetConnectionStatus.Disconnected:
                                if (client != null)
                                {
                                    ClientConnectionHandler.DisconnectClient(client, msg.ReadString());
                                }
                                break;
                            }
                            break;

                        default:
                            LunaLog.Warning($"Unhandled Lidgren Message: {msg.MessageType} -- {msg.ReadString()}");
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        LunaLog.Error($"ERROR in networking thread! Details: {e}");
                    }
                }
            }
        }
Esempio n. 21
0
        private static void HandleMessage(IMasterServerMessageBase message, NetIncomingMessage netMsg, NetPeer peer)
        {
            if (BannedIpsRetriever.IsBanned(netMsg.SenderEndPoint))
            {
                LunaLog.Debug($"Ignoring BANNED ip: {netMsg.SenderEndPoint}");
                return;
            }

            try
            {
                switch ((message?.Data as MsBaseMsgData)?.MasterServerMessageSubType)
                {
                case MasterServerMessageSubType.RegisterServer:
                    RegisterServer(message, netMsg);
                    break;

                case MasterServerMessageSubType.RequestServers:
                    LunaLog.Normal($"LIST REQUEST from: {netMsg.SenderEndPoint}");
                    SendServerLists(netMsg, peer);
                    break;

                case MasterServerMessageSubType.Introduction:
                    var msgData = (MsIntroductionMsgData)message.Data;
                    if (ServerDictionary.TryGetValue(msgData.Id, out var server))
                    {
                        _ = Task.Run(() =>
                        {
                            if (!server.InternalEndpoint6.Address.Equals(IPAddress.IPv6Loopback) &&
                                !server.InternalEndpoint6.Address.Equals(IPAddress.IPv6Loopback))
                            {
                                // Both client and server are listening on IPv6, try an IPv6 firewall punchthrough
                                // This also triggers a first punchthrough on IPv4 with the public addresses
                                LunaLog.Normal(
                                    $"INTRODUCTION request from: {msgData.InternalEndpoint6} to server: {server.InternalEndpoint6}");
                                peer.Introduce(server.InternalEndpoint6, server.ExternalEndpoint,
                                               msgData.InternalEndpoint6, // client internal
                                               netMsg.SenderEndPoint,     // client external
                                               msgData.Token);            // request token

                                // Give the first introduction attempt some time
                                Thread.Sleep(50);
                            }

                            LunaLog.Normal(
                                $"INTRODUCTION request from: {netMsg.SenderEndPoint} to server: {server.ExternalEndpoint}");
                            peer.Introduce(server.InternalEndpoint, server.ExternalEndpoint,
                                           msgData.InternalEndpoint, // client internal
                                           netMsg.SenderEndPoint,    // client external
                                           msgData.Token);           // request token
                        });
                    }
                    else
                    {
                        LunaLog.Warning($"Client {netMsg.SenderEndPoint} requested introduction to non listed host!");
                    }
                    break;
                }
            }
            catch (Exception e)
            {
                LunaLog.Error($"Error handling message. Details: {e}");
            }
        }
Esempio n. 22
0
 public override void Execute(string commandArgs)
 {
     LunaLog.Normal($"Online Players: {ServerContext.PlayerCount}");
 }
Esempio n. 23
0
 public static void PerformGCNow()
 {
     LunaLog.Normal("Performing a GarbageCollection...");
     GC.Collect();
 }
Esempio n. 24
0
        public static async void RegisterWithMasterServer()
        {
            if (!MasterServerSettings.SettingsStore.RegisterWithMasterServer)
            {
                return;
            }

            LunaLog.Normal("Registering with master servers");

            var adr4 = LunaNetUtils.GetOwnInternalIPv4Address();

            // As of right now the internal endpoint for IPv4 is mandatory, because if there is none, there is no
            // IPv4 connectivity at all, which is required to connect to the master servers (so they can determine
            // the public IPv4 address).
            if (adr4 == null)
            {
                return;
            }
            var endpoint4 = new IPEndPoint(adr4, ServerContext.Config.Port);
            // Only send IPv6 address if actually listening on IPv6, otherwise send loopback with means "none".
            IPAddress  adr6;
            IPEndPoint endpoint6;

            if (LidgrenServer.Server.Socket.AddressFamily == AddressFamily.InterNetworkV6)
            {
                adr6      = LunaNetUtils.GetOwnInternalIPv6Address();
                endpoint6 = new IPEndPoint(adr6, ServerContext.Config.Port);
            }
            else
            {
                endpoint6 = new IPEndPoint(IPAddress.IPv6Loopback, ServerContext.Config.Port);
            }

            while (ServerContext.ServerRunning)
            {
                var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <MsRegisterServerMsgData>();
                msgData.Id                = LidgrenServer.Server.UniqueIdentifier;
                msgData.Password          = !string.IsNullOrEmpty(GeneralSettings.SettingsStore.Password);
                msgData.Cheats            = GeneralSettings.SettingsStore.Cheats;
                msgData.Description       = GeneralSettings.SettingsStore.Description;
                msgData.CountryCode       = GeneralSettings.SettingsStore.CountryCode;
                msgData.Website           = GeneralSettings.SettingsStore.Website;
                msgData.WebsiteText       = GeneralSettings.SettingsStore.WebsiteText;
                msgData.RainbowEffect     = DedicatedServerSettings.SettingsStore.UseRainbowEffect;
                msgData.Color             = new[] { DedicatedServerSettings.SettingsStore.Red, DedicatedServerSettings.SettingsStore.Green, DedicatedServerSettings.SettingsStore.Blue };
                msgData.GameMode          = (int)GeneralSettings.SettingsStore.GameMode;
                msgData.InternalEndpoint  = endpoint4;
                msgData.InternalEndpoint6 = endpoint6;
                msgData.MaxPlayers        = GeneralSettings.SettingsStore.MaxPlayers;
                msgData.ModControl        = GeneralSettings.SettingsStore.ModControl;
                msgData.PlayerCount       = ServerContext.Clients.Count;
                msgData.ServerName        = GeneralSettings.SettingsStore.ServerName;
                msgData.ServerVersion     = LmpVersioning.CurrentVersion.ToString(3);
                msgData.VesselPositionUpdatesMsInterval          = IntervalSettings.SettingsStore.VesselUpdatesMsInterval;
                msgData.SecondaryVesselPositionUpdatesMsInterval = IntervalSettings.SettingsStore.SecondaryVesselUpdatesMsInterval;
                msgData.WarpMode       = (int)WarpSettings.SettingsStore.WarpMode;
                msgData.TerrainQuality = (int)GeneralSettings.SettingsStore.TerrainQuality;

                msgData.Description = msgData.Description.Length > 200 ? msgData.Description.Substring(0, 200) : msgData.Description;
                msgData.CountryCode = msgData.CountryCode.Length > 2 ? msgData.CountryCode.Substring(0, 2) : msgData.CountryCode;
                msgData.Website     = msgData.Website.Length > 60 ? msgData.Website.Substring(0, 60) : msgData.Website;
                msgData.WebsiteText = msgData.WebsiteText.Length > 15 ? msgData.WebsiteText.Substring(0, 15) : msgData.WebsiteText;
                msgData.ServerName  = msgData.ServerName.Length > 30 ? msgData.ServerName.Substring(0, 30) : msgData.ServerName;

                IPEndPoint[] masterServers;
                if (string.IsNullOrEmpty(DebugSettings.SettingsStore.CustomMasterServer))
                {
                    masterServers = MasterServerRetriever.MasterServers.GetValues;
                }
                else
                {
                    masterServers = new[]
                    {
                        LunaNetUtils.CreateEndpointFromString(DebugSettings.SettingsStore.CustomMasterServer)
                    };
                }
                foreach (var masterServer in masterServers)
                {
                    RegisterWithMasterServer(msgData, masterServer);
                }

                await Task.Delay(MasterServerRegistrationMsInterval);
            }
        }
Esempio n. 25
0
        public void RegisterWithMasterServer()
        {
            if (!GeneralSettings.SettingsStore.RegisterWithMasterServer)
            {
                return;
            }

            var adr      = NetUtility.GetMyAddress(out var _);
            var endpoint = new IPEndPoint(adr, ServerContext.Config.Port);

            if (MasterServerEndpoints == null || !MasterServerEndpoints.Any())
            {
                MasterServerEndpoints = MasterServerRetriever.RetrieveWorkingMasterServersEndpoints()
                                        .Select(Common.CreateEndpointFromString)
                                        .ToArray();
            }

            LunaLog.Normal("Registering with master servers...");
            while (ServerContext.ServerRunning)
            {
                var msgData = new MsRegisterServerMsgData
                {
                    Id     = Server.UniqueIdentifier,
                    Cheats = GeneralSettings.SettingsStore.Cheats,
                    ShowVesselsInThePast         = GeneralSettings.SettingsStore.ShowVesselsInThePast,
                    Description                  = GeneralSettings.SettingsStore.Description,
                    DropControlOnExit            = GeneralSettings.SettingsStore.Cheats,
                    DropControlOnExitFlight      = GeneralSettings.SettingsStore.Cheats,
                    DropControlOnVesselSwitching = GeneralSettings.SettingsStore.Cheats,
                    GameMode                             = (int)GeneralSettings.SettingsStore.GameMode,
                    InternalEndpoint                     = $"{endpoint.Address}:{endpoint.Port}",
                    MaxPlayers                           = GeneralSettings.SettingsStore.MaxPlayers,
                    ModControl                           = (int)GeneralSettings.SettingsStore.ModControl,
                    PlayerCount                          = ServerContext.Clients.Count,
                    ServerName                           = GeneralSettings.SettingsStore.ServerName,
                    ServerVersion                        = VersionInfo.VersionNumber,
                    VesselUpdatesSendMsInterval          = GeneralSettings.SettingsStore.VesselUpdatesSendMsInterval,
                    SecondaryVesselUpdatesSendMsInterval = GeneralSettings.SettingsStore.SecondaryVesselUpdatesSendMsInterval,
                    WarpMode                             = (int)GeneralSettings.SettingsStore.WarpMode
                };

                msgData.Description = msgData.Description.Length > 200
                            ? msgData.Description.Substring(0, 200)
                            : msgData.Description;

                msgData.ServerName = msgData.ServerName.Length > 30
                    ? msgData.ServerName.Substring(0, 30)
                    : msgData.ServerName;

                var msg      = ServerContext.MasterServerMessageFactory.CreateNew <MainMstSrvMsg>(msgData);
                var msgBytes = ServerContext.MasterServerMessageFactory.Serialize(msg);

                foreach (var masterServer in MasterServerEndpoints)
                {
                    try
                    {
                        var outMsg = Server.CreateMessage(msgBytes.Length);
                        outMsg.Write(msgBytes);
                        Server.SendUnconnectedMessage(outMsg, masterServer);
                        Server.FlushSendQueue();
                    }
                    catch (Exception)
                    {
                        // ignored
                    }
                }

                Thread.Sleep(MasterServerRegistrationMsInterval);
            }
        }
Esempio n. 26
0
        public static async void StartReceiveingMessages()
        {
            try
            {
                while (ServerContext.ServerRunning)
                {
                    var msg = Server.ReadMessage();
                    if (msg != null)
                    {
                        var client = TryGetClient(msg);
                        switch (msg.MessageType)
                        {
                        case NetIncomingMessageType.ConnectionApproval:
                            if (ServerContext.UsePassword)
                            {
                                var password = msg.ReadString();
                                if (password != GeneralSettings.SettingsStore.Password)
                                {
                                    msg.SenderConnection.Deny("Invalid password");
                                    break;
                                }
                            }
                            msg.SenderConnection.Approve();
                            break;

                        case NetIncomingMessageType.Data:
                            ClientMessageReceiver.ReceiveCallback(client, msg);
                            break;

                        case NetIncomingMessageType.WarningMessage:
                            LunaLog.Warning(msg.ReadString());
                            break;

                        case NetIncomingMessageType.DebugMessage:
                            LunaLog.NetworkDebug(msg.ReadString());
                            break;

                        case NetIncomingMessageType.ConnectionLatencyUpdated:
                        case NetIncomingMessageType.VerboseDebugMessage:
                            LunaLog.NetworkVerboseDebug(msg.ReadString());
                            break;

                        case NetIncomingMessageType.Error:
                            LunaLog.Error(msg.ReadString());
                            break;

                        case NetIncomingMessageType.StatusChanged:
                            switch ((NetConnectionStatus)msg.ReadByte())
                            {
                            case NetConnectionStatus.Connected:
                                var endpoint = msg.SenderConnection.RemoteEndPoint;
                                LunaLog.Normal($"New client Connection from {endpoint.Address}:{endpoint.Port}");
                                ClientConnectionHandler.ConnectClient(msg.SenderConnection);
                                break;

                            case NetConnectionStatus.Disconnected:
                                var reason = msg.ReadString();
                                if (client != null)
                                {
                                    ClientConnectionHandler.DisconnectClient(client, reason);
                                }
                                break;
                            }
                            break;

                        default:
                            var details = msg.PeekString();
                            LunaLog.Debug($"Lidgren: {msg.MessageType.ToString().ToUpper()} -- {details}");
                            break;
                        }
                    }
                    else
                    {
                        await Task.Delay(IntervalSettings.SettingsStore.SendReceiveThreadTickMs);
                    }
                }
            }
            catch (Exception e)
            {
                LunaLog.Fatal($"ERROR in thread receive! Details: {e}");
            }
        }
Esempio n. 27
0
        public void StartReceiveingMessages()
        {
            try
            {
                while (ServerContext.ServerRunning)
                {
                    var msg = Server.ReadMessage();
                    if (msg != null)
                    {
                        var client = TryGetClient(msg);
                        switch (msg.MessageType)
                        {
                        case NetIncomingMessageType.ConnectionApproval:
                            msg.SenderConnection.Approve();
                            break;

                        case NetIncomingMessageType.Data:
                            ClientMessageReceiver.ReceiveCallback(client, msg);
                            break;

                        case NetIncomingMessageType.WarningMessage:
                            LunaLog.Error($"Lidgren WARNING: {msg.ReadString()}");
                            break;

                        case NetIncomingMessageType.DebugMessage:
                        case NetIncomingMessageType.VerboseDebugMessage:
                            LunaLog.Debug($"Lidgren DEBUG: {msg.MessageType}-- {msg.PeekString()}");
                            break;

                        case NetIncomingMessageType.StatusChanged:
                            switch ((NetConnectionStatus)msg.ReadByte())
                            {
                            case NetConnectionStatus.Connected:
                                var endpoint = msg.SenderConnection.RemoteEndPoint;
                                LunaLog.Normal($"New client Connection from {endpoint.Address}:{endpoint.Port}");
                                ClientConnectionHandler.ConnectClient(msg.SenderConnection);
                                break;

                            case NetConnectionStatus.Disconnected:
                                var reason = msg.ReadString();
                                if (client != null)
                                {
                                    ClientConnectionHandler.DisconnectClient(client, reason);
                                }
                                break;
                            }
                            break;

                        default:
                            var details = msg.PeekString();
                            LunaLog.Debug($"Lidgren: {msg.MessageType.ToString().ToUpper()} -- {details}");
                            break;
                        }
                    }
                    else
                    {
                        Thread.Sleep(GeneralSettings.SettingsStore.SendReceiveThreadTickMs);
                    }
                }
            }
            catch (Exception e)
            {
                LunaLog.Fatal($"ERROR in thread receive! Details: {e}");
            }
        }
Esempio n. 28
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
            }
        }
Esempio n. 29
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
            }
        }
 public override bool Execute(string commandArgs)
 {
     LunaLog.Normal($"Online Players: {ServerContext.PlayerCount}");
     return(true);
 }