gexo housing

This commit is contained in:
luis
2026-09-29 00:28:57 -03:00
parent e09a88d2c7
commit cf5f2b9e78
13 changed files with 1321 additions and 35 deletions
@@ -0,0 +1,10 @@
-- Persist native neighborhood invitations by target character.
CREATE TABLE IF NOT EXISTS `character_housing_neighborhood_invite` (
`NeighborhoodGuid` VARCHAR(64) NOT NULL,
`InviteeGuid` BIGINT UNSIGNED NOT NULL,
`InviterGuid` BIGINT UNSIGNED NOT NULL,
`CreatedAt` BIGINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`NeighborhoodGuid`, `InviteeGuid`),
KEY `idx_invitee` (`InviteeGuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
@@ -0,0 +1,11 @@
-- Persist native neighborhood secondary-owner roles independently from house ownership.
CREATE TABLE IF NOT EXISTS `character_housing_neighborhood_role` (
`NeighborhoodGuid` VARCHAR(64) NOT NULL,
`CharacterGuid` BIGINT UNSIGNED NOT NULL,
`Role` TINYINT UNSIGNED NOT NULL DEFAULT 1,
`GrantedBy` BIGINT UNSIGNED NOT NULL,
`GrantedAt` BIGINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`NeighborhoodGuid`, `CharacterGuid`),
KEY `idx_character` (`CharacterGuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
@@ -0,0 +1,7 @@
-- Persist the native public/private state used by House Finder.
ALTER TABLE `housing_neighborhood`
ADD COLUMN `IsPublic` TINYINT UNSIGNED NOT NULL DEFAULT 0 AFTER `Name`;
-- Preserve the pre-migration behavior for neighborhoods already exposed by House Finder.
UPDATE `housing_neighborhood` SET `IsPublic` = 1;
@@ -0,0 +1,5 @@
-- Persist the native guild ownership used by Housing Services and House Finder.
ALTER TABLE `housing_neighborhood`
ADD COLUMN `GuildId` INT UNSIGNED NULL DEFAULT NULL AFTER `IsPublic`,
ADD UNIQUE KEY `uk_housing_neighborhood_guild` (`GuildId`);
+3
View File
@@ -16,6 +16,7 @@
*/
#include "Guild.h"
#include "HousingSessionLifecycle.h"
#include "AccountMgr.h"
#include "AchievementMgr.h"
#include "Bag.h"
@@ -1200,6 +1201,7 @@ void Guild::Disband()
{
// Call scripts before guild data removed from database
sScriptMgr->OnGuildDisband(this);
Housing::HandleGuildDisband(GetId(), GetLeaderGUID());
WorldPackets::Guild::GuildEventDisbanded guildEventDisbanded;
guildEventDisbanded.Write();
@@ -2988,6 +2990,7 @@ bool Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bo
}
// Call script on remove before member is actually removed from guild (and database)
sScriptMgr->OnGuildRemoveMember(this, guid, isDisbanding, isKicked);
Housing::HandleGuildMemberRemoved(GetId(), guid);
m_members.erase(guid);
@@ -97,6 +97,61 @@ void WorldSession::HandleHousingHouseFinderIgnoreNeighborhood(WorldPackets::Hous
Housing::HandleHouseFinderIgnoreNeighborhood(this, packet);
}
void WorldSession::HandleInvitePlayerToNeighborhood(WorldPackets::Housing::InvitePlayerToNeighborhood& packet)
{
Housing::HandleInvitePlayerToNeighborhood(this, packet);
}
void WorldSession::HandleHousingDeleteAllNeighborhoodInvites(WorldPackets::Housing::HousingDeleteAllNeighborhoodInvites& packet)
{
Housing::HandleDeleteAllNeighborhoodInvites(this, packet);
}
void WorldSession::HandleNeighborhoodCancelInvitation(WorldPackets::Housing::NeighborhoodCancelInvitation& packet)
{
Housing::HandleNeighborhoodCancelInvitation(this, packet);
}
void WorldSession::HandleHousingSvcsGuildCreateNeighborhood(WorldPackets::Housing::HousingSvcsGuildCreateNeighborhood& packet)
{
Housing::HandleHousingSvcsGuildCreateNeighborhood(this, packet);
}
void WorldSession::HandleNeighborhoodSetPublicFlag(WorldPackets::Housing::NeighborhoodSetPublicFlag& packet)
{
Housing::HandleNeighborhoodSetPublicFlag(this, packet);
}
void WorldSession::HandleNeighborhoodAddSecondaryOwner(WorldPackets::Housing::NeighborhoodAddSecondaryOwner& packet)
{
Housing::HandleNeighborhoodAddSecondaryOwner(this, packet);
}
void WorldSession::HandleNeighborhoodRemoveSecondaryOwner(WorldPackets::Housing::NeighborhoodRemoveSecondaryOwner& packet)
{
Housing::HandleNeighborhoodRemoveSecondaryOwner(this, packet);
}
void WorldSession::HandleNeighborhoodGetRoster(WorldPackets::Housing::NeighborhoodGetRoster& packet)
{
Housing::HandleNeighborhoodGetRoster(this, packet);
}
void WorldSession::HandleNeighborhoodGetInvites(WorldPackets::Housing::NeighborhoodGetInvites& packet)
{
Housing::HandleNeighborhoodGetInvites(this, packet);
}
void WorldSession::HandleNeighborhoodPlayerGetInvite(WorldPackets::Housing::NeighborhoodPlayerGetInvite& packet)
{
Housing::HandleNeighborhoodPlayerGetInvite(this, packet);
}
void WorldSession::HandleNeighborhoodPlayerDeclineInvite(WorldPackets::Housing::NeighborhoodPlayerDeclineInvite& packet)
{
Housing::HandleNeighborhoodPlayerDeclineInvite(this, packet);
}
void WorldSession::HandleHousingGetPlayerHousesInfo(WorldPackets::Housing::GetPlayerHousesInfo& packet)
{
Housing::HandleGetPlayerHousesInfo(this, packet);
+8
View File
@@ -434,6 +434,14 @@ namespace Housing
owner, houseGuid.ToString(), neighborhoodGuid.ToString(), uint32(oldPlotId), uint32(plotId),
plot.ExteriorMapId, purchaseCost, uint32(isMove ? PlotTransactionType::Move : PlotTransactionType::Purchase));
trans->PAppend("DELETE FROM housing_plot_reservation WHERE OwnerGuid = {}", owner);
if (!isMove)
{
// Invitation consumption is part of the same durability boundary as ownership.
// A failed purchase leaves the invitation available for a safe retry.
trans->PAppend(
"DELETE FROM character_housing_neighborhood_invite WHERE NeighborhoodGuid = '{}' AND InviteeGuid = {}",
neighborhoodGuid.ToString(), owner);
}
if (purchaseCost)
player->SaveInventoryAndGoldToDB(trans);
CharacterDatabase.DirectCommitTransaction(trans);
@@ -5,6 +5,8 @@
#include "HousingSessionLifecycle.h"
#include "DatabaseEnv.h"
#include "GameTime.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "HousingDynamicEntity.h"
#include "HousingMgr.h"
#include "HousingMapContext.h"
@@ -13,6 +15,8 @@
#include "HousingRoomSession.h"
#include "Log.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldSession.h"
#include <algorithm>
@@ -30,6 +34,99 @@ namespace Housing
return static_cast<uint8>(result);
}
bool CanManageNeighborhood(Player const* player, ObjectGuid const& neighborhoodGuid, bool allowSecondaryOwner)
{
if (!player || !IsNeighborhoodGuid(neighborhoodGuid))
return false;
QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT OwnerGuid, GuildId FROM housing_neighborhood WHERE NeighborhoodGuid = '{}' LIMIT 1",
neighborhoodGuid.ToString());
if (!neighborhood)
return false;
Field* fields = neighborhood->Fetch();
uint32 const guildId = fields[1].GetUInt32();
if (guildId == 0 && fields[0].GetUInt64() == player->GetGUID().GetCounter())
return true;
if (guildId != 0 && guildId == player->GetGuildId())
if (Guild* guild = sGuildMgr->GetGuildById(guildId);
guild && guild->GetLeaderGUID() == player->GetGUID())
return true;
return allowSecondaryOwner && CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_role WHERE NeighborhoodGuid = '{}' "
"AND CharacterGuid = {} AND Role = 1 LIMIT 1",
neighborhoodGuid.ToString(), player->GetGUID().GetCounter());
}
ObjectGuid ResolvePrimaryManagedNeighborhood(Player const* player)
{
if (!player)
return ObjectGuid::Empty;
HouseState house;
if (sHousingMgr.LoadOwnedHouse(player, ObjectGuid::Empty, house) == Result::Success &&
CanManageNeighborhood(player, house.NeighborhoodGuid, false))
return house.NeighborhoodGuid;
if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId());
guild && guild->GetLeaderGUID() == player->GetGUID())
{
if (QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT NeighborhoodGuid FROM housing_neighborhood WHERE GuildId = {} LIMIT 1", guild->GetId()))
{
ObjectGuid const guid = ObjectGuid::FromString(neighborhood->Fetch()[0].GetString());
if (IsNeighborhoodGuid(guid))
return guid;
}
}
if (QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT NeighborhoodGuid FROM housing_neighborhood WHERE OwnerGuid = {} "
"ORDER BY NeighborhoodGuid LIMIT 1", player->GetGUID().GetCounter()))
{
ObjectGuid const guid = ObjectGuid::FromString(neighborhood->Fetch()[0].GetString());
if (IsNeighborhoodGuid(guid))
return guid;
}
return ObjectGuid::Empty;
}
WorldPackets::Housing::HouseInfo ToPacketHouse(HouseState const& state);
void BroadcastGuildHouseUpdate(HouseState const& state, bool added)
{
QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT GuildId FROM housing_neighborhood WHERE NeighborhoodGuid = '{}' LIMIT 1",
state.NeighborhoodGuid.ToString());
if (!neighborhood)
return;
uint32 const guildId = neighborhood->Fetch()[0].GetUInt32();
Guild* guild = guildId ? sGuildMgr->GetGuildById(guildId) : nullptr;
if (!guild)
return;
if (added)
{
WorldPackets::Housing::HousingSvcsGuildAddHouseNotification notification;
notification.House = ToPacketHouse(state);
guild->BroadcastPacket(notification.Write());
}
else
{
WorldPackets::Housing::HousingSvcsGuildRemoveHouseNotification notification;
notification.House = ToPacketHouse(state);
guild->BroadcastPacket(notification.Write());
}
WorldPackets::Housing::HousingHouseFinderForceRefresh refresh;
guild->BroadcastPacket(refresh.Write());
}
WorldPackets::Housing::HouseInfo ToPacketHouse(HouseState const& state)
{
WorldPackets::Housing::HouseInfo house;
@@ -57,7 +154,7 @@ namespace Housing
return false;
QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT OwnerGuid, Name FROM housing_neighborhood WHERE NeighborhoodGuid = '{}' LIMIT 1",
"SELECT OwnerGuid, Name, IsPublic, GuildId FROM housing_neighborhood WHERE NeighborhoodGuid = '{}' LIMIT 1",
neighborhoodGuid.ToString());
if (!neighborhood)
return false;
@@ -71,7 +168,10 @@ namespace Housing
output.OwnerGUID = neighborhoodOwner;
output.Name = neighborhoodFields[1].GetString();
bool authorized = neighborhoodOwner == viewer->GetGUID();
uint32 const guildId = neighborhoodFields[3].GetUInt32();
bool authorized = neighborhoodFields[2].GetUInt8() != 0 ||
(guildId == 0 && neighborhoodOwner == viewer->GetGUID()) ||
(guildId != 0 && guildId == viewer->GetGuildId());
QueryResult houses = CharacterDatabase.PQuery(
"SELECT OwnerGuid, HouseGuid, PlotID, HouseSettingFlags FROM character_housing "
"WHERE NeighborhoodGuid = '{}' ORDER BY PlotID, HouseGuid LIMIT 64",
@@ -265,6 +365,75 @@ namespace Housing
}
}
void HandleGuildDisband(uint32 guildId, ObjectGuid const& fallbackOwnerGuid)
{
if (guildId == 0 || !fallbackOwnerGuid.IsPlayer())
return;
QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT NeighborhoodGuid FROM housing_neighborhood WHERE GuildId = {} LIMIT 1", guildId);
if (!neighborhood)
return;
std::string const neighborhoodGuid = neighborhood->Fetch()[0].GetString();
CharacterDatabase.DirectPExecute(
"DELETE FROM character_housing_neighborhood_role WHERE NeighborhoodGuid = '{}'",
neighborhoodGuid);
CharacterDatabase.DirectPExecute(
"DELETE FROM character_housing_neighborhood_invite WHERE NeighborhoodGuid = '{}'",
neighborhoodGuid);
CharacterDatabase.DirectPExecute(
"UPDATE housing_neighborhood SET GuildId = NULL, OwnerGuid = {}, IsPublic = 0 "
"WHERE NeighborhoodGuid = '{}' AND GuildId = {}",
fallbackOwnerGuid.GetCounter(), neighborhoodGuid, guildId);
WorldPackets::Housing::HousingHouseFinderForceRefresh refresh;
WorldPacket const* refreshPacket = refresh.Write();
QueryResult residents = CharacterDatabase.PQuery(
"SELECT DISTINCT OwnerGuid FROM character_housing WHERE NeighborhoodGuid = '{}'",
neighborhoodGuid);
if (residents)
{
do
{
ObjectGuid const residentGuid = ObjectGuid::Create<HighGuid::Player>(
residents->Fetch()[0].GetUInt64());
if (Player* resident = ObjectAccessor::FindConnectedPlayer(residentGuid))
resident->SendDirectMessage(refreshPacket);
} while (residents->NextRow());
}
if (Player* fallbackOwner = ObjectAccessor::FindConnectedPlayer(fallbackOwnerGuid))
fallbackOwner->SendDirectMessage(refreshPacket);
}
void HandleGuildMemberRemoved(uint32 guildId, ObjectGuid const& memberGuid)
{
if (guildId == 0 || !memberGuid.IsPlayer())
return;
QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT NeighborhoodGuid FROM housing_neighborhood WHERE GuildId = {} LIMIT 1", guildId);
if (!neighborhood)
return;
std::string const neighborhoodGuid = neighborhood->Fetch()[0].GetString();
CharacterDatabase.DirectPExecute(
"DELETE FROM character_housing_neighborhood_role "
"WHERE NeighborhoodGuid = '{}' AND CharacterGuid = {}",
neighborhoodGuid, memberGuid.GetCounter());
CharacterDatabase.DirectPExecute(
"DELETE FROM character_housing_neighborhood_invite "
"WHERE NeighborhoodGuid = '{}' AND (InviteeGuid = {} OR InviterGuid = {})",
neighborhoodGuid, memberGuid.GetCounter(), memberGuid.GetCounter());
if (Player* player = ObjectAccessor::FindConnectedPlayer(memberGuid))
{
WorldPackets::Housing::HousingHouseFinderForceRefresh refresh;
player->SendDirectMessage(refresh.Write());
}
}
void HandleGetCurrentHouseInfo(WorldSession* session, WorldPackets::Housing::GetCurrentHouseInfo& /*packet*/)
{
if (!session)
@@ -368,10 +537,7 @@ namespace Housing
return;
}
QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT OwnerGuid FROM housing_neighborhood WHERE NeighborhoodGuid = '{}' LIMIT 1",
packet.NeighborhoodGUID.ToString());
if (!neighborhood || neighborhood->Fetch()[0].GetUInt64() != player->GetGUID().GetCounter())
if (!CanManageNeighborhood(player, packet.NeighborhoodGUID, true))
{
session->SendPacket(response.Write());
return;
@@ -399,6 +565,527 @@ namespace Housing
session->SendPacket(response.Write());
}
void HandleInvitePlayerToNeighborhood(WorldSession* session,
WorldPackets::Housing::InvitePlayerToNeighborhood& packet)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodInviteNameLookupResult lookup;
WorldPackets::Housing::NeighborhoodInviteResidentResponse response;
Player* player = session->GetPlayer();
if (!player || packet.PlayerName.empty() || packet.PlayerName.size() > 63)
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
HouseState house;
if (sHousingMgr.LoadOwnedHouse(player, ObjectGuid::Empty, house) != Result::Success)
{
response.Result = ToPacketResult(Result::HouseNotFound);
session->SendPacket(response.Write());
return;
}
if (!CanManageNeighborhood(player, house.NeighborhoodGuid, true))
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
std::string escapedName = packet.PlayerName;
CharacterDatabase.EscapeString(escapedName);
QueryResult target = CharacterDatabase.PQuery(
"SELECT guid FROM characters WHERE name = '{}' LIMIT 1", escapedName);
if (!target)
{
lookup.Result = ToPacketResult(Result::HouseNotFound);
session->SendPacket(lookup.Write());
response.Result = lookup.Result;
session->SendPacket(response.Write());
return;
}
ObjectGuid const inviteeGuid = ObjectGuid::Create<HighGuid::Player>(target->Fetch()[0].GetUInt64());
lookup.PlayerGUID = inviteeGuid;
lookup.Result = ToPacketResult(Result::Success);
session->SendPacket(lookup.Write());
response.InviteeGUID = inviteeGuid;
if (inviteeGuid == player->GetGUID())
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
CharacterDatabase.DirectPExecute(
"INSERT INTO character_housing_neighborhood_invite "
"(NeighborhoodGuid, InviteeGuid, InviterGuid, CreatedAt) VALUES ('{}', {}, {}, {}) "
"ON DUPLICATE KEY UPDATE InviterGuid = VALUES(InviterGuid), CreatedAt = VALUES(CreatedAt)",
house.NeighborhoodGuid.ToString(), inviteeGuid.GetCounter(), player->GetGUID().GetCounter(),
uint64(GameTime::GetGameTime()));
response.Result = CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_invite WHERE NeighborhoodGuid = '{}' "
"AND InviteeGuid = {} LIMIT 1", house.NeighborhoodGuid.ToString(), inviteeGuid.GetCounter())
? ToPacketResult(Result::Success) : ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
if (response.Result == ToPacketResult(Result::Success))
{
if (Player* invitee = ObjectAccessor::FindConnectedPlayer(inviteeGuid))
{
WorldPackets::Housing::NeighborhoodInviteNotification notification;
notification.NeighborhoodGUID = house.NeighborhoodGuid;
invitee->SendDirectMessage(notification.Write());
}
}
}
void HandleHousingSvcsGuildCreateNeighborhood(WorldSession* session,
WorldPackets::Housing::HousingSvcsGuildCreateNeighborhood& packet)
{
Player* player = session ? session->GetPlayer() : nullptr;
if (!player)
return;
WorldPackets::Housing::HousingSvcsCreateCharterNeighborhoodResponse response;
response.Result = ToPacketResult(Result::PermissionDenied);
Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId());
if (!guild || guild->GetLeaderGUID() != player->GetGUID() ||
!ObjectMgr::IsValidCharterName(packet.NeighborhoodName))
{
session->SendPacket(response.Write());
return;
}
uint32 const guildId = guild->GetId();
if (CharacterDatabase.PQuery("SELECT 1 FROM housing_neighborhood WHERE GuildId = {} LIMIT 1", guildId))
{
session->SendPacket(response.Write());
return;
}
ObjectGuid const neighborhoodGuid = ObjectGuid::Create<HighGuid::Housing>(
4, packet.NeighborhoodTypeID, guildId, guildId);
if (!IsNeighborhoodGuid(neighborhoodGuid))
{
session->SendPacket(response.Write());
return;
}
std::string escapedName = packet.NeighborhoodName;
CharacterDatabase.EscapeString(escapedName);
CharacterDatabase.DirectPExecute(
"INSERT IGNORE INTO housing_neighborhood "
"(NeighborhoodGuid, OwnerGuid, Name, Type, Flags, IsPublic, GuildId) "
"VALUES ('{}', {}, '{}', {}, {}, 0, {})",
neighborhoodGuid.ToString(), player->GetGUID().GetCounter(), escapedName,
packet.NeighborhoodTypeID, packet.SecondaryID, guildId);
QueryResult persisted = CharacterDatabase.PQuery(
"SELECT NeighborhoodGuid FROM housing_neighborhood WHERE GuildId = {} LIMIT 1", guildId);
if (!persisted || ObjectGuid::FromString(persisted->Fetch()[0].GetString()) != neighborhoodGuid)
{
session->SendPacket(response.Write());
return;
}
response.Result = ToPacketResult(Result::Success);
response.Neighborhood.NeighborhoodGUID = neighborhoodGuid;
response.Neighborhood.OwnerGUID = player->GetGUID();
response.Neighborhood.Name = packet.NeighborhoodName;
session->SendPacket(response.Write());
WorldPackets::Housing::HousingSvcsGuildCreateNeighborhoodNotification notification;
notification.NeighborhoodGUID = neighborhoodGuid;
notification.Name = packet.NeighborhoodName;
guild->BroadcastPacket(notification.Write());
WorldPackets::Housing::HousingHouseFinderForceRefresh refresh;
guild->BroadcastPacket(refresh.Write());
}
void HandleNeighborhoodSetPublicFlag(WorldSession* session,
WorldPackets::Housing::NeighborhoodSetPublicFlag& packet)
{
if (!session)
return;
Player* player = session->GetPlayer();
if (!player || !IsNeighborhoodGuid(packet.NeighborhoodGUID))
return;
if (!CanManageNeighborhood(player, packet.NeighborhoodGUID, false))
return;
CharacterDatabase.DirectPExecute(
"UPDATE housing_neighborhood SET IsPublic = {} WHERE NeighborhoodGuid = '{}'",
packet.IsPublic ? 1 : 0, packet.NeighborhoodGUID.ToString());
QueryResult persisted = CharacterDatabase.PQuery(
"SELECT IsPublic FROM housing_neighborhood WHERE NeighborhoodGuid = '{}' LIMIT 1",
packet.NeighborhoodGUID.ToString());
if (!persisted || (persisted->Fetch()[0].GetUInt8() != 0) != packet.IsPublic)
return;
WorldPackets::Housing::HousingHouseFinderForceRefresh refresh;
session->SendPacket(refresh.Write());
}
void HandleNeighborhoodAddSecondaryOwner(WorldSession* session,
WorldPackets::Housing::NeighborhoodAddSecondaryOwner& packet)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodSecondaryOwnerResponse response(
SMSG_NEIGHBORHOOD_ADD_SECONDARY_OWNER_RESPONSE);
response.PlayerGUID = packet.PlayerGUID;
Player* player = session->GetPlayer();
if (!player || !packet.PlayerGUID.IsPlayer() || packet.PlayerGUID == player->GetGUID())
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
ObjectGuid const neighborhoodGuid = ResolvePrimaryManagedNeighborhood(player);
if (!IsNeighborhoodGuid(neighborhoodGuid))
{
response.Result = ToPacketResult(Result::HouseNotFound);
session->SendPacket(response.Write());
return;
}
if (!CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing WHERE NeighborhoodGuid = '{}' AND OwnerGuid = {} LIMIT 1",
neighborhoodGuid.ToString(), packet.PlayerGUID.GetCounter()))
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
CharacterDatabase.DirectPExecute(
"INSERT INTO character_housing_neighborhood_role "
"(NeighborhoodGuid, CharacterGuid, Role, GrantedBy, GrantedAt) VALUES ('{}', {}, 1, {}, {}) "
"ON DUPLICATE KEY UPDATE Role = 1, GrantedBy = VALUES(GrantedBy), GrantedAt = VALUES(GrantedAt)",
neighborhoodGuid.ToString(), packet.PlayerGUID.GetCounter(), player->GetGUID().GetCounter(),
uint64(GameTime::GetGameTime()));
response.Result = CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_role WHERE NeighborhoodGuid = '{}' "
"AND CharacterGuid = {} AND Role = 1 LIMIT 1", neighborhoodGuid.ToString(), packet.PlayerGUID.GetCounter())
? ToPacketResult(Result::Success) : ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
if (response.Result == ToPacketResult(Result::Success))
{
WorldPackets::Housing::NeighborhoodRosterResidentUpdate update;
update.Residents.push_back({ packet.PlayerGUID, 1, true });
WorldPacket const* updatePacket = update.Write();
session->SendPacket(updatePacket);
if (Player* target = ObjectAccessor::FindConnectedPlayer(packet.PlayerGUID); target && target != player)
target->SendDirectMessage(updatePacket);
}
}
void HandleNeighborhoodRemoveSecondaryOwner(WorldSession* session,
WorldPackets::Housing::NeighborhoodRemoveSecondaryOwner& packet)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodSecondaryOwnerResponse response(
SMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER_RESPONSE);
response.PlayerGUID = packet.PlayerGUID;
Player* player = session->GetPlayer();
if (!player || !packet.PlayerGUID.IsPlayer())
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
ObjectGuid const neighborhoodGuid = ResolvePrimaryManagedNeighborhood(player);
if (!IsNeighborhoodGuid(neighborhoodGuid))
{
response.Result = ToPacketResult(Result::HouseNotFound);
session->SendPacket(response.Write());
return;
}
CharacterDatabase.DirectPExecute(
"DELETE FROM character_housing_neighborhood_role WHERE NeighborhoodGuid = '{}' AND CharacterGuid = {}",
neighborhoodGuid.ToString(), packet.PlayerGUID.GetCounter());
response.Result = CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_role WHERE NeighborhoodGuid = '{}' "
"AND CharacterGuid = {} LIMIT 1", neighborhoodGuid.ToString(), packet.PlayerGUID.GetCounter())
? ToPacketResult(Result::PermissionDenied) : ToPacketResult(Result::Success);
session->SendPacket(response.Write());
if (response.Result == ToPacketResult(Result::Success))
{
WorldPackets::Housing::NeighborhoodRosterResidentUpdate update;
update.Residents.push_back({ packet.PlayerGUID, 1, false });
WorldPacket const* updatePacket = update.Write();
session->SendPacket(updatePacket);
if (Player* target = ObjectAccessor::FindConnectedPlayer(packet.PlayerGUID); target && target != player)
target->SendDirectMessage(updatePacket);
}
}
void HandleNeighborhoodGetRoster(WorldSession* session,
WorldPackets::Housing::NeighborhoodGetRoster& packet)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodGetRosterResponse response;
response.NeighborhoodGUID = packet.NeighborhoodGUID;
Player* player = session->GetPlayer();
if (!player || !IsNeighborhoodGuid(packet.NeighborhoodGUID))
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
QueryResult neighborhood = CharacterDatabase.PQuery(
"SELECT OwnerGuid, Name, GuildId FROM housing_neighborhood WHERE NeighborhoodGuid = '{}' LIMIT 1",
packet.NeighborhoodGUID.ToString());
if (!neighborhood)
{
response.Result = ToPacketResult(Result::HouseNotFound);
session->SendPacket(response.Write());
return;
}
Field* neighborhoodFields = neighborhood->Fetch();
response.OwnerGUID = ObjectGuid::Create<HighGuid::Player>(neighborhoodFields[0].GetUInt64());
response.NeighborhoodName = neighborhoodFields[1].GetString();
uint32 const guildId = neighborhoodFields[2].GetUInt32();
bool const isResident = response.OwnerGUID == player->GetGUID() ||
(guildId != 0 && guildId == player->GetGuildId()) || CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing WHERE NeighborhoodGuid = '{}' AND OwnerGuid = {} LIMIT 1",
packet.NeighborhoodGUID.ToString(), player->GetGUID().GetCounter()) || CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_role WHERE NeighborhoodGuid = '{}' "
"AND CharacterGuid = {} AND Role = 1 LIMIT 1",
packet.NeighborhoodGUID.ToString(), player->GetGUID().GetCounter());
if (!response.OwnerGUID.IsPlayer() || !isResident)
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
QueryResult members = CharacterDatabase.PQuery(
"SELECT OwnerGuid, HouseGuid, PlotID FROM character_housing "
"WHERE NeighborhoodGuid = '{}' ORDER BY PlotID, OwnerGuid LIMIT 64",
packet.NeighborhoodGUID.ToString());
if (members)
{
do
{
Field* fields = members->Fetch();
WorldPackets::Housing::NeighborhoodGetRosterResponse::Member member;
member.PlayerGUID = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
member.HouseGUID = ObjectGuid::FromString(fields[1].GetString());
member.PlotIndex = fields[2].GetUInt8();
if (!member.PlayerGUID.IsPlayer() || !IsHouseGuid(member.HouseGUID))
continue;
if (Player* onlineMember = ObjectAccessor::FindConnectedPlayer(member.PlayerGUID))
{
member.IsOnline = true;
member.BnetAccountGUID = onlineMember->GetSession()->GetBattlenetAccountGUID();
}
response.Members.push_back(std::move(member));
} while (members->NextRow());
}
response.Result = ToPacketResult(Result::Success);
session->SendPacket(response.Write());
}
void HandleDeleteAllNeighborhoodInvites(WorldSession* session,
WorldPackets::Housing::HousingDeleteAllNeighborhoodInvites& /*packet*/)
{
if (!session)
return;
WorldPackets::Housing::HousingDeleteAllNeighborhoodInvitesResponse response;
Player* player = session->GetPlayer();
if (!player)
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
uint64 const playerGuid = player->GetGUID().GetCounter();
CharacterDatabase.DirectPExecute(
"DELETE FROM character_housing_neighborhood_invite WHERE InviteeGuid = {}", playerGuid);
response.Result = CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_invite WHERE InviteeGuid = {} LIMIT 1", playerGuid)
? ToPacketResult(Result::PermissionDenied) : ToPacketResult(Result::Success);
session->SendPacket(response.Write());
}
void HandleNeighborhoodCancelInvitation(WorldSession* session,
WorldPackets::Housing::NeighborhoodCancelInvitation& packet)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodCancelInvitationResponse response;
response.InviteeGUID = packet.InviteeGUID;
Player* player = session->GetPlayer();
if (!player || !packet.InviteeGUID.IsPlayer() || packet.InviteeGUID == player->GetGUID())
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
uint64 const ownerGuid = player->GetGUID().GetCounter();
uint64 const inviteeGuid = packet.InviteeGUID.GetCounter();
uint32 managedGuildId = 0;
if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId());
guild && guild->GetLeaderGUID() == player->GetGUID())
managedGuildId = guild->GetId();
QueryResult ownedInvite = CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_invite i "
"INNER JOIN housing_neighborhood n ON n.NeighborhoodGuid = i.NeighborhoodGuid "
"WHERE (n.OwnerGuid = {} OR n.GuildId = {} OR EXISTS (SELECT 1 FROM character_housing_neighborhood_role r "
"WHERE r.NeighborhoodGuid = i.NeighborhoodGuid AND r.CharacterGuid = {} AND r.Role = 1)) "
"AND i.InviteeGuid = {} LIMIT 1", ownerGuid, managedGuildId, ownerGuid, inviteeGuid);
if (!ownedInvite)
{
response.Result = ToPacketResult(Result::HouseNotFound);
session->SendPacket(response.Write());
return;
}
CharacterDatabase.DirectPExecute(
"DELETE i FROM character_housing_neighborhood_invite i "
"INNER JOIN housing_neighborhood n ON n.NeighborhoodGuid = i.NeighborhoodGuid "
"WHERE (n.OwnerGuid = {} OR n.GuildId = {} OR EXISTS (SELECT 1 FROM character_housing_neighborhood_role r "
"WHERE r.NeighborhoodGuid = i.NeighborhoodGuid AND r.CharacterGuid = {} AND r.Role = 1)) "
"AND i.InviteeGuid = {}", ownerGuid, managedGuildId, ownerGuid, inviteeGuid);
response.Result = CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_invite i "
"INNER JOIN housing_neighborhood n ON n.NeighborhoodGuid = i.NeighborhoodGuid "
"WHERE (n.OwnerGuid = {} OR n.GuildId = {} OR EXISTS (SELECT 1 FROM character_housing_neighborhood_role r "
"WHERE r.NeighborhoodGuid = i.NeighborhoodGuid AND r.CharacterGuid = {} AND r.Role = 1)) "
"AND i.InviteeGuid = {} LIMIT 1", ownerGuid, managedGuildId, ownerGuid, inviteeGuid)
? ToPacketResult(Result::PermissionDenied) : ToPacketResult(Result::Success);
session->SendPacket(response.Write());
}
void HandleNeighborhoodGetInvites(WorldSession* session,
WorldPackets::Housing::NeighborhoodGetInvites& /*packet*/)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodGetInvitesResponse response;
Player* player = session->GetPlayer();
if (!player)
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
QueryResult invites = CharacterDatabase.PQuery(
"SELECT i.InviterGuid, i.CreatedAt, COALESCE((SELECT ch.HouseGuid FROM character_housing ch "
"WHERE ch.OwnerGuid = i.InviterGuid AND ch.NeighborhoodGuid = i.NeighborhoodGuid "
"ORDER BY ch.HouseGuid LIMIT 1), '') FROM character_housing_neighborhood_invite i "
"WHERE i.InviteeGuid = {} ORDER BY i.CreatedAt DESC LIMIT 64",
player->GetGUID().GetCounter());
if (invites)
{
do
{
Field* fields = invites->Fetch();
WorldPackets::Housing::NeighborhoodInviteEntry invite;
invite.PlayerGUID = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
invite.Timestamp = fields[1].GetUInt64();
invite.HouseGUID = ObjectGuid::FromString(fields[2].GetString());
if (invite.PlayerGUID.IsPlayer())
response.Invites.push_back(std::move(invite));
} while (invites->NextRow());
}
response.Result = ToPacketResult(Result::Success);
session->SendPacket(response.Write());
}
void HandleNeighborhoodPlayerGetInvite(WorldSession* session,
WorldPackets::Housing::NeighborhoodPlayerGetInvite& /*packet*/)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodPlayerGetInviteResponse response;
Player* player = session->GetPlayer();
if (!player)
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
QueryResult invite = CharacterDatabase.PQuery(
"SELECT i.InviterGuid, i.CreatedAt, COALESCE((SELECT ch.HouseGuid FROM character_housing ch "
"WHERE ch.OwnerGuid = i.InviterGuid AND ch.NeighborhoodGuid = i.NeighborhoodGuid "
"ORDER BY ch.HouseGuid LIMIT 1), '') FROM character_housing_neighborhood_invite i "
"WHERE i.InviteeGuid = {} ORDER BY i.CreatedAt DESC LIMIT 1",
player->GetGUID().GetCounter());
if (!invite)
{
response.Result = ToPacketResult(Result::HouseNotFound);
session->SendPacket(response.Write());
return;
}
Field* fields = invite->Fetch();
response.Invite.PlayerGUID = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
response.Invite.Timestamp = fields[1].GetUInt64();
response.Invite.HouseGUID = ObjectGuid::FromString(fields[2].GetString());
response.Result = response.Invite.PlayerGUID.IsPlayer()
? ToPacketResult(Result::Success) : ToPacketResult(Result::HouseNotFound);
session->SendPacket(response.Write());
}
void HandleNeighborhoodPlayerDeclineInvite(WorldSession* session,
WorldPackets::Housing::NeighborhoodPlayerDeclineInvite& packet)
{
if (!session)
return;
WorldPackets::Housing::NeighborhoodDeclineInvitationResponse response;
response.NeighborhoodGUID = packet.NeighborhoodGUID;
Player* player = session->GetPlayer();
if (!player || !IsNeighborhoodGuid(packet.NeighborhoodGUID))
{
response.Result = ToPacketResult(Result::PermissionDenied);
session->SendPacket(response.Write());
return;
}
CharacterDatabase.DirectPExecute(
"DELETE FROM character_housing_neighborhood_invite WHERE NeighborhoodGuid = '{}' AND InviteeGuid = {}",
packet.NeighborhoodGUID.ToString(), player->GetGUID().GetCounter());
response.Result = CharacterDatabase.PQuery(
"SELECT 1 FROM character_housing_neighborhood_invite WHERE NeighborhoodGuid = '{}' "
"AND InviteeGuid = {} LIMIT 1", packet.NeighborhoodGUID.ToString(), player->GetGUID().GetCounter())
? ToPacketResult(Result::PermissionDenied) : ToPacketResult(Result::Success);
session->SendPacket(response.Write());
}
void HandleGetPlayerHousesInfo(WorldSession* session, WorldPackets::Housing::GetPlayerHousesInfo& /*packet*/)
{
if (!session)
@@ -459,10 +1146,14 @@ namespace Housing
{
response.House = ToPacketHouse(state);
if (moved && hadHouse)
{
SynchronizeExteriorMove(player, previousState, state);
BroadcastGuildHouseUpdate(previousState, false);
}
else
SynchronizeExteriorPlot(player, state, true);
SendHouseEntityGraph(session, player, state);
BroadcastGuildHouseUpdate(state, true);
}
session->SendPacket(response.Write());
@@ -508,6 +1199,8 @@ namespace Housing
6, state.ExteriorMapId, uint32(state.PlotId), player->GetGUID().GetCounter());
SynchronizeExteriorMove(player, previousState, state);
SendHouseEntityGraph(session, player, state);
BroadcastGuildHouseUpdate(previousState, false);
BroadcastGuildHouseUpdate(state, true);
}
session->SendPacket(response.Write());
@@ -524,7 +1217,10 @@ namespace Housing
if (Player* player = session->GetPlayer())
{
QueryResult neighborhoods = CharacterDatabase.PQuery(
"SELECT NeighborhoodGuid FROM housing_neighborhood ORDER BY NeighborhoodGuid LIMIT 129");
"SELECT NeighborhoodGuid FROM housing_neighborhood "
"WHERE IsPublic = 1 OR OwnerGuid = {} OR GuildId = {} "
"ORDER BY NeighborhoodGuid LIMIT 129",
player->GetGUID().GetCounter(), player->GetGuildId());
if (neighborhoods)
{
do
@@ -677,6 +1373,7 @@ namespace Housing
// before the transaction may be used to remove live entities safely.
RemoveLiveHouseEntities(player, previousState, roomGuids, dynamicEntityGuids);
SynchronizeExteriorPlot(player, previousState, false);
BroadcastGuildHouseUpdate(previousState, false);
}
session->SendPacket(response.Write());
@@ -7,6 +7,7 @@
#include "Define.h"
class ObjectGuid;
class WorldSession;
namespace WorldPackets::Housing
@@ -16,6 +17,16 @@ namespace WorldPackets::Housing
class HouseStatus;
class PlayerViewHousesByPlayer;
class HousingGetPotentialHouseOwners;
class InvitePlayerToNeighborhood;
class HousingDeleteAllNeighborhoodInvites;
class NeighborhoodCancelInvitation;
class NeighborhoodSetPublicFlag;
class NeighborhoodAddSecondaryOwner;
class NeighborhoodRemoveSecondaryOwner;
class NeighborhoodGetRoster;
class NeighborhoodGetInvites;
class NeighborhoodPlayerGetInvite;
class NeighborhoodPlayerDeclineInvite;
class GetPlayerHousesInfo;
class NeighborhoodBuyHouse;
class NeighborhoodMoveHouse;
@@ -33,6 +44,9 @@ namespace Housing
// Client-facing adapters for the Housing implementation. Persistence
// and ownership validation stay in Housing::Manager; this layer owns only wire
// responses plus safe synchronization of live map entities.
TC_GAME_API void HandleGuildDisband(uint32 guildId, ObjectGuid const& fallbackOwnerGuid);
TC_GAME_API void HandleGuildMemberRemoved(uint32 guildId, ObjectGuid const& memberGuid);
TC_GAME_API void HandleGetCurrentHouseInfo(WorldSession* session,
WorldPackets::Housing::GetCurrentHouseInfo& packet);
TC_GAME_API void HandleGetPlayerPermissions(WorldSession* session,
@@ -43,6 +57,28 @@ namespace Housing
WorldPackets::Housing::PlayerViewHousesByPlayer& packet);
TC_GAME_API void HandleGetPotentialHouseOwners(WorldSession* session,
WorldPackets::Housing::HousingGetPotentialHouseOwners& packet);
TC_GAME_API void HandleInvitePlayerToNeighborhood(WorldSession* session,
WorldPackets::Housing::InvitePlayerToNeighborhood& packet);
TC_GAME_API void HandleDeleteAllNeighborhoodInvites(WorldSession* session,
WorldPackets::Housing::HousingDeleteAllNeighborhoodInvites& packet);
TC_GAME_API void HandleNeighborhoodCancelInvitation(WorldSession* session,
WorldPackets::Housing::NeighborhoodCancelInvitation& packet);
TC_GAME_API void HandleHousingSvcsGuildCreateNeighborhood(WorldSession* session,
WorldPackets::Housing::HousingSvcsGuildCreateNeighborhood& packet);
TC_GAME_API void HandleNeighborhoodSetPublicFlag(WorldSession* session,
WorldPackets::Housing::NeighborhoodSetPublicFlag& packet);
TC_GAME_API void HandleNeighborhoodAddSecondaryOwner(WorldSession* session,
WorldPackets::Housing::NeighborhoodAddSecondaryOwner& packet);
TC_GAME_API void HandleNeighborhoodRemoveSecondaryOwner(WorldSession* session,
WorldPackets::Housing::NeighborhoodRemoveSecondaryOwner& packet);
TC_GAME_API void HandleNeighborhoodGetRoster(WorldSession* session,
WorldPackets::Housing::NeighborhoodGetRoster& packet);
TC_GAME_API void HandleNeighborhoodGetInvites(WorldSession* session,
WorldPackets::Housing::NeighborhoodGetInvites& packet);
TC_GAME_API void HandleNeighborhoodPlayerGetInvite(WorldSession* session,
WorldPackets::Housing::NeighborhoodPlayerGetInvite& packet);
TC_GAME_API void HandleNeighborhoodPlayerDeclineInvite(WorldSession* session,
WorldPackets::Housing::NeighborhoodPlayerDeclineInvite& packet);
TC_GAME_API void HandleGetPlayerHousesInfo(WorldSession* session,
WorldPackets::Housing::GetPlayerHousesInfo& packet);
TC_GAME_API void HandleBuyHouse(WorldSession* session,
@@ -121,6 +121,174 @@ namespace WorldPackets::Housing
return &_worldPacket;
}
void InvitePlayerToNeighborhood::Read()
{
_worldPacket >> SizedString::BitsSize<6>(PlayerName);
_worldPacket >> SizedString::Data(PlayerName);
}
WorldPacket const* NeighborhoodInviteNameLookupResult::Write()
{
_worldPacket << uint8(Result);
_worldPacket << PlayerGUID;
return &_worldPacket;
}
WorldPacket const* NeighborhoodInviteResidentResponse::Write()
{
_worldPacket << uint8(Result);
_worldPacket << InviteeGUID;
return &_worldPacket;
}
WorldPacket const* HousingDeleteAllNeighborhoodInvitesResponse::Write()
{
_worldPacket << uint8(Result);
return &_worldPacket;
}
WorldPacket const* NeighborhoodCancelInvitationResponse::Write()
{
_worldPacket << uint8(Result);
_worldPacket << InviteeGUID;
return &_worldPacket;
}
namespace
{
void WriteNeighborhoodInviteEntry(WorldPacket& packet, NeighborhoodInviteEntry const& invite)
{
packet << uint64(invite.Timestamp);
packet << invite.PlayerGUID;
packet << invite.HouseGUID;
packet << uint64(invite.ExtraData);
}
}
void HousingSvcsGuildCreateNeighborhood::Read()
{
_worldPacket >> NeighborhoodTypeID;
_worldPacket >> SecondaryID;
_worldPacket >> SizedCString::BitsSize<8>(NeighborhoodName);
_worldPacket >> SizedCString::Data(NeighborhoodName);
}
WorldPacket const* HousingSvcsGuildCreateNeighborhoodNotification::Write()
{
_worldPacket << NeighborhoodGUID;
_worldPacket << uint8(Flag);
uint8 const nameLength = static_cast<uint8>(std::min<std::size_t>(Name.size() + 1, 255));
_worldPacket << nameLength;
if (nameLength)
_worldPacket.append(Name.c_str(), nameLength);
return &_worldPacket;
}
WorldPacket const* HousingSvcsGuildAddHouseNotification::Write()
{
WriteHouse(_worldPacket, House);
return &_worldPacket;
}
WorldPacket const* HousingSvcsGuildRemoveHouseNotification::Write()
{
WriteHouse(_worldPacket, House);
return &_worldPacket;
}
void NeighborhoodSetPublicFlag::Read()
{
_worldPacket >> NeighborhoodGUID;
_worldPacket >> Bits<1>(IsPublic);
}
WorldPacket const* NeighborhoodSecondaryOwnerResponse::Write()
{
_worldPacket << PlayerGUID;
_worldPacket << uint8(Result);
return &_worldPacket;
}
WorldPacket const* NeighborhoodRosterResidentUpdate::Write()
{
_worldPacket << uint32(Residents.size());
for (Resident const& resident : Residents)
{
_worldPacket << resident.PlayerGUID;
_worldPacket << uint8(resident.UpdateType);
_worldPacket << uint8(resident.IsPrivileged ? 0x80 : 0x00);
}
return &_worldPacket;
}
WorldPacket const* NeighborhoodGetRosterResponse::Write()
{
_worldPacket << uint8(Result);
_worldPacket << uint32(Members.size());
_worldPacket << uint32(1);
_worldPacket << NeighborhoodGUID;
_worldPacket << OwnerGUID;
_worldPacket << uint64(0);
_worldPacket << uint64(0);
_worldPacket << uint32(Members.size());
uint8 const nameLength = NeighborhoodName.empty()
? 0 : uint8(std::min<std::size_t>(NeighborhoodName.size() + 1, 255));
_worldPacket << uint8(nameLength);
_worldPacket << uint8(0);
for (Member const& member : Members)
{
_worldPacket << member.HouseGUID;
_worldPacket << member.PlayerGUID;
_worldPacket << member.BnetAccountGUID;
_worldPacket << uint8(member.PlotIndex);
_worldPacket << uint32(member.JoinTime);
_worldPacket << uint8(0);
}
if (nameLength > 1)
_worldPacket.append(NeighborhoodName.c_str(), nameLength);
_worldPacket << uint8(0);
for (Member const& member : Members)
{
_worldPacket << member.PlayerGUID;
_worldPacket << uint8(0);
_worldPacket << uint8(member.IsOnline ? 0x80 : 0x00);
}
return &_worldPacket;
}
WorldPacket const* NeighborhoodGetInvitesResponse::Write()
{
_worldPacket << uint8(Result);
_worldPacket << uint32(Invites.size());
for (NeighborhoodInviteEntry const& invite : Invites)
WriteNeighborhoodInviteEntry(_worldPacket, invite);
return &_worldPacket;
}
WorldPacket const* NeighborhoodPlayerGetInviteResponse::Write()
{
_worldPacket << uint8(Result);
WriteNeighborhoodInviteEntry(_worldPacket, Invite);
return &_worldPacket;
}
WorldPacket const* NeighborhoodDeclineInvitationResponse::Write()
{
_worldPacket << uint8(Result);
_worldPacket << NeighborhoodGUID;
return &_worldPacket;
}
WorldPacket const* NeighborhoodInviteNotification::Write()
{
_worldPacket << NeighborhoodGUID;
return &_worldPacket;
}
WorldPacket const* GetPlayerHousesInfoResponse::Write()
{
_worldPacket << uint32(PlayerHouses.size());
@@ -223,6 +391,13 @@ namespace WorldPackets::Housing
}
}
WorldPacket const* HousingSvcsCreateCharterNeighborhoodResponse::Write()
{
WriteHouseFinderNeighborhood(_worldPacket, Neighborhood);
_worldPacket << uint8(Result);
return &_worldPacket;
}
WorldPacket const* HousingGetHouseFinderInfoResponse::Write()
{
// Retail 12.1: one result bit, a raw uint32 count, then full finder records.
@@ -166,6 +166,254 @@ namespace WorldPackets::Housing
std::vector<PotentialOwner> PotentialOwners;
};
class InvitePlayerToNeighborhood final : public ClientPacket
{
public:
explicit InvitePlayerToNeighborhood(WorldPacket&& packet) : ClientPacket(CMSG_INVITE_PLAYER_TO_NEIGHBORHOOD, std::move(packet)) {}
void Read() override;
std::string PlayerName;
};
class NeighborhoodInviteNameLookupResult final : public ServerPacket
{
public:
NeighborhoodInviteNameLookupResult() : ServerPacket(SMSG_NEIGHBORHOOD_INVITE_NAME_LOOKUP_RESULT, 24) {}
WorldPacket const* Write() override;
ObjectGuid PlayerGUID;
uint8 Result = 0;
};
class NeighborhoodInviteResidentResponse final : public ServerPacket
{
public:
NeighborhoodInviteResidentResponse() : ServerPacket(SMSG_NEIGHBORHOOD_INVITE_RESIDENT_RESPONSE, 24) {}
WorldPacket const* Write() override;
ObjectGuid InviteeGUID;
uint8 Result = 0;
};
class NeighborhoodInviteNotification final : public ServerPacket
{
public:
NeighborhoodInviteNotification() : ServerPacket(SMSG_NEIGHBORHOOD_INVITE_NOTIFICATION, 16) {}
WorldPacket const* Write() override;
ObjectGuid NeighborhoodGUID;
};
struct NeighborhoodInviteEntry
{
uint64 Timestamp = 0;
ObjectGuid PlayerGUID;
ObjectGuid HouseGUID;
uint64 ExtraData = 0;
};
class HousingDeleteAllNeighborhoodInvites final : public ClientPacket
{
public:
explicit HousingDeleteAllNeighborhoodInvites(WorldPacket&& packet) : ClientPacket(CMSG_HOUSING_SVCS_DELETE_ALL_NEIGHBORHOOD_INVITES, std::move(packet)) {}
void Read() override {}
};
class HousingDeleteAllNeighborhoodInvitesResponse final : public ServerPacket
{
public:
HousingDeleteAllNeighborhoodInvitesResponse() : ServerPacket(SMSG_HOUSING_SVCS_DELETE_ALL_NEIGHBORHOOD_INVITES_RESPONSE, 1) {}
WorldPacket const* Write() override;
uint8 Result = 0;
};
class NeighborhoodCancelInvitation final : public ClientPacket
{
public:
explicit NeighborhoodCancelInvitation(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_CANCEL_INVITATION, std::move(packet)) {}
void Read() override { _worldPacket >> InviteeGUID; }
ObjectGuid InviteeGUID;
};
class NeighborhoodCancelInvitationResponse final : public ServerPacket
{
public:
NeighborhoodCancelInvitationResponse() : ServerPacket(SMSG_NEIGHBORHOOD_CANCEL_INVITATION_RESPONSE, 24) {}
WorldPacket const* Write() override;
ObjectGuid InviteeGUID;
uint8 Result = 0;
};
class HousingSvcsGuildCreateNeighborhood final : public ClientPacket
{
public:
explicit HousingSvcsGuildCreateNeighborhood(WorldPacket&& packet) : ClientPacket(CMSG_HOUSING_SVCS_GUILD_CREATE_NEIGHBORHOOD, std::move(packet)) {}
void Read() override;
uint32 NeighborhoodTypeID = 0;
uint32 SecondaryID = 0;
std::string NeighborhoodName;
};
class HousingSvcsGuildCreateNeighborhoodNotification final : public ServerPacket
{
public:
HousingSvcsGuildCreateNeighborhoodNotification() : ServerPacket(SMSG_HOUSING_SVCS_GUILD_CREATE_NEIGHBORHOOD_NOTIFICATION, 32) {}
WorldPacket const* Write() override;
ObjectGuid NeighborhoodGUID;
uint8 Flag = 0;
std::string Name;
};
class HousingSvcsGuildAddHouseNotification final : public ServerPacket
{
public:
HousingSvcsGuildAddHouseNotification() : ServerPacket(SMSG_HOUSING_SVCS_GUILD_ADD_HOUSE_NOTIFICATION, 64) {}
WorldPacket const* Write() override;
HouseInfo House;
};
class HousingSvcsGuildRemoveHouseNotification final : public ServerPacket
{
public:
HousingSvcsGuildRemoveHouseNotification() : ServerPacket(SMSG_HOUSING_SVCS_GUILD_REMOVE_HOUSE_NOTIFICATION, 64) {}
WorldPacket const* Write() override;
HouseInfo House;
};
class NeighborhoodSetPublicFlag final : public ClientPacket
{
public:
explicit NeighborhoodSetPublicFlag(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_SET_PUBLIC_FLAG, std::move(packet)) {}
void Read() override;
ObjectGuid NeighborhoodGUID;
bool IsPublic = false;
};
class HousingHouseFinderForceRefresh final : public ServerPacket
{
public:
HousingHouseFinderForceRefresh() : ServerPacket(SMSG_HOUSING_SVCS_HOUSE_FINDER_FORCE_REFRESH, 0) {}
WorldPacket const* Write() override { return &_worldPacket; }
};
class NeighborhoodAddSecondaryOwner final : public ClientPacket
{
public:
explicit NeighborhoodAddSecondaryOwner(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_ADD_SECONDARY_OWNER, std::move(packet)) {}
void Read() override { _worldPacket >> PlayerGUID; }
ObjectGuid PlayerGUID;
};
class NeighborhoodRemoveSecondaryOwner final : public ClientPacket
{
public:
explicit NeighborhoodRemoveSecondaryOwner(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER, std::move(packet)) {}
void Read() override { _worldPacket >> PlayerGUID; }
ObjectGuid PlayerGUID;
};
class NeighborhoodSecondaryOwnerResponse final : public ServerPacket
{
public:
explicit NeighborhoodSecondaryOwnerResponse(OpcodeServer opcode) : ServerPacket(opcode, 24) {}
WorldPacket const* Write() override;
ObjectGuid PlayerGUID;
uint8 Result = 0;
};
class NeighborhoodRosterResidentUpdate final : public ServerPacket
{
public:
struct Resident { ObjectGuid PlayerGUID; uint8 UpdateType = 1; bool IsPrivileged = false; };
NeighborhoodRosterResidentUpdate() : ServerPacket(SMSG_NEIGHBORHOOD_ROSTER_RESIDENT_UPDATE, 32) {}
WorldPacket const* Write() override;
std::vector<Resident> Residents;
};
class NeighborhoodGetRoster final : public ClientPacket
{
public:
explicit NeighborhoodGetRoster(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_GET_ROSTER, std::move(packet)) {}
void Read() override { _worldPacket >> NeighborhoodGUID; }
ObjectGuid NeighborhoodGUID;
};
class NeighborhoodGetRosterResponse final : public ServerPacket
{
public:
struct Member
{
ObjectGuid HouseGUID;
ObjectGuid PlayerGUID;
ObjectGuid BnetAccountGUID;
uint8 PlotIndex = 0;
uint32 JoinTime = 0;
bool IsOnline = false;
};
NeighborhoodGetRosterResponse() : ServerPacket(SMSG_NEIGHBORHOOD_GET_ROSTER_RESPONSE, 128) {}
WorldPacket const* Write() override;
ObjectGuid NeighborhoodGUID;
ObjectGuid OwnerGUID;
std::string NeighborhoodName;
std::vector<Member> Members;
uint8 Result = 0;
};
class NeighborhoodGetInvites final : public ClientPacket
{
public:
explicit NeighborhoodGetInvites(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_GET_INVITES, std::move(packet)) {}
void Read() override {}
};
class NeighborhoodPlayerGetInvite final : public ClientPacket
{
public:
explicit NeighborhoodPlayerGetInvite(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_PLAYER_GET_INVITE, std::move(packet)) {}
void Read() override {}
};
class NeighborhoodPlayerDeclineInvite final : public ClientPacket
{
public:
explicit NeighborhoodPlayerDeclineInvite(WorldPacket&& packet) : ClientPacket(CMSG_NEIGHBORHOOD_PLAYER_DECLINE_INVITE, std::move(packet)) {}
void Read() override { _worldPacket >> NeighborhoodGUID; }
ObjectGuid NeighborhoodGUID;
};
class NeighborhoodGetInvitesResponse final : public ServerPacket
{
public:
NeighborhoodGetInvitesResponse() : ServerPacket(SMSG_NEIGHBORHOOD_GET_INVITES_RESPONSE, 64) {}
WorldPacket const* Write() override;
std::vector<NeighborhoodInviteEntry> Invites;
uint8 Result = 0;
};
class NeighborhoodPlayerGetInviteResponse final : public ServerPacket
{
public:
NeighborhoodPlayerGetInviteResponse() : ServerPacket(SMSG_NEIGHBORHOOD_PLAYER_GET_INVITE_RESPONSE, 64) {}
WorldPacket const* Write() override;
NeighborhoodInviteEntry Invite;
uint8 Result = 0;
};
class NeighborhoodDeclineInvitationResponse final : public ServerPacket
{
public:
NeighborhoodDeclineInvitationResponse() : ServerPacket(SMSG_NEIGHBORHOOD_DECLINE_INVITATION_RESPONSE, 24) {}
WorldPacket const* Write() override;
ObjectGuid NeighborhoodGUID;
uint8 Result = 0;
};
class GetPlayerHousesInfo final : public ClientPacket
{
public:
@@ -278,6 +526,15 @@ namespace WorldPackets::Housing
uint8 ExtraFlags = 0;
};
class HousingSvcsCreateCharterNeighborhoodResponse final : public ServerPacket
{
public:
HousingSvcsCreateCharterNeighborhoodResponse() : ServerPacket(SMSG_HOUSING_SVCS_CREATE_CHARTER_NEIGHBORHOOD_RESPONSE, 128) {}
WorldPacket const* Write() override;
HouseFinderNeighborhoodInfo Neighborhood;
uint8 Result = 0;
};
class HousingGetHouseFinderInfo final : public ClientPacket
{
public:
+28 -28
View File
@@ -613,14 +613,14 @@ void OpcodeTable::InitializeClientOpcodes()
DEFINE_HANDLER(CMSG_HOUSING_ROOM_SET_DOOR_TYPE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingRoomSetDoorType);
DEFINE_HANDLER(CMSG_HOUSING_ROOM_SET_LAYOUT_EDIT_MODE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingRoomSetLayoutEditMode);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_ACCEPT_NEIGHBORHOOD_OWNERSHIP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_DELETE_ALL_NEIGHBORHOOD_INVITES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_DELETE_ALL_NEIGHBORHOOD_INVITES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingDeleteAllNeighborhoodInvites);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_GET_BNET_FRIEND_NEIGHBORHOODS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_GET_HOUSE_FINDER_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingGetHouseFinderInfo);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_GET_HOUSE_FINDER_NEIGHBORHOOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingGetHouseFinderNeighborhood);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_GET_PLAYER_HOUSES_INFO, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingGetPlayerHousesInfo);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_GET_POTENTIAL_HOUSE_OWNERS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingGetPotentialHouseOwners);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_HOUSE_FINDER_IGNORE_NEIGHBORHOOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingHouseFinderIgnoreNeighborhood);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_GUILD_CREATE_NEIGHBORHOOD, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_GUILD_CREATE_NEIGHBORHOOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingSvcsGuildCreateNeighborhood);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_NEIGHBORHOOD_RESERVE_PLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingReservePlot);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_PLAYER_VIEW_HOUSES_BY_BNET_ACCOUNT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_HOUSING_SVCS_PLAYER_VIEW_HOUSES_BY_PLAYER, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleHousingPlayerViewHousesByPlayer);
@@ -636,7 +636,7 @@ void OpcodeTable::InitializeClientOpcodes()
DEFINE_HANDLER(CMSG_INSPECT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleInspectOpcode);
DEFINE_HANDLER(CMSG_INSTANCE_ABANDON_VOTE_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceAbandonVoteResponse);
DEFINE_HANDLER(CMSG_INSTANCE_LOCK_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse);
DEFINE_HANDLER(CMSG_INVITE_PLAYER_TO_NEIGHBORHOOD, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_INVITE_PLAYER_TO_NEIGHBORHOOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInvitePlayerToNeighborhood);
DEFINE_HANDLER(CMSG_ISLAND_QUEUE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIslandQueue);
DEFINE_HANDLER(CMSG_ITEM_PURCHASE_REFUND, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleItemRefund);
DEFINE_HANDLER(CMSG_ITEM_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleItemTextQuery);
@@ -810,9 +810,9 @@ void OpcodeTable::InitializeClientOpcodes()
DEFINE_HANDLER(CMSG_MOVE_UPDATE_FALL_SPEED, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes);
DEFINE_HANDLER(CMSG_MOVE_WATER_WALK_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementAckMessage);
DEFINE_HANDLER(CMSG_MYTHIC_PLUS_REQUEST_MAP_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMythicPlusRequestMapStats);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_ADD_SECONDARY_OWNER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_ADD_SECONDARY_OWNER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodAddSecondaryOwner);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_BUY_HOUSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodBuyHouse);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_CANCEL_INVITATION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_CANCEL_INVITATION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodCancelInvitation);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_CHARTER_ADD_SIGNATURE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_CHARTER_CREATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_CHARTER_EDIT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
@@ -820,17 +820,17 @@ void OpcodeTable::InitializeClientOpcodes()
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_CHARTER_OPEN_CONFIRMATION_UI, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_CHARTER_SEND_SIGNATURE_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_EVICT_PLOT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_GET_INVITES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_GET_ROSTER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_GET_INVITES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodGetInvites);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_GET_ROSTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodGetRoster);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_INITIATIVE_SERVICE_STATUS_CHECK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodInitiativeServiceStatusCheck);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_INVITE_RESIDENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_MOVE_HOUSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodMoveHouse);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_OFFER_OWNERSHIP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_OPEN_CORNERSTONE_UI, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodOpenCornerstoneUI);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_PLAYER_DECLINE_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_PLAYER_GET_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_SET_PUBLIC_FLAG, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_PLAYER_DECLINE_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodPlayerDeclineInvite);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_PLAYER_GET_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodPlayerGetInvite);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodRemoveSecondaryOwner);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_SET_PUBLIC_FLAG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNeighborhoodSetPublicFlag);
DEFINE_HANDLER(CMSG_NEIGHBORHOOD_UPDATE_NAME, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_NEUTRAL_PLAYER_SELECT_FACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSelectFactionOpcode);
DEFINE_HANDLER(CMSG_NEXT_CINEMATIC_CAMERA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera);
@@ -1796,20 +1796,20 @@ void OpcodeTable::InitializeServerOpcodes()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_CANCEL_RELINQUISH_HOUSE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_CHANGE_HOUSE_COSMETIC_OWNER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_CLEAR_PLOT_RESERVATION_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_CREATE_CHARTER_NEIGHBORHOOD_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_DELETE_ALL_NEIGHBORHOOD_INVITES_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_CREATE_CHARTER_NEIGHBORHOOD_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_DELETE_ALL_NEIGHBORHOOD_INVITES_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GET_BNET_FRIEND_NEIGHBORHOODS_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GET_HOUSE_FINDER_INFO_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GET_HOUSE_FINDER_NEIGHBORHOOD_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GET_PLAYER_HOUSES_INFO_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GET_POTENTIAL_HOUSE_OWNERS_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_ADD_HOUSE_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_ADD_HOUSE_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_APPEND_NEIGHBORHOOD_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_CREATE_NEIGHBORHOOD_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_CREATE_NEIGHBORHOOD_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_GET_HOUSING_INFO_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_REMOVE_HOUSE_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_REMOVE_HOUSE_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_GUILD_RENAME_NEIGHBORHOOD_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_HOUSE_FINDER_FORCE_REFRESH, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_HOUSE_FINDER_FORCE_REFRESH, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_IGNORE_NEIGHBORHOOD_INVITE_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_NEIGHBORHOOD_OWNERSHIP_TRANSFERRED_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOUSING_SVCS_NEIGHBORHOOD_RESERVE_PLOT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -2096,30 +2096,30 @@ void OpcodeTable::InitializeServerOpcodes()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MYTHIC_PLUS_CURRENT_AFFIXES, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MYTHIC_PLUS_NEW_WEEK_RECORD, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MYTHIC_PLUS_SEASON_DATA, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_ADD_SECONDARY_OWNER_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_ADD_SECONDARY_OWNER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_BUY_HOUSE_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CANCEL_INVITATION_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CANCEL_INVITATION_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CHARTER_ADD_SIGNATURE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CHARTER_OPEN_CONFIRMATION_UI_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CHARTER_OPEN_UI_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CHARTER_SIGNATURE_REMOVED_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CHARTER_SIGN_REQUEST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_CHARTER_UPDATE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_DECLINE_INVITATION_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_DECLINE_INVITATION_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_EVICT_PLAYER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_EVICT_PLOT_NOTICE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_EVICT_PLOT_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_GET_INVITES_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_GET_ROSTER_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_INVITE_NAME_LOOKUP_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_INVITE_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_INVITE_RESIDENT_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_GET_INVITES_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_GET_ROSTER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_INVITE_NAME_LOOKUP_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_INVITE_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_INVITE_RESIDENT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_MOVE_HOUSE_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_OFFER_OWNERSHIP_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_OPEN_CORNERSTONE_UI_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_PLAYER_GET_INVITE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_ROSTER_RESIDENT_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_PLAYER_GET_INVITE_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_REMOVE_SECONDARY_OWNER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_ROSTER_RESIDENT_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEIGHBORHOOD_UPDATE_NAME_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEUTRAL_PLAYER_FACTION_SELECT_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_DATA_BUILD, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+22
View File
@@ -642,6 +642,17 @@ namespace WorldPackets
class HouseStatus;
class PlayerViewHousesByPlayer;
class HousingGetPotentialHouseOwners;
class InvitePlayerToNeighborhood;
class HousingDeleteAllNeighborhoodInvites;
class NeighborhoodCancelInvitation;
class HousingSvcsGuildCreateNeighborhood;
class NeighborhoodSetPublicFlag;
class NeighborhoodAddSecondaryOwner;
class NeighborhoodRemoveSecondaryOwner;
class NeighborhoodGetRoster;
class NeighborhoodGetInvites;
class NeighborhoodPlayerGetInvite;
class NeighborhoodPlayerDeclineInvite;
class GetPlayerHousesInfo;
class HousingBlueprintRequestCollection;
class HousingDecorDeleteFromStorage;
@@ -1977,6 +1988,17 @@ public:
void HandleHousingHouseStatus(WorldPackets::Housing::HouseStatus& packet);
void HandleHousingPlayerViewHousesByPlayer(WorldPackets::Housing::PlayerViewHousesByPlayer& packet);
void HandleHousingGetPotentialHouseOwners(WorldPackets::Housing::HousingGetPotentialHouseOwners& packet);
void HandleInvitePlayerToNeighborhood(WorldPackets::Housing::InvitePlayerToNeighborhood& packet);
void HandleHousingDeleteAllNeighborhoodInvites(WorldPackets::Housing::HousingDeleteAllNeighborhoodInvites& packet);
void HandleNeighborhoodCancelInvitation(WorldPackets::Housing::NeighborhoodCancelInvitation& packet);
void HandleHousingSvcsGuildCreateNeighborhood(WorldPackets::Housing::HousingSvcsGuildCreateNeighborhood& packet);
void HandleNeighborhoodSetPublicFlag(WorldPackets::Housing::NeighborhoodSetPublicFlag& packet);
void HandleNeighborhoodAddSecondaryOwner(WorldPackets::Housing::NeighborhoodAddSecondaryOwner& packet);
void HandleNeighborhoodRemoveSecondaryOwner(WorldPackets::Housing::NeighborhoodRemoveSecondaryOwner& packet);
void HandleNeighborhoodGetRoster(WorldPackets::Housing::NeighborhoodGetRoster& packet);
void HandleNeighborhoodGetInvites(WorldPackets::Housing::NeighborhoodGetInvites& packet);
void HandleNeighborhoodPlayerGetInvite(WorldPackets::Housing::NeighborhoodPlayerGetInvite& packet);
void HandleNeighborhoodPlayerDeclineInvite(WorldPackets::Housing::NeighborhoodPlayerDeclineInvite& packet);
void HandleHousingGetPlayerHousesInfo(WorldPackets::Housing::GetPlayerHousesInfo& packet);
void HandleHousingGetHouseFinderInfo(WorldPackets::Housing::HousingGetHouseFinderInfo& packet);
void HandleHousingGetHouseFinderNeighborhood(WorldPackets::Housing::HousingGetHouseFinderNeighborhood& packet);