水力坝(Hydro Dam)
基本信息
| 属性 | 值 |
|---|---|
| 实现类 | blocks/HEHydroDamTileEntity.java(438 行) |
| 注册 ID | HEConfig.blockIdOffset(默认 17000) |
| 物品形式 | new HEHydroDamTileEntity(HEConfig.blockIdOffset, "he_dam", "Hydro Dam").getStackForm(1L)(hooks/HEHooksShared.java:96) |
| 多方块尺寸 | 5 × 5 × 5(tt.beginStructureBlock(5, 5, 5, true),HEHydroDamTileEntity.java:328) |
| 控制器位置 | 正面中心(x+2, y+3, z+0),tt.addController("Front Center")(HEHydroDamTileEntity.java:329) |
| 壳体材料 | GT GregTechAPI.sBlockConcretes,meta 8(concreteBlockMeta = 8,HEHydroDamTileEntity.java:61) |
| 内部容积 | 3×3×3 的空腔(水就存在这里) |
| 维护需求 | 无(HEHydroDamTileEntity.java:95-101 把 6 个扳手类标志全置 true) |
这是本 mod 唯一的多层(5 层)多方块结构。 ULV 被禁用(配方注释
// ULV is disabled!), 坝的电压档位由插入槽 1 的电路决定,不分型号。
结构定义(逐格对照)
HEHydroDamTileEntity.java:71-90:
private static final IStructureDefinition<HEHydroDamTileEntity> multiblockDefinition = StructureDefinition
.<HEHydroDamTileEntity>builder()
.addShape(
HETags.structurePieceMain,
transpose(
new String[][] { { "HHHHH", "CCCCC", "CCCCC", "CCCCC", "CCCCC" },
{ "HHHHH", "C C", "C C", "C C", "C C" },
{ "HHHHH", "C C", "C C", "C C", "C C" },
{ "HH~HH", "C C", "C C", "C C", "C C" },
{ "HHHHH", "CCCCC", "CCCCC", "CCCCC", "CCCCC" } }))
.addElement('H', ofChain(
ofHatchAdder(HEHydroDamTileEntity::addClassicToMachineList, steelTextureIndex,
GregTechAPI.sBlockConcretes, concreteBlockMeta),
ofBlockAnyMeta(GregTechAPI.sBlockConcretes, concreteBlockMeta)))
.addElement('C', ofBlockAnyMeta(GregTechAPI.sBlockConcretes, concreteBlockMeta)).build();
字符串数组为 [y][z],每串 5 字符代表该 z 层沿 x 的 5 格:
| y 层 | z=0 | z=1 | z=2 | z=3 | z=4 |
|---|---|---|---|---|---|
| 4(顶) | HHHHH |
CCCCC |
CCCCC |
CCCCC |
CCCCC |
| 3 | HH~HH ← 控制器在 x=2 |
C C |
C C |
C C |
C C |
| 2 | HHHHH |
C C |
C C |
C C |
C C |
| 1 | HHHHH |
C C |
C C |
C C |
C C |
| 0(底) | HHHHH |
CCCCC |
CCCCC |
CCCCC |
CCCCC |
| 元素 | 含义 |
|---|---|
H |
GT 混凝土 meta 8(ofBlockAnyMeta)或 任意输入舱(ofHatchAdder)——纹理索引 steelTextureIndex = 16(HEHydroDamTileEntity.java:60) |
C |
GT 混凝土 meta 8(ofBlockAnyMeta) |
~ |
控制器(HEHydroDamTileEntity.java:79 的 HH~HH) |
| 空格 | 空气 —— 3×3×3 内部空腔,水在此生成 |
checkPiece(HETags.structurePieceMain, 2, 3, 0, errors)(HEHydroDamTileEntity.java:115)
与 buildPiece(..., 2, 3, 0)(HEHydroDamTileEntity.java:120)的偏移 (2, 3, 0)
与形状里的 ~ 位置一致。
关于「可否旋转 / 拆除」
源码没有任何旋转或拆除的特殊处理:
- 结构定义无
setSymmetry/setOrientation声明,即固定朝向, 控制器必须在z+0那一面 - 未覆写
onBlockBroken/onBlockDestroyed之类方法 - 破坏控制器会走
onBreakController(waterId)(HEHydroDamTileEntity.java:300), 释放该坝占用的 waterId
⚠️ 不要臆断「可以旋转建造」——源码里找不到任何支持旋转的声明。
电压档位:靠电路,不是分型号
坝没有电压型号,档位在运行时读取:
private int getVoltageTier() {
boolean configCircuitIsPresent = mInventory != null && mInventory[1] != null
&& mInventory[1].getItem() == GTUtility.getIntegratedCircuit(0).getItem();
return configCircuitIsPresent ? HEUtil.clamp(mInventory[1].getItemDamage(), 1, GTValues.V.length - 1) : 1;
}
(HEHydroDamTileEntity.java:138-142)
- 在槽 1 放入集成电路(
getIntegratedCircuit(0)只用来取物品类型比对) - 档位 = 电路的
itemDamage,用HEUtil.clamp夹在1~GTValues.V.length - 1 - 不放电路时固定为档位 1(LV)
该档位只用于两处压力换算:
| 用途 | 公式 | 行 |
|---|---|---|
| GUI 最大压力 | HEConfig.pressureIncreasePerTier * getVoltageTier() |
HEHydroDamTileEntity.java:134-136 |
| 吸入加压水的门槛 | 见下 | HEHydroDamTileEntity.java:156-160 |
每 tick 逻辑 onRunningTick(HEHydroDamTileEntity.java:144-191)
mMaxProgresstime = 1(HEHydroDamTileEntity.java:130),即每 tick 都跑。
1. 容量与钳制(151-154)
euCapacity = HEServer.instance.getEuCapacity(waterId);
euStored = HEUtil.clamp(euStored, 0, euCapacity);
euCapacityGui = HEServer.instance.getEuCapacityAt(waterId, (int) (getYCoord() + getMaxGuiPressure()));
容量按水坝的蓄水高度动态计算,GUI 上限用「控制器 Y + 最大压力」。
2. 从流体舱吸入加压水(156-167)
final int waterLevelOverController = (int) (HEServer.instance.getWaterLevel(waterId) - getYCoord());
getStoredFluids().forEach(fluidStack -> {
if (fluidStack.getFluidID() == HE.pressurizedWater.getID()
&& HE.pressurizedWater.getPressure(fluidStack) >= waterLevelOverController) {
final long availableEnergy = (long) (fluidStack.amount * HEConfig.euPerMilliBucket);
final long storableEnergy = Math.min(euCapacity - euStored, availableEnergy);
fluidStack.amount -= storableEnergy;
euStored += storableEnergy;
euPerTickIn += storableEnergy;
}
});
语义:只有当进水压力 ≥ 水面高出控制器的格数时才吸。 即「水压必须压得住这个高度差」——这正是坝的意义。
📌 单位不一致(可疑):
fluidStack.amount是毫桶(mB), 注释里也写 EU per tick。 第163行写的是fluidStack.amount -= storableEnergy;—— 直接把「按euPerMilliBucket换算出的能量」从流体数量里扣, 而不是先换算回 mB 再扣。euPerMilliBucket默认1.0时两者数值相同, 改这个配置就会出现能量与流体量不匹配。源码无注释说明是有意为之。
3. 输出加压水(169-176)
final int availableOutput = (int) Math.min(HEConfig.damDrainPerSecond, euStored);
final int availableOutputAsWater = (int) (availableOutput * HEConfig.milliBucketPerEU);
if (availableOutput > 0) {
final int distributedFluid = distributeFluid(new FluidStack(HE.pressurizedWater, availableOutputAsWater));
final long distributedEu = (long) (distributedFluid * HEConfig.euPerMilliBucket);
euStored -= distributedEu;
euPerTickOut += distributedEu;
}
单 tick 最多放 damDrainPerSecond(默认 2048,配置注释写「per tick」,
但配置项名与 Defaults 注释都写 damDrainPerSecond/per second——
单位在命名与注释间不一致,见 配置项)。
4. 雨天发电(178-184)
if (getBaseMetaTileEntity().getWorld().isRaining()) {
final long rainingEuGeneration = (long) (HEServer.instance.getRainedOnBlocks(waterId)
* HEConfig.waterBonusPerSurfaceBlockPerRainTick);
final long addedEu = Math.min(euCapacity - euStored, rainingEuGeneration);
euStored += addedEu;
euPerTickIn += addedEu;
}
下雨时按水面方块数 × waterBonusPerSurfaceBlockPerRainTick(默认 1.0)产 EU。
5. 收尾(186-190)
写入两个 AveragedRingBuffer(64) 滑动平均(euPerTickInAverage / euPerTickOutAverage,
HEHydroDamTileEntity.java:68-69),然后
HEServer.instance.setWaterLevel(waterId, euStored) —— 蓄水量与能量是同一个值。
if (waterId < 0 || waterId >= HEConfig.maxDams) return false;(HEHydroDamTileEntity.java:146) 是入口保护:waterId初始为-1(HEHydroDamTileEntity.java:62), 必须在onPlacecontroller分配到合法 ID 后才工作。
输出分配 distributeFluid(HEHydroDamTileEntity.java:193-…)
遍历 mOutputHatches(filterValidMTEs),对每个:
| 检查 | 跳过条件 | 行 |
|---|---|---|
| 能否输出液体 | !hatch.outputsLiquids() |
196-198 |
| 流体锁 | hatch.isFluidLocked() && lockedFluid != null && !lockedFluid.equals(fluidStack.getFluid()) |
199-202 |
| 输出槽为空则先填 0 量的加压水 | currentFluid.getFluid().getID() <= 0 |
204-207 |
| 容量 | hatch.getCapacity() - currentFluid.amount |
209 |
结构提示文本(HEHydroDamTileEntity.java:328-333)
tt.beginStructureBlock(5, 5, 5, true);
tt.addController("Front Center");
tt.addStructureInfo("Fill the rest with Light Concrete");
tt.addStructureInfo("No Maintenance Hatch required!");
GUI
坝有自己的配置 GUI(不是标准 GT GUI):
network/container/HEHydroDamConfigContainer.javaclient/gui/HEHydroDamConfigContainer.java(GUI 容器)client/gui/HEPopupLimitGui.java(六方向限高弹窗)- 背景贴图:
textures/gui/he_water_config.png、textures/gui/he_water_config_limits_popup.png(HE.java的两个dam*BackgroundLocation)
GUI 刷新有 200 tick(10 秒)延迟:HE.controllerGuiUpdateDelay = 200(HE.java)。