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