Сделать парту двойным блоком #1

Closed
opened 2025-09-21 22:24:53 +00:00 by grigorevde · 2 comments
grigorevde commented 2025-09-21 22:24:53 +00:00 (Migrated from git.csit.sgu.ru)

Блоки размером в более чем 1x1x1 в майнкрафте работают криво, поэтому парту надо распилить пополам и сделать по аналогии с кроватью/дверью

Блоки размером в более чем 1x1x1 в майнкрафте работают криво, поэтому парту надо распилить пополам и сделать по аналогии с кроватью/дверью
grigorevde commented 2025-09-21 22:24:53 +00:00 (Migrated from git.csit.sgu.ru)

assigned to @danilasar

assigned to `@danilasar`
grigorevde commented 2025-09-21 22:32:15 +00:00 (Migrated from git.csit.sgu.ru)

DeskBlock.java:

public class DeskBlock extends HorizontalFacingBlock {
    public static final EnumProperty<BedPart> PART = Properties.BED_PART;
    
    public DeskBlock(Settings settings) {
        super(settings);
        setDefaultState(getDefaultState()
            .with(FACING, Direction.NORTH)
            .with(PART, BedPart.FOOT)); // FOOT = левая часть
    }
    
    @Override
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
        builder.add(FACING, PART);
    }
    
    @Override
    public BlockState getPlacementState(ItemPlacementContext ctx) {
        Direction direction = ctx.getHorizontalPlayerFacing();
        BlockPos pos = ctx.getBlockPos();
        BlockPos rightPos = pos.offset(direction);
        
        World world = ctx.getWorld();
        
        // можно ли поставить правую часть
        if (world.getBlockState(rightPos).canReplace(ctx) && 
            world.getWorldBorder().contains(rightPos)) {
            return super.getPlacementState(ctx)
                .with(FACING, direction)
                .with(PART, BedPart.FOOT);
        }
        
        return null;
    }
    
    @Override
    public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
        super.onPlaced(world, pos, state, placer, itemStack);
        
        if (!world.isClient) {
            Direction direction = state.get(FACING);
            BlockPos rightPos = pos.offset(direction);
            
            world.setBlockState(rightPos, state.with(PART, BedPart.HEAD), Block.NOTIFY_ALL);
            world.updateNeighbors(pos, Blocks.AIR);
            state.updateNeighbors(world, pos, Block.NOTIFY_ALL);
        }
    }
    
    @Override
    public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
        return VoxelShapes.fullCube();
    }
    
    @Override
    public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
        return VoxelShapes.fullCube();
    }
    
    @Override
    public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, 
                                              BlockState neighborState, WorldAccess world, 
                                              BlockPos pos, BlockPos neighborPos) {
        
        Direction facing = state.get(FACING);
        BedPart part = state.get(PART);
        
        // связанная часть парты
        if (direction == (part == BedPart.FOOT ? facing : facing.getOpposite())) {
            if (!neighborState.isOf(this) || neighborState.get(PART) == part) {
                return Blocks.AIR.getDefaultState();
            }
        }
        
        return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
    }
    
    @Override
    public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
        if (!world.isClient && player.isCreative()) {
            BedPart part = state.get(PART);
            Direction facing = state.get(FACING);
            
            if (part == BedPart.FOOT) {
                BlockPos rightPos = pos.offset(facing);
                BlockState rightState = world.getBlockState(rightPos);
                
                if (rightState.isOf(this) && rightState.get(PART) == BedPart.HEAD) {
                    world.setBlockState(rightPos, Blocks.AIR.getDefaultState(), 
                        Block.NOTIFY_ALL | Block.SKIP_DROPS);
                }
            }
        }
        
        super.onBreak(world, pos, state, player);
    }
    
    @Override
    public long getRenderingSeed(BlockState state, BlockPos pos) {
        // обе части должны иметь одинаковый сид для согласованного рендеринга
        BlockPos leftPos = pos.offset(state.get(FACING), 
            state.get(PART) == BedPart.HEAD ? -1 : 0);
        return MathHelper.hashCode(leftPos.getX(), pos.getY(), leftPos.getZ());
    }
}

blockstate:

{
  "variants": {
    "facing=north,part=foot": {
      "model": "csit:block/desk1_left"
    },
    "facing=north,part=head": {
      "model": "csit:block/desk1_right"
    },
    "facing=east,part=foot": {
      "model": "csit:block/desk1_left",
      "y": 90
    },
    "facing=east,part=head": {
      "model": "csit:block/desk1_right",
      "y": 90
    },
    "facing=south,part=foot": {
      "model": "csit:block/desk1_left",
      "y": 180
    },
    "facing=south,part=head": {
      "model": "csit:block/desk1_right",
      "y": 180
    },
    "facing=west,part=foot": {
      "model": "csit:block/desk1_left",
      "y": 270
    },
    "facing=west,part=head": {
      "model": "csit:block/desk1_right",
      "y": 270
    }
  }
}

loot_table:

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "csit:desk1",
          "conditions": [
            {
              "condition": "minecraft:block_state_property",
              "block": "csit:desk1",
              "properties": {
                "part": "foot"
              }
            }
          ]
        }
      ],
      "conditions": [
        {
          "condition": "minecraft:survives_explosion"
        }
      ]
    }
  ]
}

примерно так

DeskBlock.java: ```java public class DeskBlock extends HorizontalFacingBlock { public static final EnumProperty<BedPart> PART = Properties.BED_PART; public DeskBlock(Settings settings) { super(settings); setDefaultState(getDefaultState() .with(FACING, Direction.NORTH) .with(PART, BedPart.FOOT)); // FOOT = левая часть } @Override protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { builder.add(FACING, PART); } @Override public BlockState getPlacementState(ItemPlacementContext ctx) { Direction direction = ctx.getHorizontalPlayerFacing(); BlockPos pos = ctx.getBlockPos(); BlockPos rightPos = pos.offset(direction); World world = ctx.getWorld(); // можно ли поставить правую часть if (world.getBlockState(rightPos).canReplace(ctx) && world.getWorldBorder().contains(rightPos)) { return super.getPlacementState(ctx) .with(FACING, direction) .with(PART, BedPart.FOOT); } return null; } @Override public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) { super.onPlaced(world, pos, state, placer, itemStack); if (!world.isClient) { Direction direction = state.get(FACING); BlockPos rightPos = pos.offset(direction); world.setBlockState(rightPos, state.with(PART, BedPart.HEAD), Block.NOTIFY_ALL); world.updateNeighbors(pos, Blocks.AIR); state.updateNeighbors(world, pos, Block.NOTIFY_ALL); } } @Override public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return VoxelShapes.fullCube(); } @Override public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return VoxelShapes.fullCube(); } @Override public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { Direction facing = state.get(FACING); BedPart part = state.get(PART); // связанная часть парты if (direction == (part == BedPart.FOOT ? facing : facing.getOpposite())) { if (!neighborState.isOf(this) || neighborState.get(PART) == part) { return Blocks.AIR.getDefaultState(); } } return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos); } @Override public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { if (!world.isClient && player.isCreative()) { BedPart part = state.get(PART); Direction facing = state.get(FACING); if (part == BedPart.FOOT) { BlockPos rightPos = pos.offset(facing); BlockState rightState = world.getBlockState(rightPos); if (rightState.isOf(this) && rightState.get(PART) == BedPart.HEAD) { world.setBlockState(rightPos, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL | Block.SKIP_DROPS); } } } super.onBreak(world, pos, state, player); } @Override public long getRenderingSeed(BlockState state, BlockPos pos) { // обе части должны иметь одинаковый сид для согласованного рендеринга BlockPos leftPos = pos.offset(state.get(FACING), state.get(PART) == BedPart.HEAD ? -1 : 0); return MathHelper.hashCode(leftPos.getX(), pos.getY(), leftPos.getZ()); } } ``` blockstate: ```json { "variants": { "facing=north,part=foot": { "model": "csit:block/desk1_left" }, "facing=north,part=head": { "model": "csit:block/desk1_right" }, "facing=east,part=foot": { "model": "csit:block/desk1_left", "y": 90 }, "facing=east,part=head": { "model": "csit:block/desk1_right", "y": 90 }, "facing=south,part=foot": { "model": "csit:block/desk1_left", "y": 180 }, "facing=south,part=head": { "model": "csit:block/desk1_right", "y": 180 }, "facing=west,part=foot": { "model": "csit:block/desk1_left", "y": 270 }, "facing=west,part=head": { "model": "csit:block/desk1_right", "y": 270 } } } ``` loot_table: ```json { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "csit:desk1", "conditions": [ { "condition": "minecraft:block_state_property", "block": "csit:desk1", "properties": { "part": "foot" } } ] } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ``` примерно так
grigorevde (Migrated from git.csit.sgu.ru) closed this issue 2025-09-22 04:47:21 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
grigorevde/csit#1
No description provided.