From 510ecab1acfc4dcdfc19773786d796a345069b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Mon, 4 Jul 2016 15:53:24 +0200 Subject: [PATCH] Throne, very partial 2-high block with state (i.e. direction and colour) stored partially on both blocks. Placement, removal by player and automatic removal work, as does sitting on it. Everything display-related is missing. --- src/java/mmm/deco/DThroneBlock.java | 317 ++++++++++++++++++++++++ src/java/mmm/deco/DecorativeBlocks.java | 4 + 2 files changed, 321 insertions(+) create mode 100644 src/java/mmm/deco/DThroneBlock.java diff --git a/src/java/mmm/deco/DThroneBlock.java b/src/java/mmm/deco/DThroneBlock.java new file mode 100644 index 0000000..0238912 --- /dev/null +++ b/src/java/mmm/deco/DThroneBlock.java @@ -0,0 +1,317 @@ +package mmm.deco; + + +import java.util.List; + +import mmm.utils.I_UBlockSeat; +import mmm.utils.I_UColoredBlock; +import mmm.utils.I_USupportBlock; +import mmm.utils.URegistry; +import mmm.utils.USeat; +import net.minecraft.block.Block; +import net.minecraft.block.BlockHorizontal; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.EnumPushReaction; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.properties.PropertyDirection; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +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; + + + +public class DThroneBlock + extends Block + implements I_UColoredBlock , I_UBlockSeat +{ + + public static final PropertyDirection FACING; + public static final PropertyBool IS_TOP; + public static final PropertyEnum< EnumDyeColor > COLOR; + + private static boolean dropping = false; + + static { + FACING = BlockHorizontal.FACING; + IS_TOP = PropertyBool.create( "is_top" ); + COLOR = PropertyEnum.< EnumDyeColor > create( "color" , EnumDyeColor.class ); + } + + public final E_DWoodType woodType; + + + public DThroneBlock( final E_DWoodType woodType ) + { + super( Material.WOOD ); + this.woodType = woodType; + + this.setCreativeTab( CreativeTabs.DECORATIONS ); + URegistry.setIdentifiers( this , "deco" , "throne" , woodType.suffix ); + + this.setDefaultState( this.blockState.getBaseState( ) // + .withProperty( DThroneBlock.FACING , EnumFacing.NORTH ) // + .withProperty( DThroneBlock.IS_TOP , false ) // + .withProperty( DThroneBlock.COLOR , EnumDyeColor.WHITE ) ); + + this.lightOpacity = 0; + this.translucent = false; + this.fullBlock = false; + this.blockHardness = 2.5f; + this.blockResistance = 12.5f; + this.blockSoundType = SoundType.LADDER; + this.enableStats = false; + + this.setHarvestLevel( "axe" , 0 ); + } + + + // ************************************************************************************************* + // BLOCK STATE + // ************************************************************************************************* + + @Override + protected BlockStateContainer createBlockState( ) + { + return new BlockStateContainer( this , new IProperty[] { + DThroneBlock.FACING , DThroneBlock.IS_TOP , DThroneBlock.COLOR + } ); + } + + + @Override + public IBlockState getStateFromMeta( final int meta ) + { + final boolean isTop = ( meta & 1 ) == 1; + IBlockState bs = this.getDefaultState( ).withProperty( DThroneBlock.IS_TOP , isTop ); + if ( isTop ) { + bs = bs.withProperty( DThroneBlock.COLOR , EnumDyeColor.byMetadata( meta >> 1 ) ); + } else { + bs = bs.withProperty( DThroneBlock.COLOR , EnumDyeColor.byMetadata( meta >> 1 & 1 ) ) // + .withProperty( DThroneBlock.FACING , EnumFacing.getHorizontal( meta >> 2 ) ); + } + return bs; + } + + + @Override + public int getMetaFromState( final IBlockState state ) + { + final boolean isTop = state.getValue( DThroneBlock.IS_TOP ); + int meta = isTop ? 1 : 0; + if ( isTop ) { + meta |= ( state.getValue( DThroneBlock.COLOR ).getMetadata( ) & 0x07 ) << 1; + } else { + meta |= ( state.getValue( DThroneBlock.COLOR ).getMetadata( ) & 0x01 ) << 1 // + | state.getValue( DThroneBlock.FACING ).getHorizontalIndex( ) << 2 // + ; + } + return meta; + } + + + @Override + public IBlockState getActualState( final IBlockState state , final IBlockAccess worldIn , final BlockPos pos ) + { + final boolean isTop = state.getValue( DThroneBlock.IS_TOP ); + + final IBlockState top; + final IBlockState bottom; + if ( isTop ) { + top = state; + bottom = worldIn.getBlockState( pos.down( ) ); + } else { + top = worldIn.getBlockState( pos.up( ) ); + bottom = state; + } + if ( top.getBlock( ) != this || bottom.getBlock( ) != this ) { + return this.getDefaultState( ); + } + + final EnumDyeColor cTop = top.getValue( DThroneBlock.COLOR ); + final EnumDyeColor cBottom = bottom.getValue( DThroneBlock.COLOR ); + final EnumDyeColor color = EnumDyeColor.byMetadata( cBottom.getMetadata( ) << 3 | cTop.getMetadata( ) ); + final EnumFacing facing = bottom.getValue( DThroneBlock.FACING ); + + return state.withProperty( DThroneBlock.FACING , facing )// + .withProperty( DThroneBlock.COLOR , color ); + } + + + // ************************************************************************************************* + // BLOCK PLACEMENT + // ************************************************************************************************* + + @Override + public boolean canPlaceBlockAt( final World worldIn , final BlockPos pos ) + { + return pos.getY( ) < worldIn.getHeight( ) - 1 && super.canPlaceBlockAt( worldIn , pos ) + && super.canPlaceBlockAt( worldIn , pos.up( ) ) && I_USupportBlock.check( worldIn , pos ); + } + + + @Override + public void onBlockPlacedBy( final World worldIn , final BlockPos pos , final IBlockState state , + final EntityLivingBase placer , final ItemStack stack ) + { + final int dmg = stack.getItemDamage( ); + final EnumDyeColor color = EnumDyeColor.byMetadata( dmg ); + final EnumDyeColor topColor = EnumDyeColor.byMetadata( color.getMetadata( ) & 7 ); + final EnumDyeColor bottomColor = EnumDyeColor.byMetadata( color.getMetadata( ) >> 3 ); + + final IBlockState nState = this.getDefaultState( ) // + .withProperty( DThroneBlock.FACING , placer.getHorizontalFacing( ) ); + worldIn.setBlockState( pos , nState.withProperty( DThroneBlock.COLOR , bottomColor ) , 6 ); + worldIn.setBlockState( pos.up( ) , // + nState.withProperty( DThroneBlock.IS_TOP , true ) // + .withProperty( DThroneBlock.COLOR , topColor ) , + 6 ); + } + + + // ************************************************************************************************* + // BLOCK REMOVAL AND PICKING + // ************************************************************************************************* + + @Override + public ItemStack getPickBlock( final IBlockState state , final RayTraceResult target , final World world , + final BlockPos pos , final EntityPlayer player ) + { + final Item item = Item.getItemFromBlock( this ); + return item == null + ? null + : new ItemStack( item , 1 , this.damageDropped( state.getActualState( world , pos ) ) ); + } + + + @Override + public boolean removedByPlayer( final IBlockState state , final World world , final BlockPos pos , + final EntityPlayer player , final boolean willHarvest ) + { + if ( willHarvest ) { + return true; + } + + this.removeOtherBlock( state , world , pos ); + return super.removedByPlayer( state , world , pos , player , willHarvest ); + } + + + @Override + public void dropBlockAsItemWithChance( final World worldIn , final BlockPos pos , final IBlockState state , + final float chance , final int fortune ) + { + if ( !worldIn.isRemote && !worldIn.restoringBlockSnapshots ) { + super.dropBlockAsItemWithChance( worldIn , pos , state , chance , fortune ); + this.removeOtherBlock( state , worldIn , pos ); + try { + throw new RuntimeException( "fart fart fart " + pos ); + } catch ( final RuntimeException e ) { + e.printStackTrace( ); + } + } + } + + + @Override + public void harvestBlock( final World worldIn , final EntityPlayer player , final BlockPos pos , + final IBlockState state , final TileEntity te , final ItemStack tool ) + { + super.harvestBlock( worldIn , player , pos , state , te , tool ); + this.removedByPlayer( state , worldIn , pos , player , false ); + } + + + private void removeOtherBlock( final IBlockState state , final World world , final BlockPos pos ) + { + DThroneBlock.dropping = true; + final boolean isTop = state.getValue( DThroneBlock.IS_TOP ); + final BlockPos otherPos = isTop ? pos.down( ) : pos.up( ); + if ( world.getBlockState( otherPos ).getBlock( ) == this ) { + world.setBlockToAir( otherPos ); + } + DThroneBlock.dropping = false; + } + + + @Override + public List< ItemStack > getDrops( final IBlockAccess world , final BlockPos pos , final IBlockState state , + final int fortune ) + { + return super.getDrops( world , pos , state.getActualState( world , pos ) , fortune ); + } + + + @Override + public int damageDropped( final IBlockState state ) + { + return state.getValue( DThroneBlock.COLOR ).getMetadata( ); + } + + + // ************************************************************************************************* + // AUTOMATIC REMOVAL + // ************************************************************************************************* + + @Override + public void neighborChanged( final IBlockState state , final World worldIn , final BlockPos pos , + final Block blockIn ) + { + if ( ! ( state.getValue( DThroneBlock.IS_TOP ) || DThroneBlock.dropping ) ) { + I_USupportBlock.dropIfUnsupported( state , worldIn , pos , this ); + } + } + + + @Override + public EnumPushReaction getMobilityFlag( final IBlockState state ) + { + return EnumPushReaction.DESTROY; + } + + + // ************************************************************************************************* + // INTERACTION + // ************************************************************************************************* + + @Override + public boolean onBlockActivated( final World worldIn , final BlockPos pos , final IBlockState state , + final EntityPlayer playerIn , final EnumHand hand , final ItemStack heldItem , final EnumFacing side , + final float hitX , final float hitY , final float hitZ ) + { + BlockPos p; + if ( state.getValue( DThroneBlock.IS_TOP ) ) { + p = pos.down( ); + } else { + p = pos; + } + return USeat.sit( worldIn , p , playerIn , 0.25 ); + } + + + @Override + @SideOnly( Side.CLIENT ) + public void getSubBlocks( final Item itemIn , final CreativeTabs tab , final List< ItemStack > list ) + { + for ( int i = 0 ; i < 16 ; ++i ) { + list.add( new ItemStack( itemIn , 1 , i ) ); + } + } + +} diff --git a/src/java/mmm/deco/DecorativeBlocks.java b/src/java/mmm/deco/DecorativeBlocks.java index 3d6dc40..f15b440 100644 --- a/src/java/mmm/deco/DecorativeBlocks.java +++ b/src/java/mmm/deco/DecorativeBlocks.java @@ -56,6 +56,10 @@ public class DecorativeBlocks URegistry.addBlock( CHAIR_JUNGLE = new DChair( E_DWoodType.JUNGLE ) ); URegistry.addBlock( CHAIR_DARK_OAK = new DChair( E_DWoodType.DARK_OAK ) ); URegistry.addBlock( CHAIR_ACACIA = new DChair( E_DWoodType.ACACIA ) ); + + // XXX FIXME LOL TEST!!!! + final DThroneBlock tb = new DThroneBlock( E_DWoodType.OAK ); + URegistry.addBlock( tb ); }