private async void SendMessagesThread(CancellationToken token) { while (ConnectionStatus == ConnectionStatus.Connected) { while (SendMessageQueue.TryDequeue(out var message) && message != null) { try { LidgrenServer.SendMessageToClient(this, message); } catch (Exception e) { ClientException.HandleDisconnectException("Send network message error: ", this, e); return; } LmpPluginHandler.FireOnMessageSent(this, message); } try { await Task.Delay(IntervalSettings.SettingsStore.SendReceiveThreadTickMs, token); } catch (TaskCanceledException) { break; } } }
public void HandleHandshakeRequest(ClientStructure client, HandshakeRequestMsgData data) { var valid = CheckServerFull(client); valid &= valid && CheckUsernameLength(client, data.PlayerName); valid &= valid && CheckUsernameCharacters(client, data.PlayerName); valid &= valid && CheckPlayerIsAlreadyConnected(client, data.PlayerName); valid &= valid && CheckUsernameIsReserved(client, data.PlayerName); valid &= valid && CheckPlayerIsBanned(client, data.UniqueIdentifier); if (!valid) { LunaLog.Normal($"Client {data.PlayerName} ({data.UniqueIdentifier}) failed to handshake: {Reason}. Disconnecting"); client.DisconnectClient = true; ClientConnectionHandler.DisconnectClient(client, Reason); } else { client.PlayerName = data.PlayerName; client.UniqueIdentifier = data.UniqueIdentifier; client.Authenticated = true; LmpPluginHandler.FireOnClientAuthenticated(client); LunaLog.Normal($"Client {data.PlayerName} ({data.UniqueIdentifier}) handshake successfully, Version: {data.MajorVersion}.{data.MinorVersion}.{data.BuildVersion}"); 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}"); } }
public static void ConnectClient(NetConnection newClientConnection) { var newClientObject = new ClientStructure(newClientConnection); LmpPluginHandler.FireOnClientConnect(newClientObject); ServerContext.Clients.TryAdd(newClientObject.Endpoint, newClientObject); LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ServerContext.Clients.Count}"); }
public void ReceiveCallback(ClientStructure client, NetIncomingMessage msg) { if (client == null || msg.LengthBytes <= 1) { return; } if (client.ConnectionStatus == ConnectionStatus.Connected) { client.LastReceiveTime = ServerContext.ServerClock.ElapsedMilliseconds; } var message = DeserializeMessage(msg); if (message == null) { return; } LmpPluginHandler.FireOnMessageReceived(client, message); //A plugin has handled this message and requested suppression of the default behavior if (message.Handled) { return; } if (message.VersionMismatch) { MessageQueuer.SendConnectionEnd(client, $"Version mismatch: Your version ({message.Data.MajorVersion}.{message.Data.MinorVersion}.{message.Data.BuildVersion}) " + $"does not match the server version: {LmpVersioning.CurrentVersion}."); return; } //Clients can only send HANDSHAKE until they are Authenticated. if (!client.Authenticated && message.MessageType != ClientMessageType.Handshake) { MessageQueuer.SendConnectionEnd(client, $"You must authenticate before sending a {message.MessageType} message"); return; } //Handle the message try { HandlerDictionary[message.MessageType].HandleMessage(client, message); } catch (Exception e) { LunaLog.Error($"Error handling a message from {client.PlayerName}! {e}"); } }
public void ThreadMain() { try { WarpSystem.Reset(); ChatSystem.Reset(); while (ServerContext.ServerRunning) { //Check timers NukeCommand.CheckTimer(); DekesslerCommand.CheckTimer(); LmpPluginHandler.FireOnUpdate(); //Run plugin update Thread.Sleep(GeneralSettings.SettingsStore.MainTimeTick); } } catch (Exception e) { LunaLog.Error($"Fatal error thrown, exception: {e}"); new ShutDownCommand().Execute("Crashed!"); } try { var disconnectTime = DateTime.UtcNow.Ticks; var sendingMessages = true; while (sendingMessages) { if (DateTime.UtcNow.Ticks - disconnectTime > TimeSpan.FromSeconds(5).Ticks) { LunaLog.Debug($"Shutting down with {ServerContext.PlayerCount} Players, " + $"{ServerContext.Clients.Count} connected Clients"); break; } sendingMessages = ClientRetriever.GetAuthenticatedClients().Any(c => c.SendMessageQueue.Count > 0); Thread.Sleep(GeneralSettings.SettingsStore.MainTimeTick); } ServerContext.LidgrenServer.ShutdownLidgrenServer(); } catch (Exception e) { LunaLog.Fatal($"Fatal error thrown during shutdown, exception: {e}"); throw; } }
public static void DisconnectClient(ClientStructure client, string reason = "") { if (!string.IsNullOrEmpty(reason)) { LunaLog.Debug($"{client.PlayerName} sent Connection end message, reason: {reason}"); } 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}"); } } //Remove Clients from list if (ServerContext.Clients.TryRemove(client.Endpoint, out ClientStructure removed)) { LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ServerContext.Clients.Count}"); } else { LunaLog.Error($"Error removing client: {client.PlayerName} from list"); } //As this is the last client that is connected to the server, run a safety backup once he disconnects if (ServerContext.Clients.Count == 0) { BackupSystem.RunBackup(); GcSystem.PerformGCNow(); } }
public static void DisconnectClient(ClientStructure client, string reason = "") { if (!string.IsNullOrEmpty(reason)) { LunaLog.Debug($"{client.PlayerName} sent Connection end message, reason: {reason}"); } VesselUpdateRelaySystem.RemovePlayer(client); //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) { ChatSystem.RemovePlayer(client.PlayerName); 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 void ReceiveCallback(ClientStructure client, NetIncomingMessage msg) { if (client == null || msg.LengthBytes <= 1) { return; } if (client.ConnectionStatus == ConnectionStatus.Connected) { client.LastReceiveTime = ServerContext.ServerClock.ElapsedMilliseconds; } var messageBytes = msg.ReadBytes(msg.LengthBytes); var message = ServerContext.ClientMessageFactory.Deserialize(messageBytes, DateTime.UtcNow.Ticks) as IClientMessageBase; if (message == null) { LunaLog.Error("Error deserializing message!"); return; } LmpPluginHandler.FireOnMessageReceived(client, message); //A plugin has handled this message and requested suppression of the default behavior if (message.Handled) { return; } if (message.VersionMismatch) { MessageQueuer.SendConnectionEnd(client, $"Version mismatch. Your version doesn't match the server's version: {VersionInfo.VersionNumber}. Update your plugin."); return; } //Clients can only send HANDSHAKE until they are Authenticated. if (!client.Authenticated && message.MessageType != ClientMessageType.Handshake) { MessageQueuer.SendConnectionEnd(client, $"You must authenticate before sending a {message.MessageType} message"); return; } LunaLog.Debug(message.MessageType.ToString()); //Handle the message HandlerDictionary[message.MessageType].HandleMessage(client, message.Data); }
public static async void ThreadMain() { try { while (ServerContext.ServerRunning) { //Check timers NukeCommand.CheckTimer(); DekesslerCommand.CheckTimer(); LmpPluginHandler.FireOnUpdate(); //Run plugin update await Task.Delay(IntervalSettings.SettingsStore.MainTimeTick); } } catch (Exception e) { LunaLog.Error($"Fatal error thrown, exception: {e}"); ServerContext.Shutdown("Fatal error server side"); } try { var disconnectTime = LunaNetworkTime.UtcNow.Ticks; var sendingMessages = true; while (sendingMessages) { if (LunaNetworkTime.UtcNow.Ticks - disconnectTime > TimeSpan.FromSeconds(5).Ticks) { LunaLog.Debug($"Shutting down with {ServerContext.PlayerCount} Players, " + $"{ServerContext.Clients.Count} connected Clients"); break; } sendingMessages = ClientRetriever.GetAuthenticatedClients().Any(c => c.SendMessageQueue.Count > 0); await Task.Delay(IntervalSettings.SettingsStore.MainTimeTick); } LidgrenServer.ShutdownLidgrenServer(); } catch (Exception e) { LunaLog.Fatal($"Fatal error thrown during shutdown, exception: {e}"); throw; } }
private async void SendMessagesThread() { while (ConnectionStatus == ConnectionStatus.Connected) { if (SendMessageQueue.TryDequeue(out var message) && message != null) { try { ServerContext.LidgrenServer.SendMessageToClient(this, message); } catch (Exception e) { ClientException.HandleDisconnectException("Send network message error: ", this, e); return; } LmpPluginHandler.FireOnMessageSent(this, message); }
public static void ConnectClient(NetConnection newClientConnection) { var newClientObject = new ClientStructure(newClientConnection.RemoteEndPoint) { Subspace = int.MinValue, PlayerStatus = new PlayerStatus(), ConnectionStatus = ConnectionStatus.Connected, Connection = newClientConnection, LastSendTime = 0, LastReceiveTime = ServerContext.ServerClock.ElapsedMilliseconds }; Task.Run(() => MessageSender.StartSendingOutgoingMessages(newClientObject)); LmpPluginHandler.FireOnClientConnect(newClientObject); ServerContext.Clients.TryAdd(newClientObject.Endpoint, newClientObject); VesselUpdateRelaySystem.AddPlayer(newClientObject); LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ServerContext.Clients.Count}"); }
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}"); } }
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); }
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 } }
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 static void ReceiveCallback(ClientStructure client, NetIncomingMessage msg) { if (client == null || msg.LengthBytes <= 1) { return; } if (client.ConnectionStatus == ConnectionStatus.Connected) { client.LastReceiveTime = ServerContext.ServerClock.ElapsedMilliseconds; } if (!(ServerContext.ClientMessageFactory.Deserialize(msg, LunaNetworkTime.UtcNow.Ticks) is IClientMessageBase message)) { return; } LmpPluginHandler.FireOnMessageReceived(client, message); //A plugin has handled this message and requested suppression of the default behavior if (message.Handled) { return; } if (message.VersionMismatch) { MessageQueuer.SendConnectionEnd(client, $"Version mismatch: Your version ({message.Data.MajorVersion}.{message.Data.MinorVersion}.{message.Data.BuildVersion}) " + $"does not match the server version: {LmpVersioning.CurrentVersion}."); return; } //Clients can only send HANDSHAKE until they are Authenticated. if (!client.Authenticated && message.MessageType != ClientMessageType.Handshake) { MessageQueuer.SendConnectionEnd(client, $"You must authenticate before sending a {message.MessageType} message"); return; } switch (message.MessageType) { case ClientMessageType.Admin: AdminMsgReader.HandleMessage(client, message); break; case ClientMessageType.Handshake: HandshakeMsgReader.HandleMessage(client, message); break; case ClientMessageType.Chat: ChatMsgReader.HandleMessage(client, message); break; case ClientMessageType.PlayerStatus: PlayerStatusMsgReader.HandleMessage(client, message); break; case ClientMessageType.PlayerColor: PlayerColorMsgReader.HandleMessage(client, message); break; case ClientMessageType.Scenario: ScenarioDataMsgReader.HandleMessage(client, message); break; case ClientMessageType.Kerbal: KerbalMsgReader.HandleMessage(client, message); break; case ClientMessageType.Settings: SettingsMsgReader.HandleMessage(client, message); break; case ClientMessageType.Vessel: VesselMsgReader.HandleMessage(client, message); break; case ClientMessageType.CraftLibrary: CraftLibraryMsgReader.HandleMessage(client, message); break; case ClientMessageType.Flag: FlagSyncMsgReader.HandleMessage(client, message); break; case ClientMessageType.Motd: MotdMsgReader.HandleMessage(client, message); break; case ClientMessageType.Warp: WarpControlMsgReader.HandleMessage(client, message); break; case ClientMessageType.Lock: LockSystemMsgReader.HandleMessage(client, message); break; case ClientMessageType.Mod: ModDataMsgReader.HandleMessage(client, message); break; case ClientMessageType.Groups: GroupMsgReader.HandleMessage(client, message); break; case ClientMessageType.Facility: FacilityMsgReader.HandleMessage(client, message); break; case ClientMessageType.Screenshot: ScreenshotMsgReader.HandleMessage(client, message); break; case ClientMessageType.ShareProgress: ShareProgressMsgReader.HandleMessage(client, message); break; default: break; } }
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 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; } }