diff options
author | Aokromes <jipr@hotmail.com> | 2013-05-21 09:41:18 -0700 |
---|---|---|
committer | Aokromes <jipr@hotmail.com> | 2013-05-21 09:41:18 -0700 |
commit | 78840516f1feb736b2ea26d5c040ef5bfd8ded05 (patch) | |
tree | 93acc8a557d5c6d0a3c7c6dfc87e675275cc223b | |
parent | fa5ab46d872cb5e8e28870aec1bba6e17a8a9b1a (diff) | |
parent | 051d6ef9259915f81651c1e5b9ba30c1b3b6139c (diff) |
Merge pull request #9827 from Ascathor/master
Core/Command: Rework .PInfo and give more output and add Gender to trinity_string
8 files changed, 317 insertions, 166 deletions
diff --git a/sql/updates/world/2013_05_19_00_world_trinity_strings.sql b/sql/updates/world/2013_05_19_00_world_trinity_strings.sql new file mode 100644 index 00000000000..efdffb68b59 --- /dev/null +++ b/sql/updates/world/2013_05_19_00_world_trinity_strings.sql @@ -0,0 +1,24 @@ +DELETE FROM `trinity_string` WHERE entry IN (453, 548, 549, 550, 714, 716, 749, 752, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856); +INSERT INTO `trinity_string` (entry, content_default) VALUES +(453,'│Player %s %s (guid: %u)'), +(548,'│ GM Mode active, Phase: -1'), +(549,'├─ Banned: (Type: %s, Reason: %s, Time: %s, By: %s)'), +(550,'├─ Muted: (Reason: %s, Time: %s, By: %s)'), +(714,'│ Account: %s (ID: %u), GMLevel: %u'), +(716,'│ Last Login: %s (Failed Logins: %u)'), +(749,'│ OS: %s - Latency: %u ms - Mail: %s'), +(752,'│ Last IP: %s (Locked: %s)'), +(843,'│ Level: %u (%u/%u XP (%u XP left))'), +(844,'│ Race: %s %s, %s'), +(845,'│ Alive ?: %s'), +(846,'│ Phase: %u'), +(847,'│ Money: %ug%us%uc'), +(848,'│ Map: %s, Area: %s, Zone: %s'), +(849,'│ Guild: %s (ID: %u)'), +(850,'├─ Rank: %s'), +(851,'├─ Note: %s'), +(852,'├─ O. Note: %s'), +(853,'│ Played time: %s'), +(854,'└ Mails: %d Read/%I64u Total'), +(855,'Male'), +(856,'Female'); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index e04e9208a05..3bb663f2978 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -444,7 +444,7 @@ enum TrinityStrings LANG_COMMAND_GRAVEYARDALRLINKED = 450, LANG_COMMAND_GRAVEYARDLINKED = 451, LANG_COMMAND_GRAVEYARDWRONGZONE = 452, - // = 453, see LANG_PINFO_BAN + // = 453, see LANG_PINFO_PLAYER LANG_COMMAND_GRAVEYARDERROR = 454, LANG_COMMAND_GRAVEYARD_NOTEAM = 455, LANG_COMMAND_GRAVEYARD_ANY = 456, @@ -555,13 +555,9 @@ enum TrinityStrings LANG_NPCINFO_TRAINER = 546, LANG_NPCINFO_DUNGEON_ID = 547, - LANG_PINFO_ACCOUNT = 548, - LANG_PINFO_LEVEL = 549, - LANG_PINFO_MUTE = 550, - LANG_PINFO_BAN = 453, - LANG_PINFO_MAP_ONLINE = 714, - LANG_PINFO_MAP_OFFLINE = 716, - LANG_PINFO_GUILD_INFO = 749, + // = 548, see LANG_PINFO_GM_ACTIVE + // = 549, see LANG_PINFO_BANNED + // = 550, see LANG_PINFO_MUTED LANG_YOU_SET_EXPLORE_ALL = 551, LANG_YOU_SET_EXPLORE_NOTHING = 552, @@ -709,9 +705,9 @@ enum TrinityStrings LANG_BG_QUEUE_ANNOUNCE_SELF = 711, LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713, -// = 714, see LANG_PINFO_MAP_ONLINE +// = 714, see LANG_PINFO_ACC_ACCOUNT LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, -// = 716, see LANG_PINFO_MAP_OFFLINE +// = 716, see LANG_PINFO_ACC_LASTLOGIN LANG_BG_STARTED_ANNOUNCE_WORLD = 717, LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN= 718, LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT= 719, @@ -746,10 +742,10 @@ enum TrinityStrings LANG_DIST_ARENA_POINTS_END = 746, LANG_BG_DISABLED = 747, LANG_ARENA_DISABLED = 748, -// = 749, not used +// = 749, see LANG_PINFO_ACC_OS LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." -// = 752, not used +// = 752, see LANG_PINFO_ACC_IP // LANG_BG_WS_START_TWO_MINUTES = 753, - defined above // LANG_BG_AB_START_TWO_MINUTES = 754, - defined above // LANG_BG_EY_START_TWO_MINUTES = 755, - defined above @@ -807,7 +803,32 @@ enum TrinityStrings LANG_NPCINFO_MAILBOX = 841, LANG_NPCINFO_PLAYER_VEHICLE = 842, - // Room for in-game strings 843-999 not used + // Pinfo commands + LANG_PINFO_PLAYER = 453, + LANG_PINFO_GM_ACTIVE = 548, + LANG_PINFO_BANNED = 549, + LANG_PINFO_MUTED = 550, + LANG_PINFO_ACC_ACCOUNT = 714, + LANG_PINFO_ACC_LASTLOGIN = 716, + LANG_PINFO_ACC_OS = 749, + LANG_PINFO_ACC_IP = 752, + LANG_PINFO_CHR_LEVEL = 843, + LANG_PINFO_CHR_RACE = 844, + LANG_PINFO_CHR_ALIVE = 845, + LANG_PINFO_CHR_PHASE = 846, + LANG_PINFO_CHR_MONEY = 847, + LANG_PINFO_CHR_MAP = 848, + LANG_PINFO_CHR_GUILD = 849, + LANG_PINFO_CHR_GUILD_RANK = 850, + LANG_PINFO_CHR_GUILD_NOTE = 851, + LANG_PINFO_CHR_GUILD_ONOTE = 852, + LANG_PINFO_CHR_PLAYEDTIME = 853, + LANG_PINFO_CHR_MAILS = 854, + + LANG_CHARACTER_GENDER_MALE = 855, + LANG_CHARACTER_GENDER_FEMALE = 856, + + // Room for in-game strings 857-999 not used // Level 4 (CLI only commands) LANG_COMMAND_EXIT = 1000, diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 5e4acbb2ba5..f57413344ad 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1473,37 +1473,124 @@ public: return true; } - // show info of player + + /** + * @name Player command: .pinfo + * @date 05/19/2013 + * + * @brief Prints information about a character and it's linked account to the commander + * + * Non-applying information, e.g. a character that is not in gm mode right now or + * that is not banned/muted, is not printed + * + * This can be done either by giving a name or by targeting someone, else, it'll use the commander + * + * @param args name Prints information according to the given name to the commander + * target Prints information on the target to the commander + * none No given args results in printing information on the commander + * + * @return Several pieces of information about the character and the account + **/ + static bool HandlePInfoCommand(ChatHandler* handler, char const* args) { + // Define ALL the player variables! Player* target; uint64 targetGuid; std::string targetName; + // To make sure we get a target, we convert our guid to an omniversal... uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); + // ... and make sure we get a target, somehow. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) { target = sObjectMgr->GetPlayerByLowGUID(parseGUID); targetGuid = parseGUID; } + // if not, then return false. Which shouldn't happen, now should it ? else if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; - uint32 accId = 0; - uint32 money = 0; - uint32 totalPlayerTime = 0; - uint8 level = 0; - uint32 latency = 0; - uint8 race; - uint8 Class; - int64 muteTime = 0; - int64 banTime = -1; + /* The variables we extract for the command. They are + * default as "does not exist" to prevent problems + * The output is printed in the follow manner: + * + * Player %s %s (guid: %u) - I. LANG_PINFO_PLAYER + * ** GM Mode active, Phase: -1 - II. LANG_PINFO_GM_ACTIVE (if GM) + * ** Banned: (Type, Reason, Time, By) - III. LANG_PINFO_BANNED (if banned) + * ** Muted: (Time, Reason, By) - IV. LANG_PINFO_MUTED (if muted) + * * Account: %s (id: %u), GM Level: %u - V. LANG_PINFO_ACC_ACCOUNT + * * Last Login: %u (Failed Logins: %u) - VI. LANG_PINFO_ACC_LASTLOGIN + * * Uses OS: %s - Latency: %u ms - Email %s - VII. LANG_PINFO_ACC_OS + * * Last IP: %u (Locked: %s) - VIII. LANG_PINFO_ACC_IP + * * Level: %u (%u/%u XP (%u XP left) - IX. LANG_PINFO_CHR_LEVEL + * * Race: %s %s, Class %s - X. LANG_PINFO_CHR_RACE + * * Alive ?: %s - XI. LANG_PINFO_CHR_ALIVE + * * Phase: %s - XII. LANG_PINFO_CHR_PHASE (if not GM) + * * Money: %ug%us%uc - XIII. LANG_PINFO_CHR_MONEY + * * Map: %s, Area: %s - XIV. LANG_PINFO_CHR_MAP + * * Guild: %s (Id: %u) - XV. LANG_PINFO_CHR_GUILD (if in guild) + * ** Rank: %s - XVI. LANG_PINFO_CHR_GUILD_RANK (if in guild) + * ** Note: %s - XVII. LANG_PINFO_CHR_GUILD_NOTE (if in guild and has note) + * ** O. Note: %s - XVIII.LANG_PINFO_CHR_GUILD_ONOTE (if in guild and has officer note) + * * Played time: %s - XIX. LANG_PINFO_CHR_PLAYEDTIME + * * Mails: %u Read/%u Total - XX. LANG_PINFO_CHR_MAILS (if has mails) + * + * Not all of them can be moved to the top. These should + * place the most important ones to the head, though. + * + * For a cleaner overview, I segment each output in Roman numerals + */ + + // Account data print variables + std::string userName = handler->GetTrinityString(LANG_ERROR); + uint32 accId = 0; + uint32 lowguid = GUID_LOPART(targetGuid); + std::string eMail = handler->GetTrinityString(LANG_ERROR); + uint32 security = 0; + std::string lastIp = handler->GetTrinityString(LANG_ERROR); + uint32 locked = 0; + std::string lastLogin = handler->GetTrinityString(LANG_ERROR); + int16 flogin = 0; + uint32 latency = 0; + std::string OS = "None"; + + // Mute data print variables + int64 muteTime = -1; + std::string muteReason = "unknown"; + std::string muteBy = "unknown"; + + // Ban data print variables + int64 banTime = -1; + std::string banType = "None"; + std::string banReason = "Unknown"; + std::string bannedBy = "Unknown"; + + // Character data print variables + uint8 raceid, classid = 0; //RACE_NONE, CLASS_NONE + std::string raceStr, classStr = "None"; + uint8 gender = 0; + int8 locale = handler->GetSessionDbcLocale(); + std::string genderStr = handler->GetTrinityString(LANG_ERROR); + uint32 totalPlayerTime = 0; + uint8 level = 0; + std::string alive = handler->GetTrinityString(LANG_ERROR); + uint32 money = 0; + uint32 xp = 0; + uint32 xptotal = 0; + + // Position data print uint32 mapId; uint32 areaId; - uint32 phase = 0; + uint32 phase; + std::string areaName = "<unknown>"; + std::string zoneName = "<unknown>"; + + // Guild data print is only defined if part of Guild + + // Mail data print is only defined if you have a mail - // get additional information from Player object if (target) { // check online security @@ -1515,11 +1602,13 @@ public: totalPlayerTime = target->GetTotalPlayedTime(); level = target->getLevel(); latency = target->GetSession()->GetLatency(); - race = target->getRace(); - Class = target->getClass(); + raceid = target->getRace(); + classid = target->getClass(); muteTime = target->GetSession()->m_muteTime; mapId = target->GetMapId(); areaId = target->GetAreaId(); + alive = target->isAlive() ? "Yes" : "No"; + gender = target->getGender(); phase = target->GetPhaseMask(); } // get additional information from DB @@ -1529,8 +1618,9 @@ public: if (handler->HasLowerSecurity(NULL, targetGuid)) return false; + // Query informations from the DB PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PINFO); - stmt->setUInt32(0, GUID_LOPART(targetGuid)); + stmt->setUInt32(0, lowguid); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) @@ -1541,20 +1631,14 @@ public: level = fields[1].GetUInt8(); money = fields[2].GetUInt32(); accId = fields[3].GetUInt32(); - race = fields[4].GetUInt8(); - Class = fields[5].GetUInt8(); + raceid = fields[4].GetUInt8(); + classid = fields[5].GetUInt8(); mapId = fields[6].GetUInt16(); areaId = fields[7].GetUInt16(); + gender = fields[8].GetUInt8(); } - std::string userName = handler->GetTrinityString(LANG_ERROR); - std::string eMail = handler->GetTrinityString(LANG_ERROR); - std::string muteReason = ""; - std::string muteBy = ""; - std::string lastIp = handler->GetTrinityString(LANG_ERROR); - uint32 security = 0; - std::string lastLogin = handler->GetTrinityString(LANG_ERROR); - + // Query the prepared statement for login data PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO); stmt->setInt32(0, int32(realmID)); stmt->setUInt32(1, accId); @@ -1566,23 +1650,25 @@ public: userName = fields[0].GetString(); security = fields[1].GetUInt8(); eMail = fields[2].GetString(); - muteTime = fields[5].GetUInt64(); - muteReason = fields[6].GetString(); - muteBy = fields[7].GetString(); - - if (eMail.empty()) - eMail = "-"; + // Only fetch these fields if commander has sufficient rights AND is online (prevent cheating) + /// @TODO: Add RBAC for "Can query ip and login data" if (!handler->GetSession() || handler->GetSession()->GetSecurity() >= AccountTypes(security)) { lastIp = fields[3].GetString(); lastLogin = fields[4].GetString(); + // For crossplattforming. Quoting ByteConverter.h + /** ByteConverter reverses the byte order. This is used + for cross platform where they have different endians. + */ + uint32 ip = inet_addr(lastIp.c_str()); -#if TRINITY_ENDIAN == BIGENDIAN + #if TRINITY_ENDIAN == BIGENDIAN EndianConvertReverse(ip); -#endif + #endif + // If ip2nation table is populated, it displays the country PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY); stmt->setUInt32(0, ip); if (PreparedQueryResult result2 = LoginDatabase.Query(stmt)) @@ -1593,27 +1679,26 @@ public: lastIp.append(")"); } } - else - { - lastIp = "-"; - lastLogin = "-"; - } + muteTime = fields[5].GetUInt64(); + muteReason = fields[6].GetString(); + muteBy = fields[7].GetString(); + flogin = fields[8].GetInt16(); + locked = fields[9].GetUInt16(); + OS = fields[10].GetString(); } + // Creates a chat link to the character. Returns nameLink std::string nameLink = handler->playerLink(targetName); - handler->PSendSysMessage(LANG_PINFO_ACCOUNT, (target ? "" : handler->GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGuid), userName.c_str(), accId, eMail.c_str(), security, lastIp.c_str(), lastLogin.c_str(), latency); - - std::string bannedby = "unknown"; - std::string banreason = ""; - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS); - stmt->setUInt32(0, accId); - PreparedQueryResult result2 = LoginDatabase.Query(stmt); + // Returns banType, banTime, bannedBy, banreason + PreparedStatement* stmt2 = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS); + stmt2->setUInt32(0, accId); + PreparedQueryResult result2 = LoginDatabase.Query(stmt2); if (!result2) { + banType = "Character"; stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_BANS); - stmt->setUInt32(0, GUID_LOPART(targetGuid)); + stmt->setUInt32(0, lowguid); result2 = CharacterDatabase.Query(stmt); } @@ -1621,98 +1706,83 @@ public: { Field* fields = result2->Fetch(); banTime = int64(fields[1].GetUInt64() ? 0 : fields[0].GetUInt32()); - bannedby = fields[2].GetString(); - banreason = fields[3].GetString(); + bannedBy = fields[2].GetString(); + banReason = fields[3].GetString(); } - if (muteTime > 0) - handler->PSendSysMessage(LANG_PINFO_MUTE, secsToTimeString(muteTime - time(NULL), true).c_str(), muteBy.c_str(), muteReason.c_str()); + // Can be used to query data from World database + stmt2 = WorldDatabase.GetPreparedStatement(WORLD_SEL_REQ_XP); + stmt2->setUInt8(0, level); + PreparedQueryResult result3 = WorldDatabase.Query(stmt2); + if (result3) + { + Field* fields = result3->Fetch(); + xptotal = fields[0].GetUInt32(); + } + + // Can be used to query data from Characters database + stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_XP); + stmt2->setUInt32(0, lowguid); + PreparedQueryResult result4 = CharacterDatabase.Query(stmt2); + + if (result4) + { + Field* fields = result4->Fetch(); + xp = fields[0].GetUInt32(); + } + + // Initiate output + // Output I. LANG_PINFO_PLAYER + handler->PSendSysMessage(LANG_PINFO_PLAYER, target ? "" : handler->GetTrinityString(LANG_OFFLINE), nameLink.c_str(), lowguid, eMail); + + // Output II. LANG_PINFO_GM_ACTIVE + if (target && target->isGameMaster()) + handler->PSendSysMessage(LANG_PINFO_GM_ACTIVE); + + // Output III. LANG_PINFO_BANNED if ban exists and is applied if (banTime >= 0) - handler->PSendSysMessage(LANG_PINFO_BAN, banTime > 0 ? secsToTimeString(banTime - time(NULL), true).c_str() : "permanently", bannedby.c_str(), banreason.c_str()); - - std::string raceStr, ClassStr; - switch (race) - { - case RACE_HUMAN: - raceStr = "Human"; - break; - case RACE_ORC: - raceStr = "Orc"; - break; - case RACE_DWARF: - raceStr = "Dwarf"; - break; - case RACE_NIGHTELF: - raceStr = "Night Elf"; - break; - case RACE_UNDEAD_PLAYER: - raceStr = "Undead"; - break; - case RACE_TAUREN: - raceStr = "Tauren"; - break; - case RACE_GNOME: - raceStr = "Gnome"; - break; - case RACE_TROLL: - raceStr = "Troll"; - break; - case RACE_BLOODELF: - raceStr = "Blood Elf"; - break; - case RACE_DRAENEI: - raceStr = "Draenei"; - break; - } - - switch (Class) - { - case CLASS_WARRIOR: - ClassStr = "Warrior"; - break; - case CLASS_PALADIN: - ClassStr = "Paladin"; - break; - case CLASS_HUNTER: - ClassStr = "Hunter"; - break; - case CLASS_ROGUE: - ClassStr = "Rogue"; - break; - case CLASS_PRIEST: - ClassStr = "Priest"; - break; - case CLASS_DEATH_KNIGHT: - ClassStr = "Death Knight"; - break; - case CLASS_SHAMAN: - ClassStr = "Shaman"; - break; - case CLASS_MAGE: - ClassStr = "Mage"; - break; - case CLASS_WARLOCK: - ClassStr = "Warlock"; - break; - case CLASS_DRUID: - ClassStr = "Druid"; - break; - } - - std::string timeStr = secsToTimeString(totalPlayerTime, true, true); - uint32 gold = money /GOLD; - uint32 silv = (money % GOLD) / SILVER; - uint32 copp = (money % GOLD) % SILVER; - handler->PSendSysMessage(LANG_PINFO_LEVEL, raceStr.c_str(), ClassStr.c_str(), timeStr.c_str(), level, gold, silv, copp); - - // Add map, zone, subzone and phase to output - int locale = handler->GetSessionDbcLocale(); - std::string areaName = "<unknown>"; - std::string zoneName = ""; + handler->PSendSysMessage(LANG_PINFO_BANNED, banType.c_str(), banTime > 0 ? secsToTimeString(banTime - time(NULL), true).c_str() : "permanently", banReason.c_str(), bannedBy.c_str()); - MapEntry const* map = sMapStore.LookupEntry(mapId); + // Output IV. LANG_PINFO_MUTED if mute is applied + if (muteTime > 0) + handler->PSendSysMessage(LANG_PINFO_MUTED, secsToTimeString(muteTime - time(NULL), true).c_str(), muteReason.c_str(), muteBy.c_str()); + + // Output V. LANG_PINFO_ACC_ACCOUNT + handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName.c_str(), accId, security); + + // Output VI. LANG_PINFO_ACC_LASTLOGIN + handler->PSendSysMessage(LANG_PINFO_ACC_LASTLOGIN, lastLogin.c_str(), flogin); + + // Output VIII. LANG_PINFO_ACC_OS + handler->PSendSysMessage(LANG_PINFO_ACC_OS, OS.c_str(), latency, eMail.c_str()); + + // Output IX. LANG_PINFO_ACC_IP + handler->PSendSysMessage(LANG_PINFO_ACC_IP, lastIp.c_str(), locked == 0 ? "No" : "Yes"); + + // Output X. LANG_PINFO_CHR_LEVEL + handler->PSendSysMessage(LANG_PINFO_CHR_LEVEL, level, xp, xptotal, (xptotal - xp)); + + // Output XI. LANG_PINFO_CHR_RACE + raceStr = GetRaceName(raceid, locale); + classStr = GetClassName(classid, locale); + handler->PSendSysMessage(LANG_PINFO_CHR_RACE, (gender == 0 ? handler->GetTrinityString(LANG_CHARACTER_GENDER_MALE) : handler->GetTrinityString(LANG_CHARACTER_GENDER_FEMALE)), raceStr.c_str(), classStr.c_str()); + + // Output XII. LANG_PINFO_CHR_ALIVE + handler->PSendSysMessage(LANG_PINFO_CHR_ALIVE, alive.c_str()); + // Output XIII. LANG_PINFO_CHR_PHASE if player is not in GM mode (GM is in every phase) + if (target && !target->isGameMaster()) // IsInWorld() returns false on loadingscreen, so it's more + handler->PSendSysMessage(LANG_PINFO_CHR_PHASE, phase); // precise than just target (safer ?). + // However, as we usually just require a target here, we use target instead. + // Output XIV. LANG_PINFO_CHR_MONEY + uint32 gold = money / GOLD; + uint32 silv = (money % GOLD) / SILVER; + uint32 copp = (money % GOLD) % SILVER; + handler->PSendSysMessage(LANG_PINFO_CHR_MONEY, gold, silv, copp); + + // Position data + MapEntry const* map = sMapStore.LookupEntry(mapId); AreaTableEntry const* area = GetAreaEntryByAreaID(areaId); if (area) { @@ -1724,30 +1794,56 @@ public: } if (target) - { - if (!zoneName.empty()) - handler->PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name[locale], zoneName.c_str(), areaName.c_str(), phase); - else - handler->PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name[locale], areaName.c_str(), "<unknown>", phase); + handler->PSendSysMessage(LANG_PINFO_CHR_MAP, map->name[locale], (!zoneName.empty() ? zoneName.c_str() : "<Unknown>"), (!areaName.empty() ? areaName.c_str() : "<Unknown>")); + + // Guild Data - an own query, because it may not happen. + PreparedStatement* stmt3 = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED); + stmt3->setUInt32(0, lowguid); + PreparedQueryResult result5 = CharacterDatabase.Query(stmt3); + if (result5) + { + Field* fields = result5->Fetch(); + uint32 guildId = fields[0].GetUInt32(); + std::string guildName = fields[1].GetString(); + std::string guildRank = fields[2].GetString(); + std::string note = fields[3].GetString(); + std::string officeNote = fields[4].GetString(); + + // Output XVII. - XX. + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD, guildName.c_str(), guildId); + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_RANK, guildRank.c_str()); + // Only output XIX and XX if they are not empty + if (!note.empty()) + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_NOTE, note.c_str()); + if (!officeNote.empty()) + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_ONOTE, officeNote.c_str()); } - else - handler->PSendSysMessage(LANG_PINFO_MAP_OFFLINE, map->name[locale], areaName.c_str()); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED); - stmt->setUInt32(0, GUID_LOPART(targetGuid)); + // Output XXI. LANG_PINFO_CHR_PLAYEDTIME + handler->PSendSysMessage(LANG_PINFO_CHR_PLAYEDTIME, (secsToTimeString(totalPlayerTime, true, true)).c_str()); - result = CharacterDatabase.Query(stmt); - if (result) + // Mail Data - an own query, because it may or may not be useful. + // SQL: "SELECT SUM(CASE WHEN (checked & 1) THEN 1 ELSE 0 END) AS 'readmail', COUNT(*) AS 'totalmail' FROM mail WHERE `receiver` = ?" + stmt3 = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_MAILS); + stmt3->setUInt32(0, lowguid); + PreparedQueryResult result6 = CharacterDatabase.Query(stmt3); + if (result6) { - Field* fields = result->Fetch(); + // Define the variables, so the compiler knows they exist + int rmailint = 0; - uint32 guildId = fields[0].GetUInt32(); - std::string guildName = fields[1].GetString(); - std::string guildRank = fields[2].GetString(); - std::string note = fields[3].GetString(); - std::string officeNote = fields[4].GetString(); + // Fetch the fields - readmail is a SUM(x) and given out as char! Thus... + Field* fields = result6->Fetch(); + const char* readmail = fields[0].GetCString(); + uint64 totalmail = fields[1].GetUInt64(); + + // ... we have to convert it from Char to int. We can use totalmail as it is + if (readmail) + rmailint = atoi(readmail); - handler->PSendSysMessage(LANG_PINFO_GUILD_INFO, guildName.c_str(), guildId, guildRank.c_str(), note.c_str(), officeNote.c_str()); + // Output XXII. LANG_INFO_CHR_MAILS if at least one mails is given + if (totalmail >= 1) + handler->PSendSysMessage(LANG_PINFO_CHR_MAILS, rmailint, totalmail); } return true; @@ -1785,6 +1881,7 @@ public: return true; } + // mute player for some times static bool HandleMuteCommand(ChatHandler* handler, char const* args) { diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 2e6ab10b087..4f8a32aa950 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -421,8 +421,12 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_DEL_INFO, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID, "SELECT guid FROM characters WHERE account = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone FROM characters WHERE guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone, gender FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM character_banned WHERE guid = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); + //0: lowGUID + PrepareStatement(CHAR_SEL_PINFO_MAILS, "SELECT SUM(CASE WHEN (checked & 1) THEN 1 ELSE 0 END) AS 'readmail', COUNT(*) AS 'totalmail' FROM mail WHERE `receiver` = ?", CONNECTION_SYNCH); + //0: lowGUID + PrepareStatement(CHAR_SEL_PINFO_XP, "SELECT xp FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ FROM character_homebind WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_GUID_NAME_BY_ACC, "SELECT guid, name FROM characters WHERE account = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 59ac15978b6..362bb3545df 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -365,6 +365,8 @@ enum CharacterDatabaseStatements CHAR_SEL_CHARS_BY_ACCOUNT_ID, CHAR_SEL_CHAR_PINFO, + CHAR_SEL_PINFO_XP, + CHAR_SEL_PINFO_MAILS, CHAR_SEL_PINFO_BANS, CHAR_SEL_CHAR_HOMEBIND, CHAR_SEL_CHAR_GUID_NAME_BY_ACC, diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index 0118f637205..6113dd61d70 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -79,7 +79,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT 1 FROM account WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT 1 FROM account WHERE username = ? AND sha_pass_hash = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT a.username, a.last_ip, aa.gmlevel, a.expansion FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.id = ?", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index fa7818d2dca..a36023a23b0 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -91,4 +91,6 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_INS_DISABLES, "INSERT INTO disables (entry, sourceType, flags, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_DISABLES, "SELECT entry FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC); + // 0: uint8 + PrepareStatement(WORLD_SEL_REQ_XP, "SELECT xp_for_next_level FROM player_xp_for_level WHERE lvl = ?", CONNECTION_SYNCH); } diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/shared/Database/Implementation/WorldDatabase.h index d8c3c69dbba..171627bb83a 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/shared/Database/Implementation/WorldDatabase.h @@ -112,6 +112,7 @@ enum WorldDatabaseStatements WORLD_SEL_DISABLES, WORLD_INS_DISABLES, WORLD_DEL_DISABLES, + WORLD_SEL_REQ_XP, MAX_WORLDDATABASE_STATEMENTS }; |