diff options
-rw-r--r-- | sql/base/characters_database.sql | 27 | ||||
-rw-r--r-- | sql/base/world_database.sql | 6 | ||||
-rw-r--r-- | sql/updates/10000_characters_character_banned.sql | 10 | ||||
-rw-r--r-- | sql/updates/10000_world_command.sql | 4 | ||||
-rw-r--r-- | sql/updates/10000_world_trinity_string.sql | 5 | ||||
-rw-r--r-- | src/server/game/Chat/Chat.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Chat/Chat.h | 2 | ||||
-rw-r--r-- | src/server/game/Chat/Commands/Level3.cpp | 209 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 3 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/Language.h | 5 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp | 15 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 66 | ||||
-rw-r--r-- | src/server/game/World/World.h | 2 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 8 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.h | 8 |
16 files changed, 358 insertions, 36 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 0ca70b84dec..ede2e59e225 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -489,6 +489,33 @@ LOCK TABLES `character_aura` WRITE; UNLOCK TABLES; -- +-- Table structure for table `character_banned` +-- + +DROP TABLE IF EXISTS `character_banned`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `character_banned` ( + `guid` int(11) NOT NULL default '0' COMMENT 'Account id', + `bandate` bigint(40) NOT NULL default '0', + `unbandate` bigint(40) NOT NULL default '0', + `bannedby` varchar(50) NOT NULL, + `banreason` varchar(255) NOT NULL, + `active` tinyint(4) NOT NULL default '1', + PRIMARY KEY (`guid`,`bandate`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Ban List'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `character_banned` +-- + +LOCK TABLES `character_banned` WRITE; +/*!40000 ALTER TABLE `character_banned` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_banned` ENABLE KEYS */; +UNLOCK TABLES; + +-- -- Table structure for table `character_battleground_data` -- diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql index d0731fa8a6f..a503b591cbb 100644 --- a/sql/base/world_database.sql +++ b/sql/base/world_database.sql @@ -334,7 +334,8 @@ INSERT INTO `command` VALUES ('aura',3,'Syntax: .aura #spellid\r\n\r\nAdd the aura from spell #spellid to the selected Unit.'), ('ban',3,'Syntax: .ban $subcommand\nType .ban to see the list of possible subcommands or .help ban $subcommand to see info on subcommands'), ('ban account',3,'Syntax: .ban account $Name $bantime $reason\r\nBan account kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'), -('ban character',3,'Syntax: .ban character $Name $bantime $reason\r\nBan account and kick player.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'), +('ban character',3,'Syntax: .ban character $Name $bantime $reason\nBan character and kick player.\n$bantime: negative value leads to permban, otherwise use a timestring like "4d20h3s".'), +('ban playeraccount',3,'Syntax: .ban playeraccount $Name $bantime $reason\nBan account and kick player.\n$bantime: negative value leads to permban, otherwise use a timestring like "4d20h3s".'), ('ban ip',3,'Syntax: .ban ip $Ip $bantime $reason\r\nBan IP.\r\n$bantime: negative value leads to permban, otherwise use a timestring like \"4d20h3s\".'), ('baninfo',3,'Syntax: .baninfo $subcommand\nType .baninfo to see the list of possible subcommands or .help baninfo $subcommand to see info on subcommands'), ('baninfo account',3,'Syntax: .baninfo account $accountid\r\nWatch full information about a specific ban.'), @@ -27604,6 +27605,9 @@ INSERT INTO `trinity_string` (`entry`,`content_default`,`content_loc1`,`content_ (1128, '%d - |cffffffff|Htaxinode:%u|h[%s %s]|h|r (Map:%u X:%f Y:%f Z:%f)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1129, '%d - %s %s (Map:%u X:%f Y:%f Z:%f)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1130, 'Can''t dump deleted characters, aborting.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), +(1131, 'The following characters match your query:', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), +(1132, 'Currently Banned Characters:', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), +(1133, '| Character | BanDate | UnbanDate | Banned By | Ban Reason |', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1200, 'You try to view cinemitic %u but it doesn''t exist.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1201, 'You try to view movie %u but it doesn''t exist.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1300, 'Alliance', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), diff --git a/sql/updates/10000_characters_character_banned.sql b/sql/updates/10000_characters_character_banned.sql new file mode 100644 index 00000000000..99c9195ad62 --- /dev/null +++ b/sql/updates/10000_characters_character_banned.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `character_banned`; +CREATE TABLE `character_banned` ( + `guid` int(11) NOT NULL default '0' COMMENT 'Account id', + `bandate` bigint(40) NOT NULL default '0', + `unbandate` bigint(40) NOT NULL default '0', + `bannedby` varchar(50) NOT NULL, + `banreason` varchar(255) NOT NULL, + `active` tinyint(4) NOT NULL default '1', + PRIMARY KEY (`guid`,`bandate`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Ban List'; diff --git a/sql/updates/10000_world_command.sql b/sql/updates/10000_world_command.sql new file mode 100644 index 00000000000..75717ac6aad --- /dev/null +++ b/sql/updates/10000_world_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` IN ('ban character','ban playeraccount'); +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('ban character',3,'Syntax: .ban character $Name $bantime $reason\nBan character and kick player.\n$bantime: negative value leads to permban, otherwise use a timestring like "4d20h3s".'), +('ban playeraccount',3,'Syntax: .ban playeraccount $Name $bantime $reason\nBan account and kick player.\n$bantime: negative value leads to permban, otherwise use a timestring like "4d20h3s".'); diff --git a/sql/updates/10000_world_trinity_string.sql b/sql/updates/10000_world_trinity_string.sql new file mode 100644 index 00000000000..40e970f8197 --- /dev/null +++ b/sql/updates/10000_world_trinity_string.sql @@ -0,0 +1,5 @@ +DELETE FROM `trinity_string` WHERE `entry` IN (1131,1132,1133); +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(1131, 'The following characters match your query:'), +(1132, 'Currently Banned Characters:'), +(1133, '| Character | BanDate | UnbanDate | Banned By | Ban Reason |'); diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 3c5793ae543..5714fbeb25f 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -90,6 +90,7 @@ ChatCommand * ChatHandler::getCommandTable() { { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanAccountCommand, "", NULL }, { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanCharacterCommand, "", NULL }, + { "playeraccount", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanAccountByCharCommand, "", NULL }, { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanIPCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -646,10 +647,11 @@ ChatCommand * ChatHandler::getCommandTable() static ChatCommand unbanCommandTable[] = { - { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanAccountCommand, "", NULL }, - { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanCharacterCommand, "", NULL }, - { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanAccountCommand, "", NULL }, + { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanCharacterCommand, "", NULL }, + { "playeraccount", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanAccountByCharCommand, "", NULL }, + { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand wpCommandTable[] = diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 187ef78ca1c..f0478e3c890 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -122,6 +122,7 @@ class ChatHandler bool HandleGMNotifyCommand(const char* args); bool HandleBanAccountCommand(const char* args); + bool HandleBanAccountByCharCommand(const char* args); bool HandleBanCharacterCommand(const char* args); bool HandleBanIPCommand(const char* args); bool HandleBanInfoAccountCommand(const char* args); @@ -492,6 +493,7 @@ class ChatHandler bool HandleTitlesSetMaskCommand(const char* args); bool HandleUnBanAccountCommand(const char* args); + bool HandleUnBanAccountByCharCommand(const char* args); bool HandleUnBanCharacterCommand(const char* args); bool HandleUnBanIPCommand(const char* args); diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index a0431714de7..f01636bdd8a 100644 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -5601,11 +5601,58 @@ bool ChatHandler::HandleBanAccountCommand(const char *args) return HandleBanHelper(BAN_ACCOUNT,args); } -bool ChatHandler::HandleBanCharacterCommand(const char *args) +bool ChatHandler::HandleBanAccountByCharCommand(const char *args) { return HandleBanHelper(BAN_CHARACTER,args); } +bool ChatHandler::HandleBanCharacterCommand(const char *args) +{ + if (!*args) + return false; + + char* cname = strtok((char*)args, " "); + if (!cname) + return false; + + std::string name = cname; + + char* duration = strtok(NULL," "); + if (!duration || !atoi(duration)) + return false; + + char* reason = strtok(NULL,""); + if (!reason) + return false; + + if (!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + switch (sWorld.BanCharacter(name, duration, reason, m_session ? m_session->GetPlayerName() : "")) + { + case BAN_SUCCESS: + { + if (atoi(duration) > 0) + PSendSysMessage(LANG_BAN_YOUBANNED, name.c_str(), secsToTimeString(TimeStringToSecs(duration), true).c_str(), reason); + else + PSendSysMessage(LANG_BAN_YOUPERMBANNED, name.c_str(), reason); + break; + } + case BAN_NOTFOUND: + { + PSendSysMessage(LANG_BAN_NOTFOUND, "character", name.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + return true; +} + bool ChatHandler::HandleBanIPCommand(const char *args) { return HandleBanHelper(BAN_IP,args); @@ -5686,17 +5733,45 @@ bool ChatHandler::HandleBanHelper(BanMode mode, const char *args) bool ChatHandler::HandleUnBanAccountCommand(const char *args) { - return HandleUnBanHelper(BAN_ACCOUNT,args); + return HandleUnBanHelper(BAN_ACCOUNT, args); +} + +bool ChatHandler::HandleUnBanAccountByCharCommand(const char *args) +{ + return HandleUnBanHelper(BAN_CHARACTER, args); } bool ChatHandler::HandleUnBanCharacterCommand(const char *args) { - return HandleUnBanHelper(BAN_CHARACTER,args); + if (!*args) + return false; + + char* cname = strtok((char*)args, " "); + if (!cname) + return false; + + std::string name = cname; + + if (!normalizePlayerName(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if (!sWorld.RemoveBanCharacter(name)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + return true; } bool ChatHandler::HandleUnBanIPCommand(const char *args) { - return HandleUnBanHelper(BAN_IP,args); + return HandleUnBanHelper(BAN_IP, args); } bool ChatHandler::HandleUnBanHelper(BanMode mode, const char *args) @@ -5771,21 +5846,50 @@ bool ChatHandler::HandleBanInfoAccountCommand(const char *args) bool ChatHandler::HandleBanInfoCharacterCommand(const char *args) { - Player* target; - uint64 target_guid; - if (!extractPlayerTarget((char*)args,&target,&target_guid)) + if (!*args) return false; - uint32 accountid = target ? target->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(target_guid); + Player* target = sObjectMgr.GetPlayer(args); + uint32 target_guid = 0; + std::string name(args); - std::string accountname; - if (!sAccountMgr.GetName(accountid,accountname)) + if (!target) { - PSendSysMessage(LANG_BANINFO_NOCHARACTER); - return true; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_GUID_BY_NAME); + stmt->setString(0, name); + PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt); + + if (!resultCharacter) + { + PSendSysMessage(LANG_BANINFO_NOCHARACTER); + return false; + } + + target_guid = resultCharacter->GetUInt32(0); } + else + target_guid = target->GetGUIDLow(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_BANINFO); + stmt->setUInt32(0, target_guid); + PreparedQueryResult result = CharacterDatabase.Query(stmt); + if (!result) + return true; + + PSendSysMessage(LANG_BANINFO_BANHISTORY, name.c_str()); + do + { + time_t unbandate = time_t(result->GetUInt64(3)); + bool active = false; + if (result->GetUInt8(2) && (!result->GetUInt64(1) || unbandate >= time(NULL))) + active = true; + bool permanent = (result->GetUInt64(1) == uint64(0)); + std::string bantime = permanent ? GetTrinityString(LANG_BANINFO_INFINITE) : secsToTimeString(result->GetUInt64(1), true); + PSendSysMessage(LANG_BANINFO_HISTORYENTRY, + result->GetCString(0), bantime.c_str(), active ? GetTrinityString(LANG_BANINFO_YES) : GetTrinityString(LANG_BANINFO_NO), result->GetCString(4), result->GetCString(5)); + } while (result->NextRow()); - return HandleBanInfoHelper(accountid,accountname.c_str()); + return true; } bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) @@ -5797,7 +5901,7 @@ bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) return true; } - PSendSysMessage(LANG_BANINFO_BANHISTORY,accountname); + PSendSysMessage(LANG_BANINFO_BANHISTORY, accountname); do { Field* fields = result->Fetch(); @@ -5807,10 +5911,10 @@ bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) if (fields[2].GetBool() && (fields[1].GetUInt64() == (uint64)0 ||unbandate >= time(NULL))) active = true; bool permanent = (fields[1].GetUInt64() == (uint64)0); - std::string bantime = permanent ? GetTrinityString(LANG_BANINFO_INFINITE) : secsToTimeString(fields[1].GetUInt64(), true); + std::string bantime = permanent?GetTrinityString(LANG_BANINFO_INFINITE):secsToTimeString(fields[1].GetUInt64(), true); PSendSysMessage(LANG_BANINFO_HISTORYENTRY, fields[0].GetString(), bantime.c_str(), active ? GetTrinityString(LANG_BANINFO_YES):GetTrinityString(LANG_BANINFO_NO), fields[4].GetString(), fields[5].GetString()); - }while (result->NextRow()); + } while (result->NextRow()); return true; } @@ -5848,22 +5952,83 @@ bool ChatHandler::HandleBanInfoIPCommand(const char *args) bool ChatHandler::HandleBanListCharacterCommand(const char *args) { - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); + if (!*args) + return false; - char* cFilter = strtok ((char*)args, " "); + char* cFilter = strtok((char*)args, " "); if (!cFilter) return false; - std::string filter = cFilter; - LoginDatabase.escape_string(filter); - QueryResult result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),filter.c_str()); + std::string filter(cFilter); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_GUID_BY_NAME_FILTER); + stmt->setString(0, filter.c_str()); + PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { PSendSysMessage(LANG_BANLIST_NOCHARACTER); return true; } - return HandleBanListHelper(result); + PSendSysMessage(LANG_BANLIST_MATCHINGCHARACTER); + + // Chat short output + if (m_session) + { + do + { + PreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_GET_BANNED_NAME); + stmt2->setUInt32(0, result->GetUInt32(0)); + PreparedQueryResult banresult = CharacterDatabase.Query(stmt2); + if (banresult) + PSendSysMessage("%s", banresult->GetCString(0)); + } while (result->NextRow()); + } + // Console wide output + else + { + SendSysMessage(LANG_BANLIST_CHARACTERS); + SendSysMessage(" =============================================================================== "); + SendSysMessage(LANG_BANLIST_CHARACTERS_HEADER); + do + { + SendSysMessage("-------------------------------------------------------------------------------"); + + std::string char_name; + + char_name = result->GetString(1); + + PreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_GET_BANINFO_LIST); + stmt2->setUInt32(0, result->GetUInt32(0)); + PreparedQueryResult banInfo = CharacterDatabase.Query(stmt2); + if (banInfo) + { + do + { + time_t t_ban = banInfo->GetUInt64(0); + tm* aTm_ban = localtime(&t_ban); + + if (banInfo->GetUInt64(0) == banInfo->GetUInt64(1)) + { + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", + char_name.c_str(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + banInfo->GetCString(2), banInfo->GetCString(3)); + } + else + { + time_t t_unban = banInfo->GetUInt64(1); + tm* aTm_unban = localtime(&t_unban); + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", + char_name.c_str(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min, + banInfo->GetCString(2), banInfo->GetCString(3)); + } + } while (banInfo->NextRow()); + } + } while (result->NextRow()); + SendSysMessage(" =============================================================================== "); + } + + return true; } bool ChatHandler::HandleBanListAccountCommand(const char *args) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1d306c13d0c..14ebd7f2b4c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1593,8 +1593,8 @@ bool Player::BuildEnumData(QueryResult result, WorldPacket * p_data) // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " // 8 9 10 11 12 13 14 // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 20 - // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_declinedname.genitive " + // 15 16 17 18 19 20 21 + // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, character_declinedname.genitive " Field *fields = result->Fetch(); @@ -1645,9 +1645,11 @@ bool Player::BuildEnumData(QueryResult result, WorldPacket * p_data) char_flags |= CHARACTER_FLAG_GHOST; if (atLoginFlags & AT_LOGIN_RENAME) char_flags |= CHARACTER_FLAG_RENAME; + if (fields[20].GetUInt32()) + char_flags |= CHARACTER_FLAG_LOCKED_BY_BILLING; if (sWorld.getBoolConfig(CONFIG_DECLINED_NAMES_USED)) { - if (!fields[20].GetCppString().empty()) + if (!fields[21].GetCppString().empty()) char_flags |= CHARACTER_FLAG_DECLINED; } else @@ -15880,6 +15882,12 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) return false; } + if (holder->GetResult(PLAYER_LOGIN_QUERY_LOADBANNED)) + { + sLog.outError("Player (GUID: %u) is banned, can't load.", guid); + return false; + } + Object::_Create(guid, 0, HIGHGUID_PLAYER); m_name = fields[2].GetCppString(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ed6f87b5f32..f60e4c9d13b 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -789,7 +789,8 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS = 26, PLAYER_LOGIN_QUERY_LOADRANDOMBG = 27, PLAYER_LOGIN_QUERY_LOADARENASTATS = 28, - MAX_PLAYER_LOGIN_QUERY = 29 + PLAYER_LOGIN_QUERY_LOADBANNED = 29, + MAX_PLAYER_LOGIN_QUERY = 30 }; enum PlayerDelayedOperations diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 40f346a4a53..f26581f2db2 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -794,7 +794,10 @@ enum TrinityStrings LANG_TAXINODE_ENTRY_LIST_CHAT = 1128, LANG_TAXINODE_ENTRY_LIST_CONSOLE = 1129, LANG_COMMAND_EXPORT_DELETED_CHAR = 1130, - // Room for more level 3 1131-1199 not used + LANG_BANLIST_MATCHINGCHARACTER = 1131, + LANG_BANLIST_CHARACTERS = 1132, + LANG_BANLIST_CHARACTERS_HEADER = 1133, + // Room for more level 3 1134-1199 not used // Debug commands LANG_CINEMATIC_NOT_EXIST = 1200, diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index 120341d96ee..c7e9d01653b 100644 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -100,6 +100,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADRANDOMBG, "SELECT guid FROM character_battleground_random WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENASTATS, "SELECT slot, personal_rating, matchmaker_rating FROM character_arena_stats WHERE guid = '%u' ORDER BY slot ASC", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBANNED, "SELECT guid FROM character_banned WHERE id = %u AND active = 1", GUID_LOPART(m_guid)); return res; } @@ -131,6 +132,10 @@ void WorldSession::HandleCharEnum(QueryResult result) void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) { + // remove expired bans + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_BANS); + CharacterDatabase.Execute(stmt); + /// get all the data necessary for loading all characters (along with their pets) on the account m_charEnumCallback = CharacterDatabase.AsyncPQuery( @@ -140,10 +145,11 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " // 8 9 10 11 12 13 14 "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache " + // 15 16 17 18 19 20 + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_banned.guid " "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' " "LEFT JOIN guild_member ON characters.guid = guild_member.guid " + "LEFT JOIN character_banned ON characters.guid = character_banned.guid AND character_banned.active = 1 " "WHERE characters.account = '%u' ORDER BY characters.guid" : // --------- Query With Declined Names --------- @@ -151,11 +157,12 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " // 8 9 10 11 12 13 14 "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 20 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " + // 15 16 17 18 19 20 21 + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_banned.guid, character_declinedname.genitive " "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' " "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " "LEFT JOIN guild_member ON characters.guid = guild_member.guid " + "LEFT JOIN character_banned ON characters.guid = character_banned.guid AND character_banned.active = 1 " "WHERE characters.account = '%u' ORDER BY characters.guid", PET_SAVE_AS_CURRENT, GetAccountId() ); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 04683f56f0f..0a663384027 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2301,6 +2301,72 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP) return true; } +/// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban +BanReturn World::BanCharacter(std::string name, std::string duration, std::string reason, std::string author) +{ + Player *pBanned = sObjectMgr.GetPlayer(name.c_str()); + uint32 guid = 0; + + uint32 duration_secs = TimeStringToSecs(duration); + + /// Pick a player to ban if not online + if (!pBanned) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_GUID_BY_NAME); + stmt->setString(0, name); + PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt); + + if (!resultCharacter) + return BAN_NOTFOUND; // Nobody to ban + + guid = resultCharacter->GetUInt32(0); + } + else + guid = pBanned->GetGUIDLow(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_BAN); + stmt->setUInt32(0, guid); + stmt->setUInt32(1, duration_secs); + stmt->setString(2, author); + stmt->setString(3, reason); + CharacterDatabase.Execute(stmt); + + if (pBanned) + pBanned->GetSession()->KickPlayer(); + + return BAN_SUCCESS; +} + +/// Remove a ban from a character +bool World::RemoveBanCharacter(std::string name) +{ + Player *pBanned = sObjectMgr.GetPlayer(name.c_str()); + uint32 guid = 0; + + /// Pick a player to ban if not online + if (!pBanned) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_GUID_BY_NAME); + stmt->setString(0, name); + PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt); + + if (!resultCharacter) + return false; + + guid = resultCharacter->GetUInt32(0); + } + else + guid = pBanned->GetGUIDLow(); + + if (!guid) + return false; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_NOT_BANNED); + stmt->setUInt32(0, guid); + CharacterDatabase.Execute(stmt); + return true; +} + /// Update the game time void World::_UpdateGameTime() { diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 46c2f5d2949..34ccd57bb1c 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -690,6 +690,8 @@ class World void KickAllLess(AccountTypes sec); BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author); bool RemoveBanAccount(BanMode mode, std::string nameOrIP); + BanReturn BanCharacter(std::string name, std::string duration, std::string reason, std::string author); + bool RemoveBanCharacter(std::string name); uint32 IncreaseScheduledScriptsCount() { return (uint32)++m_scheduledScripts; } uint32 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 66ec9f5bb94..9a8157ad9f1 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -39,6 +39,14 @@ bool CharacterDatabaseConnection::Open(const std::string& infoString) PrepareStatement(CHAR_DEL_TINY_GROUPS, "DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)"); PrepareStatement(CHAR_DEL_NONEXISTENT_GROUP_MEMBERS, "DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)"); PrepareStatement(CHAR_DEL_NONEXISTENT_GROUP_INSTANCES, "DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)"); + PrepareStatement(CHAR_DEL_EXPIRED_BANS, "UPDATE character_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate"); + PrepareStatement(CHAR_GET_GUID_BY_NAME, "SELECT guid FROM characters WHERE name = ?"); + PrepareStatement(CHAR_ADD_BAN, "INSERT INTO character_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?, 1)"); + PrepareStatement(CHAR_SET_NOT_BANNED, "UPDATE character_banned SET active = 0 WHERE guid = ?"); + PrepareStatement(CHAR_GET_BANINFO, "SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate, banreason, bannedby FROM character_banned WHERE guid = ? ORDER BY bandate ASC"); + PrepareStatement(CHAR_GET_GUID_BY_NAME_FILTER, "SELECT guid, name FROM characters WHERE name LIKE CONCAT('%%', ?, '%%')"); + PrepareStatement(CHAR_GET_BANINFO_LIST, "SELECT bandate, unbandate, bannedby, banreason FROM character_banned WHERE guid = ? ORDER BY unbandate"); + PrepareStatement(CHAR_GET_BANNED_NAME, "SELECT characters.name FROM characters, character_banned WHERE character_banned.guid = ? AND character_banned.guid = characters.guid"); return true; } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 0807e3ebc11..1e855f135b4 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -53,6 +53,14 @@ enum CharacterDatabaseStatements CHAR_DEL_TINY_GROUPS, CHAR_DEL_NONEXISTENT_GROUP_MEMBERS, CHAR_DEL_NONEXISTENT_GROUP_INSTANCES, + CHAR_DEL_EXPIRED_BANS, + CHAR_GET_GUID_BY_NAME, + CHAR_ADD_BAN, + CHAR_SET_NOT_BANNED, + CHAR_GET_BANINFO, + CHAR_GET_GUID_BY_NAME_FILTER, + CHAR_GET_BANINFO_LIST, + CHAR_GET_BANNED_NAME, MAX_CHARACTERDATABASE_STATEMENTS, }; |