    001package net.minecraft.block;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.List;
    006import java.util.Random;
    007import net.minecraft.client.renderer.texture.IconRegister;
    008import net.minecraft.command.IEntitySelector;
    009import net.minecraft.entity.Entity;
    010import net.minecraft.entity.item.EntityMinecart;
    011import net.minecraft.inventory.Container;
    012import net.minecraft.inventory.IInventory;
    013import net.minecraft.util.AxisAlignedBB;
    014import net.minecraft.util.Icon;
    015import net.minecraft.world.IBlockAccess;
    016import net.minecraft.world.World;
    017
    018public class BlockDetectorRail extends BlockRailBase
    019{
    020    @SideOnly(Side.CLIENT)
    021    private Icon[] iconArray;
    022
    023    public BlockDetectorRail(int par1)
    024    {
    025        super(par1, true);
    026        this.setTickRandomly(true);
    027    }
    028
    029    /**
    030     * How many world ticks before ticking
    031     */
    032    public int tickRate(World par1World)
    033    {
    034        return 20;
    035    }
    036
    037    /**
    038     * Can this block provide power. Only wire currently seems to have this change based on its state.
    039     */
    040    public boolean canProvidePower()
    041    {
    042        return true;
    043    }
    044
    045    /**
    046     * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity
    047     */
    048    public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity)
    049    {
    050        if (!par1World.isRemote)
    051        {
    052            int l = par1World.getBlockMetadata(par2, par3, par4);
    053
    054            if ((l & 8) == 0)
    055            {
    056                this.setStateIfMinecartInteractsWithRail(par1World, par2, par3, par4, l);
    057            }
    058        }
    059    }
    060
    061    /**
    062     * Ticks the block if it's been scheduled
    063     */
    064    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    065    {
    066        if (!par1World.isRemote)
    067        {
    068            int l = par1World.getBlockMetadata(par2, par3, par4);
    069
    070            if ((l & 8) != 0)
    071            {
    072                this.setStateIfMinecartInteractsWithRail(par1World, par2, par3, par4, l);
    073            }
    074        }
    075    }
    076
    077    /**
    078     * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
    079     * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
    080     * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
    081     */
    082    public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    083    {
    084        return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) != 0 ? 15 : 0;
    085    }
    086
    087    /**
    088     * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
    089     * side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
    090     */
    091    public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    092    {
    093        return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 0 ? 0 : (par5 == 1 ? 15 : 0);
    094    }
    095
    096    /**
    097     * Update the detector rail power state if a minecart enter, stays or leave the block.
    098     */
    099    private void setStateIfMinecartInteractsWithRail(World par1World, int par2, int par3, int par4, int par5)
    100    {
    101        boolean flag = (par5 & 8) != 0;
    102        boolean flag1 = false;
    103        float f = 0.125F;
    104        List list = par1World.getEntitiesWithinAABB(EntityMinecart.class, AxisAlignedBB.getAABBPool().getAABB((double)((float)par2 + f), (double)par3, (double)((float)par4 + f), (double)((float)(par2 + 1) - f), (double)((float)(par3 + 1) - f), (double)((float)(par4 + 1) - f)));
    105
    106        if (!list.isEmpty())
    107        {
    108            flag1 = true;
    109        }
    110
    111        if (flag1 && !flag)
    112        {
    113            par1World.setBlockMetadataWithNotify(par2, par3, par4, par5 | 8, 3);
    114            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
    115            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    116            par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    117        }
    118
    119        if (!flag1 && flag)
    120        {
    121            par1World.setBlockMetadataWithNotify(par2, par3, par4, par5 & 7, 3);
    122            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
    123            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    124            par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    125        }
    126
    127        if (flag1)
    128        {
    129            par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
    130        }
    131
    132        par1World.func_96440_m(par2, par3, par4, this.blockID);
    133    }
    134
    135    /**
    136     * Called whenever the block is added into the world. Args: world, x, y, z
    137     */
    138    public void onBlockAdded(World par1World, int par2, int par3, int par4)
    139    {
    140        super.onBlockAdded(par1World, par2, par3, par4);
    141        this.setStateIfMinecartInteractsWithRail(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4));
    142    }
    143
    144    /**
    145     * If this returns true, then comparators facing away from this block will use the value from
    146     * getComparatorInputOverride instead of the actual redstone signal strength.
    147     */
    148    public boolean hasComparatorInputOverride()
    149    {
    150        return true;
    151    }
    152
    153    /**
    154     * If hasComparatorInputOverride returns true, the return value from this is used instead of the redstone signal
    155     * strength when this block inputs to a comparator.
    156     */
    157    public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5)
    158    {
    159        if ((par1World.getBlockMetadata(par2, par3, par4) & 8) > 0)
    160        {
    161            float f = 0.125F;
    162            List list = par1World.selectEntitiesWithinAABB(EntityMinecart.class, AxisAlignedBB.getAABBPool().getAABB((double)((float)par2 + f), (double)par3, (double)((float)par4 + f), (double)((float)(par2 + 1) - f), (double)((float)(par3 + 1) - f), (double)((float)(par4 + 1) - f)), IEntitySelector.selectInventories);
    163
    164            if (list.size() > 0)
    165            {
    166                return Container.func_94526_b((IInventory)list.get(0));
    167            }
    168        }
    169
    170        return 0;
    171    }
    172
    173    @SideOnly(Side.CLIENT)
    174
    175    /**
    176     * When this method is called, your block should register all the icons it needs with the given IconRegister. This
    177     * is the only chance you get to register icons.
    178     */
    179    public void registerIcons(IconRegister par1IconRegister)
    180    {
    181        this.iconArray = new Icon[2];
    182        this.iconArray[0] = par1IconRegister.registerIcon("detectorRail");
    183        this.iconArray[1] = par1IconRegister.registerIcon("detectorRail_on");
    184    }
    185
    186    @SideOnly(Side.CLIENT)
    187
    188    /**
    189     * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
    190     */
    191    public Icon getIcon(int par1, int par2)
    192    {
    193        return (par2 & 8) != 0 ? this.iconArray[1] : this.iconArray[0];
    194    }
    195}