minecraft-source/src/net/minecraft/world/level/block/BedBlock.java

345 lines
16 KiB
Java

package net.minecraft.world.level.block;
import net.minecraft.world.level.block.state.AbstractStateHolder;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BedBlockEntity;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.material.PushReaction;
import java.util.Optional;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.phys.Vec3;
import java.util.List;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import javax.annotation.Nullable;
import net.minecraft.core.Direction;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.BedPart;
import net.minecraft.world.level.block.state.properties.EnumProperty;
public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock {
public static final EnumProperty<BedPart> PART;
public static final BooleanProperty OCCUPIED;
protected static final VoxelShape BASE;
protected static final VoxelShape LEG_NORTH_WEST;
protected static final VoxelShape LEG_SOUTH_WEST;
protected static final VoxelShape LEG_NORTH_EAST;
protected static final VoxelShape LEG_SOUTH_EAST;
protected static final VoxelShape NORTH_SHAPE;
protected static final VoxelShape SOUTH_SHAPE;
protected static final VoxelShape WEST_SHAPE;
protected static final VoxelShape EAST_SHAPE;
private final DyeColor color;
public BedBlock(final DyeColor bdg, final Properties c) {
super(c);
this.color = bdg;
this.registerDefaultState((((AbstractStateHolder<O, BlockState>)this.stateDefinition.any()).setValue(BedBlock.PART, BedPart.FOOT)).<Comparable, Boolean>setValue((Property<Comparable>)BedBlock.OCCUPIED, false));
}
@Override
public MaterialColor getMapColor(final BlockState byg, final BlockGetter bjd, final BlockPos fk) {
if (byg.<BedPart>getValue(BedBlock.PART) == BedPart.FOOT) {
return this.color.getMaterialColor();
}
return MaterialColor.WOOL;
}
@Nullable
public static Direction getBedOrientation(final BlockGetter bjd, final BlockPos fk) {
final BlockState byg3 = bjd.getBlockState(fk);
return (byg3.getBlock() instanceof BedBlock) ? byg3.<Direction>getValue((Property<Direction>)BedBlock.FACING) : null;
}
@Override
public InteractionResult use(BlockState byg, final Level bjt, BlockPos fk, final Player ayg, final InteractionHand ajh, final BlockHitResult cvd) {
if (bjt.isClientSide) {
return InteractionResult.CONSUME;
}
if (byg.<BedPart>getValue(BedBlock.PART) != BedPart.HEAD) {
fk = fk.relative(byg.<Direction>getValue((Property<Direction>)BedBlock.FACING));
byg = bjt.getBlockState(fk);
if (byg.getBlock() != this) {
return InteractionResult.CONSUME;
}
}
if (!bjt.dimension.mayRespawn() || bjt.getBiome(fk) == Biomes.NETHER) {
bjt.removeBlock(fk, false);
final BlockPos fk2 = fk.relative(byg.<Direction>getValue((Property<Direction>)BedBlock.FACING).getOpposite());
if (bjt.getBlockState(fk2).getBlock() == this) {
bjt.removeBlock(fk2, false);
}
bjt.explode(null, DamageSource.netherBedExplosion(), fk.getX() + 0.5, fk.getY() + 0.5, fk.getZ() + 0.5, 5.0f, true, Explosion.BlockInteraction.DESTROY);
return InteractionResult.SUCCESS;
}
if (byg.<Boolean>getValue((Property<Boolean>)BedBlock.OCCUPIED)) {
if (!this.kickVillagerOutOfBed(bjt, fk)) {
ayg.displayClientMessage(new TranslatableComponent("block.minecraft.bed.occupied", new Object[0]), true);
}
return InteractionResult.SUCCESS;
}
ayg.startSleepInBed(fk).ifLeft(a -> {
if (a != null) {
ayg.displayClientMessage(a.getMessage(), true);
}
return;
});
return InteractionResult.SUCCESS;
}
private boolean kickVillagerOutOfBed(final Level bjt, final BlockPos fk) {
final List<Villager> list4 = bjt.<Villager>getEntitiesOfClass(Villager.class, new AABB(fk), LivingEntity::isSleeping);
if (list4.isEmpty()) {
return false;
}
list4.get(0).stopSleeping();
return true;
}
@Override
public void fallOn(final Level bjt, final BlockPos fk, final Entity akn, final float float4) {
super.fallOn(bjt, fk, akn, float4 * 0.5f);
}
@Override
public void updateEntityAfterFallOn(final BlockGetter bjd, final Entity akn) {
if (akn.isSuppressingBounce()) {
super.updateEntityAfterFallOn(bjd, akn);
}
else {
this.bounceUp(akn);
}
}
private void bounceUp(final Entity akn) {
final Vec3 cvi3 = akn.getDeltaMovement();
if (cvi3.y < 0.0) {
final double double4 = (akn instanceof LivingEntity) ? 1.0 : 0.8;
akn.setDeltaMovement(cvi3.x, -cvi3.y * 0.6600000262260437 * double4, cvi3.z);
}
}
@Override
public BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6) {
if (fp != getNeighbourDirection(byg1.<BedPart>getValue(BedBlock.PART), byg1.<Direction>getValue((Property<Direction>)BedBlock.FACING))) {
return super.updateShape(byg1, fp, byg3, bju, fk5, fk6);
}
if (byg3.getBlock() == this && byg3.<BedPart>getValue(BedBlock.PART) != byg1.<BedPart>getValue(BedBlock.PART)) {
return ((AbstractStateHolder<O, BlockState>)byg1).<Comparable, Comparable>setValue((Property<Comparable>)BedBlock.OCCUPIED, (Comparable)byg3.<V>getValue((Property<V>)BedBlock.OCCUPIED));
}
return Blocks.AIR.defaultBlockState();
}
private static Direction getNeighbourDirection(final BedPart byv, final Direction fp) {
return (byv == BedPart.FOOT) ? fp : fp.getOpposite();
}
@Override
public void playerDestroy(final Level bjt, final Player ayg, final BlockPos fk, final BlockState byg, @Nullable final BlockEntity bwi, final ItemStack bek) {
super.playerDestroy(bjt, ayg, fk, Blocks.AIR.defaultBlockState(), bwi, bek);
}
@Override
public void playerWillDestroy(final Level bjt, final BlockPos fk, final BlockState byg, final Player ayg) {
final BedPart byv6 = byg.<BedPart>getValue(BedBlock.PART);
final BlockPos fk2 = fk.relative(getNeighbourDirection(byv6, byg.<Direction>getValue((Property<Direction>)BedBlock.FACING)));
final BlockState byg2 = bjt.getBlockState(fk2);
if (byg2.getBlock() == this && byg2.<BedPart>getValue(BedBlock.PART) != byv6) {
bjt.setBlock(fk2, Blocks.AIR.defaultBlockState(), 35);
bjt.levelEvent(ayg, 2001, fk2, Block.getId(byg2));
if (!bjt.isClientSide && !ayg.isCreative()) {
final ItemStack bek9 = ayg.getMainHandItem();
Block.dropResources(byg, bjt, fk, null, ayg, bek9);
Block.dropResources(byg2, bjt, fk2, null, ayg, bek9);
}
ayg.awardStat(Stats.BLOCK_MINED.get(this));
}
super.playerWillDestroy(bjt, fk, byg, ayg);
}
@Nullable
@Override
public BlockState getStateForPlacement(final BlockPlaceContext bcn) {
final Direction fp3 = bcn.getHorizontalDirection();
final BlockPos fk4 = bcn.getClickedPos();
final BlockPos fk5 = fk4.relative(fp3);
if (bcn.getLevel().getBlockState(fk5).canBeReplaced(bcn)) {
return ((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)BedBlock.FACING, fp3);
}
return null;
}
@Override
public VoxelShape getShape(final BlockState byg, final BlockGetter bjd, final BlockPos fk, final CollisionContext cvn) {
final Direction fp6 = getConnectedDirection(byg).getOpposite();
switch (fp6) {
case NORTH: {
return BedBlock.NORTH_SHAPE;
}
case SOUTH: {
return BedBlock.SOUTH_SHAPE;
}
case WEST: {
return BedBlock.WEST_SHAPE;
}
default: {
return BedBlock.EAST_SHAPE;
}
}
}
public static Direction getConnectedDirection(final BlockState byg) {
final Direction fp2 = byg.<Direction>getValue((Property<Direction>)BedBlock.FACING);
return (byg.<BedPart>getValue(BedBlock.PART) == BedPart.HEAD) ? fp2.getOpposite() : fp2;
}
public static DoubleBlockCombiner.BlockType getBlockType(final BlockState byg) {
final BedPart byv2 = byg.<BedPart>getValue(BedBlock.PART);
if (byv2 == BedPart.HEAD) {
return DoubleBlockCombiner.BlockType.FIRST;
}
return DoubleBlockCombiner.BlockType.SECOND;
}
public static Optional<Vec3> findStandUpPosition(final EntityType<?> akr, final LevelReader bjw, final BlockPos fk, int integer) {
final Direction fp5 = bjw.getBlockState(fk).<Direction>getValue((Property<Direction>)BedBlock.FACING);
final int integer2 = fk.getX();
final int integer3 = fk.getY();
final int integer4 = fk.getZ();
for (int integer5 = 0; integer5 <= 1; ++integer5) {
final int integer6 = integer2 - fp5.getStepX() * integer5 - 1;
final int integer7 = integer4 - fp5.getStepZ() * integer5 - 1;
final int integer8 = integer6 + 2;
final int integer9 = integer7 + 2;
for (int integer10 = integer6; integer10 <= integer8; ++integer10) {
for (int integer11 = integer7; integer11 <= integer9; ++integer11) {
final BlockPos fk2 = new BlockPos(integer10, integer3, integer11);
final Optional<Vec3> optional17 = getStandingLocationAtOrBelow(akr, bjw, fk2);
if (optional17.isPresent()) {
if (integer <= 0) {
return optional17;
}
--integer;
}
}
}
}
return Optional.<Vec3>empty();
}
protected static Optional<Vec3> getStandingLocationAtOrBelow(final EntityType<?> akr, final LevelReader bjw, final BlockPos fk) {
final VoxelShape cwc4 = bjw.getBlockState(fk).getCollisionShape(bjw, fk);
if (cwc4.max(Direction.Axis.Y) > 0.4375) {
return Optional.<Vec3>empty();
}
final BlockPos.MutableBlockPos a5 = new BlockPos.MutableBlockPos(fk);
while (a5.getY() >= 0 && fk.getY() - a5.getY() <= 2 && bjw.getBlockState(a5).getCollisionShape(bjw, a5).isEmpty()) {
a5.move(Direction.DOWN);
}
final VoxelShape cwc5 = bjw.getBlockState(a5).getCollisionShape(bjw, a5);
if (cwc5.isEmpty()) {
return Optional.<Vec3>empty();
}
final double double7 = a5.getY() + cwc5.max(Direction.Axis.Y) + 2.0E-7;
if (fk.getY() - double7 > 2.0) {
return Optional.<Vec3>empty();
}
final float float9 = akr.getWidth() / 2.0f;
final Vec3 cvi10 = new Vec3(a5.getX() + 0.5, double7, a5.getZ() + 0.5);
if (bjw.noCollision(new AABB(cvi10.x - float9, cvi10.y, cvi10.z - float9, cvi10.x + float9, cvi10.y + akr.getHeight(), cvi10.z + float9))) {
return Optional.<Vec3>of(cvi10);
}
return Optional.<Vec3>empty();
}
@Override
public PushReaction getPistonPushReaction(final BlockState byg) {
return PushReaction.DESTROY;
}
@Override
public RenderShape getRenderShape(final BlockState byg) {
return RenderShape.ENTITYBLOCK_ANIMATED;
}
@Override
protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
a.add(BedBlock.FACING, BedBlock.PART, BedBlock.OCCUPIED);
}
@Override
public BlockEntity newBlockEntity(final BlockGetter bjd) {
return new BedBlockEntity(this.color);
}
@Override
public void setPlacedBy(final Level bjt, final BlockPos fk, final BlockState byg, @Nullable final LivingEntity akw, final ItemStack bek) {
super.setPlacedBy(bjt, fk, byg, akw, bek);
if (!bjt.isClientSide) {
final BlockPos fk2 = fk.relative(byg.<Direction>getValue((Property<Direction>)BedBlock.FACING));
bjt.setBlock(fk2, ((AbstractStateHolder<O, BlockState>)byg).<BedPart, BedPart>setValue(BedBlock.PART, BedPart.HEAD), 3);
bjt.blockUpdated(fk, Blocks.AIR);
byg.updateNeighbourShapes(bjt, fk, 3);
}
}
public DyeColor getColor() {
return this.color;
}
@Override
public long getSeed(final BlockState byg, final BlockPos fk) {
final BlockPos fk2 = fk.relative((Direction)byg.<Direction>getValue((Property<Direction>)BedBlock.FACING), (int)((byg.<BedPart>getValue(BedBlock.PART) != BedPart.HEAD) ? 1 : 0));
return Mth.getSeed(fk2.getX(), fk.getY(), fk2.getZ());
}
@Override
public boolean isPathfindable(final BlockState byg, final BlockGetter bjd, final BlockPos fk, final PathComputationType cqo) {
return false;
}
static {
PART = BlockStateProperties.BED_PART;
OCCUPIED = BlockStateProperties.OCCUPIED;
BASE = Block.box(0.0, 3.0, 0.0, 16.0, 9.0, 16.0);
LEG_NORTH_WEST = Block.box(0.0, 0.0, 0.0, 3.0, 3.0, 3.0);
LEG_SOUTH_WEST = Block.box(0.0, 0.0, 13.0, 3.0, 3.0, 16.0);
LEG_NORTH_EAST = Block.box(13.0, 0.0, 0.0, 16.0, 3.0, 3.0);
LEG_SOUTH_EAST = Block.box(13.0, 0.0, 13.0, 16.0, 3.0, 16.0);
NORTH_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_NORTH_WEST, BedBlock.LEG_NORTH_EAST);
SOUTH_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_SOUTH_WEST, BedBlock.LEG_SOUTH_EAST);
WEST_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_NORTH_WEST, BedBlock.LEG_SOUTH_WEST);
EAST_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_NORTH_EAST, BedBlock.LEG_SOUTH_EAST);
}
}