package game.block; import java.util.List; import game.collect.Lists; import game.entity.Entity; import game.entity.npc.EntityNPC; import game.entity.projectile.EntityArrow; import game.entity.types.EntityLiving; import game.init.SoundEvent; import game.item.CheatTab; import game.material.Material; import game.model.ModelRotation; import game.properties.IProperty; import game.properties.PropertyBool; import game.properties.PropertyDirection; import game.renderer.blockmodel.ModelBlock; import game.renderer.blockmodel.Transforms; import game.rng.Random; import game.world.BlockPos; import game.world.BoundingBox; import game.world.Facing; import game.world.IWorldAccess; import game.world.State; import game.world.World; import game.world.WorldServer; public class BlockButton extends Block { public static final PropertyDirection FACING = PropertyDirection.create("facing"); public static final PropertyBool POWERED = PropertyBool.create("powered"); public static final List BUTTONS = Lists.newArrayList(); private final boolean checkArrows; private final int onTime; private final String texture; public BlockButton(boolean arrows, int onTime, String texture) { super(Material.circuits); this.setDefaultState(this.getBaseState().withProperty(FACING, Facing.NORTH).withProperty(POWERED, Boolean.valueOf(false))); // this.setTickRandomly(true); this.setTab(CheatTab.tabTech); this.checkArrows = arrows; this.onTime = onTime; this.texture = texture; BUTTONS.add(this); } public BoundingBox getCollisionBoundingBox(World worldIn, BlockPos pos, State state) { return null; } /** * How many world ticks before ticking */ public int tickRate(World worldIn, BlockPos pos) { return this.onTime; } /** * Used to determine ambient occlusion and culling when rebuilding chunks for render */ public boolean isOpaqueCube() { return false; } public boolean isFullCube() { return false; } /** * Check whether this Block can be placed on the given side */ public boolean canPlaceBlockOnSide(World worldIn, BlockPos pos, Facing side) { return canPlaceButtonOn(worldIn, pos, side.getOpposite()); } public boolean canPlaceBlockAt(World worldIn, BlockPos pos) { for (Facing enumfacing : Facing.values()) { if (canPlaceButtonOn(worldIn, pos, enumfacing)) { return true; } } return false; } protected static boolean canPlaceButtonOn(World worldIn, BlockPos pos, Facing face) { BlockPos blockpos = pos.offset(face); return face == Facing.DOWN ? worldIn.isBlockSolid(blockpos) : worldIn.getState(blockpos).getBlock().isNormalCube(); } /** * Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the * IBlockstate */ public State onBlockPlaced(World worldIn, BlockPos pos, Facing facing, float hitX, float hitY, float hitZ, int meta, EntityLiving placer) { return canPlaceButtonOn(worldIn, pos, facing.getOpposite()) ? this.getState().withProperty(FACING, facing).withProperty(POWERED, Boolean.valueOf(false)) : this.getState().withProperty(FACING, Facing.DOWN).withProperty(POWERED, Boolean.valueOf(false)); } /** * Called when a neighboring block changes. */ public void onNeighborBlockChange(World worldIn, BlockPos pos, State state, Block neighborBlock) { if (this.checkForDrop(worldIn, pos, state) && !canPlaceButtonOn(worldIn, pos, ((Facing)state.getValue(FACING)).getOpposite())) { this.dropBlockAsItem(worldIn, pos, state, 0); worldIn.setBlockToAir(pos); } } private boolean checkForDrop(World worldIn, BlockPos pos, State state) { if (this.canPlaceBlockAt(worldIn, pos)) { return true; } else { this.dropBlockAsItem(worldIn, pos, state, 0); worldIn.setBlockToAir(pos); return false; } } public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos) { this.updateBlockBounds(worldIn.getState(pos)); } private void updateBlockBounds(State state) { Facing enumfacing = (Facing)state.getValue(FACING); boolean flag = ((Boolean)state.getValue(POWERED)).booleanValue(); float f = 0.25F; float f1 = 0.375F; float f2 = (float)(flag ? 1 : 2) / 16.0F; float f3 = 0.125F; float f4 = 0.1875F; switch (enumfacing) { case EAST: this.setBlockBounds(0.0F, 0.375F, 0.3125F, f2, 0.625F, 0.6875F); break; case WEST: this.setBlockBounds(1.0F - f2, 0.375F, 0.3125F, 1.0F, 0.625F, 0.6875F); break; case SOUTH: this.setBlockBounds(0.3125F, 0.375F, 0.0F, 0.6875F, 0.625F, f2); break; case NORTH: this.setBlockBounds(0.3125F, 0.375F, 1.0F - f2, 0.6875F, 0.625F, 1.0F); break; case UP: this.setBlockBounds(0.3125F, 0.0F, 0.375F, 0.6875F, 0.0F + f2, 0.625F); break; case DOWN: this.setBlockBounds(0.3125F, 1.0F - f2, 0.375F, 0.6875F, 1.0F, 0.625F); } } public boolean onBlockActivated(World worldIn, BlockPos pos, State state, EntityNPC playerIn, Facing side, float hitX, float hitY, float hitZ) { if (((Boolean)state.getValue(POWERED)).booleanValue()) { return true; } else { worldIn.setState(pos, state.withProperty(POWERED, Boolean.valueOf(true)), 3); worldIn.markBlockRangeForRenderUpdate(pos, pos); worldIn.playSound(SoundEvent.CLICK, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, 0.3F); this.notifyNeighbors(worldIn, pos, (Facing)state.getValue(FACING)); worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn, null)); return true; } } public void onBlockRemoved(WorldServer worldIn, BlockPos pos, State state) { if (((Boolean)state.getValue(POWERED)).booleanValue()) { this.notifyNeighbors(worldIn, pos, (Facing)state.getValue(FACING)); } super.onBlockRemoved(worldIn, pos, state); } public int getWeakPower(IWorldAccess worldIn, BlockPos pos, State state, Facing side) { return ((Boolean)state.getValue(POWERED)).booleanValue() ? 15 : 0; } public int getStrongPower(IWorldAccess worldIn, BlockPos pos, State state, Facing side) { return !((Boolean)state.getValue(POWERED)).booleanValue() ? 0 : (state.getValue(FACING) == side ? 15 : 0); } /** * Can this block provide power. Only wire currently seems to have this change based on its state. */ public boolean canProvidePower() { return true; } /** * Called randomly when setTickRandomly is set to true (used by e.g. crops to grow, etc.) */ public void randomTick(WorldServer worldIn, BlockPos pos, State state, Random random) { } public void updateTick(WorldServer worldIn, BlockPos pos, State state, Random rand) { // if (!worldIn.client) // { if (((Boolean)state.getValue(POWERED)).booleanValue()) { if (this.checkArrows) { this.checkForArrows(worldIn, pos, state); } else { worldIn.setState(pos, state.withProperty(POWERED, Boolean.valueOf(false))); this.notifyNeighbors(worldIn, pos, (Facing)state.getValue(FACING)); worldIn.playSound(SoundEvent.CLICK, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, 0.3F); worldIn.markBlockRangeForRenderUpdate(pos, pos); } } // } } /** * Sets the block's bounds for rendering it as an item */ public void setBlockBoundsForItemRender() { float f = 0.1875F; float f1 = 0.125F; float f2 = 0.125F; this.setBlockBounds(0.5F - f, 0.5F - f1, 0.5F - f2, 0.5F + f, 0.5F + f1, 0.5F + f2); } /** * Called When an Entity Collided with the Block */ public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, State state, Entity entityIn) { if (!worldIn.client) { if (this.checkArrows) { if (!((Boolean)state.getValue(POWERED)).booleanValue()) { this.checkForArrows(worldIn, pos, state); } } } } private void checkForArrows(World worldIn, BlockPos pos, State state) { this.updateBlockBounds(state); List list = worldIn.getEntitiesWithinAABB(EntityArrow.class, new BoundingBox((double)pos.getX() + this.minX, (double)pos.getY() + this.minY, (double)pos.getZ() + this.minZ, (double)pos.getX() + this.maxX, (double)pos.getY() + this.maxY, (double)pos.getZ() + this.maxZ)); boolean flag = !list.isEmpty(); boolean flag1 = ((Boolean)state.getValue(POWERED)).booleanValue(); if (flag && !flag1) { worldIn.setState(pos, state.withProperty(POWERED, Boolean.valueOf(true))); this.notifyNeighbors(worldIn, pos, (Facing)state.getValue(FACING)); worldIn.markBlockRangeForRenderUpdate(pos, pos); worldIn.playSound(SoundEvent.CLICK, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, 0.3F); } if (!flag && flag1) { worldIn.setState(pos, state.withProperty(POWERED, Boolean.valueOf(false))); this.notifyNeighbors(worldIn, pos, (Facing)state.getValue(FACING)); worldIn.markBlockRangeForRenderUpdate(pos, pos); worldIn.playSound(SoundEvent.CLICK, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, 0.3F); } if (flag) { worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn, null)); } } private void notifyNeighbors(World worldIn, BlockPos pos, Facing facing) { worldIn.notifyNeighborsOfStateChange(pos, this); worldIn.notifyNeighborsOfStateChange(pos.offset(facing.getOpposite()), this); } /** * Convert the given metadata into a BlockState for this Block */ public State getStateFromMeta(int meta) { Facing enumfacing; switch (meta & 7) { case 0: enumfacing = Facing.DOWN; break; case 1: enumfacing = Facing.EAST; break; case 2: enumfacing = Facing.WEST; break; case 3: enumfacing = Facing.SOUTH; break; case 4: enumfacing = Facing.NORTH; break; case 5: default: enumfacing = Facing.UP; } return this.getState().withProperty(FACING, enumfacing).withProperty(POWERED, Boolean.valueOf((meta & 8) > 0)); } /** * Convert the BlockState into the correct metadata value */ public int getMetaFromState(State state) { int i; switch ((Facing)state.getValue(FACING)) { case EAST: i = 1; break; case WEST: i = 2; break; case SOUTH: i = 3; break; case NORTH: i = 4; break; case UP: default: i = 5; break; case DOWN: i = 0; } if (((Boolean)state.getValue(POWERED)).booleanValue()) { i |= 8; } return i; } protected IProperty[] getProperties() { return new IProperty[] {FACING, POWERED}; } public boolean isMagnetic() { return this.onTime == 10; } public Transforms getTransform() { return Transforms.BUTTON; } private static ModelRotation getRotation(Facing face) { switch(face) { case DOWN: return ModelRotation.X180_Y0; case UP: default: return ModelRotation.X0_Y0; case NORTH: return ModelRotation.X90_Y0; case SOUTH: return ModelRotation.X90_Y180; case WEST: return ModelRotation.X90_Y270; case EAST: return ModelRotation.X90_Y90; } } public String getTexture() { return this.texture; } public ModelBlock getModel(String name, State state) { boolean pressed = state.getValue(POWERED); return new ModelBlock(this.texture).add(5, 0, 6, 11, pressed ? 1 : 2, 10) .d().uv(5, 6, 11, 10).u().uv(5, 10, 11, 6).noCull() .ns().uv(5, pressed ? 15 : 14, 11, 16).noCull().we().uv(6, pressed ? 15 : 14, 10, 16).noCull() .rotate(getRotation(state.getValue(FACING))); } }