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    }