public final class References {

	public static final String CLIENT_PROXY_CLASS = "tk.cth451.transitrailmod.proxy.ClientProxy";
	public static final String MOD_ID = "transitrailmod";
	public static final String MOD_NAME = "Transit Rail Mod";
	public static final String SERVER_PROXY_CLASS = "tk.cth451.transitrailmod.proxy.CommonProxy";
	public static final String VERSION = "0.10";
} public class ClosedPlatformDoorBlock extends ClosedPlatformBlock {
	
	public static final PropertyBool POWERED = PropertyBool.create("powered");
	public static final PropertyBool LEFT = PropertyBool.create("left"); 
	
	public ClosedPlatformDoorBlock(Material materialIn) {
		super(Material.GLASS);
		this.setUnlocalizedName("closed_platform_door_block");
		this.setDefaultState(getDefaultState()
				.withProperty(FACING, EnumFacing.NORTH)
				.withProperty(UPPER, false)
				.withProperty(POWERED, true)
				.withProperty(LEFT, false));
	}
	
	// Properties
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumFacing facing = (EnumFacing) state.getValue(FACING);
		boolean isOpen = (Boolean) state.getValue(POWERED);
		boolean leftOrNot = this.isLeft(source, pos, facing);
		if (!isOpen) {
			if (facing == EnumFacing.NORTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.125F);
			} else if (facing == EnumFacing.EAST) {
				return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
			} else if (facing == EnumFacing.SOUTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F);
			} else { // if (facing == EnumFacing.WEST) 
				return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 1.0F, 1.0F);
			}
		} else if (leftOrNot) {
			if (facing == EnumFacing.NORTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 1.0F, 0.125F);
			} else if (facing == EnumFacing.EAST) {
				return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 1.0F, 0.125F);
			} else if (facing == EnumFacing.SOUTH) {
				return new AxisAlignedBB(0.875F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F);
			} else { // if (facing == EnumFacing.WEST) 
				return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 0.125F, 1.0F, 1.0F);
			}
		} else {
			if (facing == EnumFacing.NORTH) {
				return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 1.0F, 0.125F);
			} else if (facing == EnumFacing.EAST) {
				return new AxisAlignedBB(0.875F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F);
			} else if (facing == EnumFacing.SOUTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 0.125F, 1.0F, 1.0F);
			} else  { // if (facing == EnumFacing.WEST) 
				return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 1.0F, 0.125F);
			}
		}
	}
	
	// BlockStates
	@Override
	public BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {FACING, UPPER, POWERED, LEFT});
	}
	
	@Override
	public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos) {
		EnumFacing direc = (EnumFacing) state.getValue(FACING);
		return state.withProperty(UPPER, isUpper(worldIn, pos)).withProperty(LEFT, isLeft(worldIn, pos, direc));
	}
	
	// meta: 0211
	// 2: powered
	// 11 : facing
	@Override
	public int getMetaFromState(IBlockState state) {
		int mFacing = ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
		int mPowered = (Boolean) state.getValue(POWERED) ? 1 : 0;
		return mPowered *4 + mFacing;
	}
	
	// meta: 0211
	// 2: powered
	// 11 : facing
	@Override
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing pFacing = EnumFacing.getHorizontal(meta % 4); 
		boolean pPowered = meta / 4 == 1;
		return this.getDefaultState().withProperty(FACING, pFacing).withProperty(POWERED, pPowered);
	}
	
	public boolean isLeft(IBlockAccess worldIn, BlockPos pos, EnumFacing direc){
		return worldIn.getBlockState(pos.offset(direc.rotateY())).getBlock().equals(this);
	}
	
	// Interactions	
	@SideOnly(Side.CLIENT)
	public Item getItem(World worldIn, BlockPos pos) {
		return this.getItem();
	}
	
	private Item getItem() {
		return ModItems.closed_platform_door_item;
	}
	
	@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune)	{
		return this.getItem();
	}
	
	// Redstone
	@Override
	public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) {
		boolean flagUpper = isUpper(worldIn, pos);
		// check whether the block triggered is the upper part
		
		BlockPos pos1 = flagUpper ? pos.down() : pos.up();
		// get the other part
		
		Boolean flagOkay = (worldIn.getBlockState(pos1).getBlock() == this);
		// check whether the other part gets destroyed
		if (flagOkay) {
			// if not triggered by player breaking parts, update redstone status
			Boolean flag = (Boolean) worldIn.getBlockState(pos.up()).getValue(POWERED);
			if (flag != (Boolean) state.getValue(POWERED)) {
				worldIn.setBlockState(pos, state.withProperty(POWERED, Boolean.valueOf(flag)), 2);
				worldIn.markBlockRangeForRenderUpdate(pos, pos);
			}
			super.neighborChanged(state, worldIn, pos1, blockIn);
		} else {
			this.destroyParts(flagUpper, worldIn, pos);
		}
	}
} public class ClosedPlatformPanelBlock extends ClosedPlatformBlock {
	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
	
	public ClosedPlatformPanelBlock(Material materialIn) {
		super(Material.GLASS);
		this.setUnlocalizedName("closed_platform_panel_block");
		this.setDefaultState(getDefaultState().withProperty(FACING, EnumFacing.NORTH).withProperty(UPPER, false));
	}
	
	// Properties
	
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumFacing facing = (EnumFacing) source.getBlockState(pos).getValue(FACING);
		if (facing == EnumFacing.NORTH) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.125F, 1.0F, 1.0F, 0.25F);
		} else if (facing == EnumFacing.EAST) {
			return new AxisAlignedBB(0.75F, 0.0F, 0.0F, 0.875F, 1.0F, 1.0F);
		} else if (facing == EnumFacing.SOUTH) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.75F, 1.0F, 1.0F, 0.875F);
		} else { // if (facing == EnumFacing.WEST) {
			return new AxisAlignedBB(0.125F, 0.0F, 0.0F, 0.25F, 1.0F, 1.0F);
		}
	}
	
	// Block State Methods
	@Override
	public BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {FACING, UPPER});
	}
	

	@Override
	public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos) {
		return state.withProperty(UPPER, isUpper(worldIn, pos));
	}
	
	
	@Override
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) {
		return this.getDefaultState().withProperty(FACING, EnumFacing.getHorizontal(meta));
	}
	
	// Interactions
	@SideOnly(Side.CLIENT)
	public Item getItem(World worldIn, BlockPos pos)
	{
		return this.getItem();
	}
	
	private Item getItem() {
		return ModItems.closed_platform_panel_item;
	}
	
	@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune)
	{
		return this.getItem();
	}
	
	@Override
	public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) {
		boolean flagUpper = isUpper(worldIn, pos);
		// check whether the block triggered is the upper part
		BlockPos pos1 = flagUpper ? pos.down() : pos.up();
		// get the other part
		Boolean flagOkay = (worldIn.getBlockState(pos1).getBlock() == this);
		// check whether the other part gets destroyed
		if (!flagOkay) {
			this.destroyParts(flagUpper, worldIn, pos);
		}
	}
} public class ClosedPlatformTop extends CustomDirectionBlock {

	public static final PropertyBool POWERED = PropertyBool.create("powered");
	
	public ClosedPlatformTop(Material materialIn) {
		super(Material.IRON);
		this.setLightLevel(1F);
		// Full brightness
		this.setUnlocalizedName("closed_platform_top");
		this.setDefaultState(this.blockState.getBaseState()
				.withProperty(FACING, EnumFacing.NORTH)
				.withProperty(POWERED, false));
	}

	// Properties
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumFacing facing = (EnumFacing) source.getBlockState(pos).getValue(FACING);
		if (facing == EnumFacing.NORTH) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.25F);
		} else if (facing == EnumFacing.EAST) {
			return new AxisAlignedBB(0.75F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
		} else if (facing == EnumFacing.SOUTH) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.75F, 1.0F, 1.0F, 1.0F);
		} else { // if (facing == EnumFacing.WEST) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.25F, 1.0F, 1.0F);
		}
	}

	@Override
	public boolean isTranslucent(IBlockState state) {
		return true;
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}

	@Override
	public boolean canProvidePower(IBlockState state) {
		return true;
	}

	// Block state related
	// meta: 0211
	// 2: powered
	// 11 : facing
	@Override
	public int getMetaFromState(IBlockState state) {
		int mFacing = ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
		int mPowered = (Boolean) state.getValue(POWERED) ? 1 : 0;
		return mPowered * 4 + mFacing;
	}

	@Override
	public BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] { FACING, POWERED });
	}

	// meta: 0211
	// 2: powered
	// 11 : facing
	@Override
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing pFacing = EnumFacing.getHorizontal(meta % 4);
		boolean pPowered = meta / 4 == 1;
		return this.getDefaultState().withProperty(FACING, pFacing).withProperty(POWERED, pPowered);
	}

	// Interactions
	@Override
	public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) {
		// TODO: A dirty hack here.
		boolean isCreative = player.capabilities.isCreativeMode;

		if (this.getBlockBelow(world, pos).getUnlocalizedName().equals("tile.closed_platform_door_block")
				|| this.getBlockBelow(world, pos).getUnlocalizedName().equals("tile.closed_platform_panel_block")) {
			world.destroyBlock(pos.down(), !isCreative);
			world.setBlockToAir(pos.down(2));
			world.setBlockToAir(pos);
		} else {
			world.destroyBlock(pos, false);
		}
		return true;
	}

	@Override
	public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) {
		return false;
	}
	
	// Redstone
	@Override
	public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) {
		Boolean flag = worldIn.isBlockPowered(pos);
		if (flag != (Boolean) state.getValue(POWERED)) {
			worldIn.setBlockState(pos, state.withProperty(POWERED, Boolean.valueOf(flag)), 2);
			worldIn.markBlockRangeForRenderUpdate(pos, pos);
			worldIn.notifyBlockOfStateChange(pos.down(), this);
		}
	}

	@Override
	public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) {
		if (side == EnumFacing.DOWN) {
			return (Boolean) blockState.getValue(POWERED) ? 15 : 0;
		} else {
			return 0;
		}
	}

	// When middle click, get the block below.
	@Override
	public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player) {
		Item item = null;
		Block blockBelow = this.getBlockBelow(world, pos);

		if (blockBelow == ModBlocks.closed_platform_door_block) {
			item = ModItems.closed_platform_door_item;
		} else if (blockBelow == ModBlocks.closed_platform_panel_block) {
			item = ModItems.closed_platform_panel_item;
		}

		if (item == null)
			return null;

		return new ItemStack(item, 1);
	}
	
	private Block getBlockBelow(IBlockAccess worldIn, BlockPos pos) {
		return worldIn.getBlockState(pos.down()).getBlock();
	}
} public class FluorescentLamp extends CustomDirectionBlock {
	
	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
	public static final PropertyEnum ATTACH = PropertyEnum.create("attach", EnumAttachTo.class);
	
	public FluorescentLamp(Material materialIn) {
		super(Material.GLASS);
		this.setUnlocalizedName("fluorescent_lamp");
		this.setLightLevel(1F);
		this.setCreativeTab(TransitRailMod.tabTransitRail);
		this.setDefaultState(getDefaultState()
				.withProperty(ATTACH, EnumAttachTo.WALL)
				.withProperty(FACING, EnumFacing.NORTH));
	}
	
	// Properties
	@Override
	public boolean isTranslucent(IBlockState state) {
		return true;
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public BlockRenderLayer getBlockLayer() {
		return BlockRenderLayer.CUTOUT;
	}
	
	// Block States
	@Override
	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {ATTACH, FACING});
	}
	
	// meta 1122
	// 11: ATTACH
	// 22: FACING
	@Override
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing pFacing = EnumFacing.getHorizontal(meta % 4);
		EnumAttachTo pAttach = EnumAttachTo.fromMeta(meta / 4);
		return this.getDefaultState().withProperty(ATTACH, pAttach).withProperty(FACING, pFacing);
	}
	
	@Override
	public int getMetaFromState(IBlockState state) {
		int mFacing = ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
		int mAttach = ((EnumAttachTo) state.getValue(ATTACH)).toMeta();
		return mAttach * 4 + mFacing;
	}
	
	public IBlockState getAttached (World worldIn, BlockPos pos, IBlockState state){
		boolean pAbove = worldIn.getBlockState(pos.down()).getBlock() == ModBlocks.fluorescent_lamp;
		boolean pPanel;
		if (worldIn.getBlockState(pos.down()).getBlock() == ModBlocks.wire_panel) {
			pPanel = !((Boolean) worldIn.getBlockState(pos.down()).getValue(WirePanel.SHUT));
		} else {
			pPanel = worldIn.getBlockState(pos.down()).getBlock() == ModBlocks.glass_fence;
		}
		
		if (pPanel || pAbove) {
			state = state.withProperty(ATTACH, EnumAttachTo.EXTENDING);
		} else {
			EnumFacing thisFacing = (EnumFacing) state.getValue(FACING);
			boolean pWall = worldIn.getBlockState(pos.offset(thisFacing)).getBlock().isSideSolid(state, worldIn, pos.offset(thisFacing), thisFacing.getOpposite());
			boolean pGround = worldIn.getBlockState(pos.down()).getBlock().isSideSolid(state, worldIn, pos.down(), EnumFacing.UP);
			boolean pCeiling = worldIn.getBlockState(pos.up()).getBlock().isSideSolid(state, worldIn, pos.up(), EnumFacing.DOWN);
			
			if (pWall) {
				state = state.withProperty(ATTACH, EnumAttachTo.WALL);
			} else if (pGround) {
				state = state.withProperty(ATTACH, EnumAttachTo.GROUND);
			} else if (pCeiling) {
				state = state.withProperty(ATTACH, EnumAttachTo.CEILING);
			} else {
				state = state.withProperty(ATTACH, EnumAttachTo.WALL);
			}
		}
		return state;
	}
	
	// Interactions
	@Override
	public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ,
			int meta, EntityLivingBase placer) {
		// set facing to the direction player is facing
		IBlockState state = super.onBlockPlaced(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer);
		state = this.getAttached(worldIn, pos, state);
		return this.getFacingState(state, placer);
	}
	
	@Override
	public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) {
		worldIn.setBlockState(pos, this.getAttached(worldIn, pos, state));
	}
	
	// Appearance
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		if ((EnumAttachTo) state.getValue(ATTACH) == EnumAttachTo.GROUND) {
			return new AxisAlignedBB(0.375F, 0.0F, 0.375F, 0.625F, 1.0F, 0.625F);
		} else if ((EnumAttachTo) state.getValue(ATTACH) == EnumAttachTo.EXTENDING){
			return new AxisAlignedBB(0.375F, 0.0F, 0.375F, 0.625F, 1.0F, 0.625F);
		} else if ((EnumAttachTo) state.getValue(ATTACH) == EnumAttachTo.CEILING) {
			switch ((EnumFacing) state.getValue(FACING)) {
				case NORTH:
					return new AxisAlignedBB(0.0F, 0.875F, 0.375F, 1.0F, 1.0F, 0.625F);
				case SOUTH:
					return new AxisAlignedBB(0.0F, 0.875F, 0.375F, 1.0F, 1.0F, 0.625F);
				default: // EAST and WEST
					return new AxisAlignedBB(0.375F, 0.875F, 0.0F, 0.625F, 1.0F, 1.0F);
			}
		} else { // if ((EnumAttachTo) state.getValue(ATTACH) == EnumAttachTo.WALL) {
			switch ((EnumFacing) state.getValue(FACING)) {
			case NORTH:
				return new AxisAlignedBB(0.0F, 0.4375F, 0.0F, 1.0F, 0.625F, 0.125F);
			case EAST:
				return new AxisAlignedBB(0.875F, 0.4375F, 0.0F, 1.0F, 0.625F, 1.0F);
			case SOUTH:
				return new AxisAlignedBB(0.0F, 0.4375F, 0.875F, 1.0F, 0.625F, 1.0F);
			default: // WEST
				return new AxisAlignedBB(0.0F, 0.4375F, 0.0F, 0.125F, 0.625F, 1.0F);
			}
		}
	}
} public class GlassFenceBlock extends BlockFence {
	
	public GlassFenceBlock() {
		super(Material.GLASS, MapColor.IRON);
		this.setUnlocalizedName("glass_fence");
		this.setCreativeTab(TransitRailMod.tabTransitRail);
	}
	
	@Override
	public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) {
		return true;
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public BlockRenderLayer getBlockLayer() {
		return BlockRenderLayer.CUTOUT;
	}
	
	@Override
	public boolean canConnectTo(IBlockAccess worldIn, BlockPos pos) {
		Block block = worldIn.getBlockState(pos).getBlock();
		if (block == Blocks.GLASS || block == ModBlocks.turnstile_block) {
			return true;
		}
		return super.canConnectTo(worldIn, pos);
	}
} public class HungArrowSign extends ArrowSign {
		
	public HungArrowSign(Material materialIn) {
		super(Material.IRON);
		this.setUnlocalizedName("hung_arrow_sign");
		this.setCreativeTab(TransitRailMod.tabTransitRail);
	}
	
	// Properties
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}
	
	// Appearance
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumFacing facing = (EnumFacing) state.getValue(FACING);
		if (facing == EnumFacing.NORTH || facing == EnumFacing.SOUTH) {
			return new AxisAlignedBB(0.0F, 0.5F, 0.4375F, 1.0F, 1.0F, 0.5625F);
		} else {
			return new AxisAlignedBB(0.4375F, 0.5F, 0.0F, 0.5625F, 1.0F, 1.0F);
		}
	}
} public class LogoBlock extends Block {

	public LogoBlock(Material materialIn) {
		super(materialIn);
		setHardness(1.5F);
		setResistance(50);
		setLightLevel(1F);
		setUnlocalizedName("logo_block");
		setHarvestLevel("pickaxe", 1);
		setCreativeTab(TransitRailMod.tabTransitRail);
	}
} public class NoiseBarrierBlock extends BlockFence {
	
	public final boolean lamp;
	
	public NoiseBarrierBlock(boolean lampIn) {
		super(Material.GLASS, MapColor.IRON);
		lamp = lampIn;
		this.setUnlocalizedName(lamp ? "noise_barrier_with_lamp" : "noise_barrier");
		this.setLightLevel(lamp ? 1.0F : 0F);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) {
		return true;
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public BlockRenderLayer getBlockLayer() {
		return BlockRenderLayer.CUTOUT;
	}
	
	// Bounding boxes
	@Override
	public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, World worldIn, BlockPos pos) {
		boolean flag = this.canConnectTo(worldIn, pos.north());
		boolean flag1 = this.canConnectTo(worldIn, pos.south());
		boolean flag2 = this.canConnectTo(worldIn, pos.west());
		boolean flag3 = this.canConnectTo(worldIn, pos.east());
		float f = 0.4375F;
		float f1 = 0.5625F;
		float f2 = 0.4375F;
		float f3 = 0.5625F;

		if (flag) {
			f2 = 0.0F;
		}
		
		if (flag1) {
			f3 = 1.0F;
		}
		
		if (flag || flag1) {
			return new AxisAlignedBB(f, 0.0F, f2, f1, 1.0F, f3);
		}

		f2 = 0.4375F;
		f3 = 0.5625F;

		if (flag2) {
			f = 0.0F;
		}

		if (flag3) {
			f1 = 1.0F;
		}

		if (flag2 || flag3 || !flag && !flag1) {
			return new AxisAlignedBB(f, 0.0F, f2, f1, 1.0F, f3);
		}

		if (flag) {
			f2 = 0.0F;
		}

		if (flag1) {
			f3 = 1.0F;
		}

		return new AxisAlignedBB(f, 0.0F, f2, f1, 1.0F, f3);
	}
} public class PlatformArrowSign extends ArrowSign {
	
	public PlatformArrowSign(Material materialIn) {
		super(Material.IRON);
		this.setUnlocalizedName("platform_arrow_sign");
		this.setCreativeTab(TransitRailMod.tabTransitRail);
	}
} public class PlatformGateBlock extends PlatformBlock {
	
	public static final PropertyBool POWERED = PropertyBool.create("powered");
	public static final PropertyBool LEFT = PropertyBool.create("left"); 
	
	public PlatformGateBlock(Material materialIn) {
		super(Material.GLASS);
		this.setUnlocalizedName("platform_gate_block");
		this.setDefaultState(getDefaultState()
				.withProperty(UPPER, false)
				.withProperty(FACING, EnumFacing.NORTH)
				.withProperty(POWERED, false)
				.withProperty(LEFT, false));
	}
	
	public boolean isLeft(IBlockAccess worldIn, BlockPos pos, EnumFacing direc){
		return worldIn.getBlockState(pos.offset(direc.rotateY())).getBlock().equals(this);
	}
	
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumFacing facing = (EnumFacing) state.getValue(FACING);
		boolean isOpen = (Boolean) state.getValue(POWERED);
		boolean leftOrNot = this.isLeft(source, pos, facing);
		if (isUpper(source, pos)) {
			if (!isOpen) {
				if (facing == EnumFacing.NORTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 0.125F);
				} else if (facing == EnumFacing.EAST) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
				} else if (facing == EnumFacing.SOUTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 1.0F, 0.5F, 1.0F);
				} else { // if (facing == EnumFacing.WEST) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 0.5F, 1.0F);
				}
			} else if (leftOrNot) {
				if (facing == EnumFacing.NORTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 0.5F, 0.125F);
				} else if (facing == EnumFacing.EAST) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 0.5F, 0.125F);
				} else if (facing == EnumFacing.SOUTH) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.875F, 1.0F, 0.5F, 1.0F);
				} else { // if (facing == EnumFacing.WEST) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 0.125F, 0.5F, 1.0F);
				}
			} else {
				if (facing == EnumFacing.NORTH) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 0.5F, 0.125F);
				} else if (facing == EnumFacing.EAST) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.875F, 1.0F, 0.5F, 1.0F);
				} else if (facing == EnumFacing.SOUTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 0.125F, 0.5F, 1.0F);
				} else { // if (facing == EnumFacing.WEST) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 0.5F, 0.125F);
				}
			}
		} else {
			if (!isOpen) {
				if (facing == EnumFacing.NORTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.125F);
				} else if (facing == EnumFacing.EAST) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
				} else if (facing == EnumFacing.SOUTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F);
				} else { // if (facing == EnumFacing.WEST) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 1.0F, 1.0F);
				}
			} else if (leftOrNot) {
				if (facing == EnumFacing.NORTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 1.0F, 0.125F);
				} else if (facing == EnumFacing.EAST) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 1.0F, 0.125F);
				} else if (facing == EnumFacing.SOUTH) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F);
				} else { // if (facing == EnumFacing.WEST) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 0.125F, 1.0F, 1.0F);
				}
			} else {
				if (facing == EnumFacing.NORTH) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.0F, 1.0F, 1.0F, 0.125F);
				} else if (facing == EnumFacing.EAST) {
					return new AxisAlignedBB(0.875F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F);
				} else if (facing == EnumFacing.SOUTH) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.875F, 0.125F, 1.0F, 1.0F);
				} else { // if (facing == EnumFacing.WEST) {
					return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.125F, 1.0F, 0.125F);
				}
			}
		}
	}
	
	// BlockStates
	@Override
	public BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {FACING, UPPER, POWERED, LEFT});
	}
	
	// meta: 0211
	// 2: powered
	// 11 : facing
	@Override
	public int getMetaFromState(IBlockState state) {
		int mFacing = ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
		int mPowered = (Boolean) state.getValue(POWERED) ? 1 : 0;
		return mPowered *4 + mFacing;
	}
	
	// meta: 0211
	// 2: powered
	// 11 : facing
	@Override
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing pFacing = EnumFacing.getHorizontal(meta % 4); 
		boolean pPowered = meta / 4 == 1;
		return this.getDefaultState().withProperty(FACING, pFacing).withProperty(POWERED, pPowered);
	}
	
	@Override
	public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos) {
		EnumFacing direc = (EnumFacing) state.getValue(FACING);
		return super.getActualState(state, worldIn, pos).withProperty(LEFT, isLeft(worldIn, pos, direc));
	}
	
	// Redstone and interactions
	@SideOnly(Side.CLIENT)
	public Item getItem(World worldIn, BlockPos pos)
	{
		return this.getItem();
	}
	
	private Item getItem() {
		return ModItems.platform_gate_item;
	}
	
	@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune)
	{
		return this.getItem();
	}
	
	@Override
	public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) {
		if (!isUpper(worldIn, pos)){
			state = state.withProperty(POWERED, worldIn.isBlockPowered(pos));
		} else {
			Boolean isLowerPowered = (Boolean) worldIn.getBlockState(pos.down()).getValue(POWERED);
			state = state.withProperty(POWERED, isLowerPowered);
		}
		worldIn.setBlockState(pos, state);
		worldIn.markBlockRangeForRenderUpdate(pos, pos);
		super.neighborChanged(state, worldIn, pos, blockIn);
	}
} public class PlatformPanelBlock extends PlatformBlock {
	
	public PlatformPanelBlock(Material materialIn) {
		super(Material.IRON);
		this.setUnlocalizedName("platform_panel_block");
		this.setDefaultState(getDefaultState().withProperty(UPPER, false).withProperty(FACING, EnumFacing.NORTH));
	}
	
	// Properties
	public boolean isUpper(IBlockAccess worldIn, BlockPos pos){
		return worldIn.getBlockState(pos.down()).getBlock().equals(this);
	}
	
	public boolean isUpper(IBlockState state){
		return (Boolean) state.getValue(UPPER);
	}
	
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumFacing facing = (EnumFacing) state.getValue(FACING);
		if (isUpper(source, pos)) {
			if (facing == EnumFacing.NORTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.125F, 1.0F, 0.5F, 0.25F);
			} else if (facing == EnumFacing.EAST) {
				return new AxisAlignedBB(0.75F, 0.0F, 0.0F, 0.875F, 0.5F, 1.0F);
			} else if (facing == EnumFacing.SOUTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.75F, 1.0F, 0.5F, 0.875F);
			} else { // if (facing == EnumFacing.WEST) {
				return new AxisAlignedBB(0.125F, 0.0F, 0.0F, 0.25F, 0.5F, 1.0F);
			}
		} else {
			if (facing == EnumFacing.NORTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.125F, 1.0F, 1.0F, 0.25F);
			} else if (facing == EnumFacing.EAST) {
				return new AxisAlignedBB(0.75F, 0.0F, 0.0F, 0.875F, 1.0F, 1.0F);
			} else if (facing == EnumFacing.SOUTH) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.75F, 1.0F, 1.0F, 0.875F);
			} else { // if (facing == EnumFacing.WEST) {
				return new AxisAlignedBB(0.125F, 0.0F, 0.0F, 0.25F, 1.0F, 1.0F);
			}
		}
	}
	
	// Blockstates
	@Override
	public BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {FACING, UPPER});
	}
	
	@Override
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) {
		return this.getDefaultState().withProperty(FACING, EnumFacing.getHorizontal(meta));
	}
	
	// Redstone and interactions
	@SideOnly(Side.CLIENT)
	public Item getItem(World worldIn, BlockPos pos)
	{
		return this.getItem();
	}
	
	private Item getItem() {
		return ModItems.platform_panel_item;
	}
	
	@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune)
	{
		return this.getItem();
	}
} public class SlimPassengerDetector extends EntityDetector {
	
	public SlimPassengerDetector(Material materialIn) {
		super(Material.GLASS);
		this.setUnlocalizedName("slim_passenger_detector");
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}
	
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		switch ((EnumFacing) source.getBlockState(pos).getValue(FACING)) {
		case NORTH:
			return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 0.1875F, 0.0625F);
		case EAST:
			return new AxisAlignedBB(0.9375F, 0.0F, 0.0F, 1.0F, 0.1875F, 1.0F);
		case SOUTH:
			return new AxisAlignedBB(0.0F, 0.0F, 0.9375F, 1.0F, 0.1875F, 1.0F);
		default: // west
			return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.0625F, 0.1875F, 1.0F);
		}
	}
} public class TicketMachine extends Block {
	
	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);

	public TicketMachine(Material materialIn) {
		super(Material.IRON);
		this.setUnlocalizedName("ticket_machine");
		this.setCreativeTab(TransitRailMod.tabTransitRail);
		this.setDefaultState(this.getDefaultState().withProperty(FACING, EnumFacing.NORTH));
	}
	
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {FACING});
	}
	
	protected IBlockState getFacingState(IBlockState state, EntityLivingBase placer){
		EnumFacing thisFacing = placer.getHorizontalFacing();
		return state.withProperty(FACING, thisFacing);
	}
	
	@Override
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) {
		return this.getDefaultState().withProperty(FACING, EnumFacing.getHorizontal(meta));
	}
	
	@Override
	public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) {
		return true;
	}
	
	// Interactions
	@Override
	public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer){
		// set facing to the direction player is facing
		IBlockState state = super.onBlockPlaced(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer);
		return this.getFacingState(state, placer);
	}
	
	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) {
		if (!worldIn.isRemote) {
			playerIn.openGui(TransitRailMod.instance,
					EnumGuiTypes.TICKET_MACHINE.ordinal(),
					worldIn,
					pos.getX(), pos.getY(), pos.getZ());
		}
		return true;
	}
} public class TurnstileBlock extends CustomDirectionBlock{
	
	public static final PropertyBool ACTIVE = PropertyBool.create("active");
	// whether the turnstile has processed the ticket and open the gate
	public static final PropertyEnum PASSING = PropertyEnum.create("passing", EnumPassingDirection.class);
	
	public TurnstileBlock(Material materialIn) {
		super(Material.IRON);
		this.setUnlocalizedName("turnstile_block");
		this.setCreativeTab(TransitRailMod.tabTransitRail);
		this.setTickRandomly(true);
		this.setDefaultState(this.getDefaultState()
				.withProperty(ACTIVE, false)
				.withProperty(PASSING, EnumPassingDirection.INSIDE)
				.withProperty(FACING, EnumFacing.NORTH));
	}
	
	@Override
	public boolean isTranslucent(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) {
		return true;
	}
	
	@Override
	public int tickRate(World worldIn) {
		return 20;
	}
	
	// Block State
	@Override
	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {ACTIVE, PASSING, FACING});
	}
	
	// meta: 3211
	// 11: facing
	// 2: active
	// 3: passing
	@Override
	public int getMetaFromState(IBlockState state) {
		int mFacing = ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
		int mActive = (Boolean) state.getValue(ACTIVE) ? 1 : 0;
		int mPassing = ((EnumPassingDirection) state.getValue(PASSING)).toMeta();
		return mPassing * 8 + mActive * 4 + mFacing;
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing pFacing = EnumFacing.getHorizontal(meta % 4);
		boolean pActive = (meta % 8) / 4 > 0;
		EnumPassingDirection pPassing = EnumPassingDirection.fromMeta(meta / 8);
		return getDefaultState()
				.withProperty(ACTIVE, pActive)
				.withProperty(PASSING, pPassing)
				.withProperty(FACING, pFacing);
	}
	
	// Interactions
	
	@Override
	public void randomTick(World worldIn, BlockPos pos, IBlockState state, Random random) {}
	
	@Override
	public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) {
		if ((Boolean) state.getValue(ACTIVE)){
			worldIn.setBlockState(pos, state.withProperty(ACTIVE, false));
		}
	}
	
	// Appearance
	@Override
	public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World worldIn, BlockPos pos) {
		switch (((EnumFacing) state.getValue(FACING))) {
			case NORTH :
				return new AxisAlignedBB(0.75F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
			case EAST :
				return new AxisAlignedBB(0.0F, 0.0F, 0.75F, 1.0F, 1.0F, 1.0F);
			case SOUTH :
				return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.25F, 1.0F, 1.0F);
			default : //WEST
				return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.25F);
		}
	}
	
	@Override
	public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState state, Entity entityIn) {
		if (!worldIn.isRemote){
			AxisAlignedBB spaceToCheck = getSpaceToCheck(worldIn, pos);
			List list = worldIn.getEntitiesWithinAABB(EntityLivingBase.class, spaceToCheck);
			
			worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
			if (list.isEmpty()){
				if ((Boolean) state.getValue(ACTIVE)){
					worldIn.setBlockState(pos, state.withProperty(ACTIVE, false));
				}
			}
		}
	}
	
	protected AxisAlignedBB getBarBoundsBasedOnState(IBlockAccess worldIn, BlockPos pos) {
		IBlockState state = worldIn.getBlockState(pos);
		if ((Boolean) state.getValue(ACTIVE)){
			return null;
		} else {
			switch (((EnumFacing) state.getValue(FACING))) {
				case NORTH :
					return getBBFromBounds(pos, 0.0F, 0.4375F, 0.4375F, 1.0F, 1.5F, 0.5625F);
				case SOUTH :
					return getBBFromBounds(pos, 0.0F, 0.4375F, 0.4375F, 1.0F, 1.5F, 0.5625F);
				default : // EAST WEST
					return getBBFromBounds(pos, 0.4375F, 0.4375F, 0.0F, 0.5625F, 1.5F, 1.0F);
			}
		}
	}
	
	// extra bounding box on top of side panel
	protected AxisAlignedBB getSideBoundsBasedOnState(IBlockAccess worldIn, BlockPos pos) {
		IBlockState state = worldIn.getBlockState(pos);
		switch (((EnumFacing) state.getValue(FACING))) {
			case NORTH :
				return getBBFromBounds(pos, 0.75F, 1.0F, 0.0F, 1.0F, 1.5F, 1.0F);
			case EAST :
				return getBBFromBounds(pos, 0.0F, 1.0F, 0.75F, 1.0F, 1.5F, 1.0F);
			case SOUTH :
				return getBBFromBounds(pos, 0.0F, 1.0F, 0.0F, 0.25F, 1.5F, 1.0F);
			default : // WEST
				return getBBFromBounds(pos, 0.0F, 1.0F, 0.0F, 1.0F, 1.5F, 0.25F);
		}
	}
	
	private AxisAlignedBB getBBFromBounds (BlockPos pos, double x1, double y1, double z1, double x2, double y2, double z2) {
		return new AxisAlignedBB(pos.getX() + x1, pos.getY() + y1, pos.getZ() + z1, pos.getX() + x2, pos.getY() + y2, pos.getZ() + z2);
	}
	
	protected AxisAlignedBB getSpaceToCheck(World worldIn, BlockPos pos){
		return new AxisAlignedBB(
				pos.getX(),
				pos.getY(),
				pos.getZ(),
				pos.getX() + 1,
				pos.getY() + 1,
				pos.getZ() + 1);
	}
	
	@Override
	public AxisAlignedBB getCollisionBoundingBox(IBlockState state, World worldIn, BlockPos pos) {
		return this.getSelectedBoundingBox(state, worldIn, pos);
	}
	
	@Override
	public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox,
			List<AxisAlignedBB> collidingBoxes, Entity entityIn) {
		super.addCollisionBoxToList(state, worldIn, pos, entityBox, collidingBoxes, entityIn);
		AxisAlignedBB axisalignedbb1 = this.getCollisionBoundingBox(state, worldIn, pos);
		AxisAlignedBB barBound = this.getBarBoundsBasedOnState(worldIn, pos);
		AxisAlignedBB sideBound = this.getSideBoundsBasedOnState(worldIn, pos);
		collidingBoxes.add(barBound);
		collidingBoxes.add(sideBound);
	}
} public class WirePanel extends CustomDirectionBlock {
	
	public static final PropertyBool LAMP = PropertyBool.create("lamp");
	public static final PropertyBool SHUT = PropertyBool.create("shut");
	
	public WirePanel(Material materialIn) {
		super(Material.IRON);
		this.setUnlocalizedName("wire_panel");
		this.setCreativeTab(TransitRailMod.tabTransitRail);
		this.setDefaultState(this.getDefaultState()
				.withProperty(LAMP, false)
				.withProperty(FACING, EnumFacing.NORTH)
				.withProperty(SHUT, false));
	}
	
	// Properties
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}
	
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumFacing facing = (EnumFacing) state.getValue(FACING); 
		if (facing == EnumFacing.NORTH) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.5F);
		} else if (facing == EnumFacing.EAST) {
			return new AxisAlignedBB(0.5F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
		} else if (facing == EnumFacing.SOUTH) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.5F, 1.0F, 1.0F, 1.0F);
		} else { // WEST
			return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.5F, 1.0F, 1.0F);
		}
	}
	
	@Override
	public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) {
		return true;
	}
	
	@Override
	public boolean canProvidePower(IBlockState state) {
		return true;
	}
	
	// Block States
	@Override
	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {FACING, LAMP, SHUT});
	}
	
	// meta: 3211
	// 11: facing
	// 2: lamp
	// 3: shut
	@Override
	public int getMetaFromState(IBlockState state) {
		int mFacing = ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
		int mLamp = (Boolean) state.getValue(LAMP) ? 1 : 0;
		int mShut = (Boolean) state.getValue(SHUT) ? 1 : 0;
		return mShut * 8 + mLamp * 4 + mFacing;
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing pFacing = EnumFacing.getHorizontal(meta % 4);
		boolean pLamp = ((meta % 8) / 4) > 0;
		boolean pShut = meta / 8 > 0;
		return this.getDefaultState()
				.withProperty(FACING, pFacing)
				.withProperty(LAMP, pLamp)
				.withProperty(SHUT, pShut);
	}
	
	// Interactions
	@Override
	public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer){
		// set facing to the direction player is facing
		IBlockState state = super.onBlockPlaced(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer);
		return this.getFacingState(state, placer)
				.withProperty(LAMP, this.checkLampPresent(worldIn, pos))
				.withProperty(SHUT, this.checkIsExtendingAbove(worldIn,pos));
	}
	
	@Override
	public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor) {
		IBlockState state = world.getBlockState(pos);
		EnumFacing sideToProvide = ((EnumFacing) state.getValue(FACING)).getOpposite();
		state = state.withProperty(LAMP, this.checkLampPresent(world, pos));
		((World) world).setBlockState(pos, state);
		((World) world).notifyBlockOfStateChange(pos.offset(sideToProvide), this);
	}
	
	@Override
	public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) {
		if (this.checkLampPresent(blockAccess, pos) && !((Boolean) blockState.getValue(SHUT))) {
			EnumFacing sideToProvide = ((EnumFacing) blockState.getValue(FACING));
			return sideToProvide == side ? 15 : 0;
		} else {
			return 0;
		}
	}
	
	protected boolean checkLampPresent(IBlockAccess worldIn, BlockPos pos) {
		return worldIn.getBlockState(pos.up()).getBlock() == ModBlocks.fluorescent_lamp ? true : worldIn.getBlockState(pos.up()).getBlock() == ModBlocks.noise_barrier_with_lamp;
	}
	
	protected boolean checkIsExtendingAbove(IBlockAccess worldIn, BlockPos pos) {
		return worldIn.getBlockState(pos.down()).getBlock() == ModBlocks.wire_panel;
	}
	
	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) {
		if (playerIn.getHeldItemMainhand() != null) {
			if (playerIn.getHeldItemMainhand().getItem() == ModItems.style_changer){
				worldIn.setBlockState(pos, state.cycleProperty(SHUT));
				return true;
			}
		}
		return false;
	}
} public class WirePanelCorner extends Block {
	
	public static final PropertyEnum CORNER = PropertyEnum.create("corner", EnumCorner.class);
	public static final PropertyBool CONCAVE = PropertyBool.create("concave");
	
	public WirePanelCorner(Material materialIn) {
		super(Material.IRON);
		this.setUnlocalizedName("wire_panel_corner");
		this.setCreativeTab(TransitRailMod.tabTransitRail);
		this.setDefaultState(this.getDefaultState()
				.withProperty(CORNER, EnumCorner.NE)
				.withProperty(CONCAVE, false));
	}
	
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		EnumCorner corner = (EnumCorner) state.getValue(CORNER);
		if ((Boolean) state.getValue(CONCAVE)) {
			return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
		} else {
			if (corner == EnumCorner.SE) {
				return new AxisAlignedBB(0.5F, 0.0F, 0.5F, 1.0F, 1.0F, 1.0F);
			} else if (corner == EnumCorner.SW) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.5F, 0.5F, 1.0F, 1.0F);
			} else if (corner == EnumCorner.NW) {
				return new AxisAlignedBB(0.0F, 0.0F, 0.0F, 0.5F, 1.0F, 0.5F);
			} else { // NE
				return new AxisAlignedBB(0.5F, 0.0F, 0.0F, 1.0F, 1.0F, 0.5F);
			}
		}
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}
	
	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}
	
	// Interactions
	protected EnumCorner getCorner(EntityLivingBase playerIn){
		double xIndex = playerIn.getLookVec().xCoord;
		double zIndex = playerIn.getLookVec().zCoord;
		int index;
		if (xIndex > 0){
			index = zIndex > 0 ? 0 : 3;
			// x+ and z+ = south east
			// x+ and z- = north east
		} else {
			index = zIndex > 0 ? 1 : 2;
			// x- and z+ = south west
			// x- and z- = north west
		}
		return EnumCorner.fromMeta(index);
	}
	
	protected boolean getConcave(IBlockAccess worldIn, BlockPos pos) {
		return this.getConcave(worldIn, pos, worldIn.getBlockState(pos));
	}
	
	// to specify state before the block is established
	protected boolean getConcave(IBlockAccess worldIn, BlockPos pos, IBlockState state) {
		EnumCorner corner = (EnumCorner) state.getValue(CORNER);
		for (EnumFacing facing : corner.getConcaveConnections()){
			Block block = worldIn.getBlockState(pos.offset(facing)).getBlock();
			if (block == ModBlocks.wire_panel || block == ModBlocks.wire_panel_corner) {
				return true;
			}
		}
		return false;
	}
	
	@Override
	public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ,
			int meta, EntityLivingBase placer) {
		IBlockState state = super.onBlockPlaced(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer);
		state = state.withProperty(CORNER, this.getCorner(placer));
		return state.withProperty(CONCAVE, this.getConcave(worldIn, pos, state));
	}
	
	@Override
	public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) {
		state = state.withProperty(CONCAVE, this.getConcave(worldIn, pos));
		worldIn.setBlockState(pos, state);
	}
	
	// Block States
	@Override
	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] {CORNER, CONCAVE});
	}
	
	// meta: 0211
	// 2: concave
	// 11: corner
	@Override
	public int getMetaFromState(IBlockState state) {
		int mCorner = ((EnumCorner) state.getValue(CORNER)).toMeta();
		int mConcave = (Boolean) state.getValue(CONCAVE) ? 1 : 0;
		return mConcave * 4 + mCorner;
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) {
		EnumCorner pCorner = EnumCorner.fromMeta(meta % 4);
		boolean pConcave = meta / 4 > 0;
		return this.getDefaultState()
				.withProperty(CONCAVE, pConcave)
				.withProperty(CORNER, pCorner);
	}
}
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraftforge.fml.common.registry.GameRegistry;
import tk.cth451.transitrailmod.References;
import tk.cth451.transitrailmod.blocks.ClosedPlatformDoorBlock;
import tk.cth451.transitrailmod.blocks.ClosedPlatformPanelBlock;
import tk.cth451.transitrailmod.blocks.ClosedPlatformTop;
import tk.cth451.transitrailmod.blocks.FluorescentLamp;
import tk.cth451.transitrailmod.blocks.GlassFenceBlock;
import tk.cth451.transitrailmod.blocks.HungArrowSign;
import tk.cth451.transitrailmod.blocks.LogoBlock;
import tk.cth451.transitrailmod.blocks.NoiseBarrierBlock;
import tk.cth451.transitrailmod.blocks.PlatformArrowSign;
import tk.cth451.transitrailmod.blocks.PlatformGateBlock;
import tk.cth451.transitrailmod.blocks.PlatformPanelBlock;
import tk.cth451.transitrailmod.blocks.SlimPassengerDetector;
import tk.cth451.transitrailmod.blocks.TicketMachine;
import tk.cth451.transitrailmod.blocks.TurnstileBlock;
import tk.cth451.transitrailmod.blocks.WirePanel;
import tk.cth451.transitrailmod.blocks.WirePanelCorner;
package tk.cth451.transitrailmod.init;


public class ModBlocks {
	public static Block closed_platform_top;
	public static Block closed_platform_door_block;
	public static Block closed_platform_panel_block;
	public static Block platform_gate_block;
	public static Block platform_panel_block;
	public static Block logo_block;
	public static Block hung_arrow_sign;
	public static Block platform_arrow_sign;
	public static Block fluorescent_lamp;
	public static Block wire_panel;
	public static Block wire_panel_corner;
	public static Block platform_sign;
	public static Block turnstile_block;
	public static Block ticket_machine;
	public static Block glass_fence;
	public static Block noise_barrier;
	public static Block noise_barrier_with_lamp;
	public static Block slim_passenger_detector;
	
	public static void init() {
		closed_platform_top = new ClosedPlatformTop(Material.IRON);
		closed_platform_door_block = new ClosedPlatformDoorBlock(Material.GLASS);
		closed_platform_panel_block = new ClosedPlatformPanelBlock(Material.GLASS);
		platform_gate_block = new PlatformGateBlock(Material.GLASS);
		platform_panel_block = new PlatformPanelBlock(Material.IRON);
		logo_block = new LogoBlock(Material.IRON);
		hung_arrow_sign = new HungArrowSign(Material.IRON);
		platform_arrow_sign = new PlatformArrowSign(Material.IRON);
		fluorescent_lamp = new FluorescentLamp(Material.GLASS);
		wire_panel = new WirePanel(Material.IRON);