001package net.minecraft.block; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.Random; 006import net.minecraft.block.material.Material; 007import net.minecraft.entity.Entity; 008import net.minecraft.item.ItemMonsterPlacer; 009import net.minecraft.util.AxisAlignedBB; 010import net.minecraft.world.IBlockAccess; 011import net.minecraft.world.World; 012 013public class BlockPortal extends BlockBreakable 014{ 015 public BlockPortal(int par1) 016 { 017 super(par1, "portal", Material.portal, false); 018 this.setTickRandomly(true); 019 } 020 021 /** 022 * Ticks the block if it's been scheduled 023 */ 024 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 025 { 026 super.updateTick(par1World, par2, par3, par4, par5Random); 027 028 if (par1World.provider.isSurfaceWorld() && par5Random.nextInt(2000) < par1World.difficultySetting) 029 { 030 int l; 031 032 for (l = par3; !par1World.doesBlockHaveSolidTopSurface(par2, l, par4) && l > 0; --l) 033 { 034 ; 035 } 036 037 if (l > 0 && !par1World.isBlockNormalCube(par2, l + 1, par4)) 038 { 039 Entity entity = ItemMonsterPlacer.spawnCreature(par1World, 57, (double)par2 + 0.5D, (double)l + 1.1D, (double)par4 + 0.5D); 040 041 if (entity != null) 042 { 043 entity.timeUntilPortal = entity.getPortalCooldown(); 044 } 045 } 046 } 047 } 048 049 /** 050 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 051 * cleared to be reused) 052 */ 053 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 054 { 055 return null; 056 } 057 058 /** 059 * Updates the blocks bounds based on its current state. Args: world, x, y, z 060 */ 061 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 062 { 063 float f; 064 float f1; 065 066 if (par1IBlockAccess.getBlockId(par2 - 1, par3, par4) != this.blockID && par1IBlockAccess.getBlockId(par2 + 1, par3, par4) != this.blockID) 067 { 068 f = 0.125F; 069 f1 = 0.5F; 070 this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, 1.0F, 0.5F + f1); 071 } 072 else 073 { 074 f = 0.5F; 075 f1 = 0.125F; 076 this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, 1.0F, 0.5F + f1); 077 } 078 } 079 080 /** 081 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 082 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 083 */ 084 public boolean isOpaqueCube() 085 { 086 return false; 087 } 088 089 /** 090 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 091 */ 092 public boolean renderAsNormalBlock() 093 { 094 return false; 095 } 096 097 /** 098 * Checks to see if this location is valid to create a portal and will return True if it does. Args: world, x, y, z 099 */ 100 public boolean tryToCreatePortal(World par1World, int par2, int par3, int par4) 101 { 102 byte b0 = 0; 103 byte b1 = 0; 104 105 if (par1World.getBlockId(par2 - 1, par3, par4) == Block.obsidian.blockID || par1World.getBlockId(par2 + 1, par3, par4) == Block.obsidian.blockID) 106 { 107 b0 = 1; 108 } 109 110 if (par1World.getBlockId(par2, par3, par4 - 1) == Block.obsidian.blockID || par1World.getBlockId(par2, par3, par4 + 1) == Block.obsidian.blockID) 111 { 112 b1 = 1; 113 } 114 115 if (b0 == b1) 116 { 117 return false; 118 } 119 else 120 { 121 if (par1World.getBlockId(par2 - b0, par3, par4 - b1) == 0) 122 { 123 par2 -= b0; 124 par4 -= b1; 125 } 126 127 int l; 128 int i1; 129 130 for (l = -1; l <= 2; ++l) 131 { 132 for (i1 = -1; i1 <= 3; ++i1) 133 { 134 boolean flag = l == -1 || l == 2 || i1 == -1 || i1 == 3; 135 136 if (l != -1 && l != 2 || i1 != -1 && i1 != 3) 137 { 138 int j1 = par1World.getBlockId(par2 + b0 * l, par3 + i1, par4 + b1 * l); 139 140 if (flag) 141 { 142 if (j1 != Block.obsidian.blockID) 143 { 144 return false; 145 } 146 } 147 else if (j1 != 0 && j1 != Block.fire.blockID) 148 { 149 return false; 150 } 151 } 152 } 153 } 154 155 for (l = 0; l < 2; ++l) 156 { 157 for (i1 = 0; i1 < 3; ++i1) 158 { 159 par1World.setBlock(par2 + b0 * l, par3 + i1, par4 + b1 * l, Block.portal.blockID, 0, 2); 160 } 161 } 162 163 return true; 164 } 165 } 166 167 /** 168 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 169 * their own) Args: x, y, z, neighbor blockID 170 */ 171 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 172 { 173 byte b0 = 0; 174 byte b1 = 1; 175 176 if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID) 177 { 178 b0 = 1; 179 b1 = 0; 180 } 181 182 int i1; 183 184 for (i1 = par3; par1World.getBlockId(par2, i1 - 1, par4) == this.blockID; --i1) 185 { 186 ; 187 } 188 189 if (par1World.getBlockId(par2, i1 - 1, par4) != Block.obsidian.blockID) 190 { 191 par1World.setBlockToAir(par2, par3, par4); 192 } 193 else 194 { 195 int j1; 196 197 for (j1 = 1; j1 < 4 && par1World.getBlockId(par2, i1 + j1, par4) == this.blockID; ++j1) 198 { 199 ; 200 } 201 202 if (j1 == 3 && par1World.getBlockId(par2, i1 + j1, par4) == Block.obsidian.blockID) 203 { 204 boolean flag = par1World.getBlockId(par2 - 1, par3, par4) == this.blockID || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID; 205 boolean flag1 = par1World.getBlockId(par2, par3, par4 - 1) == this.blockID || par1World.getBlockId(par2, par3, par4 + 1) == this.blockID; 206 207 if (flag && flag1) 208 { 209 par1World.setBlockToAir(par2, par3, par4); 210 } 211 else 212 { 213 if ((par1World.getBlockId(par2 + b0, par3, par4 + b1) != Block.obsidian.blockID || par1World.getBlockId(par2 - b0, par3, par4 - b1) != this.blockID) && (par1World.getBlockId(par2 - b0, par3, par4 - b1) != Block.obsidian.blockID || par1World.getBlockId(par2 + b0, par3, par4 + b1) != this.blockID)) 214 { 215 par1World.setBlockToAir(par2, par3, par4); 216 } 217 } 218 } 219 else 220 { 221 par1World.setBlockToAir(par2, par3, par4); 222 } 223 } 224 } 225 226 @SideOnly(Side.CLIENT) 227 228 /** 229 * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given 230 * coordinates. Args: blockAccess, x, y, z, side 231 */ 232 public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 233 { 234 if (par1IBlockAccess.getBlockId(par2, par3, par4) == this.blockID) 235 { 236 return false; 237 } 238 else 239 { 240 boolean flag = par1IBlockAccess.getBlockId(par2 - 1, par3, par4) == this.blockID && par1IBlockAccess.getBlockId(par2 - 2, par3, par4) != this.blockID; 241 boolean flag1 = par1IBlockAccess.getBlockId(par2 + 1, par3, par4) == this.blockID && par1IBlockAccess.getBlockId(par2 + 2, par3, par4) != this.blockID; 242 boolean flag2 = par1IBlockAccess.getBlockId(par2, par3, par4 - 1) == this.blockID && par1IBlockAccess.getBlockId(par2, par3, par4 - 2) != this.blockID; 243 boolean flag3 = par1IBlockAccess.getBlockId(par2, par3, par4 + 1) == this.blockID && par1IBlockAccess.getBlockId(par2, par3, par4 + 2) != this.blockID; 244 boolean flag4 = flag || flag1; 245 boolean flag5 = flag2 || flag3; 246 return flag4 && par5 == 4 ? true : (flag4 && par5 == 5 ? true : (flag5 && par5 == 2 ? true : flag5 && par5 == 3)); 247 } 248 } 249 250 /** 251 * Returns the quantity of items to drop on block destruction. 252 */ 253 public int quantityDropped(Random par1Random) 254 { 255 return 0; 256 } 257 258 /** 259 * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity 260 */ 261 public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) 262 { 263 if (par5Entity.ridingEntity == null && par5Entity.riddenByEntity == null) 264 { 265 par5Entity.setInPortal(); 266 } 267 } 268 269 @SideOnly(Side.CLIENT) 270 271 /** 272 * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha 273 */ 274 public int getRenderBlockPass() 275 { 276 return 1; 277 } 278 279 @SideOnly(Side.CLIENT) 280 281 /** 282 * A randomly called display update to be able to add particles or other items for display 283 */ 284 public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) 285 { 286 if (par5Random.nextInt(100) == 0) 287 { 288 par1World.playSound((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "portal.portal", 0.5F, par5Random.nextFloat() * 0.4F + 0.8F, false); 289 } 290 291 for (int l = 0; l < 4; ++l) 292 { 293 double d0 = (double)((float)par2 + par5Random.nextFloat()); 294 double d1 = (double)((float)par3 + par5Random.nextFloat()); 295 double d2 = (double)((float)par4 + par5Random.nextFloat()); 296 double d3 = 0.0D; 297 double d4 = 0.0D; 298 double d5 = 0.0D; 299 int i1 = par5Random.nextInt(2) * 2 - 1; 300 d3 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D; 301 d4 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D; 302 d5 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D; 303 304 if (par1World.getBlockId(par2 - 1, par3, par4) != this.blockID && par1World.getBlockId(par2 + 1, par3, par4) != this.blockID) 305 { 306 d0 = (double)par2 + 0.5D + 0.25D * (double)i1; 307 d3 = (double)(par5Random.nextFloat() * 2.0F * (float)i1); 308 } 309 else 310 { 311 d2 = (double)par4 + 0.5D + 0.25D * (double)i1; 312 d5 = (double)(par5Random.nextFloat() * 2.0F * (float)i1); 313 } 314 315 par1World.spawnParticle("portal", d0, d1, d2, d3, d4, d5); 316 } 317 } 318 319 @SideOnly(Side.CLIENT) 320 321 /** 322 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative) 323 */ 324 public int idPicked(World par1World, int par2, int par3, int par4) 325 { 326 return 0; 327 } 328}