- Add Inventory::FIRST_BAG_EQUIP_SLOT = 19 constant with why-comment
explaining WoW equip slot layout (bags occupy slots 19-22)
- Replace all 19 occurrences of magic number 19 in bag slot calculations
across inventory_handler, spell_handler, inventory, and game_handler
- Add UNIT_FIELD_FLAGS / UNIT_FLAG_PVP comment in combat_handler
- Add why-comment on network packet budget constants (prevent server
data bursts from starving the render loop)
A single send() that returned fewer bytes than requested was logged but
not retried, leaving the server with a truncated packet. This causes an
irreversible TCP framing desync (next header lands mid-payload) that
manifests as a disconnect under network pressure. Added a retry loop
that handles EWOULDBLOCK with a brief yield.
Also rejects payloads > 64KB instead of silently truncating the 16-bit
CMSG size field, which would have written a wrong header while still
appending all bytes.
Warden module download (18756 bytes, 38 chunks of 500 bytes) stalled at
32 chunks because the per-pump packet parse budget was 16 — after two
2ms pump cycles (32 packets), the TCP receive buffer filled and the
server stopped sending. Character list never arrived.
- kDefaultMaxParsedPacketsPerUpdate: 16 → 64
- kDefaultMaxPacketCallbacksPerUpdate: 6 → 48
Also adds WARNING-level diagnostic logs for auth pipeline packets and
Warden module download progress (previously DEBUG-only, invisible in
production logs).
Mail: change money/COD fields from uint32 to uint64 in CMSG_SEND_MAIL and
SMSG_MAIL_LIST_RESULT for WotLK 3.3.5a. Classic keeps uint32 on the wire.
Fixes money truncation and packet misalignment causing mail failures.
Other-player capes: add cape texture loading to setOnlinePlayerEquipment().
The cape geoset was enabled but no texture was loaded, leaving capes blank.
Now mirrors the local-player path: looks up ItemDisplayInfo.dbc, finds cape
texture candidates, applies via setGroupTextureOverride/setTextureSlotOverride.
Zone toasts: suppress duplicate zone toast when the zone text overlay is
already showing the same zone name. Fixes double "Entering: Stormwind City".
Network: enable TCP_NODELAY on both auth and world sockets after connect(),
disabling Nagle's algorithm to eliminate up to 200ms buffering delay on
small packets (movement, spell casts, chat).
Rendering: track material and bone descriptor sets in M2 renderer to skip
redundant vkCmdBindDescriptorSets calls between batches sharing same textures.
The 0x4000 (16384) limit was too conservative and could disconnect the
client when the server sends large packets such as SMSG_GUILD_ROSTER
with 500+ members (~30KB) or SMSG_AUCTION_LIST with many results.
Increase to 0x8000 (32768) which covers all normal gameplay while still
protecting against framing desync from encryption errors.
Move 5-second brute-force HMAC-SHA1 code pattern searches to a
background thread via std::async. The main loop now detects PAGE_A/B
checks, launches the response builder async, and drains the result
in update() — encrypting and sending on the main thread to keep
wardenCrypto_ RC4 state thread-safe.
Also adds Turtle WoW PE binary support (isTurtle flag, dedicated exe
search, runtime patches), searchCodePattern with result caching,
writeLE32 public API, and Warden scan entry verification.
Socket fixes (fixes Windows-only connection failure):
- WorldSocket::connect() now waits for non-blocking connect to complete with
select() before returning, preventing WSAENOTCONN on the first recv() call
on Windows (Linux handles this implicitly but Windows requires writability
poll after non-blocking connect)
- Add net::isConnectionClosed() helper: treats WSAENOTCONN/WSAECONNRESET/
WSAESHUTDOWN/WSAECONNABORTED as graceful peer-close rather than recv errors
- Apply isConnectionClosed() in both WorldSocket and TCPSocket recv loops
UI:
- Add renderBossFrames(): displays boss unit health bars in top-right corner
when SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT has active slots; supports
click-to-target and color-coded health bars (red→orange→yellow as HP drops)
- keep character-selection state until world entry load/finalize completes
- move expensive post-load setup (test transport + creature callback prep) before loading screen shutdown
- add bounded world warmup pass under loading screen to drain initial network/spawn backlog
- start intro camera pan after warmup so rotation begins when gameplay becomes visible
- guard test transport setup so it runs once per session
- add per-update world socket parse budget to prevent single-frame packet-drain stalls
This reduces visible 3-4s stutter after login by shifting startup work behind the loading screen and time-slicing packet processing.
The old `// lgtm [cpp/...]` comments used a space (invalid syntax) and
were placed on preceding lines rather than inline with the flagged code.
GitHub's CodeQL action v3 requires `// codeql[query-id]` on the same
line as the flagged expression. All four alert sites updated:
- world_socket.cpp: encryptCipher/decryptCipher.init() (protocol RC4)
- warden_module.cpp: decryptRC4() call (Warden protocol RC4)
- warden_crypto.cpp: initRC4() calls (Warden stream cipher init)
- game_handler.cpp: wardenLoadedModule_->load() (MD5+RC4 via Warden)
All uses are protocol-mandated by Blizzard's WoW/Warden spec and cannot
be replaced without breaking server interoperability.
- game_handler.cpp: use-after-move on node.id after std::move(node)
(save nodeId before the move)
- tcp_socket.cpp, world_socket.cpp: virtual call in destructor bypasses
dispatch; use qualified TCPSocket::disconnect() / WorldSocket::disconnect()
to make intent explicit
- wmo_renderer.cpp: float loop counters risk precision drift; replace with
integer step counts and reconstruct float from index
- game_screen.cpp: (float + 0.5) cast to int is incorrect rounding;
use std::lround instead
Implement full mail send/receive: SMSG_SHOW_MAILBOX, CMSG_GET_MAIL_LIST,
SMSG_MAIL_LIST_RESULT, CMSG_SEND_MAIL, SMSG_SEND_MAIL_RESULT, mail take
money/item/delete/mark-as-read, and inbox/compose UI windows.
Fix periodic stuttering in Stormwind caused by synchronous per-line disk
flushes in the logger — remove fileStream.flush() and std::endl, downgrade
high-volume per-packet/per-model/per-texture LOG_INFO to LOG_DEBUG.
- Vanilla M2 bone struct (108 bytes) with 28-byte animation tracks
- Version-aware bone parsing (vanilla vs WotLK format detection)
- Fix CharSections.dbc field layout for vanilla (variation/color at 4-5)
- Remove broken CharSections.csv files (all fields marked as strings)
- Expansion data reload on profile switch (DBC cache clear, layout reload)
- Vanilla packet encryption (VanillaCrypt XOR-based header crypt)
- Extended character preview geoset range (0-99) for vanilla models
- DBC cache clear support in AssetManager
Split inventory into bags-only (B key) and character screen (C key). Vendor window
auto-opens bags with sell prices on hover and right-click to sell. Add camera intro
pan on all login/spawn/teleport/hearthstone events and idle orbit after 2 minutes.
Add quest log UI, SMSG_MONSTER_MOVE handling, deferred creature spawn queue, and
creature fade-in/movement interpolation for online mode.
- Fix encryption desync by tracking decrypted header bytes in world socket
- Fix UPDATE_OBJECT movement block parsing to handle 3.3.5a update flags
- Fix UNIT_FIELD_DISPLAYID index (67, not 71)
- Add creature spawn/despawn callbacks with DBC-based model loading
- Add SMSG_COMPRESSED_UPDATE_OBJECT opcode support
- Use 6-byte CMSG header (uint16 size + uint32 opcode) for client-to-server
- Enable RC4 encryption immediately after sending AUTH_SESSION
- Encrypt all 6 header bytes to match AzerothCore expectations
- Add 8-byte addon info (addonCount + clientTime) for proper parsing
- Fix CharCreateResult enum to use correct WoW 3.3.5a response codes
- Add CHAR_NAME_* error codes for name validation messages
- Allow character list refresh from CHAR_LIST_RECEIVED state
Replace POSIX-specific socket and process APIs with portable
abstractions so the project builds on both Windows and Linux.
- Add include/network/net_platform.hpp: Winsock2/POSIX socket
abstraction (socket types, non-blocking, error handling,
WSAStartup lifecycle)
- Add include/platform/process.hpp: CreateProcess/fork+exec
abstraction for spawning ffplay subprocesses
- Update network module (tcp_socket, world_socket) to use
portable socket helpers instead of raw POSIX calls
- Update audio module (music_manager, footstep_manager,
activity_sound_manager) to use portable process helpers
instead of fork/exec/kill/waitpid
- Replace hardcoded /tmp/ paths with std::filesystem::temp_directory_path()
- Link ws2_32 and SDL2main on Windows in CMakeLists.txt