/// <summary> /// Updates the World. /// </summary> public override void Update() { ThreadAsserts.IsMainThread(); // Process all of the stuff queued to be disposed ProcessDisposeStack(); var currentTime = GetTime(); // If enough time has elapsed, update stuff to be respawned if (_updateRespawnablesTime < currentTime) { _updateRespawnablesTime = currentTime + ServerSettings.Default.RespawnablesUpdateRate; _respawnTaskList.Process(); } // If enough time has elapsed, update the extra user information if (_syncExtraUserInfoTime < currentTime) { _syncExtraUserInfoTime = currentTime + ServerSettings.Default.SyncExtraUserInformationRate; SyncExtraUserInformation(); } base.Update(); }
/// <summary> /// Handles the login attempt of an account. /// </summary> /// <param name="conn">Connection that the login request was made on.</param> /// <param name="name">Name of the account.</param> /// <param name="password">Entered password for this account.</param> public void LoginAccount(IIPSocket conn, string name, string password) { if (!RequireServerRunning()) { return; } ThreadAsserts.IsMainThread(); if (conn == null) { if (log.IsErrorEnabled) { log.Error("conn is null."); } return; } // Try to log in the account IUserAccount userAccount; var loginResult = UserAccountManager.Login(conn, name, password, out userAccount); // Check that the login was successful if (loginResult != AccountLoginResult.Successful) { HandleFailedLogin(conn, loginResult, name); return; } // Check if banned int banMins; string banReason; if (BanningManager.Instance.IsBanned(userAccount.ID, out banReason, out banMins)) { userAccount.Dispose(GameMessage.AccountBanned, banMins, banReason); if (log.IsInfoEnabled) { log.InfoFormat("Disconnected account `{0}` after successful login since they have been banned.", name); } return; } // Set the connection's tag to the account conn.Tag = userAccount; // Send the "Login Successful" message using (var pw = ServerPacket.LoginSuccessful()) { conn.Send(pw, ServerMessageType.System); } if (log.IsInfoEnabled) { log.InfoFormat("Login for account `{0}` successful.", name); } // Send the account characters userAccount.SendAccountCharacterInfos(); }
/// <summary> /// Attempts to start shopping at a shop owned by the <paramref name="shopkeeper"/>. /// </summary> /// <param name="shop">The shop to start shopping at.</param> /// <param name="shopkeeper">The owner of the shop to try to start shopping at.</param> /// <param name="entityMap">The map that the <paramref name="shopkeeper"/> is on.</param> /// <returns> /// True if the shopping was successfully started at the <paramref name="shopkeeper"/>'s /// shop; otherwise false. /// </returns> bool TryStartShopping(IShop <TShopItem> shop, TShopOwner shopkeeper, IMap entityMap) { ThreadAsserts.IsMainThread(); if (shop == null || shopkeeper == null || entityMap == null) { return(false); } if (GetCharacterMap(Character) != entityMap) { return(false); } if (!IsValidDistance(Character, shopkeeper)) { return(false); } // If the User was already shopping somewhere else, stop that shopping if (_shoppingAt != null) { SendStopShopping(Character); } // Start the shopping _shoppingAt = shop; _shopOwner = shopkeeper; _shopMap = entityMap; SendStartShopping(Character, shop); return(true); }
/// <summary> /// Updates the map. /// </summary> /// <param name="deltaTime">The amount of time that elapsed since the last update.</param> public override void Update(int deltaTime) { if (IsDisposed) { return; } // This assert will have to be removed once/if we add support for multithreaded World updates ThreadAsserts.IsMainThread(); // If there are no Users on the Map, update the inactive counter or skip updating if already inactive if (_users.Count == 0) { if (IsInactive) { return; } _inactiveCounter -= deltaTime; } // Remove old map items _mapItemsCleaner.Update(GetTime()); base.Update(deltaTime); SynchronizeDynamicEntities(); }
/// <summary> /// Handles the request to create a new account. /// </summary> /// <param name="conn">Connection that the request was made on.</param> /// <param name="name">Name of the account.</param> /// <param name="password">Entered password for this account.</param> /// <param name="email">The email address.</param> public void CreateAccount(IIPSocket conn, string name, string password, string email) { if (!RequireServerRunning()) { return; } ThreadAsserts.IsMainThread(); if (conn == null) { if (log.IsErrorEnabled) { log.Error("conn is null."); } return; } // Create the account GameMessage failReason; var success = UserAccountManager.TryCreateAccount(conn, name, password, email, out failReason); // Send the appropriate success message using (var pw = ServerPacket.CreateAccount(success, failReason)) { conn.Send(pw, ServerMessageType.System); } }
void RecvCreateNewAccountCharacter(IIPSocket conn, BitStream r) { ThreadAsserts.IsMainThread(); var name = r.ReadString(); // Check for a valid account var account = TryGetAccount(conn); if (account == null) { const string errmsg = "Connection `{0}` tried to create a new account character but no account is associated with this connection."; if (log.IsWarnEnabled) { log.WarnFormat(errmsg, conn); } return; } // Ensure the connection isn't logged in if (account.User != null) { const string errmsg = "User `{0}` tried to create a new account character while already logged in."; if (log.IsWarnEnabled) { log.WarnFormat(errmsg, account.User); } return; } // Create the new account character Server.CreateAccountCharacter(conn, name); }
/// <summary> /// Draws the InfoBox. /// </summary> /// <param name="sb"><see cref="ISpriteBatch"/> to draw with.</param> public void Draw(ISpriteBatch sb) { ThreadAsserts.IsMainThread(); // Remove dead items while (_items.Count > 0 && _items[0].CreatedTime + _messageLife < TickCount.Now) { _items.RemoveAt(0); } // Loop through all items var i = 0; foreach (var item in _items) { // Set the position var pos = _position; pos.Y -= _font.GetLineSpacing() * (i++ + 1); pos.X -= item.Width; // Set the color var lifeLeft = (item.CreatedTime + _messageLife) - TickCount.Now; var alpha = (byte)Math.Min(255, lifeLeft); var color = new Color(item.Color.R, item.Color.G, item.Color.B, alpha); // Draw sb.DrawString(_font, item.Message, pos, color); } }
/// <summary> /// Handles the request to create a new account. /// </summary> /// <param name="conn">Connection that the request was made on.</param> /// <param name="name">The name of the character to create.</param> public void CreateAccountCharacter(IIPSocket conn, string name) { if (!RequireServerRunning()) { return; } ThreadAsserts.IsMainThread(); // Get the account var account = conn.Tag as IUserAccount; if (account == null) { return; } // Try to create the character string errorMessage; var success = UserAccountManager.TryAddCharacter(account.Name, name, out errorMessage); // Send the result to the client (which we have to do both when successful and failed) using (var pw = ServerPacket.CreateAccountCharacter(success, errorMessage)) { conn.Send(pw, ServerMessageType.System); } // If we successfully created the character, reload and resync the character listing if (success) { account.LoadCharacterIDs(); account.SendAccountCharacterInfos(); } }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> /// <param name="disconnectMessage">The message to use for when disconnecting the socket. When disposing an active connection, /// this can provide the client a reason why they were disconnected. The default is /// <see cref="GameMessage.DisconnectUserDisposed"/>.</param> /// <param name="p">The arguments for the <paramref name="disconnectMessage"/>.</param> public void Dispose(GameMessage disconnectMessage, params object[] p) { ThreadAsserts.IsMainThread(); try { // Make sure the User is closed CloseUser(); // Break the connection, if connected if (Socket != null) { Socket.Disconnect(disconnectMessage, p); } // Log the account out in the database DbController.GetQuery <SetAccountCurrentIPNullQuery>().Execute(ID); if (log.IsInfoEnabled) { log.InfoFormat("Disposed account `{0}`.", this); } } finally { _parent.NotifyAccountDisposed(this); } }
/// <summary> /// Attempts to purchase <paramref name="amount"/> items at the given <paramref name="slot"/> from the /// shop that the shopper is currently shopping at. /// </summary> /// <param name="slot">The index of the shop item to purchase.</param> /// <param name="amount">The amount of the item to purchase.</param> /// <returns>True if the purchase was successful; otherwise false.</returns> public bool TryPurchase(ShopItemIndex slot, byte amount) { ThreadAsserts.IsMainThread(); if (!slot.IsLegalValue()) { return(false); } // Get the shop ValidateShop(); if (_shoppingAt == null) { return(false); } // Get and validate the item var shopItem = _shoppingAt.GetShopItem(slot); if (Equals(shopItem, null)) { return(false); } // Try to buy the item return(HandleBuyShopItem(Character, shopItem, amount)); }
static void Main(string[] args) { log.Info("Starting editor..."); ThreadAsserts.IsMainThread(); #if DEBUG WinFormExceptionHelper.AddUnhandledExceptionHooks(); #endif Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // Check for a valid path to the development content if (ContentPaths.Dev == null) { const string errmsg = @"Could not find the path to the development content (ContentPaths.Dev). The file containing this path should be located at: \Content\Data\devpath.txt The path to the development content is required by the editor. See the file mentioned above for details."; MessageBox.Show(errmsg, "Error finding content path", MessageBoxButtons.OK); return; } // Ensure the content is copied over if (!ContentPaths.TryCopyContent(userArgs: CommonConfig.TryCopyContentArgs)) { const string errmsg = "Failed to copy the content from the dev to build path." + " Content in the build path will likely not update to reflect changes made in the content in the dev path."; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg); } Debug.Fail(errmsg); } // Initialize stuff EngineSettingsInitializer.Initialize(); try { GlobalState.Initialize(); // Get the command-line switches var switches = CommandLineSwitchHelper.GetCommandsUsingEnum <CommandLineSwitch>(args).ToArray(); var showEditor = !HandleSwitches(switches); if (showEditor) { // Start up the application Application.Run(new MainForm()); } } finally { GlobalState.Destroy(); } }
void RecvSelectAccountCharacter(IIPSocket conn, BitStream r) { ThreadAsserts.IsMainThread(); var index = r.ReadByte(); // Ensure the client is in a valid state to select an account character var userAccount = World.GetUserAccount(conn); if (userAccount == null) { return; } if (userAccount.User != null) { const string errmsg = "Account `{0}` tried to change characters while a character was already selected."; if (log.IsInfoEnabled) { log.InfoFormat(errmsg, userAccount); } return; } // Get the CharacterID CharacterID characterID; if (!userAccount.TryGetCharacterID(index, out characterID)) { const string errmsg = "Invalid account character index `{0}` given."; if (log.IsInfoEnabled) { log.InfoFormat(errmsg, characterID); } return; } // Load the user userAccount.SetUser(World, characterID); var user = userAccount.User; if (user != null) { // Send the MOTD if (!string.IsNullOrEmpty(ServerSettings.Default.MOTD)) { using (var pw = ServerPacket.Chat(ServerSettings.Default.MOTD)) { user.Send(pw, ServerMessageType.GUIChat); } } // Send a notification to the world that the user joined var param = new object[] { user.Name }; World.Send(GameMessage.UserJoinedWorld, ServerMessageType.GUIChat, param); } }
/// <summary> /// When overridden in the derived class, handles the output from a command. /// </summary> /// <param name="user">The user that the command came from.</param> /// <param name="text">The output text from the command. Will not be null or empty.</param> protected override void HandleCommandOutput(User user, string text) { ThreadAsserts.IsMainThread(); using (var pw = ServerPacket.Chat(text)) { user.Send(pw, ServerMessageType.GUIChat); } }
void RecvLogin(IIPSocket conn, BitStream r) { ThreadAsserts.IsMainThread(); var name = r.ReadString(); var password = r.ReadString(); Server.LoginAccount(conn, name, password); }
/// <summary> /// When overridden in the derived class, handles text that was not a command. /// </summary> /// <param name="user">The user the <paramref name="text"/> came from.</param> /// <param name="text">The text that wasn't a command.</param> protected override void HandleNonCommand(User user, string text) { ThreadAsserts.IsMainThread(); using (var pw = ServerPacket.ChatSay(user.Name, user.MapEntityIndex, text)) { user.Map.SendToArea(user, pw, ServerMessageType.GUIChat); } EventCounterManager.User.Increment(user.ID, UserEventCounterType.ChatLocalTimes); EventCounterManager.User.Increment(user.ID, UserEventCounterType.ChatLocalChars, text.Length); }
/// <summary> /// Loads and sets the User being used by this account. /// </summary> /// <param name="world">The World that the User will be part of.</param> /// <param name="characterID">The CharacterID of the user to use.</param> public void SetUser(World world, CharacterID characterID) { ThreadAsserts.IsMainThread(); // Make sure the user is not already set if (User != null) { const string errmsg = "Cannot use SetUser when the User is not null."; Debug.Fail(errmsg); if (log.IsErrorEnabled) { log.Error(errmsg); } return; } // Make sure the CharacterID is an ID of a character belonging to this UserAccount if (!_characterIDs.Contains(characterID)) { const string errmsg = "Cannot use CharacterID `{0}` - that character does not belong to this UserAccount."; Debug.Fail(string.Format(errmsg, characterID)); if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, characterID); } return; } // Load the User try { _user = new User(this, world, characterID); } catch (Exception ex) { const string errmsg = "Failed to create user with ID `{0}`. Exception: {1}"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, characterID, ex); } Debug.Fail(string.Format(errmsg, characterID, ex)); Dispose(); return; } if (log.IsInfoEnabled) { log.InfoFormat("Set User `{0}` on account `{1}`.", _user, this); } }
/// <summary> /// Handles updating this <see cref="Entity"/>. /// </summary> /// <param name="imap">The map the <see cref="Entity"/> is on.</param> /// <param name="deltaTime">The amount of time (in milliseconds) that has elapsed since the last update.</param> protected override void HandleUpdate(IMap imap, int deltaTime) { ThreadAsserts.IsMainThread(); Debug.Assert(imap != null, "How the hell is a null Map updating?"); Debug.Assert(deltaTime >= 0, "Unless we're going back in time, deltaTime < 0 makes no sense at all."); // Perform pre-collision detection updating UpdatePreCollision(imap, deltaTime); // Performs basic entity updating base.HandleUpdate(imap, deltaTime); // Perform post-collision detection updating UpdatePostCollision(deltaTime); }
/// <summary> /// Adds a message to the InfoBox. /// </summary> /// <param name="message">Message to add.</param> /// <param name="color">Color of the message's text.</param> public void Add(string message, Color color) { ThreadAsserts.IsMainThread(); var newItem = new InfoBoxItem(TickCount.Now, message, color, _font); // If we are full, remove the old messages until we have room while (_items.Count >= _maxItems) { _items.RemoveAt(0); } // Add the new item to the list _items.Add(newItem); }
/// <summary> /// Tries to execute a command. /// </summary> /// <param name="commandString">The command string to execute.</param> /// <returns>The </returns> public string ExecuteCommand(string commandString) { ThreadAsserts.IsMainThread(); string result; if (!_parser.TryParse(this, commandString, out result)) { if (string.IsNullOrEmpty(result)) { const string errmsg = "Failed to execute command string: {0}"; result = string.Format(errmsg, commandString); } } return(result); }
/// <summary> /// Attempts to start shopping at a shop owned by the <paramref name="shopkeeper"/>. /// </summary> /// <param name="shopkeeper">The owner of the shop to try to start shopping at.</param> /// <returns>True if the shopping was successfully started at the <paramref name="shopkeeper"/>'s /// shop; otherwise false.</returns> public bool TryStartShopping(TShopOwner shopkeeper) { ThreadAsserts.IsMainThread(); if (shopkeeper == null) { return(false); } var shop = GetCharacterShop(shopkeeper); if (shop == null) { return(false); } return(TryStartShopping(shop, shopkeeper, GetCharacterMap(shopkeeper))); }
/// <summary> /// Attempts to sell <paramref name="amount"/> items from the given <paramref name="slot"/> to the /// shop that the shopper is currently shopping at. /// </summary> /// <param name="slot">The index of the inventory item to sell.</param> /// <param name="amount">The amount of the item to sell.</param> /// <returns>True if the sale was successful; otherwise false.</returns> public bool TrySellInventory(InventorySlot slot, byte amount) { ThreadAsserts.IsMainThread(); ValidateShop(); if (_shoppingAt == null) { return(false); } // Make sure the shop buys stuff if (!_shoppingAt.CanBuy) { return(false); } return(HandleSellInventoryItem(Character, slot, amount, _shoppingAt)); }
static void Main() { log.Info("Starting client..."); ThreadAsserts.IsMainThread(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // Try to copy dev content over CopyContent(); // Start the game using (var game = new DemoGame()) { game.Run(); } }
/// <summary> /// Handles the Tick event of the _timer control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> void _timer_Tick(object sender, EventArgs e) { ThreadAsserts.IsMainThread(); var now = TickCount.Now; // Some manual update calls if (ToolManager.Instance != null) { ToolManager.Instance.Update(now); } // Raise event if (Tick != null) { Tick.Raise(this, EventArgsHelper.Create(now)); } }
/// <summary> /// Performs validation checks on the shop to ensure it is valid. If the shop is invalid, /// <see cref="ShoppingAt"/> and other values will be set to null. /// </summary> void ValidateShop() { ThreadAsserts.IsMainThread(); // Check for a valid shop if (_shoppingAt == null || _shopOwner == null || _shopMap == null) { return; } // Check for a valid distance if (!IsValidDistance(Character, _shopOwner)) { // Stop shopping SendStopShopping(Character); _shoppingAt = null; _shopOwner = null; _shopMap = null; } }
/// <summary> /// Initializes a new instance of the <see cref="GlobalState"/> class. /// </summary> GlobalState() { ThreadAsserts.IsMainThread(); // Load all sorts of stuff _contentManager = NetGore.Content.ContentManager.Create(); var dbConnSettings = new DbConnectionSettings(); _dbController = dbConnSettings.CreateDbControllerPromptEditWhenInvalid(x => new ServerDbController(x.GetMySqlConnectionString()), x => dbConnSettings.PromptEditFileMessageBox(x)); _defaultRenderFont = ContentManager.LoadFont("Font/Arial", 16, ContentLevel.Global); Character.NameFont = DefaultRenderFont; GrhInfo.Load(ContentPaths.Dev, ContentManager); AutomaticGrhDataSizeUpdater.Instance.UpdateSizes(); _mapGrhWalls = new MapGrhWalls(ContentPaths.Dev, x => new WallEntity(x)); // Load the child classes _mapState = new MapState(this); // Grab the audio manager instances, which will ensure that they are property initialized // before something that can't pass it an ContentManager tries to get an instance AudioManager.GetInstance(ContentManager); // Set the custom UITypeEditors CustomUITypeEditors.AddEditors(DbController); // Set up the timer _timer = new Timer { Interval = 1000 / 60 }; _timer.Tick += _timer_Tick; }
/// <summary> /// Disposes of the <see cref="Entity"/>. /// </summary> public void Dispose() { ThreadAsserts.IsMainThread(); // Check if the Entity has already been disposed if (IsDisposed) { return; } GC.SuppressFinalize(this); _isDisposed = true; // Notify listeners that the Entity is being disposed if (Disposed != null) { Disposed.Raise(this, EventArgs.Empty); } // Handle the disposing HandleDispose(true); }
void RecvCreateNewAccount(IIPSocket conn, BitStream r) { ThreadAsserts.IsMainThread(); var name = r.ReadString(); var password = r.ReadString(); var email = r.ReadString(); // Ensure the connection isn't logged in var user = TryGetUser(conn, false); if (user != null) { const string errmsg = "User `{0}` tried to create a new account while already logged in."; if (log.IsWarnEnabled) { log.WarnFormat(errmsg, user); } return; } // Create the new account Server.CreateAccount(conn, name, password, email); }
/// <summary> /// Logs out the User from this UserAccount. If the <see cref="User"/> is not null and has not been disposed, /// this method will dispose of the User, too. /// </summary> public void CloseUser() { ThreadAsserts.IsMainThread(); var u = _user; if (u == null) { return; } _user = null; if (log.IsInfoEnabled) { log.InfoFormat("Closed User `{0}` on account `{1}`.", u, this); } // Make sure the user was disposed if (!u.IsDisposed) { u.Dispose(); } }
/// <summary> /// Updates the screen if it is currently the active screen. /// </summary> /// <param name="gameTime">The current game time.</param> public override void Update(TickCount gameTime) { ThreadAsserts.IsMainThread(); // Get the current time _currentTime = gameTime; if (UserChar == null) { _userLight.IsEnabled = false; return; } ScreenManager.AudioManager.ListenerPosition = UserChar.Center; // HACK: What a stupid way to make sure the correct inventory and equipped is used... _inventoryForm.Inventory = UserInfo.Inventory; _equippedForm.UserEquipped = UserInfo.Equipped; // Check to hide the shopping form from the user going out of range of the shop owner var shopInfo = ShopForm.ShopInfo; if (shopInfo != null && shopInfo.ShopOwner != null && !GameData.IsValidDistanceToShop(UserChar, shopInfo.ShopOwner)) { ShopForm.HideShop(); } // Update some other goodies World.Update(); _damageTextPool.Update(_currentTime); _guiStatePersister.Update(_currentTime); _emoticonDisplayManager.Update(_currentTime); // Update targeting _characterTargeter.Update(GUIManager); _gameControls.TargetIndex = _characterTargeter.TargetEntityIndex; // Update controls _gameControls.Update(GUIManager, _currentTime); var sock = _socket.RemoteSocket; if (_latencyLabel != null && sock != null && sock.IsConnected) { _latencyLabel.Text = string.Format(_latencyString, sock.AverageLatency < 1 ? "<1" : Math.Round(sock.AverageLatency).ToString()); } _userLight.IsEnabled = true; _userLight.SetCenter(UserChar.Center); // Periodically synchronize the game time if (Socket != null && _nextSyncGameTime < gameTime) { _nextSyncGameTime = gameTime + ClientSettings.Default.Network_SyncGameTimeFrequency; using (var pw = ClientPacket.SynchronizeGameTime()) { Socket.Send(pw, ClientMessageType.System); } } base.Update(gameTime); }
/// <summary> /// Initializes a new instance of the <see cref="Server"/> class. /// </summary> /// <exception cref="NotSupportedException">NetGore does not support systems that are not in Little Endian mode!</exception> public Server() { ThreadAsserts.IsMainThread(); // Check for some system settings if (!BitConverter.IsLittleEndian) { const string errmsg = "NetGore does not support systems that are not in Little Endian mode!"; log.Fatal(errmsg); throw new NotSupportedException(errmsg); } // Check if patching is needed int numMissingPatches = -1; try { numMissingPatches = ServerDbPatcher.GetMissingPatches().Length; } catch (Exception ex) { log.WarnFormat("Failed to find DbPatches directory, so could not check if patching is required. Exception: {0}", ex); } if (numMissingPatches > 0) { log.ErrorFormat("There are `{0}` NetGore db patches not applied. Please backup your database then run /DemoGame.Server/DbPatches/Patch.bat.", numMissingPatches); log.ErrorFormat("Server will auto-close after 10 seconds, and will keep doing this until you patch."); Thread.Sleep(10 * 1000); return; } // Initialize the engine settings EngineSettingsInitializer.Initialize(); // Create the DbController _dbController = CreateDbController(); // Add the query stats tracker var queryStats = new BasicQueryStatsTracker { LogFilePath = ContentPaths.Build.Root.Join("querystats.txt") }; queryStats.LogFileFrequency = 1000 * 5; _dbController.ConnectionPool.QueryStats = queryStats; // Validate the database DbTableValidator.ValidateTables(_dbController); ValidateDbControllerQueryAttributes(); // Clean-up var cleaner = new ServerCleaner(this); cleaner.Run(); // Create some objects _consoleCommands = new ConsoleCommands(this); _groupManager = new GroupManager((gm, x) => new Group(x)); _userAccountManager = new UserAccountManager(DbController); _world = new World(this); _sockets = new ServerSockets(this); WorldStatsTracker.Instance.NetPeerToTrack = _sockets.GetNetServer(); // Check for the password salt if (string.IsNullOrEmpty(ServerSettings.Default.PasswordSalt)) { const string errmsg = "No password salt has been defined in the server settings file. Make sure you define one before releasing."; if (log.IsWarnEnabled) { log.WarnFormat(errmsg); } } // Set the thread priority SetThreadPriority(ServerSettings.Default.ThreadPriority); // Validate the server's settings var ssv = new ServerSettingsValidator(); ssv.Check(this); if (log.IsInfoEnabled) { log.Info("Server loaded."); } }