Core/NetworkIO: implemented undelete opcodes and moved char create/delete packets to new packet classes
This commit is contained in:
@@ -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 */;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `battlenet_accounts` ADD COLUMN `LastCharacterUndelete` INT(10) UNSIGNED DEFAULT 0 NOT NULL AFTER `os`;
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
#include "Opcodes.h"
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
struct z_stream_s;
|
||||
|
||||
class WorldPacket : public ByteBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
Reference in New Issue
Block a user