minecraft-source/src/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java

309 lines
11 KiB
Java

package net.minecraft.world.level.block.entity;
import java.util.stream.IntStream;
import net.minecraft.world.Container;
import net.minecraft.world.inventory.ShulkerBoxMenu;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.ContainerHelper;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.LevelAccessor;
import java.util.List;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.core.Direction;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nullable;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.NonNullList;
import net.minecraft.world.WorldlyContainer;
public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer, TickableBlockEntity {
private static final int[] SLOTS;
private NonNullList<ItemStack> itemStacks;
private int openCount;
private AnimationStatus animationStatus;
private float progress;
private float progressOld;
@Nullable
private DyeColor color;
private boolean loadColorFromBlock;
public ShulkerBoxBlockEntity(@Nullable final DyeColor bdg) {
super(BlockEntityType.SHULKER_BOX);
this.itemStacks = NonNullList.<ItemStack>withSize(27, ItemStack.EMPTY);
this.animationStatus = AnimationStatus.CLOSED;
this.color = bdg;
}
public ShulkerBoxBlockEntity() {
this((DyeColor)null);
this.loadColorFromBlock = true;
}
@Override
public void tick() {
this.updateAnimation();
if (this.animationStatus == AnimationStatus.OPENING || this.animationStatus == AnimationStatus.CLOSING) {
this.moveCollidedEntities();
}
}
protected void updateAnimation() {
this.progressOld = this.progress;
switch (this.animationStatus) {
case CLOSED: {
this.progress = 0.0f;
break;
}
case OPENING: {
this.progress += 0.1f;
if (this.progress >= 1.0f) {
this.moveCollidedEntities();
this.animationStatus = AnimationStatus.OPENED;
this.progress = 1.0f;
this.doNeighborUpdates();
break;
}
break;
}
case CLOSING: {
this.progress -= 0.1f;
if (this.progress <= 0.0f) {
this.animationStatus = AnimationStatus.CLOSED;
this.progress = 0.0f;
this.doNeighborUpdates();
break;
}
break;
}
case OPENED: {
this.progress = 1.0f;
break;
}
}
}
public AnimationStatus getAnimationStatus() {
return this.animationStatus;
}
public AABB getBoundingBox(final BlockState byg) {
return this.getBoundingBox(byg.<Direction>getValue(ShulkerBoxBlock.FACING));
}
public AABB getBoundingBox(final Direction fp) {
final float float3 = this.getProgress(1.0f);
return Shapes.block().bounds().expandTowards(0.5f * float3 * fp.getStepX(), 0.5f * float3 * fp.getStepY(), 0.5f * float3 * fp.getStepZ());
}
private AABB getTopBoundingBox(final Direction fp) {
final Direction fp2 = fp.getOpposite();
return this.getBoundingBox(fp).contract(fp2.getStepX(), fp2.getStepY(), fp2.getStepZ());
}
private void moveCollidedEntities() {
final BlockState byg2 = this.level.getBlockState(this.getBlockPos());
if (!(byg2.getBlock() instanceof ShulkerBoxBlock)) {
return;
}
final Direction fp3 = byg2.<Direction>getValue(ShulkerBoxBlock.FACING);
final AABB cvc4 = this.getTopBoundingBox(fp3).move(this.worldPosition);
final List<Entity> list5 = this.level.getEntities(null, cvc4);
if (list5.isEmpty()) {
return;
}
for (int integer6 = 0; integer6 < list5.size(); ++integer6) {
final Entity akn7 = list5.get(integer6);
if (akn7.getPistonPushReaction() != PushReaction.IGNORE) {
double double8 = 0.0;
double double9 = 0.0;
double double10 = 0.0;
final AABB cvc5 = akn7.getBoundingBox();
switch (fp3.getAxis()) {
case X: {
if (fp3.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
double8 = cvc4.maxX - cvc5.minX;
}
else {
double8 = cvc5.maxX - cvc4.minX;
}
double8 += 0.01;
break;
}
case Y: {
if (fp3.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
double9 = cvc4.maxY - cvc5.minY;
}
else {
double9 = cvc5.maxY - cvc4.minY;
}
double9 += 0.01;
break;
}
case Z: {
if (fp3.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
double10 = cvc4.maxZ - cvc5.minZ;
}
else {
double10 = cvc5.maxZ - cvc4.minZ;
}
double10 += 0.01;
break;
}
}
akn7.move(MoverType.SHULKER_BOX, new Vec3(double8 * fp3.getStepX(), double9 * fp3.getStepY(), double10 * fp3.getStepZ()));
}
}
}
@Override
public int getContainerSize() {
return this.itemStacks.size();
}
@Override
public boolean triggerEvent(final int integer1, final int integer2) {
if (integer1 == 1) {
if ((this.openCount = integer2) == 0) {
this.animationStatus = AnimationStatus.CLOSING;
this.doNeighborUpdates();
}
if (integer2 == 1) {
this.animationStatus = AnimationStatus.OPENING;
this.doNeighborUpdates();
}
return true;
}
return super.triggerEvent(integer1, integer2);
}
private void doNeighborUpdates() {
this.getBlockState().updateNeighbourShapes(this.getLevel(), this.getBlockPos(), 3);
}
@Override
public void startOpen(final Player ayg) {
if (!ayg.isSpectator()) {
if (this.openCount < 0) {
this.openCount = 0;
}
++this.openCount;
this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount);
if (this.openCount == 1) {
this.level.playSound(null, this.worldPosition, SoundEvents.SHULKER_BOX_OPEN, SoundSource.BLOCKS, 0.5f, this.level.random.nextFloat() * 0.1f + 0.9f);
}
}
}
@Override
public void stopOpen(final Player ayg) {
if (!ayg.isSpectator()) {
--this.openCount;
this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount);
if (this.openCount <= 0) {
this.level.playSound(null, this.worldPosition, SoundEvents.SHULKER_BOX_CLOSE, SoundSource.BLOCKS, 0.5f, this.level.random.nextFloat() * 0.1f + 0.9f);
}
}
}
@Override
protected Component getDefaultName() {
return new TranslatableComponent("container.shulkerBox", new Object[0]);
}
@Override
public void load(final CompoundTag jt) {
super.load(jt);
this.loadFromTag(jt);
}
@Override
public CompoundTag save(final CompoundTag jt) {
super.save(jt);
return this.saveToTag(jt);
}
public void loadFromTag(final CompoundTag jt) {
this.itemStacks = NonNullList.<ItemStack>withSize(this.getContainerSize(), ItemStack.EMPTY);
if (!this.tryLoadLootTable(jt) && jt.contains("Items", 9)) {
ContainerHelper.loadAllItems(jt, this.itemStacks);
}
}
public CompoundTag saveToTag(final CompoundTag jt) {
if (!this.trySaveLootTable(jt)) {
ContainerHelper.saveAllItems(jt, this.itemStacks, false);
}
return jt;
}
@Override
protected NonNullList<ItemStack> getItems() {
return this.itemStacks;
}
@Override
protected void setItems(final NonNullList<ItemStack> fy) {
this.itemStacks = fy;
}
@Override
public int[] getSlotsForFace(final Direction fp) {
return ShulkerBoxBlockEntity.SLOTS;
}
@Override
public boolean canPlaceItemThroughFace(final int integer, final ItemStack bek, @Nullable final Direction fp) {
return !(Block.byItem(bek.getItem()) instanceof ShulkerBoxBlock);
}
@Override
public boolean canTakeItemThroughFace(final int integer, final ItemStack bek, final Direction fp) {
return true;
}
public float getProgress(final float float1) {
return Mth.lerp(float1, this.progressOld, this.progress);
}
@Nullable
public DyeColor getColor() {
if (this.loadColorFromBlock) {
this.color = ShulkerBoxBlock.getColorFromBlock(this.getBlockState().getBlock());
this.loadColorFromBlock = false;
}
return this.color;
}
@Override
protected AbstractContainerMenu createMenu(final int integer, final Inventory ayf) {
return new ShulkerBoxMenu(integer, ayf, this);
}
static {
SLOTS = IntStream.range(0, 27).toArray();
}
public enum AnimationStatus {
CLOSED,
OPENING,
OPENED,
CLOSING;
}
}