001    package net.minecraft.block;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.Random;
006    import net.minecraft.block.material.Material;
007    import net.minecraft.entity.Entity;
008    import net.minecraft.item.ItemMonsterPlacer;
009    import net.minecraft.util.AxisAlignedBB;
010    import net.minecraft.world.IBlockAccess;
011    import net.minecraft.world.World;
012    
013    public class BlockPortal extends BlockBreakable
014    {
015        public BlockPortal(int par1, int par2)
016        {
017            super(par1, par2, 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 var6;
031    
032                for (var6 = par3; !par1World.doesBlockHaveSolidTopSurface(par2, var6, par4) && var6 > 0; --var6)
033                {
034                    ;
035                }
036    
037                if (var6 > 0 && !par1World.isBlockNormalCube(par2, var6 + 1, par4))
038                {
039                    Entity var7 = ItemMonsterPlacer.spawnCreature(par1World, 57, (double)par2 + 0.5D, (double)var6 + 1.1D, (double)par4 + 0.5D);
040    
041                    if (var7 != null)
042                    {
043                        var7.timeUntilPortal = var7.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 var5;
064            float var6;
065    
066            if (par1IBlockAccess.getBlockId(par2 - 1, par3, par4) != this.blockID && par1IBlockAccess.getBlockId(par2 + 1, par3, par4) != this.blockID)
067            {
068                var5 = 0.125F;
069                var6 = 0.5F;
070                this.setBlockBounds(0.5F - var5, 0.0F, 0.5F - var6, 0.5F + var5, 1.0F, 0.5F + var6);
071            }
072            else
073            {
074                var5 = 0.5F;
075                var6 = 0.125F;
076                this.setBlockBounds(0.5F - var5, 0.0F, 0.5F - var6, 0.5F + var5, 1.0F, 0.5F + var6);
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 var5 = 0;
103            byte var6 = 0;
104    
105            if (par1World.getBlockId(par2 - 1, par3, par4) == Block.obsidian.blockID || par1World.getBlockId(par2 + 1, par3, par4) == Block.obsidian.blockID)
106            {
107                var5 = 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                var6 = 1;
113            }
114    
115            if (var5 == var6)
116            {
117                return false;
118            }
119            else
120            {
121                if (par1World.getBlockId(par2 - var5, par3, par4 - var6) == 0)
122                {
123                    par2 -= var5;
124                    par4 -= var6;
125                }
126    
127                int var7;
128                int var8;
129    
130                for (var7 = -1; var7 <= 2; ++var7)
131                {
132                    for (var8 = -1; var8 <= 3; ++var8)
133                    {
134                        boolean var9 = var7 == -1 || var7 == 2 || var8 == -1 || var8 == 3;
135    
136                        if (var7 != -1 && var7 != 2 || var8 != -1 && var8 != 3)
137                        {
138                            int var10 = par1World.getBlockId(par2 + var5 * var7, par3 + var8, par4 + var6 * var7);
139    
140                            if (var9)
141                            {
142                                if (var10 != Block.obsidian.blockID)
143                                {
144                                    return false;
145                                }
146                            }
147                            else if (var10 != 0 && var10 != Block.fire.blockID)
148                            {
149                                return false;
150                            }
151                        }
152                    }
153                }
154    
155                par1World.editingBlocks = true;
156    
157                for (var7 = 0; var7 < 2; ++var7)
158                {
159                    for (var8 = 0; var8 < 3; ++var8)
160                    {
161                        par1World.setBlockWithNotify(par2 + var5 * var7, par3 + var8, par4 + var6 * var7, Block.portal.blockID);
162                    }
163                }
164    
165                par1World.editingBlocks = false;
166                return true;
167            }
168        }
169    
170        /**
171         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
172         * their own) Args: x, y, z, neighbor blockID
173         */
174        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
175        {
176            byte var6 = 0;
177            byte var7 = 1;
178    
179            if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID)
180            {
181                var6 = 1;
182                var7 = 0;
183            }
184    
185            int var8;
186    
187            for (var8 = par3; par1World.getBlockId(par2, var8 - 1, par4) == this.blockID; --var8)
188            {
189                ;
190            }
191    
192            if (par1World.getBlockId(par2, var8 - 1, par4) != Block.obsidian.blockID)
193            {
194                par1World.setBlockWithNotify(par2, par3, par4, 0);
195            }
196            else
197            {
198                int var9;
199    
200                for (var9 = 1; var9 < 4 && par1World.getBlockId(par2, var8 + var9, par4) == this.blockID; ++var9)
201                {
202                    ;
203                }
204    
205                if (var9 == 3 && par1World.getBlockId(par2, var8 + var9, par4) == Block.obsidian.blockID)
206                {
207                    boolean var10 = par1World.getBlockId(par2 - 1, par3, par4) == this.blockID || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID;
208                    boolean var11 = par1World.getBlockId(par2, par3, par4 - 1) == this.blockID || par1World.getBlockId(par2, par3, par4 + 1) == this.blockID;
209    
210                    if (var10 && var11)
211                    {
212                        par1World.setBlockWithNotify(par2, par3, par4, 0);
213                    }
214                    else
215                    {
216                        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))
217                        {
218                            par1World.setBlockWithNotify(par2, par3, par4, 0);
219                        }
220                    }
221                }
222                else
223                {
224                    par1World.setBlockWithNotify(par2, par3, par4, 0);
225                }
226            }
227        }
228    
229        @SideOnly(Side.CLIENT)
230    
231        /**
232         * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
233         * coordinates.  Args: blockAccess, x, y, z, side
234         */
235        public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
236        {
237            if (par1IBlockAccess.getBlockId(par2, par3, par4) == this.blockID)
238            {
239                return false;
240            }
241            else
242            {
243                boolean var6 = par1IBlockAccess.getBlockId(par2 - 1, par3, par4) == this.blockID && par1IBlockAccess.getBlockId(par2 - 2, par3, par4) != this.blockID;
244                boolean var7 = par1IBlockAccess.getBlockId(par2 + 1, par3, par4) == this.blockID && par1IBlockAccess.getBlockId(par2 + 2, par3, par4) != this.blockID;
245                boolean var8 = par1IBlockAccess.getBlockId(par2, par3, par4 - 1) == this.blockID && par1IBlockAccess.getBlockId(par2, par3, par4 - 2) != this.blockID;
246                boolean var9 = par1IBlockAccess.getBlockId(par2, par3, par4 + 1) == this.blockID && par1IBlockAccess.getBlockId(par2, par3, par4 + 2) != this.blockID;
247                boolean var10 = var6 || var7;
248                boolean var11 = var8 || var9;
249                return var10 && par5 == 4 ? true : (var10 && par5 == 5 ? true : (var11 && par5 == 2 ? true : var11 && par5 == 3));
250            }
251        }
252    
253        /**
254         * Returns the quantity of items to drop on block destruction.
255         */
256        public int quantityDropped(Random par1Random)
257        {
258            return 0;
259        }
260    
261        /**
262         * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity
263         */
264        public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity)
265        {
266            if (par5Entity.ridingEntity == null && par5Entity.riddenByEntity == null)
267            {
268                par5Entity.setInPortal();
269            }
270        }
271    
272        @SideOnly(Side.CLIENT)
273    
274        /**
275         * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha
276         */
277        public int getRenderBlockPass()
278        {
279            return 1;
280        }
281    
282        @SideOnly(Side.CLIENT)
283    
284        /**
285         * A randomly called display update to be able to add particles or other items for display
286         */
287        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
288        {
289            if (par5Random.nextInt(100) == 0)
290            {
291                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);
292            }
293    
294            for (int var6 = 0; var6 < 4; ++var6)
295            {
296                double var7 = (double)((float)par2 + par5Random.nextFloat());
297                double var9 = (double)((float)par3 + par5Random.nextFloat());
298                double var11 = (double)((float)par4 + par5Random.nextFloat());
299                double var13 = 0.0D;
300                double var15 = 0.0D;
301                double var17 = 0.0D;
302                int var19 = par5Random.nextInt(2) * 2 - 1;
303                var13 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D;
304                var15 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D;
305                var17 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D;
306    
307                if (par1World.getBlockId(par2 - 1, par3, par4) != this.blockID && par1World.getBlockId(par2 + 1, par3, par4) != this.blockID)
308                {
309                    var7 = (double)par2 + 0.5D + 0.25D * (double)var19;
310                    var13 = (double)(par5Random.nextFloat() * 2.0F * (float)var19);
311                }
312                else
313                {
314                    var11 = (double)par4 + 0.5D + 0.25D * (double)var19;
315                    var17 = (double)(par5Random.nextFloat() * 2.0F * (float)var19);
316                }
317    
318                par1World.spawnParticle("portal", var7, var9, var11, var13, var15, var17);
319            }
320        }
321    
322        @SideOnly(Side.CLIENT)
323    
324        /**
325         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
326         */
327        public int idPicked(World par1World, int par2, int par3, int par4)
328        {
329            return 0;
330        }
331    }