aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql27
-rw-r--r--sql/base/world_database.sql6
-rw-r--r--sql/updates/10000_characters_character_banned.sql10
-rw-r--r--sql/updates/10000_world_command.sql4
-rw-r--r--sql/updates/10000_world_trinity_string.sql5
-rw-r--r--src/server/game/Chat/Chat.cpp10
-rw-r--r--src/server/game/Chat/Chat.h2
-rw-r--r--src/server/game/Chat/Commands/Level3.cpp209
-rw-r--r--src/server/game/Entities/Player/Player.cpp14
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Miscellaneous/Language.h5
-rw-r--r--src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp15
-rw-r--r--src/server/game/World/World.cpp66
-rw-r--r--src/server/game/World/World.h2
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp8
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h8
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,
};