Commit graph

1109 commits

Author SHA1 Message Date
Kelsi
cccd52b32f fix: equipment visibility (remove layout verification gate), follow uses run speed
Equipment: removed the visibleItemLayoutVerified_ gate from
updateOtherPlayerVisibleItems(). The default WotLK field layout (base=284,
stride=2) is correct and should be used immediately. The verification
heuristic was silently blocking ALL other-player equipment rendering by
queuing for auto-inspect (which doesn't return items in WotLK anyway).

Follow: auto-follow now uses run speed (autoRunning) instead of walk speed.
Also uses squared distance for the distance checks.

Commands: /quit, /exit aliases for /logout; /difficulty normal/heroic/25/25heroic
sends CMSG_CHANGEPLAYER_DIFFICULTY.
2026-03-27 18:05:42 -07:00
Kelsi
b366773f29 fix: inspect (packed GUID), follow (client-side auto-walk); add loot/raid commands
Inspect: CMSG_INSPECT was writing full uint64 GUID instead of packed GUID.
Server silently rejected the malformed packet. Fixed both InspectPacket and
QueryInspectAchievementsPacket to use writePackedGuid().

Follow: was a no-op (only stored GUID). Added client-side auto-follow system:
camera controller walks toward followed entity, faces target, cancels on
WASD/mouse input, stops within 3 units, cancels at 40+ units distance.

Party commands:
- /lootmethod (ffa/roundrobin/master/group/nbg) sends CMSG_LOOT_METHOD
- /lootthreshold (0-5 or quality name) sets minimum loot quality
- /raidconvert converts party to raid (leader only)

Equipment diagnostic logging still active for debugging naked players.
2026-03-27 17:54:56 -07:00
Kelsi
50a3eb7f07 fix: mail money uint64, other-player cape textures, zone toast dedup, TCP_NODELAY
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.
2026-03-27 17:20:31 -07:00
Kelsi
6b1c728377 perf: eliminate double map lookups, dynamic_cast in render loops, div by 255
- Replace count()+operator[] double lookups with find() or try_emplace()
  in gameObjectInstances_, playerTextureSlotsByModelId_, onlinePlayerAppearance_
- Add Entity::isUnit() helper; replace 5 dynamic_cast<Unit*> in per-frame
  UI rendering (nameplates, combat text, pet frame) with isUnit()+static_cast
- Add constexpr kInv255 reciprocal for per-pixel normal map generation loops
  in character_renderer and wmo_renderer
2026-03-27 17:04:13 -07:00
Kelsi
6f2c8962e5 fix: use expansion context for spline parsing; preload DBC caches at world entry
Spline parsing: remove Classic format fallback from the WotLK parser. The
PacketParsers hierarchy already dispatches to expansion-specific parsers
(Classic/TBC/WotLK/Turtle), so the WotLK parseMovementBlock should only
attempt WotLK spline format. The Classic fallback could false-positive when
durationMod bytes resembled a valid point count, corrupting downstream parsing.

Preload DBC caches: call loadSpellNameCache() and 5 other lazy DBC caches
during handleLoginVerifyWorld() on initial world entry. This moves the ~170ms
Spell.csv load from the first SMSG_SPELL_GO handler to the loading screen,
eliminating the mid-gameplay stall.

WMO portal culling: move per-instance portalVisibleGroups vector and
portalVisibleGroupSet to reusable member variables, eliminating heap
allocations per WMO instance per frame.
2026-03-27 16:58:39 -07:00
Kelsi
a795239e77 fix: spline parse order (WotLK-first) fixes missing NPCs; bound WMO liquid loading
Spline auto-detection: try WotLK format before Classic to prevent false-positive
matches where durationMod float bytes resemble a valid Classic pointCount. This
caused the movement block to consume wrong byte count, corrupting the update mask
read (maskBlockCount=57/129/203 instead of ~5) and silently dropping NPC spawns.

Terrain latency: bound WMO liquid group loading to 4 groups per advanceFinalization
call. Large WMOs (e.g., Stormwind canals with 40+ liquid groups) previously loaded
all groups in one unbounded loop, blowing past the 8ms frame budget and causing
stalls up to 1300ms. Now yields back to processReadyTiles() after 4 groups so the
time budget check can break out.
2026-03-27 16:51:13 -07:00
Kelsi
d26eed1e7c perf: constexpr reciprocals, cache redundant lookups, consolidate texture maps
- Hoist DBC field index lookups before loops in game_handler (7 DBC iteration loops)
- Cache getSkybox()/getPosition() calls instead of redundant per-frame queries
- Merge textureHasAlphaByPtr_ + textureColorKeyBlackByPtr_ into single map
- Add constexpr for DEG_TO_RAD, reciprocal constants, physics delta
- Add reserve() for WMO/M2 collision grid queries and portal BFS
- Frustum plane normalize: inversesqrt instead of length+divide
- M2 particle emission: inversesqrt for direction normalization
- Parse creature display IDs from query response
- UI: show spell names/IDs as fallback instead of "Unknown"
2026-03-27 16:47:30 -07:00
Kelsi
b0466e9029 perf: eliminate ~70 unnecessary sqrt ops per frame, optimize caches and threading
Squared distance optimizations across 30 files:
- Convert glm::length() comparisons to glm::dot() (no sqrt)
- Use glm::inversesqrt() for check-then-normalize patterns (1 rsqrt vs 2 sqrt)
- Defer sqrt to after early-out checks in collision/movement code
- Hottest paths: camera_controller (21), weather particles, WMO collision,
  transport movement, creature interpolation, nameplate culling

Container and algorithm improvements:
- std::map<string> → std::unordered_map for asset/DBC/MPQ/warden caches
- std::mutex → std::shared_mutex for asset_manager and mpq_manager caches
- std::sort → std::partial_sort in lighting_manager (top-2 of N volumes)
- Double-lookup find()+operator[] → insert_or_assign in game_handler
- Add reserve() for per-frame vectors: weather, swim_effects, WMO/M2 collision

Threading and synchronization:
- Replace 1ms busy-wait polling with condition_variable in character_renderer
- Move timestamp capture before mutex in logger
- Use memory_order_acquire/release for normal map completion signaling

API additions:
- DBC getStringView()/getStringViewByOffset() for zero-copy string access
- Parse creature display IDs from SMSG_CREATURE_QUERY_SINGLE_RESPONSE
2026-03-27 16:33:16 -07:00
Kelsi
e805eae33c refactor: add [[nodiscard]] to shader/asset load functions, suppress warnings
Add [[nodiscard]] to VkShaderModule::loadFromFile, Shader::loadFromFile/
loadFromSource, AssetManifest::load, DbcLoader::load — all return bool
indicating success/failure that callers should check.

Suppress with (void) at 17 call sites where validity is checked via
isValid() after loading rather than the return value (m2_renderer
recreatePipelines, swim_effects recreatePipelines).
2026-03-27 15:17:19 -07:00
Kelsi
fb3bfe42c9 refactor: add kCastGreen/kQueueGreen constants, remove dead code
Add kCastGreen (interruptible cast bar, 5 uses) and kQueueGreen
(queue status / talent met, 7 uses across game_screen + talent_screen).

Remove commented-out renderQuestMarkers call (replaced by 3D billboards).
2026-03-27 15:01:12 -07:00
Kelsi
5b91ef398e fix: return UINT32_MAX from findMemType on failure, add [[nodiscard]]
The findMemType/findMemoryType helper in auth_screen, loading_screen,
and vk_context returned 0 on failure — a valid memory type index.
Changed to return UINT32_MAX and log an error, so vkAllocateMemory
receives an invalid index and fails cleanly rather than silently
using the wrong memory type.

Add [[nodiscard]] to VkBuffer::uploadToGPU/createMapped and
VkContext::initialize/recreateSwapchain so callers that ignore
failure are flagged at compile time. Suppress with (void) cast at
3 call sites where failure is non-actionable (resize best-effort).
2026-03-27 14:53:29 -07:00
Kelsi
e474dca2be refactor: add 9 button/bar color constants, batch constexpr promotions
New ui_colors.hpp constants: kBtnGreen, kBtnGreenHover, kBtnRed,
kBtnRedHover, kBtnDkGreen/Hover, kBtnDkRed/Hover, kMidHealthYellow
— replacing 21 inline literals across accept/decline button and
health bar patterns.

Deduplicate kMon/kMonths month arrays (2 copies → 1 kMonthAbbrev).

Promote 22 remaining static const char*/int arrays to constexpr
(kQualHex, resLabels, kRepRankNames, kTotemNames, kReactLabels,
kChatHelp, kMacroHelp, kHelpLines, kMarkWords, componentDirs,
keyLabels, kRollLabels, gossipIcons, kMarkNames, kDiffLabels,
kStatLabels, kCatHeaders, kSlotNames, kResolutions, displayToInternal).
2026-03-27 14:44:52 -07:00
Kelsi
4981d162c5 refactor: deduplicate item-set DBC key arrays, widen totem timer buffer
- Move itemKeys/spellKeys/thrKeys to shared kItemSetItemKeys/
  kItemSetSpellKeys/kItemSetThresholdKeys in ui_colors.hpp, removing
  5 identical local definitions across game_screen and inventory_screen
- Widen totem timer snprintf buffer from 8 to 16 bytes (defensive)
- Promote kStatTooltips to constexpr
2026-03-27 14:40:44 -07:00
Kelsi
92d8262f96 refactor: move kClassMasks, kRaceMasks, kSocketTypes to shared ui_colors.hpp
Deduplicate class/race bitmask arrays (3 copies each → 1 shared) and
socket type definitions (3 copies → 1 shared). Eliminates ~80 lines of
repeated struct definitions across game_screen.cpp and inventory_screen.cpp.
2026-03-27 14:35:16 -07:00
Kelsi
f5a3ebc774 refactor: deduplicate arrays in inventory_screen, add kDarkYellow constant
- Move kSocketTypes to file-scope constexpr, removing 2 identical local
  definitions across tooltip render functions
- Move kResistNames to file-scope constexpr, removing 3 identical local
  definitions (Holy..Arcane resistance labels)
- Move kRepRankNames to file-scope constexpr, removing 2 identical local
  definitions (Hated..Exalted reputation rank labels)
- Add kDarkYellow color constant, replacing 3 inline literals
2026-03-27 14:25:54 -07:00
Kelsi
22d0b9cd4c refactor: deduplicate class color functions, add 9 color constants
Move classColor/classColorU32 to shared getClassColor()/getClassColorU32()
in ui_colors.hpp, eliminating duplicate 10-case switch in character_screen
and game_screen.

New ui_colors.hpp constants: kInactiveGray, kVeryLightGray, kSymbolGold,
kLowHealthRed, kDangerRed, kEnergyYellow, kHappinessGreen, kRunicRed,
kSoulShardPurple — replacing 36 inline literals across 4 files.
2026-03-27 14:07:36 -07:00
Kelsi
54006fad83 refactor: add 9 color constants, replace 36 more inline literals
New constants in ui_colors.hpp:
- Power types: kEnergyYellow, kHappinessGreen, kRunicRed, kSoulShardPurple
- UI elements: kInactiveGray, kVeryLightGray, kSymbolGold, kLowHealthRed, kDangerRed

Replacements across game_screen(30), inventory_screen(5), character_screen(1).
2026-03-27 14:05:32 -07:00
Kelsi
c38fa6d9ec refactor: replace 31 more inline color literals with named constants in game_screen
Replace inline ImVec4 literals with shared constants from ui_colors.hpp:
kHealthGreen(5), kOrange(5), kWarmGold(5), kFriendlyGreen(3),
kActiveGreen(3), kLightGreen(4), kSocketGreen(2), new constants
kSocketGreen/kActiveGreen/kLightGreen/kHealthGreen/kWarmGold/kOrange/kFriendlyGreen
added to ui_colors.hpp.
2026-03-27 13:57:29 -07:00
Kelsi
e3c999d844 refactor: add 4 color constants, replace 31 more inline literals
Add kDarkRed, kSoftRed, kHostileRed, kMediumGray to ui_colors.hpp and
replace 31 inline ImVec4 literals across game_screen, character_screen,
inventory_screen, and performance_hud. Also replace local color aliases
in performance_hud with shared constants.
2026-03-27 10:20:45 -07:00
Kelsi
4090041431 refactor: add 6 color constants, replace 61 inline literals, remove const_cast
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
- Add kBrightGold, kPaleRed, kBrightRed, kLightBlue, kManaBlue, kCyan to ui_colors.hpp
- Replace 61 inline ImVec4 color literals across game_screen, inventory_screen,
  talent_screen, and world_map with named constants
- Remove const_cast in character_renderer render loop by using non-const iteration
2026-03-27 10:08:30 -07:00
Kelsi
7015e09f90 refactor: add kTooltipGold color constant, replace 14 inline literals
Add colors::kTooltipGold to ui_colors.hpp and replace 14 inline
ImVec4(1.0f, 0.82f, 0.0f, 1.0f) literals in inventory_screen.cpp
for item set names, unique markers, and quest item indicators.
2026-03-25 19:18:54 -07:00
Kelsi
7484ce6c2d refactor: extract getInventorySlotName and renderBindingType into shared UI utils
Add getInventorySlotName() and renderBindingType() to ui_colors.hpp,
replacing 3 copies of the 26-case slot name switch (2 inventory_screen
+ 1 game_screen) and 2 copies of the binding type switch. Removes ~80
lines of duplicate tooltip code.
2026-03-25 19:05:10 -07:00
Kelsi
97b44bf833 refactor: consolidate duplicate enchantment name cache in inventory tooltips
Extract getEnchantmentNames() to share a single SpellItemEnchantment.dbc
cache between both renderItemTooltip overloads, replacing two identical
19-line lazy-load blocks with single-line references.
2026-03-25 18:08:08 -07:00
Kelsi
d086d68a2f refactor: extract Interface settings tab into dedicated method
Extract renderSettingsInterfaceTab() (108 lines) from
renderSettingsWindow(). 6 of 7 tabs now have dedicated methods;
only Video remains inline (shares init state with parent).
2026-03-25 16:07:04 -07:00
Kelsi
d0e2d0423f refactor: extract Gameplay and Controls settings tabs
Extract renderSettingsGameplayTab() (162 lines) and
renderSettingsControlsTab() (96 lines) from renderSettingsWindow().
5 of 7 settings tabs are now in dedicated methods; only Video and
Interface remain inline (they share resolution/display local state).
2026-03-25 15:54:14 -07:00
Kelsi
c7a82923ac refactor: extract 3 settings tabs into dedicated methods
Extract renderSettingsAudioTab() (110 lines), renderSettingsChatTab()
(49 lines), and renderSettingsAboutTab() (48 lines) from the 1013-line
renderSettingsWindow(). Reduces it to ~806 lines.
2026-03-25 15:49:38 -07:00
Kelsi
b1a87114ad refactor: extract updateAutoAttack() from update()
Move 98 lines of auto-attack leash range, melee resync, facing
alignment, and hostile attacker orientation into a dedicated method.
update() is now ~180 lines (74% reduction from original 704).
2026-03-25 15:37:19 -07:00
Kelsi
3215832fed refactor: extract updateTaxiAndMountState() from update()
Move 131 lines of taxi flight detection, mount reconciliation, taxi
activation timeout, and flight recovery into a dedicated method.
update() is now ~277 lines (61% reduction from original 704).
2026-03-25 15:32:51 -07:00
Kelsi
123a19ce1c refactor: extract updateEntityInterpolation() from update()
Move entity movement interpolation loop (distance-culled per-entity
update) into its own method. update() is now ~406 lines (down from
original 704, a 42% reduction across 3 extractions).
2026-03-25 15:27:31 -07:00
Kelsi
6343ceb151 refactor: extract updateTimers() from GameHandler::update()
Move 164 lines of timer/pending-state logic into updateTimers():
auction delay, quest accept timeouts, money delta, GO loot retries,
name query resync, loot money notifications, auto-inspect throttling.
update() is now ~430 lines (down from original 704).
2026-03-25 15:23:31 -07:00
Kelsi
7066062136 refactor: extract updateNetworking() from GameHandler::update()
Move socket update, packet processing, Warden async drain, RX silence
detection, disconnect handling, and Warden gate logging into a separate
updateNetworking() method. Reduces update() from ~704 to ~591 lines.
2026-03-25 15:19:03 -07:00
Kelsi
b2e2ad12c6 refactor: add registerWorldHandler() for state-guarded dispatch entries
Add registerWorldHandler() that wraps handler calls with an IN_WORLD
state check. Replaces 8 state-guarded lambda dispatch entries with
concise one-line registrations.
2026-03-25 15:11:15 -07:00
Kelsi
6694a0aa66 refactor: add registerHandler() to replace 120 lambda dispatch wrappers
Add registerHandler() using member function pointers, replacing 120
single-line lambda dispatch entries of the form
[this](Packet& p) { handleFoo(p); } with concise
registerHandler(Opcode::X, &GameHandler::handleFoo) calls.
2026-03-25 15:08:22 -07:00
Kelsi
313a1877d5 refactor: add registerSkipHandler/registerErrorHandler for dispatch table
Add helpers for common dispatch table patterns: registerSkipHandler()
for opcodes that just discard data (14 sites), registerErrorHandler()
for opcodes that show an error message (3 sites). Reduces boilerplate
in registerOpcodeHandlers().
2026-03-25 14:50:18 -07:00
Kelsi
12355316b3 refactor: add Packet::hasData(), replace 52 position checks and 14 more Lua guards
Add Packet::hasData() for 'has remaining data' checks, replacing 52
verbose getReadPos()<getSize() comparisons across 3 files. Also replace
14 more standalone Lua return patterns with luaReturnNil/Zero helpers.
2026-03-25 14:39:01 -07:00
Kelsi
0d9aac2656 refactor: add Packet::skipAll() to replace 186 setReadPos(getSize()) calls
Add skipAll() convenience method and replace 186 instances of the
verbose 'discard remaining packet data' idiom across game_handler
and world_packets.
2026-03-25 14:27:26 -07:00
Kelsi
e4194b1fc0 refactor: add isInWorld() and replace 119 inline state+socket checks
Add GameHandler::isInWorld() helper that encapsulates the repeated
'state == IN_WORLD && socket' guard. Replace 99 negative checks and
20 positive checks across game_handler.cpp, plus fix 2 remaining
C-style casts.
2026-03-25 14:21:19 -07:00
Kelsi
56f8f5c592 refactor: extract loadWeaponM2() to deduplicate weapon model loading
Extract shared M2+skin loading logic into Application::loadWeaponM2(),
replacing duplicate 15-line blocks in loadEquippedWeapons() and
tryAttachCreatureVirtualWeapons(). Future weapon loading changes only
need to update one place.
2026-03-25 14:17:19 -07:00
Kelsi
43caf7b5e6 refactor: add Packet::writePackedGuid, remove redundant static methods
Add writePackedGuid() to Packet class for read/write symmetry. Remove
now-redundant UpdateObjectParser::readPackedGuid and
MovementPacket::writePackedGuid static methods. Replace 6 internal
readPackedGuid calls, 9 writePackedGuid calls, and 1 inline 14-line
transport GUID write with Packet method calls.
2026-03-25 14:06:42 -07:00
Kelsi
2c79d82446 refactor: add Packet::readPackedGuid() and replace 121 static method calls
Move packed GUID reading into Packet class alongside readUInt8/readFloat.
Replace 121 UpdateObjectParser::readPackedGuid(packet) calls with
packet.readPackedGuid() across 4 files, reducing coupling between
Packet and UpdateObjectParser.
2026-03-25 13:58:48 -07:00
Kelsi
ea15740e17 refactor: add withSoundManager() template to reduce renderer boilerplate
Add GameHandler::withSoundManager() that encapsulates the repeated
getInstance()->getRenderer()->getSoundManager() null-check chain.
Replace 6 call sites, with helper available for future consolidation
of remaining 25 sites.
2026-03-25 13:35:29 -07:00
Kelsi
f02fa10126 refactor: make DBC name caches mutable to eliminate 13 const_cast hacks
Mark spellNameCache_, titleNameCache_, factionNameCache_, areaNameCache_,
mapNameCache_, lfgDungeonNameCache_ and their loaded flags as mutable.
Update 6 lazy-load methods to const. Removes all 13 const_cast<GameHandler*>
calls, allowing const getters to lazily populate caches without UB.
2026-03-25 13:21:02 -07:00
Kelsi
fe043b5da8 refactor: extract getUnitByGuid() to replace 10 entity lookup + dynamic_cast patterns
Add GameHandler::getUnitByGuid() that combines entityManager.getEntity()
with dynamic_cast<Unit*>. Replaces 10 two-line lookup+cast blocks with
single-line calls.
2026-03-25 13:12:51 -07:00
Kelsi
03aa915a05 refactor: move packetHasRemaining into Packet::hasRemaining method
Add Packet::hasRemaining(size_t) and remove free function from
game_handler.cpp. Replaces 8 call sites with method calls.
2026-03-25 13:02:49 -07:00
Kelsi
25d1a7742d refactor: add renderCoinsFromCopper() to eliminate copper decomposition boilerplate
Add renderCoinsFromCopper(uint64_t) overload in ui_colors.hpp that
decomposes copper into gold/silver/copper and renders. Replace 14
manual 3-line decomposition blocks across game_screen and
inventory_screen with single-line calls.
2026-03-25 12:59:31 -07:00
Kelsi
f39271453b refactor: extract applyAudioVolumes() to deduplicate 30-line audio settings block
Extract identical 30-line audio volume application block into
GameScreen::applyAudioVolumes(), replacing two copies (startup init
and settings dialog lambda) with single-line calls.
2026-03-25 12:52:07 -07:00
Kelsi
40dd39feed refactor: move hasFullPackedGuid into Packet class, deduplicate 2 definitions
Add Packet::hasFullPackedGuid() method and remove identical standalone
definitions from game_handler.cpp and packet_parsers_classic.cpp.
Replace 53 free-function calls with method calls.
2026-03-25 12:46:44 -07:00
Kelsi
376d0a0f77 refactor: add Packet::getRemainingSize() to replace 656 arithmetic expressions
Add getRemainingSize() one-liner to Packet class and replace all 656
instances of getSize()-getReadPos() across game_handler, world_packets,
and both packet parser files.
2026-03-25 12:42:56 -07:00
Kelsi
4d46641ac2 refactor: consolidate UI colors, quality colors, and renderCoinsText
Create shared include/ui/ui_colors.hpp with common ImGui color constants,
item quality color lookup, and renderCoinsText utility. Remove 3 duplicate
renderCoinsText implementations and 3 duplicate quality color switch
blocks across game_screen, inventory_screen, and quest_log_screen.
2026-03-25 12:27:43 -07:00
Kelsi
eea205ffc9 refactor: extract toHexString utility, more color constants, final cast cleanup
Add core::toHexString() utility in logger.hpp to replace 11 duplicate
hex-dump loops across world_packets, world_socket, and game_handler.
Add kColorBrightGreen/kColorDarkGray constants in game_screen.cpp
replacing 26 inline literals. Replace remaining ~37 C-style casts in
16 files. Normalize keybinding_manager.hpp to #pragma once.
2026-03-25 12:12:03 -07:00