/// <summary> /// Create a new DisconnectPlayerEvent. /// </summary> /// <param name="Player">Supplies the player to disconnect.</param> public DisconnectPlayerEvent(GamePlayer Player) { this.Player = Player; }
/// <summary> /// This function inserts a player into the various player lists and /// issues the player load event. /// </summary> /// <param name="Player">Supplies the player object to insert. /// </param> /// <param name="Database">Supplies the database connection to use for /// queries, if required. The active rowset may be consumed.</param> private void InsertNewPlayer(GamePlayer Player, IALFADatabase Database) { PlayerList.Add(Player); OnPlayerLoaded(Player); }
/// <summary> /// This method initiates a server-to-server tell. /// </summary> /// <param name="SenderObjectId">Supplies the local object id of the /// sender player.</param> /// <param name="SenderPlayer">Supplies the GamePlayer object for the /// sender player.</param> /// <param name="RecipientPlayer">Supplies the GamePlayer object for /// the recipient player.</param> /// <param name="Message">Supplies the message to send.</param> private void SendServerToServerTell(uint SenderObjectId, GamePlayer SenderPlayer, GamePlayer RecipientPlayer, string Message) { GameServer DestinationServer = RecipientPlayer.GetOnlineServer(); Database.ACR_IncrementStatistic("SERVER_TELLS"); SetLastTellToPlayerId(SenderObjectId, RecipientPlayer.PlayerId); if (!RecipientPlayer.IsOnline() || DestinationServer == null) { SendFeedbackError(SenderObjectId, "That player is not logged on."); return; } #if DEBUG_MODE // // Debug mode always sends through the IPC queue for better // testing. // #else // // If this is a local server tell, dispatch it locally. // if (DestinationServer.ServerId == Database.ACR_GetServerID()) { foreach (uint PlayerObject in GetPlayers(true)) { if (Database.ACR_GetPlayerID(PlayerObject) != SenderPlayer.PlayerId) continue; // // Note, we call the chat callback for the first event for // two reasons: // // 1) Let the RP XP script notice the activity. // 2) Set the last tell to/from player ids. // SendChatMessage(SenderObjectId, PlayerObject, CHAT_MODE_TELL, Message, TRUE); return; } SendFeedbackError(SenderObjectId, "Internal error - attempted to re-route tell to local player, but player wasn't actually on this server."); return; } #endif if (Database.ACR_GetIsPCQuarantined(SenderObjectId)) { // // Since a player in quarantine is not marked as online, a // remote server may choose to discard a tell initiated while // in quarantine. Warn the player of this. // SendFeedbackError(SenderObjectId, "Warning: Cross-server tells may not be delivered when in quarantine."); } // // Otherwise, enqueue it, breaking large tells up into multiple // smaller tells if need be. // while (!String.IsNullOrEmpty(Message)) { string MessagePart; if (Message.Length > ACR_SERVER_IPC_MAX_EVENT_LENGTH) { MessagePart = Message.Substring(0, ACR_SERVER_IPC_MAX_EVENT_LENGTH); Message = Message.Substring(ACR_SERVER_IPC_MAX_EVENT_LENGTH); } else { MessagePart = Message; Message = null; } SignalIPCEvent( SenderPlayer.PlayerId, Database.ACR_GetServerID(), RecipientPlayer.PlayerId, DestinationServer.ServerId, GameWorldManager.ACR_SERVER_IPC_EVENT_CHAT_TELL, MessagePart); SendChatMessage( OBJECT_INVALID, SenderObjectId, CHAT_MODE_SERVER, String.Format("<c=#FFCC99>{0}: </c><c=#30DDCC>[ServerTell] {1}</c>", GetName(SenderObjectId), MessagePart), FALSE); } SetLocalInt(SenderObjectId, "ACR_XP_RPXP_ACTIVE", TRUE); }
/// <summary> /// This method is called when a page 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 OnPage(GamePlayer Sender, GamePlayer Recipient, string Message) { EnqueueEvent(new PageEvent(Sender, Recipient, Message)); }
/// <summary> /// This method is called when a player has had all of its data loaded /// from the database. The player is inserted already. /// </summary> /// <param name="Player">Supplies the player object hwich has been /// loaded.</param> private void OnPlayerLoaded(GamePlayer Player) { }
/// <summary> /// This method is called when a disconnect player request is received. /// </summary> /// <param name="Player">Supplies the player to disconnect.</param> private void OnDisconnectPlayer(GamePlayer Player) { EnqueueEvent(new DisconnectPlayerEvent(Player)); }
/// <summary> /// This method is called when a purge cached character request is /// received. /// </summary> /// <param name="Player">Supplies the player whose cached vault /// contents are to be modified.</param> /// <param name="CharacterFileName">Supplies the file name of the /// character file to remove from the local cache. Special file names /// and path characters are forbidden.</param> private void OnPurgeCachedCharacter(GamePlayer Player, string CharacterFileName) { if (!SystemInfo.IsSafeFileName(CharacterFileName)) { WriteDiagnosticLog(String.Format( "GameWorldManager.OnPurgeCachedCharacter: Invalid file name '{0}'.", CharacterFileName)); return; } EnqueueEvent(new PurgeCachedCharacterEvent(Player, CharacterFileName)); }
/// <summary> /// Reference the data for a player by the player id. If the data /// was not yet available, it is retrieved from the database. /// </summary> /// <param name="PlayerId">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> /// <returns>The object data is returned, else null if the object did /// not exist.</returns> public GamePlayer ReferencePlayerById(int PlayerId, IALFADatabase Database) { // // Check if the object is already known first. // GamePlayer Player = (from P in Players where P.PlayerId == PlayerId select P).FirstOrDefault(); if (Player != null) return Player; // // Need to pull the data from the database. // if (Database == null) return null; Database.ACR_SQLQuery(String.Format( "SELECT `Name`, `IsDM` FROM `players` WHERE `ID` = {0}", PlayerId)); if (!Database.ACR_SQLFetch()) return null; Player = new GamePlayer(this); Player.PlayerName = Database.ACR_SQLGetData(0); Player.PlayerId = PlayerId; Player.IsDM = ConvertToBoolean(Database.ACR_SQLGetData(1)); InsertNewPlayer(Player, Database); return Player; }
/// <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> /// Reference the data for a player by the player name. If the data /// was not yet available, it is retrieved from the database. /// </summary> /// <param name="PlayerName">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 GamePlayer ReferencePlayerByName(string PlayerName, IALFADatabase Database) { // // Check if the object is already known first. // GamePlayer Player = (from P in Players where P.PlayerName.Equals(PlayerName, StringComparison.InvariantCultureIgnoreCase) select P).FirstOrDefault(); if (Player != null) return Player; // // Need to pull the data from the database. // if (Database == null) return null; Database.ACR_SQLQuery(String.Format( "SELECT `ID`, `IsDM`, `Name` FROM `players` WHERE `Name` = '{0}'", Database.ACR_SQLEncodeSpecialChars(PlayerName))); if (!Database.ACR_SQLFetch()) return null; Player = new GamePlayer(this); Player.PlayerId = Convert.ToInt32(Database.ACR_SQLGetData(0)); Player.IsDM = ConvertToBoolean(Database.ACR_SQLGetData(1)); Player.PlayerName = Database.ACR_SQLGetData(2); InsertNewPlayer(Player, Database); return Player; }
/// <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> /// 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 PurgeCachedCharacterEvent. /// </summary> /// <param name="Player">Supplies the player whose vault should have /// the specific character file removed.</param> /// <param name="CharacterFileName">Supplies the character file name to /// delete. There should be no path separators, for example, /// "charfile.bic".</param> public PurgeCachedCharacterEvent(GamePlayer Player, string CharacterFileName) { this.Player = Player; this.CharacterFileName = CharacterFileName; }
/// <summary> /// Create a new PageEvent. /// </summary> /// <param name="Sender">Supplies the sender.</param> /// <param name="Recipient">Supplies the recipient.</param> /// <param name="Message">Supplies the message text.</param> public PageEvent(GamePlayer Sender, GamePlayer Recipient, string Message) { this.Sender = Sender; this.Recipient = Recipient; this.Message = Message; }