202 lines
8.6 KiB
Java
202 lines
8.6 KiB
Java
|
package net.minecraft.world.level.block;
|
||
|
|
||
|
import com.mojang.serialization.MapCodec;
|
||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||
|
import com.mojang.serialization.codecs.RecordCodecBuilder.Instance;
|
||
|
import java.util.Map;
|
||
|
import java.util.function.BiConsumer;
|
||
|
import javax.annotation.Nullable;
|
||
|
import net.minecraft.core.BlockPos;
|
||
|
import net.minecraft.core.Direction;
|
||
|
import net.minecraft.server.level.ServerLevel;
|
||
|
import net.minecraft.sounds.SoundSource;
|
||
|
import net.minecraft.util.RandomSource;
|
||
|
import net.minecraft.world.InteractionResult;
|
||
|
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.Explosion;
|
||
|
import net.minecraft.world.level.Level;
|
||
|
import net.minecraft.world.level.LevelReader;
|
||
|
import net.minecraft.world.level.ScheduledTickAccess;
|
||
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||
|
import net.minecraft.world.level.block.state.BlockState;
|
||
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||
|
import net.minecraft.world.level.block.state.properties.BlockSetType;
|
||
|
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.Half;
|
||
|
import net.minecraft.world.level.gameevent.GameEvent;
|
||
|
import net.minecraft.world.level.material.FluidState;
|
||
|
import net.minecraft.world.level.material.Fluids;
|
||
|
import net.minecraft.world.level.pathfinder.PathComputationType;
|
||
|
import net.minecraft.world.level.redstone.Orientation;
|
||
|
import net.minecraft.world.phys.BlockHitResult;
|
||
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
||
|
import net.minecraft.world.phys.shapes.Shapes;
|
||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||
|
|
||
|
public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock {
|
||
|
public static final MapCodec<TrapDoorBlock> CODEC = RecordCodecBuilder.mapCodec(
|
||
|
p_360458_ -> p_360458_.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter(p_311609_ -> p_311609_.type), propertiesCodec())
|
||
|
.apply(p_360458_, TrapDoorBlock::new)
|
||
|
);
|
||
|
public static final BooleanProperty OPEN = BlockStateProperties.OPEN;
|
||
|
public static final EnumProperty<Half> HALF = BlockStateProperties.HALF;
|
||
|
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||
|
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
||
|
private static final Map<Direction, VoxelShape> SHAPES = Shapes.rotateAll(Block.boxZ(16.0, 13.0, 16.0));
|
||
|
private final BlockSetType type;
|
||
|
|
||
|
@Override
|
||
|
public MapCodec<? extends TrapDoorBlock> codec() {
|
||
|
return CODEC;
|
||
|
}
|
||
|
|
||
|
protected TrapDoorBlock(BlockSetType p_272964_, BlockBehaviour.Properties p_273079_) {
|
||
|
super(p_273079_.sound(p_272964_.soundType()));
|
||
|
this.type = p_272964_;
|
||
|
this.registerDefaultState(
|
||
|
this.stateDefinition
|
||
|
.any()
|
||
|
.setValue(FACING, Direction.NORTH)
|
||
|
.setValue(OPEN, false)
|
||
|
.setValue(HALF, Half.BOTTOM)
|
||
|
.setValue(POWERED, false)
|
||
|
.setValue(WATERLOGGED, false)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected VoxelShape getShape(BlockState p_57563_, BlockGetter p_57564_, BlockPos p_57565_, CollisionContext p_57566_) {
|
||
|
return SHAPES.get(
|
||
|
p_57563_.getValue(OPEN) ? p_57563_.getValue(FACING) : (p_57563_.getValue(HALF) == Half.TOP ? Direction.DOWN : Direction.UP)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected boolean isPathfindable(BlockState p_57535_, PathComputationType p_57538_) {
|
||
|
switch (p_57538_) {
|
||
|
case LAND:
|
||
|
return p_57535_.getValue(OPEN);
|
||
|
case WATER:
|
||
|
return p_57535_.getValue(WATERLOGGED);
|
||
|
case AIR:
|
||
|
return p_57535_.getValue(OPEN);
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected InteractionResult useWithoutItem(BlockState p_57540_, Level p_57541_, BlockPos p_57542_, Player p_57543_, BlockHitResult p_57545_) {
|
||
|
if (!this.type.canOpenByHand()) {
|
||
|
return InteractionResult.PASS;
|
||
|
} else {
|
||
|
this.toggle(p_57540_, p_57541_, p_57542_, p_57543_);
|
||
|
return InteractionResult.SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void onExplosionHit(BlockState p_312876_, ServerLevel p_365086_, BlockPos p_312697_, Explosion p_312889_, BiConsumer<ItemStack, BlockPos> p_312223_) {
|
||
|
if (p_312889_.canTriggerBlocks() && this.type.canOpenByWindCharge() && !p_312876_.getValue(POWERED)) {
|
||
|
this.toggle(p_312876_, p_365086_, p_312697_, null);
|
||
|
}
|
||
|
|
||
|
super.onExplosionHit(p_312876_, p_365086_, p_312697_, p_312889_, p_312223_);
|
||
|
}
|
||
|
|
||
|
private void toggle(BlockState p_311901_, Level p_312039_, BlockPos p_310194_, @Nullable Player p_312003_) {
|
||
|
BlockState blockstate = p_311901_.cycle(OPEN);
|
||
|
p_312039_.setBlock(p_310194_, blockstate, 2);
|
||
|
if (blockstate.getValue(WATERLOGGED)) {
|
||
|
p_312039_.scheduleTick(p_310194_, Fluids.WATER, Fluids.WATER.getTickDelay(p_312039_));
|
||
|
}
|
||
|
|
||
|
this.playSound(p_312003_, p_312039_, p_310194_, blockstate.getValue(OPEN));
|
||
|
}
|
||
|
|
||
|
protected void playSound(@Nullable Player p_57528_, Level p_57529_, BlockPos p_57530_, boolean p_57531_) {
|
||
|
p_57529_.playSound(
|
||
|
p_57528_,
|
||
|
p_57530_,
|
||
|
p_57531_ ? this.type.trapdoorOpen() : this.type.trapdoorClose(),
|
||
|
SoundSource.BLOCKS,
|
||
|
1.0F,
|
||
|
p_57529_.getRandom().nextFloat() * 0.1F + 0.9F
|
||
|
);
|
||
|
p_57529_.gameEvent(p_57528_, p_57531_ ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, p_57530_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void neighborChanged(BlockState p_57547_, Level p_57548_, BlockPos p_57549_, Block p_57550_, @Nullable Orientation p_363180_, boolean p_57552_) {
|
||
|
if (!p_57548_.isClientSide) {
|
||
|
boolean flag = p_57548_.hasNeighborSignal(p_57549_);
|
||
|
if (flag != p_57547_.getValue(POWERED)) {
|
||
|
if (p_57547_.getValue(OPEN) != flag) {
|
||
|
p_57547_ = p_57547_.setValue(OPEN, flag);
|
||
|
this.playSound(null, p_57548_, p_57549_, flag);
|
||
|
}
|
||
|
|
||
|
p_57548_.setBlock(p_57549_, p_57547_.setValue(POWERED, flag), 2);
|
||
|
if (p_57547_.getValue(WATERLOGGED)) {
|
||
|
p_57548_.scheduleTick(p_57549_, Fluids.WATER, Fluids.WATER.getTickDelay(p_57548_));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public BlockState getStateForPlacement(BlockPlaceContext p_57533_) {
|
||
|
BlockState blockstate = this.defaultBlockState();
|
||
|
FluidState fluidstate = p_57533_.getLevel().getFluidState(p_57533_.getClickedPos());
|
||
|
Direction direction = p_57533_.getClickedFace();
|
||
|
if (!p_57533_.replacingClickedOnBlock() && direction.getAxis().isHorizontal()) {
|
||
|
blockstate = blockstate.setValue(FACING, direction)
|
||
|
.setValue(HALF, p_57533_.getClickLocation().y - p_57533_.getClickedPos().getY() > 0.5 ? Half.TOP : Half.BOTTOM);
|
||
|
} else {
|
||
|
blockstate = blockstate.setValue(FACING, p_57533_.getHorizontalDirection().getOpposite()).setValue(HALF, direction == Direction.UP ? Half.BOTTOM : Half.TOP);
|
||
|
}
|
||
|
|
||
|
if (p_57533_.getLevel().hasNeighborSignal(p_57533_.getClickedPos())) {
|
||
|
blockstate = blockstate.setValue(OPEN, true).setValue(POWERED, true);
|
||
|
}
|
||
|
|
||
|
return blockstate.setValue(WATERLOGGED, fluidstate.getType() == Fluids.WATER);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_57561_) {
|
||
|
p_57561_.add(FACING, OPEN, HALF, POWERED, WATERLOGGED);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected FluidState getFluidState(BlockState p_57568_) {
|
||
|
return p_57568_.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(p_57568_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected BlockState updateShape(
|
||
|
BlockState p_57554_,
|
||
|
LevelReader p_365791_,
|
||
|
ScheduledTickAccess p_368436_,
|
||
|
BlockPos p_57558_,
|
||
|
Direction p_57555_,
|
||
|
BlockPos p_57559_,
|
||
|
BlockState p_57556_,
|
||
|
RandomSource p_367698_
|
||
|
) {
|
||
|
if (p_57554_.getValue(WATERLOGGED)) {
|
||
|
p_368436_.scheduleTick(p_57558_, Fluids.WATER, Fluids.WATER.getTickDelay(p_365791_));
|
||
|
}
|
||
|
|
||
|
return super.updateShape(p_57554_, p_365791_, p_368436_, p_57558_, p_57555_, p_57559_, p_57556_, p_367698_);
|
||
|
}
|
||
|
|
||
|
protected BlockSetType getType() {
|
||
|
return this.type;
|
||
|
}
|
||
|
}
|