2019-03-02 17:45:28 +01:00
|
|
|
package com.minelittlepony.unicopia.block;
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Random;
|
|
|
|
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
|
2019-03-03 23:33:40 +01:00
|
|
|
import com.minelittlepony.unicopia.Predicates;
|
2020-01-16 12:35:46 +01:00
|
|
|
import com.minelittlepony.unicopia.UBlocks;
|
|
|
|
import com.minelittlepony.unicopia.UMaterials;
|
|
|
|
import com.minelittlepony.unicopia.USounds;
|
|
|
|
import com.minelittlepony.util.MagicalDamageSource;
|
2019-03-02 17:45:28 +01:00
|
|
|
import com.minelittlepony.util.PosHelper;
|
|
|
|
|
|
|
|
import net.minecraft.block.Block;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.block.BlockState;
|
2019-03-02 17:45:28 +01:00
|
|
|
import net.minecraft.entity.Entity;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.entity.LivingEntity;
|
|
|
|
import net.minecraft.entity.damage.DamageSource;
|
2019-03-02 17:45:28 +01:00
|
|
|
import net.minecraft.item.Item;
|
2019-03-03 23:33:40 +01:00
|
|
|
import net.minecraft.item.ItemStack;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.particle.ParticleTypes;
|
|
|
|
import net.minecraft.state.property.EnumProperty;
|
|
|
|
import net.minecraft.state.property.IntProperty;
|
|
|
|
import net.minecraft.util.StringIdentifiable;
|
|
|
|
import net.minecraft.util.math.Box;
|
2019-03-02 17:45:28 +01:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import net.minecraft.util.math.Vec3d;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.world.BlockView;
|
2019-03-02 17:45:28 +01:00
|
|
|
import net.minecraft.world.World;
|
|
|
|
|
|
|
|
public class BlockGrowingCuccoon extends Block {
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
public static final DamageSource DAMAGE_SOURCE = MagicalDamageSource.mundane("acid");
|
2019-03-03 23:33:40 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
public static final IntProperty AGE = IntProperty.of("age", 0, 7);
|
|
|
|
public static final EnumProperty<Shape> SHAPE = EnumProperty.of("shape", Shape.class);
|
2019-03-02 17:45:28 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
public static final Box[] SHAFTS = new Box[] {
|
|
|
|
new Box(7/16F, 0, 7/16F, 9/16F, 1, 7/16F),
|
|
|
|
new Box(6/16F, 0, 6/16F, 10/16F, 1, 10/16F),
|
|
|
|
new Box(5/16F, 0, 5/16F, 11/16F, 1, 11/16F),
|
|
|
|
new Box(4/16F, 0, 4/16F, 12/16F, 1, 12/16F)
|
2019-03-02 17:45:28 +01:00
|
|
|
};
|
2020-01-16 12:35:46 +01:00
|
|
|
public static final Box[] BULBS = new Box[] {
|
|
|
|
new Box(6/16F, 1/16F, 6/16F, 10/16F, 8/16F, 10/16F),
|
|
|
|
new Box(4/16F, 0, 4/16F, 12/16F, 9/16F, 12/16F),
|
|
|
|
new Box(3/16F, 0, 3/16F, 13/16F, 10/16F, 13/16F),
|
|
|
|
new Box(2/16F, 0, 2/16F, 14/16F, 12/16F, 14/16F),
|
2019-03-02 17:45:28 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
public BlockGrowingCuccoon(String domain, String name) {
|
|
|
|
super(UMaterials.hive);
|
|
|
|
|
|
|
|
setTranslationKey(name);
|
|
|
|
setRegistryName(domain, name);
|
|
|
|
setResistance(0);
|
|
|
|
setSoundType(SoundType.SLIME);
|
|
|
|
setCreativeTab(CreativeTabs.MATERIALS);
|
|
|
|
setDefaultSlipperiness(0.5F);
|
|
|
|
setHarvestLevel("shovel", 2);
|
|
|
|
setLightLevel(0.6F);
|
|
|
|
setLightOpacity(0);
|
|
|
|
|
|
|
|
useNeighborBrightness = true;
|
|
|
|
|
|
|
|
setDefaultState(getBlockState().getBaseState()
|
2020-01-16 12:35:46 +01:00
|
|
|
.with(AGE, 0)
|
|
|
|
.with(SHAPE, Shape.BULB));
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isTranslucent(IBlockState state) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isOpaqueCube(IBlockState state) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
//Push player out of block
|
|
|
|
public boolean isFullCube(IBlockState state) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isNormalCube(IBlockState state) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public BlockRenderLayer getRenderLayer() {
|
|
|
|
return BlockRenderLayer.TRANSLUCENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Deprecated
|
|
|
|
@Override
|
2020-01-16 12:35:46 +01:00
|
|
|
public Box getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos) {
|
2019-03-02 17:45:28 +01:00
|
|
|
return getBoundingBox(state, world, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Block.EnumOffsetType getOffsetType() {
|
|
|
|
return Block.EnumOffsetType.XZ;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void updateTick(World world, BlockPos pos, IBlockState state, Random rand) {
|
|
|
|
if (!checkSupport(world, pos)) {
|
2019-03-02 18:18:29 +01:00
|
|
|
breakConnected(world, pos);
|
2019-03-02 17:45:28 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
int age = state.get(AGE);
|
2019-03-02 17:45:28 +01:00
|
|
|
|
|
|
|
BlockPos below = pos.down();
|
|
|
|
|
|
|
|
if (world.isBlockLoaded(below)) {
|
|
|
|
boolean spaceBelow = world.isAirBlock(below);
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
Shape shape = state.get(SHAPE);
|
2019-03-02 17:45:28 +01:00
|
|
|
|
|
|
|
if (shape == Shape.STRING && spaceBelow) {
|
2020-01-16 12:35:46 +01:00
|
|
|
world.setBlockState(pos, state.with(SHAPE, Shape.BULB).with(AGE, age / 2));
|
2019-03-02 17:45:28 +01:00
|
|
|
} else if (shape == Shape.BULB && !spaceBelow) {
|
2020-01-16 12:35:46 +01:00
|
|
|
world.setBlockState(pos, state.with(SHAPE, Shape.STRING).with(AGE, age / 2));
|
2019-03-02 17:45:28 +01:00
|
|
|
} else if (age >= 7) {
|
|
|
|
if (rand.nextInt(12) == 0 && spaceBelow) {
|
2020-01-16 12:35:46 +01:00
|
|
|
world.setBlockState(below, state.with(AGE, age / 2));
|
|
|
|
world.setBlockState(pos, getDefaultState().with(AGE, age / 2).with(SHAPE, Shape.STRING));
|
2019-03-02 17:45:28 +01:00
|
|
|
world.playSound(null, pos, USounds.SLIME_ADVANCE, SoundCategory.BLOCKS, 1, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (age < getMaximumAge(world, pos, state, spaceBelow)) {
|
|
|
|
if (rand.nextInt(5 * (age + 1)) == 0) {
|
|
|
|
world.setBlockState(pos, state.cycleProperty(AGE));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
world.scheduleUpdate(pos, this, tickRate(world));
|
|
|
|
}
|
|
|
|
|
2019-03-02 18:18:29 +01:00
|
|
|
protected void breakConnected(World world, BlockPos pos) {
|
|
|
|
world.destroyBlock(pos, true);
|
|
|
|
|
|
|
|
pos = pos.down();
|
|
|
|
if (world.getBlockState(pos).getBlock() == this) {
|
|
|
|
breakConnected(world, pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-02 17:45:28 +01:00
|
|
|
protected int getMaximumAge(World world, BlockPos pos, IBlockState state, boolean spaceBelow) {
|
2020-01-16 12:35:46 +01:00
|
|
|
if (state.get(SHAPE) == Shape.STRING) {
|
2019-03-02 17:45:28 +01:00
|
|
|
IBlockState higher = world.getBlockState(pos.up());
|
|
|
|
|
|
|
|
if (higher.getBlock() != this) {
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
return Math.min(higher.get(AGE),
|
2019-03-02 18:18:29 +01:00
|
|
|
((BlockGrowingCuccoon)higher.getBlock()).getMaximumAge(world, pos.up(), higher, false) - 1
|
|
|
|
);
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!spaceBelow) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-03-02 18:18:29 +01:00
|
|
|
public int quantityDropped(IBlockState state, int fortune, Random random) {
|
2020-01-16 12:35:46 +01:00
|
|
|
return random.nextInt(3) == 0 ? state.get(AGE) : 0;
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-03-02 18:18:29 +01:00
|
|
|
public Item getItemDropped(IBlockState state, Random rand, int fortune) {
|
|
|
|
return Items.SLIME_BALL;
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean canPlaceBlockAt(World world, BlockPos pos) {
|
|
|
|
return super.canPlaceBlockAt(world, pos) && checkSupport(world, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor) {
|
|
|
|
if (world instanceof World && !checkSupport(world, pos)) {
|
2019-03-02 18:18:29 +01:00
|
|
|
breakConnected((World)world, pos);
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void breakBlock(World world, BlockPos pos, IBlockState state) {
|
|
|
|
world.notifyNeighborsOfStateChange(pos, this, true);
|
|
|
|
super.breakBlock(world, pos, state);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onBlockAdded(World world, BlockPos pos, IBlockState state) {
|
|
|
|
world.scheduleUpdate(pos, this, 10);
|
|
|
|
}
|
|
|
|
|
2019-03-03 23:33:40 +01:00
|
|
|
@Override
|
|
|
|
public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity) {
|
2020-01-16 12:35:46 +01:00
|
|
|
if (entity instanceof LivingEntity && !entity.isDead) {
|
|
|
|
LivingEntity living = (LivingEntity)entity;
|
2019-03-03 23:33:40 +01:00
|
|
|
|
|
|
|
if (!Predicates.BUGGY.test(living) && living.getHealth() > 0) {
|
|
|
|
living.attackEntityFrom(DAMAGE_SOURCE, 1);
|
|
|
|
living.setInWeb();
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (!world.isClient) {
|
2019-03-03 23:33:40 +01:00
|
|
|
if (living.getHealth() <= 0) {
|
|
|
|
living.dropItem(Items.BONE, 3);
|
|
|
|
|
|
|
|
if (living instanceof EntityPlayer) {
|
|
|
|
ItemStack skull = new ItemStack(Items.SKULL, 1);
|
|
|
|
|
|
|
|
if (world.rand.nextInt(13000) == 0) {
|
|
|
|
EntityPlayer player = (EntityPlayer)living;
|
|
|
|
|
|
|
|
skull.setTagCompound(new NBTTagCompound());
|
|
|
|
skull.getTagCompound().setTag("SkullOwner", NBTUtil.writeGameProfile(new NBTTagCompound(), player.getGameProfile()));
|
|
|
|
skull.setItemDamage(3);
|
|
|
|
} else {
|
|
|
|
living.dropItem(Items.SKULL, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
living.entityDropItem(skull, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-02 17:45:28 +01:00
|
|
|
public boolean checkSupport(IBlockAccess world, BlockPos pos) {
|
|
|
|
|
|
|
|
if (PosHelper.some(pos, p -> !world.isAirBlock(p), EnumFacing.HORIZONTALS)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = pos.up();
|
|
|
|
|
|
|
|
IBlockState above = world.getBlockState(pos);
|
|
|
|
|
|
|
|
if (above.getBlock() == this || above.getBlock() == UBlocks.hive) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (above.getBlockFaceShape(world, pos, EnumFacing.DOWN)) {
|
|
|
|
case SOLID:
|
|
|
|
case CENTER:
|
|
|
|
case CENTER_BIG:
|
|
|
|
case CENTER_SMALL: return true;
|
|
|
|
default: return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Deprecated
|
|
|
|
@Override
|
2020-01-16 12:35:46 +01:00
|
|
|
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, Box entityBox, List<Box> collidingBoxes, @Nullable Entity entity, boolean isActualState) {
|
2019-03-02 17:45:28 +01:00
|
|
|
if (!isActualState) {
|
|
|
|
state = state.getActualState(world, pos);
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
int age = state.get(AGE) / 2;
|
2019-03-02 17:45:28 +01:00
|
|
|
|
|
|
|
Vec3d offset = state.getOffset(world, pos);
|
|
|
|
|
|
|
|
addCollisionBoxToList(pos, entityBox, collidingBoxes, SHAFTS[age % SHAFTS.length].offset(offset));
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (state.get(SHAPE) == Shape.BULB) {
|
2019-03-02 17:45:28 +01:00
|
|
|
addCollisionBoxToList(pos, entityBox, collidingBoxes, BULBS[age % BULBS.length].offset(offset));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Deprecated
|
|
|
|
@Override
|
2020-01-16 12:35:46 +01:00
|
|
|
public Box getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
|
2019-03-02 17:45:28 +01:00
|
|
|
state = state.getActualState(source, pos);
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (state.get(SHAPE) == Shape.BULB) {
|
|
|
|
return BULBS[state.get(AGE) / 2].offset(state.getOffset(source, pos));
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
return SHAFTS[state.get(AGE) / 2].offset(state.getOffset(source, pos));
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected BlockStateContainer createBlockState() {
|
|
|
|
return new BlockStateContainer(this, AGE, SHAPE);
|
|
|
|
}
|
|
|
|
|
2019-03-02 18:18:29 +01:00
|
|
|
@Override
|
2020-01-16 12:35:46 +01:00
|
|
|
public boolean isLadder(BlockState state, BlockView world, BlockPos pos, LivingEntity entity) {
|
2019-03-02 18:18:29 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
@Override
|
|
|
|
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random rand) {
|
|
|
|
if (state.get(SHAPE) == Shape.BULB) {
|
2019-03-02 18:18:29 +01:00
|
|
|
if (rand.nextInt(8) == 0) {
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
Box bounds = BULBS[state.get(AGE) / 2]
|
2019-03-02 18:18:29 +01:00
|
|
|
.offset(pos)
|
2020-01-16 12:35:46 +01:00
|
|
|
.offset(state.getOffsetPos(world, pos));
|
2019-03-02 18:18:29 +01:00
|
|
|
|
|
|
|
double x = bounds.minX + (bounds.maxX - bounds.minX) * rand.nextFloat();
|
|
|
|
double y = bounds.minY;
|
|
|
|
double z = bounds.minZ + (bounds.maxZ - bounds.minZ) * rand.nextFloat();
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
world.addParticle(ParticleTypes.DRIPPING_LAVA, x, y, z, 0, 0, 0);
|
2019-03-02 18:18:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
enum Shape implements StringIdentifiable {
|
2019-03-02 17:45:28 +01:00
|
|
|
BULB,
|
|
|
|
STRING;
|
|
|
|
|
|
|
|
static final Shape[] VALUES = values();
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
2020-01-16 12:35:46 +01:00
|
|
|
return asString();
|
2019-03-02 17:45:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-01-16 12:35:46 +01:00
|
|
|
public String asString() {
|
2019-03-02 17:45:28 +01:00
|
|
|
return name().toLowerCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|