Skip to content

Add data-driven cube selection for 1.21.8 为1.21.8添加数据驱动的模型选取与描边 - #278

Merged
PigeonNian merged 2 commits into
Anvil-Dev:dev/1.21.8from
WhereisFff:codex/cube-data-1.21.8
Nov 14, 2026
Merged

PigeonNian merged 2 commits into
Anvil-Dev:dev/1.21.8from
WhereisFff:codex/cube-data-1.21.8

Conversation

@WhereisFff

@WhereisFff WhereisFff commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

feat(cube): 支持资源包配置模型选取与描边

  • 支持按命名空间和方块配置精确模型选取、仅模型描边及原版模式
  • 按资源包优先级逐项合并规则,并在模型重载完成时同步应用规则与几何
  • 保留动态部件和程序排除接口,分离描边与精确选取入口并限制邻格补扫范围
  • 补充资源配置格式、覆盖顺序及 KubeJS 整合包接入说明

fix(cube): 保持仅描边模式的动态几何逐帧更新

  • 在跳过精确选取前刷新客户端帧缓存,避免仅描边模式冻结动态部件
  • 保留嵌套射线调用的缓存保护及超出精确选取距离时的原版行为

- 支持按命名空间和方块配置精确模型选取、仅模型描边及原版模式
- 按资源包优先级逐项合并规则,并在模型重载完成时同步应用规则与几何
- 保留动态部件和程序排除接口,分离描边与精确选取入口并限制邻格补扫范围
- 补充资源配置格式、覆盖顺序及 KubeJS 整合包接入说明
@Gugle2308

Gugle2308 commented Nov 14, 2026 •

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

Module Status Breaking Changes
codec ✅ Compatible 0
collision ✅ Compatible 0
cube ✅ Compatible 0
config ✅ Compatible 0
integration ✅ Compatible 0
moveable-entity-block ✅ Compatible 0
network ✅ Compatible 0
rendering ✅ Compatible 0
space-select ✅ Compatible 0
font ✅ Compatible 0
util ✅ Compatible 0
explosion ✅ Compatible 0
rpc ✅ Compatible 0
math ✅ Compatible 0
multiblock ✅ Compatible 0
recipe ✅ Compatible 0
registrum ✅ Compatible 0
sync ✅ Compatible 0
ui ✅ Compatible 0
wheel ✅ Compatible 0
main ✅ Compatible 0

Full CSVs: see the Artifacts section of this workflow run.

- 在跳过精确选取前刷新客户端帧缓存,避免仅描边模式冻结动态部件
- 保留嵌套射线调用的缓存保护及超出精确选取距离时的原版行为
@PigeonNian
PigeonNian merged commit fdadb62 into Anvil-Dev:dev/1.21.8 Nov 14, 2026
1 check passed

@Gugle2308 Gugle2308 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结论:PR #278 已在本次审查执行前被合并(squash fdadb621,与 dev/1.21.8 tip 一致,合并树与 head 2870ee8a 完全相同);这是同一改动的第 6 条线,我在 1.21.8 官方混淆 client.jar 与 client_mappings 上复核了关键语义,未发现本 PR 引入的阻塞缺陷;六条线横向对比后,只有 1.21.1 带距离哨兵,建议明确取舍。

一、合并态与范围

判据 结果
state / merged / merged_at closed / true / 2026-11-14T11:13:05Z
merge_commit_sha fdadb621d54738db44a64289d1a50597df0c0137,与 ls-remote dev/1.21.8 相同
合并树 vs head git diff pr278h pr278b 为空 ⇒ 进主干的就是 2870ee8a
规模 7 文件 +194/−11,与 API 计数一致(changed_files=7 / additions=194 / deletions=11),diff 覆盖完整
head CI build / build ✅(total_count: 1)
既有评论 仅 Roseau API 报告 1 条,无内容级审查

二、在 1.21.8 上核对过的语义(混淆 jar + 官方 mappings)

  1. 包优先级方向正确。 MultiPackResourceManager(obf axh)的 listPacks() 返回构造器里 List.copyOf 存下的同一个列表(axh.d),构造器按列表顺序把包 push 进 FallbackResourceManager(obf axf);axf.getResourceStack 从 size()-1 倒序取、末尾 Lists.reverse ⇒ 索引升序 = 低→高,CubeSelectionRules.java:43 的升序排序 + 顺序 merge 与 README「从低到高逐项合并」一致。

  2. 目录参数校验存在且方向正确。 axh.a(String)V(checkTrailingDirectoryPath)的字节码是「endsWith("/") 为真才抛 IllegalArgumentException」⇒ 传 "anvillib"(无尾斜杠)合法。至此六条线(1.21.1 / 1.21.4 / 1.21.8 / 1.21.11 / 26.1 / 26.2)该行为完全一致,可以放心写进库文档:路径不带尾斜杠。

  3. 规则读的是本轮包集。 ReloadableResourceManager(obf axl)的 createReload 顺序为「close 旧 resources → new axh → putfield axl.c → 派发」⇒ ModifyBakingResult 期间 listPacks() 与 listResourceStacks() 看到同一批新包,packs.indexOf(sourcePackId()) 与栈顺序同源。

  4. 逐帧链路成立。 GameRenderer.pick(float)(gxb.a(F)V)的调用方只有 Minecraft.tick()(fue.t)与 GameRenderer.renderLevel(gxb.a(Lftu;)V)⇒ 每帧一次,第 2 个提交的 beginFrame 前移一定早于描边提取,仅描边模式不再冻结动态部件。

  5. 其余结论与同批 #276/#277/#279/#280/#281 相同:规则与几何成对发布(CubeModelEvents.java:22-24 / :29)、install 先写 rules 再重算(CubeSelection.java:128-131)、三种模式四个消费点收敛(target 仅 MODEL、outlineTarget MODEL+OUTLINE、extendsBlock 仅 MODEL、active()=pickingActive)、exclude 优先于配置、整份文件校验通过后才替换、公开面零增长(与 Roseau「0 breaking」一致)。

三、六线横向对比:距离哨兵只有 1.21.1 有

版本线 PR CubePicking 的 distanceToHit 上界 位置
1.21.1 #276 ✅ 有 :38-43
1.21.4 #277 ❌ 无 :38-39 直接赋值
1.21.8 #278(本 PR) ❌ 无 同上
1.21.11 #279 ❌ 无 同上
26.1 #280 ❌ 无 同上
26.2 #281 ❌ 无 同上

1.21.1 那段做的事:Entity.pick 的返回若被第三方模组重定向到远处或子空间坐标(注释点名的 Sable 场景),先在 start.distanceToSqr(end) + 1e-7 处兜底返回原版结果。另外五条线缺这层兜底,会把这个坐标直接喂给 BlockGetter.traverseBlocks(start, block.getLocation(), …) 逐格遍历整段射线(每格再跑 (2r+1)³ 次 getBlockState),且每帧一次;context.distance 同时失去「不超过射线长度」的上界。

建议二选一,避免同一份库在不同 MC 版本上行为不一致:把这三行补到其余五条线(注释可直接沿用),或者在六条线的对应位置都加注释说明它针对的模组场景与触发条件,防止将来被当成冗余代码清掉。

四、其他跟进

⚠️ 预算截断完全静默(六条线通病):ModelSelections.java 的 MAX_STATES = 32768 / MAX_GEOMETRY_BYTES = 16 MiB 超限时只做 unsupported++,而 CubeSelection.statistics() 全仓无调用者。README 新推的正是 namespace 级配置("namespaces": {"minecraft": "model"} 这类整包开启),撞上上限的表现是「一部分方块仍走原版行为」且没有任何日志。建议在 CubeModelEvents.apply 里当 unsupportedStates > 0 打一条一次性 warn。

细节建议:

  • README 69–70 行连续两个空行(### Config 模块 在 71 行)。
  • packs.indexOf(...) 的 -1 分支(CubeSelectionRules.java:39):命不中时该源被排成最低优先级(静默降级),建议 Math.max(0, …) 或 debug 日志。
  • load() 的异常边界(CubeSelectionRules.java:35、:37 在逐文件 try 之外):listPacks() / listResourceStacks() 抛 RuntimeException 会穿出 ModifyBakingResult 监听器并让整次模型重载失败,外部资源包引发的问题应退化成 EMPTY。
  • 公开重载 install(Snapshot)(CubeSelection.java:133)不重置 rules,第三方重装快照时会沿用上一轮包规则,建议 javadoc 注明。
  • extendsBlock 热路径(CubeSelection.java:193-196):新增的 mode() 每格做一次注册表反查 + 4 次 map 查询,而 extended 只在 install 时按 MODEL 过滤过(命中即必为 MODEL),可把廉价判断前移。
  • active() / isEnabled() 语义收窄(签名不变、javadoc 已更),下游若用它做渲染/拾取判断需要知会。

五、验证边界

未执行 Gradle 构建、runClient 或 JUnit;结论来自:静态读码 + 三点 diff 对账(7 文件,与 API 计数逐项一致)+ 1.21.8 官方混淆 client.jar 与 client_mappings 反汇编(obf:axh=MultiPackResourceManager、axf=FallbackResourceManager、axl=ReloadableResourceManager、gxb=GameRenderer、fue=Minecraft)+ 与同批 #276 / #277 / #279 / #280 / #281 的逐文件比对 + head CI。观感类结论(描边与动态部件是否跟手、outline 手感、F3+T 热换包)静态无法替代实机,建议按 model / outline / vanilla 三档各测一次,并覆盖「整包设成 model 触发预算」与「装带子空间坐标的重定向类模组」两种边界。

@Gugle2308 Gugle2308 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结论:PR #278 已合并(squash fdadb621,与 dev/1.21.8 tip 一致,合并树与 head 2870ee8a 完全相同),此前评论区只有 Roseau 的 API 报告;本次补做内容级复核,未发现本 PR 引入的阻塞缺陷,唯一实质跟进项是六条版本线里只有 1.21.1 带 CubePicking 的距离哨兵。

一、合并态与范围

判据 结果
state / merged / merged_at closed / true / 2026-11-14T11:13:05Z
merge_commit_sha fdadb621d54738db44a64289d1a50597df0c0137 = dev/1.21.8 tip
合并树 vs head 空 diff ⇒ 进主干的就是 2870ee8a
规模 7 文件 +194/−11,与 API 计数一致,diff 覆盖完整
head CI build / build ✅
既有评论 仅 Roseau API 报告(`cube

二、已验证的关键语义(1.21.8 官方混淆 client.jar + client_mappings 反汇编)

  1. 包优先级方向正确。 MultiPackResourceManager(obf axh)的 listPacks() 返回构造器 List.copyOf 存下的同一列表(axh.d),构造器按列表顺序 push 进 FallbackResourceManager(obf axf);axf.getResourceStack 从 size()-1 倒序取、末尾 Lists.reverse ⇒ 索引升序 = 低→高,CubeSelectionRules.java:43 的升序排序 + 顺序 merge 与 README 一致。
  2. 目录参数合法。 axh.a(String)V(checkTrailingDirectoryPath)只在路径 endsWith("/") 时抛 ⇒ 传 "anvillib" 正确;六条线该行为一致,可写进文档(路径不带尾斜杠)。
  3. 路径过滤跨 namespace 命中。 FileToIdConverter.fileToId 用 prefix.length() + 1 反推,反证返回的 id 带 anvillib/ 前缀 ⇒ :37 的 equals(PATH) 命中任意 namespace 下的同名文件。
  4. 规则取本轮包集。 ReloadableResourceManager(axl)的 createReload 顺序为 close 旧 → new axh → putfield axl.c → 派发。
  5. 逐帧链路成立。 GameRenderer.pick(float)(gxb.a(F)V)的调用方只有 Minecraft.tick()(fue.t)与 GameRenderer.renderLevel(gxb.a(Lftu;)V)⇒ 每帧一次,beginFrame 前移早于描边提取。
  6. 其余结论与同批 #276/#277/#279/#280/#281 相同:规则与几何成对发布、install 先写 rules 再重算、三种模式四消费点收敛、exclude 优先、整份文件校验后替换、公开面零增长。

三、唯一实质跟进项:六线对比,距离哨兵只在 1.21.1

版本线 PR distanceToHit 上界
1.21.1 #276 ✅ 有
1.21.4 #277 ❌ 无
1.21.8 #278(本 PR) ❌ 无(CubePicking.java:38-39 直接赋值)
1.21.11 #279 ❌ 无
26.1 #280 ❌ 无
26.2 #281 ❌ 无

1.21.1 的守卫处理「Entity.pick 返回被第三方模组重定向到远处/子空间坐标」(注释点名 Sable):先在 start.distanceToSqr(end) + 1e-7 处兜底返回原版结果。其余五条线会把该坐标直接喂给 BlockGetter.traverseBlocks(start, block.getLocation(), …) 逐格遍历整段射线(每格再跑 (2r+1)³ 次 getBlockState),且每帧一次;context.distance 同时失去「不超过射线长度」的上界。建议补到其余五条线,或在各线对应位置加注释固化其触发场景。

四、其他建议

  • ⚠️ 预算截断静默(六线通病):MAX_STATES = 32768 / MAX_GEOMETRY_BYTES = 16 MiB 超限只 unsupported++,而 CubeSelection.statistics() 全仓无调用者;namespace 级配置最容易撞上,表现为「一部分方块仍走原版行为」且无日志。建议在 CubeModelEvents.apply 里 unsupportedStates > 0 时打一条一次性 warn。
  • 💡 README 69–70 行连续两个空行(### Config 模块 在 71 行)。
  • 💡 packs.indexOf(...) 的 -1(CubeSelectionRules.java:39):命不中会被排成最低优先级(静默降级),可 Math.max(0, …) 或 debug 日志。
  • 💡 load() 的异常边界(:35、:37 在逐文件 try 之外):listPacks()/listResourceStacks() 抛 RuntimeException 会穿出监听器、让整次模型重载失败,外部资源包引发的问题应退化成 EMPTY。
  • 💡 公开重载 install(Snapshot)(CubeSelection.java:133)不重置 rules,第三方重装快照会沿用上一轮包规则,建议 javadoc 注明。
  • 💡 extendsBlock 热路径(CubeSelection.java:193-196):mode() 每格多一次注册表反查 + 4 次 map 查询,而 extended 命中即必为 MODEL,可把廉价判断前移。
  • 💡 active() / isEnabled() 语义收窄(签名不变、javadoc 已更),下游若做渲染/拾取判断需知会。

五、验证边界

未执行 Gradle 构建、runClient 或 JUnit;结论来自静态读码 + 三点 diff 对账(7 文件,与 API 计数逐项一致)+ 1.21.8 官方混淆 client.jar 与 client_mappings 反汇编(axh/axf/axl/gxb/fue)+ 与同批 #276 / #277 / #279 / #280 / #281 的逐文件比对 + head CI。观感类结论(描边跟手度、outline 手感、F3+T 热换包)静态无法替代实机,建议按 model / outline / vanilla 三档各测一次,并覆盖「整包设成 model 触发预算」与「装带子空间坐标的重定向类模组」两种边界。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants