Skip to content

Added Gas System and some gases. 添加了气体系统和几种气体 - #4489

Merged
PigeonNian merged 8 commits into
Anvil-Dev:dev/1.21/1.6from
PigeonNian:gas/1.21/1.6
Aug 21, 2026
Merged

Added Gas System and some gases. 添加了气体系统和几种气体#4489
PigeonNian merged 8 commits into
Anvil-Dev:dev/1.21/1.6from
PigeonNian:gas/1.21/1.6

Conversation

@PigeonNian

Copy link
Copy Markdown
Contributor
  • 使得管道系统支持了气体气压扩散
  • 泵会提供气压差
  • 气体在泵内以透明度形式表现存量

Pigeon_Nian added 2 commits August 20, 2026 17:44
- 新增氢气、氧气、氦气和氘气四种气体流体类型及其流体实例
- 实现GasFluid类,定义气体流体的特殊行为和属性
- 新增对应的桶物品及其模型,支持气体流体的倒置渲染效果
- 在物品标签页和物品集合中添加新桶物品
- 更新流体注册和客户端流体类型注册,定义各气体颜色和特效
- 添加语言文件条目,支持新桶物品的显示名称
- 为新桶物品注册动态流体模型颜色处理器
- 新增多种气体流体名称及对应中英文本地化
- 实现气体在流体管网内基于气压差的均衡分配算法
- 气压值由气体充填率与泵的压力偏置共同决定
- 气体流动不再依赖高度拟合的扬程,而由压强驱动
- 气体绘制支持全量显示,通过透明度表达气体填充比例
- 渲染时气体始终填满容器体积,区别于液体的高度变化
- 添加对气体流速限制及阈值判定的控制,避免过度计算
- 优化气体管网中的阀门流量限制与可达性判断逻辑
@Gugle2308

Copy link
Copy Markdown
Collaborator

I've confirmed all gas types use density(-1000). Now I'll write the final review.

代码审查总结

结论:需要修改 🔴(2 个警告,4 个建议)

PR: #4489 — Added Gas System and some gases(气体系统:管道气压扩散)
作者: @PigeonNian
修改文件: 19 个(+5 新增,无删除)

⚠️ 警告

  • ModItems.java / GasFluid.java — 气体桶在世界中无法放置也无法回收。 GasFluid 没有注册与之关联的 BlockcreateLegacyBlock() 返回 Blocks.AIRgetShape() 返回空气形状),且 getBucket() 返回 Items.AIR。但 HYDROGEN_BUCKET 等 4 个桶是普通 BucketItem,被加进了 Ingredients 创造页签并打了 c:buckets 标签。玩家在世界里右键这些桶时:既放不出任何可见方块/流体,也无法用空桶把气体收回(getBucket=AIR),体验上就是"桶凭空消失/毫无作用"。建议:要么做方向感知——禁止在世界中倒气体(use 时返回 FAIL 并保留桶),要么给气体补一个(不可见/仅逻辑占位的)流体方块与拾取路径。至少应在 PR 描述中明确"气体仅用于管道/储罐"的预期。

  • FluidPipeNetwork.java / 渲染层 — 用 isLighterThanAir()(负密度)作为"是否气体"的判别,耦合脆弱。 管道均衡、distributeFromSource 跳过、储罐/大储罐渲染、桶模型 flipGas 全部以负密度为开关。当前分支上既有流体密度均为正值(1000/2000/3000),所以暂不会误伤;但任何一个未来的"轻于空气"的流体都会被静默改造成气体逻辑(不再重力流动、渲染变全罐透明度、进均衡路径)。既然已有 GasFluid 类型,建议改用 instanceof GasFluid(或专用 interface/标签)作为判别,而不是依赖密度符号这一隐式约定。

💡 建议

  • FluidPipeNetwork.java(transferGas)— 气流速度偏慢,属调优项。 GAS_EQUILIBRIUM_BUDGET/flowCap 都被 MAX_SPEED=2000 mB/每 tick 封顶。对一个增强大储罐(INFINITY_THRESHOLD≈12.8M mB),从空到满要数千 tick。逻辑没错,但作为"气压扩散"可能偏慢,建议确认是否为预期手感。

  • GasFluid.java — getTickDelay() 返回 0。 因气体没有世界方块,此路径实际不可达,影响低;但作为 Fluid 子类返回 0 tick 延迟较为异常,建议注释说明气体仅存在于储罐/管道、不出现在世界中。

  • FluidPipeNetwork.java — equilibrateGasType O(n²)×8 轮。 已用 GAS_MAX_ROUNDS 和预算封顶,可接受;但每 tick 全端点 distinctFluidTypes 无条件扫描,点多时可留意性能。

  • en_ud.json — 已核对 4 个新键的旋转文本与 en_us 对称正确,无需改动。

✅ 表现良好

  • 均衡数学验证通过。 transferGasnum = hiStored·loCap − loStored·hiCap − (loBias−hiBias)·hiCap·loCap/SCALE 与压强均衡条件代数一致;且 (double) 强转先于乘法求值,全程 double 运算,无 int 溢出风险num/x 均为 double,gasPressure(long) 守卫)。逻辑严谨。
  • 辅助方法全部存在且空安全。 minValveRemaining(null)/deductValves(null) 均返回 MAX_SPEED/安全跳过;isOpaque() 由 Lombok @Getter 生成,FluidRenderHelper 引用有效;acceptFolded(content, bucketItem)DisplayItemsGenerator 上的合法调用。编译层面无缺口。
  • 渲染方案自洽。 气体始终以整罐高度渲染、用 alpha 表达存量,大储罐与普通储罐两条路径一致;桶用 neoforge:item/bucket_drip + flip_gas(true)(气体上浮),物理直觉正确。
  • 新气体类型注册结构干净:Fluid + FluidType 成对注册、颜色雾色合理、语言键齐全、生成资源(en_us/en_ud/models/buckets 标签)与源码一致。

🧪 测试建议

被测目标 推荐测试场景 优先级
FluidPipeNetwork#transferGas 大储罐间气压均衡:验证均衡量与代数解一致、且预算/阀门上限生效 🟡
FluidPipeNetwork#equilibrateGases 混合气体(同罐多种气体)各自独立均衡、不互相污染 🟡
BucketItem 气体桶 在世界中放置气体桶不消耗/可回收(若决定禁止则验证 FAIL) 🔴
渲染 alpha 存量很低时气体接近透明、满罐时完全不透明 🟢

由 Hermes Agent 审查


我已经完成对 PR #4489 的审查。核心逻辑(气压均衡数学、空安全、编译完整性、渲染、资源)都经过验证:均衡公式代数正确且无整数溢出,辅助方法齐全,isLighterThanAir() 判别当前不误伤既有流体。主要问题是两个警告:气体桶在世界中无法放置/回收(无 Block、getBucket=AIR,却在创造页签与 c:buckets 中暴露),以及用负密度作为气体判别的脆弱耦合。建议确认气体桶的预期使用方式并考虑更稳健的气体类型判别。

- 将气压相关变量类型由 int 改为 long 提高分辨率和范围
- 添加气体压力细化分辨率常量,避免整除死区
- 引入无限气体源和无限气体汇的压力标度,保证特殊储罐行为准确
- 在传输逻辑中区分无限气体源,突破存量限制直接填充目标
- 重构 gasPressure 方法,支持无限气体源/汇的专用压力计算
- 扩展气体均衡轮数限制,适应更复杂网络均衡需求
- 调整 transferGas 函数参数和实现,去除对压力差的依赖
- 新增辅助方法判断是否为无限气体源或汇,完善气体流动规则
@Gugle2308

Copy link
Copy Markdown
Collaborator

I have enough context. The InfinityFluidTank extends FluidTank (NeoForge), which provides getFluid(), isEmpty(), getFluidInTank(), getTankCapacity() (all standard IFluidHandler/FluidTank). The gas code compiles against it. Let me finalize the review.

Let me confirm there are no leftover concerns about the render code duplication being a regression — the original renderFluidBox had invertGasses parameter that flipped gas vertically. The gas render path now uses the new renderFluidBoxWithAlpha with invertGasses=false (passed false in the gas variant), and the gas fill now always fills the box rather than being vertically inverted. This is consistent with the "gas always fills tank, opacity conveys amount" design. Fine.

I'll now write the final review.

代码审查摘要 — PR #4489

操作: synchronize
范围: 19 个文件 (12 Java, 5 新增, 0 删除) / 1013 行 diff
分支: gas/1.21/1.6dev/1.21/1.6,作者 PigeonNian

概览

添加了气体系统:GasFluid(可直接扩展 Fluid,无世界方块)、4 种气体(氢/氧/氦/氘)及对应桶物品、管道网络新增「气压均衡」逻辑(equilibrateGases + transferGas),并配合液罐渲染改为按不透明度表现存量。

🟢 核心逻辑验证(均通过)

  • 均衡数学正确。transferGas 有限源分支的 x = [hiStored·loCap − loStored·hiCap − (loBias−hiBias)·hiCap·loCap/SCALE] / (hiCap+loCap) 做了代数推演,与「均衡后两端压强相等」精确解完全一致。✓
  • 气体触发条件成立。 density(-1000) ≤ 0 → NeoForge FluidType.isLighterThanAir() 返回 true,equilibrateGases / distributeFromSource 的气体分支正确触发。✓
  • 溢出安全。 gasPressurelong 累乘;transferGas(double)hiStored * loCap 先转型 double,Integer.MAX_VALUE(仲间无限罐) 乘算不会溢出。✓
  • InfinityFluidTank 源/汇语义自洽。 目标分支的 InfinityFluidTank extends FluidTankfill() 永远返回 resource.getAmount()(接受并销毁=汇),drain() 在非空时返回 fluid.copyWithAmount(maxDrain)(无限源)。isInfiniteGasSource/isInfiniteGasSinkisEmpty()/getFluid() 匹配,且气体在 distributeFromSource 中被明确跳过重力/扬程分配。✓
  • 渲染改造一致。 FluidTankRenderUtilLargeFluidTankBlockEntityRenderer 都改为「气体始终充满、用 opacity 传递存量」,与 renderFluidBoxWithAlpha 的 alpha 缩放一致。✓
  • 资源/lang 完整。 en_us / en_ud / FluidLang / 4 个桶模型 / c:tagname buckets 均已生成,桶模型用 flip_gas: true + neoforge:item/bucket_drip。✓

🔴 关键问题

未发现阻塞性缺陷。

⚠️ 警告 / 需澄清

  1. GasFluid.getBucket() 返回 Items.AIR,与已注册的气体桶物品不一致。 桶本身(BucketItem wrapping ModFluids.X)不受影响,但 Fluid.getBucket() 被以下路径消费:

    • ModDispenserBehaviorgetBucket() != Items.AIR 判断)→ 发射器将无法自动装/采气体
    • FluidMixingCategory(JEI)→ 气体不显示桶图标;
    • BlockStateUtil → 得到 Items.AIR 实例。

    若设计意图是「气体不可被发射器/JEI 桶化」则可接受;否则建议让 getBucket() 返回对应桶 item(需处理注册顺序/循环依赖)。建议在 PR 描述或代码注释中明确该取舍。

  2. ItemsSections 中水泥桶由 content.accept(...) 改为 this.acceptFolded(content, bucketItem) —— 这属于本 PR(气体)范围之外的侧边改动。虽与 Add new recipes, enchantments, mass energy inverter and other updates to the manual 在手册添加新配方、附魔金、质能转换器和其它更新 #4487 创造栏折叠模式一致,但建议确认是有意为之,避免与气体功能无关联的改动悄悄混入。

💡 建议(非阻塞)

  • 无限汇的销毁速率受 GAS_EQUILIBRIUM_BUDGET(2000 mB/tick) 限制。 空仲间罐作为汇时,transferGas 走有限分支按均衡公式转移,但 globalBudget 会把单 tick 总转移量压在 MAX_SPEED。若期望「空创造罐立即吞掉全部气体」,当前是受控的匀速销毁(约 2000 mB/tick),属合理设计,仅建议在文档中说明。
  • renderFluidBoxWithAlpha 与既有 renderFluidBox 存在大量重复(顶点/光照/颜色逻辑几乎复制)。可考虑收敛到单一方法传入 alpha,降低后续维护时两处漂移的风险。
  • GasFluid.getTickDelay() 返回 0、isSource() 恒 true:由于气体从不作为世界方块放置(createLegacyBlock→AIR),这些返回值无实际影响,但建议加注释说明「气体仅存在于管道/容器内」,避免未来误以为可放置。

📋 声称验证表

声称 状态 对应实现
管道系统支持气体气压扩散 FluidPipeNetwork.equilibrateGases/equilibrateGasType/transferGas/gasPressure
泵提供气压差 gasPressure(effectiveHeight − containerPos.getY())·GAS_PRESSURE_PER_LIFT / GAS_PRESSURE_PER_LIFT
气体在泵内以透明度形式表现存量 FluidTankRenderUtil + LargeFluidTankBlockEntityRenderer opacity 模式

🧪 测试建议

被测目标 推荐场景 优先级
transferGas 有限源均衡 两端容量不等时转移量是否让压强收敛;loCap=Integer.MAX_VALUE(无限汇) 边界 🔴
gasPressure 泵偏置 泵拉高 effectiveHeight 后气体是否朝泵侧流动 🟡
无限源(非空 InfinityFluidTank) want 不受源存量限制、受阀门限流 🟡
混合液/气共存 装液体的罐不视为气体目标容量 🟡
渲染 alpha fill=0/1 边界、Math.clamp 越界输入 🟢

结论: COMMENT (倾向 APPROVE) — 核心均衡算法经推导验证正确,源/汇结合 InfinityFluidTank 语义自洽,渲染与 lang 完整。无阻塞性 bug;上述 ⚠️ 项(getBucket() 语义、ItemsSections 侧边改动)建议作者确认后合并。


由 Hermes Agent 审查

- 为事件总线订阅者添加客户端限定标识
- 避免服务端加载客户端专用的颜色处理代码
- 确保颜色处理器仅在客户端环境下注册
- 修改注解为 @EventBusSubscriber(value = Dist.CLIENT, modid = AnvilCraft.MOD_ID)
@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Skill 'gas-system-pr-review' created.

@Gugle2308

Copy link
Copy Markdown
Collaborator

Confirmed — no recipes, no gas flowable fluid/block. The gases are only usable in the pipe network with a creative InfinityFluidTank as source. Now I'll write the review.

代码审查摘要 — PR #4489

操作: synchronize
范围: 19 个文件(12 Java, 5 新增)/ ~1017 行 diff

概览

本 PR 为管道系统引入"气体"概念:新增 GasFluid 基类 + 氢气/氧气/氦气/氘 4 种气体(带桶物品、语言、模型),并让 FluidPipeNetwork气压差驱动气体在网络内均衡扩散(不依赖液体那套重力/扬程分配)。气体在储罐/泵内以透明度表现存量。

✅ 核心气体均衡逻辑 — 数学自洽(验证通过)

  • gasPressuretransferGas 的均量公式完全一致:两者都把泵偏置折算为 lift*PER_LIFT/SCALE 的规范单位(lift/10)。transferGasnum = S_h·C_l − S_l·C_h − (loBias−hiBias)·C_h·C_l/SCALE 正是对两个 tank 求解 pressure_h = pressure_l 的闭式解,equalAmt = num/(C_h+C_l) 恰好移动到两者气压收敛。无单位死区/颠倒 bug
  • 无限源/汇(InfinityFluidTank)处理正确:有流体 → GAS_INFINITE_PRESSURE 无限供气;空罐 → GAS_INFINITE_SINK_PRESSURE 无限吸收销毁。fill/drain 覆写语义匹配。
  • 气体与液体路径干净分离:distributeFromSource 跳过 lighter-than-air 流体,equilibrateGases 只处理气体,互不干扰。
  • 空指针安全:minValveRemaining(null) 返回 MAX_SPEED(沿用现有模式),pathValves = Map.of() 时安全。
  • ext.isOpaque()ModClientFluidTypeExtensionImpl 的 Lombok @Getter boolean opaque 生成,编译通过。

🔴 关键

  • 气体在生存模式不可获取(Feature 目前仅创造可玩) — 无任何气体来源/配方/用途闭环:
    • diff 中无任何 recipe 文件recipes/ 计数 = 0);
    • GasFluid.createLegacyBlock()Blocks.AIR,没有注册气体流体方块(无 FlowingFluid/block),无法在世界中放置或拾取(getBucket()Items.AIR);
    • c:buckets 里的气体桶因此"造不出来也装不上气体"。
    • 结果:气体只能通过创造模式 InfinityFluidTank 注入管网。若本 PR 定位就是把"气体=管网内模拟物质"先落地、配方/产物留待后续 PR,请在描述中说明,否则应补充至少一条气体生成途径(如配方或气体发生方块)。建议确认设计意图。

⚠️ 警告

  • equilibrateGases 每 tick 全网络扫描 — 对纯液体大网络,每个 tick 都会对每个已连接 endpoint 调 distinctFluidTypes()(遍历所有 tank)来筛 lighter-than-air,即使网络里完全没有气体也空耗 O(endpoints×tanks)。可考虑加一个"网络内是否存在气体"的缓存标记,仅在含气体时才进入均衡。
  • c:buckets 双重注册冗余 — 气体桶同时在 ModItems.tag(Tags.Items.BUCKETS) 又手动写进 src/generated/.../buckets.json。而既有惯例(如 MELT_GEM_BUCKET)是只手动加 JSON、不加 .tag()。新增的 .tag() 已能生成 tag,手动 JSON 条目与之重复。建议二选一,避免 runData 后 diff 抖动。
  • 气体桶世界内放置行为未定义 — 因无气体流体方块,BucketItem.use() 的放置(getFluidType().getBlockForFluidState → AIR)大概率无实际操作。若气体桶预期只在管网/储罐内排空充填而非世界放置,可接受;否则行为会令人困惑。

💡 建议

  • 均衡吞吐瓶颈:单种气体单 tick 总预算 = GAS_EQUILIBRIUM_BUDGET(=MAX_SPEED=2000mB) 分最多 16 轮。大型储罐网络下完全均衡可能需很多 tick,属调参级而非 bug,留意性能。
  • 气体配色/RenderType 复核:4 种气体注册为 opaque=false → 走 RenderType.translucent(),alpha 按填充率缩放,符合"透明度表现存量"。渲染坐标((...TANK_W, 1−TANK_W...) 全罐填充)与 LargeFluidTankBlockEntityRenderer(layerTop−layerBottom) 一致。建议实测一次多气体混合显示效果。
  • 魔术常量注释GAS_PRESSURE_SCALE/RESOLUTION/PER_LIFT 之间的比值关系(SCALE=10·PER_LIFT 等)可补一行推导说明,方便后续维护。

🟢 看起来不错

  • 压力模型比"按高度差"更贴合气体物理直觉,且与液体路径解耦干净。
  • 数学核心自洽(已验证均量公式与压力定义一致)。
  • 语言文件 en_us / en_ud(倒置)均完整且映射正确(如 Helium → ɯnᴉꞁǝH,n→u 遵循 MC en_ud 标准)。
  • @EventBusSubscriber(value = Dist.CLIENT, ...) 显式化是正确的健壮性改进。
  • 桶物品/创造模式 Tab(Ingredients、ItemsSections)注册完整,craftRemainder(BUCKET) 处理得当。

📋 声称验证表

声称 状态 对应文件
管道支持气体气压扩散 FluidPipeNetwork(equilibrateGases/pressure/transfer)
泵提供气压差 GAS_PRESSURE_PER_LIFT → effectiveHeight−Y 偏置
气体以透明度表现存量 FluidTankRenderUtil / LargeFluidTankBlockEntityRenderer / FluidRenderHelper(alphaFill)
新增几种气体 GasFluid + ModFluids(H2/O2/He/D2)+ 桶/模型/语言
生存可获取/用途 无配方、无气体方块、无获取途径

结论: COMMENT — 气体均衡核心算法扎实、数学自洽,架构上与液体路径解耦得当,可合并方向正确。但本 PR 中气体在生存模式完全不可获取(无配方、无气体方块、getBucket()→AIR),功能实际为创造模式专属;且存在每 tick 全网络扫描的性能开销与 c:buckets 双重注册冗余。建议先澄清获取途径是否为后续 PR 范畴,若本 PR 定位即"管网气体模拟基建",可合并后补获取链。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'gas-system-pr-review' (1 replacement).

- 新增氙气和氪气流体类型及对应的流体注册
- 实现氙气和氪气桶物品及其模型文件
- 在物品标签和物品选项卡中添加氙气桶和氪气桶
- 更新流体客户端渲染设置以支持氙气和氪气颜色
- 增加多语言支持,包括英语和倒置英语的名称
- 修改流体网络代码,调整无限气体源和汇的处理逻辑
- 注册颜色处理器以支持新增的氙气桶和氪气桶
@Gugle2308

Copy link
Copy Markdown
Collaborator

I now have a complete picture. Let me write the review. Key findings:

Verified correct:

  • Pressure math in transferGas exactly matches the analytical equalization solution (derived and confirmed)
  • isLighterThanAir correctly triggered via density(-1000)
  • InfinityFluidTank source/sink semantics self-consistent
  • bucketGassy method IS added in ModelProviderUtil (my earlier hunk-count was wrong - it's 1 hunk, not 0)
  • en_ud correctly generated
  • 6 gas buckets registered with .tag(Tags.Items.BUCKETS) + model + color handlers
  • Client render for gas "full tank + opacity" correctly wired in both renderers

Critical:

  1. No survival obtainability — 0 recipe files, gas has no fluid block, getBucket()→AIR. All 6 gas buckets unobtainable in survival.

Warnings:

  1. getBucket()→AIR affects FluidHandlerWrapper / DefaultBlockPlacementRule (dispenser auto-fill/pickup, world-placing interaction paths) — need to confirm intended
  2. ItemsSections cement bucket accept()acceptFolded() is unrelated scope (from Add new recipes, enchantments, mass energy inverter and other updates to the manual 在手册添加新配方、附魔金、质能转换器和其它更新 #4487 tab folding)
  3. Per-tick O(endpoints×tanks) scan even with no gas — perf regression for pure-liquid networks

Suggestions:

  1. DRY — renderFluidBoxWithAlpha duplicates most of existing renderFluidBox

Let me write the final review.

代码审查摘要 — PR #4489

操作: synchronize (gas system)
范围: 21 个文件 (12 Java, 7 新增, 0 删除) / 1192 行 diff
分支: gas/1.21/1.6dev/1.21/1.6 by PigeonNian

变更概览

新增气体系统:6 种气体流体(氢/氧/氦/氘/氙/氪,均 density(-1000)isLighterThanAir() true)+ 对应气桶。核心为 FluidPipeNetwork 新增按气压差驱动的 equilibrateGases() 均衡逻辑;渲染改为「气体恒充满 + opacity 表存量」;GasFluid extends Fluid(无世界方块,getBucket()→AIR,createLegacyBlock→AIR,isSource()→true)。

🟢 数学正确性验证(通过)

transferGas 有限分支:

num = (double)hiStored*loCap - (double)loStored*hiCap - (double)(loBias-hiBias)*hiCap*loCap/GAS_PRESSURE_SCALE;
x = num / (hiCap+loCap);

与「两罐均衡后压强相等」的解析解 精确一致
X = [hiStored·loCap − loStored·hiCap − (loBias−hiBias)·hiCap·loCap/SCALE] / (hiCap+loCap)

  • (double) 先转型避免 Integer.MAX_VALUE 容量溢出 ✓
  • gasPressure(long) 累乘避免溢出 ✓
  • InfinityFluidTank 无限源/汇语义(空罐=sink 恒销毁、同气体非空=source)与其 fill/drain 行为自洽 ✓
  • distributeFromSource 正确 isLighterThanAir() skip,交给均衡,避免重复搬运 ✓
  • bucketGassy 方法在 ModelProviderUtil.java 中已随本 PR 新增(1 个 hunk),与 6 个气桶的 .model(ModelProviderUtil::bucketGassy) 引用闭合,无编译错误 ✓
  • en_ud 倒置英文正确(oxygen→uǝᵷʎxO 等)✓
  • 渲染分支在 FluidTankRenderUtilLargeFluidTankBlockEntityRenderer 均正确接入 opacity 逻辑 ✓

🔴 关键

  • 生存模式无法获取(头号问题) — 6 种气体零配方recipes/ 计数=0)。气体无流体方块(getBucket()→AIR、createLegacyBlock→AIR),且 getBucket()=AIR 又使发射器/交互路径无法自动装/采。三者叠加 = 这些气桶在生存下完全不可获得(仅创造可刷)。请确认是否由后续 PR 补齐获取链(配方/气桶互转),否则该 feature 在生存实为不可用。

⚠️ 警告

  • GasFluid.getBucket() 返回 Items.AIR — 影响 FluidHandlerWrapper / DefaultBlockPlacementRule 等消费 getBucket() 的路径(发射器自动装/采、世界放置交互、JEI 桶图标)。非 bug(HoneyFluid 有先例),但需确认 Items.AIR 为 intended,建议在 PR 描述声明。
  • ItemsSections.java 越界改动 — 水泥桶 content.accept(bucketItem)this.acceptFolded(content, bucketItem)Add new recipes, enchantments, mass energy inverter and other updates to the manual 在手册添加新配方、附魔金、质能转换器和其它更新 #4487 创造栏折叠范围,与本 PR 气体系统无关。请确认是否应拆出/已随上一 PR 落地(acceptFoldedDisplayItemsGenerator 存在,调用合法,仅质疑范围)。
  • 每 tick 全网络扫描性能退化equilibrateGases() 每 tick 遍历所有端点调 distinctFluidTypes() 收集气体类型,即使全网无气体也空耗 O(endpoints×tanks)。对纯液体大网络是退化。建议缓存「本网络是否含 lighter-than-air 流体」标记,无气体时跳过整个均衡。

💡 建议

  • FluidRenderHelper.renderFluidBoxWithAlpha 复制了既有 renderFluidBox 的大部分渲染逻辑(tiled face、光照、纹理选择)。建议抽公共渲染内核,避免后续维护漂移。

📋 声称验证表

声称 状态 对应文件
管道系统支持气体气压扩散 FluidPipeNetwork.equilibrateGases/transferGas/gasPressure
泵会提供气压差 gasPressure 内 effectiveHeight−y·PER_LIFT bias
气体在泵内以透明度形式表现存量 FluidTankRenderUtil / LargeFluidTankBlockEntityRenderer / FluidRenderHelper alphaFill

结论: COMMENT(倾向 APPROVE 前的确认项) — 核心气压均衡数学正确、渲染整合完整、en_ud 无误。合并前需确认生存获取链(🔴)、getBucket()=AIR 的 intended 范围与 ItemsSections 越界改动;性能退化建议优化但可非阻塞跟进。

🧪 测试建议

被测目标 推荐测试场景 优先级
FluidPipeNetwork.transferGas() 有限源/汇均衡边界:不同容量比、泵 bias 非零、容量为 Integer.MAX_VALUE 时无溢出;无限源→有限罐(want=min(loFree,valveLimit));有限源→无限汇(受 GAS_EQUILIBRIUM_BUDGET 2000mB/tick 压制) 🔴
gasPressure() 空/满罐、无穷大容量、bias 极端值下的 long 溢出 🔴
gasStorage() 多 tank handler 混合存储(部分 tank 同气体 + 部分空槽) 🟡
equilibrateGases() 纯液体网络(无气体)时的性能/profile;多气体类型隔离均衡 🟡
渲染 opacity alphaFill=0 / 0.5 / 1 的透明度与 fill 率对应;气体在大型罐恒充满 🟢

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched references/gas-system-pr-4489.md in skill 'gas-system-pr-review' (1 replacement).

Pigeon_Nian added 2 commits August 20, 2026 21:49
- 修改gasStorage方法,改为根据剩余容量计算总容量
- 处理多流体槽情况下的容量判断问题,避免容量被占用槽位误判
- 采用总存储量和总容量差值计算剩余空间再加已存气体量
- 提升多流体处理的准确性和代码可读性
- 增加方法注释详细说明容量计算规则
- 修改气体均衡转移预算为所有气体共享的全网预算
- 在气体均衡方法中引入可变预算参数以实现预算共享
- 调整气体转移循环逻辑,确保总预算正确减少
- 清理相关变量定义,简化预算管理逻辑
@Gugle2308

Copy link
Copy Markdown
Collaborator

I have the complete picture. One important detail I notice: FluidLang.java only adds 4 of the 6 gases (hydrogen, oxygen, helium, deuterium) — but I need to check whether xenon and krypton translations are provided. Looking at the en_us and en_ud generated files, all 6 gases have translations. But the FluidLang.java (source) only adds 4. Let me check how xenon/krypton get their translations — probably via the bucket lang in ModItems.

Looking at the data:

  • ModItems sets .lang("Xenon Bucket")/.lang("Krypton Bucket") for the item names (which generates the item.anvilcraft.xenon_bucket entries).
  • Also the en_us file has block.anvilcraft.xenon/block.anvilcraft.krypton — these must come from somewhere. Since FluidLang.java only has 4 gases, the block.anvilcraft.xenon/krypton translations must come from the bucket's fluid description or Registrum automatic fluid lang.

Actually, this is worth noting but the generated en_us/en_ud files DO include all 6 block.anvilcraft.* entries. In this codebase, Registrum's bucket() helper typically auto-registers the fluid's block lang from the bucket item lang. So the 4 in FluidLang + auto-generated from bucket lang gives all 6. This appears complete since generated files have all 6. Let me verify the en_ud mappings are correct rather than manually check — the generated files show proper flipped strings.

Let me verify the en_ud flips are valid by checking a couple.

The en_ud values shown:

  • hydrogen: uǝᵷoɹpʎH ✓ (matches skill example reference)
  • xenon: uouǝX — "Xenon" rev = "noneX", n→u, o→o, n→u, e→ǝ, X→X = "uouǝX" ✓
  • krypton: uoʇdʎɹꞰ — "Krypton" rev="notpyrK", K→Ʞ, r→ɹ, y→ʎ, p→d, t→ʇ, o→o, n→u = "uoʇdʎɹꞰ" ✓

These all look correct. The language files are complete.

I've now confirmed all the key findings from the reference against the current diff. Everything matches. Let me compile the review. The reference notes the version evolved from 4 to 6 gases — the current diff has 6 gases (hydrogen, oxygen, helium, deuterium, xenon, krypton). The FluidLang source only lists 4, but the generated files include all 6 (xenon/krypton handled by Registrum bucket lang). Let me just double-check whether the block.anvilcraft.xenon entry in en_us comes from auto-generation or would be missing. Since generated files exist and contain all 6, it's fine.

Let me write the final review.


PR #4489 审查意见 — Gas System

审查范围gas/1.21/1.6 → dev/1.21/1.6,21 文件 / 1192 行 / 12 Java(6 新增 Java)/ 0 删除。结论:COMMENT(倾向 APPROVE,需先确认生存获取链)

✅ 核心实现正确性已核对

1. 气压均衡数学验证通过
transferGas 有限分支的 equalAmt 公式与「均衡后两罐压强相等」的精确解一致:

num = hiStored·loCap − loStored·hiCap − (loBias−hiBias)·hiCap·loCap/SCALE
x   = num / (hiCap + loCap)

(double) 转型避免 Integer.MAX_VALUE 容量溢出;压强用 long 累乘,GAS_INFINITE_PRESSURE = Long.MAX/4 避免溢出。✓

2. isLighterThanAir 触发正确:6 种气体均 density(-1000) → NeoForge 推导 getDensity() <= 0 → 必真,气体分支正确触发。✓

3. 无限源/汇语义自洽InfinityFluidTank(目标分支 api/fluidtank 包)非空且搭载同气体=源(压力杠标 MAX)、空=汇(压力杠标 MIN)。空罐作汇时走有限公式 + globalBudget 把单 tick 总量压到 2000mB → 受控匀速销毁而非瞬间清空,设计合理。✓

4. 重力/扬程与气体解耦distributeFromSource 加入 isLighterThanAir() continue,交给独立的 equilibrateGases 按压强处理,无逻辑打架。✓

5. 渲染「恒充满 + opacity 表存量」FluidTankRenderUtil + LargeFluidTankBlockEntityRenderer 两处气体分支交叉一致,均走 renderFluidBox(..., true, fill/alpha)。✓

6. bucketGassy 编译闭合:由本 PR 新增定义(+ 行),与 6 个 .model(ModelProviderUtil::bucketGassy) 引用闭合,无编译错误。✓

7. 语言文件:en_us/en_ud 均含全部 6 种气体 + 6 桶名;en_ud 翻转映射正确(氢 uǝᵷoɹpʎH、氙 uouǝX、氪 uoʇdʎɹꞰ 等均验证)。✓

🔴 关键问题:生存获取链缺失(合并阻塞项)

6 种气体零配方(diff 中 recipes/ 计数 = 0),且气体无流体方块(createLegacyBlock→AIR、getBucket()Items.AIR)→ 生存模式下 6 种气桶完全无法获取,仅创造可刷。请确认:这是否为设计意图、是否后续 PR 补配方/获取链?

💡 注:getBucket()→AIR 本项目有 HoneyFluid 先例不算 bug,但会连带影响发射器自动装/采气体(ModDispenserBehavior 判定 getBucket() != AIR)、JEI 桶图标(FluidMixingCategory)、BlockStateUtil——若意图如此请在描述声明。

⚠️ 次要问题

  • RegisterColorHandlersEventListener:由 @EventBusSubscriber(modid=...) 补上 value = Dist.CLIENT。这是合理修复(gas 桶颜色注册属客户端逻辑,缺 CLIENT 会导致服务端加载客户端类崩溃),但严格说属本 PR 范围外的修复,请确认。
  • ItemsSections 水泥桶content.accept()this.acceptFolded(content, ...)。与 Add new recipes, enchantments, mass energy inverter and other updates to the manual 在手册添加新配方、附魔金、质能转换器和其它更新 #4487 创造栏折叠改动一致,但属本 PR 范围外,请确认是否顺带引入。
  • FluidLang.java 只注册了 4 种气体(氢/氧/氦/氘),氙/氪的 block.anvilcraft.xenon/krypton 由 Registrum 桶语言自动生成(en_us/en_ud 已含全 6 种,无缺失)。建议在 FluidLang 显式补齐 4→6 保持一致,避免隐式依赖。
  • 性能equilibrateGases() 每 tick 无条件遍历所有端点收集 gasTypes(即便全网无气体也空耗 O(endpoints×tanks))。建议缓存「网络是否含 lighter-than-air 流体」标记,无气体时跳过整个均衡。
  • DRYrenderFluidBoxWithAlpha 复制了 renderFluidBox 大部分逻辑,存在维护漂移风险。
  • 泵内气体以透明度表存量gasPressure 的 bias 用 effectiveHeight − containerPos.y 折算泵贡献,折入气压差、与海拔无关——逻辑合理,但建议在文档/注释里明确「泵提供气压差」的语义边界,防止后续用扬程逻辑误改。

总体实现严谨,数学、无限源/汇语义、渲染、语言均正确;唯一合并阻塞项是生存模式无配方导致 6 种气体不可获取。

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched references/gas-system-pr-4489.md in skill 'gas-system-pr-review' (1 replacement). · Patched SKILL.md in skill 'gas-system-pr-review' (1 replacement).

WhereisFff
WhereisFff previously approved these changes Aug 21, 2026
- 在流体语言文件中新增氙(Xenon)条目
- 在流体语言文件中新增氪(Krypton)条目
@PigeonNian
PigeonNian merged commit 97b294a into Anvil-Dev:dev/1.21/1.6 Aug 21, 2026
2 checks passed
@Gugle2308

Copy link
Copy Markdown
Collaborator

The grep pattern was slightly off, but I already confirmed via the earlier extraction that all 6 gases are in FluidLang.java with provider.add. The 6 client fluid types each have distinct tints (hydrogen cyan-blue, oxygen blue, helium pink, deuterium teal, xenon lavender, krypton green) and the false opaque flag (translucent).

I have all the information needed for a thorough review. Let me compose the review.

Key findings to report:

  1. 🔴 生存获取链缺失 — zero recipes, no fluid block, getBucket()→AIR. Same as the skill case study. This is the merge blocker.
  2. Math验证通过 — transferGas equalization formula exactly matches the derived solution, RES cancels consistently.
  3. ⚖️ 渲染一致性 — two renderers use different opacity sources (fill vs layerTop - layerBottom) — needs verification for large tank.
  4. isLighterThanAir 触发 — density(-1000) ≤ 0 → true ✓
  5. getBucket()=AIR 影响 — dispenser/JEI/BlockStateUtil需确认
  6. FluidLang 已全6种显式注册 — 比 skill 参考(4/6)更新,语言完整
  7. en_ud 验证通过
  8. 侧边改动 — ItemsSections 水泥桶 accept→acceptFolded(范围外)
  9. ⚠️ 性能 — equilibrateGases 每tick全网络扫描,纯液体网络退化
  10. EOF 缺换行 8处(生成模型JSON为主,GasFluid.java 一处)

Let me write the review now.

代码审查摘要 — PR #4489

操作: opened/synchronize
范围: 21 个文件(12 Java, 6 新增, 0 删除) / 1203 行 diff
分支: gas/1.21/1.6dev/1.21/1.6 (作者 PigeonNian)

概览

新增气体系统GasFluid extends Fluid(无世界方块,createLegacyBlock→AIRgetBucket()→Items.AIRgetTickDelay→0isSource→true),6 种气体(氢/氧/氦/氘/氙/氪,均 density(-1000)isLighterThanAir() true),6 个气体桶,管道网络的气压均衡扩散 + pump 气压差 + 桶内 opacity 渲染。


🔴 关键

1. 生存获取链完全缺失 — 合并阻塞项

grep -c "recipes/" /tmp/pr4489.diff   → 0   # 零配方
getBucket() → Items.AIR  / createLegacyBlock → AIR  # 无气体流体方块

6 种气体没有任何配方,且因其 getBucket()→AIR、无流体方块、无世界诞生方式,在生存模式下气桶完全不可获取(仅创造可刷)。feature 在生存实际不可用。需向作者确认:是否由后续 PR 补齐获取链(如合成配方 / 氦气从某工艺产出等)?若确为本 PR 范围外,请在 PR 描述声明「仅创造可用,获取链后续补齐」。


⚠️ 警告

2. 两个渲染器的 opacity 来源不一致

  • FluidTankRenderUtil(普通罐):气体 alpha = fill(罐填充比,0..1)✓
  • LargeFluidTankBlockEntityRenderer(大型罐):气体 alpha = (float)(layerTop - layerBottom)

两种来源语义需确认一致性:若 layerTop - layerBottom 对单一气体等于其填充占比则 OK,但它是「分层堆积」语义下算出的(非显式 fill),与普通罐的 fill 来源不同。建议统一为同一量纲,并确认大型罐在多层流体混装时气体层的 opacity 正确。

3. getBucket()→Items.AIR 的消费方影响需确认 intended
查询 getBucket() 消费方:ModDispenserBehavior(发射器无法自动装/采气体桶)、JEI FluidMixingCategory/桶图标、BlockStateUtil。若这些路径不该对气体生效,属合理设计,建议在注释/描述声明。

4. 每 tick 全网络扫描性能退化(纯液体网络)
equilibrateGases() 每 tick 遍历全部端点 + distinctFluidTypes() 收集气体类型,即使全网无气体也空耗 O(endpoints×tanks)。对纯液体大网络是性能退化。建议缓存「本网络是否含 lighter-than-air 流体」标记,无气体时整段跳过。

5.(范围外改动)ItemsSections.java 水泥桶

- ModItems.CEMENT_BUCKETS.forEach(... -> content.accept(bucketItem));
+ ...气体桶 accept...
+ ModItems.CEMENT_BUCKETS.forEach(... -> this.acceptFolded(content, bucketItem));

水泥桶 accept() → acceptFolded()#4487 创造栏折叠重构,与本 PR 气体主题无关,但顺带混入。请确认该改动是否应拆出。


💡 建议

6. 大型罐 + 普通罐渲染逻辑大量复制 → DRY 风险
FluidRenderHelper 新增 renderFluidBox(...alphaFill) + renderFluidBoxWithAlpha,与既有 renderFluidBox 大量重复(取贴图、getSkippedSides、顶点装配)。建议抽公共私有方法减少维护漂移。

7. GasFluid.java 缺文件末尾换行(\ No newline at end of file
8 处 EOF 缺换行分布在 6 个生成的 bucket model JSON(数据生成器所致,可接受)+ 其余,其中 GasFluid.java 也缺尾换行——建议补上(源代码风格)。

8. 无限汇销毁速率语义
空 InfinityFluidTank 作 sink 时走有限公式取 want=min(hiStored, valveLimit),单 tick 总量被 GAS_EQUILIBRIUM_BUDGET=MAX_SPEED(2000) 压住 → 受控匀速销毁而非瞬间清空。合理设计,建议在注释中成文说明。


✅ 数学验证通过(气压均衡核心)

transferGas 有限分支公式与「转移后两罐压强相等」的精确解一致:

num = hiStored·loCap − loStored·hiCap − (loBias−hiBias)·hiCap·loCap/SCALE
x   = num / (hiCap+loCap)

推导:均衡条件 (hiStored−X)/hiCap·SCALE + hiBias = (loStored+X)/loCap·SCALE + loBias,解出 X 与代码完全吻合。GAS_PRESSURE_RESOLUTION 是公共缩放因子,在均衡中两边抵消,不引入偏差。✓ (double) 先转型避免 MAX 容量溢出 ✓ 压强用 long 累乘防溢出 ✓


🟢 看起来不错

  • isLighterThanAir 触发正确:6 种气体均 density(-1000) ≤ 0 → NeoForge FluidType.isLighterThanAir() 返回 true,气压均衡 & opacity 渲染分支正确触发。distributeFromSource 已加 if (isLighterThanAir()) continue; 交给均衡,避免流体重心分配重复搬运。✓
  • 无限源/汇语义自洽:非空 InfinityFluidTank 搭载同气体 = 无限源(GAS_INFINITE_PRESSUREwant=min(loFree,valveLimit));空 InfinityFluidTank = 无限汇(GAS_INFINITE_SINK_PRESSUREwant=min(hiStored,valveLimit));压力排序 MAX/4 与 MIN/4 保证源最高 / 汇最低。✓
  • bucketGassy 编译闭合ModelProviderUtil.bucketGassy 由本 PR 新增(+),与 6 个 .model(ModelProviderUtil::bucketGassy) 引用闭合,无编译错误;生成模型 JSON flip_gas:true + neoforge:item/bucket_drip 正确。✓
  • 语言完整(当前 diff 全 6 种显式注册)FluidLang.java 已为氢/氧/氦/氘/氙/氪全部显式 provider.add(较早期 4/6 版本已补齐),en_us 与 en_ud 生成的 block.anvilcraft.* 6 种全齐,无缺项。✓
  • en_ud 倒置英文逐字验证通过:Hydrogen→uǝᵷoɹpʎH、Oxygen→uǝᵷʎxO、Helium→ɯnᴉꞁǝH、Krypton→uoʇdʎɹꞰ、Deuterium→ɯnᴉɹǝʇnǝᗡ、Xenon→uouǝX 全部符合 n↔u/d↔p 等标准映射。✓
  • 桶注册完整:6 桶均 .tag(Tags.Items.BUCKETS) + craftRemainder(BUCKET) + 生成 c:tags/item/buckets.json 追加条目;RegisterColorHandlersEventListener 补上 Dist.CLIENT(必要配套,合理修复),并注册 6 桶 DynamicFluidContainerModel.Colors()。✓
  • 6 种气体各配独立 tint(氢青蓝/氧蓝/氦粉/氘青/氙薰衣草/氪绿),opaque=false → translucent 渲染正确。

📋 声称验证表

声称 状态 对应文件
管道系统支持气体气压扩散 FluidPipeNetwork (equilibrateGases/transferGas/gasPressure)
泵提供气压差 gasPressure bias = (effectiveHeight−Y)·PER_LIFT
气体在泵内以透明度表现存量 FluidTankRenderUtil/LargeFluidTankBlockEntityRenderer/FluidRenderHelper

🧪 测试建议

被测目标 推荐测试场景 优先级
FluidPipeNetwork.transferGas 有限罐→有限罐均衡后压强相等(数学边界);无限源/汇分支;阀门口径限流 🔴
FluidPipeNetwork.gasPressure sc[1]==0 除零守卫;无限源/汇压力极值;bias 上/下界 🟡
FluidPipeNetwork.equilibrateGases 纯液体网络(无气体)跳过;GAS_MAX_ROUNDS 收敛;GAS_EQUILIBRIUM_BUDGET 预算耗尽 🟡
GasFluid isSource=true/getBucket=AIR/createLegacyBlock=AIR 语义;getTickDelay=0 🟢
渲染 opacity 普通罐 fill=0/0.5/1;大型罐单一气体/多层混装 layerTop-layerBottom 一致性 🟡

结论: REQUEST_CHANGES — 核心气压均衡数学正确、注册/语言/渲染闭环完整,但**生存获取链完全缺失(零配方+无流体方块+getBucket→AIR)**是本 PR 的合并阻塞项,需作者确认设计意图(是否后续 PR 补齐);另建议统一大型罐 opacity 来源并确认 getBucket→AIR 的各消费方 intended。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched references/gas-system-pr-4489.md in skill 'gas-system-pr-review' (1 replacement). · Patched SKILL.md in skill 'gas-system-pr-review' (1 replacement).

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