Skip to content

Building Record 建筑记录

状态:Authoritative Reference v1

1. 物理结构

BTL Building record 固定为:

text
0x20 = 32 bytes

当前 1.28.0 corpus:

text
Building records = 32127

原版构造链将每条 Building 记录定位到 Tile,并由 FUN_004759D8 等路径构造/应用建筑状态。Building record 中多个字节是 packed/mixed state,因此“能读出某个低位值”不等于整字节可独立编辑。

主要证据:

text
reports/btl_v1280_so_recovery.md
reports/btl_editor/round4/field_write_whitelist_matrix.csv
reconstruction/src/WC4.Runtime.BattleData/BtlRecords.cs
reconstruction/docs/rendering/static_city_summary_integration_report.md

2. 完整 byte map

OffsetSizeRaw type当前中文语义 / code name状态写入边界
+0x002uint16 LEBuilding Tile ID / TileIdConfirmed需独立占用/引用验证
+0x022int16 LE建筑名称/显示身份 ID / NameIdConfirmedNotAssessed
+0x041uint8Building type / BuildingTypeConfirmedNotAssessed
+0x051uint8appearance raw / AppearanceConfirmedNotAssessed
+0x061uint8CityFeature ID / CityFeatureIdConfirmedNotAssessed
+0x071uint8decoration type / DecorationTypeConfirmedNotAssessed
+0x082uint16 LEtype-dependent unlock/resource/feature ID / UnlockOrFeatureIdPartialNoGo
+0x0A2uint16 LEtype-dependent reward/parameter / RewardOrParameterPartialNoGo
+0x0C1int8signed priority / PriorityRawConfirmedNotAssessed
+0x0D1uint8objective marker / ObjectiveMarkerConfirmedNotAssessed
+0x0E1int8capture Event ID / CaptureEventIdConfirmed runtime projection需 Event 引用诊断
+0x0F1raw byte未闭合 raw;当前 corpus 全零UnknownNoGo
+0x102int16 LEinitial health/stage raw / InitialHealthStageRawPartialNoGo
+0x121raw byteactive raw / Header12RawPartialNoGo
+0x131raw byteactive raw / Header13RawPartialNoGo
+0x141packed uint8mixed building state / PackedState14PartialNoGo whole-byte edit
+0x151packed/raw uint8mixed/未闭合 state / PackedState15PartialNoGo
+0x161uint8air-defence type / AirDefenceTypeConfirmedNotAssessed
+0x171packed uint8air-defence/other flags / PackedAirDefenceFlagsPartialNoGo whole-byte edit
+0x181uint8Factory facility level / FactoryLevelConfirmedtype validation required
+0x191uint8Research facility level / ResearchLevelConfirmedtype validation required
+0x1A1uint8Medical facility level / MedicalLevelConfirmedtype validation required
+0x1B1uint8Airfield facility level / AirfieldLevelConfirmedtype validation required
+0x1C1uint8Missile facility level / MissileLevelConfirmedtype validation required
+0x1D1packed uint8low 3 bits Nuclear level + active extension bits / PackedNuclearAndExtensionLevelPartialNoGo whole-byte edit
+0x1E..+0x1F2raw bytes未闭合 tail bytesUnknownNoGo

+0x10 是一个完整 int16+0x11 只是这个 word 的第二个物理字节,不是另一个可独立编辑字段。旧审计中若按 byte 列出 +0x11,只能视为重叠观察面。

2.1 +0x0E CaptureEventId 的磁盘 / runtime 投影

Android 1.28.0 原版 FUN_004759D8 直接执行:

text
00475BA8  ldrsb w8, [BuildingRecord+0x0E]
00475BAC  str   w8, [runtime Tile+0x150]

因此磁盘 int8 CaptureEventId 会符号扩展后进入 runtime Tile 的 int32 capture-Event 槽。反向序列化 FUN_004757E0 又直接执行:

text
00475984  ldr  w8, [runtime Tile+0x150]
00475988  strb w8, [BuildingRecord+0x0E]

所以当前 authority 已闭合为:

text
Building+0x0E int8 CaptureEventId
<-> runtime Tile+0x150 int32

owner-transition 路径会从 Tile+0x150 取 EventId 进入 FUN_00383AC8,随后清零该 runtime 槽。这个结论闭合的是原版读入、runtime 投影和回写关系,不自动开放 writer validity

新增证据:

text
reconstruction/docs/btl_event_producer_and_execution_lifecycle_closure_v1_report.md
reports/btl_semantic_recovery/event_producer_and_execution_lifecycle_closure_v1/event_producer_and_execution_lifecycle_closure.json

3. +0x00 TileId 与 Building owner 不能混为一谈

Building 通过 TileId 放置到地图 Tile,但 Building 存在并不证明该 Tile 一定有 Country owner。

当前 corpus 已观察到:

text
270 original Buildings are on ownerless Tiles

因此:

  • Building placement 与 Tile ownership 是两个独立域;
  • 工具不能因为某 Tile 上有 Building 就自动补 owner;
  • Building duplicate / occupied Tile 的完整原版 winner/lifecycle 仍有 Unknown,不授权自动去重或重排。

4. +0x06 CityFeatureId 与旧 Landmark 名称

当前 parser 使用 CityFeatureId,旧兼容 alias 曾使用 LandmarkType

原版 definition/表现路径支持这是 CityFeature 类输入。Reference 主名称采用:

text
CityFeatureId

LandmarkType 可以作为搜索 alias,但不再作为更强的全局业务断言。

5. +0x08/+0x0A 是 type-dependent 参数

这两个 uint16 都是有效序列化输入,但不能给出一个覆盖全部 BuildingType 的单一业务名。

当前保守名称:

text
+0x08 UnlockOrFeatureId
+0x0A RewardOrParameter

它们会根据 Building type / mode 进入不同 consumer。此前关于“初始城市资源清除来源”的旧 H6C 解释已经被 native consumer 否定;不能用该旧结论反向强行命名这两个字段。

因此当前状态为 Partial,写入保持 NoGo 直至 type matrix 闭合。

6. +0x14 不是一个普通布尔值

原版代码把 +0x14 拆成多个状态位。即使当前 corpus 某些 bit/组合稀少或全零,也不能:

  • 把整个 byte 命名成一个 bool;
  • 为修改一个已知 bit 覆盖其他 bit;
  • 将未观察位清零。

Reference 统一名称:

text
PackedState14

完整 bit mask 尚未闭合,状态 Partial

7. +0x17 是 packed flags

+0x16 是可独立读取的 AirDefenceType;相邻 +0x17 不是简单第二个防空等级,而包含多个独立 flag。

因此:

text
+0x16 AirDefenceType             Confirmed
+0x17 PackedAirDefenceFlags     Partial

高保真 writer 必须 mask-preserve 未知位。

8. +0x18..+0x1D Facility levels

已确认的独立 facility level:

Offset类型
+0x18Factory
+0x19Research
+0x1AMedical
+0x1BAirfield
+0x1CMissile

当前原版 corpus 中这些字段的观察等级范围主要是 0..4,但这是观察范围,不是格式上限证明。

+0x1D

原版 parser 已确认:

text
NuclearLevel = raw[0x1D] & 0x07

即 low 3 bits 是 Nuclear level。

但是高 5 bits 不是安全 padding;已有证据表明它们属于 active extension bits。因此正式字段仍写成:

text
PackedNuclearAndExtensionLevel

而不是单纯 NuclearLevel 1-byte scalar。

9. +0x1E..+0x1F

当前 corpus 中这两个 tail byte 全零,但尚无足够证据证明:

  • 它们永远不会在其他版本/模式出现;
  • 它们是编译器 padding;
  • 原版 writer 可以任意规范化。

所以仍为:

text
Unknown
Raw-preserve
NoGo write

10. 当前 closure backlog

Building 剩余重点:

  1. +0x08/+0x0A 的完整 BuildingType × consumer matrix;
  2. +0x10 health/stage 的全部类型语义;
  3. +0x12/+0x13
  4. +0x14 全 bit mask;
  5. +0x15
  6. +0x17 全 bit mask;
  7. +0x1D 高 5 bits;
  8. +0x1E/+0x1F
  9. 同 Tile Building duplicate 的构造 winner、失败对象生命周期和删除行为。

这些 Unknown 不影响 0x20 Building record 的物理 round-trip。