Commit graph

1391 commits

Author SHA1 Message Date
Kelsi
e26ed39da8 fix(combat): add diagnostic logging to handleAttackerStateUpdate
Log parse failures with remaining packet size and successful parses with
attacker/target/player GUIDs, damage, and callback status to diagnose
why meleeSwingCallback is never invoked during auto-attack.
2026-04-05 18:54:01 -07:00
Kelsi
696baffdf7 fix(movement): upgrade teleport and heartbeat diagnostics to WARNING
MSG_MOVE_TELEPORT_ACK now logs server-sent coordinates AND current
position at WARNING level (was LOG_INFO, invisible in log file).
Heartbeat position audit now logs every ~60 heartbeats (~30s) at
WARNING level to trace position drift before rogue teleports.
2026-04-05 17:39:56 -07:00
Kelsi
aff545edef fix(rendering): emote animations, WMO portal culling, transport teleport
Emote animations: fix DBC chain for /laugh, /flirt, /sleep, /fart, /stink.
Previously all emotes with AnimID=0 used emoteRef as animId (wrong DBC
record IDs). Now resolves through Emotes.dbc properly, with per-emote
overrides for emotes whose DBC chain yields 0. Adds Emotes.dbc load
failure warning and diagnostic logging.

WMO culling: skip portal culling when camera is outside all groups (fixes
vanishing Stormwind ground tiles). Also handle indoor/outdoor AABB overlap
by showing all groups when position is in both indoor and outdoor AABBs.

Transport: clear ONTRANSPORT flag and transport state when transport not
found, preventing stale transport data from teleporting player to map
origin. Add area trigger safety net near (0,0,0) on Eastern Kingdoms.
2026-04-05 17:25:25 -07:00
Kelsi
fe29ccad3f fix(transport): guard against untracked transport placing player at map origin
When on-transport flag is set but the transport isn't tracked by
TransportManager, getPlayerWorldPosition() returns localOffset (a small
relative value) as a world position. This overwrites movementInfo with
near-zero coordinates, teleporting the player to map origin on Eastern
Kingdoms (Alterac/Hillsbrad area). Add transport existence checks in
sendMovement() and getComposedWorldPosition() before composing position.
2026-04-05 16:01:14 -07:00
Kelsi
a23c2172a8 fix(chat): handle SMSG_GM_MESSAGECHAT format, add chat diagnostics
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
SMSG_GM_MESSAGECHAT has an extra gmNameLen+gmName field after the
standard header that was causing misaligned parsing for non-whisper GM
messages. Strip the GM name before forwarding to the regular parser.

Also improve party state notifications (show member names on join) and
add INFO-level logging for all incoming/outgoing chat messages and
WARNING-level logging for group invite/accept packets to diagnose
recurring phantom party state issues.
2026-04-05 05:16:57 -07:00
Kelsi
e4bd380c0d fix(chat): prevent AFK/DND auto-reply whisper spam loop
Auto-reply was sent on every incoming whisper with no dedup, causing
infinite loops when both players had auto-reply enabled. Now tracks
which senders have been replied to and only sends one auto-reply per
sender per AFK/DND session.
2026-04-05 04:50:40 -07:00
Kelsi
19bfaaef97 fix(movement): stop spoofing player position for area triggers
The area trigger system was temporarily moving the player to the trigger
center and sending a heartbeat before firing CMSG_AREATRIGGER. This told
the server the player was at a different location, causing unexpected
teleports (e.g. Stormwind to Hillsbrad). Just send the area trigger
packet directly — the player is already inside the trigger radius.
2026-04-05 04:40:46 -07:00
Kelsi
e4c4b6f429 fix(ui): use display name from Map.dbc field 4 instead of internal name
Was reading field 2 (InstanceType) which fell back to field 1 (internal
name like "Azeroth"). Field 4 has the localized display name ("Eastern
Kingdoms").
2026-04-05 04:32:10 -07:00
Kelsi
535ae8aa89 fix(ui): resolve map 0 name and allow guild queries at character screen
getMapName() returned empty for mapId 0 (Eastern Kingdoms) due to an
early return guard. Remove it since 0 is a valid map ID.

queryGuildInfo() required IN_WORLD state but the character screen is at
CHAR_LIST_RECEIVED. The server accepts CMSG_GUILD_QUERY before login,
so just check for a connected socket.
2026-04-05 04:30:32 -07:00
Kelsi
2e30490fc5 fix(ui): show guild name and zone name on character select screen
Load area names from AreaTable.dbc (canonical zone names) in addition
to WorldMapArea.dbc so zone IDs from SMSG_CHAR_ENUM resolve to names.
Use lookupGuildName() to query and display guild names instead of raw
guild IDs.
2026-04-05 04:28:36 -07:00
Kelsi
35be19e74c fix(mail): route GO mailbox open through InventoryHandler
The decomposition PRs moved mail state to InventoryHandler but the GO
interaction code still set stale GameHandler fields. Add openMailbox()
on InventoryHandler and forward from GameHandler so the correct
mailboxGuid_/mailboxOpen_ are set and refreshMailList() works.
2026-04-05 04:22:48 -07:00
Kelsi
62f3f515e2 fix(mail): let SMSG_SHOW_MAILBOX open mailbox instead of stale GameHandler fields
GO interaction was setting the old GameHandler mailbox state instead of
InventoryHandler's, so refreshMailList saw mailboxGuid_=0 and bailed.
2026-04-05 04:17:55 -07:00
Kelsi
53244d025c feat(repair): DBC-based repair cost estimation and UI display
Calculate repair costs client-side using DurabilityCosts.dbc and
DurabilityQuality.dbc. Block repair when player can't afford it and
only apply optimistic durability/gold updates when cost is verified.
Show repair cost next to the Repair All button in the vendor window.
2026-04-05 04:15:48 -07:00
Kelsi
1dd1a431f4 fix(repair): process item durability updates even when entity missing from manager
handleValuesUpdate silently dropped VALUES updates for item GUIDs not in
entityManager, causing repair-all durability changes to be lost. Fall
through to updateItemOnValuesUpdate for items tracked in onlineItems_.
2026-04-05 03:15:03 -07:00
Pavel Okhlopkov
e386fbb069
Merge branch 'master' into feat/animation-handling 2026-04-05 12:37:08 +03:00
Kelsi
0d188edd75 fix(areatrigger): use actual DBC dimensions instead of inflated minimums
The minimum floor (3.0 for sphere radius, 4.0 for box dimensions) was
inflating narrow triggers like AT 5711 (boxWidth 1.06 → 4.0), causing
false area trigger fires near the Stormwind AH and unexpected teleports.
2026-04-05 02:35:47 -07:00
Paul
b4989dc11f feat(animation): decompose AnimationController into FSM-based architecture
Replace the 2,200-line monolithic AnimationController (goto-driven,
single class, untestable) with a composed FSM architecture per
refactor.md.

New subsystem (src/rendering/animation/ — 16 headers, 10 sources):
- CharacterAnimator: FSM composer implementing ICharacterAnimator
- LocomotionFSM: idle/walk/run/sprint/jump/swim/strafe
- CombatFSM: melee/ranged/spell cast/stun/hit reaction/charge
- ActivityFSM: emote/loot/sit-down/sitting/sit-up
- MountFSM: idle/run/flight/taxi/fidget/rear-up (per-instance RNG)
- AnimCapabilitySet + AnimCapabilityProbe: probe once at model load,
  eliminate per-frame hasAnimation() linear search
- AnimationManager: registry of CharacterAnimator by GUID
- EmoteRegistry: DBC-backed emote command → animId singleton
- FootstepDriver, SfxStateDriver: extracted from AnimationController

animation_ids.hpp/.cpp moved to animation/ subdirectory (452 named
constants); all include paths updated.

AnimationController retained as thin adapter (~400 LOC): collects
FrameInput, delegates to CharacterAnimator, applies AnimOutput.

Priority order: Mount > Stun > HitReaction > Spell > Charge >
Melee/Ranged > CombatIdle > Emote > Loot > Sit > Locomotion.
STAY_IN_STATE policy when all FSMs return valid=false.

Bugs fixed:
- Remove static mt19937 in mount fidget (shared state across all
  mounted units) — replaced with per-instance seeded RNG
- Remove goto from mounted animation branch (skipped init)
- Remove per-frame hasAnimation() calls (now one probe at load)
- Fix VK_INDEX_TYPE_UINT16 → UINT32 in shadow pass

Tests (4 new suites, all ASAN+UBSan clean):
- test_locomotion_fsm: 167 assertions
- test_combat_fsm: 125 cases
- test_activity_fsm: 112 cases
- test_anim_capability: 56 cases

docs/ANIMATION_SYSTEM.md added (architecture reference).
2026-04-05 12:27:35 +03:00
Paul
e58f9b4b40 feat(animation): 452 named constants, 30-phase character animation state machine
Add animation_ids.hpp/cpp with all 452 WoW animation ID constants (anim::STAND,
anim::RUN, anim::FIRE_BOW, ... anim::FLY_BACKWARDS, etc.), nameFromId() O(1)
lookup, and flyVariant() compact 218-element ground→FLY_* resolver.

Expand AnimationController into a full state machine with 20+ named states:
spell cast (directed→omni→cast fallback chain, instant one-shot release),
hit reactions (WOUND/CRIT/DODGE/BLOCK/SHIELD_BLOCK), stun, wounded idle,
stealth animation substitution, loot, fishing channel, sit/sleep/kneel
down→loop→up transitions, sheathe/unsheathe combat enter/exit, ranged weapons
(BOW/GUN/CROSSBOW/THROWN with reload states), game object OPEN/CLOSE/DESTROY,
vehicle enter/exit, mount flight directionals (FLY_LEFT/RIGHT/UP/DOWN/BACKWARDS),
emote state variants, off-hand/pierce/dual-wield alternation, NPC
birth/spawn/drown/rise, sprint aura override, totem idle, NPC greeting/farewell.

Add spell_defines.hpp with SpellEffect (~45 constants) and SpellMissInfo
(12 constants) namespaces; replace all magic numbers in spell_handler.cpp.

Add GAMEOBJECT_BYTES_1 to update field table (all 4 expansion JSONs) and wire
GameObjectStateCallback. Add DBC cross-validation on world entry.

Expand tools/_ANIM_NAMES from ~35 to 452 entries in m2_viewer.py and
asset_pipeline_gui.py. Add tests/test_animation_ids.cpp.

Bug fixes included:
- Stand state 1 was animating READY_2H(27) — fixed to SITTING(97)
- Spell casts ended freeze-frame — add one-shot release animation
- NPC 2H swing probe chain missing ATTACK_2H_LOOSE (polearm/staff)
- Chair sits (states 2/4/5/6) incorrectly played floor-sit transition
- STOP(3) used for all spell casts — replaced with model-aware chain
2026-04-04 23:02:53 +03:00
k
b3fa8cf5f3 fix: warden mmap on macOS, add external listfile support to asset extractor
Drop PROT_EXEC from warden module mmap when using Unicorn emulation
(not needed — module image is copied into emulator address space). Use
MAP_JIT on macOS for the native fallback path.

Add --listfile option to asset_extract and SFileAddListFileEntries
support for resolving unnamed MPQ hash table entries from external
listfiles.
2026-04-04 00:22:07 -07:00
Kelsi
5538655383 fix(chat): resolve /r reply target when name arrives after whisper
Whisper sender name may not be in the player name cache when the packet
arrives. Store the sender GUID and lazily resolve the name from the
cache in getLastWhisperSender(). Also backfill lastWhisperSender_ when
the SMSG_NAME_QUERY_RESPONSE arrives.
2026-04-04 00:03:19 -07:00
Kelsi
100394a743 fix(rendering,game): init bone SSBO to identity; stop movement before cast
Bone SSBO buffers were allocated for MAX_BONES (240) entries but only
the first numBones were written. Uninitialized GPU memory in the
remaining slots caused vertex spikes when any bone index exceeded the
model's actual bone count.

Also send MSG_MOVE_STOP before spell casts so the server doesn't reject
cast-time spells (e.g. hearthstone) with "can't do that while moving".
2026-04-04 00:03:19 -07:00
Kelsi
def821055b fix(parsing): validate spline endPoint coords to reject false-positive format matches
The WotLK spline parser tries 6 format variants and accepts the first
that passes minimal validation (pointCount<=256, splineMode<=3). A wrong
format can pass by coincidence, consuming incorrect bytes and corrupting
all subsequent UPDATE_OBJECT blocks (e.g. maskBlockCount=219 garbage).

Add endPoint coordinate validation: reject spline parses where the
endpoint is non-finite or outside world bounds (65k). Also harden the
Turtle parser to keep successfully-parsed blocks on mid-packet failure
instead of discarding the entire packet.
2026-04-03 19:36:34 -07:00
Kelsi
345b41b810 fix(auction): resolve item GUID with fallback and gate packet format
auctionSellItem now resolves the item GUID internally via
backpackSlotGuids_ with resolveOnlineItemGuid fallback, matching the
pattern used by vendor sell and item use. Previously the UI passed
the GUID directly from getBackpackItemGuid() with no fallback, so
items with unset slot GUIDs silently failed to list.

Also gates CMSG_AUCTION_SELL_ITEM format by expansion: Classic/TBC
omits the itemCount and stackCount fields that WotLK requires.
2026-04-03 18:46:49 -07:00
Kelsi
8fd4dccf6b fix(vendor): preserve repair flag across ListInventory parse
ListInventoryParser::parse() was resetting the entire ListInventoryData
struct, wiping the canRepair flag set by the gossip handler before the
server response arrived. Preserve it across the parse.

Also detect repair capability from UNIT_NPC_FLAG_REPAIR (0x1000) on the
vendor NPC entity, so direct vendors without gossip menus also show the
repair button.
2026-04-03 18:18:53 -07:00
Kelsi
06a83537cf chore: re-remove dead functions reintroduced by PR #39 merge
The Lua refactor branch was based before the cleanup commit and
brought back allMacroCommands, getMacroShowtooltipArg (game_screen),
lfgJoinResultString, lfgTeleportDeniedString (game_handler).
2026-04-03 03:37:22 -07:00
Paul
a2814ab082 Merge commit '7f4c274e35' into chore/refactor-lua-engine 2026-04-03 07:35:57 +03:00
Paul
a916270a13 chore(lua): refactor addon Lua engine API + progress docs
- Refactor Lua addon integration:
  - Update CMakeLists.txt for addon build paths
  - Enhance addons API headers and Lua engine interface
  - Add new Lua API addon modules (`lua_api_helpers`, `lua_api_registrations`, `lua_services`, `lua_action_api`, `lua_inventory_api`, `lua_quest_api`, `lua_social_api`, `lua_spell_api`, `lua_system_api`, `lua_unit_api`)
  - Update implementation in addon_manager.cpp, lua_engine.cpp, application.cpp, game_handler.cpp
2026-04-03 07:31:06 +03:00
Kelsi
fe1c4c622b chore: remove dead functions left behind by handler extractions
685 lines of unused code duplicated into extracted handler files
(entity_controller, spell_handler, quest_handler, warden_handler,
social_handler, action_bar_panel, chat_panel, window_manager)
during PRs #33-#38. Build is now warning-free.
2026-04-02 14:47:04 -07:00
Paul
5af9f7aa4b chore(renderer): extract AnimationController and remove audio pass-throughs
Extract ~1,500 lines of character animation state from Renderer into a dedicated
AnimationController class, and complete the AudioCoordinator migration by removing
all 10 audio pass-through getters from Renderer.

AnimationController:
- New: include/rendering/animation_controller.hpp (182 lines)
- New: src/rendering/animation_controller.cpp (1,703 lines)
- Moves: locomotion state machine (50+ members), mount animation (40+ members),
  emote system, footstep triggering, surface detection, melee combat animations
- Renderer holds std::unique_ptr<AnimationController> and delegates completely
- AnimationController accesses audio via renderer_->getAudioCoordinator()

Audio caller migration:
- Migrate ~60 external callers from renderer->getXManager() to AudioCoordinator
  directly, grouped by access pattern:
  - UIServices: settings_panel, game_screen, toast_manager, chat_panel,
    combat_ui, window_manager
  - GameServices: game_handler, spell_handler, inventory_handler, quest_handler,
    social_handler, combat_handler
  - Application singleton: application.cpp, auth_screen.cpp, lua_engine.cpp
- Remove 10 pass-through getter definitions from renderer.cpp
- Remove 10 pass-through getter declarations from renderer.hpp
- Remove individual audio manager forward declarations from renderer.hpp
- Redirect 69 internal renderer.cpp audio calls to audioCoordinator_ directly
- game_handler.cpp: withSoundManager template uses services_.audioCoordinator;
  MFP changed from &Renderer::getUiSoundManager to &AudioCoordinator::getUiSoundManager
- GameServices struct: add AudioCoordinator* audioCoordinator member
- settings_panel: applyAudioVolumes(Renderer*) -> applyAudioVolumes(AudioCoordinator*)
2026-04-02 13:06:31 +03:00
Paul
b6e4e405b6 Merge commit 'ea8b0d9305' into chore/game-screen-extract 2026-03-31 20:17:21 +03:00
Paul
0e6aaeb44e fix warnings, remove phases from commentaries 2026-03-31 20:11:28 +03:00
Kelsi
5ad225313d fix: revert Warden HASH_RESULT fallback — silence is correct behavior
ChromieCraft/AzerothCore tolerates no HASH_RESULT response (continues
session without Warden checks), but immediately kicks on a WRONG hash.
The previous commit sent a fallback SHA1 which the server rejected,
breaking login that was working before.

Restore the skip behavior for WotLK/TBC: stay silent on HASH_REQUEST
when no CR match exists, and advance to WAIT_CHECKS so the rest of the
session proceeds normally. Turtle/Classic servers still get the fallback
hash since they're lenient about wrong values.
2026-03-31 01:18:58 -07:00
Kelsi
f3f7511105 fix: send Warden HASH_RESULT fallback instead of skipping response
Previously, WotLK/TBC servers with no CR match would skip the
HASH_REQUEST response entirely to "avoid account bans". This caused
a guaranteed kick-on-timeout for ALL WotLK servers including
permissive ones like ChromieCraft/AzerothCore.

Now sends a best-effort fallback hash (SHA1 of module image or raw
data) for all server types. Permissive servers accept this and
continue the session normally. Strict servers (Warmane) will reject
it but only kick — same outcome as the previous skip behavior, just
faster feedback.

For strict servers, the correct fix remains providing a .cr file
with pre-computed seed→reply entries for each module.
2026-03-31 01:10:43 -07:00
Kelsi
681e25a4f2 fix: clean up unused parameter style in entity_controller
Use nameless parameters instead of /*comment*/ syntax for unused
args in IObjectTypeHandler interface defaults and overrides.
2026-03-31 00:55:40 -07:00
Kelsi
11561184e6 fix: silence all -Wunused-parameter warnings in entity_controller
Suppress 9 unused parameter warnings in IObjectTypeHandler interface
methods and their overrides by commenting out parameter names:
- Base class: onCreate/onValuesUpdate/onMovementUpdate default empty
  implementations (parameters intentionally unused in base)
- ItemTypeHandler::onCreate: entity param forwarded only to onCreateItem
  which doesn't need it
- CorpseTypeHandler::onCreate: entity param not needed for corpse spawn

Build now produces zero warnings (excluding third-party stb headers).
2026-03-31 00:48:03 -07:00
Kelsi
32bb0becc8 fix: replace placeholder Warden RSA modulus with real Blizzard key
Replace the incorrectly extracted RSA-2048 modulus (which contained
the exponent bytes embedded inside it) with the verified Blizzard
public key used across all pre-Cataclysm clients (1.12.1, 2.4.3,
3.3.5a).

Key confirmed against two independent sources:
- namreeb/WardenSigning ClientKey.hpp (72 verified sniffed modules)
- SkullSecurity wiki Warden_Modules documentation

The modulus starts with 0x6BCE F52D... and ends with ...03F4 AFC7.
Exponent remains 65537 (0x010001).

Verification algorithm: SHA1(module_data + "MAIEV.MOD"), 0xBB-padded
to 256 bytes, RSA verify-recover with raw (no-padding) mode.

Signature failures are non-fatal (log warning, continue loading) so
private-server modules signed with custom keys still work. This is
necessary because servers like ChromieCraft/AzerothCore may use their
own signing keys.

Also update warden_module.hpp status: all implementation items now .
2026-03-30 22:50:47 -07:00
Kelsi
88d047d2fb feat: implement Warden API binding / IAT patching for module imports
Complete the last major Warden stub — the import table parser that
resolves Windows API calls in loaded modules. This is the critical
missing piece for strict servers like Warmane.

Implementation:
- Parse Warden module import table from decompressed data (after
  relocation entries): alternating libraryName\0 / functionName\0
  pairs, terminated by null library name
- For each import, look up the emulator's pre-registered stub address
  (VirtualAlloc, GetTickCount, ReadProcessMemory, etc.)
- Auto-stub unrecognized APIs with a no-op returning 0 — prevents
  module crashes on unimplemented Windows functions
- Patch each IAT slot (sequential dwords at module image base) with
  the resolved stub address
- Add WardenEmulator::getAPIAddress() public accessor for IAT lookups
- Fix initialization order: bindAPIs() now runs inside initializeModule()
  after emulator setup but before entry point call

The full Warden pipeline is now: RC4 decrypt → RSA verify → zlib
decompress → parse executable → relocate → create emulator → register
API hooks → bind imports (IAT patch) → call entry point → extract
exported functions (packetHandler, tick, generateRC4Keys, unload).
2026-03-30 22:38:05 -07:00
Kelsi
248d131af7 feat: implement Warden module callbacks (sendPacket, validateModule, generateRC4)
Implement the three stubbed Warden module callbacks that were previously
TODO placeholders:

- **sendPacket**: Encrypts module output via WardenCrypto RC4 and sends
  as CMSG_WARDEN_DATA through the game socket. Enables modules to send
  responses back to the server (required for strict servers like Warmane).

- **validateModule**: Compares the module's provided 16-byte MD5 hash
  against the hash received during download. Logs error on mismatch
  (indicates corrupted module transit).

- **generateRC4**: Derives new encrypt/decrypt RC4 keys from a 16-byte
  seed using SHA1Randx, then replaces the active WardenCrypto key state.
  Handles mid-session re-keying requested by the module.

Architecture:
- Add setCallbackDependencies() to inject WardenCrypto* and socket send
  function into WardenModule before load() is called
- Use thread_local WardenModule* so C function pointer callbacks (which
  can't capture state) can reach the module's dependencies during init
- Wire dependencies from WardenHandler before module load

Also update warden_module.hpp status markers — RSA verification, zlib,
executable parsing, relocation, and Unicorn emulation are all implemented
(were incorrectly marked as TODO). Only API binding/IAT patching and
RSA modulus verification against real WoW.exe remain as gaps.
2026-03-30 20:29:26 -07:00
Kelsi
2c50cc94e1 docs: add why-comments to TBC parsers, bell audio, portrait preview
- packet_parsers_tbc: explain spline waypoint cap (DoS prevention),
  spline compression flags (Catmull-Rom 0x80000 / linear 0x2000 use
  uncompressed format, others use packed delta), spell hit target cap
  (128 >> real AOE max of ~20), guild roster cap (1000 safety limit)
- ambient_sound_manager: explain 1.5s bell toll spacing — matches
  retail WoW cadence, allows each toll to ring out before the next
- character_preview.hpp: explain 4:5 portrait aspect ratio for
  full-body character display in creation/selection screen
2026-03-30 17:26:13 -07:00
Kelsi
92369c1cec docs: add why-comments to rendering, packets, and UI code
- charge_effect: explain inversesqrt guard (prevents NaN on stationary
  character) and dust accumulator rate (30 particles/sec * 16ms)
- swim_effects: explain why insect pipeline disables depth test
  (screen-space sprites must render above water geometry)
- packet_parsers_classic: explain spline waypoint cap (DoS prevention)
  and packed GUID compression format (non-zero bytes only, mask byte)
- talent_screen: explain class ID to bitmask conversion (1-indexed
  WoW class IDs → power-of-2 mask for TalentTab.classMask matching)
- auth_screen: explain login music volume reduction (80% so UI sounds
  remain audible over background track)
2026-03-30 17:23:07 -07:00
Kelsi
e8a4a7402f fix: clamp player percentage stats, add scale field why-comment
- entity_controller: clamp block/dodge/parry/crit/rangedCrit percentage
  fields to [0..100] after memcpy from update fields — guards against
  NaN/Inf from corrupted packets reaching the UI renderer
- entity_controller: add why-comment on OBJECT_FIELD_SCALE_X raw==0
  check — IEEE 754 0.0f is all-zero bits, so raw==0 means the field
  was never populated; keeping default 1.0f prevents invisible entities
2026-03-30 15:48:30 -07:00
Kelsi
fe7912b5fa fix: prevent buffer overflows in Warden PE parsing
- Add bounds checks to readLE32/readLE16 — malformed Warden modules
  could cause out-of-bounds reads on untrusted PE data
- Fix unsigned underflow in PE section loading: if rawDataOffset or
  virtualAddr exceeds buffer size, the subtraction wrapped to a huge
  uint32_t causing memcpy to read/write far beyond bounds. Now skips
  the section entirely and uses std::min with pre-validated maxima
2026-03-30 15:33:03 -07:00
Kelsi
b39f0f3605 refactor: name GUID type and LFG role constants, add why-comments
- world_packets: name kGuidTypeMask/kGuidTypePet/kGuidTypeVehicle
  for chat receiver GUID type detection, with why-comment explaining
  WoW's bits-48-63 entity type encoding and 0xF0FF mask purpose
- lua_engine: name kRoleTank/kRoleHealer/kRoleDamager (0x02/0x04/0x08)
  for WotLK LFG role bitmask, add context on Leader bit (0x01) and
  source packets (SMSG_GROUP_LIST / SMSG_LFG_ROLE_CHECK_UPDATE)
2026-03-30 15:28:18 -07:00
Kelsi
a389fd2ef4 refactor: name SRP/Warden crypto constants, add why-comments
- srp: name kEphemeralBytes (19 = 152 bits, matches Blizzard client)
  and kMaxEphemeralAttempts (100) with why-comment explaining A != 0
  mod N requirement and near-zero failure probability
- warden_module: add why-comment on 0x400000 module base (default
  PE image base for 32-bit Windows executables)
- warden_module: name kRsaSignatureSize (256 = RSA-2048) with
  why-comment explaining signature stripping (placeholder modulus
  can't verify Blizzard's signatures)
2026-03-30 15:12:27 -07:00
Kelsi
d2a7d79f60 refactor: add why-comments to zone tiles, audio cache, socket buffer
- zone_manager: document tile-to-zone key encoding (tileX * 100 + tileY,
  safe because tileY < 64 < 100) and explain that ranges are empirically
  derived from the retail WoW map grid
- audio_engine: expand sample rate comment — miniaudio defaults to
  device rate causing pitch distortion if not set explicitly; name
  kMaxCachedSounds constant with memory budget explanation
- tcp_socket: add why-comment on 4 KB recv buffer sizing — covers
  typical 20-500 byte packets and worst-case ~2 KB UPDATE_OBJECT
2026-03-30 14:52:51 -07:00
Kelsi
8c7db3e6c8 refactor: name FNV-1a/transport constants, fix dead code, add comments
- vk_context: name FNV-1a hash constants (kFnv1aOffsetBasis/kFnv1aPrime)
  with why-comment on algorithm choice for sampler cache
- transport_manager: collapse redundant if/else that both set
  looping=false into single unconditional assignment, add why-comment
  explaining the time-closed path design
- transport_manager: hoist duplicate kMinFallbackZOffset constants out
  of separate if-blocks, add why-comment on icebreaker Z clamping
- entity: expand velocity smoothing comment — explain 65/35 EMA ratio
  and its tradeoff (jitter suppression vs direction change lag)
2026-03-30 14:48:06 -07:00
Kelsi
a940859e6a refactor: name auth security flags, log JSON parse failures
- auth_handler: define kSecurityFlagPin/MatrixCard/Authenticator
  constants (0x01/0x02/0x04) with why-comment explaining WoW login
  challenge securityFlags byte, replace all bare hex literals
- expansion_profile: log warning on jsonInt() parse failure instead
  of silently returning default — makes malformed expansion.json
  diagnosable without debugger
2026-03-30 14:43:50 -07:00
Kelsi
28e5cd9281 refactor: replace magic bag slot offset 19 with FIRST_BAG_EQUIP_SLOT
- 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)
2026-03-30 14:20:39 -07:00
Kelsi
6dfac314ee fix: remove dead code, name constants, add why-comments
- renderer: remove no-op assignment (mountAnims_.stand = 0 when already 0)
- renderer: add why-comments on blacksmith WMO ID 96048 (ambient forge
  sounds) with TODO for other smithy buildings
- terrain_renderer: replace 1e30f sentinel with numeric_limits::max(),
  name terrain view distance constant (1200 units ≈ 9 ADT tiles)
- social_handler: add missing LFG case 15, document case 0 nullptr
  return (success = no error message), add enum name comments
2026-03-30 14:10:32 -07:00
Kelsi
4acebff65c refactor: extract fallback textures, add why-comments, name WMO constant
- character_renderer: extract duplicated fallback texture creation
  (white/transparent/flat-normal) into createFallbackTextures() — was
  copy-pasted between initialize() and clear()
- wmo_renderer: replace magic 8192 with kMaxRetryTracked constant,
  add why-comment explaining the fallback-retry set cap (Dalaran has
  2000+ unique WMO groups)
- quest_handler: add why-comment on reqCount=0 fallback — escort/event
  quests can report kill credit without objective counts in query response
2026-03-30 14:06:30 -07:00