MC 1.19.3 Fabric双格高方块交互功能实现求助
解决方案
1. 修复顶部区域交互问题
Minecraft默认方块射线检测仅识别自身坐标Y=0到Y=1范围内的碰撞,要让2格高的顶部区域触发交互,需重写getRaycastShape方法,将射线检测范围设为与碰撞箱一致的2格高:
@Override public VoxelShape getRaycastShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return SHAPE; }
修改后,玩家点击顶部区域时,射线会命中下方的VendingMachineBlock,进而触发onUse方法。你原有代码中的相对Y位置判断逻辑,此时就能正确响应顶部区域的点击。
2. 阻止上方放置方块覆盖
当前canReplace方法仅处理替换现有方块的场景,玩家向空的上方位置放置方块时不会生效。需通过自定义BlockItem拦截放置行为:
步骤1:创建自定义BlockItem
public class VendingMachineBlockItem extends BlockItem { public VendingMachineBlockItem(Block block, Settings settings) { super(block, settings); } @Override public ActionResult place(ItemPlacementContext context) { BlockPos targetPos = context.getBlockPos(); // 拦截在自动售货机正上方的放置操作 if (context.getWorld().getBlockState(targetPos.down()).isOf(getBlock())) { return ActionResult.FAIL; } return super.place(context); } }
步骤2:注册方块时关联自定义BlockItem
在模组注册类中,注册方块时使用自定义的VendingMachineBlockItem:
public static final Block VENDING_MACHINE = registerBlock("vending_machine", new VendingMachineBlock(), new Item.Settings().group(ItemGroup.MISC)); // 注册方法示例 private static Block registerBlock(String name, Block block, Item.Settings settings) { Block registeredBlock = Registry.register(Registry.BLOCK, new Identifier(MOD_ID, name), block); Registry.register(Registry.ITEM, new Identifier(MOD_ID, name), new VendingMachineBlockItem(block, settings)); return registeredBlock; }
3. 完整修改后的VendingMachineBlock代码
public class VendingMachineBlock extends Block { private static final VoxelShape SHAPE = Block.createCuboidShape(0, 0, 0, 16, 32, 16); public VendingMachineBlock() { super(Settings.of(Material.METAL) .nonOpaque() .strength(4.0f) .requiresTool() .sounds(BlockSoundGroup.METAL) ); } @Override public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return SHAPE; } @Override public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return SHAPE; } @Override public VoxelShape getRaycastShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return SHAPE; } @Override public boolean canReplace(BlockState state, ItemPlacementContext context) { BlockPos pos = context.getBlockPos(); if (context.getWorld().getBlockState(pos.down()).isOf(this)) { return false; } return super.canReplace(state, context); } @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { double relativeHitY = hit.getPos().y - pos.getY(); // 覆盖0到2的完整2格范围,处理所有区域的交互 if (relativeHitY >= 0 && relativeHitY <= 2) { if (!world.isClient) { player.sendMessage(Text.of("Hello, world!"), false); // 后续可在此处添加GUI打开逻辑 // player.openHandledScreen(state.createScreenHandlerFactory(world, pos)); } return ActionResult.SUCCESS; } return super.onUse(state, world, pos, player, hand, hit); } }
内容的提问来源于stack exchange,提问作者Captain
相关产品推荐
相关产品推荐

