package net.minecraft.block; import java.util.Random; 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.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.dispenser.BehaviorDefaultDispenseItem; import net.minecraft.dispenser.IBehaviorDispenseItem; import net.minecraft.dispenser.IBlockSource; import net.minecraft.dispenser.IPosition; import net.minecraft.dispenser.PositionImpl; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.InventoryHelper; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.stats.StatList; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityDispenser; import net.minecraft.tileentity.TileEntityDropper; import net.minecraft.util.EnumBlockRenderType; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.RegistryDefaulted; import net.minecraft.world.World; public class BlockDispenser extends BlockContainer { public static final PropertyDirection FACING = BlockDirectional.FACING; public static final PropertyBool TRIGGERED = PropertyBool.create("triggered"); /** Registry for all dispense behaviors. */ public static final RegistryDefaulted DISPENSE_BEHAVIOR_REGISTRY = new RegistryDefaulted(new BehaviorDefaultDispenseItem()); protected Random rand = new Random(); protected BlockDispenser() { super(Material.ROCK); this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(TRIGGERED, Boolean.valueOf(false))); this.setCreativeTab(CreativeTabs.REDSTONE); } /** * How many world ticks before ticking */ public int tickRate(World worldIn) { return 4; } /** * Called after the block is set in the Chunk data, but before the Tile Entity is set */ public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) { super.onBlockAdded(worldIn, pos, state); this.setDefaultDirection(worldIn, pos, state); } private void setDefaultDirection(World worldIn, BlockPos pos, IBlockState state) { if (!worldIn.isRemote) { EnumFacing enumfacing = (EnumFacing)state.getValue(FACING); boolean flag = worldIn.getBlockState(pos.north()).isFullBlock(); boolean flag1 = worldIn.getBlockState(pos.south()).isFullBlock(); if (enumfacing == EnumFacing.NORTH && flag && !flag1) { enumfacing = EnumFacing.SOUTH; } else if (enumfacing == EnumFacing.SOUTH && flag1 && !flag) { enumfacing = EnumFacing.NORTH; } else { boolean flag2 = worldIn.getBlockState(pos.west()).isFullBlock(); boolean flag3 = worldIn.getBlockState(pos.east()).isFullBlock(); if (enumfacing == EnumFacing.WEST && flag2 && !flag3) { enumfacing = EnumFacing.EAST; } else if (enumfacing == EnumFacing.EAST && flag3 && !flag2) { enumfacing = EnumFacing.WEST; } } worldIn.setBlockState(pos, state.withProperty(FACING, enumfacing).withProperty(TRIGGERED, Boolean.valueOf(false)), 2); } } /** * Called when the block is right clicked by a player. */ public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { if (worldIn.isRemote) { return true; } else { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof TileEntityDispenser) { playerIn.displayGUIChest((TileEntityDispenser)tileentity); if (tileentity instanceof TileEntityDropper) { playerIn.addStat(StatList.DROPPER_INSPECTED); } else { playerIn.addStat(StatList.DISPENSER_INSPECTED); } } return true; } } protected void dispense(World worldIn, BlockPos pos) { BlockSourceImpl blocksourceimpl = new BlockSourceImpl(worldIn, pos); TileEntityDispenser tileentitydispenser = (TileEntityDispenser)blocksourceimpl.getBlockTileEntity(); if (tileentitydispenser != null) { int i = tileentitydispenser.getDispenseSlot(); if (i < 0) { worldIn.playEvent(1001, pos, 0); } else { ItemStack itemstack = tileentitydispenser.getStackInSlot(i); IBehaviorDispenseItem ibehaviordispenseitem = this.getBehavior(itemstack); if (ibehaviordispenseitem != IBehaviorDispenseItem.DEFAULT_BEHAVIOR) { tileentitydispenser.setInventorySlotContents(i, ibehaviordispenseitem.dispense(blocksourceimpl, itemstack)); } } } } protected IBehaviorDispenseItem getBehavior(ItemStack stack) { return DISPENSE_BEHAVIOR_REGISTRY.getObject(stack.getItem()); } /** * Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor * change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid * block, etc. */ public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) { boolean flag = worldIn.isBlockPowered(pos) || worldIn.isBlockPowered(pos.up()); boolean flag1 = ((Boolean)state.getValue(TRIGGERED)).booleanValue(); if (flag && !flag1) { worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn)); worldIn.setBlockState(pos, state.withProperty(TRIGGERED, Boolean.valueOf(true)), 4); } else if (!flag && flag1) { worldIn.setBlockState(pos, state.withProperty(TRIGGERED, Boolean.valueOf(false)), 4); } } public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) { if (!worldIn.isRemote) { this.dispense(worldIn, pos); } } /** * Returns a new instance of a block's tile entity class. Called on placing the block. */ public TileEntity createNewTileEntity(World worldIn, int meta) { return new TileEntityDispenser(); } /** * Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the * IBlockstate */ public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) { return this.getDefaultState().withProperty(FACING, EnumFacing.getDirectionFromEntityLiving(pos, placer)).withProperty(TRIGGERED, Boolean.valueOf(false)); } /** * Called by ItemBlocks after a block is set in the world, to allow post-place logic */ public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { worldIn.setBlockState(pos, state.withProperty(FACING, EnumFacing.getDirectionFromEntityLiving(pos, placer)), 2); if (stack.hasDisplayName()) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof TileEntityDispenser) { ((TileEntityDispenser)tileentity).setCustomName(stack.getDisplayName()); } } } /** * Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated */ public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof TileEntityDispenser) { InventoryHelper.dropInventoryItems(worldIn, pos, (TileEntityDispenser)tileentity); worldIn.updateComparatorOutputLevel(pos, this); } super.breakBlock(worldIn, pos, state); } /** * Get the position where the dispenser at the given Coordinates should dispense to. */ public static IPosition getDispensePosition(IBlockSource coords) { EnumFacing enumfacing = (EnumFacing)coords.getBlockState().getValue(FACING); double d0 = coords.getX() + 0.7D * (double)enumfacing.getFrontOffsetX(); double d1 = coords.getY() + 0.7D * (double)enumfacing.getFrontOffsetY(); double d2 = coords.getZ() + 0.7D * (double)enumfacing.getFrontOffsetZ(); return new PositionImpl(d0, d1, d2); } public boolean hasComparatorInputOverride(IBlockState state) { return true; } public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos) { return Container.calcRedstone(worldIn.getTileEntity(pos)); } /** * The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only, * LIQUID for vanilla liquids, INVISIBLE to skip all rendering */ public EnumBlockRenderType getRenderType(IBlockState state) { return EnumBlockRenderType.MODEL; } /** * Convert the given metadata into a BlockState for this Block */ public IBlockState getStateFromMeta(int meta) { return this.getDefaultState().withProperty(FACING, EnumFacing.getFront(meta & 7)).withProperty(TRIGGERED, Boolean.valueOf((meta & 8) > 0)); } /** * Convert the BlockState into the correct metadata value */ public int getMetaFromState(IBlockState state) { int i = 0; i = i | ((EnumFacing)state.getValue(FACING)).getIndex(); if (((Boolean)state.getValue(TRIGGERED)).booleanValue()) { i |= 8; } return i; } /** * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed * blockstate. */ public IBlockState withRotation(IBlockState state, Rotation rot) { return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING))); } /** * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed * blockstate. */ public IBlockState withMirror(IBlockState state, Mirror mirrorIn) { return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))); } protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, new IProperty[] {FACING, TRIGGERED}); } }