/// <summary> /// Get the primary server that the player is online at. Returns null /// if the player is not online. /// </summary> /// <returns>The primary server that the player is online at is /// returned, else null if the player is not online.</returns> public GameServer GetOnlineServer() { GameCharacter Character = GetOnlineCharacter(); if (Character == null) { return(null); } return(Character.Server); }
/// <summary> /// Create a new CharacterPartEvent. /// </summary> /// <param name="Character">Supplies the character.</param> /// <param name="IsDM">Supplies true if the character was DM /// privileged at part time.</param> /// <param name="Server">Supplies the server that the character has /// parted.</param> public CharacterPartEvent(GameCharacter Character, bool IsDM, GameServer Server) { this.Character = Character; this.IsDM = IsDM; this.Server = Server; }
/// <summary> /// Reference the data for a character by the character name. If the /// data was not yet available, it is retrieved from the database. /// </summary> /// <param name="CharacterName">Supplies the object name.</param> /// <param name="Database">Supplies the database connection to use for /// queries, if required. The active rowset may be consumed.</param> /// <returns>The object data is returned, else null if the object did /// not exist.</returns> public GameCharacter ReferenceCharacterByName(string CharacterName, IALFADatabase Database) { // // Check if the object is already known first. // GameCharacter Character = (from C in Characters where C.CharacterName.Equals(CharacterName, StringComparison.InvariantCultureIgnoreCase) orderby C.Online descending select C).FirstOrDefault(); if (Character != null) return Character; // // Need to pull the data from the database. // if (Database == null) return null; int ServerId; Database.ACR_SQLQuery(String.Format( "SELECT `ID`, `PlayerID`, `IsOnline`, `ServerID`, `Name`, `Location` FROM `characters` WHERE `Name` = '{0}' AND `IsDeleted` = 0 AND `IsPlayable` = 1 ORDER BY `ID` ASC ", Database.ACR_SQLEncodeSpecialChars(CharacterName))); if (!Database.ACR_SQLFetch()) return null; Character = new GameCharacter(this); Character.CharacterId = Convert.ToInt32(Database.ACR_SQLGetData(0)); Character.PlayerId = Convert.ToInt32(Database.ACR_SQLGetData(1)); Character.Online = ConvertToBoolean(Database.ACR_SQLGetData(2)); ServerId = Convert.ToInt32(Database.ACR_SQLGetData(3)); Character.CharacterName = Database.ACR_SQLGetData(4); Character.LocationString = Database.ACR_SQLGetData(5); InsertNewCharacter(Character, ServerId, Database, null); return Character; }
/// <summary> /// This function inserts a character into the various character lists /// and issues the character join event. /// </summary> /// <param name="Character">Supplies the character object to insert. /// </param> /// <param name="ServerId">Supplies the server id that the player is /// logged on to (only meaningful if the character is online).</param> /// <param name="Database">Supplies the database connection to use for /// queries, if required. The active rowset may be consumed.</param> /// <param name="InitialDMState">Supplies the initial DM state of the /// backing player object to update, for a synchronization of an /// existing player with a new character.</param> private void InsertNewCharacter(GameCharacter Character, int ServerId, IALFADatabase Database, bool? InitialDMState) { GameServer Server; Character.Player = ReferencePlayerById(Character.PlayerId, Database); if (Character.Player == null) throw new ApplicationException(String.Format("Character {0} references invalid player id {1}", Character.CharacterId, Character.PlayerId)); if (InitialDMState != null) Character.Player.IsDM = (InitialDMState != false); Character.Player.Characters.Add(Character); try { CharacterList.Add(Character); try { if (Character.Online) { Server = ReferenceServerById(ServerId, Database); if (Server == null) throw new ApplicationException(String.Format("Character {0} is online but references invalid server id {1}", Character.CharacterId, ServerId)); Character.Server = Server; // // If the character is coming online, but its associated server is // not actually online, then mark the character as offline. // if (Character.Online && !Character.Server.Online) { Character.Online = false; return; } // // Mark the character as visited so that if we come in // on the main thread during the middle of a character // synchronization cycle, we won't immediate offline // the character. // Character.Visited = true; Character.Server = Server; Character.Server.Characters.Add(Character); try { OnlineCharacterList.Add(Character); try { Character.Player.UpdateOnlineCharacter(); OnCharacterJoin(Character); } catch { OnlineCharacterList.Remove(Character); throw; } } catch { Character.Server.Characters.Remove(Character); throw; } } } catch { CharacterList.Remove(Character); throw; } } catch { Character.Player.Characters.Remove(Character); Character.Player.UpdateOnlineCharacter(); throw; } }
/// <summary> /// This method is called when a character is discovered to have gone /// offline. /// </summary> /// <param name="Character">Supplies the character that is now /// considered to be offline.</param> private void OnCharacterPart(GameCharacter Character) { EnqueueEvent(new CharacterPartEvent(Character, Character.Player.IsDM, Character.Server)); }
/// <summary> /// This method is called when a chat tell IPC event is received. /// </summary> /// <param name="Sender">Supplies the sender.</param> /// <param name="Recipient">Supplies the recipient.</param> /// <param name="Message">Supplies the message text.</param> private void OnChatTell(GameCharacter Sender, GamePlayer Recipient, string Message) { EnqueueEvent(new ChatTellEvent(Sender, Recipient, Message)); }
/// <summary> /// This method performs the initial synchronization step at first run /// that downloads the initial character list. A bulk query is issued /// here to reduce the number of database round-trips at startup time. /// /// Note that no attempt is made to mark offline characters here. That /// step is done in the normal synchronization round, as this is the /// initial round anyway. /// </summary> private void PerformInitialSynchronization() { IALFADatabase Database = DatabaseLinkQueryThread; List<InitialSynchronizationRow> Rowset = new List<InitialSynchronizationRow>(); Database.ACR_SQLQuery( "SELECT " + "`characters`.`ID` AS character_id, " + // 0 "`characters`.`PlayerID` AS player_id, " + // 1 "`characters`.`Name` AS character_name, " + // 2 "`characters`.`ServerID` AS server_id, " + // 3 "`characters`.`Location` AS character_location, " + // 4 "`players`.`IsDM` AS player_is_dm, " + // 5 "`players`.`Name` AS player_name, " + // 6 "`servers`.`IPAddress` AS server_address_string, " + // 7 "`servers`.`Name` AS server_name " + // 8 "FROM " + "`characters` " + "INNER JOIN `servers` ON `characters`.`ServerID` = `servers`.`ID` " + "INNER JOIN `players` ON `characters`.`PlayerID` = `players`.`ID` " + "WHERE " + "`characters`.`IsOnline` = 1 " ); while (Database.ACR_SQLFetch()) { InitialSynchronizationRow Row; Row.CharacterId = Convert.ToInt32(Database.ACR_SQLGetData(0)); Row.PlayerId = Convert.ToInt32(Database.ACR_SQLGetData(1)); Row.CharacterName = Database.ACR_SQLGetData(2); Row.ServerId = Convert.ToInt32(Database.ACR_SQLGetData(3)); Row.CharacterLocation = Database.ACR_SQLGetData(4); Row.PlayerIsDM = ConvertToBoolean(Database.ACR_SQLGetData(5)); Row.PlayerName = Database.ACR_SQLGetData(6); Row.ServerAddressString = Database.ACR_SQLGetData(7); Row.ServerName = Database.ACR_SQLGetData(8); Rowset.Add(Row); } lock (this) { // // Update entries. // foreach (InitialSynchronizationRow Row in Rowset) { GameServer Server = (from S in Servers where S.ServerId == Row.ServerId select S).FirstOrDefault(); if (Server == null) { Server = new GameServer(this); Server.ServerName = Row.ServerName; Server.ServerId = Row.ServerId; Server.SetHostnameAndPort(Row.ServerAddressString); InsertNewServer(Server, Database); } GamePlayer Player = (from P in Players where P.PlayerId == Row.PlayerId select P).FirstOrDefault(); if (Player == null) { Player = new GamePlayer(this); Player.PlayerName = Row.PlayerName; Player.PlayerId = Row.PlayerId; Player.IsDM = Row.PlayerIsDM; InsertNewPlayer(Player, Database); } GameCharacter Character = (from C in Characters where C.CharacterId == Row.CharacterId select C).FirstOrDefault(); if (Character == null) { Character = new GameCharacter(this); Character.CharacterId = Row.CharacterId; Character.PlayerId = Row.PlayerId; Character.Online = true; Character.CharacterName = Row.CharacterName; Character.LocationString = Row.CharacterLocation; InsertNewCharacter(Character, Row.ServerId, Database, null); } } #if DEBUG_MODE WriteDiagnosticLog(String.Format("GameWorldManager.PerformInitialSynchronization: Synchronized {0} servers, {1} players, {2} characters.", ServerList.Count, PlayerList.Count, CharacterList.Count)); #endif } }
/// <summary> /// Reference the data for a character by the character id. If the /// data was not yet available, it is retrieved from the database. /// </summary> /// <param name="CharacterId">Supplies the object id.</param> /// <param name="Database">Supplies the database connection to use for /// queries, if required. The active rowset may be consumed.</param> /// <param name="InitialDMState">Supplies the initial DM state of the /// backing player object to update, for a synchronization of an /// existing player with a new character.</param> /// <returns>The object data is returned, else null if the object did /// not exist.</returns> public GameCharacter ReferenceCharacterById(int CharacterId, IALFADatabase Database, bool? InitialDMState) { // // Check if the object is already known first. // GameCharacter Character = (from C in Characters where C.CharacterId == CharacterId select C).FirstOrDefault(); if (Character != null) return Character; // // Need to pull the data from the database. // if (Database == null) return null; int ServerId; Database.ACR_SQLQuery(String.Format( "SELECT `Name`, `PlayerID`, `IsOnline`, `ServerID`, `Location` FROM `characters` WHERE `ID` = {0}", CharacterId)); if (!Database.ACR_SQLFetch()) return null; Character = new GameCharacter(this); Character.CharacterName = Database.ACR_SQLGetData(0); Character.CharacterId = CharacterId; Character.PlayerId = Convert.ToInt32(Database.ACR_SQLGetData(1)); Character.Online = ConvertToBoolean(Database.ACR_SQLGetData(2)); ServerId = Convert.ToInt32(Database.ACR_SQLGetData(3)); Character.LocationString = Database.ACR_SQLGetData(4); InsertNewCharacter(Character, ServerId, Database, InitialDMState); return Character; }
/// <summary> /// Create a new ChatTellEvent. /// </summary> /// <param name="Sender">Supplies the sender.</param> /// <param name="Recipient">Supplies the recipient.</param> /// <param name="Message">Supplies the message text.</param> public ChatTellEvent(GameCharacter Sender, GamePlayer Recipient, string Message) { this.Sender = Sender; this.Recipient = Recipient; this.Message = Message; }
/// <summary> /// Create a new CharacterJoinEvent. /// </summary> /// <param name="Character">Supplies the character.</param> /// <param name="IsDM">Supplies true if the character was DM /// privileged at join time.</param> /// <param name="Server">Supplies the server that the character has /// joined.</param> public CharacterJoinEvent(GameCharacter Character, bool IsDM, GameServer Server) { this.Character = Character; this.IsDM = IsDM; this.Server = Server; }