* Make TaskContext not copyable - this allowed removing shared `_consumed` state, getting rid of memory allocation per task execution
* Use std::make_shared
* Remove unnceccessary memory alloc/dealloc in TaskContext::Repeat
* Remove std::function wrapping in every TaskContext function
1. Floor material: APPLY_COMPONENT_MATERIALS now directly updates the
specific component MeshObject's textureID instead of going through
room-level WallpaperId (which was overwritten/reset on each change).
2. Stairwell doorway: Reverted HasStairs check — stairwell rooms connect
horizontally through walls like any room. The doorway should open.
3. Added GetRoomComponentOptionID/GetHouseThemeID accessors to MeshObject
for per-component texture updates without room-level state.
Stairwell rooms are tall rooms (geobox Z=-1 to 14) placed ADJACENT to
the source room on the SAME floor, not above it. They extend vertically
through the ceiling. Only rooms connected at the stairwell's ceiling
door should go to floor+1. Was incorrectly using FloorIndex+1.
Interior decor was sent TWICE at login: once by the map visibility system
(AddToMap → UpdateObjectVisibilityOnCreate) and again by the deferred
callback (manual BuildCreateUpdateBlockForPlayer). The double CREATE
corrupted the client's entity state, making decor unselectable.
Session-placed decor only got one CREATE (via AddToMap) and worked fine.
Fix: removed the manual decor CREATE from the deferred callback. The
visibility system already handles decor delivery to the player.
1. APPLY_COMPONENT_MATERIALS handler now passes componentIDs filter to
UpdateRoomComponentVisuals (was updating ALL components including floor).
2. Stairwell room placement no longer destroys the source room's wall
(stairwells are vertical connections, not horizontal doorways).
Decor placed before the room entity system had empty RoomGuid in DB.
Without a valid AttachParentGUID (Housing/2 room entity), the client
can't select the decor for moving/removing. Now auto-assigns decor with
empty RoomGuid to the first non-base room. Also uses FloorIndex for
room Z position in decor world coordinate calculation.
The CMSG sends TextureID=4294967295 (0xFFFFFFFF) to mean "reset to
default". This was stored as WallpaperId and on respawn overrode the
texture lookup (WallpaperId != 0 → use -1 as texture). The client
showed an empty Floor Material dropdown because RoomComponentTextureID=-1.
Fix: treat WallpaperId=0xFFFFFFFF as 0 (no override) in both storage
and the spawn/update texture lookups. Also cleaned up -1 values in DB.
Note: RoomComponentOptionTexture DB2 table is empty in retail — Blizzard
hasn't populated it. Textures work via RoomComponentTexture (19 entries)
which the client reads directly by component type and theme.