character_warband_groups
This commit is contained in:
@@ -890,14 +890,23 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
//WowCommunity
|
||||
|
||||
//WARBANDS
|
||||
PrepareStatement(CHAR_SEL_WARBAND_GROUPS, "SELECT groupId, orderIndex, warbandSceneId, flags, contentSetId, name FROM character_warband_groups WHERE battlenetAccountId = ? ORDER BY orderIndex", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_WARBAND_GROUP_MEMBERS, "SELECT gm.groupId, gm.memberIndex, gm.guid, gm.warbandScenePlacementId, gm.memberType, gm.contentSetId FROM character_warband_group_members gm INNER JOIN character_warband_groups g ON gm.groupId = g.groupId WHERE g.battlenetAccountId = ? ORDER BY gm.groupId, gm.memberIndex", CONNECTION_ASYNC);
|
||||
// Group selects are CONNECTION_BOTH: the character enumeration holder runs them async, and
|
||||
// WorldSession::SaveWarbandGroupsToDB re-reads CHAR_SEL_WARBAND_GROUPS synchronously to pick up the ids the
|
||||
// rewrite just got assigned (an ASYNC-only statement has no m_mStmt on the sync connection -> assertion).
|
||||
PrepareStatement(CHAR_SEL_WARBAND_GROUPS, "SELECT groupId, orderIndex, warbandSceneId, flags, contentSetId, name FROM character_warband_groups WHERE battlenetAccountId = ? ORDER BY orderIndex", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_WARBAND_GROUP_MEMBERS, "SELECT gm.groupId, gm.memberIndex, gm.guid, gm.warbandScenePlacementId, gm.memberType, gm.contentSetId FROM character_warband_group_members gm INNER JOIN character_warband_groups g ON gm.groupId = g.groupId WHERE g.battlenetAccountId = ? ORDER BY gm.groupId, gm.memberIndex", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_INS_WARBAND_GROUP, "INSERT INTO character_warband_groups (groupId, battlenetAccountId, orderIndex, warbandSceneId, flags, contentSetId, name) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_WARBAND_GROUP, "UPDATE character_warband_groups SET orderIndex = ?, warbandSceneId = ?, flags = ?, contentSetId = ?, name = ? WHERE groupId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_WARBAND_GROUPS_BY_ACCOUNT, "DELETE FROM character_warband_groups WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
|
||||
// The warband group rewrite transaction (WorldSession::SaveWarbandGroupsToDB) is committed with
|
||||
// DirectCommitTransaction so the auto_increment ids exist for the immediate read-back, which runs it on a
|
||||
// synchronous connection: every statement in that transaction must be CONNECTION_BOTH (ASYNC-only statements
|
||||
// have no handle there -> "Could not fetch prepared statement ... connection type: synchronous").
|
||||
PrepareStatement(CHAR_DEL_WARBAND_GROUPS_BY_ACCOUNT, "DELETE FROM character_warband_groups WHERE battlenetAccountId = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_INS_WARBAND_GROUP_MEMBER, "INSERT INTO character_warband_group_members (groupId, memberIndex, guid, warbandScenePlacementId, memberType, contentSetId) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_WARBAND_GROUP_MEMBERS, "DELETE FROM character_warband_group_members WHERE groupId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_WARBAND_MEMBER_BY_GUID, "DELETE FROM character_warband_group_members WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_WARBAND_GROUP_MEMBERS_BY_ACCOUNT, "DELETE gm FROM character_warband_group_members gm INNER JOIN character_warband_groups g ON gm.groupId = g.groupId WHERE g.battlenetAccountId = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_INS_WARBAND_GROUP_AUTO, "INSERT INTO character_warband_groups (battlenetAccountId, orderIndex, warbandSceneId, flags, contentSetId, name) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
|
||||
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_BANK_TAB_SETTINGS, "SELECT tabId, name, icon, description, depositFlags FROM account_bank_tab_settings WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ACCOUNT_BANK_TAB_SETTINGS, "DELETE FROM account_bank_tab_settings WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
|
||||
|
||||
@@ -722,6 +722,12 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_INS_WARBAND_GROUP_MEMBER,
|
||||
CHAR_DEL_WARBAND_GROUP_MEMBERS,
|
||||
CHAR_DEL_WARBAND_MEMBER_BY_GUID,
|
||||
// Rewriting a warband deletes this account's member rows through a join on the groups table, so they must
|
||||
// go before the groups rows themselves
|
||||
CHAR_DEL_WARBAND_GROUP_MEMBERS_BY_ACCOUNT,
|
||||
// groupId is a global auto_increment primary key (not per account), so group inserts let the server assign
|
||||
// the id instead of writing the one the client sent - which would collide across accounts
|
||||
CHAR_INS_WARBAND_GROUP_AUTO,
|
||||
|
||||
CHAR_SEL_ACCOUNT_BANK_TAB_SETTINGS,
|
||||
CHAR_DEL_ACCOUNT_BANK_TAB_SETTINGS,
|
||||
|
||||
@@ -591,7 +591,7 @@ public:
|
||||
SetSize(MAX);
|
||||
}
|
||||
|
||||
bool Initialize(uint32 accountId, bool withDeclinedNames, bool isDeletedCharacters)
|
||||
bool Initialize(uint32 accountId, uint32 battlenetAccountId, bool withDeclinedNames, bool isDeletedCharacters)
|
||||
{
|
||||
_isDeletedCharacters = isDeletedCharacters;
|
||||
|
||||
@@ -614,6 +614,15 @@ public:
|
||||
stmt->setUInt32(0, accountId);
|
||||
result &= SetPreparedQuery(SHOP_BOOSTS, stmt);
|
||||
|
||||
// Warband groups belong to the battle.net account, not the WoW account above
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_WARBAND_GROUPS);
|
||||
stmt->setUInt32(0, battlenetAccountId);
|
||||
result &= SetPreparedQuery(WARBAND_GROUPS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_WARBAND_GROUP_MEMBERS);
|
||||
stmt->setUInt32(0, battlenetAccountId);
|
||||
result &= SetPreparedQuery(WARBAND_GROUP_MEMBERS, stmt);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -749,6 +758,12 @@ void WorldSession::HandleCharEnum(CharacterDatabaseQueryHolder const& holder)
|
||||
});
|
||||
}
|
||||
|
||||
// Warband groups are rebuilt from the account rows rather than kept in session memory, so the selection
|
||||
// screen gets the same list on every login (and on every server-pushed re-enumeration).
|
||||
if (!charEnum.IsDeletedCharacters)
|
||||
LoadWarbandGroupsFromDB(holder.GetPreparedResult(EnumCharactersQueryHolder::WARBAND_GROUPS),
|
||||
holder.GetPreparedResult(EnumCharactersQueryHolder::WARBAND_GROUP_MEMBERS));
|
||||
|
||||
if (_warbandGroups)
|
||||
charEnum.WarbandGroups = _warbandGroups->Groups;
|
||||
|
||||
@@ -769,7 +784,7 @@ void WorldSession::SendCharacterEnum()
|
||||
|
||||
/// get all the data necessary for loading all characters (along with their pets) on the account
|
||||
std::shared_ptr<EnumCharactersQueryHolder> holder = std::make_shared<EnumCharactersQueryHolder>();
|
||||
if (!holder->Initialize(GetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), false))
|
||||
if (!holder->Initialize(GetAccountId(), GetBattlenetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), false))
|
||||
{
|
||||
HandleCharEnum(*holder);
|
||||
return;
|
||||
@@ -790,7 +805,7 @@ void WorldSession::HandleCharUndeleteEnumOpcode(WorldPackets::Character::EnumCha
|
||||
{
|
||||
/// get all the data necessary for loading all undeleted characters (along with their pets) on the account
|
||||
std::shared_ptr<EnumCharactersQueryHolder> holder = std::make_shared<EnumCharactersQueryHolder>();
|
||||
if (!holder->Initialize(GetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), true))
|
||||
if (!holder->Initialize(GetAccountId(), GetBattlenetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), true))
|
||||
{
|
||||
HandleCharEnum(*holder);
|
||||
return;
|
||||
@@ -3426,6 +3441,137 @@ void WorldSession::HandleSetupWarbandGroups(WorldPackets::Character::SetupWarban
|
||||
_warbandGroups = std::make_unique<WorldPackets::Character::AccountWarbandGroups>();
|
||||
|
||||
_warbandGroups->Groups = std::move(setupWarbandGroups.Groups);
|
||||
|
||||
// Persist: without this the list only lived for the session, so the next character enumeration came back
|
||||
// empty and the client had to push the whole thing again.
|
||||
SaveWarbandGroupsToDB();
|
||||
}
|
||||
|
||||
void WorldSession::LoadWarbandGroupsFromDB(PreparedQueryResult groupsResult, PreparedQueryResult membersResult)
|
||||
{
|
||||
if (!groupsResult)
|
||||
return; // no stored groups: keep whatever this session already holds
|
||||
|
||||
// Members first - they are keyed by group id, which only the group rows below carry
|
||||
std::unordered_map<uint64, std::vector<WorldPackets::Character::WarbandGroupMember>> membersByGroup;
|
||||
if (membersResult)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = membersResult->Fetch(); // groupId, memberIndex, guid, warbandScenePlacementId, memberType, contentSetId
|
||||
|
||||
WorldPackets::Character::WarbandGroupMember& member = membersByGroup[fields[0].GetUInt64()].emplace_back();
|
||||
member.Guid = ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt64());
|
||||
member.WarbandScenePlacementID = fields[3].GetUInt32();
|
||||
member.Type = fields[4].GetInt32();
|
||||
member.ContentSetID = fields[5].GetInt32();
|
||||
} while (membersResult->NextRow());
|
||||
}
|
||||
|
||||
auto groups = std::make_unique<WorldPackets::Character::AccountWarbandGroups>();
|
||||
do
|
||||
{
|
||||
Field* fields = groupsResult->Fetch(); // groupId, orderIndex, warbandSceneId, flags, contentSetId, name
|
||||
|
||||
WorldPackets::Character::WarbandGroup& group = groups->Groups.emplace_back();
|
||||
group.GroupID = fields[0].GetUInt64();
|
||||
group.OrderIndex = fields[1].GetUInt8();
|
||||
group.WarbandSceneID = fields[2].GetUInt32();
|
||||
group.Flags = fields[3].GetUInt32();
|
||||
group.ContentSetID = fields[4].GetInt32();
|
||||
group.Name = fields[5].GetString();
|
||||
|
||||
if (auto itr = membersByGroup.find(group.GroupID); itr != membersByGroup.end())
|
||||
group.Members = std::move(itr->second);
|
||||
} while (groupsResult->NextRow());
|
||||
|
||||
_warbandGroups = std::move(groups);
|
||||
}
|
||||
|
||||
void WorldSession::SaveWarbandGroupsToDB()
|
||||
{
|
||||
if (!_warbandGroups)
|
||||
return;
|
||||
|
||||
uint32 const bnetAccountId = GetBattlenetAccountId();
|
||||
|
||||
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
|
||||
// Members first: they identify "this account's" rows through a join on the groups table, which goes next.
|
||||
// Groups are rewritten as a whole - the client owns the full list and sends it in one packet.
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_WARBAND_GROUP_MEMBERS_BY_ACCOUNT);
|
||||
stmt->setUInt32(0, bnetAccountId);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_WARBAND_GROUPS_BY_ACCOUNT);
|
||||
stmt->setUInt32(0, bnetAccountId);
|
||||
trans->Append(stmt);
|
||||
|
||||
for (auto const& group : _warbandGroups->Groups)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_WARBAND_GROUP_AUTO);
|
||||
stmt->setUInt32(0, bnetAccountId);
|
||||
stmt->setUInt8(1, group.OrderIndex);
|
||||
stmt->setUInt32(2, group.WarbandSceneID);
|
||||
stmt->setUInt32(3, group.Flags);
|
||||
stmt->setInt32(4, group.ContentSetID);
|
||||
stmt->setString(5, group.Name);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
// Committed directly (synchronously): the read-back below needs the auto_increment ids these inserts just
|
||||
// got, and CommitTransaction only enqueues the work on the async pool, so the SELECT could run first.
|
||||
CharacterDatabase.DirectCommitTransaction(trans);
|
||||
|
||||
if (_warbandGroups->Groups.empty())
|
||||
return;
|
||||
|
||||
// groupId is a global auto_increment primary key shared by every account, so the ids the client sent are not
|
||||
// written back: read the rows just inserted (they are this account's only ones now) and adopt the assigned
|
||||
// ids in insertion order, which is what the next enumeration echoes to the client.
|
||||
CharacterDatabasePreparedStatement* selStmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_WARBAND_GROUPS);
|
||||
selStmt->setUInt32(0, bnetAccountId);
|
||||
PreparedQueryResult groupRows = CharacterDatabase.Query(selStmt);
|
||||
if (!groupRows)
|
||||
{
|
||||
TC_LOG_ERROR("network", "WorldSession::SaveWarbandGroupsToDB: account {} wrote {} warband group(s) but read back none.", bnetAccountId, _warbandGroups->Groups.size());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint64> assignedIds;
|
||||
do
|
||||
assignedIds.push_back(groupRows->Fetch()[0].GetUInt64());
|
||||
while (groupRows->NextRow());
|
||||
|
||||
std::sort(assignedIds.begin(), assignedIds.end()); // auto_increment ids ascend in insert order
|
||||
|
||||
if (assignedIds.size() != _warbandGroups->Groups.size())
|
||||
{
|
||||
TC_LOG_ERROR("network", "WorldSession::SaveWarbandGroupsToDB: account {} expected {} warband group(s), read back {}.", bnetAccountId, _warbandGroups->Groups.size(), assignedIds.size());
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterDatabaseTransaction memberTrans = CharacterDatabase.BeginTransaction();
|
||||
for (std::size_t i = 0; i < assignedIds.size(); ++i)
|
||||
{
|
||||
WorldPackets::Character::WarbandGroup& group = _warbandGroups->Groups[i];
|
||||
group.GroupID = assignedIds[i];
|
||||
|
||||
uint8 memberIndex = 0;
|
||||
for (auto const& member : group.Members)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_WARBAND_GROUP_MEMBER);
|
||||
stmt->setUInt64(0, group.GroupID);
|
||||
stmt->setUInt8(1, memberIndex++);
|
||||
stmt->setUInt64(2, member.Guid.GetCounter());
|
||||
stmt->setUInt32(3, member.WarbandScenePlacementID);
|
||||
stmt->setInt32(4, member.Type);
|
||||
stmt->setInt32(5, member.ContentSetID);
|
||||
memberTrans->Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
CharacterDatabase.CommitTransaction(memberTrans);
|
||||
}
|
||||
|
||||
void WorldSession::HandleGetAccountCharListOpcode(WorldPackets::Character::GetAccountCharacterList& accountCharList)
|
||||
@@ -3440,7 +3586,7 @@ void WorldSession::HandleGetAccountCharListOpcode(WorldPackets::Character::GetAc
|
||||
};
|
||||
|
||||
std::shared_ptr<EnumCharactersQueryHolder> holder = std::make_shared<EnumCharactersQueryHolder>();
|
||||
if (!holder->Initialize(GetAccountId(), false, false))
|
||||
if (!holder->Initialize(GetAccountId(), GetBattlenetAccountId(), false, false))
|
||||
{
|
||||
sendEmpty();
|
||||
return;
|
||||
|
||||
@@ -116,7 +116,7 @@ void HousingMgr::Initialize()
|
||||
"falling back to base room entry {}", _baseRoomEntryId);
|
||||
}
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded housing data: {} decor, {} levels, "
|
||||
TC_LOG_DEBUG("server.loading", ">> Loaded housing data: {} decor, {} levels, "
|
||||
"{} rooms, {} themes, {} decor materials, {} exterior wmos, {} level rewards, "
|
||||
"{} initiatives, {} neighborhood maps, {} neighborhood plots, "
|
||||
"{} decor categories, {} decor subcategories, {} decor dye slots, "
|
||||
@@ -552,7 +552,7 @@ int32 HousingMgr::ResolvePlotIndex(WorldObject const* searcher, ObjectGuid corne
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Housing/Neighborhood GUIDs have no GO entry — callers sometimes pass them for diagnostics; return -1.
|
||||
// Housing/Neighborhood GUIDs have no GO entry ? callers sometimes pass them for diagnostics; return -1.
|
||||
if (cornerstoneGuid.GetHigh() != HighGuid::GameObject)
|
||||
{
|
||||
return -1;
|
||||
@@ -706,7 +706,7 @@ bool HousingMgr::CanVisitorAccessPlot(Player const* visitor, ObjectGuid ownerGui
|
||||
|
||||
if (settingsFlags & partyFlag)
|
||||
{
|
||||
// Party requires both online — same Group instance.
|
||||
// Party requires both online ? same Group instance.
|
||||
if (ownerPlayer && visitor->GetGroup() && visitor->GetGroup() == ownerPlayer->GetGroup())
|
||||
return true;
|
||||
}
|
||||
@@ -722,7 +722,7 @@ bool HousingMgr::CanVisitorAccessPlot(Player const* visitor, ObjectGuid ownerGui
|
||||
|
||||
if (settingsFlags & friendsFlag)
|
||||
{
|
||||
// Friends are mutual on retail — visitor's social manager has the same record.
|
||||
// Friends are mutual on retail ? visitor's social manager has the same record.
|
||||
if (visitor->GetSocial() && visitor->GetSocial()->HasFriend(ownerGuid))
|
||||
return true;
|
||||
}
|
||||
@@ -1066,7 +1066,7 @@ void HousingMgr::BuildRoomComponentTextureIndex()
|
||||
_textureByOptionId.clear();
|
||||
_textureByComponentType.clear();
|
||||
|
||||
// Build option→texture link from RoomComponentOptionTexture join table
|
||||
// Build option?texture link from RoomComponentOptionTexture join table
|
||||
for (RoomComponentOptionTextureEntry const* link : sRoomComponentOptionTextureStore)
|
||||
{
|
||||
if (!link)
|
||||
@@ -1074,7 +1074,7 @@ void HousingMgr::BuildRoomComponentTextureIndex()
|
||||
_textureByOptionId[link->RoomComponentOptionID] = link->RoomComponentTextureID;
|
||||
}
|
||||
|
||||
// Build type→texture fallback from RoomComponentTexture (Type = component type: 1=wall, 2=floor, 3=ceiling)
|
||||
// Build type?texture fallback from RoomComponentTexture (Type = component type: 1=wall, 2=floor, 3=ceiling)
|
||||
for (RoomComponentTextureEntry const* tex : sRoomComponentTextureStore)
|
||||
{
|
||||
if (!tex || tex->Type <= 0)
|
||||
@@ -1126,7 +1126,7 @@ void HousingMgr::EnsureDoorGameObjectTemplates()
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a GOOBER template (type=10) — clickable interaction object for house entry
|
||||
// Create a GOOBER template (type=10) ? clickable interaction object for house entry
|
||||
std::string name = entry->Name[DEFAULT_LOCALE] ? entry->Name[DEFAULT_LOCALE] : "Housing Door";
|
||||
|
||||
// Insert directly into ObjectMgr's in-memory store (derived from DB2, no DB write).
|
||||
@@ -1164,9 +1164,9 @@ void HousingMgr::EnsureDoorGameObjectTemplates()
|
||||
}
|
||||
|
||||
if (created)
|
||||
TC_LOG_INFO("server.loading", ">> Auto-created {} missing door GO templates from ExteriorComponent DB2", created);
|
||||
TC_LOG_DEBUG("server.loading", ">> Auto-created {} missing door GO templates from ExteriorComponent DB2", created);
|
||||
if (scripted)
|
||||
TC_LOG_INFO("server.loading", ">> Bound go_housing_door to {} door GO templates", scripted);
|
||||
TC_LOG_DEBUG("server.loading", ">> Bound go_housing_door to {} door GO templates", scripted);
|
||||
}
|
||||
|
||||
void HousingMgr::BuildExteriorComponentIndexes()
|
||||
@@ -1271,7 +1271,7 @@ uint32 HousingMgr::GetDefaultFixtureForType(uint8 componentType, uint32 wmoDataI
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// Fallback: scan all sizes for this (type, wmo) — useful when caller doesn't know the size.
|
||||
// Fallback: scan all sizes for this (type, wmo) ? useful when caller doesn't know the size.
|
||||
for (uint8 sz = 1; sz <= 4; ++sz)
|
||||
{
|
||||
if (sz == houseSize)
|
||||
@@ -1419,7 +1419,7 @@ int32 HousingMgr::GetFactionDefaultThemeID(int32 factionRestriction) const
|
||||
|
||||
int32 HousingMgr::GetDefaultSubThemeID(int32 baseThemeID) const
|
||||
{
|
||||
// The base theme's "(neutral)" child in HouseTheme.db2 — always the lowest child ID; a childless theme stands for itself.
|
||||
// The base theme's "(neutral)" child in HouseTheme.db2 ? always the lowest child ID; a childless theme stands for itself.
|
||||
int32 defaultSubTheme = 0;
|
||||
for (auto const& [id, theme] : _houseThemeStore)
|
||||
if (theme.ParentThemeID == baseThemeID && (!defaultSubTheme || int32(id) < defaultSubTheme))
|
||||
|
||||
@@ -415,7 +415,7 @@ void Map::LoadGridsInRange(float x, float y, float radius)
|
||||
EnsureGridLoaded(GridCoord(gx, gy));
|
||||
}
|
||||
|
||||
TransferAbortParams Map::CannotEnter(Player* player)
|
||||
TransferAbortParams Map::CannotEnter(Player* /*player*/)
|
||||
{
|
||||
return { TRANSFER_ABORT_NONE };
|
||||
}
|
||||
|
||||
@@ -1706,6 +1706,9 @@ public:
|
||||
void HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& playerLogin);
|
||||
//WowCommunity
|
||||
void HandleSetupWarbandGroups(WorldPackets::Character::SetupWarbandGroups& setupWarbandGroups);
|
||||
// character_warband_groups / _members persistence for the setup handler above (CharacterHandler.cpp)
|
||||
void LoadWarbandGroupsFromDB(PreparedQueryResult groupsResult, PreparedQueryResult membersResult);
|
||||
void SaveWarbandGroupsToDB();
|
||||
void HandleGetAccountCharListOpcode(WorldPackets::Character::GetAccountCharacterList& accountCharList);
|
||||
void HandleGetRegionwideCharacterRestrictionAndMailData(WorldPackets::Character::GetRegionwideCharacterRestrictionAndMailData& packet);
|
||||
void HandleGetRafAccountInfo(WorldPackets::RaF::GetRafAccountInfo& packet);
|
||||
|
||||
Reference in New Issue
Block a user