218 lines
8.2 KiB
Java
218 lines
8.2 KiB
Java
package net.minecraft.world.level.block;
|
|
|
|
import com.mojang.serialization.MapCodec;
|
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.registries.BuiltInRegistries;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
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.BlockStateProperties;
|
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|
import net.minecraft.world.level.block.state.properties.Property;
|
|
import net.minecraft.world.level.gameevent.GameEvent;
|
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
|
|
public class TripWireBlock extends Block {
|
|
public static final MapCodec<TripWireBlock> CODEC = RecordCodecBuilder.mapCodec(
|
|
instance -> instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("hook").forGetter(tripWireBlock -> tripWireBlock.hook), propertiesCodec())
|
|
.apply(instance, TripWireBlock::new)
|
|
);
|
|
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
|
public static final BooleanProperty ATTACHED = BlockStateProperties.ATTACHED;
|
|
public static final BooleanProperty DISARMED = BlockStateProperties.DISARMED;
|
|
public static final BooleanProperty NORTH = PipeBlock.NORTH;
|
|
public static final BooleanProperty EAST = PipeBlock.EAST;
|
|
public static final BooleanProperty SOUTH = PipeBlock.SOUTH;
|
|
public static final BooleanProperty WEST = PipeBlock.WEST;
|
|
private static final Map<Direction, BooleanProperty> PROPERTY_BY_DIRECTION = CrossCollisionBlock.PROPERTY_BY_DIRECTION;
|
|
protected static final VoxelShape AABB = Block.box(0.0, 1.0, 0.0, 16.0, 2.5, 16.0);
|
|
protected static final VoxelShape NOT_ATTACHED_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0);
|
|
private static final int RECHECK_PERIOD = 10;
|
|
private final Block hook;
|
|
|
|
@Override
|
|
public MapCodec<TripWireBlock> codec() {
|
|
return CODEC;
|
|
}
|
|
|
|
public TripWireBlock(Block hook, BlockBehaviour.Properties properties) {
|
|
super(properties);
|
|
this.registerDefaultState(
|
|
this.stateDefinition
|
|
.any()
|
|
.setValue(POWERED, false)
|
|
.setValue(ATTACHED, false)
|
|
.setValue(DISARMED, false)
|
|
.setValue(NORTH, false)
|
|
.setValue(EAST, false)
|
|
.setValue(SOUTH, false)
|
|
.setValue(WEST, false)
|
|
);
|
|
this.hook = hook;
|
|
}
|
|
|
|
@Override
|
|
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
|
|
return state.getValue(ATTACHED) ? AABB : NOT_ATTACHED_AABB;
|
|
}
|
|
|
|
@Override
|
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
|
BlockGetter blockGetter = context.getLevel();
|
|
BlockPos blockPos = context.getClickedPos();
|
|
return this.defaultBlockState()
|
|
.setValue(NORTH, this.shouldConnectTo(blockGetter.getBlockState(blockPos.north()), Direction.NORTH))
|
|
.setValue(EAST, this.shouldConnectTo(blockGetter.getBlockState(blockPos.east()), Direction.EAST))
|
|
.setValue(SOUTH, this.shouldConnectTo(blockGetter.getBlockState(blockPos.south()), Direction.SOUTH))
|
|
.setValue(WEST, this.shouldConnectTo(blockGetter.getBlockState(blockPos.west()), Direction.WEST));
|
|
}
|
|
|
|
@Override
|
|
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
|
|
return direction.getAxis().isHorizontal()
|
|
? state.setValue((Property)PROPERTY_BY_DIRECTION.get(direction), this.shouldConnectTo(neighborState, direction))
|
|
: super.updateShape(state, direction, neighborState, level, pos, neighborPos);
|
|
}
|
|
|
|
@Override
|
|
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
|
if (!oldState.is(state.getBlock())) {
|
|
this.updateSource(level, pos, state);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
|
if (!movedByPiston && !state.is(newState.getBlock())) {
|
|
this.updateSource(level, pos, state.setValue(POWERED, true));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public BlockState playerWillDestroy(Level level, BlockPos pos, BlockState state, Player player) {
|
|
if (!level.isClientSide && !player.getMainHandItem().isEmpty() && player.getMainHandItem().is(Items.SHEARS)) {
|
|
level.setBlock(pos, state.setValue(DISARMED, true), 4);
|
|
level.gameEvent(player, GameEvent.SHEAR, pos);
|
|
}
|
|
|
|
return super.playerWillDestroy(level, pos, state, player);
|
|
}
|
|
|
|
private void updateSource(Level level, BlockPos pos, BlockState state) {
|
|
for (Direction direction : new Direction[]{Direction.SOUTH, Direction.WEST}) {
|
|
for (int i = 1; i < 42; i++) {
|
|
BlockPos blockPos = pos.relative(direction, i);
|
|
BlockState blockState = level.getBlockState(blockPos);
|
|
if (blockState.is(this.hook)) {
|
|
if (blockState.getValue(TripWireHookBlock.FACING) == direction.getOpposite()) {
|
|
TripWireHookBlock.calculateState(level, blockPos, blockState, false, true, i, state);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!blockState.is(this)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
|
|
if (!level.isClientSide) {
|
|
if (!(Boolean)state.getValue(POWERED)) {
|
|
this.checkPressed(level, pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
|
if ((Boolean)level.getBlockState(pos).getValue(POWERED)) {
|
|
this.checkPressed(level, pos);
|
|
}
|
|
}
|
|
|
|
private void checkPressed(Level level, BlockPos pos) {
|
|
BlockState blockState = level.getBlockState(pos);
|
|
boolean bl = (Boolean)blockState.getValue(POWERED);
|
|
boolean bl2 = false;
|
|
List<? extends Entity> list = level.getEntities(null, blockState.getShape(level, pos).bounds().move(pos));
|
|
if (!list.isEmpty()) {
|
|
for (Entity entity : list) {
|
|
if (!entity.isIgnoringBlockTriggers()) {
|
|
bl2 = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bl2 != bl) {
|
|
blockState = blockState.setValue(POWERED, bl2);
|
|
level.setBlock(pos, blockState, 3);
|
|
this.updateSource(level, pos, blockState);
|
|
}
|
|
|
|
if (bl2) {
|
|
level.scheduleTick(new BlockPos(pos), this, 10);
|
|
}
|
|
}
|
|
|
|
public boolean shouldConnectTo(BlockState state, Direction direction) {
|
|
return state.is(this.hook) ? state.getValue(TripWireHookBlock.FACING) == direction.getOpposite() : state.is(this);
|
|
}
|
|
|
|
@Override
|
|
protected BlockState rotate(BlockState state, Rotation rotation) {
|
|
switch (rotation) {
|
|
case CLOCKWISE_180:
|
|
return state.setValue(NORTH, (Boolean)state.getValue(SOUTH))
|
|
.setValue(EAST, (Boolean)state.getValue(WEST))
|
|
.setValue(SOUTH, (Boolean)state.getValue(NORTH))
|
|
.setValue(WEST, (Boolean)state.getValue(EAST));
|
|
case COUNTERCLOCKWISE_90:
|
|
return state.setValue(NORTH, (Boolean)state.getValue(EAST))
|
|
.setValue(EAST, (Boolean)state.getValue(SOUTH))
|
|
.setValue(SOUTH, (Boolean)state.getValue(WEST))
|
|
.setValue(WEST, (Boolean)state.getValue(NORTH));
|
|
case CLOCKWISE_90:
|
|
return state.setValue(NORTH, (Boolean)state.getValue(WEST))
|
|
.setValue(EAST, (Boolean)state.getValue(NORTH))
|
|
.setValue(SOUTH, (Boolean)state.getValue(EAST))
|
|
.setValue(WEST, (Boolean)state.getValue(SOUTH));
|
|
default:
|
|
return state;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected BlockState mirror(BlockState state, Mirror mirror) {
|
|
switch (mirror) {
|
|
case LEFT_RIGHT:
|
|
return state.setValue(NORTH, (Boolean)state.getValue(SOUTH)).setValue(SOUTH, (Boolean)state.getValue(NORTH));
|
|
case FRONT_BACK:
|
|
return state.setValue(EAST, (Boolean)state.getValue(WEST)).setValue(WEST, (Boolean)state.getValue(EAST));
|
|
default:
|
|
return super.mirror(state, mirror);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
|
builder.add(POWERED, ATTACHED, DISARMED, NORTH, EAST, WEST, SOUTH);
|
|
}
|
|
}
|