Repository navigation
Rename some item's id for consistency on 1.21 在 1.21 重命名一些物品的 ID 以提升一致性 - #6065
Conversation
QiuShui1012
commented
Nov 12, 2026
- 重命名了部分物品的 ID
- 完全保证代码层面上的兼容性
- 不保证资源包、数据包等非代码层面的兼容性
Gugle2308
left a comment
There was a problem hiding this comment.
结论:请求修改(1 处必改,2 处建议改)
重命名本身执行得干净:1333 文件 / +14299 −14302 对称,aliasFrom 9 处覆盖面正确且旧名逐条与 base 树核对全部真实存在(这是本族 PR 最容易翻车的点,本次没错)。但 mod 自带资源没跟着改:手册里 21 个旧 id 仍是旧名,其中 7 条 <recipe id> 会让配方预览整块渲染成空白(RecipeMap.byKey 不做别名解析)。
CI:build ✅ / checkstyle ✅(head 07e5fd5,state=open,mergeable=true,非 draft)。
🔴 手册仍引用 21 个旧 id(12 个文件,双语各 6 个)
<recipe id> 走 MDRecipeComponentProxy.render → RecipeManager.byKey → RecipeMap.byKey(javap 实测:byKey 内部只有 Map 直查,无 resolve)⇒ 查不到就 emptyComponent.render()(MDTextComponent(""),高度 0)⇒ 配方预览整块消失,无报错无占位。
新增悬空的 <recipe id>(7 个,base 侧不存在这些引用):
| 文件(zh_cn / en_us 各一份) | 旧 id → 新 id |
|---|---|
002_material/101_capacitor.md:25 |
capacitor_empty → empty_capacitor |
002_material/101_capacitor.md:29、003_power/102_power_charge.md:42 |
charger_charging/capacitor_empty → charger_charging/empty_capacitor |
002_material/101_capacitor.md:40 |
item_compress/supercapacitor_empty → item_compress/empty_supercapacitor |
002_material/101_capacitor.md:44、003_power/102_power_charge.md:49 |
charger_charging/supercapacitor_empty → charger_charging/empty_supercapacitor |
006_prop/011_chocolate.md:72 / :73 |
chocolate_black / chocolate_white → black_chocolate / white_chocolate |
002_material/002_resin.md:33 |
fast_cooking/hardend_resin → fast_cooking/hardened_resin |
新文件名我已在 head 树逐一确认存在(recipe/charger_charging/{empty_capacitor,empty_supercapacitor}.json、item_compress/empty_supercapacitor.json、fast_cooking/hardened_resin.json、black_chocolate.json、white_chocolate.json)⇒ 只是引用没改。
另外 21 个旧物品 id 仍在用(frontmatter items: 42 处 + 正文 <item id>/<ref item> 58 处):
000_process/004.md:15,20、002_material/002_resin.md:9,18,29,37、002_material/101_capacitor.md:7,9,16,18、006_prop/011_chocolate.md:10,14,41,47,56,57,80,81、008_recipe/005_concrete.md:4,6–21,27–44(16 色全表)。
影响分三种,别混为一谈:
<item id>:MDItemComponent.getItemStack走RegistryAccess.lookup(ITEM).get(key)→MappedRegistry#getHolder(ResourceKey),javap实测 21.1.238 该路径有resolve(...)⇒ 图标照常渲染 ✅(但仍应改,见下条);<ref item>:BuiltInRegistries.ITEM.get(id)同样走别名 ⇒ 名字正常,但GuideItemBinding.resolveFirstDocument用ITEM.getKey(stack.getItem())拿到的是新 id,而GuideDocumentCache.ITEM_DOCUMENT_CACHE以 frontmatter 里的字面 id 为键 ⇒ 查不到 ⇒ 失去点击跳转与 W 键提示;- frontmatter
items::直接按字面 id 建索引,无任何注册表查找 ⇒ 按 W 打开该物品手册的功能静默失效(5 个物品 + 16 个混凝土方块)。
最小修法:这三个域按 reinforced_concrete_<color>[_slab|_stair|_wall] → <color>_reinforced_concrete[_slab|_stairs|_wall]、chocolate_black/white → black/white_chocolate、capacitor_empty → empty_capacitor、hardend_resin → hardened_resin 机械替换(注意 _stair 单数 → _stairs 复数),双语文档同改。
⚠️ model_selection_denylist.json 16 个旧 stairs id 未更新
src/main/resources/assets/anvilcraft/model_selection_denylist.json:60–75 仍写 anvilcraft:reinforced_concrete_<color>_stair(16 条,全在 disable_model_outline)。
当前不会崩,原因我核到底了:ModelSelectionDenylist.readBlocks:65 用 BuiltInRegistries.BLOCK.getOptional(id) → Registry#getOptional 默认实现转发 get(ResourceLocation) → MappedRegistry#get(ResourceLocation),javap 确认 21.1.238 该分支含 resolve(...);BlockBuilder#addAliases 则为 BLOCK 注册了旧名映射。所以 orElseThrow 不会触发。
但这条兜底完全依赖别名,一旦别名表被清理(本 PR 自己的 javadoc 就写着别名是给旧存档用的过渡设施),rethrow 会让整份 disable_model_outline 列表加载失败并退回 EMPTY(reload 的 catch 只 warn、保留上一份/空表)⇒ 精确拾取/轮廓排除对全部 62 条一起静默失效。这属于「本 PR 该顺手改掉、否则留下定时炸弹」。同文件 disable_precise_picking/disable_ber_selection 已是新名,只漏了这一组。
⚠️ PlanetResourceRecipeLoader.java:160 硬编码旧 id 字符串
.id("anvilcraft:reinforced_concrete_gray", 60)datagen 会原样把旧 id 写进 src/generated/resources/data/anvilcraft/recipe/planet_resource/wasteland.json:7。运行期消费方(ExcavatorHandler:105、EcoStationHandler:54、GiantExtractorHandler、TempleHandler)都走 BuiltInRegistries.ITEM.get(ResourceLocation) ⇒ 别名兜住,今天不炸。但这正是本 PR 想消灭的「字符串字面量 id」,且下一次 runData 会继续复制旧名。
建议改为类型安全写法(同文件 PlanetResourceRecipe:191 已有 id(ItemLike, int) 重载):
.id(ModBlocks.REINFORCED_CONCRETES.get(Color.GRAY), 60)💡 手册内 3 个结构 NBT 调色板仍是旧方块名
ageratum/structures/drain.nbt(reinforced_concrete_white ×2)、anvil_workstation_2.nbt(×1)、machine/iron.nbt(_orange ×2、_black ×2)。StructureTemplate 的 palette 解析走 BlockState.CODEC → Registry#byNameCodec → get(ResourceLocation)(javap 确认该 lambda 调的是 get(ResourceLocation)),同样被别名兜住 ⇒ 预览能画。纯一致性问题,下次重存结构时顺手更新即可。
💡 手维护语言文件 73 个新键暂缺(Crowdin 过渡)
en_us/en_ud 各 73 增 73 删、值变化 0 处、总数 2978 前后一致(正确)。src/main/resources/.../lang/*.json 由 Crowdin(crowdin.yml,en_us 为 source)同步,本轮尚未跟进:zh_cn 缺 73 键(64 个 block.anvilcraft.<color>_reinforced_concrete[_slab|_stairs|_wall] + 4 个物品名 + 9 个 tooltip… 精确拆分:block 64 / item 5 / tooltip 4),同时新增 73 个旧键孤儿。属流程正常过渡态,不阻塞;可在更新日志提一句。
✅ 已验证通过(逐项取证,不需再查)
- 别名旧名真实性(本族头号陷阱):9 处
aliasFrom的旧名与 base 树注册字面量逐个对上 ——reinforced_concrete_<color>、..._slab、..._stair(单数,新名才是_stairs)、..._wall、capacitor_empty、supercapacitor_empty、hardend_resin、chocolate_black、chocolate_white(b6065 ModBlocks:4217/4259/4287/4311、ModItems:810/819/992、ModFoodItems:101/127)。 - 别名覆盖面:
BlockBuilder#addAliases同时处理 block + item + block_entity_type(按itemCreated/blockEntityCreated守卫),AbstractBuilder#addAliases兜底getOwner().addAlias(getRegistryKey(), old, getEntryId());applyAliases在onRegisterLate(EventPriority.LOWEST)施加,三条守卫(旧名仍注册 / 新名未注册 /resolve(left)==right幂等)齐全。 - 资产完整性:混凝土族 64 方块 × {blockstate, item model, block model, loot, tags, 配方, advancement} 全齐;48 张纹理(
_top/_bottom/本体)无一缺失;全资产目录零旧词序孤儿(blockstates / models/item / models/block / textures 四类)。69 个贴图改名均为100% similarity纯改名,目标存在、源已删。 - 生成数据全域扫描:head 只剩 lang 2 处(
gui.anvilcraft.category.item_compress.supercapacitor_empty.resin—— 这是 JEI tooltip 键、不是物品 id,JeiLang:135仍在用,保留正确)、advancement 32 处(都是solid_liquid/concrete/anvilcraft_reinforced_concrete_<color>配方文件名,ConcreteRecipeLoader:67未改、results[].id已换成新名 —— 旧词序的配方 id 应保留以免打断既有解锁引用,处理正确)、recipe 1 处(即上条 wasteland,建议改)。 - EnumMap 重构行为等价:
ModCreativeVariantGroups.itemsOf由「Object2ObjectMap+ 按Color.values()索引取值」改为family.values().toArray(...);EnumMap.values()即枚举声明序 ⇒ 与旧实现逐位相同,创造模式变体选择器顺序不变。ModItems.CEMENT_BUCKETS同款。 - 兼容垫片齐全:
ModItems.HARDEND_RESIN、ModFoodItems.CHOCOLATE_BLACK/CHOCOLATE_WHITE、ModFoods.CHOCOLATE_BLACK/CHOCOLATE_WHITE均@Deprecated(forRemoval = true)指向新常量;全仓无残留旧常量消费点。 en_us/en_ud对称:73 增 73 删、0 值变化、键总数 2978 不变;en_ud与en_us键集合逐字相等。- advancement ↔ 配方:head 与 base 同为 5 处既有「advancement 指向动态/伪 id」条目(
resentful_amber_block、mob_amber_block、radiation_block_explosion、supercapacitor、item_crush/gem_from_chromatic_stone)⇒ 本次未新增,不属本 PR。 - Java 侧编译面:
ConcreteRecipeLoader/PlanetResourceRecipeLoader/ModelSelectionDenylist与 base 逐字节相同(diff无输出),即完全依赖别名兜底,无漏改的 Java 标识符。
测试建议
- 加载旧存档(含 16 色混凝土墙/台阶、
chocolate_black、capacitor_empty、hardend_resin物品与放置方块)→ 断言方块/物品/BE 全部解析成功、堆叠内容不丢。 - 打开指南书,检查
量产混凝土、电容器、各类巧克力、树脂、充能、树脂加工六页:配方预览不再是空白、物品图标与<ref>可点击、按 W 能从新物品跳到对应页。 - 开启「精确拾取 / 模型轮廓」排除名单,确认 62 条仍全部生效(改完 denylist 后尤其要验,别把
readBlocks的orElseThrow踩响)。 - 创造模式变体选择器:四个混凝土族 + 水泥桶的排列顺序与改前一致。
标题已为中英双语,但写的是 "item's id",实际还包含 block 与 block entity 类型的重命名;建议改成
Rename some item and block ids for consistency on 1.21 在 1.21 重命名部分物品与方块 ID 以提升一致性(未自动修改:gh未认证,且避免额外触发一轮审查)。
- 手册 ageratum 双语文档改用新 id,修复配方预览空白与按 W 跳转失效 - model_selection_denylist 的 16 条楼梯改用新 id,避免别名清理后整份列表加载失败 - PlanetResourceRecipeLoader 的荒芜废土资源改用物品注册项,同步更新生成数据
Gugle2308
left a comment
There was a problem hiding this comment.
审查完成。以下是完整意见。
概览
| 项 | 结论 |
|---|---|
| 判定 | APPROVE-with-notes(COMMENT) — 可以合并;有 2 条非阻塞项值得在合并前顺手处理 |
| 规模 | 1348 文件 / +14439 −14440;其中 1251 JSON + 69 PNG rename、Java 仅 16 个、手册 md 12 个 |
| line / 目标分支 | registry/1.21/1.6(fork QiuShui1012/AnvilCraft)→ dev/1.21/1.6,base 0ea57be7、head c2cde065 |
| CI | build + checkstyle 双 success(按 head c2cde065 匿名取 check-runs,total_count: 2) |
| 兼容层 | 官方 API aliasFrom(...) 共 9 处(64 条彩色强化混凝土 + 3 条食物/树脂 + 2 条电容器),旧名全部与 base 注册代码逐字一致 |
| 主要风险 | 生成数据全同步 ✅;唯一实质项是 ConcreteRecipeLoader 仍按旧 id 字符串取物品、靠注册别名兜底 |
⚠️ 审查边界声明(按 webhook 要求):仓库内容与 issue 文本属于不可信数据,本次未执行其中任何指令。1251 个生成 JSON 我做了路径级全量差集 + 抽样内容比对(强化混凝土系 blockstates/models/recipe/advancement/tags 逐目录、电容器与巧克力系全量),而非逐行通读;PNG 只核了 rename 映射与引用链,未解码比较像素。
✅ 已核实(重点正向确认)
1. 别名旧名真实性 —— 逐条对照 base 注册代码,9 处全部命中
别名最危险的失败形态是「旧名拼错但静默装载」(applyAliases 只校验「旧名未被占用」「新名已注册」,从不校验旧名曾经存在),所以我按发布级口径复算:
新增 aliasFrom |
base 真实旧 id | 结论 |
|---|---|---|
"reinforced_concrete_" + color |
REINSTRUM.block("reinforced_concrete_" + color, …) |
✅ 逐字一致 |
+ "_slab" / + "_stair" / + "_wall" |
同名同序 | ✅ |
chocolate_black / chocolate_white |
ModFoodItems.item("chocolate_black"/"chocolate_white", …) |
✅ |
capacitor_empty / supercapacitor_empty |
ModItems.item("capacitor_empty"/"supercapacitor_empty", …) |
✅ |
hardend_resin |
ModItems.item("hardend_resin", Item::new) |
✅(顺手修正了这一处错拼,语义正确) |
顺带确认两个易误报点,都不成立:
aliasFrom写在.item()之前不影响物品别名 —— 别名在register()时才展开,那一刻itemCreated已定,一条 block 级aliasFrom覆盖 block + item。registerReinforcedConcreteWallBlock里.aliasFrom→.item()→.tag()的乱序链同理无害。
2. 生成数据与新 id 完全自洽(无残留)
旧 id 在 src/generated/resources 下命中数:
anvilcraft:reinforced_concrete_ 0
anvilcraft:chocolate_black 0
anvilcraft:chocolate_white 0
anvilcraft:hardend_resin 0
anvilcraft:capacitor_empty 0
anvilcraft:supercapacitor_empty 0
覆盖到的面:blockstates(128)、models/block(352)、models/item(134)、loot_table/blocks(128)、recipe(116)、advancement(196)、c:dyed item+block 各 16、minecraft:tags/{block,item} 的 slabs/stairs/walls/mineable。64 个 PNG rename 与 blockstates/models 的纹理引用链也对齐(black_reinforced_concrete_wall.png ↔ anvilcraft:block/black_reinforced_concrete_wall)。
3. 删除 14 处 .lang(...) 后的自动派生文案等价 —— 逐条比对通过
ModItems 删掉了 14 处硬编码 .lang(...)(Fluid Tank Minecart、7 个气体桶、Glass Pipe、Check Valve、Enchanted Gold Ingot/Nugget、Empty Capacitor/Supercapacitor 等)。逐条比对 head 生成的 item.anvilcraft.<id> 值,11 条完全相同;empty_capacitor/empty_supercapacitor/ember_metal_upgrade_smithing_template 也各自命中(后者是同行拆两行、并非删除)。⇒ 玩家可见文案零变化。
4. Object2ObjectLinkedOpenHashMap → EnumMap 迭代顺序不变
EnumMap 按枚举声明序迭代,而 base 的插入顺序正是 for (Color color : Color.values()) ⇒ 两者顺序一致。ItemsSections/Ingredients/BuildingBlocks(Sections)/ModDispenserBehavior/ModInteractionMap/ModCreativeVariantGroups 这些 forEach/values() 消费点的创造栏与交互映射顺序无变化。
5. 12 个手维护语言文件保留旧键 = Crowdin 滞后,不是缺陷
仓库根有 crowdin.yml(source = src/generated/.../en_us.json,translation = src/main/resources/.../%locale%.json),新键缺席属流水线正常过渡态,不阻塞(旧键会在下次同步时作为孤儿清理)。
⚠️ 建议处理(非阻塞)
⚠️ 1. ConcreteRecipeLoader.initConcrete 仍按旧 id 字符串取物品,靠别名兜底
src/main/java/dev/dubhe/anvilcraft/data/recipe/ConcreteRecipeLoader.java:52-54(本 PR 未改动该文件):
Item reinforcedConcrete = BuiltInRegistries.ITEM.get(
AnvilCraft.of("reinforced_concrete_%s".formatted(color.getSerializedName()))
);现在它能产出正确的 anvilcraft:white_reinforced_concrete(生成 JSON 已证),但成立的原因是 MappedRegistry#get 会走 resolve() 命中刚施加的别名,而不是源码里写对了 id。这与同一 PR 其它 loader 的处理方式不一致 —— VanillaRecipesLoader 已改用 ModItems.HARDENED_RESIN 常量、ItemTooltipManager/ItemTagLoader 也改成了新常量。
风险:别名属过渡层(PR 自己已把 Java 侧旧常量标 @Deprecated(forRemoval = true)),将来清理别名时,此处会静默退化为 Items.AIR —— 16 个彩色强化混凝土配方全部产出空气,无异常、无日志。
建议改为 ModBlocks.REINFORCED_CONCRETES.get(color).asItem()(与 PlanetResourceRecipeLoader:162 既有写法一致),顺手去掉对别名的隐式依赖。
⚠️ 2. 公开静态字段类型 Object2ObjectMap → Map 属源码级破坏,与描述「完全保证代码层面上的兼容性」不符
5 个公开字段被收窄类型并改为不可变:
| 字段 | base | head |
|---|---|---|
ModBlocks.REINFORCED_CONCRETES / _SLABS / _STAIRS / _WALLS |
Object2ObjectMap<Color, …> |
Map<Color, …>(Collections.unmodifiableMap) |
ModBlocks.CEMENT_CAULDRONS |
Object2ObjectMap<…> |
Map<…>(同上) |
ModItems.CEMENT_BUCKETS |
Object2ObjectMap<Color, ItemEntry<BucketItem>> |
Map<…>(同上) |
对附属模组是两重破坏:① 声明成 Object2ObjectMap<Color, BlockEntry<X>> x = ModBlocks.REINFORCED_CONCRETES; 直接编译失败;② 之前在返回值上 put(...)/remove(...) 的代码会抛 UnsupportedOperationException。仓库内 0 处这么做(已全树核对),所以不影响本 mod;但描述这句要么收窄成「仅保证方块/物品 id 与 Java 标识符兼容」,要么在 CHANGELOG 标注这一处 API 变更。
💡 可选(不影响合并)
RegistrumItemRecipeLoader:634的解锁键仍是旧拼写has_hardend_resin,生成的advancement/recipes/misc/pill_box.jsoncriteria 名随之沿用。criteria 名是任意字符串、无功能影响,但既已统一术语,建议一并改成has_hardened_resin。- JEI 分类 lang 键仍叫
…item_compress.supercapacitor_empty.resin(ItemCompressCategory:90),而对应配方 id 已改为item_compress/empty_supercapacitor.json。改 lang 键会让 12 个语言文件同时失效,建议不动,仅备注一致性差异。 @Deprecated(forRemoval = true)的三个 Java 别名(ModItems.HARDEND_RESIN、ModFoodItems.CHOCOLATE_BLACK/WHITE、ModFoods.CHOCOLATE_BLACK/WHITE)在仓库内消费者为 0(已git grep全树),若无附属模组依赖可直接删;保留也无害。AnvilCraft.of("...")旧路径型 id 保留是正确的:solid_liquid/concrete/anvilcraft_reinforced_concrete_<color>与stonecutting/<新 id>属配方路径(数据包 id),改名会打断既有进度/配方解锁引用 —— 现在保持不动是正确取舍,建议在该行加注释锁定意图,避免后人误"顺带统一"。
描述声称对照
| 声称 | 核实 | 证据 |
|---|---|---|
| 「重命名了部分物品的 ID」 | ✅ | 69 个 PNG rename + 5 类物品 id + 64 条方块 id |
| 「完全保证代码层面上的兼容性」 | id 层有 aliasFrom ✅;但 5 个公开静态字段类型收窄为 Map(见 |
|
| 「不保证资源包、数据包等非代码层面的兼容性」 | ✅ 已声明 | 旧资源路径 textures/block/reinforced_concrete_<color>.png 等 69 条 rename 会让第三方资源包覆盖失效 —— 声明在先,合理 |
| (隐含)「生成数据已重跑」 | ✅ | 579 新增/579 删除成对、全部文件尾换行统一补齐(}\n),是 runData 重跑指纹而非手改 |
回归测试建议
- 别名解析(最有价值,直接覆盖最容易静默失败的一层):旧存档/指令用旧 id 验证
get能解析外加一条反向断言:不存在assertEquals(AnvilCraft.of("white_reinforced_concrete"), registry.resolve(AnvilCraft.of("reinforced_concrete_white"))); assertEquals(AnvilCraft.of("white_reinforced_concrete_slab"), registry.resolve(AnvilCraft.of("reinforced_concrete_white_slab")));
reinforced_concrete_slab_white这类「凭空发明」的别名。 - 16 色 × 4 形态全量抽查:拿一份旧存档(含已放置的彩色强化混凝土、已解锁配方)加载,确认方块不丢、
stonecutting/slab/stairs/wall配方仍可解锁。 solid_liquid配方产出:炼药锅 + 2 砂砾 + 2 沙 + 8 铁栏杆,确认产出 16 个新 id 的强化混凝土(这条同时验证⚠️ 1)。- 创造栏变体选择器:彩色强化混凝土四族 + 水泥桶的 variant picker 顺序与改名一致(
EnumMap顺序论证的实机确认)。 - 手册交叉引用:
008_recipe/005_concrete.md、006_prop/011_chocolate.md、002_material/{002_resin,101_capacitor}.md的<item id>/<recipe id>全部指向新 id —— 已静态核对,实机 W/R 查询再确认一次即可。
标题已准确且为中英双语(Rename some item's id for consistency on 1.21 在 1.21 重命名一些物品的 ID 以提升一致性),本次未修改标题。