Unicopia/src/main/java/com/minelittlepony/unicopia/block/TallCropBlock.java
2020-04-24 21:27:48 +02:00

257 lines
8.1 KiB
Java

package com.minelittlepony.unicopia.block;
import java.util.Random;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.CropBlock;
import net.minecraft.entity.EntityContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.state.property.IntProperty;
import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldView;
public class TallCropBlock extends CropBlock {
public static final IntProperty AGE = IntProperty.of("age", 0, 4);
public static final EnumProperty<Half> HALF = EnumProperty.of("half", Half.class);
private static final VoxelShape[] SHAPES = new VoxelShape[] {
Block.createCuboidShape(0, 0, 0, 16, 1.6, 16),
Block.createCuboidShape(0, 0, 0, 16, 3.2, 16),
Block.createCuboidShape(0, 0, 0, 16, 4.4, 16),
Block.createCuboidShape(0, 0, 0, 16, 9.6, 16),
Block.createCuboidShape(0, 0, 0, 16, 12.8, 16),
Block.createCuboidShape(0, 0, 0, 16, 16, 16),
Block.createCuboidShape(0, 0, 0, 16, 17.6, 16),
Block.createCuboidShape(0, 0, 0, 16, 19.2, 16),
Block.createCuboidShape(0, 0, 0, 16, 20.4, 16),
Block.createCuboidShape(0, 0, 0, 16, 25.6, 16),
Block.createCuboidShape(0, 0, 0, 16, 32, 16),
Block.createCuboidShape(0, 0, 0, 16, 33.6, 16),
Block.createCuboidShape(0, 0, 0, 16, 38.4, 16),
Block.createCuboidShape(0, 0, 0, 16, 67.6, 16),
Block.createCuboidShape(0, 0, 0, 16, 44.8, 16),
Block.createCuboidShape(0, 0, 0, 16, 48, 16)
};
public TallCropBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(HALF, Half.BOTTOM));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(AGE, HALF);
}
@Override
public OffsetType getOffsetType() {
return OffsetType.XZ;
}
@Override
public IntProperty getAgeProperty() {
return AGE;
}
@Override
public int getMaxAge() {
return 4;
}
@Override
protected Item getSeedsItem() {
return UItems.ALFALFA_SEEDS;
}
@Override
public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random rand) {
if (rand.nextInt(10) != 0 && world.isChunkLoaded(pos) && world.getLightLevel(pos.up()) >= 9) {
if (canGrow(world, rand, pos, state)) {
growUpwards(world, pos, state, 1);
}
}
}
@Override
protected boolean canPlantOnTop(BlockState state, BlockView view, BlockPos pos) {
return state.getBlock() == this || super.canPlantOnTop(state, view, pos);
}
protected void growUpwards(World world, BlockPos pos, BlockState state, int increase) {
boolean hasDown = world.getBlockState(pos.down()).getBlock() == this;
boolean hasTrunk = world.getBlockState(pos.down(2)).getBlock() == this;
boolean hasRoot = world.getBlockState(pos.down(3)).getBlock() == this;
if (state.getBlock() != this) {
if (state.isAir()) {
if (!(hasDown && hasTrunk && hasRoot)) {
world.setBlockState(pos, withAge(increase).with(HALF, Half.TOP));
}
}
return;
}
int age = getAge(state) + increase;
int max = getMaxAge();
if (age > max) {
if (!(hasDown && hasTrunk)) {
growUpwards(world, pos.up(), world.getBlockState(pos.up()), age - max);
}
age = max;
}
boolean hasUp = world.getBlockState(pos.up()).getBlock() == this;
if (hasDown && hasUp) {
world.setBlockState(pos, withAge(age).with(HALF, Half.MIDDLE));
} else if (hasUp) {
world.setBlockState(pos, withAge(age).with(HALF, Half.BOTTOM));
} else {
world.setBlockState(pos, withAge(age).with(HALF, Half.TOP));
}
}
@Override
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
return getHalf(state) != Half.BOTTOM || super.canPlaceAt(state, world, pos);
}
public void onPlayerDestroy(World worldIn, BlockPos pos, BlockState state) {
breakConnectedBlocks(worldIn, pos, null);
}
@Override
public void onBreak(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
breakConnectedBlocks(worldIn, pos, player);
}
protected void breakConnectedBlocks(World worldIn, BlockPos pos, @Nullable PlayerEntity player) {
BlockState state = worldIn.getBlockState(pos);
if (state.getBlock() != this) {
return;
}
worldIn.breakBlock(pos, true);
Half half = getHalf(state);
if (half.checkDown()) {
breakConnectedBlocks(worldIn, pos.down(), player);
}
if (half.checkUp()) {
breakConnectedBlocks(worldIn, pos.up(), player);
}
}
@Override
protected int getGrowthAmount(World world) {
return super.getGrowthAmount(world) / 2;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
if (getHalf(state) != Half.MIDDLE) {
return VoxelShapes.empty();
}
return super.getCollisionShape(state, view, pos, context);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, EntityContext ePos) {
Vec3d offset = getOffsetPos(state, view, pos);
return SHAPES[Math.min(SHAPES.length - 1, getFullAge(view, pos))].offset(offset.x, offset.y, offset.z);
}
@Override
public boolean canGrow(World world, Random random, BlockPos pos, BlockState state) {
Half half = getHalf(state);
if (half == Half.MIDDLE || (half == Half.TOP && world.getBlockState(pos.down()).getBlock() == this)) {
return false;
}
BlockState above = world.getBlockState(pos.up(1));
BlockState higher = world.getBlockState(pos.up(2));
boolean iCanGrow = !isMature(state);
boolean aboveCanGrow = above.getBlock() != this || !isMature(above);
boolean higherCanGrow = higher.getBlock() != this || !isMature(higher);
return iCanGrow || aboveCanGrow || higherCanGrow;
}
@Override
public void applyGrowth(World world, BlockPos pos, BlockState state) {
growUpwards(world, pos, state, getGrowthAmount(world));
}
protected BlockPos getTip(World world, BlockPos pos) {
BlockPos above = pos.up();
BlockState state = world.getBlockState(above);
if (state.getBlock() == this) {
return getTip(world, above);
}
return pos;
}
protected int getFullAge(BlockView world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
int age = 0;
if (state.getBlock() == this) {
age += state.get(getAgeProperty());
age += getFullAge(world, pos.up());
}
return age;
}
protected Half getHalf(BlockState state) {
return state.get(HALF);
}
public enum Half implements StringIdentifiable {
TOP,
MIDDLE,
BOTTOM;
boolean checkUp() {
return this != TOP;
}
boolean checkDown() {
return this != BOTTOM;
}
@Override
public String toString() {
return super.toString().toLowerCase();
}
@Override
public String asString() {
return toString();
}
}
}