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

379 lines
16 KiB
Java

package net.minecraft.world.level.block;
import net.minecraft.world.level.block.state.AbstractStateHolder;
import javax.annotation.Nullable;
import net.minecraft.world.SimpleContainer;
import net.minecraft.Util;
import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.WorldlyContainer;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.LevelAccessor;
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.phys.shapes.CollisionContext;
import java.util.Random;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.Items;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.ItemLike;
import it.unimi.dsi.fastutil.objects.Object2FloatMap;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.WorldlyContainerHolder;
public class ComposterBlock extends Block implements WorldlyContainerHolder {
public static final IntegerProperty LEVEL;
public static final Object2FloatMap<ItemLike> COMPOSTABLES;
public static final VoxelShape OUTER_SHAPE;
private static final VoxelShape[] SHAPES;
public static void bootStrap() {
ComposterBlock.COMPOSTABLES.defaultReturnValue(-1.0f);
final float float1 = 0.3f;
final float float2 = 0.5f;
final float float3 = 0.65f;
final float float4 = 0.85f;
final float float5 = 1.0f;
add(0.3f, Items.JUNGLE_LEAVES);
add(0.3f, Items.OAK_LEAVES);
add(0.3f, Items.SPRUCE_LEAVES);
add(0.3f, Items.DARK_OAK_LEAVES);
add(0.3f, Items.ACACIA_LEAVES);
add(0.3f, Items.BIRCH_LEAVES);
add(0.3f, Items.OAK_SAPLING);
add(0.3f, Items.SPRUCE_SAPLING);
add(0.3f, Items.BIRCH_SAPLING);
add(0.3f, Items.JUNGLE_SAPLING);
add(0.3f, Items.ACACIA_SAPLING);
add(0.3f, Items.DARK_OAK_SAPLING);
add(0.3f, Items.BEETROOT_SEEDS);
add(0.3f, Items.DRIED_KELP);
add(0.3f, Items.GRASS);
add(0.3f, Items.KELP);
add(0.3f, Items.MELON_SEEDS);
add(0.3f, Items.PUMPKIN_SEEDS);
add(0.3f, Items.SEAGRASS);
add(0.3f, Items.SWEET_BERRIES);
add(0.3f, Items.WHEAT_SEEDS);
add(0.5f, Items.DRIED_KELP_BLOCK);
add(0.5f, Items.TALL_GRASS);
add(0.5f, Items.CACTUS);
add(0.5f, Items.SUGAR_CANE);
add(0.5f, Items.VINE);
add(0.5f, Items.MELON_SLICE);
add(0.65f, Items.SEA_PICKLE);
add(0.65f, Items.LILY_PAD);
add(0.65f, Items.PUMPKIN);
add(0.65f, Items.CARVED_PUMPKIN);
add(0.65f, Items.MELON);
add(0.65f, Items.APPLE);
add(0.65f, Items.BEETROOT);
add(0.65f, Items.CARROT);
add(0.65f, Items.COCOA_BEANS);
add(0.65f, Items.POTATO);
add(0.65f, Items.WHEAT);
add(0.65f, Items.BROWN_MUSHROOM);
add(0.65f, Items.RED_MUSHROOM);
add(0.65f, Items.MUSHROOM_STEM);
add(0.65f, Items.DANDELION);
add(0.65f, Items.POPPY);
add(0.65f, Items.BLUE_ORCHID);
add(0.65f, Items.ALLIUM);
add(0.65f, Items.AZURE_BLUET);
add(0.65f, Items.RED_TULIP);
add(0.65f, Items.ORANGE_TULIP);
add(0.65f, Items.WHITE_TULIP);
add(0.65f, Items.PINK_TULIP);
add(0.65f, Items.OXEYE_DAISY);
add(0.65f, Items.CORNFLOWER);
add(0.65f, Items.LILY_OF_THE_VALLEY);
add(0.65f, Items.WITHER_ROSE);
add(0.65f, Items.FERN);
add(0.65f, Items.SUNFLOWER);
add(0.65f, Items.LILAC);
add(0.65f, Items.ROSE_BUSH);
add(0.65f, Items.PEONY);
add(0.65f, Items.LARGE_FERN);
add(0.85f, Items.HAY_BLOCK);
add(0.85f, Items.BROWN_MUSHROOM_BLOCK);
add(0.85f, Items.RED_MUSHROOM_BLOCK);
add(0.85f, Items.BREAD);
add(0.85f, Items.BAKED_POTATO);
add(0.85f, Items.COOKIE);
add(1.0f, Items.CAKE);
add(1.0f, Items.PUMPKIN_PIE);
}
private static void add(final float float1, final ItemLike bjs) {
ComposterBlock.COMPOSTABLES.put(bjs.asItem(), float1);
}
public ComposterBlock(final Properties c) {
super(c);
this.registerDefaultState(((AbstractStateHolder<O, BlockState>)this.stateDefinition.any()).<Comparable, Integer>setValue((Property<Comparable>)ComposterBlock.LEVEL, 0));
}
public static void handleFill(final Level bjt, final BlockPos fk, final boolean boolean3) {
final BlockState byg4 = bjt.getBlockState(fk);
bjt.playLocalSound(fk.getX(), fk.getY(), fk.getZ(), boolean3 ? SoundEvents.COMPOSTER_FILL_SUCCESS : SoundEvents.COMPOSTER_FILL, SoundSource.BLOCKS, 1.0f, 1.0f, false);
final double double5 = byg4.getShape(bjt, fk).max(Direction.Axis.Y, 0.5, 0.5) + 0.03125;
final double double6 = 0.13124999403953552;
final double double7 = 0.737500011920929;
final Random random11 = bjt.getRandom();
for (int integer12 = 0; integer12 < 10; ++integer12) {
final double double8 = random11.nextGaussian() * 0.02;
final double double9 = random11.nextGaussian() * 0.02;
final double double10 = random11.nextGaussian() * 0.02;
bjt.addParticle(ParticleTypes.COMPOSTER, fk.getX() + 0.13124999403953552 + 0.737500011920929 * random11.nextFloat(), fk.getY() + double5 + random11.nextFloat() * (1.0 - double5), fk.getZ() + 0.13124999403953552 + 0.737500011920929 * random11.nextFloat(), double8, double9, double10);
}
}
@Override
public VoxelShape getShape(final BlockState byg, final BlockGetter bjd, final BlockPos fk, final CollisionContext cvn) {
return ComposterBlock.SHAPES[byg.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL)];
}
@Override
public VoxelShape getInteractionShape(final BlockState byg, final BlockGetter bjd, final BlockPos fk) {
return ComposterBlock.OUTER_SHAPE;
}
@Override
public VoxelShape getCollisionShape(final BlockState byg, final BlockGetter bjd, final BlockPos fk, final CollisionContext cvn) {
return ComposterBlock.SHAPES[0];
}
@Override
public void onPlace(final BlockState byg1, final Level bjt, final BlockPos fk, final BlockState byg4, final boolean boolean5) {
if (byg1.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL) == 7) {
bjt.getBlockTicks().scheduleTick(fk, byg1.getBlock(), 20);
}
}
@Override
public InteractionResult use(final BlockState byg, final Level bjt, final BlockPos fk, final Player ayg, final InteractionHand ajh, final BlockHitResult cvd) {
final int integer8 = byg.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
final ItemStack bek9 = ayg.getItemInHand(ajh);
if (integer8 < 8 && ComposterBlock.COMPOSTABLES.containsKey(bek9.getItem())) {
if (integer8 < 7 && !bjt.isClientSide) {
final boolean boolean10 = addItem(byg, bjt, fk, bek9);
bjt.levelEvent(1500, fk, boolean10 ? 1 : 0);
if (!ayg.abilities.instabuild) {
bek9.shrink(1);
}
}
return InteractionResult.SUCCESS;
}
if (integer8 == 8) {
if (!bjt.isClientSide) {
final float float10 = 0.7f;
final double double11 = bjt.random.nextFloat() * 0.7f + 0.15000000596046448;
final double double12 = bjt.random.nextFloat() * 0.7f + 0.06000000238418579 + 0.6;
final double double13 = bjt.random.nextFloat() * 0.7f + 0.15000000596046448;
final ItemEntity avy17 = new ItemEntity(bjt, fk.getX() + double11, fk.getY() + double12, fk.getZ() + double13, new ItemStack(Items.BONE_MEAL));
avy17.setDefaultPickUpDelay();
bjt.addFreshEntity(avy17);
}
empty(byg, bjt, fk);
bjt.playSound(null, fk, SoundEvents.COMPOSTER_EMPTY, SoundSource.BLOCKS, 1.0f, 1.0f);
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
private static void empty(final BlockState byg, final LevelAccessor bju, final BlockPos fk) {
bju.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byg).<Comparable, Integer>setValue((Property<Comparable>)ComposterBlock.LEVEL, 0), 3);
}
private static boolean addItem(final BlockState byg, final LevelAccessor bju, final BlockPos fk, final ItemStack bek) {
final int integer5 = byg.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
final float float6 = ComposterBlock.COMPOSTABLES.getFloat(bek.getItem());
if ((integer5 == 0 && float6 > 0.0f) || bju.getRandom().nextDouble() < float6) {
final int integer6 = integer5 + 1;
bju.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byg).<Comparable, Integer>setValue((Property<Comparable>)ComposterBlock.LEVEL, integer6), 3);
if (integer6 == 7) {
bju.getBlockTicks().scheduleTick(fk, byg.getBlock(), 20);
}
return true;
}
return false;
}
@Override
public void tick(final BlockState byg, final ServerLevel xd, final BlockPos fk, final Random random) {
if (byg.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL) == 7) {
xd.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byg).<Comparable>cycle((Property<Comparable>)ComposterBlock.LEVEL), 3);
xd.playSound(null, fk, SoundEvents.COMPOSTER_READY, SoundSource.BLOCKS, 1.0f, 1.0f);
}
super.tick(byg, xd, fk, random);
}
@Override
public boolean hasAnalogOutputSignal(final BlockState byg) {
return true;
}
@Override
public int getAnalogOutputSignal(final BlockState byg, final Level bjt, final BlockPos fk) {
return byg.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
}
@Override
protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
a.add(ComposterBlock.LEVEL);
}
@Override
public boolean isPathfindable(final BlockState byg, final BlockGetter bjd, final BlockPos fk, final PathComputationType cqo) {
return false;
}
@Override
public WorldlyContainer getContainer(final BlockState byg, final LevelAccessor bju, final BlockPos fk) {
final int integer5 = byg.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
if (integer5 == 8) {
return new OutputContainer(byg, bju, fk, new ItemStack(Items.BONE_MEAL));
}
if (integer5 < 7) {
return new InputContainer(byg, bju, fk);
}
return new EmptyContainer();
}
static {
LEVEL = BlockStateProperties.LEVEL_COMPOSTER;
COMPOSTABLES = (Object2FloatMap)new Object2FloatOpenHashMap();
OUTER_SHAPE = Shapes.block();
int integer2;
SHAPES = Util.<VoxelShape[]>make(new VoxelShape[9], arr -> {
for (integer2 = 0; integer2 < 8; ++integer2) {
arr[integer2] = Shapes.join(ComposterBlock.OUTER_SHAPE, Block.box(2.0, Math.max(2, 1 + integer2 * 2), 2.0, 14.0, 16.0, 14.0), BooleanOp.ONLY_FIRST);
}
arr[8] = arr[7];
});
}
static class EmptyContainer extends SimpleContainer implements WorldlyContainer {
public EmptyContainer() {
super(0);
}
@Override
public int[] getSlotsForFace(final Direction fp) {
return new int[0];
}
@Override
public boolean canPlaceItemThroughFace(final int integer, final ItemStack bek, @Nullable final Direction fp) {
return false;
}
@Override
public boolean canTakeItemThroughFace(final int integer, final ItemStack bek, final Direction fp) {
return false;
}
}
static class OutputContainer extends SimpleContainer implements WorldlyContainer {
private final BlockState state;
private final LevelAccessor level;
private final BlockPos pos;
private boolean changed;
public OutputContainer(final BlockState byg, final LevelAccessor bju, final BlockPos fk, final ItemStack bek) {
super(bek);
this.state = byg;
this.level = bju;
this.pos = fk;
}
@Override
public int getMaxStackSize() {
return 1;
}
@Override
public int[] getSlotsForFace(final Direction fp) {
return (fp == Direction.DOWN) ? new int[] { 0 } : new int[0];
}
@Override
public boolean canPlaceItemThroughFace(final int integer, final ItemStack bek, @Nullable final Direction fp) {
return false;
}
@Override
public boolean canTakeItemThroughFace(final int integer, final ItemStack bek, final Direction fp) {
return !this.changed && fp == Direction.DOWN && bek.getItem() == Items.BONE_MEAL;
}
@Override
public void setChanged() {
empty(this.state, this.level, this.pos);
this.changed = true;
}
}
static class InputContainer extends SimpleContainer implements WorldlyContainer {
private final BlockState state;
private final LevelAccessor level;
private final BlockPos pos;
private boolean changed;
public InputContainer(final BlockState byg, final LevelAccessor bju, final BlockPos fk) {
super(1);
this.state = byg;
this.level = bju;
this.pos = fk;
}
@Override
public int getMaxStackSize() {
return 1;
}
@Override
public int[] getSlotsForFace(final Direction fp) {
return (fp == Direction.UP) ? new int[] { 0 } : new int[0];
}
@Override
public boolean canPlaceItemThroughFace(final int integer, final ItemStack bek, @Nullable final Direction fp) {
return !this.changed && fp == Direction.UP && ComposterBlock.COMPOSTABLES.containsKey(bek.getItem());
}
@Override
public boolean canTakeItemThroughFace(final int integer, final ItemStack bek, final Direction fp) {
return false;
}
@Override
public void setChanged() {
final ItemStack bek2 = this.getItem(0);
if (!bek2.isEmpty()) {
this.changed = true;
addItem(this.state, this.level, this.pos, bek2);
this.removeItemNoUpdate(0);
}
}
}
}