Skip to content

Fix item splitter stack limits 修复物品分配器掉落物堆叠上限 - #5136

Merged
PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:fix/5135-splitter-stack-limit
Oct 2, 2026
Merged

PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:fix/5135-splitter-stack-limit

Conversation

@WhereisFff

Copy link
Copy Markdown
Contributor

按物品实际堆叠上限拆分每个目标位置的掉落物,保留均分份额、余数、零动量和拾取延迟。

修复 Anvil-Dev#5135
@Gugle2308

Copy link
Copy Markdown
Collaborator

代码审查摘要 — PR #5136

操作: opened(已确认现状:state=open、merged=false、mergeable=true;无重复评论风险)
范围: 1 个文件(1 Java)/ +15 −13 / diff 39 行
目标分支: dev/1.21/1.6(1.21.1 / NeoForge)
完整性核对: 已额外从 base 分支 dev/1.21/1.6 拉取 ItemSplitterBlockEntity.java 与 PR head 逐行 diff,结果与 patch 完全一致 → 该 PR 仅改 dropAt 一个方法,无隐藏改动、无 ghost 文件、无 EOF 缺失。

变更概要

private void dropAt(BlockPos target, ItemStack stack) {
    if (this.level == null) return;
    Vec3 center = target.getCenter();
    while (!stack.isEmpty()) {
        ItemEntity itemEntity = new ItemEntity(
            this.level, center.x, center.y, center.z,
            stack.split(stack.getMaxStackSize()),   // ← 按实际上限切分
            0, 0, 0);
        itemEntity.setDefaultPickUpDelay();
        this.level.addFreshEntity(itemEntity);
    }
}

📋 声称验证表

声称 状态 证据
按物品实际堆叠上限拆分掉落物 ✅ stack.split(stack.getMaxStackSize())(L289),循环至 stack 耗尽
保留均分份额 ✅ splitToSpace() 的 share = getTotalCount() / shares 与调用点未改动
保留余数(除不尽留在自身) ✅ extractTotal / break 逻辑未改动
保留零动量 ✅ 仍显式传 0,0,0(8 参数构造器,非 5 参数带随机动量版本)
保留默认拾取延迟 ✅ setDefaultPickUpDelay() 移入循环体内,每个实体都调用
fixed #5135 ✅ issue #5135「物品分配器被铁砧砸吐出超出堆叠上限的物品实体」(1.21.1 / snapshot-2385,open),根因与修法吻合

🔴 关键问题

无。

⚠️ 警告

  • ItemSplitterBlockEntity.dropAt()(L279) — 契约变更未写入文档:修改前 dropAt 不修改入参,修改后会把传入的 stack 清空(split() 逐次 shrink)。当前唯一调用方 splitToSpace() 传入的是 extractTotal() 返回的临时副本(result = extracted.copy(),非库存槽位引用),因此没有实际 bug;但 Javadoc「在指定位置以零动量抛出一份物品」建议补一句「调用后会清空 stack」,否则后续新增调用方复用同一 stack 会被静默吞掉物品(这类"隐式消耗入参"很容易在重构时踩坑)。

💡 建议

  • 建议提为局部变量并做下界保护:final int max = Math.max(1, stack.getMaxStackSize()); —— 既避免每次迭代重复读数据组件,也消除 max <= 0 时的理论死循环(split(0) 返回空 stack 且 shrink(0) 无效,while (!stack.isEmpty()) 永不退出)。正常路径不可达(max_stack_size 组件 codec 约束 1..99),属防御性改动,不阻塞。
  • 「切分行为」保留在抛出处而非限制 extractTotal 的 share 是正确取舍:同一个 share 仍需支持下发给容器的多槽大堆(走 ItemHandlerHelper.insertItem 时由各槽自行 clamp),不应在源头截断。

🟢 看起来不错

  • ItemStack.split(amount) 内部按 Math.min(amount, getCount()) 截断 → 循环不会丢物品、不会超发;不可堆叠物(上限 1)也自然退化为 1 个/实体,比原实现(10 把剑塞进 1 个实体)正确。
  • 出货路径未受牵连:splitToContainers() 的超限 portion 由 ItemStackHandler / 容器 insertItem 按槽上限收纳;insertBack() 的兜底走原版 Containers.dropItemStack,其自带 10~30 的分堆,本身安全。
  • 实体总数有界:内部 16 槽 × 上限 ⇒ 单次 dropAt 最多 16 个实体,总量守恒,无性能/刷实体风险。
  • 改动最小、无无关文件、无生成资源污染。

ℹ️ 下游行为备注(非阻塞,供维护者确认预期)

同一次 dropAt 打出的多个实体坐标、初速完全相同(完全重叠),原版 Containers.dropItemStack 是会随机散布的。后果是:同一格上的 16 个实体,漏斗每 8gt 只能吸走一个,自动化抽取节奏比"1 个超限实体"慢(但这就是正确行为的必然代价,且与玩家手动丢弃的原版表现一致)。若维护者希望散布,可加微小随机偏移/初速 —— 但那会与 PR 声明的"零动量"设计意图冲突,当前实现按 PR 描述是正确的。

🧪 测试建议

被测目标 推荐测试场景 优先级
ItemSplitterBlockEntity.dropAt() 16 槽装满 1024 个可堆叠物 + 铁砧落下(share > 上限):期望每目标格生成 ceil(share/64) 个 64 堆叠实体,实体计数之和 == 原数量 🔴
同上 不可堆叠物(16 把不同/相同剑):期望 16 个 1 堆叠实体,无合并成超限实体 🟡
同上 share 非上限整数倍 + 除不尽余数:余数仍留在分配器内部 🟡
实体交互 多实体完全重叠时:玩家拾取、漏斗抽取均正常,地面上不残留 count > 上限 的实体 🟢

结论: APPROVE — 修复点选得准(切分放在抛出处而非截断 share),split() 的截断语义保证不丢不超,PR 描述的四项保留全部成立,最小改动且与 issue #5135 完全对应。仅建议补 dropAt 的"消耗入参"文档 + 一行防御性 max 下界。

PR 标题 Fix item splitter stack limits 修复物品分配器掉落物堆叠上限 已准确(英文+中文),无需修改(本机 gh token 已失效,未做标题编辑)。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'anvilcraft-anvil-impact-review' (1 replacement). · Patched references/shell-only-diff-navigation.md in skill 'github-webhook-pr-review' (1 replacement). · Patched references/pr-class-routing.md in skill 'github-webhook-pr-review' (1 replacement).

@WhereisFff
WhereisFff marked this pull request as ready for review October 2, 2026 11:01
Copilot AI balanced review requested due to automatic review settings October 2, 2026 11:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Gugle2308

Copy link
Copy Markdown
Collaborator

代码审查摘要 — PR #5136

标题: Fix item splitter stack limits 修复物品分配器掉落物堆叠上限(标题准确,无需修改)
操作: ready_for_review
范围: 1 个文件 · Java 1 个 · +15 / −13 行(ItemSplitterBlockEntity.java)

diff 完整性已校验:patch-diff 与本地 git diff rvbase1216(94dd46d3)..rvhead5136(2060eff7) 除 hunk 上下文函数名外逐字节一致,无截断、无 ghost 文件、无跨界改动。


🔍 变更核实

- ItemStack stack 原样塞进 ItemEntity            // 单实体,count 可 > maxStackSize
+ while (!stack.isEmpty()) {
+     stack.split(stack.getMaxStackSize()), 0, 0, 0   // 按实际上限切分,逐个生成
+ }

追踪了唯一调用链 tick() → splitToSpace(shares) → extractTotal(share) → dropAt(target, portion):

检查点 结论
是否会真的产出超上限堆叠 ✅ 会。extractTotal() 跨 16 槽 grow() 累加,share = getTotalCount()/shares,shares=1 时可达 1024;与 issue #5135「均分后超过该物品堆叠上限」完全对应
dropAt 是否只此一处调用 ✅ 仅 splitToSpace(第 150 行),修复覆盖面完整
split() 参数被消耗是否影响调用方 ✅ 安全。portion 是 extractTotal 内 extracted.copy() 产生的新实例(ItemStackHandler.extractItem 返回的引用已被 .copy() 隔离),且调用方每次循环都重新赋值、用后即弃,不会二次读取
循环可终止性 ✅ getMaxStackSize() 对非空堆叠恒 ≥ 1,每轮至少消耗 1,不会死循环
数量守恒 ✅ split 不丢失物品;moved=true 的判定仍基于 portion.isEmpty(),语义未变
声称保留的行为 ✅ 0,0,0 零动量保留;setDefaultPickUpDelay() 保留;@param shares 均分/余数留在自身的语义未触碰

另一个正向点: 同位置零动量的多个实体在后续 tick 会走 ItemEntity 的邻居合并,而合并上限即 getMaxStackSize(),因此修复后的状态是自稳定的——不会出现「合并回去又超上限」的回退。


💡 建议(非阻塞)

  • dropAt 的 javadoc 未反映新的副作用:@param stack 待抛出的物品 现在实际是「会被 split() 消耗的堆叠」。同类方法 OverflowChuteBlockEntity 用的是 stack.copy()(调用方语义为不消耗),本方法改为消耗式,建议补一句 (会消耗传入的堆叠),或改为在方法内先 stack.copy() 再切分,避免未来调用方踩坑。
  • 与原生 Containers.dropItemStack 的差异:原版(本文件 insertBack 的回退路径第 270 行也在用)按 random.nextInt(21)+10 切分并附带微小随机偏移,使实体略有散开;此处按 getMaxStackSize() 切分、位置与动量完全相同,多个实体会重叠成一堆再合并。这符合 PR「保留零动量」的意图,若希望视觉上不重叠,可加 ±0.1 级的随机位置偏移而不动动量。

🟢 结论

APPROVE — 最小改动、行为等价、无副作用外溢。修复精准命中 #5135(snapshot-2385,铁砧砸分器均分后单实体超堆叠上限),无阻塞问题;上面两条仅为文档/风格层面的可选改进。

🧪 测试建议

被测目标 推荐场景 优先级
dropAt() 16 槽塞满 64 个物品、shares=1 → 断言产出 16 个 count=64 的 ItemEntity(而非 1 个 1024) 🔴
dropAt() 上限为 1 的工具类物品(share=8)→ 断言生成 8 个 count=1 实体 🟡
dropAt() / splitToSpace() share 恰好等于上限(64)→ 断言只生成 1 个实体,未产生退化行为 🟢

备注:gh auth status 显示当前 token 已失效(Gugle2308),故未执行 gh pr edit;本 PR 标题本身已符合 <英文标题> <中文标题> 格式,无需修改。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'anvilcraft-anvil-impact-review' (1 replacement). · Patched references/item-drop-stack-limit-split-review.md in skill 'anvilcraft-anvil-impact-review' (1 replacement).

@PigeonNian
PigeonNian merged commit da7e856 into Anvil-Dev:dev/1.21/1.6 Oct 2, 2026
2 checks passed
@Gugle2308

Copy link
Copy Markdown
Collaborator

PR #5136 状态为 closed,按 webhook 审查约束第 1 条(closed/labeled → 停止),不再进行审查,也不会发布任何评论。

未执行任何 diff 下载或评论操作。如需对已关闭/已合并的 PR 做事后审查,请显式告知,我再单独处理。

PigeonNian added a commit that referenced this pull request Oct 3, 2026
…修复到26.1 (#5143)

* The text regarding celestial death has been corrected, and some progress has been made. 修正了天体死亡文本,增加了一些进度 (#5129)

* feat(advancement): 添加天体进化挑战成就及触发器

- 新增 CelestialEvolutionTrigger 用于天体质量进化判定
- 在触发 util 中添加 celestialEvolution 方法,触发成就判定
- 在加速器逻辑中调用触发方法进行成就检测
- 添加无残留(no_remnant)挑战成就,要求64质量铁砧的天体进化至终局
- 将成就文本翻译添加至英文语言文件和特殊字符文件
- 在成就数据中注册无残留成就及其触发条件

* feat(advancement): 添加行星毁灭成就及触发器支持

- 新增PlanetDetonationTrigger用于行星毁灭事件的判定
- 在ExcavatorHandler中增加触发行星毁灭触发器的逻辑
- 在AdvancementLineHelper中集成planetDetonation方法方便创建该成就
- 在AnvilCraftAdvancement中添加efficiency成就分支,绑定行星毁灭触发器
- 更新语言文件,添加行星毁灭成就的标题与描述
- 注册PlanetDetonationTrigger触发器并完善其触发实现
- 新增efficiency成就JSON配置文件,定义触发条件及显示信息

* feat(advancement): 新增因行星坍缩死亡的成就触发器

- 添加了 PlanetaryCollapseDeathTrigger 触发器类及其数据结构
- 在 ModCriterionTriggers 中注册 planetary_collapse_death 触发器
- 在 AdvancementLineHelper 中新增 planetaryCollapseDeath 方法便于调用
- 在 AnvilCraftAdvancement 中添加 Cannon Fodder 成就,绑定行星坍缩死亡触发器
- 在语言文件中添加 Cannon Fodder 成就标题与描述的多语言支持
- 在 OverworldLikeEventListener 中监听行星坍缩死亡事件并触发相应成就
- 在 TriggerUtil 中实现 planetaryCollapseDeath 方法来触发成就判定
- 新增 Cannon Fodder 成就的 JSON 配置文件,包含父级与图标等信息
- 修改效率成就添加隐藏属性,改善游戏内成就展示体验

* feat(advancement): 新增黑洞和中子星终局星体成就

- TriggerUtil新增支持根据StellarTerminal.Kind触发星体演化成就
- CelestialEvolutionTrigger增加对终局类型的判定和对应触发方法
- AdvancementLineHelper新增celestialEvolution重载方法支持终局类型参数
- AnvilCraftAdvancement中增加黑洞和中子星分支成就定义和保存
- AdvancementLang添加黑洞与中子星成就名称及描述多语言支持
- 语言文件(en_us, en_ud)增加对应成就的描述和标题
- 新增黑洞和中子星成就JSON数据文件,定义触发条件和显示信息

* feat(damage): 新增天体接触伤害类型及独立标签支持

- 添加黑洞接触、恒星接触及行星接触三种新伤害类型
- 天体接触伤害采用独立类型以实现专属死亡提示
- 更新伤害标签,支持新伤害类型绕过护甲、抗性、击退等效果
- 修改重力控制器中伤害来源,替换为对应新天体接触伤害类型
- 保持星体及行星接触伤害原版燃烧和摔落效果表现不变
- 增加对应的语言文本显示新伤害的死亡描述信息
- 修正玩家攻击混入对行星接触伤害的判定,保持原摔落伤害一致性
- 新增相关资源数据文件,完善伤害类型和标签配置

* feat(advancement): 添加“夜晚来访”星接触死亡进度条件

- 新增 StarContactDeathTrigger 实现星接触死亡触发器
- 注册并初始化星接触死亡触发条件 ModCriterionTriggers.STAR_CONTACT_DEATH
- AdvancementLineHelper 新增 starContactDeath 方法支持该触发器
- AnvilCraftAdvancement 新增“come_at_night”任务,使用星接触死亡触发器
- AdvancementLang 中添加“come_at_night”进度名称及描述文本
- OverworldLikeEventListener 监听星接触死亡事件触发进度
- TriggerUtil 新增 starContactDeath 方法简化触发调用

* feat(locale): 添加“come_at_night”成就的中英文描述

- 新增“advancements.anvilcraft.come_at_night”标题的本地化文本
- 新增“advancements.anvilcraft.come_at_night”描述的本地化文本
- 中文描述内容为“被星光笼罩”
- 英文标题内容为“Showdown at Night”倒转样式

* feat(advancement): 添加“come_at_night”隐藏成就

- 创建新的隐藏成就“come_at_night”
- 设置成就触发器为“star_contact_death”
- 指定成就图标为“celestial_forging_anvil”
- 定义成就的父级为“the_start”
- 启用成就的遥测事件发送

---------

Co-authored-by: Pigeon_Nian <adove2005@163.com>

* fix(celestial): 修复演化音效衰减与锻造界面恢复 (#5131) (#5132)

- 将演化音乐归入唱片音量分类,并以单声道音源实现 64 格原生距离衰减。
- 保持音效与字幕的听距一致。
- 通过实时同步入口恢复锻造状态,避免重开界面时丢失正在锻造的进度。

* fix(building): 修复幻灵铁砧虚影撤销时重复返还物品 (#5134)

- 撤销无掉落幻灵铁砧虚影时不再结算基础物品
- 保留实体铁砧与其他下落方块的资源结算

fixed #5133

* fix(item-splitter): 修复物品分配器掉落物超出堆叠上限 (#5136)

按物品实际堆叠上限拆分每个目标位置的掉落物,保留均分份额、余数、零动量和拾取延迟。

修复 #5135

* fix(button): 修复大红按钮遮挡边缘交互与按压动画 (#5141)

- 使用实际命中位置进行服务端射线校验,修复按钮可见但底座中心被遮挡时无法按下的问题。
- 按住按钮后等待服务端确认再播放手部动画,并忽略已释放或已切换目标的过期确认。
- fixed #5138

* fix(storage-port): 修复服务端扫描仓储端口时崩溃 (#5140)

- 优先使用原版 includeData 标志控制数据复制,避免服务端扫描读取客户端按键状态
- 保留 26.1 服务端中键克隆时的缓存、标记与流体数据

(cherry picked from commit d7c2f74)

---------

Co-authored-by: PigeonNian <78527064+PigeonNian@users.noreply.github.com>
Co-authored-by: Pigeon_Nian <adove2005@163.com>
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.

[Bug] 物品分配器被铁砧砸吐出超出堆叠上限的物品实体

4 participants