package joshie.harvest.core.base.block; import com.google.common.collect.Lists; import joshie.harvest.core.HFTab; import joshie.harvest.core.helpers.MCClientHelper; import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.block.statemap.StateMap; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.common.IShearable; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Random; import static net.minecraft.block.BlockLeaves.CHECK_DECAY; import static net.minecraft.block.BlockLeaves.DECAYABLE; public abstract class BlockHFLeaves<B extends BlockHFLeaves, E extends Enum<E> & IStringSerializable> extends BlockHFEnum<B, E> implements IShearable { private int[] surroundings; //Main Constructor public BlockHFLeaves(Class<E> clazz, CreativeTabs tab) { super(Material.LEAVES, clazz, tab); setTickRandomly(true); setHardness(0.2F); setLightOpacity(1); setSoundType(SoundType.PLANT); } //Constructor default to farming tab public BlockHFLeaves(Class<E> clazz) { this(clazz, HFTab.FARMING); } @Override protected BlockStateContainer createBlockState() { if(property == null) return new BlockStateContainer(this, temporary, CHECK_DECAY, DECAYABLE); return new BlockStateContainer(this, property, CHECK_DECAY, DECAYABLE); } @Override public void breakBlock(@Nonnull World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state) { int k = pos.getX(); int l = pos.getY(); int i1 = pos.getZ(); if (worldIn.isAreaLoaded(new BlockPos(k - 2, l - 2, i1 - 2), new BlockPos(k + 2, l + 2, i1 + 2))) { for (int j1 = -1; j1 <= 1; ++j1) { for (int k1 = -1; k1 <= 1; ++k1) { for (int l1 = -1; l1 <= 1; ++l1) { BlockPos blockpos = pos.add(j1, k1, l1); IBlockState iblockstate = worldIn.getBlockState(blockpos); if (iblockstate.getBlock().isLeaves(iblockstate, worldIn, blockpos)) { iblockstate.getBlock().beginLeavesDecay(iblockstate, worldIn, blockpos); } } } } } } @Override public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) { if (!worldIn.isRemote) { if (state.getValue(CHECK_DECAY) && state.getValue(DECAYABLE)) { int k = pos.getX(); int l = pos.getY(); int i1 = pos.getZ(); if (surroundings == null) { surroundings = new int[32768]; } if (worldIn.isAreaLoaded(new BlockPos(k - 5, l - 5, i1 - 5), new BlockPos(k + 5, l + 5, i1 + 5))) { BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); for (int i2 = -4; i2 <= 4; ++i2) { for (int j2 = -4; j2 <= 4; ++j2) { for (int k2 = -4; k2 <= 4; ++k2) { IBlockState iblockstate = worldIn.getBlockState(blockpos$mutableblockpos.setPos(k + i2, l + j2, i1 + k2)); Block block = iblockstate.getBlock(); if (!block.canSustainLeaves(iblockstate, worldIn, blockpos$mutableblockpos.setPos(k + i2, l + j2, i1 + k2))) { if (block.isLeaves(iblockstate, worldIn, blockpos$mutableblockpos.setPos(k + i2, l + j2, i1 + k2))) { surroundings[(i2 + 16) * 1024 + (j2 + 16) * 32 + k2 + 16] = -2; } else { surroundings[(i2 + 16) * 1024 + (j2 + 16) * 32 + k2 + 16] = -1; } } else { surroundings[(i2 + 16) * 1024 + (j2 + 16) * 32 + k2 + 16] = 0; } } } } for (int i3 = 1; i3 <= 4; ++i3) { for (int j3 = -4; j3 <= 4; ++j3) { for (int k3 = -4; k3 <= 4; ++k3) { for (int l3 = -4; l3 <= 4; ++l3) { if (surroundings[(j3 + 16) * 1024 + (k3 + 16) * 32 + l3 + 16] == i3 - 1) { if (surroundings[(j3 + 16 - 1) * 1024 + (k3 + 16) * 32 + l3 + 16] == -2) { surroundings[(j3 + 16 - 1) * 1024 + (k3 + 16) * 32 + l3 + 16] = i3; } if (surroundings[(j3 + 16 + 1) * 1024 + (k3 + 16) * 32 + l3 + 16] == -2) { surroundings[(j3 + 16 + 1) * 1024 + (k3 + 16) * 32 + l3 + 16] = i3; } if (surroundings[(j3 + 16) * 1024 + (k3 + 16 - 1) * 32 + l3 + 16] == -2) { surroundings[(j3 + 16) * 1024 + (k3 + 16 - 1) * 32 + l3 + 16] = i3; } if (surroundings[(j3 + 16) * 1024 + (k3 + 16 + 1) * 32 + l3 + 16] == -2) { surroundings[(j3 + 16) * 1024 + (k3 + 16 + 1) * 32 + l3 + 16] = i3; } if (surroundings[(j3 + 16) * 1024 + (k3 + 16) * 32 + (l3 + 16 - 1)] == -2) { surroundings[(j3 + 16) * 1024 + (k3 + 16) * 32 + (l3 + 16 - 1)] = i3; } if (surroundings[(j3 + 16) * 1024 + (k3 + 16) * 32 + l3 + 16 + 1] == -2) { surroundings[(j3 + 16) * 1024 + (k3 + 16) * 32 + l3 + 16 + 1] = i3; } } } } } } } int l2 = surroundings[16912]; if (l2 >= 0) { worldIn.setBlockState(pos, state.withProperty(CHECK_DECAY, false), 4); } else { destroy(worldIn, pos); } } } } private void destroy(World worldIn, BlockPos pos) { dropBlockAsItem(worldIn, pos, worldIn.getBlockState(pos), 0); worldIn.setBlockToAir(pos); } @Override protected ItemStack createStackedBlock(@Nonnull IBlockState state) { return new ItemStack(this, 1, getEnumFromState(state).ordinal()); } @Override public IBlockState getStateFromMeta(int meta) { return this.getDefaultState().withProperty(property, getEnumFromMeta(meta)).withProperty(DECAYABLE, (meta & 4) == 0).withProperty(CHECK_DECAY, (meta & 8) > 0); } @Override public int damageDropped(IBlockState state) { return super.getMetaFromState(state); } @Override public int getMetaFromState(IBlockState state) { int i = 0; i = i | super.getMetaFromState(state); if (!(state.getValue(DECAYABLE))) { i |= 4; } if (state.getValue(CHECK_DECAY)) { i |= 8; } return i; } @SuppressWarnings("deprecation") @SideOnly(Side.CLIENT) @Override public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { if (worldIn.isRainingAt(pos.up()) && !worldIn.getBlockState(pos.down()).isFullyOpaque() && rand.nextInt(15) == 1) { double d0 = (double) ((float) pos.getX() + rand.nextFloat()); double d1 = (double) pos.getY() - 0.05D; double d2 = (double) ((float) pos.getZ() + rand.nextFloat()); worldIn.spawnParticle(EnumParticleTypes.DRIP_WATER, d0, d1, d2, 0.0D, 0.0D, 0.0D); } } @Override public int quantityDropped(Random random) { return 0; } @Override @Nullable public Item getItemDropped(IBlockState state, Random rand, int fortune) { return Item.getItemFromBlock(Blocks.SAPLING); } @Override public boolean isOpaqueCube(IBlockState state) { return false; } @SideOnly(Side.CLIENT) public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.CUTOUT_MIPPED; } @Override public boolean isVisuallyOpaque() { return false; } @Override public boolean isShearable(ItemStack item, IBlockAccess world, BlockPos pos) { return true; } @Override public boolean isLeaves(IBlockState state, IBlockAccess world, BlockPos pos) { return true; } @Override public void beginLeavesDecay(IBlockState state, World world, BlockPos pos) { if (!state.getValue(CHECK_DECAY)) { world.setBlockState(pos, state.withProperty(CHECK_DECAY, true), 4); } } @SideOnly(Side.CLIENT) @Override @SuppressWarnings("deprecation") public boolean shouldSideBeRendered(IBlockState blockState, @Nonnull IBlockAccess blockAccess, @Nonnull BlockPos pos, EnumFacing side) { return !(!MCClientHelper.getMinecraft().gameSettings.fancyGraphics && blockAccess.getBlockState(pos.offset(side)).getBlock() == this) && super.shouldSideBeRendered(blockState, blockAccess, pos, side); } @Override public List<ItemStack> onSheared(ItemStack item, IBlockAccess world, BlockPos pos, int fortune) { return Lists.newArrayList(new ItemStack(this, 1, super.getMetaFromState(world.getBlockState(pos)))); } @SideOnly(Side.CLIENT) @Override public void registerModels(Item item, String name) { ModelLoader.setCustomStateMapper(this, new StateMap.Builder().ignore(CHECK_DECAY, DECAYABLE).build()); super.registerModels(item, name); } }