mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: implement SMSG_BATTLEFIELD_LIST handler
Parse the battleground availability list sent by the server when the player opens the BG finder. Handles all three expansion wire formats: - Classic: bgTypeId + isRegistered + count + instanceIds - TBC: adds isHoliday byte - WotLK: adds minLevel/maxLevel for bracket display Stores results in availableBgs_ (public via getAvailableBgs()) so the UI can show available battlegrounds and running instance counts without an additional server round-trip.
This commit is contained in:
parent
793c2b5611
commit
f8f57411f2
2 changed files with 90 additions and 1 deletions
|
|
@ -405,11 +405,22 @@ public:
|
|||
std::chrono::steady_clock::time_point inviteReceivedTime{};
|
||||
};
|
||||
|
||||
// Available BG list (populated by SMSG_BATTLEFIELD_LIST)
|
||||
struct AvailableBgInfo {
|
||||
uint32_t bgTypeId = 0;
|
||||
bool isRegistered = false;
|
||||
bool isHoliday = false;
|
||||
uint32_t minLevel = 0;
|
||||
uint32_t maxLevel = 0;
|
||||
std::vector<uint32_t> instanceIds;
|
||||
};
|
||||
|
||||
// Battleground
|
||||
bool hasPendingBgInvite() const;
|
||||
void acceptBattlefield(uint32_t queueSlot = 0xFFFFFFFF);
|
||||
void declineBattlefield(uint32_t queueSlot = 0xFFFFFFFF);
|
||||
const std::array<BgQueueSlot, 3>& getBgQueues() const { return bgQueues_; }
|
||||
const std::vector<AvailableBgInfo>& getAvailableBgs() const { return availableBgs_; }
|
||||
|
||||
// BG scoreboard (MSG_PVP_LOG_DATA)
|
||||
struct BgPlayerScore {
|
||||
|
|
@ -2475,6 +2486,10 @@ private:
|
|||
// ---- Battleground queue state ----
|
||||
std::array<BgQueueSlot, 3> bgQueues_{};
|
||||
|
||||
// ---- Available battleground list (SMSG_BATTLEFIELD_LIST) ----
|
||||
std::vector<AvailableBgInfo> availableBgs_;
|
||||
void handleBattlefieldList(network::Packet& packet);
|
||||
|
||||
// Instance difficulty
|
||||
uint32_t instanceDifficulty_ = 0;
|
||||
bool instanceIsHeroic_ = false;
|
||||
|
|
|
|||
|
|
@ -5001,7 +5001,7 @@ void GameHandler::handlePacket(network::Packet& packet) {
|
|||
handleBattlefieldStatus(packet);
|
||||
break;
|
||||
case Opcode::SMSG_BATTLEFIELD_LIST:
|
||||
LOG_INFO("Received SMSG_BATTLEFIELD_LIST");
|
||||
handleBattlefieldList(packet);
|
||||
break;
|
||||
case Opcode::SMSG_BATTLEFIELD_PORT_DENIED:
|
||||
addSystemChatMessage("Battlefield port denied.");
|
||||
|
|
@ -13220,6 +13220,80 @@ void GameHandler::handleBattlefieldStatus(network::Packet& packet) {
|
|||
}
|
||||
}
|
||||
|
||||
void GameHandler::handleBattlefieldList(network::Packet& packet) {
|
||||
// SMSG_BATTLEFIELD_LIST wire format by expansion:
|
||||
//
|
||||
// Classic 1.12 (vmangos/cmangos):
|
||||
// bgTypeId(4) isRegistered(1) count(4) [instanceId(4)...]
|
||||
//
|
||||
// TBC 2.4.3:
|
||||
// bgTypeId(4) isRegistered(1) isHoliday(1) count(4) [instanceId(4)...]
|
||||
//
|
||||
// WotLK 3.3.5a:
|
||||
// bgTypeId(4) isRegistered(1) isHoliday(1) minLevel(4) maxLevel(4) count(4) [instanceId(4)...]
|
||||
|
||||
if (packet.getSize() - packet.getReadPos() < 5) return;
|
||||
|
||||
AvailableBgInfo info;
|
||||
info.bgTypeId = packet.readUInt32();
|
||||
info.isRegistered = packet.readUInt8() != 0;
|
||||
|
||||
const bool isWotlk = isActiveExpansion("wotlk");
|
||||
const bool isTbc = isActiveExpansion("tbc");
|
||||
|
||||
if (isTbc || isWotlk) {
|
||||
if (packet.getSize() - packet.getReadPos() < 1) return;
|
||||
info.isHoliday = packet.readUInt8() != 0;
|
||||
}
|
||||
|
||||
if (isWotlk) {
|
||||
if (packet.getSize() - packet.getReadPos() < 8) return;
|
||||
info.minLevel = packet.readUInt32();
|
||||
info.maxLevel = packet.readUInt32();
|
||||
}
|
||||
|
||||
if (packet.getSize() - packet.getReadPos() < 4) return;
|
||||
uint32_t count = packet.readUInt32();
|
||||
|
||||
// Sanity cap to avoid OOM from malformed packets
|
||||
constexpr uint32_t kMaxInstances = 256;
|
||||
count = std::min(count, kMaxInstances);
|
||||
info.instanceIds.reserve(count);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (packet.getSize() - packet.getReadPos() < 4) break;
|
||||
info.instanceIds.push_back(packet.readUInt32());
|
||||
}
|
||||
|
||||
// Update or append the entry for this BG type
|
||||
bool updated = false;
|
||||
for (auto& existing : availableBgs_) {
|
||||
if (existing.bgTypeId == info.bgTypeId) {
|
||||
existing = std::move(info);
|
||||
updated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!updated) {
|
||||
availableBgs_.push_back(std::move(info));
|
||||
}
|
||||
|
||||
const auto& stored = availableBgs_.back();
|
||||
static const std::unordered_map<uint32_t, const char*> kBgNames = {
|
||||
{1, "Alterac Valley"}, {2, "Warsong Gulch"}, {3, "Arathi Basin"},
|
||||
{4, "Nagrand Arena"}, {5, "Blade's Edge Arena"}, {6, "All Arenas"},
|
||||
{7, "Eye of the Storm"}, {8, "Ruins of Lordaeron"},
|
||||
{9, "Strand of the Ancients"}, {10, "Dalaran Sewers"},
|
||||
{11, "The Ring of Valor"}, {30, "Isle of Conquest"},
|
||||
};
|
||||
auto nameIt = kBgNames.find(stored.bgTypeId);
|
||||
const char* bgName = (nameIt != kBgNames.end()) ? nameIt->second : "Unknown Battleground";
|
||||
|
||||
LOG_INFO("SMSG_BATTLEFIELD_LIST: ", bgName, " bgType=", stored.bgTypeId,
|
||||
" registered=", stored.isRegistered ? "yes" : "no",
|
||||
" instances=", stored.instanceIds.size());
|
||||
}
|
||||
|
||||
void GameHandler::declineBattlefield(uint32_t queueSlot) {
|
||||
if (state != WorldState::IN_WORLD) return;
|
||||
if (!socket) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue