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{};
|
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
|
// Battleground
|
||||||
bool hasPendingBgInvite() const;
|
bool hasPendingBgInvite() const;
|
||||||
void acceptBattlefield(uint32_t queueSlot = 0xFFFFFFFF);
|
void acceptBattlefield(uint32_t queueSlot = 0xFFFFFFFF);
|
||||||
void declineBattlefield(uint32_t queueSlot = 0xFFFFFFFF);
|
void declineBattlefield(uint32_t queueSlot = 0xFFFFFFFF);
|
||||||
const std::array<BgQueueSlot, 3>& getBgQueues() const { return bgQueues_; }
|
const std::array<BgQueueSlot, 3>& getBgQueues() const { return bgQueues_; }
|
||||||
|
const std::vector<AvailableBgInfo>& getAvailableBgs() const { return availableBgs_; }
|
||||||
|
|
||||||
// BG scoreboard (MSG_PVP_LOG_DATA)
|
// BG scoreboard (MSG_PVP_LOG_DATA)
|
||||||
struct BgPlayerScore {
|
struct BgPlayerScore {
|
||||||
|
|
@ -2475,6 +2486,10 @@ private:
|
||||||
// ---- Battleground queue state ----
|
// ---- Battleground queue state ----
|
||||||
std::array<BgQueueSlot, 3> bgQueues_{};
|
std::array<BgQueueSlot, 3> bgQueues_{};
|
||||||
|
|
||||||
|
// ---- Available battleground list (SMSG_BATTLEFIELD_LIST) ----
|
||||||
|
std::vector<AvailableBgInfo> availableBgs_;
|
||||||
|
void handleBattlefieldList(network::Packet& packet);
|
||||||
|
|
||||||
// Instance difficulty
|
// Instance difficulty
|
||||||
uint32_t instanceDifficulty_ = 0;
|
uint32_t instanceDifficulty_ = 0;
|
||||||
bool instanceIsHeroic_ = false;
|
bool instanceIsHeroic_ = false;
|
||||||
|
|
|
||||||
|
|
@ -5001,7 +5001,7 @@ void GameHandler::handlePacket(network::Packet& packet) {
|
||||||
handleBattlefieldStatus(packet);
|
handleBattlefieldStatus(packet);
|
||||||
break;
|
break;
|
||||||
case Opcode::SMSG_BATTLEFIELD_LIST:
|
case Opcode::SMSG_BATTLEFIELD_LIST:
|
||||||
LOG_INFO("Received SMSG_BATTLEFIELD_LIST");
|
handleBattlefieldList(packet);
|
||||||
break;
|
break;
|
||||||
case Opcode::SMSG_BATTLEFIELD_PORT_DENIED:
|
case Opcode::SMSG_BATTLEFIELD_PORT_DENIED:
|
||||||
addSystemChatMessage("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) {
|
void GameHandler::declineBattlefield(uint32_t queueSlot) {
|
||||||
if (state != WorldState::IN_WORLD) return;
|
if (state != WorldState::IN_WORLD) return;
|
||||||
if (!socket) return;
|
if (!socket) return;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue