379 lines
16 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
}
|