Merge pull request #12 from Gexo91/housing/restart-stage-06-room-client-data-69587

Core/Housing: stage 6 room client-data contract for 12.1.0.69587
This commit is contained in:
Gexo91
2026-09-11 17:16:02 +03:00
committed by GitHub
2 changed files with 102 additions and 4 deletions
@@ -0,0 +1,92 @@
-- Housing room client-data contract for WoW 12.1.0.69587.
--
-- Verified DB2 contracts:
-- HouseRoom.db2 FileDataID 5163003, layout 0xF04DC279
-- HouseLevelData.db2 FileDataID 7149539, layout 0xF8146F9D
--
-- This update is intentionally non-destructive. Existing hotfix rows are preserved.
-- HouseDecor is deliberately not touched here because that table remains quarantined
-- from the active 12.1.0 client hotfix path until its duplicate-key crash is resolved.
CREATE TABLE IF NOT EXISTS `house_level_data` (
`ID` int unsigned NOT NULL DEFAULT '0',
`Level` int NOT NULL DEFAULT '0',
`QuestID` int NOT NULL DEFAULT '0',
`Field_12_0_7_67808_003` int NOT NULL DEFAULT '0',
`VerifiedBuild` int NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`,`VerifiedBuild`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `house_room` (
`Name` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`ID` int unsigned NOT NULL DEFAULT '0',
`Size` tinyint NOT NULL DEFAULT '0',
`Flags` int NOT NULL DEFAULT '0',
`Field_002` int NOT NULL DEFAULT '0',
`RoomWmoDataID` int NOT NULL DEFAULT '0',
`UiTextureAtlasElementID` int NOT NULL DEFAULT '0',
`WeightCost` int NOT NULL DEFAULT '0',
`ItemID` int NOT NULL DEFAULT '0',
`SortPriority` int NOT NULL DEFAULT '0',
`VerifiedBuild` int NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`,`VerifiedBuild`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `house_room_locale` (
`ID` int unsigned NOT NULL DEFAULT '0',
`locale` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`Name_lang` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`VerifiedBuild` int NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Reconcile installations that already have the older three-field HouseLevelData
-- table without relying on MariaDB-only ADD COLUMN IF NOT EXISTS syntax.
SET @housing_sql := IF(
EXISTS(
SELECT 1
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA` = DATABASE()
AND `TABLE_NAME` = 'house_level_data'
AND `COLUMN_NAME` = 'Field_12_0_7_67808_003'
),
'SELECT 1',
'ALTER TABLE `house_level_data` ADD COLUMN `Field_12_0_7_67808_003` int NOT NULL DEFAULT 0 AFTER `QuestID`'
);
PREPARE housing_stmt FROM @housing_sql;
EXECUTE housing_stmt;
DEALLOCATE PREPARE housing_stmt;
-- HouseRoom gained ItemID and SortPriority in the verified 69587 layout. Preserve
-- existing rows and add only the columns that are absent on older installations.
SET @housing_sql := IF(
EXISTS(
SELECT 1
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA` = DATABASE()
AND `TABLE_NAME` = 'house_room'
AND `COLUMN_NAME` = 'ItemID'
),
'SELECT 1',
'ALTER TABLE `house_room` ADD COLUMN `ItemID` int NOT NULL DEFAULT 0 AFTER `WeightCost`'
);
PREPARE housing_stmt FROM @housing_sql;
EXECUTE housing_stmt;
DEALLOCATE PREPARE housing_stmt;
SET @housing_sql := IF(
EXISTS(
SELECT 1
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA` = DATABASE()
AND `TABLE_NAME` = 'house_room'
AND `COLUMN_NAME` = 'SortPriority'
),
'SELECT 1',
'ALTER TABLE `house_room` ADD COLUMN `SortPriority` int NOT NULL DEFAULT 0 AFTER `ItemID`'
);
PREPARE housing_stmt FROM @housing_sql;
EXECUTE housing_stmt;
DEALLOCATE PREPARE housing_stmt;
SET @housing_sql := NULL;
@@ -14,6 +14,11 @@ namespace Housing
{
namespace
{
// HouseRoom.db2, FileDataID 5163003, verified for WoW 12.1.0.69587.
// Keep persisted/client supplied room ids fail-closed if generated metadata
// drifts to another layout or the store was not actually loaded.
constexpr uint32 HouseRoomLayoutHash69587 = 0xF04DC279;
RoomState ReadRoomState(Field* fields)
{
RoomState state;
@@ -61,10 +66,11 @@ namespace Housing
bool RoomPersistence::IsRoomTemplateStoreReady() const
{
// DB2StorageBase starts with tableHash=0 and receives the real hash only
// after Load(). This intentionally treats a disabled HouseRoom store as
// unavailable instead of validating client-controlled IDs against an empty
// storage object.
return sHouseRoomStore.GetTableHash() != 0 && sHouseRoomStore.GetNumRows() != 0;
// after Load(). The explicit layout guard prevents a future generated-data
// drift from turning client-controlled HouseRoom ids into trusted template ids.
return sHouseRoomStore.GetLayoutHash() == HouseRoomLayoutHash69587 &&
sHouseRoomStore.GetTableHash() != 0 &&
sHouseRoomStore.GetNumRows() != 0;
}
bool RoomPersistence::IsKnownRoomTemplate(uint32 houseRoomId) const