package slimeknights.tconstruct.shared.block; import com.google.common.collect.ImmutableMap; import net.minecraft.block.Block; import net.minecraft.block.BlockLiquid; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.properties.PropertyDirection; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.List; import java.util.Random; import javax.annotation.Nonnull; import slimeknights.tconstruct.gadgets.TinkerGadgets; import slimeknights.tconstruct.gadgets.item.ItemThrowball; public class BlockGlow extends Block { public static PropertyDirection FACING = PropertyDirection.create("facing"); public BlockGlow() { super(Material.CIRCUITS); this.setTickRandomly(true); this.setHardness(0.0F); this.setLightLevel(0.9375F); this.setSoundType(SoundType.CLOTH); this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.DOWN)); } @Nonnull @Override protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, FACING); } @Override public int getMetaFromState(IBlockState state) { return state.getValue(FACING).getIndex(); } @Nonnull @Override public IBlockState getStateFromMeta(int meta) { return getDefaultState().withProperty(FACING, EnumFacing.getFront(meta)); } @Nonnull @Override public ItemStack getPickBlock(@Nonnull IBlockState state, RayTraceResult target, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player) { // only use the glowball for pickblock if it was loaded (which happens when gadgets is loaded) if(TinkerGadgets.throwball != null) { return new ItemStack(TinkerGadgets.throwball, 1, ItemThrowball.ThrowballType.GLOW.ordinal()); } // if unavailable, just return nothing, Minecraft will just not do anything on pick block return null; } @Override public void neighborChanged(IBlockState state, World world, BlockPos pos, Block blockIn) { // if the location is not stable, break the block if(!canBlockStay(world, pos, state.getValue(FACING))) { world.setBlockToAir(pos); } super.neighborChanged(state, world, pos, blockIn); } /** * Determines if a block side can contain a glow. * Returns true if the block side is solid and the block at the given BlockPos is not a liquid */ protected boolean canBlockStay(World world, BlockPos pos, EnumFacing facing) { BlockPos placedOn = pos.offset(facing); boolean isSolidSide = world.getBlockState(placedOn).isSideSolid(world, placedOn, facing.getOpposite()); boolean isLiquid = world.getBlockState(pos).getBlock() instanceof BlockLiquid ; return !isLiquid && isSolidSide; } /** * Adds a glow block to the world, setting its facing based on the surroundings if not valid * Used since onBlockPlaced is not called when placing via World.setBlockState * * @param world World object * @param pos Position to place the block * @param facing Preferred facing, if the facing is not valid another one may be chosen * @return A boolean stating whether a glow was placed. * Will be false if the block position contains a non-replacable block or none of the surrounding blocks has a solid face */ public boolean addGlow(World world, BlockPos pos, EnumFacing facing) { // only place the block if the current block at the location is replacable (eg, air, tall grass, etc.) IBlockState oldState = world.getBlockState(pos); if(oldState.getBlock().getMaterial(oldState).isReplaceable()) { // if the location is valid, place the block directly if(this.canBlockStay(world, pos, facing)) { if(!world.isRemote) { world.setBlockState(pos, getDefaultState().withProperty(FACING, facing)); } return true; } // otherwise, try and place it facing a different way else { for(EnumFacing enumfacing : EnumFacing.VALUES) { if(this.canBlockStay(world, pos, enumfacing)) { if(!world.isRemote) { world.setBlockState(pos, getDefaultState().withProperty(FACING, enumfacing)); } return true; } } } } return false; } @Override public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { super.randomDisplayTick(stateIn, worldIn, pos, rand); } /* Bounds */ private static final ImmutableMap<EnumFacing, AxisAlignedBB> BOUNDS; static { ImmutableMap.Builder<EnumFacing, AxisAlignedBB> builder = ImmutableMap.builder(); builder.put(EnumFacing.UP, new AxisAlignedBB(0.0D, 0.9375D, 0.0D, 1.0D, 1.0D, 1.0D)); builder.put(EnumFacing.DOWN, new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D)); builder.put(EnumFacing.NORTH, new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 0.0625D)); builder.put(EnumFacing.SOUTH, new AxisAlignedBB(0.0D, 0.0D, 0.9375D, 1.0D, 1.0D, 1.0D)); builder.put(EnumFacing.EAST, new AxisAlignedBB(0.9375D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D)); builder.put(EnumFacing.WEST, new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0625D, 1.0D, 1.0D)); BOUNDS = builder.build(); } @Nonnull @Override public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { return BOUNDS.get(state.getValue(FACING)); } @Override public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, @Nonnull World worldIn, @Nonnull BlockPos pos) { return NULL_AABB; } @Override public boolean isOpaqueCube(IBlockState state) { return false; } @Override public boolean isFullCube(IBlockState state) { return false; } @Nonnull @Override @SideOnly(Side.CLIENT) public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.TRANSLUCENT; } @Override public Item getItemDropped(IBlockState state, Random rand, int fortune) { return null; } @Override public void getSubBlocks(@Nonnull Item itemIn, CreativeTabs tab, List<ItemStack> list) { } }