218 lines
9.6 KiB
Java
218 lines
9.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.List;
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
import java.util.function.Consumer;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.stats.Stats;
|
|
import net.minecraft.world.Containers;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.item.ItemEntity;
|
|
import net.minecraft.world.entity.monster.Shulker;
|
|
import net.minecraft.world.entity.monster.piglin.PiglinAi;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
|
import net.minecraft.world.item.DyeColor;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
|
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
|
|
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.EnumProperty;
|
|
import net.minecraft.world.level.storage.loot.LootParams;
|
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
|
import net.minecraft.world.phys.AABB;
|
|
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 ShulkerBoxBlock extends BaseEntityBlock {
|
|
public static final MapCodec<ShulkerBoxBlock> CODEC = RecordCodecBuilder.mapCodec(
|
|
p_360450_ -> p_360450_.group(DyeColor.CODEC.optionalFieldOf("color").forGetter(p_309293_ -> Optional.ofNullable(p_309293_.color)), propertiesCodec())
|
|
.apply(p_360450_, (p_309290_, p_309291_) -> new ShulkerBoxBlock(p_309290_.orElse(null), p_309291_))
|
|
);
|
|
public static final Map<Direction, VoxelShape> SHAPES_OPEN_SUPPORT = Shapes.rotateAll(Block.boxZ(16.0, 0.0, 1.0));
|
|
public static final EnumProperty<Direction> FACING = DirectionalBlock.FACING;
|
|
public static final ResourceLocation CONTENTS = ResourceLocation.withDefaultNamespace("contents");
|
|
@Nullable
|
|
private final DyeColor color;
|
|
|
|
@Override
|
|
public MapCodec<ShulkerBoxBlock> codec() {
|
|
return CODEC;
|
|
}
|
|
|
|
public ShulkerBoxBlock(@Nullable DyeColor p_56188_, BlockBehaviour.Properties p_56189_) {
|
|
super(p_56189_);
|
|
this.color = p_56188_;
|
|
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.UP));
|
|
}
|
|
|
|
@Override
|
|
public BlockEntity newBlockEntity(BlockPos p_154552_, BlockState p_154553_) {
|
|
return new ShulkerBoxBlockEntity(this.color, p_154552_, p_154553_);
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level p_154543_, BlockState p_154544_, BlockEntityType<T> p_154545_) {
|
|
return createTickerHelper(p_154545_, BlockEntityType.SHULKER_BOX, ShulkerBoxBlockEntity::tick);
|
|
}
|
|
|
|
@Override
|
|
protected InteractionResult useWithoutItem(BlockState p_56227_, Level p_56228_, BlockPos p_56229_, Player p_56230_, BlockHitResult p_56232_) {
|
|
if (p_56228_ instanceof ServerLevel serverlevel
|
|
&& p_56228_.getBlockEntity(p_56229_) instanceof ShulkerBoxBlockEntity shulkerboxblockentity
|
|
&& canOpen(p_56227_, p_56228_, p_56229_, shulkerboxblockentity)) {
|
|
p_56230_.openMenu(shulkerboxblockentity);
|
|
p_56230_.awardStat(Stats.OPEN_SHULKER_BOX);
|
|
PiglinAi.angerNearbyPiglins(serverlevel, p_56230_, true);
|
|
}
|
|
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
private static boolean canOpen(BlockState p_154547_, Level p_154548_, BlockPos p_154549_, ShulkerBoxBlockEntity p_154550_) {
|
|
if (p_154550_.getAnimationStatus() != ShulkerBoxBlockEntity.AnimationStatus.CLOSED) {
|
|
return true;
|
|
} else {
|
|
AABB aabb = Shulker.getProgressDeltaAabb(1.0F, p_154547_.getValue(FACING), 0.0F, 0.5F, p_154549_.getBottomCenter()).deflate(1.0E-6);
|
|
return p_154548_.noCollision(aabb);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public BlockState getStateForPlacement(BlockPlaceContext p_56198_) {
|
|
return this.defaultBlockState().setValue(FACING, p_56198_.getClickedFace());
|
|
}
|
|
|
|
@Override
|
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_56249_) {
|
|
p_56249_.add(FACING);
|
|
}
|
|
|
|
@Override
|
|
public BlockState playerWillDestroy(Level p_56212_, BlockPos p_56213_, BlockState p_56214_, Player p_56215_) {
|
|
BlockEntity blockentity = p_56212_.getBlockEntity(p_56213_);
|
|
if (blockentity instanceof ShulkerBoxBlockEntity shulkerboxblockentity) {
|
|
if (!p_56212_.isClientSide && p_56215_.preventsBlockDrops() && !shulkerboxblockentity.isEmpty()) {
|
|
ItemStack itemstack = getColoredItemStack(this.getColor());
|
|
itemstack.applyComponents(blockentity.collectComponents());
|
|
ItemEntity itementity = new ItemEntity(p_56212_, p_56213_.getX() + 0.5, p_56213_.getY() + 0.5, p_56213_.getZ() + 0.5, itemstack);
|
|
itementity.setDefaultPickUpDelay();
|
|
p_56212_.addFreshEntity(itementity);
|
|
} else {
|
|
shulkerboxblockentity.unpackLootTable(p_56215_);
|
|
}
|
|
}
|
|
|
|
return super.playerWillDestroy(p_56212_, p_56213_, p_56214_, p_56215_);
|
|
}
|
|
|
|
@Override
|
|
protected List<ItemStack> getDrops(BlockState p_287632_, LootParams.Builder p_287691_) {
|
|
BlockEntity blockentity = p_287691_.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
|
|
if (blockentity instanceof ShulkerBoxBlockEntity shulkerboxblockentity) {
|
|
p_287691_ = p_287691_.withDynamicDrop(CONTENTS, p_56219_ -> {
|
|
for (int i = 0; i < shulkerboxblockentity.getContainerSize(); i++) {
|
|
p_56219_.accept(shulkerboxblockentity.getItem(i));
|
|
}
|
|
});
|
|
}
|
|
|
|
return super.getDrops(p_287632_, p_287691_);
|
|
}
|
|
|
|
@Override
|
|
protected void affectNeighborsAfterRemoval(BlockState p_393214_, ServerLevel p_391858_, BlockPos p_393972_, boolean p_396098_) {
|
|
Containers.updateNeighboursAfterDestroy(p_393214_, p_391858_, p_393972_);
|
|
}
|
|
|
|
@Override
|
|
protected VoxelShape getBlockSupportShape(BlockState p_259177_, BlockGetter p_260305_, BlockPos p_259168_) {
|
|
return p_260305_.getBlockEntity(p_259168_) instanceof ShulkerBoxBlockEntity shulkerboxblockentity && !shulkerboxblockentity.isClosed()
|
|
? SHAPES_OPEN_SUPPORT.get(p_259177_.getValue(FACING).getOpposite())
|
|
: Shapes.block();
|
|
}
|
|
|
|
@Override
|
|
protected VoxelShape getShape(BlockState p_56257_, BlockGetter p_56258_, BlockPos p_56259_, CollisionContext p_56260_) {
|
|
return p_56258_.getBlockEntity(p_56259_) instanceof ShulkerBoxBlockEntity shulkerboxblockentity
|
|
? Shapes.create(shulkerboxblockentity.getBoundingBox(p_56257_))
|
|
: Shapes.block();
|
|
}
|
|
|
|
@Override
|
|
protected boolean propagatesSkylightDown(BlockState p_330948_) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected boolean hasAnalogOutputSignal(BlockState p_56221_) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected int getAnalogOutputSignal(BlockState p_56223_, Level p_56224_, BlockPos p_56225_) {
|
|
return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(p_56224_.getBlockEntity(p_56225_));
|
|
}
|
|
|
|
public static Block getBlockByColor(@Nullable DyeColor p_56191_) {
|
|
if (p_56191_ == null) {
|
|
return Blocks.SHULKER_BOX;
|
|
} else {
|
|
return switch (p_56191_) {
|
|
case WHITE -> Blocks.WHITE_SHULKER_BOX;
|
|
case ORANGE -> Blocks.ORANGE_SHULKER_BOX;
|
|
case MAGENTA -> Blocks.MAGENTA_SHULKER_BOX;
|
|
case LIGHT_BLUE -> Blocks.LIGHT_BLUE_SHULKER_BOX;
|
|
case YELLOW -> Blocks.YELLOW_SHULKER_BOX;
|
|
case LIME -> Blocks.LIME_SHULKER_BOX;
|
|
case PINK -> Blocks.PINK_SHULKER_BOX;
|
|
case GRAY -> Blocks.GRAY_SHULKER_BOX;
|
|
case LIGHT_GRAY -> Blocks.LIGHT_GRAY_SHULKER_BOX;
|
|
case CYAN -> Blocks.CYAN_SHULKER_BOX;
|
|
case BLUE -> Blocks.BLUE_SHULKER_BOX;
|
|
case BROWN -> Blocks.BROWN_SHULKER_BOX;
|
|
case GREEN -> Blocks.GREEN_SHULKER_BOX;
|
|
case RED -> Blocks.RED_SHULKER_BOX;
|
|
case BLACK -> Blocks.BLACK_SHULKER_BOX;
|
|
case PURPLE -> Blocks.PURPLE_SHULKER_BOX;
|
|
};
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public DyeColor getColor() {
|
|
return this.color;
|
|
}
|
|
|
|
public static ItemStack getColoredItemStack(@Nullable DyeColor p_56251_) {
|
|
return new ItemStack(getBlockByColor(p_56251_));
|
|
}
|
|
|
|
@Override
|
|
protected BlockState rotate(BlockState p_56243_, Rotation p_56244_) {
|
|
return p_56243_.setValue(FACING, p_56244_.rotate(p_56243_.getValue(FACING)));
|
|
}
|
|
|
|
@Override
|
|
protected BlockState mirror(BlockState p_56240_, Mirror p_56241_) {
|
|
return p_56240_.rotate(p_56241_.getRotation(p_56240_.getValue(FACING)));
|
|
}
|
|
} |