Core/NetworkIO: implemented undelete opcodes and moved char create/delete packets to new packet classes

This commit is contained in:
joschiwald
2014-11-03 19:11:14 +01:00
parent 064154c540
commit 52bd9a771e
30 changed files with 965 additions and 303 deletions
+1
View File
@@ -217,6 +217,7 @@ CREATE TABLE `battlenet_accounts` (
`online` tinyint(3) unsigned NOT NULL DEFAULT '0',
`locale` tinyint(3) unsigned NOT NULL DEFAULT '0',
`os` varchar(3) NOT NULL DEFAULT '',
`LastCharacterUndelete` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='Account System';
/*!40101 SET character_set_client = @saved_cs_client */;
+1
View File
@@ -0,0 +1 @@
ALTER TABLE `battlenet_accounts` ADD COLUMN `LastCharacterUndelete` INT(10) UNSIGNED DEFAULT 0 NOT NULL AFTER `os`;
+10 -10
View File
@@ -359,17 +359,17 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint32 flags) const
bool EnablePortals = false;
bool PlayHoverAnim = false;
bool IsSuppressingGreetings = false;
bool HasMovementUpdate = flags & UPDATEFLAG_LIVING ? true : false;
bool HasMovementTransport = flags & UPDATEFLAG_TRANSPORT_POSITION ? true : false;
bool Stationary = flags & UPDATEFLAG_STATIONARY_POSITION ? true : false;
bool CombatVictim = flags & UPDATEFLAG_HAS_TARGET ? true : false;
bool ServerTime = flags & UPDATEFLAG_TRANSPORT ? true : false;
bool VehicleCreate = flags & UPDATEFLAG_VEHICLE ? true : false;
bool AnimKitCreate = flags & UPDATEFLAG_ANIMKITS ? true : false;
bool Rotation = flags & UPDATEFLAG_ROTATION ? true : false;
bool HasMovementUpdate = (flags & UPDATEFLAG_LIVING) != 0;
bool HasMovementTransport = (flags & UPDATEFLAG_TRANSPORT_POSITION) != 0;
bool Stationary = (flags & UPDATEFLAG_STATIONARY_POSITION) != 0;
bool CombatVictim = (flags & UPDATEFLAG_HAS_TARGET) != 0;
bool ServerTime = (flags & UPDATEFLAG_TRANSPORT) != 0;
bool VehicleCreate = (flags & UPDATEFLAG_VEHICLE) != 0;
bool AnimKitCreate = (flags & UPDATEFLAG_ANIMKITS) != 0;
bool Rotation = (flags & UPDATEFLAG_ROTATION) != 0;
bool HasAreaTrigger = false;
bool HasGameObject = false;
bool ThisIsYou = flags & UPDATEFLAG_SELF ? true : false;
bool ThisIsYou = (flags & UPDATEFLAG_SELF) != 0;
bool ReplaceActive = false;
bool SceneObjCreate = false;
bool ScenePendingInstances = false;
@@ -379,7 +379,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint32 flags) const
PauseTimesCount = go->GetGOValue()->Transport.StopFrames->size();
data->WriteBit(NoBirthAnim);
data->WriteBit(EnablePortals);
data->WriteBit(EnablePortals);
data->WriteBit(PlayHoverAnim);
data->WriteBit(IsSuppressingGreetings);
data->WriteBit(HasMovementUpdate);
+9 -8
View File
@@ -31,6 +31,7 @@
#include "Channel.h"
#include "ChannelMgr.h"
#include "CharacterDatabaseCleaner.h"
#include "CharacterPackets.h"
#include "Chat.h"
#include "Common.h"
#include "ConditionMgr.h"
@@ -930,7 +931,7 @@ void Player::CleanupsBeforeDelete(bool finalCleanup)
itr->second.save->RemovePlayer(this);
}
bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo)
bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::CharacterCreateInfo const* createInfo)
{
//FIXME: outfitId not used in player creating
/// @todo need more checks against packet modifications
@@ -970,14 +971,14 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
setFactionForRace(createInfo->Race);
if (!IsValidGender(createInfo->Gender))
if (!IsValidGender(createInfo->Sex))
{
TC_LOG_ERROR("entities.player", "Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with an invalid gender (%u) - refusing to do so",
GetSession()->GetAccountId(), m_name.c_str(), createInfo->Gender);
GetSession()->GetAccountId(), m_name.c_str(), createInfo->Sex);
return false;
}
uint32 RaceClassGender = (createInfo->Race) | (createInfo->Class << 8) | (createInfo->Gender << 16);
uint32 RaceClassGender = (createInfo->Race) | (createInfo->Class << 8) | (createInfo->Sex << 16);
SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24)));
InitDisplayIds();
@@ -993,11 +994,11 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); // -1 is default value
SetUInt32Value(PLAYER_BYTES, (createInfo->Skin | (createInfo->Face << 8) | (createInfo->HairStyle << 16) | (createInfo->HairColor << 24)));
SetUInt32Value(PLAYER_BYTES_2, (createInfo->FacialHair |
SetUInt32Value(PLAYER_BYTES_2, (createInfo->FacialHairStyle |
(0x00 << 8) |
(0x00 << 16) |
(((GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0) ? REST_STATE_RAF_LINKED : REST_STATE_NOT_RAF_LINKED) << 24)));
SetByteValue(PLAYER_BYTES_3, 0, createInfo->Gender);
SetByteValue(PLAYER_BYTES_3, 0, createInfo->Sex);
SetByteValue(PLAYER_BYTES_3, 3, 0); // BattlefieldArenaFaction (0 or 1)
SetGuidValue(OBJECT_FIELD_DATA, ObjectGuid::Empty);
@@ -1121,7 +1122,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
addActionButton(action_itr->button, action_itr->action, action_itr->type);
// original items
if (CharStartOutfitEntry const* oEntry = GetCharStartOutfitEntry(createInfo->Race, createInfo->Class, createInfo->Gender))
if (CharStartOutfitEntry const* oEntry = GetCharStartOutfitEntry(createInfo->Race, createInfo->Class, createInfo->Sex))
{
for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j)
{
@@ -20242,7 +20243,7 @@ void Player::SetUInt32ValueInArray(Tokenizer& Tokenizer, uint16 index, uint32 va
Tokenizer[index] = buf;
}
void Player::Customize(CharacterCustomizeInfo const* customizeInfo, SQLTransaction& trans)
void Player::Customize(WorldPackets::Character::CharacterCustomizeInfo const* customizeInfo, SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PLAYERBYTES2);
stmt->setUInt64(0, customizeInfo->Guid.GetCounter());
+2 -5
View File
@@ -44,7 +44,6 @@ struct VendorItem;
template<class T> class AchievementMgr;
class ReputationMgr;
class Channel;
class CharacterCreateInfo;
class Creature;
class DynamicObject;
class Group;
@@ -56,8 +55,6 @@ class PlayerSocial;
class SpellCastTargets;
class UpdateMask;
struct CharacterCustomizeInfo;
typedef std::deque<Mail*> PlayerMails;
#define PLAYER_MAX_SKILLS 128
@@ -1289,7 +1286,7 @@ class Player : public Unit, public GridObject<Player>
void SetSummonPoint(uint32 mapid, float x, float y, float z);
void SummonIfPossible(bool agree);
bool Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo);
bool Create(ObjectGuid::LowType guidlow, WorldPackets::Character::CharacterCreateInfo const* createInfo);
void Update(uint32 time) override;
@@ -1711,7 +1708,7 @@ class Player : public Unit, public GridObject<Player>
static void SetUInt32ValueInArray(Tokenizer& data, uint16 index, uint32 value);
static void SetFloatValueInArray(Tokenizer& data, uint16 index, float value);
static void Customize(CharacterCustomizeInfo const* customizeInfo, SQLTransaction& trans);
static void Customize(WorldPackets::Character::CharacterCustomizeInfo const* customizeInfo, SQLTransaction& trans);
static void SavePositionInDB(WorldLocation const& loc, uint16 zoneId, ObjectGuid guid, SQLTransaction& trans);
static void DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRealmChars = true, bool deleteFinally = false);
+25 -1
View File
@@ -20,6 +20,7 @@
#include "WorldSession.h"
#include "WorldPacket.h"
#include "AuthenticationPackets.h"
#include "SystemPackets.h"
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos)
{
@@ -64,7 +65,7 @@ void WorldSession::SendAuthWaitQue(uint32 position)
response.WaitInfo.value.WaitCount = position;
response.Result = AUTH_WAIT_QUEUE;
}
response.Write();
SendPacket(&response.GetWorldPacket());
}
@@ -75,3 +76,26 @@ void WorldSession::SendClientCacheVersion(uint32 version)
data << uint32(version);
SendPacket(&data);
}
void WorldSession::SendSetTimeZoneInformation()
{
/// @todo: replace dummy values
WorldPackets::System::SetTimeZoneInformation packet;
packet.ServerTimeTZ = "Europe/Paris";
packet.GameTimeTZ = "Europe/Paris";
packet.Write();
SendPacket(&packet.GetWorldPacket());
}
void WorldSession::SendFeatureSystemStatusGlueScreen()
{
WorldPackets::System::FeatureSystemStatusGlueScreen features;
features.BpayStoreAvailable = false;
features.BpayStoreDisabledByParentalControls = false;
features.CharUndeleteEnabled = sWorld->getBoolConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_ENABLED);
features.BpayStoreEnabled = sWorld->getBoolConfig(CONFIG_FEATURE_SYSTEM_BPAY_STORE_ENABLED);
features.Write();
SendPacket(&features.GetWorldPacket());
}
@@ -149,7 +149,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
WorldPacket data;
sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_LFG_CANT_USE_BATTLEGROUND);
GetPlayer()->GetSession()->SendPacket(&data);
SendPacket(&data);
return;
}
@@ -158,7 +158,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
WorldPacket data;
sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data);
SendPacket(&data);
return;
}
@@ -167,7 +167,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
// player is already in random queue
WorldPacket data;
sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_RANDOM_BG);
_player->GetSession()->SendPacket(&data);
SendPacket(&data);
return;
}
@@ -176,7 +176,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
// player is already in queue, can't start random queue
WorldPacket data;
sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_NON_RANDOM_BG);
_player->GetSession()->SendPacket(&data);
SendPacket(&data);
return;
}
@@ -190,7 +190,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
WorldPacket data;
sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_BATTLEGROUND_TOO_MANY_QUEUES);
_player->GetSession()->SendPacket(&data);
SendPacket(&data);
return;
}
+318 -97
View File
@@ -227,10 +227,10 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
charEnum.Success = true;
charEnum.IsDeletedCharacters = false;
_legitCharacters.clear();
if (result)
{
_legitCharacters.clear();
do
{
Field* fields = result->Fetch();
@@ -270,39 +270,59 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket& /*recvData*/)
stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
stmt->setUInt32(1, GetAccountId());
_charEnumCallback = CharacterDatabase.AsyncQuery(stmt);
_charEnumCallback.SetParam(false);
_charEnumCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
}
void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
void WorldSession::HandleCharUndeleteEnum(PreparedQueryResult result)
{
CharacterCreateInfo createInfo;
WorldPackets::Character::CharEnumResult charEnum;
charEnum.Success = true;
charEnum.IsDeletedCharacters = true;
uint32 nameLength = recvData.ReadBits(6);
bool hasTempalte = recvData.ReadBit();
if (result)
{
do
{
Field* fields = result->Fetch();
WorldPackets::Character::CharEnumResult::CharacterInfo charInfo(fields);
recvData >> createInfo.Race
>> createInfo.Class
>> createInfo.Gender
>> createInfo.Skin
>> createInfo.Face
>> createInfo.HairStyle
>> createInfo.HairColor
>> createInfo.FacialHair
>> createInfo.OutfitId;
TC_LOG_INFO("network", "Loading undeleted char guid %s from account %u.", charInfo.Guid.ToString().c_str(), GetAccountId());
createInfo.Name = recvData.ReadString(nameLength);
charEnum.Characters.emplace_back(charInfo);
}
while (result->NextRow());
}
if (hasTempalte)
recvData.read_skip<uint32>(); // Template from SMSG_AUTH_RESPONSE
charEnum.Write();
SendPacket(&charEnum.GetWorldPacket());
}
void WorldSession::HandleCharUndeleteEnumOpcode(WorldPacket& /*recvData*/)
{
/// get all the data necessary for loading all undeleted characters (along with their pets) on the account
PreparedStatement* stmt = nullptr;
if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME);
else
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_UNDELETE_ENUM);
stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
stmt->setUInt32(1, GetAccountId());
_charEnumCallback.SetParam(true);
_charEnumCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
}
void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CharacterCreate& charCreate)
{
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK))
{
if (uint32 mask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED))
{
bool disabled = false;
switch (Player::TeamForRace(createInfo.Race))
switch (Player::TeamForRace(charCreate.CreateInfo->Race))
{
case ALLIANCE:
disabled = (mask & (1 << 0)) != 0;
@@ -320,18 +340,18 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
}
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(createInfo.Class);
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(charCreate.CreateInfo->Class);
if (!classEntry)
{
TC_LOG_ERROR("network", "Class (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", createInfo.Class, GetAccountId());
TC_LOG_ERROR("network", "Class (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", charCreate.CreateInfo->Class, GetAccountId());
SendCharCreate(CHAR_CREATE_FAILED);
return;
}
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(createInfo.Race);
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(charCreate.CreateInfo->Race);
if (!raceEntry)
{
TC_LOG_ERROR("network", "Race (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", createInfo.Race, GetAccountId());
TC_LOG_ERROR("network", "Race (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", charCreate.CreateInfo->Race, GetAccountId());
SendCharCreate(CHAR_CREATE_FAILED);
return;
}
@@ -339,7 +359,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion race without Expansion account
if (raceEntry->expansion > Expansion())
{
TC_LOG_ERROR("network", "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, createInfo.Race);
TC_LOG_ERROR("network", "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, charCreate.CreateInfo->Race);
SendCharCreate(CHAR_CREATE_EXPANSION);
return;
}
@@ -347,7 +367,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion class without Expansion account
if (classEntry->expansion > Expansion())
{
TC_LOG_ERROR("network", "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, createInfo.Class);
TC_LOG_ERROR("network", "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, charCreate.CreateInfo->Class);
SendCharCreate(CHAR_CREATE_EXPANSION_CLASS);
return;
}
@@ -355,7 +375,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (createInfo.Race - 1)) & raceMaskDisabled)
if ((1 << (charCreate.CreateInfo->Race - 1)) & raceMaskDisabled)
{
SendCharCreate(CHAR_CREATE_DISABLED);
return;
@@ -365,7 +385,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK))
{
uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
if ((1 << (createInfo.Class - 1)) & classMaskDisabled)
if ((1 << (charCreate.CreateInfo->Class - 1)) & classMaskDisabled)
{
SendCharCreate(CHAR_CREATE_DISABLED);
return;
@@ -373,7 +393,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
// prevent character creating with invalid name
if (!normalizePlayerName(createInfo.Name))
if (!normalizePlayerName(charCreate.CreateInfo->Name))
{
TC_LOG_ERROR("network", "Account:[%d] but tried to Create character with empty [name] ", GetAccountId());
SendCharCreate(CHAR_NAME_NO_NAME);
@@ -381,32 +401,30 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
// check name limitations
ResponseCodes res = ObjectMgr::CheckPlayerName(createInfo.Name, true);
ResponseCodes res = ObjectMgr::CheckPlayerName(charCreate.CreateInfo->Name, true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharCreate(res);
return;
}
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(createInfo.Name))
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(charCreate.CreateInfo->Name))
{
SendCharCreate(CHAR_NAME_RESERVED);
return;
}
if (createInfo.Class == CLASS_DEATH_KNIGHT && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER))
if (charCreate.CreateInfo->Class == CLASS_DEATH_KNIGHT && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER))
{
// speedup check for heroic class disabled case
uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
if (heroic_free_slots == 0)
if (!sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM))
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
return;
}
// speedup check for heroic class disabled case
uint32 req_level_for_heroic = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
if (req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
if (sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER) > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
return;
@@ -414,18 +432,17 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->setString(0, createInfo.Name);
stmt->setString(0, charCreate.CreateInfo->Name);
delete _charCreateCallback.GetParam(); // Delete existing if any, to make the callback chain reset to stage 0
_charCreateCallback.SetParam(new CharacterCreateInfo(std::move(createInfo)));
_charCreateCallback.SetParam(charCreate.CreateInfo);
_charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
}
void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo)
void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPackets::Character::CharacterCreateInfo* createInfo)
{
/** This is a series of callbacks executed consecutively as a result from the database becomes available.
This is much more efficient than synchronous requests on packet handler, and much less DoS prone.
It also prevents data syncrhonisation errors.
It also prevents data synchronisation errors.
*/
switch (_charCreateCallback.GetStage())
{
@@ -434,12 +451,11 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (result)
{
SendCharCreate(CHAR_CREATE_NAME_IN_USE);
delete createInfo;
_charCreateCallback.Reset();
return;
}
ASSERT(_charCreateCallback.GetParam() == createInfo);
ASSERT(_charCreateCallback.GetParam().get() == createInfo);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS);
stmt->setUInt32(0, GetAccountId());
@@ -464,12 +480,11 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
{
SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
delete createInfo;
_charCreateCallback.Reset();
return;
}
ASSERT(_charCreateCallback.GetParam() == createInfo);
ASSERT(_charCreateCallback.GetParam().get() == createInfo);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
stmt->setUInt32(0, GetAccountId());
@@ -489,7 +504,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
{
SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
delete createInfo;
_charCreateCallback.Reset();
return;
}
@@ -542,7 +556,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (freeHeroicSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
delete createInfo;
_charCreateCallback.Reset();
return;
}
@@ -567,7 +580,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (accTeam != team)
{
SendCharCreate(CHAR_CREATE_PVP_TEAMS_VIOLATION);
delete createInfo;
_charCreateCallback.Reset();
return;
}
@@ -597,7 +609,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (freeHeroicSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
delete createInfo;
_charCreateCallback.Reset();
return;
}
@@ -616,7 +627,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (checkHeroicReqs && !hasHeroicReqLevel)
{
SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
delete createInfo;
_charCreateCallback.Reset();
return;
}
@@ -629,7 +639,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
newChar.CleanupsBeforeDelete();
SendCharCreate(CHAR_CREATE_ERROR);
delete createInfo;
_charCreateCallback.Reset();
return;
}
@@ -665,25 +674,37 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
sWorld->AddCharacterNameData(newChar.GetGUID(), newChar.GetName(), newChar.getGender(), newChar.getRace(), newChar.getClass(), newChar.getLevel());
newChar.CleanupsBeforeDelete();
delete createInfo;
_charCreateCallback.Reset();
break;
}
}
}
void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
void WorldSession::HandleCharDeleteOpcode(WorldPackets::Character::CharacterDelete& charDelete)
{
ObjectGuid guid;
recvData >> guid;
// Initiating
uint32 initAccountId = GetAccountId();
// can't delete loaded character
if (ObjectAccessor::FindPlayer(guid))
if (ObjectAccessor::FindPlayer(charDelete.Guid))
{
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
return;
}
// is guild leader
if (sGuildMgr->GetGuildByLeader(charDelete.Guid))
{
sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
SendCharDelete(CHAR_DELETE_FAILED_GUILD_LEADER);
return;
}
// is arena team captain
if (sArenaTeamMgr->GetArenaTeamByCaptain(charDelete.Guid))
{
sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
SendCharDelete(CHAR_DELETE_FAILED_ARENA_CAPTAIN);
return;
}
@@ -691,24 +712,8 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
uint8 level = 0;
std::string name;
// is guild leader
if (sGuildMgr->GetGuildByLeader(guid))
{
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
SendCharDelete(CHAR_DELETE_FAILED_GUILD_LEADER);
return;
}
// is arena team captain
if (sArenaTeamMgr->GetArenaTeamByCaptain(guid))
{
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
SendCharDelete(CHAR_DELETE_FAILED_ARENA_CAPTAIN);
return;
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_DATA_BY_GUID);
stmt->setUInt64(0, guid.GetCounter());
stmt->setUInt64(0, charDelete.Guid.GetCounter());
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
@@ -721,26 +726,26 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
// prevent deleting other players' characters using cheating tools
if (accountId != initAccountId)
{
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
return;
}
TC_LOG_INFO("entities.player.character", "Account: %u, IP: %s deleted character: %s, %s, Level: %u", accountId, GetRemoteAddress().c_str(), name.c_str(), guid.ToString().c_str(), level);
TC_LOG_INFO("entities.player.character", "Account: %u, IP: %s deleted character: %s, %s, Level: %u", accountId, GetRemoteAddress().c_str(), name.c_str(), charDelete.Guid.ToString().c_str(), level);
// To prevent hook failure, place hook before removing reference from DB
sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
sScriptMgr->OnPlayerDelete(charDelete.Guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
// Shouldn't interfere with character deletion though
if (sLog->ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) // optimize GetPlayerDump call
{
std::string dump;
if (PlayerDumpWriter().GetDump(guid.GetCounter(), dump))
sLog->outCharDump(dump.c_str(), accountId, guid.GetCounter(), name.c_str());
if (PlayerDumpWriter().GetDump(charDelete.Guid.GetCounter(), dump))
sLog->outCharDump(dump.c_str(), accountId, charDelete.Guid.GetCounter(), name.c_str());
}
sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(guid);
sCalendarMgr->RemoveAllPlayerEventsAndInvites(guid);
Player::DeleteFromDB(guid, accountId);
sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(charDelete.Guid);
sCalendarMgr->RemoveAllPlayerEventsAndInvites(charDelete.Guid);
Player::DeleteFromDB(charDelete.Guid, accountId);
SendCharDelete(CHAR_DELETE_SUCCESS);
}
@@ -1156,7 +1161,7 @@ void WorldSession::HandleShowingCloakOpcode(WorldPacket& recvData)
void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
{
CharacterRenameInfo renameInfo;
WorldPackets::Character::CharacterRenameInfo renameInfo;
recvData >> renameInfo.Guid
>> renameInfo.Name;
@@ -1193,11 +1198,11 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
stmt->setString(4, renameInfo.Name);
delete _charRenameCallback.GetParam();
_charRenameCallback.SetParam(new CharacterRenameInfo(std::move(renameInfo)));
_charRenameCallback.SetParam(new WorldPackets::Character::CharacterRenameInfo(std::move(renameInfo)));
_charRenameCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
}
void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, CharacterRenameInfo const* renameInfo)
void WorldSession::HandleCharRenameCallBack(PreparedQueryResult result, WorldPackets::Character::CharacterRenameInfo const* renameInfo)
{
if (!result)
{
@@ -1394,7 +1399,7 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData)
void WorldSession::HandleCharCustomize(WorldPacket& recvData)
{
CharacterCustomizeInfo customizeInfo;
WorldPackets::Character::CharacterCustomizeInfo customizeInfo;
recvData >> customizeInfo.Guid;
if (!IsLegitCharacterForAccount(customizeInfo.Guid))
@@ -1625,7 +1630,7 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData)
void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
{
CharacterFactionChangeInfo factionChangeInfo;
WorldPackets::Character::CharacterFactionChangeInfo factionChangeInfo;
recvData >> factionChangeInfo.Guid;
if (!IsLegitCharacterForAccount(factionChangeInfo.Guid))
@@ -2240,21 +2245,216 @@ void WorldSession::HandleOpeningCinematic(WorldPacket& /*recvData*/)
}
}
void WorldSession::HandleUndeleteCooldownStatusQuery(WorldPacket& /*recvData*/)
{
/// empty result to force wait
PreparedQueryResultPromise result;
result.set_value(PreparedQueryResult(nullptr));
_undeleteCooldownStatusCallback.SetFutureResult(result.get_future());
}
void WorldSession::HandleUndeleteCooldownStatusCallback(PreparedQueryResult result)
{
switch (_undeleteCooldownStatusCallback.GetStage())
{
case 0:
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LAST_CHAR_UNDELETE);
stmt->setUInt32(0, GetBattlenetAccountId());
_undeleteCooldownStatusCallback.FreeResult();
_undeleteCooldownStatusCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt));
_undeleteCooldownStatusCallback.NextStage();
break;
}
case 1:
{
uint32 cooldown = 0;
uint32 maxCooldown = sWorld->getIntConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN);
if (result)
{
uint32 lastUndelete = result->Fetch()[0].GetUInt32();
if (lastUndelete)
cooldown = uint32(std::max<int32>(0, int32(lastUndelete) + maxCooldown - time(nullptr)));
}
SendUndeleteCooldownStatusResponse(cooldown, maxCooldown);
_undeleteCooldownStatusCallback.Reset();
break;
}
}
}
void WorldSession::HandleCharUndeleteOpcode(WorldPackets::Character::UndeleteCharacter& undeleteInfo)
{
if (!sWorld->getBoolConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_ENABLED))
{
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_DISABLED, undeleteInfo.UndeleteInfo.get());
return;
}
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LAST_CHAR_UNDELETE);
stmt->setUInt32(0, GetBattlenetAccountId());
_charUndeleteCallback.SetParam(undeleteInfo.UndeleteInfo);
_charUndeleteCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt));
_charUndeleteCallback.NextStage();
}
void WorldSession::HandleCharUndeleteCallback(PreparedQueryResult result, WorldPackets::Character::CharacterUndeleteInfo* undeleteInfo)
{
/** This is a series of callbacks executed consecutively as a result from the database becomes available.
* This is much more efficient than synchronous requests on packet handler.
* It also prevents data synchronisation errors.
*/
ASSERT(_charUndeleteCallback.GetParam().get() == undeleteInfo);
switch (_charUndeleteCallback.GetStage())
{
case 1:
{
if (result)
{
uint32 lastUndelete = result->Fetch()[0].GetUInt32();
uint32 maxCooldown = sWorld->getIntConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN);
if (lastUndelete && (lastUndelete + maxCooldown > time(nullptr)))
{
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_COOLDOWN, undeleteInfo);
_charUndeleteCallback.Reset();
return;
}
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID);
stmt->setUInt64(0, undeleteInfo->CharacterGuid.GetCounter());
_charUndeleteCallback.FreeResult();
_charUndeleteCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_charUndeleteCallback.NextStage();
break;
}
case 2:
{
if (!result)
{
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_CHAR_CREATE, undeleteInfo);
_charUndeleteCallback.Reset();
return;
}
Field* fields = result->Fetch();
undeleteInfo->Name = fields[1].GetString();
uint32 account = fields[2].GetUInt32();
if (account != GetAccountId())
{
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_UNKNOWN, undeleteInfo);
_charUndeleteCallback.Reset();
return;
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->setString(0, undeleteInfo->Name);
_charUndeleteCallback.FreeResult();
_charUndeleteCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_charUndeleteCallback.NextStage();
break;
}
case 3:
{
if (result)
{
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_NAME_TAKEN_BY_THIS_ACCOUNT, undeleteInfo);
_charUndeleteCallback.Reset();
return;
}
/// @todo: add more safety checks
/// * max char count per account
/// * max heroic char count
/// * team violation
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
stmt->setUInt32(0, GetAccountId());
_charUndeleteCallback.FreeResult();
_charUndeleteCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_charUndeleteCallback.NextStage();
break;
}
case 4:
{
if (result)
{
Field* fields = result->Fetch();
if (fields[0].GetUInt64() >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)) // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
{
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_CHAR_CREATE, undeleteInfo);
_charUndeleteCallback.Reset();
return;
}
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_RESTORE_DELETE_INFO);
stmt->setString(0, undeleteInfo->Name);
stmt->setUInt32(1, GetAccountId());
stmt->setUInt64(2, undeleteInfo->CharacterGuid.GetCounter());
CharacterDatabase.Execute(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_CHAR_UNDELETE);
stmt->setUInt32(0, GetBattlenetAccountId());
LoginDatabase.Execute(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA);
stmt->setUInt64(0, undeleteInfo->CharacterGuid.GetCounter());
_charUndeleteCallback.FreeResult();
_charUndeleteCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_charUndeleteCallback.NextStage();
break;
}
case 5:
{
if (!result)
{
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_UNKNOWN, undeleteInfo);
_charUndeleteCallback.Reset();
return;
}
Field* fields = result->Fetch();
sWorld->AddCharacterNameData(undeleteInfo->CharacterGuid, undeleteInfo->Name, fields[2].GetUInt8(), fields[0].GetUInt8(), fields[1].GetUInt8(), fields[3].GetUInt8());
SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_OK, undeleteInfo);
_charUndeleteCallback.Reset();
break;
}
}
}
void WorldSession::SendCharCreate(ResponseCodes result)
{
WorldPacket data(SMSG_CHAR_CREATE, 1);
data << uint8(result);
SendPacket(&data);
WorldPackets::Character::CharacterCreateResponse response;
response.Code = result;
response.Write();
SendPacket(&response.GetWorldPacket());
}
void WorldSession::SendCharDelete(ResponseCodes result)
{
WorldPacket data(SMSG_CHAR_DELETE, 1);
data << uint8(result);
SendPacket(&data);
WorldPackets::Character::CharacterDeleteResponse response;
response.Code = result;
response.Write();
SendPacket(&response.GetWorldPacket());
}
void WorldSession::SendCharRename(ResponseCodes result, CharacterRenameInfo const& renameInfo)
void WorldSession::SendCharRename(ResponseCodes result, WorldPackets::Character::CharacterRenameInfo const& renameInfo)
{
WorldPacket data(SMSG_CHAR_RENAME, 1 + 8 + renameInfo.Name.size() + 1);
data << uint8(result);
@@ -2266,7 +2466,7 @@ void WorldSession::SendCharRename(ResponseCodes result, CharacterRenameInfo cons
SendPacket(&data);
}
void WorldSession::SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const& customizeInfo)
void WorldSession::SendCharCustomize(ResponseCodes result, WorldPackets::Character::CharacterCustomizeInfo const& customizeInfo)
{
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1 + 8 + customizeInfo.Name.size() + 1 + 6);
data << uint8(result);
@@ -2284,7 +2484,7 @@ void WorldSession::SendCharCustomize(ResponseCodes result, CharacterCustomizeInf
SendPacket(&data);
}
void WorldSession::SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const& factionChangeInfo)
void WorldSession::SendCharFactionChange(ResponseCodes result, WorldPackets::Character::CharacterFactionChangeInfo const& factionChangeInfo)
{
WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1 + 8 + factionChangeInfo.Name.size() + 1 + 7);
data << uint8(result);
@@ -2318,3 +2518,24 @@ void WorldSession::SendBarberShopResult(BarberShopResult result)
data << uint32(result);
SendPacket(&data);
}
void WorldSession::SendUndeleteCooldownStatusResponse(uint32 currentCooldown, uint32 maxCooldown)
{
WorldPackets::Character::UndeleteCooldownStatusResponse response;
response.OnCooldown = (currentCooldown > 0);
response.MaxCooldown = maxCooldown;
response.CurrentCooldown = currentCooldown;
response.Write();
SendPacket(&response.GetWorldPacket());
}
void WorldSession::SendUndeleteCharacterResponse(CharacterUndeleteResult result, WorldPackets::Character::CharacterUndeleteInfo const* undeleteInfo)
{
WorldPackets::Character::UndeleteCharacterResponse response;
response.UndeleteInfo = undeleteInfo;
response.Result = result;
response.Write();
SendPacket(&response.GetWorldPacket());
}
+49 -36
View File
@@ -4324,45 +4324,58 @@ enum ResponseCodes
CHAR_CREATE_CHARACTER_RACE_ONLY = 67,
CHAR_CREATE_CHARACTER_GOLD_LIMIT = 68,
CHAR_CREATE_FORCE_LOGIN = 69,
CHAR_CREATE_TRIAL = 70,
CHAR_DELETE_IN_PROGRESS = 70,
CHAR_DELETE_SUCCESS = 71,
CHAR_DELETE_FAILED = 72,
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 73,
CHAR_DELETE_FAILED_GUILD_LEADER = 74,
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 75,
CHAR_DELETE_FAILED_HAS_HEIRLOOM_OR_MAIL = 76,
CHAR_DELETE_IN_PROGRESS = 71,
CHAR_DELETE_SUCCESS = 72,
CHAR_DELETE_FAILED = 73,
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 74,
CHAR_DELETE_FAILED_GUILD_LEADER = 75,
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 76,
CHAR_DELETE_FAILED_HAS_HEIRLOOM_OR_MAIL = 77,
CHAR_LOGIN_IN_PROGRESS = 77,
CHAR_LOGIN_SUCCESS = 78,
CHAR_LOGIN_NO_WORLD = 79,
CHAR_LOGIN_DUPLICATE_CHARACTER = 80,
CHAR_LOGIN_NO_INSTANCES = 81,
CHAR_LOGIN_FAILED = 82,
CHAR_LOGIN_DISABLED = 83,
CHAR_LOGIN_NO_CHARACTER = 84,
CHAR_LOGIN_LOCKED_FOR_TRANSFER = 85,
CHAR_LOGIN_LOCKED_BY_BILLING = 86,
CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 87,
CHAR_LOGIN_TEMPORARY_GM_LOCK = 88,
CHAR_LOGIN_IN_PROGRESS = 78,
CHAR_LOGIN_SUCCESS = 79,
CHAR_LOGIN_NO_WORLD = 80,
CHAR_LOGIN_DUPLICATE_CHARACTER = 81,
CHAR_LOGIN_NO_INSTANCES = 82,
CHAR_LOGIN_FAILED = 83,
CHAR_LOGIN_DISABLED = 84,
CHAR_LOGIN_NO_CHARACTER = 85,
CHAR_LOGIN_LOCKED_FOR_TRANSFER = 86,
CHAR_LOGIN_LOCKED_BY_BILLING = 87,
CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 88,
CHAR_LOGIN_TEMPORARY_GM_LOCK = 89,
CHAR_LOGIN_LOCKED_BY_CHARACTER_UPGRADE = 90,
CHAR_LOGIN_LOCKED_BY_REVOKED_CHARACTER_UPGRADE = 91,
CHAR_NAME_SUCCESS = 89,
CHAR_NAME_FAILURE = 90,
CHAR_NAME_NO_NAME = 91,
CHAR_NAME_TOO_SHORT = 92,
CHAR_NAME_TOO_LONG = 93,
CHAR_NAME_INVALID_CHARACTER = 94,
CHAR_NAME_MIXED_LANGUAGES = 95,
CHAR_NAME_PROFANE = 96,
CHAR_NAME_RESERVED = 97,
CHAR_NAME_INVALID_APOSTROPHE = 98,
CHAR_NAME_MULTIPLE_APOSTROPHES = 99,
CHAR_NAME_THREE_CONSECUTIVE = 100,
CHAR_NAME_INVALID_SPACE = 101,
CHAR_NAME_CONSECUTIVE_SPACES = 102,
CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 103,
CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 104,
CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 105,
CHAR_NAME_SUCCESS = 92,
CHAR_NAME_FAILURE = 93,
CHAR_NAME_NO_NAME = 94,
CHAR_NAME_TOO_SHORT = 95,
CHAR_NAME_TOO_LONG = 96,
CHAR_NAME_INVALID_CHARACTER = 97,
CHAR_NAME_MIXED_LANGUAGES = 98,
CHAR_NAME_PROFANE = 99,
CHAR_NAME_RESERVED = 100,
CHAR_NAME_INVALID_APOSTROPHE = 101,
CHAR_NAME_MULTIPLE_APOSTROPHES = 102,
CHAR_NAME_THREE_CONSECUTIVE = 103,
CHAR_NAME_INVALID_SPACE = 104,
CHAR_NAME_CONSECUTIVE_SPACES = 105,
CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 106,
CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 107,
CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 108
};
enum CharacterUndeleteResult
{
CHARACTER_UNDELETE_RESULT_OK = 0,
CHARACTER_UNDELETE_RESULT_ERROR_COOLDOWN = 1,
CHARACTER_UNDELETE_RESULT_ERROR_CHAR_CREATE = 2,
CHARACTER_UNDELETE_RESULT_ERROR_DISABLED = 3,
CHARACTER_UNDELETE_RESULT_ERROR_NAME_TAKEN_BY_THIS_ACCOUNT = 4,
CHARACTER_UNDELETE_RESULT_ERROR_UNKNOWN = 5
};
/// Ban function modes
@@ -29,7 +29,7 @@ namespace WorldPackets
class AuthChallenge final : public ServerPacket
{
public:
AuthChallenge() : ServerPacket(SMSG_AUTH_CHALLENGE, 8 + 32 + 1), Challenge(0) { }
AuthChallenge() : ServerPacket(SMSG_AUTH_CHALLENGE, 4 + 32 + 1), Challenge(0) { }
void Write() override;
@@ -37,8 +37,8 @@ WorldPackets::Character::CharEnumResult::CharacterInfo::CharacterInfo(Field* fie
HairColor = uint8((fields[5].GetUInt32() >> 24) & 0xFF);
FacialHair = uint8(fields[6].GetUInt32() & 0xFF);
Level = fields[7].GetUInt8();
ZoneId = fields[8].GetUInt16();
MapId = fields[9].GetUInt16();
ZoneId = int32(fields[8].GetUInt16());
MapId = int32(fields[9].GetUInt16());
PreLoadPosition.x = fields[10].GetFloat();
PreLoadPosition.y = fields[11].GetFloat();
PreLoadPosition.z = fields[12].GetFloat();
@@ -147,8 +147,8 @@ void WorldPackets::Character::CharEnumResult::Write()
_worldPacket << uint8(charInfo.HairColor);
_worldPacket << uint8(charInfo.FacialHair);
_worldPacket << uint8(charInfo.Level);
_worldPacket << uint32(charInfo.ZoneId);
_worldPacket << uint32(charInfo.MapId);
_worldPacket << int32(charInfo.ZoneId);
_worldPacket << int32(charInfo.MapId);
_worldPacket << float(charInfo.PreLoadPosition.x);
_worldPacket << float(charInfo.PreLoadPosition.y);
_worldPacket << float(charInfo.PreLoadPosition.z);
@@ -178,11 +178,97 @@ void WorldPackets::Character::CharEnumResult::Write()
for (RestrictedFactionChangeRuleInfo const& rule : FactionChangeRestrictions)
{
_worldPacket << uint32(rule.Mask);
_worldPacket << int32(rule.Mask);
_worldPacket << uint8(rule.Race);
}
}
WorldPackets::Character::CharacterCreate::CharacterCreate(WorldPacket&& packet)
: ClientPacket(std::move(packet))
{
ASSERT(_worldPacket.GetOpcode() == CMSG_CHAR_CREATE);
}
void WorldPackets::Character::CharacterCreate::Read()
{
CreateInfo.reset(new CharacterCreateInfo());
uint32 nameLength = _worldPacket.ReadBits(6);
CreateInfo->TemplateSet.HasValue = _worldPacket.ReadBit();
_worldPacket >> CreateInfo->Race;
_worldPacket >> CreateInfo->Class;
_worldPacket >> CreateInfo->Sex;
_worldPacket >> CreateInfo->Skin;
_worldPacket >> CreateInfo->Face;
_worldPacket >> CreateInfo->HairStyle;
_worldPacket >> CreateInfo->HairColor;
_worldPacket >> CreateInfo->FacialHairStyle;
_worldPacket >> CreateInfo->OutfitId;
CreateInfo->Name = _worldPacket.ReadString(nameLength);
if (CreateInfo->TemplateSet.HasValue)
_worldPacket >> CreateInfo->TemplateSet.value;
}
WorldPackets::Character::CharacterCreateResponse::CharacterCreateResponse()
: ServerPacket(SMSG_CHAR_CREATE, 1) { }
void WorldPackets::Character::CharacterCreateResponse::Write()
{
_worldPacket << uint8(Code);
}
WorldPackets::Character::CharacterDelete::CharacterDelete(WorldPacket&& packet)
: ClientPacket(std::move(packet))
{
ASSERT(_worldPacket.GetOpcode() == CMSG_CHAR_DELETE);
}
void WorldPackets::Character::CharacterDelete::Read()
{
_worldPacket >> Guid;
}
WorldPackets::Character::CharacterDeleteResponse::CharacterDeleteResponse()
: ServerPacket(SMSG_CHAR_DELETE, 1) { }
void WorldPackets::Character::CharacterDeleteResponse::Write()
{
_worldPacket << uint8(Code);
}
WorldPackets::Character::UndeleteCharacter::UndeleteCharacter(WorldPacket&& packet)
: ClientPacket(std::move(packet))
{
ASSERT(_worldPacket.GetOpcode() == CMSG_UNDELETE_CHARACTER);
}
void WorldPackets::Character::UndeleteCharacter::Read()
{
UndeleteInfo.reset(new CharacterUndeleteInfo());
_worldPacket >> UndeleteInfo->ClientToken;
_worldPacket >> UndeleteInfo->CharacterGuid;
}
WorldPackets::Character::UndeleteCharacterResponse::UndeleteCharacterResponse()
: ServerPacket(SMSG_UNDELETE_CHARACTER_RESPONSE, 26) { }
void WorldPackets::Character::UndeleteCharacterResponse::Write()
{
ASSERT(UndeleteInfo);
_worldPacket << int32(UndeleteInfo->ClientToken);
_worldPacket << uint32(Result);
_worldPacket << UndeleteInfo->CharacterGuid;
}
WorldPackets::Character::UndeleteCooldownStatusResponse::UndeleteCooldownStatusResponse()
: ServerPacket(SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE, 9) { }
void WorldPackets::Character::UndeleteCooldownStatusResponse::Write()
{
_worldPacket.WriteBit(OnCooldown);
_worldPacket << uint32(MaxCooldown);
_worldPacket << uint32(CurrentCooldown);
}
WorldPackets::Character::PlayerLogin::PlayerLogin(WorldPacket&& packet)
: ClientPacket(std::move(packet))
{
@@ -25,6 +25,77 @@ namespace WorldPackets
{
namespace Character
{
struct CharacterCreateInfo
{
friend class CharacterCreate;
friend class Player;
friend class WorldSession;
protected:
/// User specified variables
uint8 Race = 0;
uint8 Class = 0;
uint8 Sex = GENDER_NONE;
uint8 Skin = 0;
uint8 Face = 0;
uint8 HairStyle = 0;
uint8 HairColor = 0;
uint8 FacialHairStyle = 0;
uint8 OutfitId = 0;
Optional<int32> TemplateSet;
std::string Name;
/// Server side data
uint8 CharCount = 0;
};
struct CharacterRenameInfo
{
friend class WorldSession;
protected:
ObjectGuid Guid;
std::string Name;
};
struct CharacterCustomizeInfo : public CharacterRenameInfo
{
friend class Player;
friend class WorldSession;
protected:
uint8 Gender = GENDER_NONE;
uint8 Skin = 0;
uint8 Face = 0;
uint8 HairStyle = 0;
uint8 HairColor = 0;
uint8 FacialHair = 0;
};
struct CharacterFactionChangeInfo : public CharacterCustomizeInfo
{
friend class Player;
friend class WorldSession;
protected:
uint8 Race = 0;
};
struct CharacterUndeleteInfo
{
friend class UndeleteCharacter;
friend class UndeleteCharacterResponse;
friend class WorldSession;
protected:
/// User specified variables
ObjectGuid CharacterGuid; ///< Guid of the character to restore
int32 ClientToken = 0; ///< @todo: research
/// Server side data
std::string Name;
};
class CharEnumResult final : public ServerPacket
{
public:
@@ -51,8 +122,8 @@ namespace WorldPackets
uint8 HairColor = 0;
uint8 FacialHair = 0;
uint8 Level = 0;
uint32 ZoneId = 0;
uint32 MapId = 0;
int32 ZoneId = 0;
int32 MapId = 0;
G3D::Vector3 PreLoadPosition;
ObjectGuid GuildGuid;
uint32 Flags = 0; ///< Character flag @see enum CharacterFlags
@@ -68,7 +139,7 @@ namespace WorldPackets
} Pet;
bool BoostInProgress = false; ///< @todo
uint32 ProfessionIds[2]; ///< @todo
int32 ProfessionIds[2]; ///< @todo
struct VisualItemInfo
{
@@ -82,11 +153,11 @@ namespace WorldPackets
struct RestrictedFactionChangeRuleInfo
{
RestrictedFactionChangeRuleInfo(uint32 mask, uint8 race)
RestrictedFactionChangeRuleInfo(int32 mask, uint8 race)
: Mask(mask), Race(race) { }
uint32 Mask = 0;
uint8 Race = 0;
int32 Mask = 0;
uint8 Race = 0;
};
CharEnumResult();
@@ -100,6 +171,100 @@ namespace WorldPackets
std::list<RestrictedFactionChangeRuleInfo> FactionChangeRestrictions; ///< @todo: research
};
class CharacterCreate final : public ClientPacket
{
public:
CharacterCreate(WorldPacket&& packet);
void Read() override;
/**
* @var uint8 Race
* @var uint8 Class
* @var uint8 Sex
* @var uint8 Skin
* @var uint8 Face
* @var uint8 HairStyle
* @var uint8 HairColor
* @var uint8 FacialHairStyle
* @var uint8 OutfitId
* @var Optional<int32> TemplateSet
* @var std::string Name
*/
std::shared_ptr<CharacterCreateInfo> CreateInfo;
};
class CharacterCreateResponse final : public ServerPacket
{
public:
CharacterCreateResponse();
void Write() override;
uint8 Code = 0; ///< Result code @see enum ResponseCodes
};
class CharacterDelete final : public ClientPacket
{
public:
CharacterDelete(WorldPacket&& packet);
void Read() override;
ObjectGuid Guid; ///< Guid of the character to delete
};
class CharacterDeleteResponse final : public ServerPacket
{
public:
CharacterDeleteResponse();
void Write() override;
uint8 Code = 0; ///< Result code @see enum ResponseCodes
};
class UndeleteCharacter final : public ClientPacket
{
public:
UndeleteCharacter(WorldPacket&& packet);
void Read() override;
/**
* @var ObjectGuid CharacterGuid
* @var int32 ClientToken
*/
std::shared_ptr<CharacterUndeleteInfo> UndeleteInfo;
};
class UndeleteCharacterResponse final : public ServerPacket
{
public:
UndeleteCharacterResponse();
void Write() override;
/**
* @var ObjectGuid CharacterGuid
* @var int32 ClientToken
*/
CharacterUndeleteInfo const* UndeleteInfo = nullptr;
uint32 Result = 0; ///< @see enum CharacterUndeleteResult
};
class UndeleteCooldownStatusResponse final : public ServerPacket
{
public:
UndeleteCooldownStatusResponse();
void Write() override;
bool OnCooldown = false; ///<
uint32 MaxCooldown = 0; ///< Max. cooldown until next free character restoration. Displayed in undelete confirm message. (in sec)
uint32 CurrentCooldown = 0; ///< Current cooldown until next free character restoration. (in sec)
};
class PlayerLogin final : public ClientPacket
{
public:
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SystemPackets.h"
WorldPackets::System::FeatureSystemStatusGlueScreen::FeatureSystemStatusGlueScreen()
: ServerPacket(SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN, 1) { }
void WorldPackets::System::FeatureSystemStatusGlueScreen::Write()
{
_worldPacket.WriteBit(BpayStoreEnabled);
_worldPacket.WriteBit(BpayStoreAvailable);
_worldPacket.WriteBit(BpayStoreDisabledByParentalControls);
_worldPacket.WriteBit(CharUndeleteEnabled);
_worldPacket.FlushBits();
}
WorldPackets::System::SetTimeZoneInformation::SetTimeZoneInformation()
: ServerPacket(SMSG_SET_TIME_ZONE_INFORMATION) { }
void WorldPackets::System::SetTimeZoneInformation::Write()
{
_worldPacket.reserve(1 + ServerTimeTZ.length() + GameTimeTZ.length());
_worldPacket.WriteBits(ServerTimeTZ.length(), 7);
_worldPacket.WriteBits(GameTimeTZ.length(), 7);
_worldPacket.WriteString(ServerTimeTZ);
_worldPacket.WriteString(GameTimeTZ);
}
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SystemPackets_h__
#define SystemPackets_h__
#include "Packet.h"
namespace WorldPackets
{
namespace System
{
class FeatureSystemStatusGlueScreen final : public ServerPacket
{
public:
FeatureSystemStatusGlueScreen();
void Write() override;
bool BpayStoreAvailable = false; // NYI
bool BpayStoreDisabledByParentalControls = false; // NYI
bool CharUndeleteEnabled = false; // NYI
bool BpayStoreEnabled = false; // NYI
};
class SetTimeZoneInformation final : public ServerPacket
{
public:
SetTimeZoneInformation();
void Write() override;
std::string ServerTimeTZ;
std::string GameTimeTZ;
};
}
}
#endif // SystemPackets_h__
+13 -4
View File
@@ -214,13 +214,14 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANNEL_UNSILENCE_VOICE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANNEL_VOICE_OFF, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelVoiceOnOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANNEL_VOICE_ON, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelVoiceOnOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_CREATE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCreateOpcode );
DEFINE_HANDLER(CMSG_CHAR_CREATE, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharacterCreate, &WorldSession::HandleCharCreateOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_CUSTOMIZE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCustomize );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_DELETE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharDeleteOpcode );
DEFINE_HANDLER(CMSG_CHAR_DELETE, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharacterDelete, &WorldSession::HandleCharDeleteOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_ENUM, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharEnumOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_FACTION_CHANGE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_RACE_CHANGE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_RENAME, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharRenameOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAR_UNDELETE_ENUM, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharUndeleteEnumOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_FILTERED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_IGNORED, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChatIgnoredOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_CLEAR_CHANNEL_WATCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
@@ -259,6 +260,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_EQUIPMENT_SET_DELETE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetDelete );
DEFINE_OPCODE_HANDLER_OLD(CMSG_EQUIPMENT_SET_SAVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetSave );
DEFINE_OPCODE_HANDLER_OLD(CMSG_EQUIPMENT_SET_USE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetUse );
DEFINE_OPCODE_HANDLER_OLD(CMSG_FACTION_BONUS_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_FAR_SIGHT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleFarSightOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_FORCE_MOVE_ROOT_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck );
DEFINE_OPCODE_HANDLER_OLD(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveUnRootAck );
@@ -585,6 +587,8 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_TUTORIAL_FLAG, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlag );
DEFINE_OPCODE_HANDLER_OLD(CMSG_TUTORIAL_RESET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialReset );
DEFINE_OPCODE_HANDLER_OLD(CMSG_UNACCEPT_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode );
DEFINE_HANDLER(CMSG_UNDELETE_CHARACTER, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::UndeleteCharacter, &WorldSession::HandleCharUndeleteOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_UNDELETE_COOLDOWN_STATUS_QUERY, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleUndeleteCooldownStatusQuery);
DEFINE_OPCODE_HANDLER_OLD(CMSG_UNLEARN_SKILL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnlearnSkillOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_UNLEARN_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_UNREGISTER_ALL_ADDON_PREFIXES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnregisterAddonPrefixesOpcode);
@@ -736,6 +740,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_INFO_THROTTLED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_JOINED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_LEFT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDER_CONFIRM, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDPOINTUPDATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDZONEREPLY, STATUS_UNHANDLED);
@@ -774,7 +779,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CREATE, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_DELETE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_DELETE, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_ENUM, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_FACTION_CHANGE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_RENAME, STATUS_UNHANDLED);
@@ -856,7 +861,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EXPLORATION_EXPERIENCE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FAILED_PLAYER_CONDITION, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FEATURE_SYSTEM_STATUS, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FEIGN_DEATH_RESISTED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FISH_ESCAPED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FISH_NOT_HOOKED, STATUS_UNHANDLED);
@@ -954,6 +959,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_INFO, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_NOTIFY, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INITIALIZE_FACTIONS, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INITIAL_SETUP, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INITIAL_SPELLS, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INIT_CURRENCY, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INIT_WORLD_STATES, STATUS_UNHANDLED);
@@ -1231,6 +1237,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PROFICIENCY, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PROJECTILE_POSITION, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_TIME_ZONE_INFORMATION, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOWTAXINODES, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_BANK, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_UNHANDLED);
@@ -1324,6 +1331,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_MOVIE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TURN_IN_PETITION_RESULTS, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TUTORIAL_FLAGS, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UNDELETE_CHARACTER_RESPONSE, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UNIT_HEALTH_FREQUENT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UNIT_SPELLCAST_START, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_ACCOUNT_DATA, STATUS_UNHANDLED);
+30 -22
View File
@@ -46,7 +46,7 @@ enum OpcodeClient : uint32
CMSG_ADD_IGNORE = 0xBADD,
CMSG_ADD_VOICE_IGNORE = 0xBADD,
CMSG_ALTER_APPEARANCE = 0xBADD,
CMSG_AREATRIGGER = 0xBADD,
CMSG_AREATRIGGER = 0x01B4,
CMSG_AREA_SPIRIT_HEALER_QUERY = 0xBADD,
CMSG_AREA_SPIRIT_HEALER_QUEUE = 0xBADD,
CMSG_ARENA_TEAM_ACCEPT = 0xBADD,
@@ -162,6 +162,7 @@ enum OpcodeClient : uint32
CMSG_CHAR_FACTION_CHANGE = 0xBADD,
CMSG_CHAR_RACE_CHANGE = 0xBADD,
CMSG_CHAR_RENAME = 0xBADD,
CMSG_CHAR_UNDELETE_ENUM = 0x0F2D,
CMSG_CHAT_FILTERED = 0xBADD,
CMSG_CHAT_IGNORED = 0xBADD,
CMSG_CLEAR_CHANNEL_WATCH = 0xBADD,
@@ -201,6 +202,7 @@ enum OpcodeClient : uint32
CMSG_EQUIPMENT_SET_DELETE = 0xBADD,
CMSG_EQUIPMENT_SET_SAVE = 0x1B54,
CMSG_EQUIPMENT_SET_USE = 0xBADD,
CMSG_FACTION_BONUS_INFO = 0x0928,
CMSG_FAR_SIGHT = 0xBADD,
CMSG_FORCE_MOVE_ROOT_ACK = 0xBADD,
CMSG_FORCE_MOVE_UNROOT_ACK = 0xBADD,
@@ -278,7 +280,7 @@ enum OpcodeClient : uint32
CMSG_GUILD_REPLACE_GUILD_MASTER = 0xBADD,
CMSG_GUILD_REQUEST_CHALLENGE_UPDATE = 0xBADD,
CMSG_GUILD_REQUEST_MAX_DAILY_XP = 0xBADD,
CMSG_GUILD_REQUEST_PARTY_STATE = 0xBADD,
CMSG_GUILD_REQUEST_PARTY_STATE = 0x0A8E,
CMSG_GUILD_ROSTER = 0xBADD,
CMSG_GUILD_SET_ACHIEVEMENT_TRACKING = 0xBADD,
CMSG_GUILD_SET_GUILD_MASTER = 0xBADD,
@@ -443,8 +445,8 @@ enum OpcodeClient : uint32
CMSG_QUESTGIVER_QUERY_QUEST = 0x1924,
CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0xBADD,
CMSG_QUESTGIVER_REQUEST_REWARD = 0xBADD,
CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0xBADD,
CMSG_QUESTGIVER_STATUS_QUERY = 0xBADD,
CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x0131,
CMSG_QUESTGIVER_STATUS_QUERY = 0x0704,
CMSG_QUESTLOG_REMOVE_QUEST = 0xBADD,
CMSG_QUESTLOG_SWAP_QUEST = 0xBADD,
CMSG_QUEST_CONFIRM_ACCEPT = 0xBADD,
@@ -458,7 +460,7 @@ enum OpcodeClient : uint32
CMSG_RECLAIM_CORPSE = 0xBADD,
CMSG_REDIRECTION_AUTH_PROOF = 0x0485,
CMSG_REFORGE_ITEM = 0xBADD,
CMSG_REORDER_CHARACTERS = 0xBADD,
CMSG_REORDER_CHARACTERS = 0x0DAA,
CMSG_REPAIR_ITEM = 0xBADD,
CMSG_REPLACE_ACCOUNT_DATA = 0xBADD,
CMSG_REPOP_REQUEST = 0xBADD,
@@ -567,6 +569,8 @@ enum OpcodeClient : uint32
CMSG_TUTORIAL_FLAG = 0xBADD,
CMSG_TUTORIAL_RESET = 0xBADD,
CMSG_UNACCEPT_TRADE = 0xBADD,
CMSG_UNDELETE_CHARACTER = 0x0D99,
CMSG_UNDELETE_COOLDOWN_STATUS_QUERY = 0x19A9,
CMSG_UNLEARN_SKILL = 0xBADD,
CMSG_UNLEARN_SPECIALIZATION = 0xBADD,
CMSG_UNREGISTER_ALL_ADDON_PREFIXES = 0xBADD,
@@ -738,6 +742,7 @@ enum OpcodeServer : uint32
SMSG_BATTLEGROUND_INFO_THROTTLED = 0xBADD,
SMSG_BATTLEGROUND_PLAYER_JOINED = 0xBADD,
SMSG_BATTLEGROUND_PLAYER_LEFT = 0xBADD,
SMSG_BATTLE_PET_JOURNAL = 0x19A2,
SMSG_BINDER_CONFIRM = 0xBADD,
SMSG_BINDPOINTUPDATE = 0x0A30,
SMSG_BINDZONEREPLY = 0xBADD,
@@ -916,7 +921,7 @@ enum OpcodeServer : uint32
SMSG_GROUP_SET_LEADER = 0xBADD,
SMSG_GROUP_SET_ROLE = 0xBADD,
SMSG_GROUP_UNINVITE = 0xBADD,
SMSG_GUILD_ACHIEVEMENT_DATA = 0xBADD,
SMSG_GUILD_ACHIEVEMENT_DATA = 0x1866,
SMSG_GUILD_ACHIEVEMENT_DELETED = 0xBADD,
SMSG_GUILD_ACHIEVEMENT_EARNED = 0xBADD,
SMSG_GUILD_ACHIEVEMENT_MEMBERS = 0xBADD,
@@ -933,7 +938,7 @@ enum OpcodeServer : uint32
SMSG_GUILD_CRITERIA_DATA = 0xBADD,
SMSG_GUILD_CRITERIA_DELETED = 0xBADD,
SMSG_GUILD_DECLINE = 0xBADD,
SMSG_GUILD_EVENT = 0xBADD,
SMSG_GUILD_EVENT = 0x1027,
SMSG_GUILD_EVENT_LOG_QUERY_RESULT = 0xBADD,
SMSG_GUILD_EVENT_PRESENCE_CHANGE = 0x1228,
SMSG_GUILD_FLAGGED_FOR_RENAME = 0xBADD,
@@ -950,12 +955,12 @@ enum OpcodeServer : uint32
SMSG_GUILD_MOVE_STARTING = 0xBADD,
SMSG_GUILD_NEWS_DELETED = 0xBADD,
SMSG_GUILD_NEWS_UPDATE = 0xBADD,
SMSG_GUILD_PARTY_STATE_RESPONSE = 0xBADD,
SMSG_GUILD_PARTY_STATE_RESPONSE = 0x1225,
SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0xBADD,
SMSG_GUILD_QUERY_RESPONSE = 0x1046,
SMSG_GUILD_RANK = 0x1218,
SMSG_GUILD_RANKS_UPDATE = 0xBADD,
SMSG_GUILD_RECIPES = 0xBADD,
SMSG_GUILD_RECIPES = 0x1078,
SMSG_GUILD_RENAMED = 0xBADD,
SMSG_GUILD_REPUTATION_REACTION_CHANGED = 0xBADD,
SMSG_GUILD_REPUTATION_WEEKLY_CAP = 0xBADD,
@@ -974,7 +979,8 @@ enum OpcodeServer : uint32
SMSG_HOTFIX_NOTIFY = 0xBADD,
SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0xBADD,
SMSG_IGNORE_REQUIREMENTS_CHEAT = 0xBADD,
SMSG_INITIALIZE_FACTIONS = 0xBADD,
SMSG_INITIALIZE_FACTIONS = 0x0B10,
SMSG_INITIAL_SETUP = 0x0B07,
SMSG_INITIAL_SPELLS = 0x0A81,
SMSG_INIT_CURRENCY = 0x0B06,
SMSG_INIT_WORLD_STATES = 0x0B04,
@@ -1013,7 +1019,7 @@ enum OpcodeServer : uint32
SMSG_LFG_OFFER_CONTINUE = 0xBADD,
SMSG_LFG_OPEN_FROM_GOSSIP = 0xBADD,
SMSG_LFG_PARTY_INFO = 0xBADD,
SMSG_LFG_PLAYER_INFO = 0xBADD,
SMSG_LFG_PLAYER_INFO = 0x0F36,
SMSG_LFG_PLAYER_REWARD = 0xBADD,
SMSG_LFG_PROPOSAL_UPDATE = 0xBADD,
SMSG_LFG_QUEUE_STATUS = 0xBADD,
@@ -1139,7 +1145,7 @@ enum OpcodeServer : uint32
SMSG_PARTY_MEMBER_STATS = 0xBADD,
SMSG_PARTY_MEMBER_STATS_FULL = 0xBADD,
SMSG_PAUSE_MIRROR_TIMER = 0xBADD,
SMSG_PERIODICAURALOG = 0xBADD,
SMSG_PERIODICAURALOG = 0x0B1B,
SMSG_PETGODMODE = 0xBADD,
SMSG_PETITION_ALREADY_SIGNED = 0xBADD,
SMSG_PETITION_QUERY_RESPONSE = 0xBADD,
@@ -1179,7 +1185,7 @@ enum OpcodeServer : uint32
SMSG_PLAY_SPELL_VISUAL_KIT = 0xBADD,
SMSG_PLAY_TIME_WARNING = 0xBADD,
SMSG_PONG = 0x17CA,
SMSG_POWER_UPDATE = 0xBADD,
SMSG_POWER_UPDATE = 0x0B27,
SMSG_PRE_RESURRECT = 0xBADD,
SMSG_PROCRESIST = 0xBADD,
SMSG_PROPOSE_LEVEL_GRANT = 0xBADD,
@@ -1196,8 +1202,8 @@ enum OpcodeServer : uint32
SMSG_QUESTGIVER_QUEST_INVALID = 0xBADD,
SMSG_QUESTGIVER_QUEST_LIST = 0xBADD,
SMSG_QUESTGIVER_REQUEST_ITEMS = 0xBADD,
SMSG_QUESTGIVER_STATUS = 0xBADD,
SMSG_QUESTGIVER_STATUS_MULTIPLE = 0xBADD,
SMSG_QUESTGIVER_STATUS = 0x1567,
SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x17C6,
SMSG_QUESTLOG_FULL = 0xBADD,
SMSG_QUESTUPDATE_ADD_ITEM = 0xBADD,
SMSG_QUESTUPDATE_ADD_KILL = 0xBADD,
@@ -1205,7 +1211,7 @@ enum OpcodeServer : uint32
SMSG_QUESTUPDATE_COMPLETE = 0xBADD,
SMSG_QUESTUPDATE_FAILED = 0xBADD,
SMSG_QUESTUPDATE_FAILEDTIMER = 0xBADD,
SMSG_QUEST_NPC_QUERY_RESPONSE = 0xBADD,
SMSG_QUEST_NPC_QUERY_RESPONSE = 0x1591,
SMSG_QUEST_CONFIRM_ACCEPT = 0xBADD,
SMSG_QUEST_FORCE_REMOVE = 0xBADD,
SMSG_QUEST_POI_QUERY_RESPONSE = 0x1715,
@@ -1245,7 +1251,6 @@ enum OpcodeServer : uint32
SMSG_RWHOIS = 0xBADD,
SMSG_SELL_ITEM = 0xBADD,
SMSG_SEND_MAIL_RESULT = 0x0302,
SMSG_SEND_SERVER_LOCATION = 0x153E,
SMSG_SEND_UNLEARN_SPELLS = 0x1A82,
SMSG_SERVERTIME = 0xBADD,
SMSG_SERVER_FIRST_ACHIEVEMENT = 0xBADD,
@@ -1268,6 +1273,7 @@ enum OpcodeServer : uint32
SMSG_SET_PLAY_HOVER_ANIM = 0xBADD,
SMSG_SET_PROFICIENCY = 0x00D3,
SMSG_SET_PROJECTILE_POSITION = 0xBADD,
SMSG_SET_TIME_ZONE_INFORMATION = 0x153E,
SMSG_SET_VIGNETTE = 0x09AC,
SMSG_SHOWTAXINODES = 0xBADD,
SMSG_SHOW_BANK = 0x0204,
@@ -1278,11 +1284,11 @@ enum OpcodeServer : uint32
SMSG_SPELLBREAKLOG = 0xBADD,
SMSG_SPELLDAMAGESHIELD = 0xBADD,
SMSG_SPELLDISPELLOG = 0xBADD,
SMSG_SPELLENERGIZELOG = 0xBADD,
SMSG_SPELLHEALLOG = 0xBADD,
SMSG_SPELLENERGIZELOG = 0x137C,
SMSG_SPELLHEALLOG = 0x0114,
SMSG_SPELLINSTAKILLLOG = 0xBADD,
SMSG_SPELLINTERRUPTLOG = 0xBADD,
SMSG_SPELLLOGEXECUTE = 0xBADD,
SMSG_SPELLLOGEXECUTE = 0x1823,
SMSG_SPELLLOGMISS = 0xBADD,
SMSG_SPELLNONMELEEDAMAGELOG = 0x11FB,
SMSG_SPELLORDAMAGE_IMMUNE = 0xBADD,
@@ -1358,14 +1364,16 @@ enum OpcodeServer : uint32
SMSG_TRAINER_BUY_SUCCEEDED = 0xBADD,
SMSG_TRAINER_LIST = 0x0BA9,
SMSG_TRANSFER_ABORTED = 0xBADD,
SMSG_TRANSFER_PENDING = 0xBADD,
SMSG_TRANSFER_PENDING = 0x172A,
SMSG_TRIGGER_CINEMATIC = 0xBADD,
SMSG_TRIGGER_MOVIE = 0xBADD,
SMSG_TURN_IN_PETITION_RESULTS = 0xBADD,
SMSG_TUTORIAL_FLAGS = 0x020F,
SMSG_UNDELETE_CHARACTER_RESPONSE = 0x0344,
SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE = 0x0310,
SMSG_UNIT_HEALTH_FREQUENT = 0xBADD,
SMSG_UNIT_SPELLCAST_START = 0xBADD,
SMSG_UPDATE_ACCOUNT_DATA = 0xBADD,
SMSG_UPDATE_ACCOUNT_DATA = 0x1520,
SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0xBADD,
SMSG_UPDATE_COMBO_POINTS = 0xBADD,
SMSG_UPDATE_CURRENCY = 0xBADD,
-2
View File
@@ -23,8 +23,6 @@
#include "Opcodes.h"
#include "ByteBuffer.h"
struct z_stream_s;
class WorldPacket : public ByteBuffer
{
public:
+32 -10
View File
@@ -21,7 +21,6 @@
*/
#include "WorldSocket.h"
#include "Packet.h"
#include <zlib.h>
#include "Config.h"
#include "Common.h"
@@ -49,6 +48,7 @@
#include "WardenWin.h"
#include "WardenMac.h"
#include "BattlenetServerManager.h"
#include "CharacterPackets.h"
namespace {
@@ -1042,25 +1042,32 @@ void WorldSession::SetPlayer(Player* player)
void WorldSession::InitializeQueryCallbackParameters()
{
// Callback parameters that have pointers in them should be properly
// initialized to NULL here.
_charCreateCallback.SetParam(NULL);
// initialized to nullptr here.
_charRenameCallback.SetParam(nullptr);
}
void WorldSession::ProcessQueryCallbacks()
{
PreparedQueryResult result;
//! HandleCharEnumOpcode
if (_charEnumCallback.valid() && _charEnumCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
//! HandleCharEnumOpcode and HandleCharUndeleteEnumOpcode
if (_charEnumCallback.IsReady())
{
result = _charEnumCallback.get();
HandleCharEnum(result);
_charEnumCallback.GetResult(result);
if (bool undelete = _charEnumCallback.GetParam())
HandleCharUndeleteEnum(result);
else
HandleCharEnum(result);
_charEnumCallback.FreeResult();
}
//! HandleCharCreateOpcode
if (_charCreateCallback.IsReady())
{
_charCreateCallback.GetResult(result);
HandleCharCreateCallback(result, _charCreateCallback.GetParam());
HandleCharCreateCallback(result, _charCreateCallback.GetParam().get());
}
//! HandlePlayerLoginOpcode
@@ -1083,12 +1090,27 @@ void WorldSession::ProcessQueryCallbacks()
if (_charRenameCallback.IsReady())
{
_charRenameCallback.GetResult(result);
CharacterRenameInfo* renameInfo = _charRenameCallback.GetParam();
HandleChangePlayerNameOpcodeCallBack(result, renameInfo);
WorldPackets::Character::CharacterRenameInfo* renameInfo = _charRenameCallback.GetParam();
HandleCharRenameCallBack(result, renameInfo);
delete renameInfo;
_charRenameCallback.Reset();
}
/// HandleUndeleteCooldownStatusOpcode
/// wait until no char undelete is in progress
if (!_charUndeleteCallback.GetStage() && _undeleteCooldownStatusCallback.IsReady())
{
_undeleteCooldownStatusCallback.GetResult(result);
HandleUndeleteCooldownStatusCallback(result);
}
/// HandleCharUndeleteOpcode
if (_charUndeleteCallback.IsReady())
{
_charUndeleteCallback.GetResult(result);
HandleCharUndeleteCallback(result, _charUndeleteCallback.GetParam().get());
}
//- HandleCharAddIgnoreOpcode
if (_addIgnoreCallback.valid() && _addIgnoreCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
+40 -74
View File
@@ -54,6 +54,7 @@ struct DeclinedName;
struct ItemTemplate;
struct MovementInfo;
struct TradeStatusInfo;
struct z_stream_s;
namespace lfg
{
@@ -73,10 +74,17 @@ class RBACData;
namespace WorldPackets
{
class ServerPacket;
namespace Character
{
struct CharacterCreateInfo;
struct CharacterRenameInfo;
struct CharacterCustomizeInfo;
struct CharacterFactionChangeInfo;
struct CharacterUndeleteInfo;
class CharacterCreate;
class CharacterDelete;
class UndeleteCharacter;
class PlayerLogin;
}
}
@@ -176,6 +184,7 @@ private:
PacketFilter(PacketFilter const& right) = delete;
PacketFilter& operator=(PacketFilter const& right) = delete;
};
//process only thread-safe packets in Map::Update()
class MapSessionFilter : public PacketFilter
{
@@ -199,62 +208,6 @@ public:
virtual bool Process(WorldPacket* packet) override;
};
// Proxy structure to contain data passed to callback function,
// only to prevent bloating the parameter list
class CharacterCreateInfo
{
friend class WorldSession;
friend class Player;
protected:
/// User specified variables
std::string Name;
uint8 Race = 0;
uint8 Class = 0;
uint8 Gender = GENDER_NONE;
uint8 Skin = 0;
uint8 Face = 0;
uint8 HairStyle = 0;
uint8 HairColor = 0;
uint8 FacialHair = 0;
uint8 OutfitId = 0;
/// Server side data
uint8 CharCount = 0;
};
struct CharacterRenameInfo
{
friend class WorldSession;
protected:
ObjectGuid Guid;
std::string Name;
};
struct CharacterCustomizeInfo : public CharacterRenameInfo
{
friend class Player;
friend class WorldSession;
protected:
uint8 Gender = GENDER_NONE;
uint8 Skin = 0;
uint8 Face = 0;
uint8 HairStyle = 0;
uint8 HairColor = 0;
uint8 FacialHair = 0;
};
struct CharacterFactionChangeInfo : public CharacterCustomizeInfo
{
friend class Player;
friend class WorldSession;
protected:
uint8 Race = 0;
};
struct PacketCounter
{
time_t lastReceiveTime;
@@ -337,6 +290,9 @@ class WorldSession
/// Handle the authentication waiting queue (to be completed)
void SendAuthWaitQue(uint32 position);
void SendSetTimeZoneInformation();
void SendFeatureSystemStatusGlueScreen();
void SendNameQueryOpcode(ObjectGuid guid);
void SendTrainerList(ObjectGuid guid);
@@ -471,25 +427,38 @@ class WorldSession
void Handle_ServerSide(WorldPacket& recvPacket); // sever side only, can't be accepted from client
void Handle_Deprecated(WorldPacket& recvPacket); // never used anymore by client
void HandleCharEnumOpcode(WorldPacket& recvPacket);
void HandleCharDeleteOpcode(WorldPacket& recvPacket);
void HandleCharCreateOpcode(WorldPacket& recvPacket);
void HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo);
void HandleCharEnum(PreparedQueryResult result);
void HandleCharEnumOpcode(WorldPacket& /*recvData*/);
void HandleCharUndeleteEnum(PreparedQueryResult result);
void HandleCharUndeleteEnumOpcode(WorldPacket& /*recvData*/);
void HandleCharDeleteOpcode(WorldPackets::Character::CharacterDelete& charDelete);
void HandleCharCreateOpcode(WorldPackets::Character::CharacterCreate& charCreate);
void HandleCharCreateCallback(PreparedQueryResult result, WorldPackets::Character::CharacterCreateInfo* createInfo);
void HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& playerLogin);
void HandleLoadScreenOpcode(WorldPacket& recvPacket);
void HandleCharEnum(PreparedQueryResult result);
void HandlePlayerLogin(LoginQueryHolder * holder);
void HandleCharRenameOpcode(WorldPacket& recvData);
void HandleCharRenameCallBack(PreparedQueryResult result, WorldPackets::Character::CharacterRenameInfo const* renameInfo);
void HandleSetPlayerDeclinedNames(WorldPacket& recvData);
void HandleAlterAppearance(WorldPacket& recvData);
void HandleCharFactionOrRaceChange(WorldPacket& recvData);
void HandleRandomizeCharNameOpcode(WorldPacket& recvData);
void HandleReorderCharacters(WorldPacket& recvData);
void HandleOpeningCinematic(WorldPacket& recvData);
void HandleUndeleteCooldownStatusQuery(WorldPacket& /*recvData*/);
void HandleUndeleteCooldownStatusCallback(PreparedQueryResult result);
void HandleCharUndeleteOpcode(WorldPackets::Character::UndeleteCharacter& undeleteInfo);
void HandleCharUndeleteCallback(PreparedQueryResult result, WorldPackets::Character::CharacterUndeleteInfo* undeleteInfo);
void SendCharCreate(ResponseCodes result);
void SendCharDelete(ResponseCodes result);
void SendCharRename(ResponseCodes result, CharacterRenameInfo const& renameInfo);
void SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const& customizeInfo);
void SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const& factionChangeInfo);
void SendCharRename(ResponseCodes result, WorldPackets::Character::CharacterRenameInfo const& renameInfo);
void SendCharCustomize(ResponseCodes result, WorldPackets::Character::CharacterCustomizeInfo const& customizeInfo);
void SendCharFactionChange(ResponseCodes result, WorldPackets::Character::CharacterFactionChangeInfo const& factionChangeInfo);
void SendSetPlayerDeclinedNamesResult(DeclinedNameResult result, ObjectGuid guid);
void SendBarberShopResult(BarberShopResult result);
void SendUndeleteCooldownStatusResponse(uint32 currentCooldown, uint32 maxCooldown);
void SendUndeleteCharacterResponse(CharacterUndeleteResult result, WorldPackets::Character::CharacterUndeleteInfo const* undeleteInfo);
// played time
void HandlePlayedTime(WorldPacket& recvPacket);
@@ -858,10 +827,6 @@ class WorldSession
void HandleSetActionBarToggles(WorldPacket& recvData);
void HandleCharRenameOpcode(WorldPacket& recvData);
void HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, CharacterRenameInfo const* renameInfo);
void HandleSetPlayerDeclinedNames(WorldPacket& recvData);
void HandleTotemDestroyed(WorldPacket& recvData);
void HandleDismissCritter(WorldPacket& recvData);
@@ -1026,7 +991,6 @@ class WorldSession
// Miscellaneous
void HandleSpellClick(WorldPacket& recvData);
void HandleMirrorImageDataRequest(WorldPacket& recvData);
void HandleAlterAppearance(WorldPacket& recvData);
void HandleRemoveGlyph(WorldPacket& recvData);
void HandleCharCustomize(WorldPacket& recvData);
void HandleQueryInspectAchievements(WorldPacket& recvData);
@@ -1057,15 +1021,17 @@ class WorldSession
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
PreparedQueryResultFuture _charEnumCallback;
PreparedQueryResultFuture _addIgnoreCallback;
PreparedQueryResultFuture _stablePetCallback;
QueryCallback<PreparedQueryResult, CharacterRenameInfo*> _charRenameCallback;
QueryCallback<PreparedQueryResult, bool> _charEnumCallback;
QueryCallback<PreparedQueryResult, std::string> _addFriendCallback;
QueryCallback<PreparedQueryResult, uint32> _unstablePetCallback;
QueryCallback<PreparedQueryResult, uint32> _stableSwapCallback;
QueryCallback<PreparedQueryResult, ObjectGuid> _sendStabledPetCallback;
QueryCallback<PreparedQueryResult, CharacterCreateInfo*, true> _charCreateCallback;
QueryCallback<PreparedQueryResult, std::shared_ptr<WorldPackets::Character::CharacterCreateInfo>, true> _charCreateCallback;
QueryCallback<PreparedQueryResult, WorldPackets::Character::CharacterRenameInfo*> _charRenameCallback;
QueryCallback<PreparedQueryResult, bool, true> _undeleteCooldownStatusCallback;
QueryCallback<PreparedQueryResult, std::shared_ptr<WorldPackets::Character::CharacterUndeleteInfo>, true> _charUndeleteCallback;
QueryResultHolderFuture _charLoginCallback;
friend class World;
+1 -1
View File
@@ -389,7 +389,7 @@ void fixNULLfields(std::string &line)
DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid)
{
uint32 charcount = AccountMgr::GetCharactersCount(account);
if (charcount >= 10)
if (charcount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
return DUMP_TOO_MANY_CHARS;
FILE* fin = fopen(file.c_str(), "r");
+13 -4
View File
@@ -271,6 +271,10 @@ void World::AddSession_(WorldSession* s)
}
s->SendAuthResponse(AUTH_OK, false);
s->SendSetTimeZoneInformation();
s->SendFeatureSystemStatusGlueScreen();
s->SendAddonsInfo();
s->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
s->SendTutorialsData();
@@ -707,11 +711,11 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.RaceMask", 0);
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.ClassMask", 0);
m_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfigMgr->GetIntDefault("CharactersPerRealm", 10);
if (m_int_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_int_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
m_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfigMgr->GetIntDefault("CharactersPerRealm", MAX_CHARACTERS_PER_REALM);
if (m_int_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_int_configs[CONFIG_CHARACTERS_PER_REALM] > MAX_CHARACTERS_PER_REALM)
{
TC_LOG_ERROR("server.loading", "CharactersPerRealm (%i) must be in range 1..10. Set to 10.", m_int_configs[CONFIG_CHARACTERS_PER_REALM]);
m_int_configs[CONFIG_CHARACTERS_PER_REALM] = 10;
m_int_configs[CONFIG_CHARACTERS_PER_REALM] = MAX_CHARACTERS_PER_REALM;
}
// must be after CONFIG_CHARACTERS_PER_REALM
@@ -1226,6 +1230,11 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_WARDEN_CLIENT_FAIL_ACTION] = sConfigMgr->GetIntDefault("Warden.ClientCheckFailAction", 0);
m_int_configs[CONFIG_WARDEN_CLIENT_RESPONSE_DELAY] = sConfigMgr->GetIntDefault("Warden.ClientResponseDelay", 600);
// Feature System
m_bool_configs[CONFIG_FEATURE_SYSTEM_BPAY_STORE_ENABLED] = sConfigMgr->GetBoolDefault("FeatureSystem.BpayStore.Enabled", false);
m_bool_configs[CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_ENABLED] = sConfigMgr->GetBoolDefault("FeatureSystem.CharacterUndelete.Enabled", false);
m_int_configs[CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN] = sConfigMgr->GetIntDefault("FeatureSystem.CharacterUndelete.Cooldown", 2592000);
// Dungeon finder
m_int_configs[CONFIG_LFG_OPTIONSMASK] = sConfigMgr->GetIntDefault("DungeonFinder.OptionsMask", 1);
@@ -3190,7 +3199,7 @@ void World::ProcessQueryCallbacks()
{
PreparedQueryResult result;
for (std::deque<std::future<PreparedQueryResult>>::iterator itr = m_realmCharCallbacks.begin(); itr != m_realmCharCallbacks.end(); )
for (std::deque<PreparedQueryResultFuture>::iterator itr = m_realmCharCallbacks.begin(); itr != m_realmCharCallbacks.end(); )
{
if ((*itr).wait_for(std::chrono::seconds(0)) != std::future_status::ready)
{
+6 -1
View File
@@ -170,6 +170,8 @@ enum WorldBoolConfigs
CONFIG_ALLOW_TRACK_BOTH_RESOURCES,
CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA,
CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA,
CONFIG_FEATURE_SYSTEM_BPAY_STORE_ENABLED,
CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_ENABLED,
BOOL_CONFIG_VALUE_COUNT
};
@@ -358,6 +360,7 @@ enum WorldIntConfigs
CONFIG_BG_REWARD_WINNER_CONQUEST_LAST,
CONFIG_CREATURE_PICKPOCKET_REFILL,
CONFIG_AHBOT_UPDATE_INTERVAL,
CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN,
INT_CONFIG_VALUE_COUNT
};
@@ -510,6 +513,8 @@ enum WorldStates
WS_GUILD_WEEKLY_RESET_TIME = 20050, // Next guild week reset time
};
#define MAX_CHARACTERS_PER_REALM 11
/// Storage class for commands issued for delayed execution
struct CliCommandHolder
{
@@ -878,7 +883,7 @@ class World
void LoadCharacterNameData();
void ProcessQueryCallbacks();
std::deque<std::future<PreparedQueryResult>> m_realmCharCallbacks;
std::deque<PreparedQueryResultFuture> m_realmCharCallbacks;
};
extern Battlenet::RealmHandle realmHandle;
+2 -2
View File
@@ -105,7 +105,7 @@ public:
if (isNumeric(searchString.c_str()))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID);
stmt->setUInt64(0, uint32(atoi(searchString.c_str())));
stmt->setUInt64(0, strtoull(searchString.c_str(), nullptr, 10));
result = CharacterDatabase.Query(stmt);
}
// search by name
@@ -205,7 +205,7 @@ public:
// check character count
uint32 charcount = AccountMgr::GetCharactersCount(delInfo.accountId);
if (charcount >= 10)
if (charcount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
{
handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId);
return;
@@ -51,12 +51,21 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_UNDELETE_ENUM, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
"gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot "
"FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, "
"c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, "
"cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT name FROM characters WHERE guid = ? AND account = ? AND (at_login & ?) = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_RACE, "SELECT race FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_LEVEL, "SELECT level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level FROM characters WHERE guid = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH);
@@ -432,7 +441,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_CHARACTER_POSITION, "UPDATE characters SET position_x = ?, position_y = ?, position_z = ?, orientation = ?, map = ?, zone = ?, trans_x = 0, trans_y = 0, trans_z = 0, transguid = 0, taxi_path = '' WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_AURA_FROZEN, "SELECT characters.name, character_aura.remaintime FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARACTER_ONLINE, "SELECT name, account, map, zone FROM characters WHERE online > 0", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_BOTH);
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);
@@ -63,6 +63,8 @@ enum CharacterDatabaseStatements
CHAR_SEL_MAIL_LIST_ITEMS,
CHAR_SEL_ENUM,
CHAR_SEL_ENUM_DECLINED_NAME,
CHAR_SEL_UNDELETE_ENUM,
CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME,
CHAR_SEL_FREE_NAME,
CHAR_SEL_GUID_RACE_ACC_BY_NAME,
CHAR_SEL_CHAR_RACE,
@@ -136,4 +136,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK, "UPDATE battlenet_accounts SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK_CONTRY, "UPDATE battlenet_accounts SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT, "SELECT battlenet_account FROM account WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_LAST_CHAR_UNDELETE, "SELECT LastCharacterUndelete FROM battlenet_accounts WHERE Id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_LAST_CHAR_UNDELETE, "UPDATE battlenet_accounts SET LastCharacterUndelete = UNIX_TIMESTAMP() WHERE Id = ?", CONNECTION_ASYNC);
}
@@ -153,6 +153,9 @@ enum LoginDatabaseStatements
LOGIN_UPD_BNET_ACCOUNT_LOCK_CONTRY,
LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT,
LOGIN_SEL_LAST_CHAR_UNDELETE,
LOGIN_UPD_LAST_CHAR_UNDELETE,
MAX_LOGINDATABASE_STATEMENTS
};
+2 -2
View File
@@ -45,7 +45,7 @@ class QueryCallback
return _result;
}
int IsReady()
bool IsReady()
{
return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
@@ -128,7 +128,7 @@ class QueryCallback_2
return _result;
}
int IsReady()
bool IsReady()
{
return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
+5 -3
View File
@@ -30,9 +30,11 @@
template<typename T>
struct Optional
{
T value;
bool HasValue;
{
Optional() : value(), HasValue(false) { }
T value;
bool HasValue;
};
// Searcher for map of structs
+23 -2
View File
@@ -1074,11 +1074,32 @@ Account.PasswordChangeSecurity = 0
# Description: Set to date of project's birth in UNIX time. By default the date when
# TrinityCore was started (Thu Oct 2, 2008)
# Default: 1222964635
#
#
BirthdayTime = 1222964635
#
# FeatureSystem.BpayStore.Enabled
# Description: Not yet implemented
# Default: 0 - (Disabled)
# 1 - (Enabled)
FeatureSystem.BpayStore.Enabled = 0
#
# FeatureSystem.CharacterUndelete.Enabled
# Description: Controls Feature in CharacterList to restore delete Characters.
# Default: 0 - (Disabled)
# 1 - (Enabled, Experimental)
FeatureSystem.CharacterUndelete.Enabled = 0
#
# FeatureSystem.CharacterUndelete.Cooldown
# Description: Time between available character restorations. (in sec)
# Default: 2592000 (30 days)
FeatureSystem.CharacterUndelete.Cooldown = 2592000
#
###################################################################################################