package net.minecraft.world.entity.vehicle; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.HasCustomInventoryScreen; import net.minecraft.world.entity.SlotAccess; import net.minecraft.world.entity.monster.piglin.PiglinAi; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ChestMenu; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.storage.loot.LootTable; import org.jetbrains.annotations.Nullable; public class ChestBoat extends Boat implements HasCustomInventoryScreen, ContainerEntity { private static final int CONTAINER_SIZE = 27; private NonNullList itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); @Nullable private ResourceKey lootTable; private long lootTableSeed; public ChestBoat(EntityType entityType, Level level) { super(entityType, level); } public ChestBoat(Level level, double x, double y, double z) { super(EntityType.CHEST_BOAT, level); this.setPos(x, y, z); this.xo = x; this.yo = y; this.zo = z; } @Override protected float getSinglePassengerXOffset() { return 0.15F; } @Override protected int getMaxPassengers() { return 1; } @Override protected void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); this.addChestVehicleSaveData(compound, this.registryAccess()); } @Override protected void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); this.readChestVehicleSaveData(compound, this.registryAccess()); } @Override public void destroy(DamageSource source) { this.destroy(this.getDropItem()); this.chestVehicleDestroyed(source, this.level(), this); } @Override public void remove(Entity.RemovalReason reason) { if (!this.level().isClientSide && reason.shouldDestroy()) { Containers.dropContents(this.level(), this, this); } super.remove(reason); } @Override public InteractionResult interact(Player player, InteractionHand hand) { if (!player.isSecondaryUseActive()) { InteractionResult interactionResult = super.interact(player, hand); if (interactionResult != InteractionResult.PASS) { return interactionResult; } } if (this.canAddPassenger(player) && !player.isSecondaryUseActive()) { return InteractionResult.PASS; } else { InteractionResult interactionResult = this.interactWithContainerVehicle(player); if (interactionResult.consumesAction()) { this.gameEvent(GameEvent.CONTAINER_OPEN, player); PiglinAi.angerNearbyPiglins(player, true); } return interactionResult; } } @Override public void openCustomInventoryScreen(Player player) { player.openMenu(this); if (!player.level().isClientSide) { this.gameEvent(GameEvent.CONTAINER_OPEN, player); PiglinAi.angerNearbyPiglins(player, true); } } @Override public Item getDropItem() { return switch (this.getVariant()) { case SPRUCE -> Items.SPRUCE_CHEST_BOAT; case BIRCH -> Items.BIRCH_CHEST_BOAT; case JUNGLE -> Items.JUNGLE_CHEST_BOAT; case ACACIA -> Items.ACACIA_CHEST_BOAT; case CHERRY -> Items.CHERRY_CHEST_BOAT; case DARK_OAK -> Items.DARK_OAK_CHEST_BOAT; case MANGROVE -> Items.MANGROVE_CHEST_BOAT; case BAMBOO -> Items.BAMBOO_CHEST_RAFT; default -> Items.OAK_CHEST_BOAT; }; } @Override public void clearContent() { this.clearChestVehicleContent(); } @Override public int getContainerSize() { return 27; } @Override public ItemStack getItem(int slot) { return this.getChestVehicleItem(slot); } @Override public ItemStack removeItem(int slot, int amount) { return this.removeChestVehicleItem(slot, amount); } @Override public ItemStack removeItemNoUpdate(int slot) { return this.removeChestVehicleItemNoUpdate(slot); } @Override public void setItem(int slot, ItemStack stack) { this.setChestVehicleItem(slot, stack); } @Override public SlotAccess getSlot(int slot) { return this.getChestVehicleSlot(slot); } @Override public void setChanged() { } @Override public boolean stillValid(Player player) { return this.isChestVehicleStillValid(player); } @Nullable @Override public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { if (this.lootTable != null && player.isSpectator()) { return null; } else { this.unpackLootTable(inventory.player); return ChestMenu.threeRows(i, inventory, this); } } public void unpackLootTable(@Nullable Player player) { this.unpackChestVehicleLootTable(player); } @Nullable @Override public ResourceKey getLootTable() { return this.lootTable; } @Override public void setLootTable(@Nullable ResourceKey lootTable) { this.lootTable = lootTable; } @Override public long getLootTableSeed() { return this.lootTableSeed; } @Override public void setLootTableSeed(long lootTableSeed) { this.lootTableSeed = lootTableSeed; } @Override public NonNullList getItemStacks() { return this.itemStacks; } @Override public void clearItemStacks() { this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); } @Override public void stopOpen(Player player) { this.level().gameEvent(GameEvent.CONTAINER_CLOSE, this.position(), GameEvent.Context.of(player)); } }