Fix WarbandScenePlacementFilterReq layout to match client metadata.
Fix all parent index fields to be unsigned as required by DB2 loader.
Update warband group limit from 5 to 20 (retail 11.1+).
Audit 2026-04-21 (FINDINGS.md sec 1.1) measured 4 Group A Entity mirrors
per plot at retail idx 9984; we were spawning one. The previous fix
covered only the Type-9 (Base) root, leaving the Roof/Door/Window
companions on retail uncreated.
_houseMirrorEntities is now a vector<unique_ptr<HousingMirrorEntity>>
per plot. SpawnHouseForPlot iterates the same fixture-tier MeshObjects
the Group B pass walks (ExteriorComponent Type 9/10/11/12) and pairs a
Group A mirror with each. All four share AttachParent = Housing/2 room
identity (sniff-decoded "01 c1 XX 12 40 dc" - subType=2, arg2=18) and
local pos (0,0,0) - the room is positioned at the plot centre, so the
chain resolves there for every piece.
Tagging is now an enum (None / Piece / PieceAndRoot) on HousingMirror
Entity::InitPositionData. The Type-9 root (pieceIndex 0) keeps both
Tag_HouseExteriorPiece and Tag_HouseExteriorRoot - this is the canonical
GUID referenced by FHousingPlayerHouse_C.EntityGUID and the world-map
icon picker. The other three (Roof/Door/Window) carry only
Tag_HouseExteriorPiece. Group B per-mesh mirrors switch to Tagging::None
which is identical behaviour to the prior isExteriorRoot=false path.
MakeHouseMirrorGuid gains a pieceIndex parameter (default 0) and packs
(bnetId<<16)|(plot<<8)|piece so each per-piece GUID is unique while the
default-arg call site that proxy emission uses still resolves to the
root mirror's GUID.
Player::BuildCreateUpdateBlockForPlayer iterates the new
GetHouseMirrors() list so all four Group A mirrors land in the initial
UPDATE_OBJECT bundle alongside the four Group B ones (8 mirrors per
plot total, matching retail idx 9984).
Audit 2026-04-21 (README sec 1) measured ~20x over-emission of
CREATE_OBJECT on housing maps because HousingMap::InitVisibilityDistance
forced m_VisibleDistance = MAX_VISIBILITY_DISTANCE (533y). Every player
on the map received CREATEs for every plot AT, cornerstone GO, room
identity, component mesh, and decor on every other plot - completely
unbounded.
Drop the map's visibility distance to 200y (wide enough for adjacent
plots to still render naturally as the player walks the neighborhood,
narrow enough to bound per-player update traffic). Adjacent decor and
component meshes now stream in via grid visibility instead of being
broadcast to every player at all times.
The persistent infra entities - plot AreaTriggers, cornerstone
GameObjects, and Housing/2 room identity entities - must be in the
client's entity registry at any distance, otherwise lookups for
ENTER_PLOT / IsInsidePlot / OutsidePlotBounds / OPEN_CORNERSTONE_UI
fail when the player is far from the relevant plot. Mark each of those
three with setActive(true) + SetFarVisible(true) at spawn time so they
broadcast regardless of player position. The previous workaround for
the lookup-fail bug was to keep visibility at MAX, which fixed lookups
at the cost of the over-emission this commit removes.
Decor / fixtures / component meshes are not active - they only need to
be visible when the player is on or near the plot, which grid
visibility handles correctly at 200y.
Visit teleport (TELEPORT_TO_PLOT, TeleportType=5):
CanVisitorAccess() returned false whenever the plot owner was offline
because the helper takes Player const* and aborts on null. Result: the
client received PERMISSION_DENIED and never teleported, even on plots
whose settings were "ANYONE".
Fix: add CanVisitorAccessPlot(visitor, ownerGuid, settingsFlags, isInterior)
that resolves friend / guild / neighborhood relationships from the
visitor side + sCharacterCache, so the check works for offline owners.
Settings come from a new PlotInfo::HouseSettingsFlags mirrored from
character_housing.settingsFlags at neighborhood preload, refreshed when
Housing::SaveSettings runs while the owner is online.
TeleportToPlot now passes the persisted plot settings into the new
helper instead of bailing on a null Player*.
Group B Entity mirrors:
Audit 2026-04-21 (FINDINGS.md sec 1.2) found retail emits 4 per-piece
Entity mirrors per plot - one FMirroredPositionData_C-only mirror
attached to each visible exterior fixture MeshObject (Base/Roof/Door/
Window - ExteriorComponent Type 9/10/11/12). We were emitting one,
anchored to the root only.
_houseMeshMirrorEntities is now a vector<unique_ptr<HousingMirrorEntity>>
per plot. SpawnHouseForPlot iterates the plot's MeshObjects, and pairs
one Group B mirror per fixture-tier mesh. MakeHouseMeshMirrorGuid now
packs (bnetId << 16) | (plot << 8) | piece so each mirror has a unique
GUID. Player::BuildCreateUpdateBlockForPlayer iterates the new
GetHouseMeshMirrors() list so all per-piece mirrors land in the
initial UPDATE_OBJECT bundle.
Schema:
CHAR_SEL_NEIGHBORHOOD_MEMBERS extended with ch.settingsFlags so
Neighborhood::LoadFromDB can populate PlotInfo::HouseSettingsFlags
for every member's plot at startup.
These three CharacterDatabase prepared statements feed
Neighborhood::LoadFromDB so it can pre-populate every occupied plot's
fixtures, decor, and room data at neighborhood init (without requiring
each owner to be online). They were dropped during the cross-fork
transplant because the surrounding hunk had already been partially
applied. Also extends CHAR_SEL_NEIGHBORHOOD_MEMBERS projection with
ch.houseLevel/favor/houseName/houseType so the loader can mirror per-plot
data onto the neighborhood plot table for the world map tooltip.
Follow-up to e16cb5f0. The squash patch left 5 .rej files; investigation
showed all 5 either:
(a) were redundant — other hunks of the same patch had already added the
content elsewhere, OR
(b) duplicated entries the target already had from its own prior
housing-system experimentation.
Changes in this commit:
src/server/game/Server/Protocol/Opcodes.h
- Hand-applied the rejected hunks from Opcodes.h.rej:
* Inserted CMSG_GET_NEIGHBORHOOD_INITIATIVE_INFO_REQUEST (0x380003) and
the CMSG_NEIGHBORHOOD_INITIATIVE_OPCODE_01..0F catalogue between
CMSG_GET_INITIATIVE_ACTIVITY_LOG_REQUEST and CMSG_GET_ITEM_PURCHASE_DATA.
* Inserted the TC-CUSTOM housing CMSG block (HOUSING_DECOR_*,
HOUSING_FIXTURE_*, HOUSING_REQUEST_*, HOUSING_SVCS_*, HOUSING_SYSTEM_*,
NEIGHBORHOOD_*) right before the closing brace of OpcodeClient.
* Inserted the TC-CUSTOM housing SMSG block (placeholders in 0xF1000000+
range) right before the closing brace of OpcodeServer.
src/server/database/Database/Implementation/HotfixDatabase.h
- Removed three patch-added duplicate blocks that conflicted with target's
alphabetically-sorted entries.
- Re-added HOTFIX_SEL_HOUSE / _DECOR / _DECOR_MATERIAL / _DECOR_THEME_SET /
_EXTERIOR_WMO_DATA / _LEVEL_DATA / _LEVEL_REWARD_INFO / _ROOM / _THEME
(and their _MAX_ID / _LOCALE variants) which were unique to our patch.
Inserted in alphabetical position right after HOTFIX_SEL_HOLIDAYS.
src/server/database/Database/Implementation/HotfixDatabase.cpp
- Removed the entire "WowCommunity" duplicate PrepareStatement block
(lines 2374-3005, ~630 lines). All 30+ housing-related PrepareStatement
calls there duplicated target's existing entries elsewhere in
DoPrepareStatements (queries are byte-identical, so the dedup is safe).
Status:
- Working tree clean (.rej files all resolved).
- feature/import-housing branch is local-only (not pushed yet).
- The repo is structurally consistent — enum entries no longer redefine,
PrepareStatement calls are unique. Need a real CMake build cycle on the
target to surface remaining type/template/include issues from the
cross-fork transplant.
Next steps for human review:
1. cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
2. cmake --build build --target worldserver --parallel
3. Resolve remaining compile errors (likely method-signature drift between
source's TC version and target's customizations to Player.cpp,
WorldSession.cpp, Account.cpp, etc.)
4. Test runtime — the housing system has its own initialisation flow that
must succeed before any housing CMSG handler is reachable
5. git push -u origin feature/import-housing (only after build is green)
Do NOT merge to main until the build is verified.
Squash transplant of 433 commits from agatho/TrinityCore feature/housing-system
(c4775862d1d "Re-CREATE HousingPlayerHouseEntity on move so plot icon updates")
onto WowCommunityProject main. Source and target share no git ancestry — this
import is delivered as a single 3-way patch apply with --reject for residual
conflicts.
What's in this commit:
- Full housing subsystem: Housing/, Entities/Housing/, Entities/MeshObject/,
HousingMap, HouseInteriorMap, HousingMgr, NeighborhoodMgr, NeighborhoodHandler.
- New SMSG/CMSG packet families (0x33xxxx, 0x39xxxx, 0x55xxxx, 0x5Cxxxx,
0x5Bxxxx, plus 0x42xxxx initiative & decor opcodes) wired into Opcodes.cpp,
HousingHandler, NeighborhoodHandler, WorldSession.
- DB2 stores for HouseDecor*, HouseRoom*, HouseTheme*, HouseLevel*,
HouseExteriorWmoData, NeighborhoodPlot, NeighborhoodInitiative*, etc.
- Character DB schema for character_housing*, neighborhood_*, including
decor/rooms/fixtures/catalog tables (sql/updates/characters/master/*).
- World DB updates for housing GO templates, AT scripts, NPCs.
- Spell scripts for housing-related spell effects (npc_housing_steward,
spell_housing, at_housing_plot, go_housing_door).
- Project documentation and analysis dumps under docs/.
Files NOT in this commit (5 .rej files left in the working tree for manual
integration — the target's diverged versions of these list/enum files
prevented automatic apply):
src/server/database/Database/Implementation/CharacterDatabase.cpp.rej
src/server/database/Database/Implementation/CharacterDatabase.h.rej
src/server/database/Database/Implementation/HotfixDatabase.h.rej
src/server/game/DataStores/DB2Metadata.h.rej
src/server/game/Server/Protocol/Opcodes.h.rej
Each .rej is a "list insertion" conflict where our patch wants to add new
enum/statement entries between target lines whose neighbours diverged.
Resolution is mechanical (paste the rejected hunks into the right slots in
the target version) but should be done with awareness of the target's local
ordering. Until those are resolved the build will fail on missing opcodes,
DB statements, and DB2 metadata for housing tables.