static void RaiseShutdownBeganEvent(ShutdownParams shutdownParams) { var h = ShutdownBegan; if (h != null) { h(null, new ShutdownEventArgs(shutdownParams)); } }
private static void RaiseShutdownEndedEvent(ShutdownParams shutdownParams) { var h = ShutdownEnded; if (h != null) { h(null, new ShutdownEventArgs(shutdownParams)); } }
static void RaiseShutdownEndedEvent(ShutdownParams shutdownParams) { var handler = ShutdownEnded; if (handler != null) { handler(null, new ShutdownEventArgs(shutdownParams)); } }
static void RestartHandler( Player player, Command cmd ) { string delayString = cmd.Next(); TimeSpan delayTime = DefaultShutdownTime; string reason = ""; if( delayString != null ) { if( delayString.Equals( "abort", StringComparison.OrdinalIgnoreCase ) ) { if( Server.CancelShutdown() ) { Logger.Log( LogType.UserActivity, "Restart aborted by {0}.", player.Name ); Server.Message( "&WRestart aborted by {0}", player.ClassyName ); } else { player.MessageNow( "Cannot abort restart - too late." ); } return; } else if( !delayString.TryParseMiniTimespan( out delayTime ) ) { CdShutdown.PrintUsage( player ); return; } reason = cmd.NextAll(); } if( delayTime.TotalMilliseconds > Int32.MaxValue - 1 ) { player.Message( "Restart: Delay is too long, maximum is {0}", TimeSpan.FromMilliseconds( Int32.MaxValue - 1 ).ToMiniString() ); return; } Server.Message( "&WServer restarting in {0}", delayTime.ToMiniString() ); if( String.IsNullOrEmpty( reason ) ) { Logger.Log( LogType.UserActivity, "{0} scheduled a restart ({1} delay).", player.Name, delayTime.ToCompactString() ); ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delayTime, true, true ); Server.Shutdown( sp, false ); } else { Server.Message( "&WRestart reason: {0}", reason ); Logger.Log( LogType.UserActivity, "{0} scheduled a restart ({1} delay). Reason: {2}", player.Name, delayTime.ToCompactString(), reason ); ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delayTime, true, true, reason, player ); Server.Shutdown( sp, false ); } }
/// <summary> Starts the server: /// Creates Console pseudo-player, loads the world list, starts listening for incoming connections, /// sets up scheduled tasks and starts the scheduler, starts the heartbeat, and connects to IRC. /// Raises Server.Starting and Server.Started events. /// May throw an exception on hard failure. </summary> /// <returns> True if server started normally, false on soft failure. </returns> /// <exception cref="System.InvalidOperationException"> Server is already running, or server/library have not been initialized. </exception> public static bool StartServer() { if( IsRunning ) { throw new InvalidOperationException( "Server is already running" ); } if( !libraryInitialized || !serverInitialized ) { throw new InvalidOperationException( "Server.InitLibrary and Server.InitServer must be called before Server.StartServer" ); } StartTime = DateTime.UtcNow; cpuUsageStartingOffset = Process.GetCurrentProcess().TotalProcessorTime; Players = new Player[0]; RaiseEvent( Starting ); if( ConfigKey.BackupDataOnStartup.Enabled() ) { BackupData(); } Player.Console = new Player( ConfigKey.ConsoleName.GetString() ); Player.AutoRank = new Player( "(AutoRank)" ); // Back up server data (PlayerDB, worlds, bans, config) if( ConfigKey.BlockDBEnabled.Enabled() ) { BlockDB.Init(); } // Load the world list if( !WorldManager.LoadWorldList() ) return false; WorldManager.SaveWorldList(); // Back up all worlds (if needed) if( ConfigKey.BackupOnStartup.Enabled() ) { foreach( World world in WorldManager.Worlds ) { string backupFileName = String.Format( World.TimedBackupFormat, world.Name, DateTime.Now ); // localized world.SaveBackup( Path.Combine( Paths.BackupPath, backupFileName ) ); } } // open the port Port = ConfigKey.Port.GetInt(); InternalIP = IPAddress.Parse( ConfigKey.IP.GetString() ); try { listener = new TcpListener( InternalIP, Port ); listener.Start(); } catch( Exception ex ) { // if the port is unavailable Logger.Log( LogType.Error, "Could not start listening on port {0}, stopping. ({1})", Port, ex.Message ); if( !ConfigKey.IP.IsDefault() ) { Logger.Log( LogType.Warning, "Do not use the \"Designated IP\" setting unless you have multiple NICs or IPs." ); } return false; } // Resolve internal and external IP addresses InternalIP = ( (IPEndPoint)listener.LocalEndpoint ).Address; IPAddress foundExternalIP = null; for( int i = 0; i < 3 && foundExternalIP == null; i++ ) { Logger.Log( LogType.SystemActivity, "Resolving external IP address... (try {0})", i + 1 ); foundExternalIP = CheckExternalIP(); } if( foundExternalIP != null ) { ExternalIP = foundExternalIP; Logger.Log( LogType.SystemActivity, "Server.StartServer: now accepting connections at {0}:{1}", ExternalIP, Port ); } else { Logger.Log( LogType.SystemActivity, "Server.StartServer: External IP could not be looked up. Now accepting connections on port {0}", Port ); } // list loaded worlds WorldManager.UpdateWorldList(); Logger.Log( LogType.SystemActivity, "All available worlds: {0}", WorldManager.Worlds.JoinToString( ", ", w => w.Name ) ); Logger.Log( LogType.SystemActivity, "Main world: {0}; default rank: {1}", WorldManager.MainWorld.Name, RankManager.DefaultRank.Name ); // Check for incoming connections (every 250ms) checkConnectionsTask = Scheduler.NewTask( CheckConnections ).RunForever( CheckConnectionsInterval ); // Check for idles (every 30s) checkIdlesTask = Scheduler.NewTask( CheckIdles ).RunForever( CheckIdlesInterval ); // Monitor CPU usage (every 30s) try { MonitorProcessorUsage( null ); Scheduler.NewTask( MonitorProcessorUsage ).RunForever( MonitorProcessorUsageInterval, MonitorProcessorUsageInterval ); } catch( Exception ex ) { Logger.Log( LogType.Error, "Server.StartServer: Could not start monitoring CPU use: {0}", ex ); } // PlayerDB saving (every 90s) PlayerDB.StartSaveTask(); // Announcements if( ConfigKey.AnnouncementInterval.GetInt() > 0 ) { TimeSpan announcementInterval = TimeSpan.FromMinutes( ConfigKey.AnnouncementInterval.GetInt() ); Scheduler.NewTask( ShowRandomAnnouncement ) .RunForever( announcementInterval ); } // garbage collection (every 60s) gcTask = Scheduler.NewTask( DoGC ) .RunForever( GCInterval, TimeSpan.FromSeconds( 45 ) ); Heartbeat.Start(); if( ConfigKey.IRCBotEnabled.Enabled() ) { IRC.Start(); } if( ConfigKey.AutoRankEnabled.Enabled() ) { Scheduler.NewTask( AutoRankManager.TaskCallback ) .RunForever( AutoRankManager.TickInterval ); } if( ConfigKey.RestartInterval.GetInt() > 0 ) { // schedule automatic restart TimeSpan restartIn = TimeSpan.FromSeconds( ConfigKey.RestartInterval.GetInt() ); ShutdownParams sp = new ShutdownParams( ShutdownReason.RestartTimer, restartIn, true, "Automatic Server Restart", Player.Console ); Shutdown( sp, false ); } // start the main loop - server is now connectible Scheduler.Start(); IsRunning = true; RaiseEvent( Started ); return true; }
static void RaiseShutdownEndedEvent( ShutdownParams shutdownParams ) { var h = ShutdownEnded; if( h != null ) h( null, new ShutdownEventArgs( shutdownParams ) ); }
static void ShutdownHandler([NotNull] Player player, [NotNull] CommandReader cmd) { string delayString = cmd.Next(); TimeSpan delayTime = DefaultShutdownTime; string reason = ""; if (delayString != null) { if (delayString.Equals("abort", StringComparison.OrdinalIgnoreCase)) { if (Server.CancelShutdown()) { Logger.Log(LogType.UserActivity, "Shutdown aborted by {0}.", player.Name); Server.Message("&WShutdown aborted by {0}", player.ClassyName); } else { player.MessageNow("Cannot abort shutdown - too late."); } return; } else if (!delayString.TryParseMiniTimeSpan(out delayTime)) { CdShutdown.PrintUsage(player); return; } if (delayTime > DateTimeUtil.MaxTimeSpan) { player.MessageMaxTimeSpan(); return; } reason = cmd.NextAll(); } if (delayTime.TotalMilliseconds > Int32.MaxValue - 1) { player.Message("WShutdown: Delay is too long, maximum is {0}", TimeSpan.FromMilliseconds(Int32.MaxValue - 1).ToMiniString()); return; } Server.Message("&WServer shutting down in {0}", delayTime.ToMiniString()); if (String.IsNullOrWhiteSpace(reason)) { Logger.Log(LogType.UserActivity, "{0} scheduled a shutdown ({1} delay).", player.Name, delayTime.ToCompactString()); ShutdownParams sp = new ShutdownParams(ShutdownReason.ShutdownCommand, delayTime, false); Server.Shutdown(sp, false); } else { Server.Message("&SShutdown reason: {0}", reason); Logger.Log(LogType.UserActivity, "{0} scheduled a shutdown ({1} delay). Reason: {2}", player.Name, delayTime.ToCompactString(), reason); ShutdownParams sp = new ShutdownParams(ShutdownReason.ShutdownCommand, delayTime, false, reason, player); Server.Shutdown(sp, false); } }
private static void RaiseShutdownBeganEvent( ShutdownParams shutdownParams ) { var h = ShutdownBegan; if ( h != null ) h( null, new ShutdownEventArgs( shutdownParams ) ); }
internal static void ShutdownNow( ShutdownParams shutdownParams ) { if( IsShuttingDown ) return; // to avoid starting shutdown twice if( shutdownParams == null ) throw new ArgumentNullException( "shutdownParams" ); IsShuttingDown = true; #if DEBUG #else try { #endif RaiseShutdownBeganEvent( shutdownParams ); Scheduler.BeginShutdown(); Logger.Log( "Server shutting down ({0})", LogType.SystemActivity, shutdownParams.ReasonString ); // stop accepting new players if( listener != null ) { listener.Stop(); listener = null; } // kick all players lock( SessionLock ) { foreach( Session s in Sessions ) { // NOTE: kick packet delivery here is not currently guaranteed s.Kick( "Server shutting down (" + shutdownParams.ReasonString + Color.White + ")", LeaveReason.ServerShutdown ); } if( Sessions.Count > 0 ) { // increase the chances of kick packets being delivered Thread.Sleep( 1000 ); } } // kill IRC bot IRC.Disconnect(); if( WorldManager.WorldList != null ) { lock( WorldManager.WorldListLock ) { // unload all worlds (includes saving) foreach( World world in WorldManager.WorldList ) { world.SaveMap(); } } } Scheduler.EndShutdown(); if( PlayerDB.IsLoaded ) PlayerDB.Save(); if( IPBanList.IsLoaded ) IPBanList.Save(); RaiseShutdownEndedEvent( shutdownParams ); #if DEBUG #else } catch( Exception ex ) { Logger.LogAndReportCrash( "Error in Server.Shutdown", "fCraft", ex, true ); } #endif }
/// <summary> Initiates the server shutdown with given parameters. </summary> /// <param name="shutdownParams"> Shutdown parameters </param> /// <param name="waitForShutdown"> If true, blocks the calling thread until shutdown is complete or cancelled. </param> public static void Shutdown( ShutdownParams shutdownParams, bool waitForShutdown ) { if( shutdownParams == null ) throw new ArgumentNullException( "shutdownParams" ); if( !CancelShutdown() ) return; shutdownThread = new Thread( ShutdownThread ) { Name = "fCraft.Shutdown" }; shutdownThread.Start( shutdownParams ); if( waitForShutdown ) { ShutdownWaiter.WaitOne(); } }
static void AutoRestartCallback( SchedulerTask task ) { var shutdownParams = new ShutdownParams( ShutdownReason.Restarting, 5, true, true ); Server.Shutdown( shutdownParams, false ); }
static void RestartHandler(Player player, CommandReader cmd) { string delayString = cmd.Next(); TimeSpan delayTime = DefaultShutdownTime; string reason = ""; if (delayString != null) { if (delayString.Equals("abort", StringComparison.OrdinalIgnoreCase)) { if (Server.CancelShutdown()) { Logger.Log(LogType.UserActivity, "Restart aborted by {0}.", player.Name); Server.Message("&WRestart aborted by {0}", player.ClassyName); } else { player.MessageNow("Cannot abort restart - too late."); } return; } else if (!delayString.TryParseMiniTimespan(out delayTime)) { CdShutdown.PrintUsage(player); return; } if (delayTime > DateTimeUtil.MaxTimeSpan) { player.MessageMaxTimeSpan(); return; } reason = cmd.NextAll(); } if (delayTime.TotalMilliseconds > Int32.MaxValue - 1) { player.Message("Restart: Delay is too long, maximum is {0}", TimeSpan.FromMilliseconds(Int32.MaxValue - 1).ToMiniString()); return; } Server.Message("&WServer restarting in {0}", delayTime.ToMiniString()); if (String.IsNullOrEmpty(reason)) { Logger.Log(LogType.UserActivity, "{0} scheduled a restart ({1} delay).", player.Name, delayTime.ToCompactString()); ShutdownParams sp = new ShutdownParams(ShutdownReason.Restarting, delayTime, true, true); Server.Shutdown(sp, false); } else { Server.Message("&WRestart reason: {0}", reason); Logger.Log(LogType.UserActivity, "{0} scheduled a restart ({1} delay). Reason: {2}", player.Name, delayTime.ToCompactString(), reason); ShutdownParams sp = new ShutdownParams(ShutdownReason.Restarting, delayTime, true, true, reason, player); Server.Shutdown(sp, false); } }
static void RaiseShutdownEndedEvent( ShutdownParams shutdownParams ) { var handler = ShutdownEnded; if( handler != null ) handler( null, new ShutdownEventArgs( shutdownParams ) ); }
static void Restart( Player player, Command cmd ) { int delay; if( !cmd.NextInt( out delay ) ) { delay = 5; cmd.Rewind(); } string reason = cmd.Next(); Server.SendToAll( "&WServer restarting in {0} seconds.", delay ); if( reason == null ) { Logger.Log( "{0} restarted the server ({1} second delay).", LogType.UserActivity, player.Name, delay ); ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delay, true, true ); Server.Shutdown( sp, false ); } else { Logger.Log( "{0} restarted the server ({1} second delay). Reason: {2}", LogType.UserActivity, player.Name, delay, reason ); ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delay, true, true, reason, player ); Server.Shutdown( sp, false ); } }
static void Shutdown( Player player, Command cmd ) { int delay; if( !cmd.NextInt( out delay ) ) { delay = 5; cmd.Rewind(); } string reason = cmd.NextAll(); if( reason.Equals( "abort", StringComparison.OrdinalIgnoreCase ) ) { if( Server.CancelShutdown() ) { Logger.Log( "Shutdown aborted by {0}.", LogType.UserActivity, player.Name ); Server.SendToAll( "&WShutdown aborted by {0}", player.GetClassyName() ); } else { player.MessageNow( "Cannot abort shutdown - too late." ); } return; } Server.SendToAll( "&WServer shutting down in {0} seconds.", delay ); if( String.IsNullOrEmpty( reason ) ) { Logger.Log( "{0} shut down the server ({1} second delay).", LogType.UserActivity, player.Name, delay ); ShutdownParams sp = new ShutdownParams( ShutdownReason.ShuttingDown, delay, true, false ); Server.Shutdown( sp, false ); } else { Server.SendToAll( "&WShutdown reason: {0}", reason ); Logger.Log( "{0} shut down the server ({1} second delay). Reason: {2}", LogType.UserActivity, player.Name, delay, reason ); ShutdownParams sp = new ShutdownParams( ShutdownReason.ShuttingDown, delay, true, false, reason, player ); Server.Shutdown( sp, false ); } }