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.field_96566_b); 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 getBlockTextureFromSideAndMetadata(int par1, int par2) 192 { 193 return (par2 & 8) != 0 ? this.iconArray[1] : this.iconArray[0]; 194 } 195}