From 071892ea95426bb229fc7ad56d7d55fe30925c26 Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 1 Jun 2026 22:27:18 +0800 Subject: [PATCH 01/27] refactor(pipe): improve fluid movement logic by adjusting height calculations based on actual connection positions --- .../entity/fluid/AbstractPipeBlockEntity.java | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) 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..7c1044a0f6 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 @@ -213,6 +213,9 @@ protected void sendNeighbourUpdate() { /** * 流体传输(带高度差检查):使用等效高度替代真实 Y 坐标。 * 仅在源等效高度高于目标等效高度时执行传输。 + * + *

高度差基于移位后的实际连接位置(sourcePos/targetPos), + * 而非管道自身位置,以正确处理同方块两端端头的情况。 */ public static void moveFluidWithHeightCheck( Level level, @@ -221,25 +224,31 @@ public static void moveFluidWithHeightCheck( BlockPos targetCurPos, Direction targetCurDirection ) { - // 计算源的等效高度 - int sourceEffectiveY = sourceCurPos.getY(); - int targetEffectiveY = targetCurPos.getY(); - if (level.getBlockEntity(sourceCurPos) instanceof AbstractPipeBlockEntity sourceBe) { - sourceEffectiveY = sourceBe.getEffectiveHeight(); + BlockPos sourcePos = sourceCurPos.relative(sourceCurDirection); + BlockPos targetPos = targetCurPos.relative(targetCurDirection); + + // 用移位后的实际连接位置计算基础高度 + int sourceEffectiveY = sourcePos.getY(); + int targetEffectiveY = targetPos.getY(); + + // 叠加管道自身和目标位置 BlockEntity 的 heightBonus + if (level.getBlockEntity(sourceCurPos) instanceof AbstractPipeBlockEntity be) { + sourceEffectiveY += be.getHeightBonus(); } - if (level.getBlockEntity(targetCurPos) instanceof AbstractPipeBlockEntity targetBe) { - targetEffectiveY = targetBe.getEffectiveHeight(); + if (level.getBlockEntity(targetCurPos) instanceof AbstractPipeBlockEntity be) { + targetEffectiveY += be.getHeightBonus(); } - - if (sourceEffectiveY <= targetEffectiveY) { - return; + if (level.getBlockEntity(sourcePos) instanceof AbstractPipeBlockEntity be) { + sourceEffectiveY += be.getHeightBonus(); + } + if (level.getBlockEntity(targetPos) instanceof AbstractPipeBlockEntity be) { + targetEffectiveY += be.getHeightBonus(); } - BlockPos sourcePos = sourceCurPos.relative(sourceCurDirection); - BlockPos targetPos = targetCurPos.relative(targetCurDirection); + if (sourceEffectiveY <= targetEffectiveY) return; + Direction sourceDirection = sourceCurDirection.getOpposite(); Direction targetDirection = targetCurDirection.getOpposite(); - // 使用等效高度差计算流速 moveFluid(level, sourcePos, sourceDirection, targetPos, targetDirection, sourceEffectiveY - targetEffectiveY); } From ffe16f72213708538b8f71a55e2aba5870a7e3dc Mon Sep 17 00:00:00 2001 From: Gugle Date: Tue, 2 Jun 2026 17:38:35 +0800 Subject: [PATCH 02/27] refactor(pipe): add Pump block and its associated BlockEntity with crafting recipe --- .../assets/anvilcraft/blockstates/pump.json | 216 ++++++++++++++++++ .../assets/anvilcraft/lang/en_ud.json | 1 + .../assets/anvilcraft/lang/en_us.json | 1 + .../assets/anvilcraft/models/item/pump.json | 3 + .../anvilcraft/loot_table/blocks/pump.json | 21 ++ .../tags/block/mineable/pickaxe.json | 3 +- .../dev/dubhe/anvilcraft/block/PumpBlock.java | 142 ++++++++++++ .../block/entity/PumpBlockEntity.java | 118 ++++++++++ .../recipe/RegistrumItemRecipeLoader.java | 15 ++ .../init/block/ModBlockEntities.java | 6 + .../anvilcraft/init/block/ModBlocks.java | 33 +++ 11 files changed, 558 insertions(+), 1 deletion(-) create mode 100644 src/generated/resources/assets/anvilcraft/blockstates/pump.json create mode 100644 src/generated/resources/assets/anvilcraft/models/item/pump.json create mode 100644 src/generated/resources/data/anvilcraft/loot_table/blocks/pump.json create mode 100644 src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java create mode 100644 src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java 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..6f36b76afa --- /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 bd9d315ac0..12ea611a69 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_ud.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_ud.json @@ -477,6 +477,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 42c91f798f..de8f72d86d 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_us.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_us.json @@ -477,6 +477,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/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/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json index 1e35aa4c92..ce76ff9732 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:infinite_collector", "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/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java new file mode 100644 index 0000000000..cecb1c1959 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java @@ -0,0 +1,142 @@ +package dev.dubhe.anvilcraft.block; + +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.PumpBlockEntity; +import dev.dubhe.anvilcraft.block.state.Orientation; +import dev.dubhe.anvilcraft.init.block.ModBlockEntities; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +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.Block; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.Rotation; +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 ORIENTATION = EnumProperty.create("orientation", Orientation.class); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty OVERLOAD = IPowerComponent.OVERLOAD; + + /** 主体碰撞箱 [5,5,5]→[11,11,11](6x6x6 中心体) */ + private static final VoxelShape SHAPE = box(5, 5, 5, 11, 11, 11); + + public PumpBlock(Properties properties) { + super(properties); + registerDefaultState(stateDefinition.any() + .setValue(ORIENTATION, Orientation.NORTH_UP) + .setValue(POWERED, false) + .setValue(OVERLOAD, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(ORIENTATION, POWERED, OVERLOAD); + } + + @Override + public RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + /** 仅主体部分的碰撞箱 */ + @Override + public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext ctx) { + return SHAPE; + } + + @Override + protected MapCodec codec() { + return simpleCodec(PumpBlock::new); + } + + /** 放置时根据玩家视线和 Shift 计算朝向 */ + @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(); + + // 背向放置: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 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); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java new file mode 100644 index 0000000000..ca603d2849 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java @@ -0,0 +1,118 @@ +package dev.dubhe.anvilcraft.block.entity; + +import dev.dubhe.anvilcraft.api.power.IPowerConsumer; +import dev.dubhe.anvilcraft.api.power.PowerComponentType; +import dev.dubhe.anvilcraft.api.power.PowerGrid; +import dev.dubhe.anvilcraft.block.PumpBlock; +import dev.dubhe.anvilcraft.block.entity.fluid.AbstractPipeBlockEntity; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +/** + * 泵的 BlockEntity。消费 32kW 电力,提供输入端 +10 / 输出端 -10 的等效高度偏移。 + * + *

工作状态判定: + *

+ * + *

方向映射:{@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 电力消耗 + private static final int PUMP_HEAD = 10; // 10 米扬程 + + private PowerGrid grid; + private boolean working; + + public PumpBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + public static PumpBlockEntity create(BlockEntityType type, BlockPos pos, BlockState state) { + return new PumpBlockEntity(type, pos, state); + } + + @Override + public int getInputPower() { + return PUMP_POWER; + } + + @Override + public PowerComponentType getComponentType() { + return PowerComponentType.CONSUMER; + } + + @Override + public @Nullable Level getCurrentLevel() { + return getLevel(); + } + + @Override + public BlockPos getPos() { + return getBlockPos(); + } + + // ---- NBT ---- + + @Override + protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.saveAdditional(tag, registries); + tag.putBoolean("Working", working); + } + + @Override + public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.loadAdditional(tag, registries); + working = tag.getBoolean("Working"); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + CompoundTag tag = super.getUpdateTag(registries); + tag.putBoolean("Working", working); + return tag; + } + + // ---- Tick ---- + + /** + * Per-tick:刷新电力/红石/过载状态,更新 heightBonus。 + *

+ */ + public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEntity entity) { + if (level.isClientSide) return; + + boolean powered = state.getValue(PumpBlock.POWERED); + boolean overload = state.getValue(PumpBlock.OVERLOAD); + + entity.flushState(level, pos); + + boolean wasWorking = entity.working; + entity.working = !powered && !overload && entity.grid != null && entity.grid.isWorking(); + + if (entity.working != wasWorking) { + entity.setChanged(); + if (!level.isClientSide()) entity.sendUpdate(); + } + + // 设置等效高度偏移:工作中时提供 ±PUMP_HEAD 的扬程,否则为 0 + entity.heightBonus = entity.working ? PUMP_HEAD : 0; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java index 5f07d9140c..723da2bdb9 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java @@ -1365,4 +1365,19 @@ public static void pipe(DataGenContext ctx, RegistrumR ) .save(provider); } + + public static void pump(DataGenContext ctx, RegistrumRecipeProvider provider) { + ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get(), 2) + .pattern("PIP") + .pattern("P P") + .pattern(" ") + .define('P', Blocks.PISTON) + .define('I', Items.IRON_BLOCK) + .group(ctx.getId().toString()) + .unlockedBy( + AnvilCraftDatagen.hasItem(Items.PISTON), + RegistrumRecipeProvider.has(Items.PISTON) + ) + .save(provider); + } } diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java index 46e9a2c510..ba26adeee5 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java @@ -48,6 +48,7 @@ import dev.dubhe.anvilcraft.block.entity.PowerConverterBlockEntity; import dev.dubhe.anvilcraft.block.entity.PropelPistonBlockEntity; import dev.dubhe.anvilcraft.block.entity.PulseGeneratorBlockEntity; +import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; import dev.dubhe.anvilcraft.block.entity.RedStoneComputerBlockEntity; import dev.dubhe.anvilcraft.block.entity.RemoteTransmissionPoleBlockEntity; import dev.dubhe.anvilcraft.block.entity.ResentfulAmberBlockEntity; @@ -491,6 +492,11 @@ public class ModBlockEntities { .renderer(() -> LaserBlockRenderer::new) .register(); + public static final BlockEntityEntry PUMP = REGISTRUM + .blockEntity("pump", PumpBlockEntity::create) + .validBlock(ModBlocks.PUMP) + .register(); + public static final BlockEntityEntry WIP_BLOCK = REGISTRUM .blockEntity("wip_block", WipBlockEntity::new) .validBlock(ModBlocks.WIP_BLOCK) diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index 421febd770..f841865532 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -16,6 +16,8 @@ import dev.dubhe.anvilcraft.block.BlockDevourerBlock; import dev.dubhe.anvilcraft.block.BlockPlacerBlock; import dev.dubhe.anvilcraft.block.BurningHeaterBlock; +import dev.dubhe.anvilcraft.block.PumpBlock; +import dev.dubhe.anvilcraft.block.state.Orientation; import dev.dubhe.anvilcraft.block.CakeBaseBlock; import dev.dubhe.anvilcraft.block.CakeBlock; import dev.dubhe.anvilcraft.block.CementCauldronBlock; @@ -4201,6 +4203,37 @@ private static BlockEntry registerCementLiquidBlock(Color color) { .tag(BlockTags.MINEABLE_WITH_PICKAXE) .register(); + public static final BlockEntry PUMP = REGISTRUM.block("pump", PumpBlock::new) + .initialProperties(() -> Blocks.IRON_BLOCK) + .properties(p -> p.noOcclusion().sound(SoundType.METAL)) + .blockstate((ctx, provider) -> { + provider.getVariantBuilder(ctx.get()).forAllStates(state -> { + boolean powered = state.getValue(PumpBlock.POWERED); + boolean overload = state.getValue(PumpBlock.OVERLOAD); + Orientation orientation = state.getValue(PumpBlock.ORIENTATION); + + String modelName; + if (overload) { + modelName = "block/pump_overload"; + } else if (powered) { + modelName = "block/pump_off"; + } else { + modelName = "block/pump_base"; + } + + var model = provider.models().getExistingFile(AnvilCraft.of(modelName)); + + return net.neoforged.neoforge.client.model.generators.ConfiguredModel.builder() + .modelFile(model) + .rotationX((int) orientation.getXRotation()) + .rotationY((int) orientation.getYRotation()) + .build(); + }); + }) + .simpleItem() + .tag(BlockTags.MINEABLE_WITH_PICKAXE) + .register(); + public static void register() { } From c00c9e025691807dad941ad63291e17d221d73cc Mon Sep 17 00:00:00 2001 From: Gugle Date: Tue, 2 Jun 2026 18:24:01 +0800 Subject: [PATCH 03/27] refactor(pipe): reorganize imports for PumpBlock and Orientation classes --- src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index f841865532..9101073d75 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -107,6 +107,7 @@ import dev.dubhe.anvilcraft.block.PowerConverterSmallBlock; import dev.dubhe.anvilcraft.block.PropelPiston; import dev.dubhe.anvilcraft.block.PulseGeneratorBlock; +import dev.dubhe.anvilcraft.block.PumpBlock; import dev.dubhe.anvilcraft.block.RedstoneComputerBlock; import dev.dubhe.anvilcraft.block.ReinforcedConcreteBlock; import dev.dubhe.anvilcraft.block.RemoteTransmissionPoleBlock; @@ -210,6 +211,7 @@ import dev.dubhe.anvilcraft.block.state.Cube3x3PartHalf; import dev.dubhe.anvilcraft.block.state.DirectionCube3x3PartHalf; import dev.dubhe.anvilcraft.block.state.FragmentationDegree; +import dev.dubhe.anvilcraft.block.state.Orientation; import dev.dubhe.anvilcraft.block.state.Vertical3PartHalf; import dev.dubhe.anvilcraft.block.state.Vertical4PartHalf; import dev.dubhe.anvilcraft.data.generator.PipeBlockStateGenerator; From 111cfa3ed19a722f05979d94a2db150984398e62 Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 03:55:26 +0800 Subject: [PATCH 04/27] =?UTF-8?q?refactor(blocks):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=88=9D=E5=A7=8B=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除未使用的 PumpBlock 和 Orientation 导入 - 调整 CelestialForgingAnvilPortalBlockItem 的导入位置 - 优化模块块初始化顺序 --- src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index 9101073d75..77731e63d5 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -16,8 +16,6 @@ import dev.dubhe.anvilcraft.block.BlockDevourerBlock; import dev.dubhe.anvilcraft.block.BlockPlacerBlock; import dev.dubhe.anvilcraft.block.BurningHeaterBlock; -import dev.dubhe.anvilcraft.block.PumpBlock; -import dev.dubhe.anvilcraft.block.state.Orientation; import dev.dubhe.anvilcraft.block.CakeBaseBlock; import dev.dubhe.anvilcraft.block.CakeBlock; import dev.dubhe.anvilcraft.block.CementCauldronBlock; @@ -155,10 +153,10 @@ import dev.dubhe.anvilcraft.block.cfa.item.CelestialForgingAnvilAmplifierBlockItem; import dev.dubhe.anvilcraft.block.cfa.item.CelestialForgingAnvilBlockItem; import dev.dubhe.anvilcraft.block.cfa.item.CelestialForgingAnvilInterfaceBlockItem; +import dev.dubhe.anvilcraft.block.cfa.item.CelestialForgingAnvilPortalBlockItem; 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.cfa.item.CelestialForgingAnvilPortalBlockItem; import dev.dubhe.anvilcraft.block.heatable.GlowingBlock; import dev.dubhe.anvilcraft.block.heatable.HeatedBlock; import dev.dubhe.anvilcraft.block.heatable.IncandescentBlock; From cd86d0229895e2d74c6aa3191b4d0d0d7be36e8b Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 04:30:15 +0800 Subject: [PATCH 05/27] =?UTF-8?q?style(block):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=B3=B5=E6=A8=A1=E5=9E=8B=E7=9A=84=E6=98=BE=E7=A4=BA=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除第三人称左右手的旋转设置 - 调整第三人称左右手的平移和缩放值 - 移除第一人称左右手的显示配置 - 移除地面和GUI的显示配置 - 修改头部的平移位置 - 更新固定视角的旋转和缩放设置 - 添加书架上放置的旋转配置 --- .../assets/anvilcraft/models/block/pump.json | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/src/main/resources/assets/anvilcraft/models/block/pump.json b/src/main/resources/assets/anvilcraft/models/block/pump.json index 61bf853de0..8e6ee499a0 100644 --- a/src/main/resources/assets/anvilcraft/models/block/pump.json +++ b/src/main/resources/assets/anvilcraft/models/block/pump.json @@ -166,40 +166,22 @@ ], "display": { "thirdperson_righthand": { - "rotation": [75, 45, 0], - "translation": [0, 2.5, 0], - "scale": [0.2, 0.2, 0.2] + "translation": [0, -2, 0], + "scale": [0.5, 0.5, 0.5] }, "thirdperson_lefthand": { - "rotation": [75, 45, 0], - "translation": [0, 2.5, 0], - "scale": [0.2, 0.2, 0.2] - }, - "firstperson_righthand": { - "rotation": [0, -135, 0], - "translation": [3.75, 0, 0], - "scale": [0.2, 0.2, 0.2] - }, - "firstperson_lefthand": { - "rotation": [0, -135, 0], - "translation": [3.75, 0, 0], - "scale": [0.2, 0.2, 0.2] - }, - "ground": { - "translation": [0, 4, 0], - "scale": [0.2, 0.2, 0.2] - }, - "gui": { - "rotation": [30, -135, 0], - "translation": [0, -0.25, 0], - "scale": [0.24, 0.24, 0.24] + "translation": [0, -2, 0], + "scale": [0.5, 0.5, 0.5] }, "head": { - "translation": [0, 1, 0], - "scale": [0.6, 0.6, 0.6] + "translation": [0, 0, -14.25] }, "fixed": { - "scale": [0.66, 0.66, 0.66] + "rotation": [90, 0, 0], + "scale": [0.5, 0.5, 0.5] + }, + "on_shelf": { + "rotation": [90, 0, 0] } } } \ No newline at end of file From ea29a8082e8741977f80e48d626c8e613e6f4364 Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 05:31:36 +0800 Subject: [PATCH 06/27] =?UTF-8?q?feat(block):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B3=B5=E6=96=B9=E5=9D=97=E5=8A=9F=E8=83=BD=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=B5=81=E4=BD=93=E4=BC=A0=E8=BE=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 注册泵方块实体类型并添加流体处理器能力 - 实现泵的主动流体抽取和注入逻辑 - 添加泵与管道系统的连接和转换机制 - 实现泵的工作状态检测和电力消耗 - 添加泵的配方和物品模型 - 实现泵活塞动画渲染效果 - 添加泵放置时的朝向计算和管道对接逻辑 --- .../advancement/recipes/misc/pump.json | 43 +++++ .../data/anvilcraft/recipe/pump.json | 22 +++ .../dev/dubhe/anvilcraft/block/PumpBlock.java | 53 +++++- .../block/entity/PumpBlockEntity.java | 162 +++++++++++++++++- .../blockentity/PumpBlockEntityRenderer.java | 124 ++++++++++++++ .../recipe/RegistrumBlockRecipeLoader.java | 19 ++ .../recipe/RegistrumItemRecipeLoader.java | 14 -- .../event/CapabilitiesEventListener.java | 3 +- .../init/block/ModBlockEntities.java | 2 + .../anvilcraft/init/block/ModBlocks.java | 1 + 10 files changed, 423 insertions(+), 20 deletions(-) create mode 100644 src/generated/resources/data/anvilcraft/advancement/recipes/misc/pump.json create mode 100644 src/generated/resources/data/anvilcraft/recipe/pump.json create mode 100644 src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java 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/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/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java index cecb1c1959..d3a33fba65 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java @@ -6,10 +6,15 @@ import dev.dubhe.anvilcraft.api.power.IPowerComponent; import dev.dubhe.anvilcraft.block.better.BetterBaseEntityBlock; import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; +import dev.dubhe.anvilcraft.block.fluid.PipeBlock; +import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock; +import dev.dubhe.anvilcraft.block.fluid.PipeStraightBlock; 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; @@ -71,7 +76,7 @@ protected MapCodec codec() { return simpleCodec(PumpBlock::new); } - /** 放置时根据玩家视线和 Shift 计算朝向 */ + /** 放置时根据玩家视线和 Shift 计算朝向,并对接管道 */ @Override @Nullable public BlockState getStateForPlacement(BlockPlaceContext context) { @@ -104,9 +109,55 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { }; }; + // 对着管道开口放置时:背向放置(输出口背离管道) + BlockPos targetPos = context.getClickedPos().relative(context.getClickedFace().getOpposite()); + BlockState targetState = context.getLevel().getBlockState(targetPos); + if (targetState.getBlock() instanceof PipeBlock) { + orientation = orientation.opposite(); + } + 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, dir.getOpposite()); + } + } + } + } + + /** 将直管转为三通节点,保留原有两端的连接并添加新方向 */ + private void convertPipeToNode(Level level, BlockPos pos, BlockState state, Direction newDirection) { + Direction.Axis axis = state.getValue(PipeBlock.AXIS); + Direction startDir = Direction.get(Direction.AxisDirection.NEGATIVE, axis); + Direction endDir = Direction.get(Direction.AxisDirection.POSITIVE, axis); + + BlockState nodeState = ModBlocks.PIPE_NODE.get().defaultBlockState() + .setValue(PipeBlock.WATERLOGGED, state.getValue(PipeBlock.WATERLOGGED)); + nodeState = nodeState.setValue( + PipeBlock.getPropertyForDirection(startDir), + PipeNodeBlock.evaluateNeighbor(level, pos, startDir)); + nodeState = nodeState.setValue( + PipeBlock.getPropertyForDirection(endDir), + PipeNodeBlock.evaluateNeighbor(level, pos, endDir)); + nodeState = nodeState.setValue( + PipeBlock.getPropertyForDirection(newDirection), + PipeBlock.NodePipe.PIPE); + level.setBlockAndUpdate(pos, nodeState); + } + /** 红石信号更新 */ @Override public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java index ca603d2849..bb91250f38 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java @@ -1,18 +1,24 @@ package dev.dubhe.anvilcraft.block.entity; +import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; import dev.dubhe.anvilcraft.api.power.IPowerConsumer; import dev.dubhe.anvilcraft.api.power.PowerComponentType; import dev.dubhe.anvilcraft.api.power.PowerGrid; import dev.dubhe.anvilcraft.block.PumpBlock; import dev.dubhe.anvilcraft.block.entity.fluid.AbstractPipeBlockEntity; +import dev.dubhe.anvilcraft.block.state.Orientation; import lombok.Getter; import lombok.Setter; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; import org.jetbrains.annotations.Nullable; /** @@ -30,7 +36,7 @@ */ @Getter @Setter -public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerConsumer { +public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerConsumer, IFluidHandlerHolder { private static final int PUMP_POWER = 32; // 32 kW 电力消耗 private static final int PUMP_HEAD = 10; // 10 米扬程 @@ -38,6 +44,13 @@ public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerCo private PowerGrid grid; private boolean working; + /** 上 tick 实际传输的流体量(mB),用于客户端活塞动画速度 */ + @Getter + private int lastTransferAmount; + + /** 重入防护:防止 IFluidHandler relay 时无限递归 */ + private boolean transferring; + public PumpBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } @@ -66,33 +79,137 @@ public BlockPos getPos() { return getBlockPos(); } + // ---- IFluidHandlerHolder ---- + + @Override + public IFluidHandler getFluidHandler() { + return new PumpFluidHandler(); + } + + /** + * 获取相邻方块在指定侧面的 IFluidHandler。 + * + * @param side 泵朝向该邻居的方向 + */ + @Nullable + private IFluidHandler getNeighborFluidHandler(Direction side) { + if (level == null) return null; + BlockPos neighborPos = getBlockPos().relative(side); + return level.getCapability(Capabilities.FluidHandler.BLOCK, neighborPos, side.getOpposite()); + } + + /** + * 泵的无缓存流体处理器。 + *
    + *
  • 工作中:drain 从输入端邻居抽取,fill 向输出端邻居注入
  • + *
  • 关闭/过载:容量为 0,阻塞所有流体
  • + *
+ */ + private class PumpFluidHandler implements IFluidHandler { + + @Override + public int getTanks() { + return 1; + } + + @Override + public FluidStack getFluidInTank(int tank) { + return FluidStack.EMPTY; + } + + @Override + public int getTankCapacity(int tank) { + if (!working) return 0; + return PUMP_HEAD * 50; // 500 mB/tick = 10m × 50 mB/tick/m + } + + @Override + public boolean isFluidValid(int tank, FluidStack stack) { + return working; + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + if (!working || transferring) return 0; + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof PumpBlock)) return 0; + Direction outputDir = state.getValue(PumpBlock.ORIENTATION).getDirection(); + IFluidHandler output = getNeighborFluidHandler(outputDir); + if (output == null) return 0; + + transferring = true; + try { + return output.fill(resource, action); + } finally { + transferring = false; + } + } + + @Override + public FluidStack drain(FluidStack resource, FluidAction action) { + if (!working || transferring) return FluidStack.EMPTY; + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof PumpBlock)) return FluidStack.EMPTY; + Direction inputDir = state.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); + IFluidHandler input = getNeighborFluidHandler(inputDir); + if (input == null) return FluidStack.EMPTY; + + transferring = true; + try { + return input.drain(resource, action); + } finally { + transferring = false; + } + } + + @Override + public FluidStack drain(int maxDrain, FluidAction action) { + if (!working || transferring) return FluidStack.EMPTY; + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof PumpBlock)) return FluidStack.EMPTY; + Direction inputDir = state.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); + IFluidHandler input = getNeighborFluidHandler(inputDir); + if (input == null) return FluidStack.EMPTY; + + transferring = true; + try { + return input.drain(maxDrain, action); + } finally { + transferring = false; + } + } + } + // ---- NBT ---- @Override protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.saveAdditional(tag, registries); tag.putBoolean("Working", working); + tag.putInt("LastTransferAmount", lastTransferAmount); } @Override public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); working = tag.getBoolean("Working"); + lastTransferAmount = tag.getInt("LastTransferAmount"); } @Override public CompoundTag getUpdateTag(HolderLookup.Provider registries) { CompoundTag tag = super.getUpdateTag(registries); tag.putBoolean("Working", working); + tag.putInt("LastTransferAmount", lastTransferAmount); return tag; } // ---- Tick ---- /** - * Per-tick:刷新电力/红石/过载状态,更新 heightBonus。 + * Per-tick:刷新电力/红石/过载状态,更新 heightBonus,并执行主动流体中转。 *
    - *
  • 正常工作 → heightBonus = +PUMP_HEAD(输入端),-PUMP_HEAD(输出端)
  • + *
  • 正常工作 → heightBonus = +PUMP_HEAD,主动从输入端抽流体注入输出端
  • *
  • 关闭/过载 → heightBonus = 0(阻塞流体)
  • *
*/ @@ -112,7 +229,44 @@ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEn if (!level.isClientSide()) entity.sendUpdate(); } - // 设置等效高度偏移:工作中时提供 ±PUMP_HEAD 的扬程,否则为 0 + // 设置等效高度偏移:工作中时提供 PUMP_HEAD 的扬程,否则为 0 entity.heightBonus = entity.working ? PUMP_HEAD : 0; + + // 主动流体中转:从输入端抽取流体,注入输出端 + int transferred = 0; + if (entity.working && !entity.transferring) { + Orientation orientation = state.getValue(PumpBlock.ORIENTATION); + Direction outputDir = orientation.getDirection(); + Direction inputDir = outputDir.getOpposite(); + + IFluidHandler inputHandler = entity.getNeighborFluidHandler(inputDir); + IFluidHandler outputHandler = entity.getNeighborFluidHandler(outputDir); + + if (inputHandler != null && outputHandler != null) { + int maxTransfer = PUMP_HEAD * 50; // 500 mB/tick + entity.transferring = true; + try { + FluidStack drained = inputHandler.drain(maxTransfer, IFluidHandler.FluidAction.SIMULATE); + if (!drained.isEmpty()) { + int filled = outputHandler.fill(drained, IFluidHandler.FluidAction.SIMULATE); + if (filled > 0) { + FluidStack toMove = drained.copyWithAmount(filled); + inputHandler.drain(toMove, IFluidHandler.FluidAction.EXECUTE); + outputHandler.fill(toMove, IFluidHandler.FluidAction.EXECUTE); + transferred = filled; + } + } + } finally { + entity.transferring = false; + } + } + } + + // 同步传输量到客户端(用于活塞动画速度) + if (entity.lastTransferAmount != transferred) { + entity.lastTransferAmount = transferred; + entity.setChanged(); + if (!level.isClientSide()) entity.sendUpdate(); + } } } diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java new file mode 100644 index 0000000000..ae15964798 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -0,0 +1,124 @@ +package dev.dubhe.anvilcraft.client.renderer.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.block.PumpBlock; +import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; +import dev.dubhe.anvilcraft.block.state.Orientation; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +/** + * 泵的方块实体渲染器。 + * 在工作状态时渲染两个活塞模型(pump_piston_1, pump_piston_2), + * 交替上下运动,运动速度与流体传输量正相关。 + * + *

基础模型(pump_base/pump_off/pump_overload)由 blockstate 系统渲染, + * 本渲染器仅负责动画活塞部分。 + */ +public class PumpBlockEntityRenderer implements BlockEntityRenderer { + + private static final ModelResourceLocation PUMP_PISTON_1 = + ModelResourceLocation.standalone(AnvilCraft.of("block/pump_piston_1")); + private static final ModelResourceLocation PUMP_PISTON_2 = + ModelResourceLocation.standalone(AnvilCraft.of("block/pump_piston_2")); + + /** 活塞最大位移(单位:方块,2/16 = 2 像素) */ + private static final float MAX_PISTON_OFFSET = 2.0f / 16.0f; + + /** 最大传输速率(mB/tick),用于归一化动画速度 */ + private static final float MAX_TRANSFER_RATE = 500.0f; + + @SuppressWarnings("unused") + public PumpBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + public void render( + PumpBlockEntity blockEntity, + float partialTick, + PoseStack poseStack, + MultiBufferSource buffer, + int packedLight, + int packedOverlay + ) { + if (!blockEntity.isWorking()) return; + + BlockState state = blockEntity.getBlockState(); + if (!(state.getBlock() instanceof PumpBlock)) return; + + Orientation orientation = state.getValue(PumpBlock.ORIENTATION); + Direction outputDir = orientation.getDirection(); + + // 动画速度与传输量正相关 + float speed = blockEntity.getLastTransferAmount() / MAX_TRANSFER_RATE; + if (speed < 0.05f) speed = 1.0f; // 最慢也有基础动画 + + long gameTime = blockEntity.getLevel().getGameTime(); + float cycle = ((gameTime + partialTick) * speed) % 20.0f / 20.0f; + + // 活塞 1:峰值在 cycle = 0.25(上顶点) + float piston1Offset = sinPulse(cycle, 0.25f) * MAX_PISTON_OFFSET; + // 活塞 2:峰值在 cycle = 0.75(上顶点),与活塞 1 错开半周期 + float piston2Offset = sinPulse(cycle, 0.75f) * MAX_PISTON_OFFSET; + + // 沿输出方向平移并渲染 + float dx = outputDir.getStepX(); + float dy = outputDir.getStepY(); + float dz = outputDir.getStepZ(); + + // 注意:活塞模型设计在 NORTH_UP 方向(Y 旋转 180°),需匹配 blockstate 的旋转 + // 这里的平移是相对于泵主体的局部空间,沿输出方向运动 + + poseStack.pushPose(); + poseStack.translate(dx * piston1Offset, dy * piston1Offset, dz * piston1Offset); + renderPistonModel(poseStack, buffer, PUMP_PISTON_1, packedLight, packedOverlay); + poseStack.popPose(); + + poseStack.pushPose(); + poseStack.translate(dx * piston2Offset, dy * piston2Offset, dz * piston2Offset); + renderPistonModel(poseStack, buffer, PUMP_PISTON_2, packedLight, packedOverlay); + poseStack.popPose(); + } + + /** + * 正弦脉冲:在 phase 处达到最大值 1,phase±0.25 处为 0。 + * + * @param cycle 当前周期位置 [0, 1) + * @param phase 峰值相位 [0, 1) + * @return 脉冲高度 [0, 1] + */ + private static float sinPulse(float cycle, float phase) { + float dist = Math.abs(cycle - phase); + if (dist > 0.5f) dist = 1.0f - dist; + if (dist > 0.25f) return 0f; + return (float) Math.sin(dist / 0.25f * Math.PI); + } + + private void renderPistonModel( + PoseStack poseStack, + MultiBufferSource buffer, + ModelResourceLocation modelLocation, + int packedLight, + int packedOverlay + ) { + Minecraft.getInstance() + .getBlockRenderer() + .getModelRenderer() + .renderModel( + poseStack.last(), + buffer.getBuffer(RenderType.cutout()), + null, + Minecraft.getInstance().getModelManager().getModel(modelLocation), + 1.0f, 1.0f, 1.0f, + packedLight, + packedOverlay + ); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumBlockRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumBlockRecipeLoader.java index 9139b33b06..81601f8c07 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumBlockRecipeLoader.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumBlockRecipeLoader.java @@ -2139,4 +2139,23 @@ public static void infiniteCollector(DataGenContext AnvilCraftDatagen.has(ModItems.TRANSCENDIUM_INGOT)) .save(provider); } + + public static void pump(DataGenContext ctx, RegistrumRecipeProvider provider) { + ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get().asItem(), 2) + .pattern("PCP") + .pattern("P P") + .pattern(" ") + .define('P', Blocks.PISTON) + .define('C', ModBlocks.PIPE_STRAIGHT.asItem()) + .group(ctx.getId().toString()) + .unlockedBy( + AnvilCraftDatagen.hasItem(Blocks.PISTON.asItem()), + RegistrumRecipeProvider.has(Blocks.PISTON) + ) + .unlockedBy( + AnvilCraftDatagen.hasItem(ModBlocks.PIPE_STRAIGHT.asItem()), + RegistrumRecipeProvider.has(ModBlocks.PIPE_STRAIGHT) + ) + .save(provider); + } } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java index 723da2bdb9..2a7d3386a3 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RegistrumItemRecipeLoader.java @@ -1366,18 +1366,4 @@ public static void pipe(DataGenContext ctx, RegistrumR .save(provider); } - public static void pump(DataGenContext ctx, RegistrumRecipeProvider provider) { - ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get(), 2) - .pattern("PIP") - .pattern("P P") - .pattern(" ") - .define('P', Blocks.PISTON) - .define('I', Items.IRON_BLOCK) - .group(ctx.getId().toString()) - .unlockedBy( - AnvilCraftDatagen.hasItem(Items.PISTON), - RegistrumRecipeProvider.has(Items.PISTON) - ) - .save(provider); - } } diff --git a/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java index 72db4c3b73..470be2818a 100644 --- a/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java @@ -71,7 +71,8 @@ public static void registerCapabilities(final RegisterCapabilitiesEvent event) { ModBlockEntities.FLUID_TANK.get(), ModBlockEntities.LARGE_FLUID_TANK.get(), ModBlockEntities.CREATIVE_FLUID_TANK.get(), - ModBlockEntities.PIPE_NODE.get() + ModBlockEntities.PIPE_NODE.get(), + ModBlockEntities.PUMP.get() ).forEach(type -> event.registerBlockEntity( Capabilities.FluidHandler.BLOCK, type, diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java index ba26adeee5..bcd58fc6a0 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java @@ -102,6 +102,7 @@ import dev.dubhe.anvilcraft.client.renderer.blockentity.LargeFluidTankBlockEntityRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.LaserBlockRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.PlasmaJetsRenderer; +import dev.dubhe.anvilcraft.client.renderer.blockentity.PumpBlockEntityRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.SmartBlockPlacerRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.TeslaTowerRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.TradingStationBlockEntityRenderer; @@ -495,6 +496,7 @@ public class ModBlockEntities { public static final BlockEntityEntry PUMP = REGISTRUM .blockEntity("pump", PumpBlockEntity::create) .validBlock(ModBlocks.PUMP) + .renderer(() -> PumpBlockEntityRenderer::new) .register(); public static final BlockEntityEntry WIP_BLOCK = REGISTRUM diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index 77731e63d5..73a84763e6 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -4231,6 +4231,7 @@ private static BlockEntry registerCementLiquidBlock(Color color) { }); }) .simpleItem() + .recipe(RegistrumBlockRecipeLoader::pump) .tag(BlockTags.MINEABLE_WITH_PICKAXE) .register(); From de4a543c485188aae2bc99ea60fb6728955674f2 Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 19:01:21 +0800 Subject: [PATCH 07/27] =?UTF-8?q?fix(pump):=20=E4=BF=AE=E5=A4=8D=E6=B3=B5?= =?UTF-8?q?=E6=96=B9=E5=9D=97=E6=94=BE=E7=BD=AE=E6=97=B6=E7=9A=84=E6=9C=9D?= =?UTF-8?q?=E5=90=91=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除自动对接管道的逻辑,避免意外的朝向反转 - 更新注释说明,默认输入端朝向目标方块,Shift 键反向 - 明确按住 Shift 键时的放置行为(输出端朝向目标方块) --- .../java/dev/dubhe/anvilcraft/block/PumpBlock.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java index d3a33fba65..b56e4b41df 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java @@ -76,7 +76,7 @@ protected MapCodec codec() { return simpleCodec(PumpBlock::new); } - /** 放置时根据玩家视线和 Shift 计算朝向,并对接管道 */ + /** 放置时根据玩家视线和 Shift 计算朝向。默认输入端朝向目标方块,Shift 反向 */ @Override @Nullable public BlockState getStateForPlacement(BlockPlaceContext context) { @@ -85,7 +85,7 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { Player player = context.getPlayer(); boolean shiftDown = player != null && player.isShiftKeyDown(); - // 背向放置:shift 反转 + // 按住 Shift 反向放置(输出端朝向目标方块) if (shiftDown) horizontalDir = horizontalDir.getOpposite(); Orientation orientation = switch (lookDir) { @@ -109,13 +109,6 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { }; }; - // 对着管道开口放置时:背向放置(输出口背离管道) - BlockPos targetPos = context.getClickedPos().relative(context.getClickedFace().getOpposite()); - BlockState targetState = context.getLevel().getBlockState(targetPos); - if (targetState.getBlock() instanceof PipeBlock) { - orientation = orientation.opposite(); - } - return defaultBlockState().setValue(ORIENTATION, orientation); } From b264e22582f200c4f3152c7cb5bd19bb3c255eb5 Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 19:19:15 +0800 Subject: [PATCH 08/27] =?UTF-8?q?fix(block):=20=E4=BF=AE=E6=AD=A3=E6=B0=B4?= =?UTF-8?q?=E6=B3=B5=E6=96=B9=E5=9D=97=E6=94=BE=E7=BD=AE=E6=9C=9D=E5=90=91?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复注释中关于默认输出端朝向的描述 - 纠正放置时朝向计算逻辑,默认输出端朝向目标方块,Shift反向 - 调整活塞动画渲染代码顺序,确保注释与实现一致 - 优化活塞移动偏移量计算的代码结构 --- .../java/dev/dubhe/anvilcraft/block/PumpBlock.java | 6 +++--- .../renderer/blockentity/PumpBlockEntityRenderer.java | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java index b56e4b41df..40c8ac20b7 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java @@ -76,7 +76,7 @@ protected MapCodec codec() { return simpleCodec(PumpBlock::new); } - /** 放置时根据玩家视线和 Shift 计算朝向。默认输入端朝向目标方块,Shift 反向 */ + /** 放置时根据玩家视线和 Shift 计算朝向。默认输出端朝向目标方块,Shift 反向(输出端指向玩家) */ @Override @Nullable public BlockState getStateForPlacement(BlockPlaceContext context) { @@ -85,8 +85,8 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { Player player = context.getPlayer(); boolean shiftDown = player != null && player.isShiftKeyDown(); - // 按住 Shift 反向放置(输出端朝向目标方块) - if (shiftDown) horizontalDir = horizontalDir.getOpposite(); + // 默认输出端朝向目标方块;按住 Shift 反向(输出端指向玩家) + if (!shiftDown) horizontalDir = horizontalDir.getOpposite(); Orientation orientation = switch (lookDir) { case UP -> switch (horizontalDir) { diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index ae15964798..eb8f91a297 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -63,11 +63,6 @@ public void render( long gameTime = blockEntity.getLevel().getGameTime(); float cycle = ((gameTime + partialTick) * speed) % 20.0f / 20.0f; - // 活塞 1:峰值在 cycle = 0.25(上顶点) - float piston1Offset = sinPulse(cycle, 0.25f) * MAX_PISTON_OFFSET; - // 活塞 2:峰值在 cycle = 0.75(上顶点),与活塞 1 错开半周期 - float piston2Offset = sinPulse(cycle, 0.75f) * MAX_PISTON_OFFSET; - // 沿输出方向平移并渲染 float dx = outputDir.getStepX(); float dy = outputDir.getStepY(); @@ -76,11 +71,17 @@ public void render( // 注意:活塞模型设计在 NORTH_UP 方向(Y 旋转 180°),需匹配 blockstate 的旋转 // 这里的平移是相对于泵主体的局部空间,沿输出方向运动 + // 活塞 1:峰值在 cycle = 0.25(上顶点) + float piston1Offset = sinPulse(cycle, 0.25f) * MAX_PISTON_OFFSET; + poseStack.pushPose(); poseStack.translate(dx * piston1Offset, dy * piston1Offset, dz * piston1Offset); renderPistonModel(poseStack, buffer, PUMP_PISTON_1, packedLight, packedOverlay); poseStack.popPose(); + // 活塞 2:峰值在 cycle = 0.75(上顶点),与活塞 1 错开半周期 + float piston2Offset = sinPulse(cycle, 0.75f) * MAX_PISTON_OFFSET; + poseStack.pushPose(); poseStack.translate(dx * piston2Offset, dy * piston2Offset, dz * piston2Offset); renderPistonModel(poseStack, buffer, PUMP_PISTON_2, packedLight, packedOverlay); From e334557f3dc159b9071730332169b4c9a99b51fa Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 19:22:23 +0800 Subject: [PATCH 09/27] =?UTF-8?q?fix(block):=20=E4=BF=AE=E5=A4=8D=E6=8A=BD?= =?UTF-8?q?=E6=B0=B4=E6=9C=BA=E7=A2=B0=E6=92=9E=E7=AE=B1=E5=BD=A2=E7=8A=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整碰撞箱从 6x6x6 中心体 [5,5,5]→[11,11,11] - 修改为匹配模型元素 1/2/7 的尺寸 x[3,13] y[3,13] z[0,16] --- src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java index 40c8ac20b7..cfa0b064c8 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java @@ -44,8 +44,8 @@ public class PumpBlock extends BetterBaseEntityBlock implements IHammerRemovable public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty OVERLOAD = IPowerComponent.OVERLOAD; - /** 主体碰撞箱 [5,5,5]→[11,11,11](6x6x6 中心体) */ - private static final VoxelShape SHAPE = box(5, 5, 5, 11, 11, 11); + /** 主体碰撞箱,匹配模型元素 1/2/7:x[3,13] y[3,13] z[0,16] */ + private static final VoxelShape SHAPE = box(3, 3, 0, 13, 13, 16); public PumpBlock(Properties properties) { super(properties); From a2bf5e9fc11b6c5c70e6e3c932380fd2258af8ae Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 19:23:34 +0800 Subject: [PATCH 10/27] =?UTF-8?q?fix(block):=20=E4=BF=AE=E5=A4=8D=E6=B3=B5?= =?UTF-8?q?=E5=9D=97=E5=9C=A8=E4=B8=8D=E5=90=8C=E6=9C=9D=E5=90=91=E4=B8=8B?= =?UTF-8?q?=E7=9A=84=E7=A2=B0=E6=92=9E=E7=AE=B1=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将单一碰撞箱拆分为三个方向特定的碰撞箱(X、Y、Z轴) - 为NORTH_UP/SOUTH_UP朝向添加沿Z轴延伸的碰撞箱 - 为WEST_UP/EAST_UP朝向添加沿X轴延伸的碰撞箱 - 为UP_*/DOWN_*朝向添加沿Y轴延伸的碰撞箱 - 根据方块朝向动态返回正确的碰撞箱形状 - 修正了方块在不同方向下碰撞检测不准确的问题 --- .../dev/dubhe/anvilcraft/block/PumpBlock.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java index cfa0b064c8..23f3139b80 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java @@ -44,8 +44,12 @@ public class PumpBlock extends BetterBaseEntityBlock implements IHammerRemovable public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty OVERLOAD = IPowerComponent.OVERLOAD; - /** 主体碰撞箱,匹配模型元素 1/2/7:x[3,13] y[3,13] z[0,16] */ - private static final VoxelShape SHAPE = box(3, 3, 0, 13, 13, 16); + /** 主体碰撞箱 — 沿 Z 轴延伸(NORTH_UP / SOUTH_UP) */ + private static final VoxelShape SHAPE_Z = box(3, 3, 0, 13, 13, 16); + /** 主体碰撞箱 — 沿 X 轴延伸(WEST_UP / EAST_UP) */ + private static final VoxelShape SHAPE_X = box(0, 3, 3, 16, 13, 13); + /** 主体碰撞箱 — 沿 Y 轴延伸(UP_* / DOWN_*) */ + private static final VoxelShape SHAPE_Y = box(3, 0, 3, 13, 16, 13); public PumpBlock(Properties properties) { super(properties); @@ -65,10 +69,14 @@ public RenderShape getRenderShape(BlockState state) { return RenderShape.MODEL; } - /** 仅主体部分的碰撞箱 */ + /** 根据朝向返回旋转后的主体碰撞箱 */ @Override public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext ctx) { - return SHAPE; + return switch (state.getValue(ORIENTATION).getDirection().getAxis()) { + case X -> SHAPE_X; + case Y -> SHAPE_Y; + default -> SHAPE_Z; + }; } @Override From c904e09bc16dbcf4ef3715deebaef8895a2c8efe Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 19:32:20 +0800 Subject: [PATCH 11/27] =?UTF-8?q?refactor(renderer):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B0=B4=E6=B3=B5=E6=96=B9=E5=9D=97=E5=AE=9E=E4=BD=93=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E5=99=A8=E5=AE=9E=E7=8E=B0=E6=B4=BB=E5=A1=9E=E5=8A=A8?= =?UTF-8?q?=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 导入 Axis 类用于旋转操作 - 移除 Direction 导入并改用 BakedModel 替代 ModelResourceLocation - 通过姿态变换应用 blockstate 旋转使活塞坐标系与模型对齐 - 将活塞模型沿 Z 轴方向移动改为在模型空间内进行变换 - 简化活塞偏移计算逻辑并优化姿态堆栈管理 - 更新渲染方法参数以直接使用烘焙模型对象 - 删除无用的方向变量和注释说明 --- .../blockentity/PumpBlockEntityRenderer.java | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index eb8f91a297..1a2d496322 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -1,6 +1,7 @@ package dev.dubhe.anvilcraft.client.renderer.blockentity; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.block.PumpBlock; import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; @@ -10,8 +11,8 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; /** @@ -53,47 +54,43 @@ public void render( BlockState state = blockEntity.getBlockState(); if (!(state.getBlock() instanceof PumpBlock)) return; - Orientation orientation = state.getValue(PumpBlock.ORIENTATION); - Direction outputDir = orientation.getDirection(); - // 动画速度与传输量正相关 float speed = blockEntity.getLastTransferAmount() / MAX_TRANSFER_RATE; - if (speed < 0.05f) speed = 1.0f; // 最慢也有基础动画 + if (speed < 0.05f) speed = 1.0f; long gameTime = blockEntity.getLevel().getGameTime(); float cycle = ((gameTime + partialTick) * speed) % 20.0f / 20.0f; - // 沿输出方向平移并渲染 - float dx = outputDir.getStepX(); - float dy = outputDir.getStepY(); - float dz = outputDir.getStepZ(); - - // 注意:活塞模型设计在 NORTH_UP 方向(Y 旋转 180°),需匹配 blockstate 的旋转 - // 这里的平移是相对于泵主体的局部空间,沿输出方向运动 - - // 活塞 1:峰值在 cycle = 0.25(上顶点) + Orientation orientation = state.getValue(PumpBlock.ORIENTATION); + // 应用与 blockstate 相同的旋转,使活塞坐标系与模型对齐 + poseStack.pushPose(); + poseStack.translate(0.5, 0.5, 0.5); + poseStack.mulPose(Axis.YP.rotationDegrees(orientation.getYRotation())); + poseStack.mulPose(Axis.XP.rotationDegrees(orientation.getXRotation())); + poseStack.translate(-0.5, -0.5, -0.5); + + // 活塞模型沿 +Z 方向运动(模型空间中输出方向 = +Z) + BakedModel piston1 = Minecraft.getInstance().getModelManager().getModel(PUMP_PISTON_1); + // 活塞 1:峰值在 cycle=0.25(上顶点) float piston1Offset = sinPulse(cycle, 0.25f) * MAX_PISTON_OFFSET; - poseStack.pushPose(); - poseStack.translate(dx * piston1Offset, dy * piston1Offset, dz * piston1Offset); - renderPistonModel(poseStack, buffer, PUMP_PISTON_1, packedLight, packedOverlay); + poseStack.translate(0, 0, piston1Offset); + renderPistonModel(poseStack, buffer, piston1, packedLight, packedOverlay); poseStack.popPose(); - // 活塞 2:峰值在 cycle = 0.75(上顶点),与活塞 1 错开半周期 + BakedModel piston2 = Minecraft.getInstance().getModelManager().getModel(PUMP_PISTON_2); + // 活塞 2:峰值在 cycle=0.75(上顶点),与活塞 1 错开半周期 float piston2Offset = sinPulse(cycle, 0.75f) * MAX_PISTON_OFFSET; - poseStack.pushPose(); - poseStack.translate(dx * piston2Offset, dy * piston2Offset, dz * piston2Offset); - renderPistonModel(poseStack, buffer, PUMP_PISTON_2, packedLight, packedOverlay); + poseStack.translate(0, 0, piston2Offset); + renderPistonModel(poseStack, buffer, piston2, packedLight, packedOverlay); + poseStack.popPose(); + poseStack.popPose(); } /** * 正弦脉冲:在 phase 处达到最大值 1,phase±0.25 处为 0。 - * - * @param cycle 当前周期位置 [0, 1) - * @param phase 峰值相位 [0, 1) - * @return 脉冲高度 [0, 1] */ private static float sinPulse(float cycle, float phase) { float dist = Math.abs(cycle - phase); @@ -105,7 +102,7 @@ private static float sinPulse(float cycle, float phase) { private void renderPistonModel( PoseStack poseStack, MultiBufferSource buffer, - ModelResourceLocation modelLocation, + BakedModel model, int packedLight, int packedOverlay ) { @@ -116,7 +113,7 @@ private void renderPistonModel( poseStack.last(), buffer.getBuffer(RenderType.cutout()), null, - Minecraft.getInstance().getModelManager().getModel(modelLocation), + model, 1.0f, 1.0f, 1.0f, packedLight, packedOverlay From 614bdae370754486b4463b6f75fb5b7909fe9129 Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 19:49:11 +0800 Subject: [PATCH 12/27] =?UTF-8?q?feat(pump):=20=E4=B8=BA=E6=B3=B5=E6=96=B9?= =?UTF-8?q?=E5=9D=97=E6=B7=BB=E5=8A=A0=E5=AE=9E=E4=BD=93=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E6=B5=81=E4=BD=93=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了 BaseEntityBlock 和 BlockEntity 相关接口实现 - 重构了注释以提高代码可读性 - 实现了 TickableBlockEntity 功能 - 优化了流体处理逻辑,增加电网供电检查 - 修复了红石信号和电网过载状态处理 - 更新了碰撞箱和方块状态处理逻辑 --- .../dev/dubhe/anvilcraft/block/PumpBlock.java | 63 +++++++++++------ .../block/entity/PumpBlockEntity.java | 69 +++++++++++-------- 2 files changed, 85 insertions(+), 47 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java index 23f3139b80..a9046e8cad 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java @@ -20,9 +20,13 @@ 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; @@ -39,16 +43,21 @@ * 12 向放置({@link Orientation}),铁砧锤右键反转方向,红石可关闭。 */ public class PumpBlock extends BetterBaseEntityBlock implements IHammerRemovable, IHammerChangeable { - public static final EnumProperty ORIENTATION = EnumProperty.create("orientation", Orientation.class); public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty OVERLOAD = IPowerComponent.OVERLOAD; - /** 主体碰撞箱 — 沿 Z 轴延伸(NORTH_UP / SOUTH_UP) */ + /** + * 主体碰撞箱 — 沿 Z 轴延伸(NORTH_UP / SOUTH_UP) + */ private static final VoxelShape SHAPE_Z = box(3, 3, 0, 13, 13, 16); - /** 主体碰撞箱 — 沿 X 轴延伸(WEST_UP / EAST_UP) */ + /** + * 主体碰撞箱 — 沿 X 轴延伸(WEST_UP / EAST_UP) + */ private static final VoxelShape SHAPE_X = box(0, 3, 3, 16, 13, 13); - /** 主体碰撞箱 — 沿 Y 轴延伸(UP_* / DOWN_*) */ + /** + * 主体碰撞箱 — 沿 Y 轴延伸(UP_* / DOWN_*) + */ private static final VoxelShape SHAPE_Y = box(3, 0, 3, 13, 16, 13); public PumpBlock(Properties properties) { @@ -69,7 +78,9 @@ public RenderShape getRenderShape(BlockState state) { return RenderShape.MODEL; } - /** 根据朝向返回旋转后的主体碰撞箱 */ + /** + * 根据朝向返回旋转后的主体碰撞箱 + */ @Override public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext ctx) { return switch (state.getValue(ORIENTATION).getDirection().getAxis()) { @@ -84,7 +95,9 @@ protected MapCodec codec() { return simpleCodec(PumpBlock::new); } - /** 放置时根据玩家视线和 Shift 计算朝向。默认输出端朝向目标方块,Shift 反向(输出端指向玩家) */ + /** + * 放置时根据玩家视线和 Shift 计算朝向。默认输出端朝向目标方块,Shift 反向(输出端指向玩家) + */ @Override @Nullable public BlockState getStateForPlacement(BlockPlaceContext context) { @@ -120,7 +133,9 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { 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); @@ -139,27 +154,26 @@ public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable L } } - /** 将直管转为三通节点,保留原有两端的连接并添加新方向 */ + /** + * 将直管转为三通节点,保留原有两端的连接并添加新方向 + */ private void convertPipeToNode(Level level, BlockPos pos, BlockState state, Direction newDirection) { Direction.Axis axis = state.getValue(PipeBlock.AXIS); Direction startDir = Direction.get(Direction.AxisDirection.NEGATIVE, axis); Direction endDir = Direction.get(Direction.AxisDirection.POSITIVE, axis); - BlockState nodeState = ModBlocks.PIPE_NODE.get().defaultBlockState() + BlockState nodeState = ModBlocks.PIPE_NODE.get() + .defaultBlockState() .setValue(PipeBlock.WATERLOGGED, state.getValue(PipeBlock.WATERLOGGED)); - nodeState = nodeState.setValue( - PipeBlock.getPropertyForDirection(startDir), - PipeNodeBlock.evaluateNeighbor(level, pos, startDir)); - nodeState = nodeState.setValue( - PipeBlock.getPropertyForDirection(endDir), - PipeNodeBlock.evaluateNeighbor(level, pos, endDir)); - nodeState = nodeState.setValue( - PipeBlock.getPropertyForDirection(newDirection), - PipeBlock.NodePipe.PIPE); + nodeState = nodeState.setValue(PipeBlock.getPropertyForDirection(startDir), PipeNodeBlock.evaluateNeighbor(level, pos, startDir)); + nodeState = nodeState.setValue(PipeBlock.getPropertyForDirection(endDir), PipeNodeBlock.evaluateNeighbor(level, pos, endDir)); + nodeState = nodeState.setValue(PipeBlock.getPropertyForDirection(newDirection), PipeBlock.NodePipe.PIPE); level.setBlockAndUpdate(pos, nodeState); } - /** 红石信号更新 */ + /** + * 红石信号更新 + */ @Override public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { if (level.isClientSide) return; @@ -169,7 +183,9 @@ public void neighborChanged(BlockState state, Level level, BlockPos pos, Block b } } - /** 铁砧锤反转方向 */ + /** + * 铁砧锤反转方向 + */ @Override public boolean change(Player player, BlockPos blockPos, Level level, ItemStack anvilHammer) { BlockState state = level.getBlockState(blockPos); @@ -191,4 +207,11 @@ public BlockState rotate(BlockState state, Rotation rotation) { public @Nullable PumpBlockEntity newBlockEntity(BlockPos pos, BlockState state) { return ModBlockEntities.PUMP.get().create(pos, state); } + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + if (level.isClientSide()) return null; + return BaseEntityBlock.createTickerHelper(type, ModBlockEntities.PUMP.get(), PumpBlockEntity::tick); + } } diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java index bb91250f38..f43aef8461 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java @@ -2,7 +2,6 @@ import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; import dev.dubhe.anvilcraft.api.power.IPowerConsumer; -import dev.dubhe.anvilcraft.api.power.PowerComponentType; import dev.dubhe.anvilcraft.api.power.PowerGrid; import dev.dubhe.anvilcraft.block.PumpBlock; import dev.dubhe.anvilcraft.block.entity.fluid.AbstractPipeBlockEntity; @@ -19,7 +18,8 @@ import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.capability.IFluidHandler; -import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nullable; /** * 泵的 BlockEntity。消费 32kW 电力,提供输入端 +10 / 输出端 -10 的等效高度偏移。 @@ -41,14 +41,18 @@ public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerCo private static final int PUMP_POWER = 32; // 32 kW 电力消耗 private static final int PUMP_HEAD = 10; // 10 米扬程 - private PowerGrid grid; + private @Nullable PowerGrid grid; private boolean working; - /** 上 tick 实际传输的流体量(mB),用于客户端活塞动画速度 */ + /** + * 上 tick 实际传输的流体量(mB),用于客户端活塞动画速度 + */ @Getter private int lastTransferAmount; - /** 重入防护:防止 IFluidHandler relay 时无限递归 */ + /** + * 重入防护:防止 IFluidHandler relay 时无限递归 + */ private boolean transferring; public PumpBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { @@ -64,11 +68,6 @@ public int getInputPower() { return PUMP_POWER; } - @Override - public PowerComponentType getComponentType() { - return PowerComponentType.CONSUMER; - } - @Override public @Nullable Level getCurrentLevel() { return getLevel(); @@ -98,11 +97,18 @@ private IFluidHandler getNeighborFluidHandler(Direction side) { return level.getCapability(Capabilities.FluidHandler.BLOCK, neighborPos, side.getOpposite()); } + /** + * 泵是否能实际泵送流体(启用 + 电网有电) + */ + private boolean canPump() { + return working && grid != null && grid.isWorking(); + } + /** * 泵的无缓存流体处理器。 *

    - *
  • 工作中:drain 从输入端邻居抽取,fill 向输出端邻居注入
  • - *
  • 关闭/过载:容量为 0,阻塞所有流体
  • + *
  • 能泵送时:drain 从输入端邻居抽取,fill 向输出端邻居注入
  • + *
  • 关闭/过载/无电:容量为 0,阻塞所有流体
  • *
*/ private class PumpFluidHandler implements IFluidHandler { @@ -119,18 +125,18 @@ public FluidStack getFluidInTank(int tank) { @Override public int getTankCapacity(int tank) { - if (!working) return 0; + if (!canPump()) return 0; return PUMP_HEAD * 50; // 500 mB/tick = 10m × 50 mB/tick/m } @Override public boolean isFluidValid(int tank, FluidStack stack) { - return working; + return canPump(); } @Override public int fill(FluidStack resource, FluidAction action) { - if (!working || transferring) return 0; + if (!canPump() || transferring) return 0; BlockState state = getBlockState(); if (!(state.getBlock() instanceof PumpBlock)) return 0; Direction outputDir = state.getValue(PumpBlock.ORIENTATION).getDirection(); @@ -147,7 +153,7 @@ public int fill(FluidStack resource, FluidAction action) { @Override public FluidStack drain(FluidStack resource, FluidAction action) { - if (!working || transferring) return FluidStack.EMPTY; + if (!canPump() || transferring) return FluidStack.EMPTY; BlockState state = getBlockState(); if (!(state.getBlock() instanceof PumpBlock)) return FluidStack.EMPTY; Direction inputDir = state.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); @@ -164,7 +170,7 @@ public FluidStack drain(FluidStack resource, FluidAction action) { @Override public FluidStack drain(int maxDrain, FluidAction action) { - if (!working || transferring) return FluidStack.EMPTY; + if (!canPump() || transferring) return FluidStack.EMPTY; BlockState state = getBlockState(); if (!(state.getBlock() instanceof PumpBlock)) return FluidStack.EMPTY; Direction inputDir = state.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); @@ -209,33 +215,42 @@ public CompoundTag getUpdateTag(HolderLookup.Provider registries) { /** * Per-tick:刷新电力/红石/过载状态,更新 heightBonus,并执行主动流体中转。 *
    - *
  • 正常工作 → heightBonus = +PUMP_HEAD,主动从输入端抽流体注入输出端
  • - *
  • 关闭/过载 → heightBonus = 0(阻塞流体)
  • + *
  • 红石信号 / 电网过载 → working=false(阻塞流体,停动画)
  • + *
  • 正常启用 + 电网供电 → 实际泵送 + heightBonus
  • + *
  • 启用但电网未供电 → 仅动画运行(活塞运动),不泵送
  • *
*/ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEntity entity) { if (level.isClientSide) return; - boolean powered = state.getValue(PumpBlock.POWERED); - boolean overload = state.getValue(PumpBlock.OVERLOAD); - + // 刷新电网过载状态到 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 && entity.grid != null && entity.grid.isWorking(); + entity.working = !powered && !overload; if (entity.working != wasWorking) { entity.setChanged(); if (!level.isClientSide()) entity.sendUpdate(); } - // 设置等效高度偏移:工作中时提供 PUMP_HEAD 的扬程,否则为 0 - entity.heightBonus = entity.working ? PUMP_HEAD : 0; + // 电网是否能提供足够功率 + boolean gridPowered = entity.grid != null && entity.grid.isWorking(); + + // 实际泵送需要启用状态 + 电网供电 + boolean canPump = entity.working && gridPowered; + entity.heightBonus = canPump ? PUMP_HEAD : 0; // 主动流体中转:从输入端抽取流体,注入输出端 int transferred = 0; - if (entity.working && !entity.transferring) { - Orientation orientation = state.getValue(PumpBlock.ORIENTATION); + if (canPump && !entity.transferring) { + Orientation orientation = updatedState.getValue(PumpBlock.ORIENTATION); Direction outputDir = orientation.getDirection(); Direction inputDir = outputDir.getOpposite(); From 180749e4008809ff000243932eaa4d7d1fe4730c Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 20:02:41 +0800 Subject: [PATCH 13/27] =?UTF-8?q?fix(renderer):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=B3=B5=E6=96=B9=E5=9D=97=E5=AE=9E=E4=BD=93=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E5=81=8F=E7=A7=BB=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在Y轴方向移动-2像素以校正整体位置 - 将活塞1的Z轴偏移量改为Y轴偏移 - 将活塞2的Z轴偏移量改为Y轴偏移 - 注册新的泵活塞模型资源位置 --- .../client/event/RegisterAdditionalEventListener.java | 2 ++ .../renderer/blockentity/PumpBlockEntityRenderer.java | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/client/event/RegisterAdditionalEventListener.java b/src/main/java/dev/dubhe/anvilcraft/client/event/RegisterAdditionalEventListener.java index 6006af59f2..7fed12f92b 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/event/RegisterAdditionalEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/event/RegisterAdditionalEventListener.java @@ -71,6 +71,8 @@ public static void registerModels(ModelEvent.RegisterAdditional event) { event.register(ModelResourceLocation.standalone(AnvilCraft.of("block/smart_block_placer_forearm"))); event.register(ModelResourceLocation.standalone(AnvilCraft.of("block/smart_block_placer_claw"))); event.register(ModelResourceLocation.standalone(AnvilCraft.of("block/smart_block_placer_claw_open"))); + event.register(ModelResourceLocation.standalone(AnvilCraft.of("block/pump_piston_1"))); + event.register(ModelResourceLocation.standalone(AnvilCraft.of("block/pump_piston_2"))); // Special celestial body models event.register(ModelResourceLocation.standalone(AnvilCraft.of("block/celestial_body/planet_overworld"))); diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index 1a2d496322..4f204ec71e 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -69,12 +69,14 @@ public void render( poseStack.mulPose(Axis.XP.rotationDegrees(orientation.getXRotation())); poseStack.translate(-0.5, -0.5, -0.5); + poseStack.translate(0, -2.0f / 16.0f, 0); + // 活塞模型沿 +Z 方向运动(模型空间中输出方向 = +Z) BakedModel piston1 = Minecraft.getInstance().getModelManager().getModel(PUMP_PISTON_1); // 活塞 1:峰值在 cycle=0.25(上顶点) float piston1Offset = sinPulse(cycle, 0.25f) * MAX_PISTON_OFFSET; poseStack.pushPose(); - poseStack.translate(0, 0, piston1Offset); + poseStack.translate(0, piston1Offset, 0); renderPistonModel(poseStack, buffer, piston1, packedLight, packedOverlay); poseStack.popPose(); @@ -82,7 +84,7 @@ public void render( // 活塞 2:峰值在 cycle=0.75(上顶点),与活塞 1 错开半周期 float piston2Offset = sinPulse(cycle, 0.75f) * MAX_PISTON_OFFSET; poseStack.pushPose(); - poseStack.translate(0, 0, piston2Offset); + poseStack.translate(0, piston2Offset, 0); renderPistonModel(poseStack, buffer, piston2, packedLight, packedOverlay); poseStack.popPose(); From 65ae69eb372ed406f8146bc779583961532bde57 Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 20:07:05 +0800 Subject: [PATCH 14/27] =?UTF-8?q?fix(renderer):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=B3=B5=E6=96=B9=E5=9D=97=E5=AE=9E=E4=BD=93=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E6=97=8B=E8=BD=AC=E6=96=B9=E5=90=91=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 应用负值旋转角度以校正 blockstate 与 JOML 坐标系之间的差异 - 调整旋转应用顺序为先 X 轴后 Y 轴以确保正确的变换矩阵乘法 - 添加注释说明坐标系差异及旋转顺序的重要性 --- .../renderer/blockentity/PumpBlockEntityRenderer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index 4f204ec71e..4fb128b485 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -65,8 +65,10 @@ public void render( // 应用与 blockstate 相同的旋转,使活塞坐标系与模型对齐 poseStack.pushPose(); poseStack.translate(0.5, 0.5, 0.5); - poseStack.mulPose(Axis.YP.rotationDegrees(orientation.getYRotation())); - poseStack.mulPose(Axis.XP.rotationDegrees(orientation.getXRotation())); + // blockstate Y+ 方向与 JOML 相反,需取反 + // 顺序:先 X 后 Y(mulPose 后乘,先 Y 则 X 对向量先生效) + poseStack.mulPose(Axis.YP.rotationDegrees(-orientation.getYRotation())); + poseStack.mulPose(Axis.XP.rotationDegrees(-orientation.getXRotation())); poseStack.translate(-0.5, -0.5, -0.5); poseStack.translate(0, -2.0f / 16.0f, 0); From 10bc735fcaae91b941319b4c334d402ba71c753e Mon Sep 17 00:00:00 2001 From: Gugle Date: Sun, 21 Jun 2026 20:13:06 +0800 Subject: [PATCH 15/27] =?UTF-8?q?refactor(renderer):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B3=B5=E6=B4=BB=E5=A1=9E=E5=8A=A8=E7=94=BB=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将活塞最大位移从 2/16 减少到 1.5/16 - 活塞运动方式从 Z 轴单方向改为 Y 轴正弦余弦交替运动 - 使用正弦和余弦函数分别控制两个活塞的位移计算 - 移除 sinPulse 辅助方法并简化动画计算逻辑 - 消除活塞运动过程中的死区问题 --- .../blockentity/PumpBlockEntityRenderer.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index 4fb128b485..3dfbdfb45f 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -31,7 +31,7 @@ public class PumpBlockEntityRenderer implements BlockEntityRenderer 0.5f) dist = 1.0f - dist; - if (dist > 0.25f) return 0f; - return (float) Math.sin(dist / 0.25f * Math.PI); - } - private void renderPistonModel( PoseStack poseStack, MultiBufferSource buffer, From 2d1fdd7f3f0489566109c2c4faa61d5f2fc68edd Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 20:19:48 +0800 Subject: [PATCH 16/27] =?UTF-8?q?feat(fluid):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=AE=A1=E9=81=93=E6=B5=81=E4=BD=93=E4=BC=A0=E8=BE=93=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E6=94=AF=E6=8C=81=E6=B3=B5=E6=89=AC=E7=A8=8B=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 AbstractPipeBlockEntity 中的 heightBonus 字段及其相关方法 - 添加 PumpBlock 和 PumpBlockEntity 的依赖导入 - 修改 getPipeEnd 方法以支持泵的等效高度计算和追踪逻辑 - 实现泵输出端的流体传输透传追踪功能 - 更新 moveFluidWithHeightCheck 方法签名以传递有效高度参数 - 修改管道和节点方块实体中的流体传输逻辑以兼容新高度计算方式 - 将 PumpBlockEntity 中的 PUMP_HEAD 常量重命名为 PUMP_HEADLIFT 并改为 public - 修改 PumpBlockEntity 中的 canPump 方法访问级别为 public - 移除泵工作时对 heightBonus 的设置逻辑 - 更新 PumpBlockEntity 中的容量和传输量计算使用新常量名 --- .../block/entity/PumpBlockEntity.java | 9 +- .../entity/fluid/AbstractPipeBlockEntity.java | 126 ++++++++++-------- .../block/entity/fluid/PipeBlockEntity.java | 125 ++++++++++++----- .../entity/fluid/PipeNodeBlockEntity.java | 69 +++++++--- 4 files changed, 215 insertions(+), 114 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java index f43aef8461..faae7422d3 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java @@ -39,7 +39,7 @@ public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerConsumer, IFluidHandlerHolder { private static final int PUMP_POWER = 32; // 32 kW 电力消耗 - private static final int PUMP_HEAD = 10; // 10 米扬程 + public static final int PUMP_HEADLIFT = 10; // 10 米扬程 private @Nullable PowerGrid grid; private boolean working; @@ -100,7 +100,7 @@ private IFluidHandler getNeighborFluidHandler(Direction side) { /** * 泵是否能实际泵送流体(启用 + 电网有电) */ - private boolean canPump() { + public boolean canPump() { return working && grid != null && grid.isWorking(); } @@ -126,7 +126,7 @@ public FluidStack getFluidInTank(int tank) { @Override public int getTankCapacity(int tank) { if (!canPump()) return 0; - return PUMP_HEAD * 50; // 500 mB/tick = 10m × 50 mB/tick/m + return PUMP_HEADLIFT * 50; // 500 mB/tick = 10m × 50 mB/tick/m } @Override @@ -245,7 +245,6 @@ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEn // 实际泵送需要启用状态 + 电网供电 boolean canPump = entity.working && gridPowered; - entity.heightBonus = canPump ? PUMP_HEAD : 0; // 主动流体中转:从输入端抽取流体,注入输出端 int transferred = 0; @@ -258,7 +257,7 @@ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEn IFluidHandler outputHandler = entity.getNeighborFluidHandler(outputDir); if (inputHandler != null && outputHandler != null) { - int maxTransfer = PUMP_HEAD * 50; // 500 mB/tick + int maxTransfer = PUMP_HEADLIFT * 50; // 500 mB/tick entity.transferring = true; try { FluidStack drained = inputHandler.drain(maxTransfer, IFluidHandler.FluidAction.SIMULATE); 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 7c1044a0f6..472f84d890 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 @@ -1,5 +1,7 @@ package dev.dubhe.anvilcraft.block.entity.fluid; +import dev.dubhe.anvilcraft.block.PumpBlock; +import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; import dev.dubhe.anvilcraft.block.fluid.PipeBlock; import dev.dubhe.anvilcraft.block.fluid.PipeCornerBlock; import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock; @@ -36,48 +38,16 @@ * 限制流速(每格高度差 50 mB/tick)。 * *

等效高度(Effective Height)

- * 每个管道 BlockEntity 持有一个 {@link #heightBonus} 字段, * 代表该段管道的等效高度偏移(泵可增大此值实现扬程)。 * 流体传输和 PipeEnd 排序均以 {@code pos.getY() + heightBonus} 作为等效高度, * 而非真实 Y 坐标。 */ @Getter public abstract class AbstractPipeBlockEntity extends BlockEntity { - - /** - * 本段管道的等效高度偏移。泵等设备可设置为正值以实现扬程。 - * 最终等效高度 = {@code getBlockPos().getY() + heightBonus}。 - */ - protected int heightBonus; - protected AbstractPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { super(type, pos, blockState); } - /** - * 本段管道的等效高度 - * - * @return 本段管道的等效高度(真实Y + 偏移) - */ - public int getEffectiveHeight() { - return this.getBlockPos().getY() + this.heightBonus; - } - - /** - * 设置本段管道的等效高度偏移。 - * - * @param bonus 偏移量(正值提高等效高度,实现扬程) - */ - public void setHeightBonus(int bonus) { - if (this.heightBonus != bonus) { - this.heightBonus = bonus; - this.setChanged(); - if (this.level != null && !this.level.isClientSide()) { - this.sendUpdate(); - } - } - } - /** * 触发客户端渲染更新 */ @@ -115,20 +85,25 @@ protected void sendNeighbourUpdate() { } BlockState blockState = level.getBlockState(blockPos); - // 累加当前位置管道的高度偏移 - int bonus = 0; - if (level.getBlockEntity(blockPos) instanceof AbstractPipeBlockEntity pipeBe) { - bonus = pipeBe.getHeightBonus(); - } - if (blockState.getBlock() instanceof PipeNodeBlock) { - return new PipeEnd(blockPos.relative(direction.getOpposite()), direction, accumulatedHeight + bonus + blockPos.getY()); + return new PipeEnd(blockPos.relative(direction.getOpposite()), direction, accumulatedHeight); } if (blockState.getBlock() instanceof PipeStraightBlock) { - return getPipeStraightEnd(level, blockPos, blockState, direction, accumulatedHeight + bonus); + return getPipeStraightEnd(level, blockPos, blockState, direction, accumulatedHeight); } if (blockState.getBlock() instanceof PipeCornerBlock) { - return getPipeCornerEnd(level, blockPos, blockState, direction, accumulatedHeight + bonus); + return getPipeCornerEnd(level, blockPos, blockState, direction, accumulatedHeight); + } + if (blockState.getBlock() instanceof PumpBlock) { + Direction pumpOutputDir = blockState.getValue(PumpBlock.ORIENTATION).getDirection(); + if (direction == pumpOutputDir) { + if (level.getBlockEntity(blockPos) instanceof PumpBlockEntity pumpBe && pumpBe.canPump()) { + // 泵可工作且方向匹配 → 等效距离 +10 并继续追踪 + return getPumpPipeEnd(level, blockPos, direction, accumulatedHeight); + } + } + // 方向不匹配或泵不能工作 → 清空等效距离并返回 + return null; } return null; } @@ -169,7 +144,12 @@ protected void sendNeighbourUpdate() { } Direction targetDir = direction.getOpposite(); if (!hasNext) { - return new PipeEnd(blockPos, targetDir, accumulatedHeight + blockPos.getY()); + // 检查端头指向的方块是否是泵,若是则继续追踪 + BlockPos neighborPos = blockPos.relative(targetDir); + if (level.getBlockState(neighborPos).getBlock() instanceof PumpBlock) { + return getPipeEnd(level, neighborPos, targetDir, accumulatedHeight); + } + return new PipeEnd(blockPos, targetDir, accumulatedHeight); } return getPipeEnd(level, blockPos.relative(targetDir), direction, accumulatedHeight); } @@ -205,11 +185,54 @@ protected void sendNeighbourUpdate() { targetDir = startDir; } if (!hasNext) { - return new PipeEnd(blockPos, targetDir, accumulatedHeight + blockPos.getY()); + // 检查端头指向的方块是否是泵,若是则继续追踪 + BlockPos neighborPos = blockPos.relative(targetDir); + if (level.getBlockState(neighborPos).getBlock() instanceof PumpBlock) { + return getPipeEnd(level, neighborPos, targetDir, accumulatedHeight); + } + return new PipeEnd(blockPos, targetDir, accumulatedHeight); } return getPipeEnd(level, blockPos.relative(targetDir), targetDir.getOpposite(), accumulatedHeight); } + /** + * 从泵的输出端继续追踪 PipeEnd。 + *
    + *
  • 相邻方块是管道/泵 → 继续递归追踪
  • + *
  • 相邻方块是 IFluidHandler → 返回 PipeEnd(泵输出端直接对其排液)
  • + *
  • 其他 → null(无有效终点)
  • + *
+ * + * @param level 世界 + * @param pumpPos 泵的位置 + * @param direction 追踪方向(泵的输出方向) + * @param accumulatedHeight 已累积的等效高度(含泵的 heightBonus) + * @return PipeEnd,不可达时返回 null + */ + private static @Nullable PipeEnd getPumpPipeEnd(Level level, BlockPos pumpPos, Direction direction, int accumulatedHeight) { + BlockPos nextPos = pumpPos.relative(direction); + if (!level.isLoaded(nextPos)) return null; + + BlockState nextState = level.getBlockState(nextPos); + + // 若相邻是管道或泵,继续管道追踪 + if ( + nextState.getBlock() instanceof PipeNodeBlock + || nextState.getBlock() instanceof PipeStraightBlock + || nextState.getBlock() instanceof PipeCornerBlock + || nextState.getBlock() instanceof PumpBlock + ) { + return getPipeEnd(level, nextPos, direction, accumulatedHeight + PumpBlockEntity.PUMP_HEADLIFT); + } + + // 若相邻是流体处理器,泵输出端直接对其排液 + if (PipeBlock.isFluidHandler(level, nextPos)) { + return new PipeEnd(pumpPos, direction, accumulatedHeight + PumpBlockEntity.PUMP_HEADLIFT); + } + + return null; + } + /** * 流体传输(带高度差检查):使用等效高度替代真实 Y 坐标。 * 仅在源等效高度高于目标等效高度时执行传输。 @@ -222,7 +245,8 @@ public static void moveFluidWithHeightCheck( BlockPos sourceCurPos, Direction sourceCurDirection, BlockPos targetCurPos, - Direction targetCurDirection + Direction targetCurDirection, + int effectiveHeight ) { BlockPos sourcePos = sourceCurPos.relative(sourceCurDirection); BlockPos targetPos = targetCurPos.relative(targetCurDirection); @@ -231,19 +255,7 @@ public static void moveFluidWithHeightCheck( int sourceEffectiveY = sourcePos.getY(); int targetEffectiveY = targetPos.getY(); - // 叠加管道自身和目标位置 BlockEntity 的 heightBonus - if (level.getBlockEntity(sourceCurPos) instanceof AbstractPipeBlockEntity be) { - sourceEffectiveY += be.getHeightBonus(); - } - if (level.getBlockEntity(targetCurPos) instanceof AbstractPipeBlockEntity be) { - targetEffectiveY += be.getHeightBonus(); - } - if (level.getBlockEntity(sourcePos) instanceof AbstractPipeBlockEntity be) { - sourceEffectiveY += be.getHeightBonus(); - } - if (level.getBlockEntity(targetPos) instanceof AbstractPipeBlockEntity be) { - targetEffectiveY += be.getHeightBonus(); - } + targetEffectiveY -= effectiveHeight; if (sourceEffectiveY <= targetEffectiveY) return; 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..e1cd1d083a 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 @@ -1,5 +1,6 @@ package dev.dubhe.anvilcraft.block.entity.fluid; +import dev.dubhe.anvilcraft.block.PumpBlock; import dev.dubhe.anvilcraft.block.fluid.PipeBlock; import dev.dubhe.anvilcraft.block.fluid.PipeCornerBlock; import dev.dubhe.anvilcraft.block.fluid.PipeStraightBlock; @@ -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 getUpdatePacket() { /** * Per-tick 排液逻辑。 * - *

仅当有端头时才执行。两端端头且非垂直/非垂直弯管时跳过(避免水平管误排)。 - * 单端端头时沿无端头端追踪 PipeEnd 并向其排液。 + *

仅当有端头时才执行。两端端头时按管轴方向排液, + * 端头指向泵时自动透传追踪(不提前返回)。 + * 单端端头时沿无端头方向追踪 PipeEnd 并向其排液。 */ public static void tick(Level level, BlockPos pos, BlockState state) { int endCount = getEndCount(state); @@ -102,34 +96,86 @@ 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); + + // 检查端头指向的方块是否是泵,若是则透传追踪 + BlockPos sourceCurPos = pos; + Direction sourceCurDir = posDir; + BlockPos targetCurPos = pos; + Direction targetCurDir = negDir; + + BlockPos sourceNeighbor = pos.relative(posDir); + if (level.getBlockState(sourceNeighbor).getBlock() instanceof PumpBlock) { + PipeEnd pumpEnd = getPipeEnd(level, sourceNeighbor, posDir); + if (pumpEnd != null) { + sourceCurPos = pumpEnd.pos(); + sourceCurDir = pumpEnd.direction().getOpposite(); + } + } + + BlockPos targetNeighbor = pos.relative(negDir); + int effectiveHeight = 0; + if (level.getBlockState(targetNeighbor).getBlock() instanceof PumpBlock) { + PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, negDir); + if (pumpEnd != null) { + targetCurPos = pumpEnd.pos(); + targetCurDir = pumpEnd.direction().getOpposite(); + effectiveHeight = pumpEnd.effectiveHeight(); + } + } + + AbstractPipeBlockEntity.moveFluidWithHeightCheck( + level, + sourceCurPos, + sourceCurDir, + targetCurPos, + targetCurDir, + effectiveHeight + ); } 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(); + + BlockPos sourceCurPos = pos; + Direction sourceCurDir = firstDir; + BlockPos targetCurPos = pos; + Direction targetCurDir = secondDir; + + BlockPos sourceNeighbor = pos.relative(firstDir); + if (level.getBlockState(sourceNeighbor).getBlock() instanceof PumpBlock) { + PipeEnd pumpEnd = getPipeEnd(level, sourceNeighbor, firstDir); + if (pumpEnd != null) { + sourceCurPos = pumpEnd.pos(); + sourceCurDir = pumpEnd.direction().getOpposite(); + } } + + BlockPos targetNeighbor = pos.relative(secondDir); + int effectiveHeight = 0; + if (level.getBlockState(targetNeighbor).getBlock() instanceof PumpBlock) { + PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, secondDir); + if (pumpEnd != null) { + targetCurPos = pumpEnd.pos(); + targetCurDir = pumpEnd.direction().getOpposite(); + effectiveHeight = pumpEnd.effectiveHeight(); + } + } + + AbstractPipeBlockEntity.moveFluidWithHeightCheck( + level, + sourceCurPos, + sourceCurDir, + targetCurPos, + targetCurDir, + effectiveHeight + ); } return; } @@ -156,6 +202,13 @@ 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() + ); } } 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..db9ed8c70f 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 @@ -1,6 +1,7 @@ package dev.dubhe.anvilcraft.block.entity.fluid; import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; +import dev.dubhe.anvilcraft.block.PumpBlock; import dev.dubhe.anvilcraft.block.fluid.PipeBlock; import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock; import lombok.Getter; @@ -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 property = PipeBlock.getPropertyForDirection(direction); PipeBlock.NodePipe value = state.getValue(property); - // END + UP:向上方排液 + // END + UP:向上方排液(若端头指向泵则透传追踪) if (value.equals(PipeBlock.NodePipe.END) && direction.equals(Direction.UP)) { - AbstractPipeBlockEntity.moveFluidWithHeightCheck( - level, pos, Direction.UP, pos.relative(Direction.UP), Direction.DOWN); + BlockPos neighborPos = pos.relative(Direction.UP); + if (level.getBlockState(neighborPos).getBlock() instanceof PumpBlock) { + PipeEnd pumpEnd = AbstractPipeBlockEntity.getPipeEnd(level, neighborPos, Direction.UP); + if (pumpEnd != null) { + AbstractPipeBlockEntity.moveFluidWithHeightCheck( + level, + pos, + Direction.UP, + pumpEnd.pos(), + pumpEnd.direction(), + pumpEnd.effectiveHeight() + ); + } + } else { + AbstractPipeBlockEntity.moveFluidWithHeightCheck( + level, + pos, + Direction.UP, + pos.relative(Direction.UP), + Direction.DOWN, + 0 + ); + } } - // END + DOWN:向下方排液 + // END + DOWN:向下方排液(若端头指向泵则透传追踪) if (value.equals(PipeBlock.NodePipe.END) && direction.equals(Direction.DOWN)) { - AbstractPipeBlockEntity.moveFluidWithHeightCheck( - level, pos.relative(Direction.DOWN), Direction.UP, pos, Direction.DOWN); + BlockPos neighborPos = pos.relative(Direction.DOWN); + if (level.getBlockState(neighborPos).getBlock() instanceof PumpBlock) { + PipeEnd pumpEnd = AbstractPipeBlockEntity.getPipeEnd(level, neighborPos, Direction.DOWN); + if (pumpEnd != null) { + AbstractPipeBlockEntity.moveFluidWithHeightCheck( + level, + pos.relative(Direction.DOWN), + Direction.UP, + pumpEnd.pos(), + pumpEnd.direction(), + pumpEnd.effectiveHeight() + ); + } + } else { + AbstractPipeBlockEntity.moveFluidWithHeightCheck( + level, + pos.relative(Direction.DOWN), + Direction.UP, + pos, + Direction.DOWN, + 0 + ); + } } if (!value.equals(PipeBlock.NodePipe.PIPE)) { @@ -148,7 +184,7 @@ public static void tick(Level level, BlockPos pos, BlockState state) { if (pipeEnd == null) { continue; } - pipeEnds.add(new EndAndDirection(pipeEnd, direction)); + pipeEnds.add(new EndAndDirection(pipeEnd, direction, pipeEnd.effectiveHeight())); } if (pipeEnds.isEmpty()) { @@ -162,7 +198,8 @@ public static void tick(Level level, BlockPos pos, BlockState state) { pos.relative(endAndDirection.direction()), endAndDirection.direction().getOpposite(), endAndDirection.end().pos(), - endAndDirection.end().direction() + endAndDirection.end().direction(), + endAndDirection.effectiveHeight() ); } } @@ -170,6 +207,6 @@ public static void tick(Level level, BlockPos pos, BlockState state) { /** * PipeEnd + 方向对 */ - record EndAndDirection(PipeEnd end, Direction direction) { + record EndAndDirection(PipeEnd end, Direction direction, int effectiveHeight) { } } From 1829ad4c951796d1ea14f9cf5ee8404f99315d3a Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 20:37:08 +0800 Subject: [PATCH 17/27] =?UTF-8?q?refactor(fluid):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B3=B5=E5=9D=97=E7=9B=B8=E5=85=B3=E7=B1=BB=E7=9A=84=E5=8C=85?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E5=B9=B6=E4=BC=98=E5=8C=96=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E6=B8=B2=E6=9F=93=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 PumpBlock 从 dev.dubhe.anvilcraft.block 移至 dev.dubhe.anvilcraft.block.fluid - 将 PumpBlockEntity 从 dev.dubhe.anvilcraft.block.entity 移至 dev.dubhe.anvilcraft.block.entity.fluid - 更新 AbstractPipeBlockEntity、PipeBlockEntity、PipeNodeBlockEntity 中的导入路径 - 更新 ModBlocks 和 ModBlockEntities 中的导入路径以匹配新的包结构 - 在 PipeBlockEntity 中提前声明 effectiveHeight 变量避免重复定义 - 优化 PumpBlockEntity 的客户端渲染逻辑,直接设置 working 状态 --- .../block/entity/fluid/AbstractPipeBlockEntity.java | 3 +-- .../block/entity/fluid/PipeBlockEntity.java | 8 +++++--- .../block/entity/fluid/PipeNodeBlockEntity.java | 2 +- .../block/entity/{ => fluid}/PumpBlockEntity.java | 12 ++++++++---- .../anvilcraft/block/{ => fluid}/PumpBlock.java | 7 ++----- .../blockentity/PumpBlockEntityRenderer.java | 4 ++-- .../anvilcraft/init/block/ModBlockEntities.java | 2 +- .../dev/dubhe/anvilcraft/init/block/ModBlocks.java | 2 +- 8 files changed, 21 insertions(+), 19 deletions(-) rename src/main/java/dev/dubhe/anvilcraft/block/entity/{ => fluid}/PumpBlockEntity.java (96%) rename src/main/java/dev/dubhe/anvilcraft/block/{ => fluid}/PumpBlock.java (97%) 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 472f84d890..2b05156a61 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 @@ -1,7 +1,6 @@ package dev.dubhe.anvilcraft.block.entity.fluid; -import dev.dubhe.anvilcraft.block.PumpBlock; -import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.fluid.PipeBlock; import dev.dubhe.anvilcraft.block.fluid.PipeCornerBlock; import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock; 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 e1cd1d083a..db4a2d820f 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 @@ -1,6 +1,6 @@ package dev.dubhe.anvilcraft.block.entity.fluid; -import dev.dubhe.anvilcraft.block.PumpBlock; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.fluid.PipeBlock; import dev.dubhe.anvilcraft.block.fluid.PipeCornerBlock; import dev.dubhe.anvilcraft.block.fluid.PipeStraightBlock; @@ -108,6 +108,7 @@ public static void tick(Level level, BlockPos pos, BlockState state) { Direction sourceCurDir = posDir; BlockPos targetCurPos = pos; Direction targetCurDir = negDir; + int effectiveHeight = 0; BlockPos sourceNeighbor = pos.relative(posDir); if (level.getBlockState(sourceNeighbor).getBlock() instanceof PumpBlock) { @@ -115,11 +116,11 @@ public static void tick(Level level, BlockPos pos, BlockState state) { if (pumpEnd != null) { sourceCurPos = pumpEnd.pos(); sourceCurDir = pumpEnd.direction().getOpposite(); + effectiveHeight = pumpEnd.effectiveHeight(); } } BlockPos targetNeighbor = pos.relative(negDir); - int effectiveHeight = 0; if (level.getBlockState(targetNeighbor).getBlock() instanceof PumpBlock) { PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, negDir); if (pumpEnd != null) { @@ -147,6 +148,7 @@ public static void tick(Level level, BlockPos pos, BlockState state) { Direction sourceCurDir = firstDir; BlockPos targetCurPos = pos; Direction targetCurDir = secondDir; + int effectiveHeight = 0; BlockPos sourceNeighbor = pos.relative(firstDir); if (level.getBlockState(sourceNeighbor).getBlock() instanceof PumpBlock) { @@ -154,11 +156,11 @@ public static void tick(Level level, BlockPos pos, BlockState state) { if (pumpEnd != null) { sourceCurPos = pumpEnd.pos(); sourceCurDir = pumpEnd.direction().getOpposite(); + effectiveHeight = pumpEnd.effectiveHeight(); } } BlockPos targetNeighbor = pos.relative(secondDir); - int effectiveHeight = 0; if (level.getBlockState(targetNeighbor).getBlock() instanceof PumpBlock) { PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, secondDir); if (pumpEnd != null) { 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 db9ed8c70f..abffa7a7bc 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 @@ -1,7 +1,7 @@ package dev.dubhe.anvilcraft.block.entity.fluid; import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; -import dev.dubhe.anvilcraft.block.PumpBlock; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.fluid.PipeBlock; import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock; import lombok.Getter; diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java similarity index 96% rename from src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java rename to src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java index faae7422d3..d6b8364655 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java @@ -1,10 +1,9 @@ -package dev.dubhe.anvilcraft.block.entity; +package dev.dubhe.anvilcraft.block.entity.fluid; import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; import dev.dubhe.anvilcraft.api.power.IPowerConsumer; import dev.dubhe.anvilcraft.api.power.PowerGrid; -import dev.dubhe.anvilcraft.block.PumpBlock; -import dev.dubhe.anvilcraft.block.entity.fluid.AbstractPipeBlockEntity; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.state.Orientation; import lombok.Getter; import lombok.Setter; @@ -221,7 +220,12 @@ public CompoundTag getUpdateTag(HolderLookup.Provider registries) { * */ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEntity entity) { - if (level.isClientSide) return; + if (level.isClientSide()) { + boolean powered = state.getValue(PumpBlock.POWERED); + boolean overload = state.getValue(PumpBlock.OVERLOAD); + entity.working = !powered && !overload; + return; + } // 刷新电网过载状态到 blockstate entity.flushState(level, pos); diff --git a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java similarity index 97% rename from src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java rename to src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java index a9046e8cad..68251e7750 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java @@ -1,14 +1,11 @@ -package dev.dubhe.anvilcraft.block; +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.PumpBlockEntity; -import dev.dubhe.anvilcraft.block.fluid.PipeBlock; -import dev.dubhe.anvilcraft.block.fluid.PipeNodeBlock; -import dev.dubhe.anvilcraft.block.fluid.PipeStraightBlock; +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; diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index 3dfbdfb45f..e623319dad 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -3,8 +3,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import dev.dubhe.anvilcraft.AnvilCraft; -import dev.dubhe.anvilcraft.block.PumpBlock; -import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; +import dev.dubhe.anvilcraft.block.entity.fluid.PumpBlockEntity; import dev.dubhe.anvilcraft.block.state.Orientation; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java index bcd58fc6a0..6c40998c6a 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java @@ -48,7 +48,7 @@ import dev.dubhe.anvilcraft.block.entity.PowerConverterBlockEntity; import dev.dubhe.anvilcraft.block.entity.PropelPistonBlockEntity; import dev.dubhe.anvilcraft.block.entity.PulseGeneratorBlockEntity; -import dev.dubhe.anvilcraft.block.entity.PumpBlockEntity; +import dev.dubhe.anvilcraft.block.entity.fluid.PumpBlockEntity; import dev.dubhe.anvilcraft.block.entity.RedStoneComputerBlockEntity; import dev.dubhe.anvilcraft.block.entity.RemoteTransmissionPoleBlockEntity; import dev.dubhe.anvilcraft.block.entity.ResentfulAmberBlockEntity; diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index dede754b4a..82c92453a2 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -105,7 +105,7 @@ import dev.dubhe.anvilcraft.block.PowerConverterSmallBlock; import dev.dubhe.anvilcraft.block.PropelPiston; import dev.dubhe.anvilcraft.block.PulseGeneratorBlock; -import dev.dubhe.anvilcraft.block.PumpBlock; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.RedstoneComputerBlock; import dev.dubhe.anvilcraft.block.ReinforcedConcreteBlock; import dev.dubhe.anvilcraft.block.RemoteTransmissionPoleBlock; From 38aeaa56e327777ec6f8e0c940028bd56c3c30ec Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 20:39:27 +0800 Subject: [PATCH 18/27] =?UTF-8?q?refactor(fluid):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B5=81=E4=BD=93=E7=AE=A1=E9=81=93=E7=B3=BB=E7=BB=9F=E7=9A=84?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E9=A1=BA=E5=BA=8F=E5=92=8C=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整 AbstractPipeBlockEntity 中 PumpBlock 的导入位置 - 重新排序 ModBlockEntities 中 PumpBlockEntity 的导入顺序 - 重新组织 ModBlocks 中 PumpBlock 的导入并优化注解格式 - 调整 PipeBlockEntity 和 PipeNodeBlockEntity 中 PumpBlock 的导入顺序 - 优化 PumpBlockEntityRenderer 中的常量文档注释格式 - 重构 CelestialForgingAnvilBlock 的战利品表生成代码结构 --- .../entity/fluid/AbstractPipeBlockEntity.java | 2 +- .../block/entity/fluid/PipeBlockEntity.java | 2 +- .../entity/fluid/PipeNodeBlockEntity.java | 2 +- .../blockentity/PumpBlockEntityRenderer.java | 10 +++++++--- .../init/block/ModBlockEntities.java | 2 +- .../anvilcraft/init/block/ModBlocks.java | 19 +++++++++++-------- 6 files changed, 22 insertions(+), 15 deletions(-) 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 2b05156a61..5cfbaa9449 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 @@ -1,10 +1,10 @@ package dev.dubhe.anvilcraft.block.entity.fluid; -import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.fluid.PipeBlock; 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; 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 db4a2d820f..04b4ac49e0 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 @@ -1,9 +1,9 @@ package dev.dubhe.anvilcraft.block.entity.fluid; -import dev.dubhe.anvilcraft.block.fluid.PumpBlock; 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; 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 abffa7a7bc..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 @@ -1,9 +1,9 @@ package dev.dubhe.anvilcraft.block.entity.fluid; import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; -import dev.dubhe.anvilcraft.block.fluid.PumpBlock; 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; diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index e623319dad..2d8e57fee8 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -3,8 +3,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import dev.dubhe.anvilcraft.AnvilCraft; -import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.entity.fluid.PumpBlockEntity; +import dev.dubhe.anvilcraft.block.fluid.PumpBlock; import dev.dubhe.anvilcraft.block.state.Orientation; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; @@ -30,10 +30,14 @@ public class PumpBlockEntityRenderer implements BlockEntityRenderer { // Generate empty loot table (rolls=0) so datagen doesn't break. // Actual drop (with NBT) is handled manually in onRemove. - tables.add(block, LootTable.lootTable() - .withPool(LootPool.lootPool() - .setRolls(ConstantValue.exactly(0.0f)))); + tables.add( + block, + LootTable.lootTable().withPool(LootPool.lootPool().setRolls(ConstantValue.exactly(0.0f))) + ); }) .tag((BlockTags.MINEABLE_WITH_PICKAXE), BlockTags.WITHER_IMMUNE, BlockTags.DRAGON_IMMUNE, ModBlockTags.COLLISION_IMMUNE) .item(CelestialForgingAnvilBlockItem::new) From 4ad54675ae72599349f44641242165b411840b30 Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 21:00:49 +0800 Subject: [PATCH 19/27] =?UTF-8?q?fix(pipe):=20=E4=BF=AE=E5=A4=8D=E6=B3=B5?= =?UTF-8?q?=E5=9D=97=E5=AE=9E=E4=BD=93=E7=AE=A1=E9=81=93=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=8C=85=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复泵输出方向判断逻辑,使用相反方向进行匹配检查 - 合并泵状态检查条件以简化代码流程 - 添加网络数据包同步功能到泵块实体 - 实现 getUpdatePacket 方法以支持客户端同步 --- .../block/entity/fluid/AbstractPipeBlockEntity.java | 10 ++++------ .../anvilcraft/block/entity/fluid/PumpBlockEntity.java | 9 +++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) 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 5cfbaa9449..2bd7becfb5 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 @@ -94,12 +94,10 @@ protected void sendNeighbourUpdate() { return getPipeCornerEnd(level, blockPos, blockState, direction, accumulatedHeight); } if (blockState.getBlock() instanceof PumpBlock) { - Direction pumpOutputDir = blockState.getValue(PumpBlock.ORIENTATION).getDirection(); - if (direction == pumpOutputDir) { - if (level.getBlockEntity(blockPos) instanceof PumpBlockEntity pumpBe && pumpBe.canPump()) { - // 泵可工作且方向匹配 → 等效距离 +10 并继续追踪 - return getPumpPipeEnd(level, blockPos, direction, accumulatedHeight); - } + Direction pumpOutputDir = blockState.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); + if (direction == pumpOutputDir && level.getBlockEntity(blockPos) instanceof PumpBlockEntity pumpBe && pumpBe.canPump()) { + // 泵可工作且方向匹配 → 等效距离 +10 并继续追踪 + return getPumpPipeEnd(level, blockPos, direction, accumulatedHeight); } // 方向不匹配或泵不能工作 → 清空等效距离并返回 return null; diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java index d6b8364655..d112f3917b 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java @@ -11,6 +11,9 @@ import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -209,6 +212,12 @@ public CompoundTag getUpdateTag(HolderLookup.Provider registries) { return tag; } + @Nullable + @Override + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + // ---- Tick ---- /** From 71e349d0da0010b5a223d1ca97b76a7006c0aa49 Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 21:10:25 +0800 Subject: [PATCH 20/27] =?UTF-8?q?fix(pipe):=20=E4=BF=AE=E5=A4=8D=E6=B3=B5?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E7=AB=AF=E6=96=B9=E5=90=91=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修正了相邻流体处理器时泵输出端的方向计算 - 将方向参数从原始方向改为相反方向以确保正确流向 - 解决了泵无法正确向相邻流体处理器排液的问题 --- .../anvilcraft/block/entity/fluid/AbstractPipeBlockEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2bd7becfb5..2ea9188261 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 @@ -224,7 +224,7 @@ protected void sendNeighbourUpdate() { // 若相邻是流体处理器,泵输出端直接对其排液 if (PipeBlock.isFluidHandler(level, nextPos)) { - return new PipeEnd(pumpPos, direction, accumulatedHeight + PumpBlockEntity.PUMP_HEADLIFT); + return new PipeEnd(pumpPos, direction.getOpposite(), accumulatedHeight + PumpBlockEntity.PUMP_HEADLIFT); } return null; From 4a0e8a70253d9817aebdfc02fba3acfc6972e2ae Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 21:14:56 +0800 Subject: [PATCH 21/27] =?UTF-8?q?refactor(fluid):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=B3=B5=E6=96=B9=E5=9D=97=E5=AE=9E=E4=BD=93=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E6=B5=81=E4=BD=93=E5=A4=84=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 IFluidHandlerHolder 接口实现 - 删除 PumpFluidHandler 内部类及其相关方法 - 移除流体传输相关的逻辑处理代码 - 删除 lastTransferAmount 属性及 NBT 相关操作 - 简化客户端渲染器中的动画速度计算 - 移除流体传输相关的 tick 处理逻辑 --- .../block/entity/fluid/PumpBlockEntity.java | 167 +----------------- .../blockentity/PumpBlockEntityRenderer.java | 6 +- 2 files changed, 4 insertions(+), 169 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java index d112f3917b..c7c700d808 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java @@ -1,14 +1,11 @@ package dev.dubhe.anvilcraft.block.entity.fluid; -import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; import dev.dubhe.anvilcraft.api.power.IPowerConsumer; import dev.dubhe.anvilcraft.api.power.PowerGrid; import dev.dubhe.anvilcraft.block.fluid.PumpBlock; -import dev.dubhe.anvilcraft.block.state.Orientation; import lombok.Getter; import lombok.Setter; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.Packet; @@ -17,9 +14,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.neoforged.neoforge.capabilities.Capabilities; -import net.neoforged.neoforge.fluids.FluidStack; -import net.neoforged.neoforge.fluids.capability.IFluidHandler; import javax.annotation.Nullable; @@ -38,20 +32,13 @@ */ @Getter @Setter -public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerConsumer, IFluidHandlerHolder { - +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; - /** - * 上 tick 实际传输的流体量(mB),用于客户端活塞动画速度 - */ - @Getter - private int lastTransferAmount; - /** * 重入防护:防止 IFluidHandler relay 时无限递归 */ @@ -80,25 +67,6 @@ public BlockPos getPos() { return getBlockPos(); } - // ---- IFluidHandlerHolder ---- - - @Override - public IFluidHandler getFluidHandler() { - return new PumpFluidHandler(); - } - - /** - * 获取相邻方块在指定侧面的 IFluidHandler。 - * - * @param side 泵朝向该邻居的方向 - */ - @Nullable - private IFluidHandler getNeighborFluidHandler(Direction side) { - if (level == null) return null; - BlockPos neighborPos = getBlockPos().relative(side); - return level.getCapability(Capabilities.FluidHandler.BLOCK, neighborPos, side.getOpposite()); - } - /** * 泵是否能实际泵送流体(启用 + 电网有电) */ @@ -106,109 +74,24 @@ public boolean canPump() { return working && grid != null && grid.isWorking(); } - /** - * 泵的无缓存流体处理器。 - *

    - *
  • 能泵送时:drain 从输入端邻居抽取,fill 向输出端邻居注入
  • - *
  • 关闭/过载/无电:容量为 0,阻塞所有流体
  • - *
- */ - private class PumpFluidHandler implements IFluidHandler { - - @Override - public int getTanks() { - return 1; - } - - @Override - public FluidStack getFluidInTank(int tank) { - return FluidStack.EMPTY; - } - - @Override - public int getTankCapacity(int tank) { - if (!canPump()) return 0; - return PUMP_HEADLIFT * 50; // 500 mB/tick = 10m × 50 mB/tick/m - } - - @Override - public boolean isFluidValid(int tank, FluidStack stack) { - return canPump(); - } - - @Override - public int fill(FluidStack resource, FluidAction action) { - if (!canPump() || transferring) return 0; - BlockState state = getBlockState(); - if (!(state.getBlock() instanceof PumpBlock)) return 0; - Direction outputDir = state.getValue(PumpBlock.ORIENTATION).getDirection(); - IFluidHandler output = getNeighborFluidHandler(outputDir); - if (output == null) return 0; - - transferring = true; - try { - return output.fill(resource, action); - } finally { - transferring = false; - } - } - - @Override - public FluidStack drain(FluidStack resource, FluidAction action) { - if (!canPump() || transferring) return FluidStack.EMPTY; - BlockState state = getBlockState(); - if (!(state.getBlock() instanceof PumpBlock)) return FluidStack.EMPTY; - Direction inputDir = state.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); - IFluidHandler input = getNeighborFluidHandler(inputDir); - if (input == null) return FluidStack.EMPTY; - - transferring = true; - try { - return input.drain(resource, action); - } finally { - transferring = false; - } - } - - @Override - public FluidStack drain(int maxDrain, FluidAction action) { - if (!canPump() || transferring) return FluidStack.EMPTY; - BlockState state = getBlockState(); - if (!(state.getBlock() instanceof PumpBlock)) return FluidStack.EMPTY; - Direction inputDir = state.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); - IFluidHandler input = getNeighborFluidHandler(inputDir); - if (input == null) return FluidStack.EMPTY; - - transferring = true; - try { - return input.drain(maxDrain, action); - } finally { - transferring = false; - } - } - } - // ---- NBT ---- @Override protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.saveAdditional(tag, registries); tag.putBoolean("Working", working); - tag.putInt("LastTransferAmount", lastTransferAmount); } @Override public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); working = tag.getBoolean("Working"); - lastTransferAmount = tag.getInt("LastTransferAmount"); } @Override public CompoundTag getUpdateTag(HolderLookup.Provider registries) { CompoundTag tag = super.getUpdateTag(registries); tag.putBoolean("Working", working); - tag.putInt("LastTransferAmount", lastTransferAmount); return tag; } @@ -230,9 +113,6 @@ public Packet getUpdatePacket() { */ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEntity entity) { if (level.isClientSide()) { - boolean powered = state.getValue(PumpBlock.POWERED); - boolean overload = state.getValue(PumpBlock.OVERLOAD); - entity.working = !powered && !overload; return; } @@ -250,50 +130,9 @@ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEn if (entity.working != wasWorking) { entity.setChanged(); - if (!level.isClientSide()) entity.sendUpdate(); - } - - // 电网是否能提供足够功率 - boolean gridPowered = entity.grid != null && entity.grid.isWorking(); - - // 实际泵送需要启用状态 + 电网供电 - boolean canPump = entity.working && gridPowered; - - // 主动流体中转:从输入端抽取流体,注入输出端 - int transferred = 0; - if (canPump && !entity.transferring) { - Orientation orientation = updatedState.getValue(PumpBlock.ORIENTATION); - Direction outputDir = orientation.getDirection(); - Direction inputDir = outputDir.getOpposite(); - - IFluidHandler inputHandler = entity.getNeighborFluidHandler(inputDir); - IFluidHandler outputHandler = entity.getNeighborFluidHandler(outputDir); - - if (inputHandler != null && outputHandler != null) { - int maxTransfer = PUMP_HEADLIFT * 50; // 500 mB/tick - entity.transferring = true; - try { - FluidStack drained = inputHandler.drain(maxTransfer, IFluidHandler.FluidAction.SIMULATE); - if (!drained.isEmpty()) { - int filled = outputHandler.fill(drained, IFluidHandler.FluidAction.SIMULATE); - if (filled > 0) { - FluidStack toMove = drained.copyWithAmount(filled); - inputHandler.drain(toMove, IFluidHandler.FluidAction.EXECUTE); - outputHandler.fill(toMove, IFluidHandler.FluidAction.EXECUTE); - transferred = filled; - } - } - } finally { - entity.transferring = false; - } + if (!level.isClientSide()) { + entity.sendUpdate(); } } - - // 同步传输量到客户端(用于活塞动画速度) - if (entity.lastTransferAmount != transferred) { - entity.lastTransferAmount = transferred; - entity.setChanged(); - if (!level.isClientSide()) entity.sendUpdate(); - } } } diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index 2d8e57fee8..6d278c1f06 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -57,11 +57,7 @@ public void render( BlockState state = blockEntity.getBlockState(); if (!(state.getBlock() instanceof PumpBlock)) return; - - // 动画速度与传输量正相关 - float speed = blockEntity.getLastTransferAmount() / MAX_TRANSFER_RATE; - if (speed < 0.05f) speed = 1.0f; - + float speed = 1.0f; long gameTime = blockEntity.getLevel().getGameTime(); float cycle = ((gameTime + partialTick) * speed) % 20.0f / 20.0f; From c11f25929598347421560a966d1ef2e4948e3853 Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 22:06:51 +0800 Subject: [PATCH 22/27] =?UTF-8?q?fix(pipe):=20=E4=BF=AE=E5=A4=8D=E6=B3=B5?= =?UTF-8?q?=E7=9A=84=E6=B5=81=E4=BD=93=E4=BC=A0=E8=BE=93=E6=96=B9=E5=90=91?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修正泵的方向判断逻辑,移除不必要的反向操作 - 更新泵端位置计算,确保正确的流体传输路径 - 移除泵块实体的能力注册以避免冲突 - 优化泵的工作状态检查逻辑 - 添加完整的流体传输实现,包括高度检测和管道连接处理 --- .../entity/fluid/AbstractPipeBlockEntity.java | 4 +-- .../block/entity/fluid/PumpBlockEntity.java | 32 ++++++++++++++++++- .../event/CapabilitiesEventListener.java | 3 +- 3 files changed, 34 insertions(+), 5 deletions(-) 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 2ea9188261..634364594e 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 @@ -94,7 +94,7 @@ protected void sendNeighbourUpdate() { return getPipeCornerEnd(level, blockPos, blockState, direction, accumulatedHeight); } if (blockState.getBlock() instanceof PumpBlock) { - Direction pumpOutputDir = blockState.getValue(PumpBlock.ORIENTATION).getDirection().getOpposite(); + Direction pumpOutputDir = blockState.getValue(PumpBlock.ORIENTATION).getDirection(); if (direction == pumpOutputDir && level.getBlockEntity(blockPos) instanceof PumpBlockEntity pumpBe && pumpBe.canPump()) { // 泵可工作且方向匹配 → 等效距离 +10 并继续追踪 return getPumpPipeEnd(level, blockPos, direction, accumulatedHeight); @@ -207,7 +207,7 @@ protected void sendNeighbourUpdate() { * @return PipeEnd,不可达时返回 null */ private static @Nullable PipeEnd getPumpPipeEnd(Level level, BlockPos pumpPos, Direction direction, int accumulatedHeight) { - BlockPos nextPos = pumpPos.relative(direction); + BlockPos nextPos = pumpPos.relative(direction.getOpposite()); if (!level.isLoaded(nextPos)) return null; BlockState nextState = level.getBlockState(nextPos); diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java index c7c700d808..c9de0c5f4a 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java @@ -2,10 +2,13 @@ import dev.dubhe.anvilcraft.api.power.IPowerConsumer; import dev.dubhe.anvilcraft.api.power.PowerGrid; +import dev.dubhe.anvilcraft.block.fluid.PipeBlock; import dev.dubhe.anvilcraft.block.fluid.PumpBlock; +import dev.dubhe.anvilcraft.block.state.Orientation; import lombok.Getter; import lombok.Setter; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.Packet; @@ -14,6 +17,8 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; import javax.annotation.Nullable; @@ -71,7 +76,7 @@ public BlockPos getPos() { * 泵是否能实际泵送流体(启用 + 电网有电) */ public boolean canPump() { - return working && grid != null && grid.isWorking(); + return this.working && this.grid != null && this.grid.isWorking(); } // ---- NBT ---- @@ -134,5 +139,30 @@ public static void tick(Level level, BlockPos pos, BlockState state, PumpBlockEn 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/event/CapabilitiesEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java index 470be2818a..72db4c3b73 100644 --- a/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java @@ -71,8 +71,7 @@ public static void registerCapabilities(final RegisterCapabilitiesEvent event) { ModBlockEntities.FLUID_TANK.get(), ModBlockEntities.LARGE_FLUID_TANK.get(), ModBlockEntities.CREATIVE_FLUID_TANK.get(), - ModBlockEntities.PIPE_NODE.get(), - ModBlockEntities.PUMP.get() + ModBlockEntities.PIPE_NODE.get() ).forEach(type -> event.registerBlockEntity( Capabilities.FluidHandler.BLOCK, type, From 945c749036c4915d36f4c5d1938f7d549235a640 Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 22:55:29 +0800 Subject: [PATCH 23/27] =?UTF-8?q?fix(pipe):=20=E4=BF=AE=E5=A4=8D=E7=AE=A1?= =?UTF-8?q?=E9=81=93=E7=AB=AF=E7=82=B9=E6=96=B9=E5=90=91=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修正了泵连接时的方向参数传递错误 - 调整了管道追踪中相反方向的计算方式 - 统一了流体传输中的方向处理逻辑 - 修复了管道系统中高度累积的计算问题 - 优化了管道端点查找的递归调用参数 - 解决了泵连接检测中的方向反转错误 --- .../block/entity/fluid/AbstractPipeBlockEntity.java | 4 ++-- .../anvilcraft/block/entity/fluid/PipeBlockEntity.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) 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 634364594e..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 @@ -144,7 +144,7 @@ protected void sendNeighbourUpdate() { // 检查端头指向的方块是否是泵,若是则继续追踪 BlockPos neighborPos = blockPos.relative(targetDir); if (level.getBlockState(neighborPos).getBlock() instanceof PumpBlock) { - return getPipeEnd(level, neighborPos, targetDir, accumulatedHeight); + return getPipeEnd(level, neighborPos, direction, accumulatedHeight); } return new PipeEnd(blockPos, targetDir, accumulatedHeight); } @@ -185,7 +185,7 @@ protected void sendNeighbourUpdate() { // 检查端头指向的方块是否是泵,若是则继续追踪 BlockPos neighborPos = blockPos.relative(targetDir); if (level.getBlockState(neighborPos).getBlock() instanceof PumpBlock) { - return getPipeEnd(level, neighborPos, targetDir, accumulatedHeight); + return getPipeEnd(level, neighborPos, targetDir.getOpposite(), accumulatedHeight); } return new PipeEnd(blockPos, targetDir, accumulatedHeight); } 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 04b4ac49e0..2ca740a285 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 @@ -115,7 +115,7 @@ public static void tick(Level level, BlockPos pos, BlockState state) { PipeEnd pumpEnd = getPipeEnd(level, sourceNeighbor, posDir); if (pumpEnd != null) { sourceCurPos = pumpEnd.pos(); - sourceCurDir = pumpEnd.direction().getOpposite(); + sourceCurDir = pumpEnd.direction(); effectiveHeight = pumpEnd.effectiveHeight(); } } @@ -125,7 +125,7 @@ public static void tick(Level level, BlockPos pos, BlockState state) { PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, negDir); if (pumpEnd != null) { targetCurPos = pumpEnd.pos(); - targetCurDir = pumpEnd.direction().getOpposite(); + targetCurDir = pumpEnd.direction(); effectiveHeight = pumpEnd.effectiveHeight(); } } @@ -155,7 +155,7 @@ public static void tick(Level level, BlockPos pos, BlockState state) { PipeEnd pumpEnd = getPipeEnd(level, sourceNeighbor, firstDir); if (pumpEnd != null) { sourceCurPos = pumpEnd.pos(); - sourceCurDir = pumpEnd.direction().getOpposite(); + sourceCurDir = pumpEnd.direction(); effectiveHeight = pumpEnd.effectiveHeight(); } } @@ -165,7 +165,7 @@ public static void tick(Level level, BlockPos pos, BlockState state) { PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, secondDir); if (pumpEnd != null) { targetCurPos = pumpEnd.pos(); - targetCurDir = pumpEnd.direction().getOpposite(); + targetCurDir = pumpEnd.direction(); effectiveHeight = pumpEnd.effectiveHeight(); } } From ff2c56c9811d0b9becc0660b63895b573401b647 Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 23:04:47 +0800 Subject: [PATCH 24/27] =?UTF-8?q?refactor(pipe):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=AE=A1=E9=81=93=E6=B5=81=E4=BD=93=E4=BC=A0=E8=BE=93=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E4=BB=A5=E6=8F=90=E9=AB=98=E4=BB=A3=E7=A0=81=E5=8F=AF?= =?UTF-8?q?=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除重复的流体传输代码并提取为独立方法 tickEndCount2 - 简化主逻辑中的条件判断和变量声明 - 优化泵连接检查的处理流程 - 统一不同管道类型的流体传输调用方式 - 提高代码复用性和维护性 --- .../block/entity/fluid/PipeBlockEntity.java | 102 ++++++------------ 1 file changed, 34 insertions(+), 68 deletions(-) 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 2ca740a285..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 @@ -104,80 +104,16 @@ public static void tick(Level level, BlockPos pos, BlockState state) { Direction negDir = PipeBlock.getDirectionFromAxis(axis, Direction.AxisDirection.NEGATIVE); // 检查端头指向的方块是否是泵,若是则透传追踪 - BlockPos sourceCurPos = pos; - Direction sourceCurDir = posDir; - BlockPos targetCurPos = pos; - Direction targetCurDir = negDir; - int effectiveHeight = 0; - - BlockPos sourceNeighbor = pos.relative(posDir); - if (level.getBlockState(sourceNeighbor).getBlock() instanceof PumpBlock) { - PipeEnd pumpEnd = getPipeEnd(level, sourceNeighbor, posDir); - if (pumpEnd != null) { - sourceCurPos = pumpEnd.pos(); - sourceCurDir = pumpEnd.direction(); - effectiveHeight = pumpEnd.effectiveHeight(); - } - } - - BlockPos targetNeighbor = pos.relative(negDir); - if (level.getBlockState(targetNeighbor).getBlock() instanceof PumpBlock) { - PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, negDir); - if (pumpEnd != null) { - targetCurPos = pumpEnd.pos(); - targetCurDir = pumpEnd.direction(); - effectiveHeight = pumpEnd.effectiveHeight(); - } - } - - AbstractPipeBlockEntity.moveFluidWithHeightCheck( - level, - sourceCurPos, - sourceCurDir, - targetCurPos, - targetCurDir, - effectiveHeight - ); + tickEndCount2(level, pos, posDir, negDir); + tickEndCount2(level, pos, negDir, posDir); } else { // 弯管两端端头 PipeBlock.CornerEnded cornerEnded = state.getValue(PipeCornerBlock.CORNER_ENDED); Direction firstDir = cornerEnded.getFirstDirection(); Direction secondDir = cornerEnded.getSecondDirection(); - BlockPos sourceCurPos = pos; - Direction sourceCurDir = firstDir; - BlockPos targetCurPos = pos; - Direction targetCurDir = secondDir; - int effectiveHeight = 0; - - BlockPos sourceNeighbor = pos.relative(firstDir); - if (level.getBlockState(sourceNeighbor).getBlock() instanceof PumpBlock) { - PipeEnd pumpEnd = getPipeEnd(level, sourceNeighbor, firstDir); - if (pumpEnd != null) { - sourceCurPos = pumpEnd.pos(); - sourceCurDir = pumpEnd.direction(); - effectiveHeight = pumpEnd.effectiveHeight(); - } - } - - BlockPos targetNeighbor = pos.relative(secondDir); - if (level.getBlockState(targetNeighbor).getBlock() instanceof PumpBlock) { - PipeEnd pumpEnd = getPipeEnd(level, targetNeighbor, secondDir); - if (pumpEnd != null) { - targetCurPos = pumpEnd.pos(); - targetCurDir = pumpEnd.direction(); - effectiveHeight = pumpEnd.effectiveHeight(); - } - } - - AbstractPipeBlockEntity.moveFluidWithHeightCheck( - level, - sourceCurPos, - sourceCurDir, - targetCurPos, - targetCurDir, - effectiveHeight - ); + tickEndCount2(level, pos, firstDir, secondDir); + tickEndCount2(level, pos, secondDir, firstDir); } return; } @@ -213,4 +149,34 @@ public static void tick(Level level, BlockPos pos, BlockState state) { 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 + ); + } } From bb65886cf7c7505dfcd1aafb330c0ebb2ce9f7eb Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 23:06:45 +0800 Subject: [PATCH 25/27] =?UTF-8?q?refactor(power):=20=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=9D=97=E8=A1=A8=E8=BE=BE=E5=BC=8F=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 @SuppressWarnings 注解中的冗余大括号和换行 - 将多行注解数组改为单行紧凑格式 - 保持了原有的 unused 和 CodeBlock2Expr 检查忽略功能 --- .../java/dev/dubhe/anvilcraft/init/block/ModBlocks.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index 71129374a8..524a9276ac 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -278,12 +278,7 @@ import static dev.dubhe.anvilcraft.api.power.IPowerComponent.OVERLOAD; import static dev.dubhe.anvilcraft.api.power.IPowerComponent.SWITCH; -@SuppressWarnings( - { - "unused", - "CodeBlock2Expr" - } -) +@SuppressWarnings({"unused", "CodeBlock2Expr"}) public class ModBlocks { static { REGISTRUM.defaultCreativeTab(ModItemGroups.ANVILCRAFT_FUNCTION_BLOCK.getKey()); From 8f526a577797232227568e3bdde529f4b8b20f56 Mon Sep 17 00:00:00 2001 From: Gugle Date: Mon, 22 Jun 2026 23:53:16 +0800 Subject: [PATCH 26/27] =?UTF-8?q?fix(pipe):=20=E4=BF=AE=E5=A4=8D=E7=AE=A1?= =?UTF-8?q?=E9=81=93=E4=B8=8E=E6=B3=B5=E7=9A=84=E8=BF=9E=E6=8E=A5=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=92=8C=E6=A8=A1=E5=9E=8B=E6=97=8B=E8=BD=AC=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了 infinite_collector 到碰撞免疫标签中 - 修复了泵在不同朝向下的模型旋转角度问题 - 添加了 SingularityCrystalItem 的导入语句优化 - 优化了 SmartBlockPlacerBlock 的属性获取方式 - 简化了 ConfiguredModel.builder 的引用方式 - 为 PumpBlock 添加了 checkBlockState 方法返回 false - 修复了 PumpBlockEntityRenderer 中 X 轴旋转方向的问题 - 更新了 PipeBlock 的 isFluidHandlerOrPump 方法以支持泵连接 - 修改了管道与泵连接时的连接逻辑判断 - 优化了泵放置时的朝向计算逻辑,支持垂直摆放 - 改进了泵放置后对相邻管道转换为节点的处理逻辑 - 添加了详细的 JavaDoc 注释说明各种情况下的行为 --- .../assets/anvilcraft/blockstates/pump.json | 64 +++++++++---------- .../tags/block/collision_immune.json | 4 +- .../anvilcraft/block/fluid/PipeBlock.java | 16 +++++ .../block/fluid/PipeCornerBlock.java | 5 +- .../anvilcraft/block/fluid/PipeNodeBlock.java | 4 +- .../block/fluid/PipeStraightBlock.java | 6 +- .../anvilcraft/block/fluid/PumpBlock.java | 51 +++++++++++---- .../anvilcraft/block/item/PipeBlockItem.java | 6 +- .../blockentity/PumpBlockEntityRenderer.java | 2 +- .../anvilcraft/init/block/ModBlocks.java | 15 +++-- 10 files changed, 108 insertions(+), 65 deletions(-) diff --git a/src/generated/resources/assets/anvilcraft/blockstates/pump.json b/src/generated/resources/assets/anvilcraft/blockstates/pump.json index 6f36b76afa..1f8fa498b3 100644 --- a/src/generated/resources/assets/anvilcraft/blockstates/pump.json +++ b/src/generated/resources/assets/anvilcraft/blockstates/pump.json @@ -2,78 +2,78 @@ "variants": { "orientation=down_east,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": 90, + "x": -90, "y": -90 }, "orientation=down_east,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": 90, + "x": -90, "y": -90 }, "orientation=down_east,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": 90, + "x": -90, "y": -90 }, "orientation=down_east,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": 90, + "x": -90, "y": -90 }, "orientation=down_north,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": 90, + "x": -90, "y": 180 }, "orientation=down_north,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": 90, + "x": -90, "y": 180 }, "orientation=down_north,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": 90, + "x": -90, "y": 180 }, "orientation=down_north,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": 90, + "x": -90, "y": 180 }, "orientation=down_south,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": 90 + "x": -90 }, "orientation=down_south,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": 90 + "x": -90 }, "orientation=down_south,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": 90 + "x": -90 }, "orientation=down_south,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": 90 + "x": -90 }, "orientation=down_west,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": 90, + "x": -90, "y": 90 }, "orientation=down_west,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": 90, + "x": -90, "y": 90 }, "orientation=down_west,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": 90, + "x": -90, "y": 90 }, "orientation=down_west,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": 90, + "x": -90, "y": 90 }, "orientation=east_up,overload=false,powered=false": { @@ -122,78 +122,78 @@ }, "orientation=up_east,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": -90, + "x": 90, "y": -90 }, "orientation=up_east,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": -90, + "x": 90, "y": -90 }, "orientation=up_east,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": -90, + "x": 90, "y": -90 }, "orientation=up_east,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": -90, + "x": 90, "y": -90 }, "orientation=up_north,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": -90, + "x": 90, "y": 180 }, "orientation=up_north,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": -90, + "x": 90, "y": 180 }, "orientation=up_north,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": -90, + "x": 90, "y": 180 }, "orientation=up_north,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": -90, + "x": 90, "y": 180 }, "orientation=up_south,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": -90 + "x": 90 }, "orientation=up_south,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": -90 + "x": 90 }, "orientation=up_south,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": -90 + "x": 90 }, "orientation=up_south,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": -90 + "x": 90 }, "orientation=up_west,overload=false,powered=false": { "model": "anvilcraft:block/pump_base", - "x": -90, + "x": 90, "y": 90 }, "orientation=up_west,overload=false,powered=true": { "model": "anvilcraft:block/pump_off", - "x": -90, + "x": 90, "y": 90 }, "orientation=up_west,overload=true,powered=false": { "model": "anvilcraft:block/pump_overload", - "x": -90, + "x": 90, "y": 90 }, "orientation=up_west,overload=true,powered=true": { "model": "anvilcraft:block/pump_overload", - "x": -90, + "x": 90, "y": 90 }, "orientation=west_up,overload=false,powered=false": { 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/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( * 评估指定方向邻居的连接状态。 *
    *
  • 邻居是管道且对准本节点 → {@link NodePipe#PIPE}
  • - *
  • 邻居是 IFluidHandler → {@link NodePipe#END}
  • + *
  • 邻居是 IFluidHandler 或 PumpBlock → {@link NodePipe#END}
  • *
  • 其他 → {@link NodePipe#NONE}
  • *
* @@ -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 index 68251e7750..4aaf74b7c8 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/fluid/PumpBlock.java @@ -93,7 +93,11 @@ protected MapCodec codec() { } /** - * 放置时根据玩家视线和 Shift 计算朝向。默认输出端朝向目标方块,Shift 反向(输出端指向玩家) + * 放置时根据玩家视线和 Shift 计算朝向。 + *
    + *
  • 水平摆放:默认输出端朝向目标方块,Shift 反向(输出端指向玩家)
  • + *
  • 垂直摆放:默认输出端朝向上方/下方,Shift 反转垂直方向(UP ↔ DOWN)
  • + *
*/ @Override @Nullable @@ -103,8 +107,17 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { Player player = context.getPlayer(); boolean shiftDown = player != null && player.isShiftKeyDown(); - // 默认输出端朝向目标方块;按住 Shift 反向(输出端指向玩家) - if (!shiftDown) horizontalDir = horizontalDir.getOpposite(); + 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) { @@ -131,7 +144,7 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { } /** - * 放置后将侧面连接的直管转为三通节点 + * 放置后将侧面连接的直管/弯管转为三通节点,使其能正确吸附管道。 */ @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { @@ -145,26 +158,31 @@ public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable L Direction.Axis pipeAxis = neighborState.getValue(PipeBlock.AXIS); // 泵贴在直管侧面 → 将直管转为三通节点 if (dir.getAxis() != pipeAxis) { - convertPipeToNode(level, neighborPos, neighborState, dir.getOpposite()); + 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, Direction newDirection) { - Direction.Axis axis = state.getValue(PipeBlock.AXIS); - Direction startDir = Direction.get(Direction.AxisDirection.NEGATIVE, axis); - Direction endDir = Direction.get(Direction.AxisDirection.POSITIVE, axis); - + private void convertPipeToNode(Level level, BlockPos pos, BlockState state) { BlockState nodeState = ModBlocks.PIPE_NODE.get() .defaultBlockState() .setValue(PipeBlock.WATERLOGGED, state.getValue(PipeBlock.WATERLOGGED)); - nodeState = nodeState.setValue(PipeBlock.getPropertyForDirection(startDir), PipeNodeBlock.evaluateNeighbor(level, pos, startDir)); - nodeState = nodeState.setValue(PipeBlock.getPropertyForDirection(endDir), PipeNodeBlock.evaluateNeighbor(level, pos, endDir)); - nodeState = nodeState.setValue(PipeBlock.getPropertyForDirection(newDirection), PipeBlock.NodePipe.PIPE); + for (Direction dir : Direction.values()) { + nodeState = nodeState.setValue( + PipeBlock.getPropertyForDirection(dir), + PipeNodeBlock.evaluateNeighbor(level, pos, dir) + ); + } level.setBlockAndUpdate(pos, nodeState); } @@ -211,4 +229,9 @@ public BlockEntityTicker getTicker(Level level, Block if (level.isClientSide()) return null; return BaseEntityBlock.createTickerHelper(type, ModBlockEntities.PUMP.get(), PumpBlockEntity::tick); } + + @Override + public boolean checkBlockState(BlockState blockState) { + return false; + } } diff --git a/src/main/java/dev/dubhe/anvilcraft/block/item/PipeBlockItem.java b/src/main/java/dev/dubhe/anvilcraft/block/item/PipeBlockItem.java index 3fcd14c374..ccdff70db9 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/item/PipeBlockItem.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/item/PipeBlockItem.java @@ -87,9 +87,9 @@ private boolean tryConnectAdjacent(BlockPlaceContext context) { BlockState placeState = level.getBlockState(placePos); boolean targetIsPipe = targetState.getBlock() instanceof PipeBlock; - boolean targetIsFluid = PipeBlock.isFluidHandler(level, targetPos); + boolean targetIsFluid = PipeBlock.isFluidHandlerOrPump(level, targetPos); boolean placeIsPipe = placeState.getBlock() instanceof PipeBlock; - boolean placeIsFluid = PipeBlock.isFluidHandler(level, placePos); + boolean placeIsFluid = PipeBlock.isFluidHandlerOrPump(level, placePos); // 双方至少有一方是管道/IFluidHandler 且另一方也是 if ((!targetIsPipe && !targetIsFluid) || (!placeIsPipe && !placeIsFluid)) { @@ -375,7 +375,7 @@ protected BlockState getPlacementState(BlockPlaceContext context) { boolean shiftDown = player != null && player.isShiftKeyDown(); boolean clickedOnPipe = targetBlock instanceof PipeBlock; - boolean clickedOnFluidHandler = PipeBlock.isFluidHandler(level, targetPos); + boolean clickedOnFluidHandler = PipeBlock.isFluidHandlerOrPump(level, targetPos); // 视线模式 if (shiftDown || (!clickedOnPipe && !clickedOnFluidHandler)) { diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java index 6d278c1f06..3ef41ef0d5 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/PumpBlockEntityRenderer.java @@ -68,7 +68,7 @@ public void render( // blockstate Y+ 方向与 JOML 相反,需取反 // 顺序:先 X 后 Y(mulPose 后乘,先 Y 则 X 对向量先生效) poseStack.mulPose(Axis.YP.rotationDegrees(-orientation.getYRotation())); - poseStack.mulPose(Axis.XP.rotationDegrees(-orientation.getXRotation())); + poseStack.mulPose(Axis.XP.rotationDegrees(orientation.getXRotation())); poseStack.translate(-0.5, -0.5, -0.5); poseStack.translate(0, -2.0f / 16.0f, 0); diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java index 524a9276ac..28c4cef950 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -218,6 +218,7 @@ import dev.dubhe.anvilcraft.init.item.ModItemGroups; import dev.dubhe.anvilcraft.init.item.ModItemTags; import dev.dubhe.anvilcraft.init.item.ModItems; +import dev.dubhe.anvilcraft.item.SingularityCrystalItem; import dev.dubhe.anvilcraft.item.TeslaTowerItem; import dev.dubhe.anvilcraft.item.property.component.OverLimitItemContainerContents; import dev.dubhe.anvilcraft.util.DangerUtil; @@ -997,9 +998,9 @@ public class ModBlocks { .blockstate((ctx, provider) -> { provider.getVariantBuilder(ctx.get()).forAllStates(state -> { Direction facing = state.getValue(HorizontalDirectionalBlock.FACING); - boolean upsideDown = state.getValue(dev.dubhe.anvilcraft.block.SmartBlockPlacerBlock.UPSIDE_DOWN); - boolean powered = state.getValue(dev.dubhe.anvilcraft.block.SmartBlockPlacerBlock.POWERED); - boolean overload = state.getValue(dev.dubhe.anvilcraft.block.SmartBlockPlacerBlock.OVERLOAD); + boolean upsideDown = state.getValue(SmartBlockPlacerBlock.UPSIDE_DOWN); + boolean powered = state.getValue(SmartBlockPlacerBlock.POWERED); + boolean overload = state.getValue(SmartBlockPlacerBlock.OVERLOAD); // 根据状态选择模型 String modelName; @@ -1025,7 +1026,7 @@ public class ModBlocks { rotation = (rotation + 180) % 360; } - return net.neoforged.neoforge.client.model.generators.ConfiguredModel.builder() + return ConfiguredModel.builder() .modelFile(model) .rotationX(upsideDown ? 180 : 0) .rotationY(rotation) @@ -3875,7 +3876,7 @@ private static BlockEntry registerCementLiquidBlock(Color color) { .strength(50F, 1200.0F) .requiresCorrectToolForDrops()) .tag(BlockTags.MINEABLE_WITH_PICKAXE, ModBlockTags.NEEDS_TRANSCENDIUM_TOOL, ModBlockTags.COLLISION_IMMUNE) - .item(dev.dubhe.anvilcraft.item.SingularityCrystalItem::new) + .item(SingularityCrystalItem::new) .initialProperties(() -> new Item.Properties().fireResistant().stacksTo(1)) .tag(ModItemTags.EXPLOSION_PROOF) .build() @@ -4224,9 +4225,9 @@ private static BlockEntry registerCementLiquidBlock(Color color) { var model = provider.models().getExistingFile(AnvilCraft.of(modelName)); - return net.neoforged.neoforge.client.model.generators.ConfiguredModel.builder() + return ConfiguredModel.builder() .modelFile(model) - .rotationX((int) orientation.getXRotation()) + .rotationX((int) -orientation.getXRotation()) .rotationY((int) orientation.getYRotation()) .build(); }); From 4eb60b07f448b16d8a2eb9ab3d05daaab888a439 Mon Sep 17 00:00:00 2001 From: Gugle Date: Tue, 23 Jun 2026 00:02:22 +0800 Subject: [PATCH 27/27] =?UTF-8?q?refactor(fluid):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=B3=B5=E5=9D=97=E5=AE=9E=E4=BD=93=E4=B8=AD=E7=9A=84=E9=87=8D?= =?UTF-8?q?=E5=85=A5=E9=98=B2=E6=8A=A4=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 transferring 字段及其相关注释 - 简化了 PumpBlockEntity 的内部状态管理 - 移除了用于防止 IFluidHandler relay 无限递归的保护机制 --- .../dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java index c9de0c5f4a..80c882f404 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/fluid/PumpBlockEntity.java @@ -44,11 +44,6 @@ public class PumpBlockEntity extends AbstractPipeBlockEntity implements IPowerCo private @Nullable PowerGrid grid; private boolean working; - /** - * 重入防护:防止 IFluidHandler relay 时无限递归 - */ - private boolean transferring; - public PumpBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); }