Implement SMSG_RAID_INSTANCE_INFO handler to track instance lockouts

Parse and store dungeon/raid lockout data sent on login:
- mapId, difficulty, resetTime (Unix timestamp), locked, extended flags
- Stored in instanceLockouts_ vector for UI / LFG / dungeon state queries
- Public InstanceLockout struct + getInstanceLockouts() accessor
This commit is contained in:
Kelsi 2026-03-09 13:36:23 -07:00
parent b33831d833
commit 8f7c4a58cd
2 changed files with 42 additions and 2 deletions

View file

@ -707,6 +707,16 @@ public:
bool hasPendingGroupInvite() const { return pendingGroupInvite; }
const std::string& getPendingInviterName() const { return pendingInviterName; }
// ---- Instance lockouts ----
struct InstanceLockout {
uint32_t mapId = 0;
uint32_t difficulty = 0; // 0=normal,1=heroic/10man,2=25man,3=25man heroic
uint64_t resetTime = 0; // Unix timestamp of instance reset
bool locked = false;
bool extended = false;
};
const std::vector<InstanceLockout>& getInstanceLockouts() const { return instanceLockouts_; }
// ---- LFG / Dungeon Finder ----
enum class LfgState : uint8_t {
None = 0,
@ -1230,6 +1240,9 @@ private:
void loadAreaTriggerDbc();
void checkAreaTriggers();
// ---- Instance lockout handler ----
void handleRaidInstanceInfo(network::Packet& packet);
// ---- LFG / Dungeon Finder handlers ----
void handleLfgJoinResult(network::Packet& packet);
void handleLfgQueueStatus(network::Packet& packet);
@ -1566,6 +1579,9 @@ private:
uint32_t instanceDifficulty_ = 0;
bool instanceIsHeroic_ = false;
// Instance / raid lockouts
std::vector<InstanceLockout> instanceLockouts_;
// LFG / Dungeon Finder state
LfgState lfgState_ = LfgState::None;
uint32_t lfgDungeonId_ = 0; // current dungeon entry

View file

@ -1848,8 +1848,7 @@ void GameHandler::handlePacket(network::Packet& packet) {
packet.setReadPos(packet.getSize());
break;
case Opcode::SMSG_RAID_INSTANCE_INFO:
// Raid lockout list (not yet surfaced in UI).
packet.setReadPos(packet.getSize());
handleRaidInstanceInfo(packet);
break;
case Opcode::SMSG_DUEL_REQUESTED:
// Duel request UI flow not implemented yet.
@ -8847,6 +8846,31 @@ void GameHandler::acceptBattlefield(uint32_t queueSlot) {
LOG_INFO("Sent CMSG_BATTLEFIELD_PORT: accept bgTypeId=", slot->bgTypeId);
}
void GameHandler::handleRaidInstanceInfo(network::Packet& packet) {
// SMSG_RAID_INSTANCE_INFO: uint32 count, then for each:
// mapId(u32) + difficulty(u32) + resetTime(u64) + locked(u8) + extended(u8)
if (packet.getSize() - packet.getReadPos() < 4) return;
uint32_t count = packet.readUInt32();
instanceLockouts_.clear();
instanceLockouts_.reserve(count);
constexpr size_t kEntrySize = 4 + 4 + 8 + 1 + 1;
for (uint32_t i = 0; i < count; ++i) {
if (packet.getSize() - packet.getReadPos() < kEntrySize) break;
InstanceLockout lo;
lo.mapId = packet.readUInt32();
lo.difficulty = packet.readUInt32();
lo.resetTime = packet.readUInt64();
lo.locked = packet.readUInt8() != 0;
lo.extended = packet.readUInt8() != 0;
instanceLockouts_.push_back(lo);
LOG_INFO("Instance lockout: mapId=", lo.mapId, " diff=", lo.difficulty,
" reset=", lo.resetTime, " locked=", lo.locked, " extended=", lo.extended);
}
LOG_INFO("SMSG_RAID_INSTANCE_INFO: ", instanceLockouts_.size(), " lockout(s)");
}
void GameHandler::handleInstanceDifficulty(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 8) return;
instanceDifficulty_ = packet.readUInt32();