diff --git a/src/generated/resources/assets/anvilcraft/blockstates/pump.json b/src/generated/resources/assets/anvilcraft/blockstates/pump.json new file mode 100644 index 0000000000..1f8fa498b3 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/blockstates/pump.json @@ -0,0 +1,216 @@ +{ + "variants": { + "orientation=down_east,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": -90, + "y": -90 + }, + "orientation=down_east,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": -90, + "y": -90 + }, + "orientation=down_east,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": -90, + "y": -90 + }, + "orientation=down_east,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": -90, + "y": -90 + }, + "orientation=down_north,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": -90, + "y": 180 + }, + "orientation=down_north,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": -90, + "y": 180 + }, + "orientation=down_north,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": -90, + "y": 180 + }, + "orientation=down_north,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": -90, + "y": 180 + }, + "orientation=down_south,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": -90 + }, + "orientation=down_south,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": -90 + }, + "orientation=down_south,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": -90 + }, + "orientation=down_south,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": -90 + }, + "orientation=down_west,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": -90, + "y": 90 + }, + "orientation=down_west,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": -90, + "y": 90 + }, + "orientation=down_west,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": -90, + "y": 90 + }, + "orientation=down_west,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": -90, + "y": 90 + }, + "orientation=east_up,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "y": -90 + }, + "orientation=east_up,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "y": -90 + }, + "orientation=east_up,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "y": -90 + }, + "orientation=east_up,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "y": -90 + }, + "orientation=north_up,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "y": 180 + }, + "orientation=north_up,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "y": 180 + }, + "orientation=north_up,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "y": 180 + }, + "orientation=north_up,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "y": 180 + }, + "orientation=south_up,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base" + }, + "orientation=south_up,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off" + }, + "orientation=south_up,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload" + }, + "orientation=south_up,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload" + }, + "orientation=up_east,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": 90, + "y": -90 + }, + "orientation=up_east,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": 90, + "y": -90 + }, + "orientation=up_east,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": 90, + "y": -90 + }, + "orientation=up_east,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": 90, + "y": -90 + }, + "orientation=up_north,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": 90, + "y": 180 + }, + "orientation=up_north,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": 90, + "y": 180 + }, + "orientation=up_north,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": 90, + "y": 180 + }, + "orientation=up_north,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": 90, + "y": 180 + }, + "orientation=up_south,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": 90 + }, + "orientation=up_south,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": 90 + }, + "orientation=up_south,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": 90 + }, + "orientation=up_south,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": 90 + }, + "orientation=up_west,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "x": 90, + "y": 90 + }, + "orientation=up_west,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "x": 90, + "y": 90 + }, + "orientation=up_west,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "x": 90, + "y": 90 + }, + "orientation=up_west,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "x": 90, + "y": 90 + }, + "orientation=west_up,overload=false,powered=false": { + "model": "anvilcraft:block/pump_base", + "y": 90 + }, + "orientation=west_up,overload=false,powered=true": { + "model": "anvilcraft:block/pump_off", + "y": 90 + }, + "orientation=west_up,overload=true,powered=false": { + "model": "anvilcraft:block/pump_overload", + "y": 90 + }, + "orientation=west_up,overload=true,powered=true": { + "model": "anvilcraft:block/pump_overload", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/lang/en_ud.json b/src/generated/resources/assets/anvilcraft/lang/en_ud.json index a77762ba75..72ccaf05d1 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_ud.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_ud.json @@ -478,6 +478,7 @@ "block.anvilcraft.powered_sliding_rail": "ꞁᴉɐᴚ ᵷuᴉpᴉꞁS pǝɹǝʍoԀ", "block.anvilcraft.propel_piston": "uoʇsᴉԀ ꞁǝdoɹԀ", "block.anvilcraft.pulse_generator": "ɹoʇɐɹǝuǝ⅁ ǝsꞁnԀ", + "block.anvilcraft.pump": "dɯnԀ", "block.anvilcraft.purple_cement": "ʇuǝɯǝƆ ǝꞁdɹnԀ", "block.anvilcraft.purple_cement_cauldron": "uoɹpꞁnɐƆ ʇuǝɯǝƆ ǝꞁdɹnԀ", "block.anvilcraft.quartz_sand": "puɐS zʇɹɐnꝹ", diff --git a/src/generated/resources/assets/anvilcraft/lang/en_us.json b/src/generated/resources/assets/anvilcraft/lang/en_us.json index ad40c7356e..662897170b 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_us.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_us.json @@ -478,6 +478,7 @@ "block.anvilcraft.powered_sliding_rail": "Powered Sliding Rail", "block.anvilcraft.propel_piston": "Propel Piston", "block.anvilcraft.pulse_generator": "Pulse Generator", + "block.anvilcraft.pump": "Pump", "block.anvilcraft.purple_cement": "Purple Cement", "block.anvilcraft.purple_cement_cauldron": "Purple Cement Cauldron", "block.anvilcraft.quartz_sand": "Quartz Sand", diff --git a/src/generated/resources/assets/anvilcraft/models/item/pump.json b/src/generated/resources/assets/anvilcraft/models/item/pump.json new file mode 100644 index 0000000000..b9f0eea474 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/item/pump.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/pump" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/misc/pump.json b/src/generated/resources/data/anvilcraft/advancement/recipes/misc/pump.json new file mode 100644 index 0000000000..2f680f6f07 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/misc/pump.json @@ -0,0 +1,43 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_pipe": { + "conditions": { + "items": [ + { + "items": "anvilcraft:pipe" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_piston": { + "conditions": { + "items": [ + { + "items": "minecraft:piston" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:pump" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_piston", + "has_pipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:pump" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/loot_table/blocks/pump.json b/src/generated/resources/data/anvilcraft/loot_table/blocks/pump.json new file mode 100644 index 0000000000..667d302966 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/loot_table/blocks/pump.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:pump" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/pump" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/pump.json b/src/generated/resources/data/anvilcraft/recipe/pump.json new file mode 100644 index 0000000000..244b6fe268 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/pump.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "group": "anvilcraft:pump", + "key": { + "C": { + "item": "anvilcraft:pipe" + }, + "P": { + "item": "minecraft:piston" + } + }, + "pattern": [ + "PCP", + "P P", + " " + ], + "result": { + "count": 2, + "id": "anvilcraft:pump" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/tags/block/collision_immune.json b/src/generated/resources/data/anvilcraft/tags/block/collision_immune.json index 81e753a7d3..99fee903e9 100644 --- a/src/generated/resources/data/anvilcraft/tags/block/collision_immune.json +++ b/src/generated/resources/data/anvilcraft/tags/block/collision_immune.json @@ -1,6 +1,7 @@ { "values": [ "anvilcraft:transcendence_anvil", + "anvilcraft:infinite_collector", "anvilcraft:celestial_forging_anvil", "anvilcraft:celestial_forging_anvil_portal", "anvilcraft:transcendium_block", @@ -10,7 +11,6 @@ "anvilcraft:confined_energy_anvilon", "anvilcraft:confined_neutronium_ingot", "anvilcraft:confinement_chamber", - "anvilcraft:singularity_crystal", - "anvilcraft:infinite_collector" + "anvilcraft:singularity_crystal" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json index 68716ffe95..3ee28002e0 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -317,6 +317,7 @@ "anvilcraft:creative_crate", "anvilcraft:pipe_straight", "anvilcraft:pipe_corner", - "anvilcraft:pipe_node" + "anvilcraft:pipe_node", + "anvilcraft:pump" ] } \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/AbstractPipeBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/AbstractPipeBlockEntity.java index b41d1c6a42..75bac5b6ea 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/AbstractPipeBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/AbstractPipeBlockEntity.java @@ -4,6 +4,7 @@ import dev.dubhe.anvilcraft.block.fluid.PipeCornerBlock; import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock; import dev.dubhe.anvilcraft.block.fluid.PipeStraightBlock; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import lombok.Getter; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -36,48 +37,16 @@ * 限制流速(每格高度差 50 mB/tick)。 * *
高度差基于移位后的实际连接位置(sourcePos/targetPos),
+ * 而非管道自身位置,以正确处理同方块两端端头的情况。
*/
public static void moveFluidWithHeightCheck(
Level level,
BlockPos sourceCurPos,
Direction sourceCurDirection,
BlockPos targetCurPos,
- Direction targetCurDirection
+ Direction targetCurDirection,
+ int effectiveHeight
) {
- // 计算源的等效高度
- int sourceEffectiveY = sourceCurPos.getY();
- int targetEffectiveY = targetCurPos.getY();
- if (level.getBlockEntity(sourceCurPos) instanceof AbstractPipeBlockEntity sourceBe) {
- sourceEffectiveY = sourceBe.getEffectiveHeight();
- }
- if (level.getBlockEntity(targetCurPos) instanceof AbstractPipeBlockEntity targetBe) {
- targetEffectiveY = targetBe.getEffectiveHeight();
- }
-
- if (sourceEffectiveY <= targetEffectiveY) {
- return;
- }
-
BlockPos sourcePos = sourceCurPos.relative(sourceCurDirection);
BlockPos targetPos = targetCurPos.relative(targetCurDirection);
+
+ // 用移位后的实际连接位置计算基础高度
+ int sourceEffectiveY = sourcePos.getY();
+ int targetEffectiveY = targetPos.getY();
+
+ targetEffectiveY -= effectiveHeight;
+
+ if (sourceEffectiveY <= targetEffectiveY) return;
+
Direction sourceDirection = sourceCurDirection.getOpposite();
Direction targetDirection = targetCurDirection.getOpposite();
- // 使用等效高度差计算流速
moveFluid(level, sourcePos, sourceDirection, targetPos, targetDirection, sourceEffectiveY - targetEffectiveY);
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeBlockEntity.java
index 2bafe5b801..a8f66637d0 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeBlockEntity.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeBlockEntity.java
@@ -3,6 +3,7 @@
import dev.dubhe.anvilcraft.block.fluid.PipeBlock;
import dev.dubhe.anvilcraft.block.fluid.PipeCornerBlock;
import dev.dubhe.anvilcraft.block.fluid.PipeStraightBlock;
+import dev.dubhe.anvilcraft.block.fluid.PumpBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
@@ -61,24 +62,16 @@ public static int getEndCount(BlockState blockState) {
@Override
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.saveAdditional(tag, registries);
- if (this.heightBonus != 0) {
- tag.putInt("HeightBonus", this.heightBonus);
- }
}
@Override
public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.loadAdditional(tag, registries);
- this.heightBonus = tag.getInt("HeightBonus");
}
@Override
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
- CompoundTag tag = super.getUpdateTag(registries);
- if (this.heightBonus != 0) {
- tag.putInt("HeightBonus", this.heightBonus);
- }
- return tag;
+ return super.getUpdateTag(registries);
}
@Override
@@ -91,8 +84,9 @@ public Packet 仅当有端头时才执行。两端端头且非垂直/非垂直弯管时跳过(避免水平管误排)。
- * 单端端头时沿无端头端追踪 PipeEnd 并向其排液。
+ * 仅当有端头时才执行。两端端头时按管轴方向排液,
+ * 端头指向泵时自动透传追踪(不提前返回)。
+ * 单端端头时沿无端头方向追踪 PipeEnd 并向其排液。
*/
public static void tick(Level level, BlockPos pos, BlockState state) {
int endCount = getEndCount(state);
@@ -102,34 +96,24 @@ public static void tick(Level level, BlockPos pos, BlockState state) {
boolean isStraight = state.getBlock() instanceof PipeStraightBlock;
- // 两端端头 + 水平直管 → 跳过
- if (endCount == 2 && isStraight && !Direction.Axis.Y.equals(state.getValue(PipeStraightBlock.AXIS))) {
- return;
- }
-
- // 两端端头 + 水平弯管(不涉及 Y 轴)→ 跳过
- if (
- endCount == 2 && !isStraight
- && !state.getValue(PipeCornerBlock.CORNER_ENDED).getFirstDirection().equals(Direction.DOWN)
- && !state.getValue(PipeCornerBlock.CORNER_ENDED).getFirstDirection().equals(Direction.UP)
- ) {
- return;
- }
-
if (endCount == 2) {
- // 两端端头 → 同柱/同管排液
+ // 两端端头 → 按管轴方向排液,检查端头是否指向泵
if (isStraight) {
- // 垂直直管:上端 → 下端
- AbstractPipeBlockEntity.moveFluidWithHeightCheck(level, pos, Direction.UP, pos, Direction.DOWN);
+ Direction.Axis axis = state.getValue(PipeStraightBlock.AXIS);
+ Direction posDir = PipeBlock.getDirectionFromAxis(axis, Direction.AxisDirection.POSITIVE);
+ Direction negDir = PipeBlock.getDirectionFromAxis(axis, Direction.AxisDirection.NEGATIVE);
+
+ // 检查端头指向的方块是否是泵,若是则透传追踪
+ tickEndCount2(level, pos, posDir, negDir);
+ tickEndCount2(level, pos, negDir, posDir);
} else {
- // 垂直弯管:垂直端 → 水平端(或反向)
- if (state.getValue(PipeCornerBlock.CORNER_ENDED).getFirstDirection().equals(Direction.DOWN)) {
- PipeBlock.CornerEnded cornerEnded = state.getValue(PipeCornerBlock.CORNER_ENDED);
- AbstractPipeBlockEntity.moveFluidWithHeightCheck(level, pos, cornerEnded.getSecondDirection(), pos, Direction.DOWN);
- } else {
- PipeBlock.CornerEnded cornerEnded = state.getValue(PipeCornerBlock.CORNER_ENDED);
- AbstractPipeBlockEntity.moveFluidWithHeightCheck(level, pos, Direction.UP, pos, cornerEnded.getSecondDirection());
- }
+ // 弯管两端端头
+ PipeBlock.CornerEnded cornerEnded = state.getValue(PipeCornerBlock.CORNER_ENDED);
+ Direction firstDir = cornerEnded.getFirstDirection();
+ Direction secondDir = cornerEnded.getSecondDirection();
+
+ tickEndCount2(level, pos, firstDir, secondDir);
+ tickEndCount2(level, pos, secondDir, firstDir);
}
return;
}
@@ -156,6 +140,43 @@ public static void tick(Level level, BlockPos pos, BlockState state) {
if (pipeEnd == null) {
return;
}
- AbstractPipeBlockEntity.moveFluidWithHeightCheck(level, pos, sourceDirection, pipeEnd.pos(), pipeEnd.direction());
+ AbstractPipeBlockEntity.moveFluidWithHeightCheck(
+ level,
+ pos,
+ sourceDirection,
+ pipeEnd.pos(),
+ pipeEnd.direction(),
+ pipeEnd.effectiveHeight()
+ );
+ }
+
+ private static void tickEndCount2(Level level, BlockPos pos, Direction posDir, Direction negDir) {
+ BlockPos targetCurPos = pos;
+ Direction targetCurDir = negDir;
+ int effectiveHeight = 0;
+
+ BlockPos sourceNeighbor = pos.relative(posDir);
+ if (level.getBlockState(sourceNeighbor).getBlock() instanceof PumpBlock) {
+ return;
+ }
+
+ BlockPos targetNeighbor = pos.relative(negDir);
+ if (level.getBlockState(targetNeighbor).getBlock() instanceof PumpBlock) {
+ PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, negDir.getOpposite());
+ if (pumpEnd != null) {
+ targetCurPos = pumpEnd.pos();
+ targetCurDir = pumpEnd.direction();
+ effectiveHeight = pumpEnd.effectiveHeight();
+ }
+ }
+
+ AbstractPipeBlockEntity.moveFluidWithHeightCheck(
+ level,
+ pos,
+ posDir,
+ targetCurPos,
+ targetCurDir,
+ effectiveHeight
+ );
}
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeNodeBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeNodeBlockEntity.java
index 0116ec23b2..b44c41f6e9 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeNodeBlockEntity.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PipeNodeBlockEntity.java
@@ -3,6 +3,7 @@
import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder;
import dev.dubhe.anvilcraft.block.fluid.PipeBlock;
import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock;
+import dev.dubhe.anvilcraft.block.fluid.PumpBlock;
import lombok.Getter;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -80,16 +81,12 @@ protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries)
if (!tankNbt.isEmpty()) {
tag.put("Fluid", tankNbt);
}
- if (this.heightBonus != 0) {
- tag.putInt("HeightBonus", this.heightBonus);
- }
}
@Override
public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.loadAdditional(tag, registries);
this.fluidHandler.readFromNBT(registries, tag.getCompound("Fluid"));
- this.heightBonus = tag.getInt("HeightBonus");
}
@Override
@@ -99,9 +96,6 @@ public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
if (!tankNbt.isEmpty()) {
tag.put("Fluid", tankNbt);
}
- if (this.heightBonus != 0) {
- tag.putInt("HeightBonus", this.heightBonus);
- }
return tag;
}
@@ -128,15 +122,57 @@ public static void tick(Level level, BlockPos pos, BlockState state) {
EnumProperty 工作状态判定:
+ * 方向映射:{@link dev.dubhe.anvilcraft.block.state.Orientation#getDirection()} 返回输出方向。
+ * 输入端为该方向的反方向。泵的输出端高度降低,输入端高度抬升。
+ */
+@Getter
+@Setter
+public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerConsumer {
+ private static final int PUMP_POWER = 32; // 32 kW 电力消耗
+ public static final int PUMP_HEADLIFT = 10; // 10 米扬程
+
+ private @Nullable PowerGrid grid;
+ private boolean working;
+
+ public PumpBlockEntity(BlockEntityType extends PumpBlockEntity> type, BlockPos pos, BlockState state) {
+ super(type, pos, state);
+ }
+
+ public static PumpBlockEntity create(BlockEntityType 基础模型(pump_base/pump_off/pump_overload)由 blockstate 系统渲染,
+ * 本渲染器仅负责动画活塞部分。
+ */
+public class PumpBlockEntityRenderer implements BlockEntityRenderer
+ *
+ *
+ *
+ *
+ */
+ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEntity entity) {
+ if (level.isClientSide()) {
+ return;
+ }
+
+ // 刷新电网过载状态到 blockstate
+ entity.flushState(level, pos);
+ // flushState 通过 setBlockAndUpdate 修改了 blockstate,需重读
+ BlockState updatedState = level.getBlockState(pos);
+
+ boolean powered = updatedState.getValue(PumpBlock.POWERED);
+ boolean overload = updatedState.getValue(PumpBlock.OVERLOAD);
+
+ // working = 泵处于启用状态(控制动画和流体开关)
+ boolean wasWorking = entity.working;
+ entity.working = !powered && !overload;
+
+ if (entity.working != wasWorking) {
+ entity.setChanged();
+ if (!level.isClientSide()) {
+ entity.sendUpdate();
+ }
+ }
+ Orientation orientation = updatedState.getValue(PumpBlock.ORIENTATION);
+ Direction sourceDir = orientation.getDirection();
+ BlockPos sourcePos = pos.relative(sourceDir);
+ if (level.getBlockState(sourcePos).getBlock() instanceof PipeBlock || !entity.canPump()) {
+ return;
+ }
+ Direction targetCurDir = sourceDir.getOpposite();
+ IFluidHandler fluidHandler = level.getCapability(Capabilities.FluidHandler.BLOCK, sourcePos, targetCurDir);
+ if (fluidHandler == null) return;
+ PipeEnd pumpEnd = getPipeEnd(level, pos, sourceDir);
+ BlockPos targetCurPos = pos;
+ int effectiveHeight = 0;
+ if (pumpEnd != null) {
+ targetCurPos = pumpEnd.pos();
+ targetCurDir = pumpEnd.direction();
+ effectiveHeight = pumpEnd.effectiveHeight();
+ }
+ AbstractPipeBlockEntity.moveFluidWithHeightCheck(
+ level,
+ pos,
+ sourceDir,
+ targetCurPos,
+ targetCurDir,
+ effectiveHeight
+ );
+ }
+}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeBlock.java
index 13558d6e15..2ca6e15a2c 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeBlock.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeBlock.java
@@ -233,6 +233,22 @@ public static boolean isFluidHandler(Level level, BlockPos pos) {
return level.getCapability(Capabilities.FluidHandler.BLOCK, pos, state, be, null) != null;
}
+ /**
+ * 检查指定位置是否为流体处理器(通过 NeoForge Capability 系统)或泵。
+ *
+ * @param level 世界
+ * @param pos 位置
+ * @return 该位置是否提供 {@link net.neoforged.neoforge.fluids.capability.IFluidHandler} 或是泵
+ */
+ public static boolean isFluidHandlerOrPump(Level level, BlockPos pos) {
+ BlockState state = level.getBlockState(pos);
+ if (state.getBlock() instanceof PumpBlock) {
+ return true;
+ }
+ BlockEntity be = level.getBlockEntity(pos);
+ return level.getCapability(Capabilities.FluidHandler.BLOCK, pos, state, be, null) != null;
+ }
+
/**
* 检查指定方向的邻居是否被"占用"(有管道对准 或 是流体处理器)。
* 用于判断管道端头是否应该打开(无端头连接)。
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeCornerBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeCornerBlock.java
index 51f6fb0c57..a67a5f6503 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeCornerBlock.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeCornerBlock.java
@@ -92,8 +92,9 @@ protected void neighborChanged(
}
if (!corner.containsDirection(neighborDir)) {
- // 非弯管方向(侧面):有对准的管道 → 转节点
- if (isNeighborPipeToward(level, pos, neighborDir)) {
+ // 非弯管方向(侧面):有对准的管道或泵 → 转节点
+ BlockState neighborState = level.getBlockState(neighborPos);
+ if (isNeighborPipeToward(level, pos, neighborDir) || neighborState.getBlock() instanceof PumpBlock) {
BlockState nodeState = ModBlocks.PIPE_NODE.get().defaultBlockState().setValue(WATERLOGGED, state.getValue(WATERLOGGED));
for (Direction dir : Direction.values()) {
nodeState = nodeState.setValue(getPropertyForDirection(dir), PipeNodeBlock.evaluateNeighbor(level, pos, dir));
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeNodeBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeNodeBlock.java
index f255be034c..b4565beef6 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeNodeBlock.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeNodeBlock.java
@@ -144,7 +144,7 @@ protected void neighborChanged(
* 评估指定方向邻居的连接状态。
*
*
*
@@ -159,7 +159,7 @@ public static NodePipe evaluateNeighbor(Level level, BlockPos pos, Direction dir
if (neighborState.getBlock() instanceof PipeBlock && hasConnectionToward(neighborState, dir.getOpposite())) {
return NodePipe.PIPE;
}
- if (isFluidHandler(level, neighborPos)) {
+ if (isFluidHandler(level, neighborPos) || neighborState.getBlock() instanceof PumpBlock) {
return NodePipe.END;
}
return NodePipe.NONE;
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeStraightBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeStraightBlock.java
index c17ef83951..b60a6da74a 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeStraightBlock.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PipeStraightBlock.java
@@ -112,9 +112,11 @@ protected void neighborChanged(
}
if (neighborDir.getAxis() != axis) {
- // 侧面连接:检查邻居管道是否对准本方块
+ // 侧面连接:检查邻居管道是否对准本方块,或邻居是泵
+ BlockState neighborState = level.getBlockState(neighborPos);
boolean neighborIsPipeToward = isNeighborPipeToward(level, pos, neighborDir);
- if (!neighborIsPipeToward) {
+ boolean neighborIsPump = neighborState.getBlock() instanceof PumpBlock;
+ if (!neighborIsPipeToward && !neighborIsPump) {
return;
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java
new file mode 100644
index 0000000000..4aaf74b7c8
--- /dev/null
+++ b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java
@@ -0,0 +1,237 @@
+package dev.dubhe.anvilcraft.block.fluid;
+
+import com.mojang.serialization.MapCodec;
+import dev.dubhe.anvilcraft.api.hammer.IHammerChangeable;
+import dev.dubhe.anvilcraft.api.hammer.IHammerRemovable;
+import dev.dubhe.anvilcraft.api.power.IPowerComponent;
+import dev.dubhe.anvilcraft.block.better.BetterBaseEntityBlock;
+import dev.dubhe.anvilcraft.block.entity.fluid.PumpBlockEntity;
+import dev.dubhe.anvilcraft.block.state.Orientation;
+import dev.dubhe.anvilcraft.init.block.ModBlockEntities;
+import dev.dubhe.anvilcraft.init.block.ModBlocks;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
+import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.BaseEntityBlock;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.RenderShape;
+import net.minecraft.world.level.block.Rotation;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.BlockEntityTicker;
+import net.minecraft.world.level.block.entity.BlockEntityType;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.block.state.StateDefinition;
+import net.minecraft.world.level.block.state.properties.BlockStateProperties;
+import net.minecraft.world.level.block.state.properties.BooleanProperty;
+import net.minecraft.world.level.block.state.properties.EnumProperty;
+import net.minecraft.world.level.block.state.properties.Property;
+import net.minecraft.world.phys.shapes.CollisionContext;
+import net.minecraft.world.phys.shapes.VoxelShape;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * 泵(Pump),管道系统的主动流体输送设备。
+ * 消耗 32kW 电力,输入端等效高度 +10,输出端 -10。
+ * 12 向放置({@link Orientation}),铁砧锤右键反转方向,红石可关闭。
+ */
+public class PumpBlock extends BetterBaseEntityBlock implements IHammerRemovable, IHammerChangeable {
+ public static final EnumProperty
+ *
+ */
+ @Override
+ @Nullable
+ public BlockState getStateForPlacement(BlockPlaceContext context) {
+ Direction lookDir = context.getNearestLookingDirection();
+ Direction horizontalDir = context.getHorizontalDirection();
+ Player player = context.getPlayer();
+ boolean shiftDown = player != null && player.isShiftKeyDown();
+
+ if (lookDir.getAxis() == Direction.Axis.Y) {
+ // 垂直摆放:Shift 反转垂直方向(UP ↔ DOWN),水平方向跟随玩家朝向
+ if (!shiftDown) {
+ lookDir = lookDir.getOpposite();
+ }
+ } else {
+ // 水平摆放:默认输出端朝向目标方块,Shift 反向(输出端指向玩家)
+ if (!shiftDown) {
+ horizontalDir = horizontalDir.getOpposite();
+ }
+ }
+
+ Orientation orientation = switch (lookDir) {
+ case UP -> switch (horizontalDir) {
+ case SOUTH -> Orientation.UP_SOUTH;
+ case WEST -> Orientation.UP_WEST;
+ case EAST -> Orientation.UP_EAST;
+ default -> Orientation.UP_NORTH;
+ };
+ case DOWN -> switch (horizontalDir) {
+ case SOUTH -> Orientation.DOWN_SOUTH;
+ case WEST -> Orientation.DOWN_WEST;
+ case EAST -> Orientation.DOWN_EAST;
+ default -> Orientation.DOWN_NORTH;
+ };
+ default -> switch (horizontalDir) {
+ case SOUTH -> Orientation.SOUTH_UP;
+ case WEST -> Orientation.WEST_UP;
+ case EAST -> Orientation.EAST_UP;
+ default -> Orientation.NORTH_UP;
+ };
+ };
+
+ return defaultBlockState().setValue(ORIENTATION, orientation);
+ }
+
+ /**
+ * 放置后将侧面连接的直管/弯管转为三通节点,使其能正确吸附管道。
+ */
+ @Override
+ public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
+ super.setPlacedBy(level, pos, state, placer, stack);
+ if (level.isClientSide) return;
+
+ for (Direction dir : Direction.values()) {
+ BlockPos neighborPos = pos.relative(dir);
+ BlockState neighborState = level.getBlockState(neighborPos);
+ if (neighborState.getBlock() instanceof PipeStraightBlock) {
+ Direction.Axis pipeAxis = neighborState.getValue(PipeBlock.AXIS);
+ // 泵贴在直管侧面 → 将直管转为三通节点
+ if (dir.getAxis() != pipeAxis) {
+ convertPipeToNode(level, neighborPos, neighborState);
+ }
+ } else if (neighborState.getBlock() instanceof PipeCornerBlock) {
+ PipeBlock.CornerEnded corner = neighborState.getValue(PipeBlock.CORNER_ENDED);
+ // 泵贴在弯管非拐角方向的侧面 → 将弯管转为三通节点
+ if (!corner.containsDirection(dir.getOpposite())) {
+ convertPipeToNode(level, neighborPos, neighborState);
+ }
+ }
+ }
+ }
+
+ /**
+ * 将直管或弯管转为三通节点,扫描全部六个方向重新计算连接状态。
+ */
+ private void convertPipeToNode(Level level, BlockPos pos, BlockState state) {
+ BlockState nodeState = ModBlocks.PIPE_NODE.get()
+ .defaultBlockState()
+ .setValue(PipeBlock.WATERLOGGED, state.getValue(PipeBlock.WATERLOGGED));
+ for (Direction dir : Direction.values()) {
+ nodeState = nodeState.setValue(
+ PipeBlock.getPropertyForDirection(dir),
+ PipeNodeBlock.evaluateNeighbor(level, pos, dir)
+ );
+ }
+ level.setBlockAndUpdate(pos, nodeState);
+ }
+
+ /**
+ * 红石信号更新
+ */
+ @Override
+ public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) {
+ if (level.isClientSide) return;
+ boolean hasSignal = level.hasNeighborSignal(pos);
+ if (hasSignal != state.getValue(POWERED)) {
+ level.setBlock(pos, state.setValue(POWERED, hasSignal), 2);
+ }
+ }
+
+ /**
+ * 铁砧锤反转方向
+ */
+ @Override
+ public boolean change(Player player, BlockPos blockPos, Level level, ItemStack anvilHammer) {
+ BlockState state = level.getBlockState(blockPos);
+ level.setBlockAndUpdate(blockPos, state.setValue(ORIENTATION, state.getValue(ORIENTATION).opposite()));
+ return true;
+ }
+
+ @Override
+ public @Nullable Property> getChangeableProperty(BlockState state) {
+ return ORIENTATION;
+ }
+
+ @Override
+ public BlockState rotate(BlockState state, Rotation rotation) {
+ return state.setValue(ORIENTATION, state.getValue(ORIENTATION).rotate(rotation));
+ }
+
+ @Override
+ public @Nullable PumpBlockEntity newBlockEntity(BlockPos pos, BlockState state) {
+ return ModBlockEntities.PUMP.get().create(pos, state);
+ }
+
+ @Override
+ @Nullable
+ public