001    package net.minecraft.src;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    
006    public class AxisAlignedBB
007    {
008        /** ThreadLocal AABBPool */
009        private static final ThreadLocal theAABBLocalPool = new AABBLocalPool();
010        public double minX;
011        public double minY;
012        public double minZ;
013        public double maxX;
014        public double maxY;
015        public double maxZ;
016    
017        /**
018         * Returns a bounding box with the specified bounds. Args: minX, minY, minZ, maxX, maxY, maxZ
019         */
020        public static AxisAlignedBB getBoundingBox(double par0, double par2, double par4, double par6, double par8, double par10)
021        {
022            return new AxisAlignedBB(par0, par2, par4, par6, par8, par10);
023        }
024    
025        /**
026         * Gets the ThreadLocal AABBPool
027         */
028        public static AABBPool getAABBPool()
029        {
030            return (AABBPool)theAABBLocalPool.get();
031        }
032    
033        protected AxisAlignedBB(double par1, double par3, double par5, double par7, double par9, double par11)
034        {
035            this.minX = par1;
036            this.minY = par3;
037            this.minZ = par5;
038            this.maxX = par7;
039            this.maxY = par9;
040            this.maxZ = par11;
041        }
042    
043        /**
044         * Sets the bounds of the bounding box. Args: minX, minY, minZ, maxX, maxY, maxZ
045         */
046        public AxisAlignedBB setBounds(double par1, double par3, double par5, double par7, double par9, double par11)
047        {
048            this.minX = par1;
049            this.minY = par3;
050            this.minZ = par5;
051            this.maxX = par7;
052            this.maxY = par9;
053            this.maxZ = par11;
054            return this;
055        }
056    
057        /**
058         * Adds the coordinates to the bounding box extending it if the point lies outside the current ranges. Args: x, y, z
059         */
060        public AxisAlignedBB addCoord(double par1, double par3, double par5)
061        {
062            double var7 = this.minX;
063            double var9 = this.minY;
064            double var11 = this.minZ;
065            double var13 = this.maxX;
066            double var15 = this.maxY;
067            double var17 = this.maxZ;
068    
069            if (par1 < 0.0D)
070            {
071                var7 += par1;
072            }
073    
074            if (par1 > 0.0D)
075            {
076                var13 += par1;
077            }
078    
079            if (par3 < 0.0D)
080            {
081                var9 += par3;
082            }
083    
084            if (par3 > 0.0D)
085            {
086                var15 += par3;
087            }
088    
089            if (par5 < 0.0D)
090            {
091                var11 += par5;
092            }
093    
094            if (par5 > 0.0D)
095            {
096                var17 += par5;
097            }
098    
099            return getAABBPool().addOrModifyAABBInPool(var7, var9, var11, var13, var15, var17);
100        }
101    
102        /**
103         * Returns a bounding box expanded by the specified vector (if negative numbers are given it will shrink). Args: x,
104         * y, z
105         */
106        public AxisAlignedBB expand(double par1, double par3, double par5)
107        {
108            double var7 = this.minX - par1;
109            double var9 = this.minY - par3;
110            double var11 = this.minZ - par5;
111            double var13 = this.maxX + par1;
112            double var15 = this.maxY + par3;
113            double var17 = this.maxZ + par5;
114            return getAABBPool().addOrModifyAABBInPool(var7, var9, var11, var13, var15, var17);
115        }
116    
117        /**
118         * Returns a bounding box offseted by the specified vector (if negative numbers are given it will shrink). Args: x,
119         * y, z
120         */
121        public AxisAlignedBB getOffsetBoundingBox(double par1, double par3, double par5)
122        {
123            return getAABBPool().addOrModifyAABBInPool(this.minX + par1, this.minY + par3, this.minZ + par5, this.maxX + par1, this.maxY + par3, this.maxZ + par5);
124        }
125    
126        /**
127         * if instance and the argument bounding boxes overlap in the Y and Z dimensions, calculate the offset between them
128         * in the X dimension.  return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
129         * calculated offset.  Otherwise return the calculated offset.
130         */
131        public double calculateXOffset(AxisAlignedBB par1AxisAlignedBB, double par2)
132        {
133            if (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY)
134            {
135                if (par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ)
136                {
137                    double var4;
138    
139                    if (par2 > 0.0D && par1AxisAlignedBB.maxX <= this.minX)
140                    {
141                        var4 = this.minX - par1AxisAlignedBB.maxX;
142    
143                        if (var4 < par2)
144                        {
145                            par2 = var4;
146                        }
147                    }
148    
149                    if (par2 < 0.0D && par1AxisAlignedBB.minX >= this.maxX)
150                    {
151                        var4 = this.maxX - par1AxisAlignedBB.minX;
152    
153                        if (var4 > par2)
154                        {
155                            par2 = var4;
156                        }
157                    }
158    
159                    return par2;
160                }
161                else
162                {
163                    return par2;
164                }
165            }
166            else
167            {
168                return par2;
169            }
170        }
171    
172        /**
173         * if instance and the argument bounding boxes overlap in the X and Z dimensions, calculate the offset between them
174         * in the Y dimension.  return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
175         * calculated offset.  Otherwise return the calculated offset.
176         */
177        public double calculateYOffset(AxisAlignedBB par1AxisAlignedBB, double par2)
178        {
179            if (par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX)
180            {
181                if (par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ)
182                {
183                    double var4;
184    
185                    if (par2 > 0.0D && par1AxisAlignedBB.maxY <= this.minY)
186                    {
187                        var4 = this.minY - par1AxisAlignedBB.maxY;
188    
189                        if (var4 < par2)
190                        {
191                            par2 = var4;
192                        }
193                    }
194    
195                    if (par2 < 0.0D && par1AxisAlignedBB.minY >= this.maxY)
196                    {
197                        var4 = this.maxY - par1AxisAlignedBB.minY;
198    
199                        if (var4 > par2)
200                        {
201                            par2 = var4;
202                        }
203                    }
204    
205                    return par2;
206                }
207                else
208                {
209                    return par2;
210                }
211            }
212            else
213            {
214                return par2;
215            }
216        }
217    
218        /**
219         * if instance and the argument bounding boxes overlap in the Y and X dimensions, calculate the offset between them
220         * in the Z dimension.  return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
221         * calculated offset.  Otherwise return the calculated offset.
222         */
223        public double calculateZOffset(AxisAlignedBB par1AxisAlignedBB, double par2)
224        {
225            if (par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX)
226            {
227                if (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY)
228                {
229                    double var4;
230    
231                    if (par2 > 0.0D && par1AxisAlignedBB.maxZ <= this.minZ)
232                    {
233                        var4 = this.minZ - par1AxisAlignedBB.maxZ;
234    
235                        if (var4 < par2)
236                        {
237                            par2 = var4;
238                        }
239                    }
240    
241                    if (par2 < 0.0D && par1AxisAlignedBB.minZ >= this.maxZ)
242                    {
243                        var4 = this.maxZ - par1AxisAlignedBB.minZ;
244    
245                        if (var4 > par2)
246                        {
247                            par2 = var4;
248                        }
249                    }
250    
251                    return par2;
252                }
253                else
254                {
255                    return par2;
256                }
257            }
258            else
259            {
260                return par2;
261            }
262        }
263    
264        /**
265         * Returns whether the given bounding box intersects with this one. Args: axisAlignedBB
266         */
267        public boolean intersectsWith(AxisAlignedBB par1AxisAlignedBB)
268        {
269            return par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX ? (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY ? par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ : false) : false;
270        }
271    
272        /**
273         * Offsets the current bounding box by the specified coordinates. Args: x, y, z
274         */
275        public AxisAlignedBB offset(double par1, double par3, double par5)
276        {
277            this.minX += par1;
278            this.minY += par3;
279            this.minZ += par5;
280            this.maxX += par1;
281            this.maxY += par3;
282            this.maxZ += par5;
283            return this;
284        }
285    
286        /**
287         * Returns if the supplied Vec3D is completely inside the bounding box
288         */
289        public boolean isVecInside(Vec3 par1Vec3)
290        {
291            return par1Vec3.xCoord > this.minX && par1Vec3.xCoord < this.maxX ? (par1Vec3.yCoord > this.minY && par1Vec3.yCoord < this.maxY ? par1Vec3.zCoord > this.minZ && par1Vec3.zCoord < this.maxZ : false) : false;
292        }
293    
294        @SideOnly(Side.CLIENT)
295    
296        /**
297         * Returns the average length of the edges of the bounding box.
298         */
299        public double getAverageEdgeLength()
300        {
301            double var1 = this.maxX - this.minX;
302            double var3 = this.maxY - this.minY;
303            double var5 = this.maxZ - this.minZ;
304            return (var1 + var3 + var5) / 3.0D;
305        }
306    
307        /**
308         * Returns a bounding box that is inset by the specified amounts
309         */
310        public AxisAlignedBB contract(double par1, double par3, double par5)
311        {
312            double var7 = this.minX + par1;
313            double var9 = this.minY + par3;
314            double var11 = this.minZ + par5;
315            double var13 = this.maxX - par1;
316            double var15 = this.maxY - par3;
317            double var17 = this.maxZ - par5;
318            return getAABBPool().addOrModifyAABBInPool(var7, var9, var11, var13, var15, var17);
319        }
320    
321        /**
322         * Returns a copy of the bounding box.
323         */
324        public AxisAlignedBB copy()
325        {
326            return getAABBPool().addOrModifyAABBInPool(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ);
327        }
328    
329        public MovingObjectPosition calculateIntercept(Vec3 par1Vec3, Vec3 par2Vec3)
330        {
331            Vec3 var3 = par1Vec3.getIntermediateWithXValue(par2Vec3, this.minX);
332            Vec3 var4 = par1Vec3.getIntermediateWithXValue(par2Vec3, this.maxX);
333            Vec3 var5 = par1Vec3.getIntermediateWithYValue(par2Vec3, this.minY);
334            Vec3 var6 = par1Vec3.getIntermediateWithYValue(par2Vec3, this.maxY);
335            Vec3 var7 = par1Vec3.getIntermediateWithZValue(par2Vec3, this.minZ);
336            Vec3 var8 = par1Vec3.getIntermediateWithZValue(par2Vec3, this.maxZ);
337    
338            if (!this.isVecInYZ(var3))
339            {
340                var3 = null;
341            }
342    
343            if (!this.isVecInYZ(var4))
344            {
345                var4 = null;
346            }
347    
348            if (!this.isVecInXZ(var5))
349            {
350                var5 = null;
351            }
352    
353            if (!this.isVecInXZ(var6))
354            {
355                var6 = null;
356            }
357    
358            if (!this.isVecInXY(var7))
359            {
360                var7 = null;
361            }
362    
363            if (!this.isVecInXY(var8))
364            {
365                var8 = null;
366            }
367    
368            Vec3 var9 = null;
369    
370            if (var3 != null && (var9 == null || par1Vec3.squareDistanceTo(var3) < par1Vec3.squareDistanceTo(var9)))
371            {
372                var9 = var3;
373            }
374    
375            if (var4 != null && (var9 == null || par1Vec3.squareDistanceTo(var4) < par1Vec3.squareDistanceTo(var9)))
376            {
377                var9 = var4;
378            }
379    
380            if (var5 != null && (var9 == null || par1Vec3.squareDistanceTo(var5) < par1Vec3.squareDistanceTo(var9)))
381            {
382                var9 = var5;
383            }
384    
385            if (var6 != null && (var9 == null || par1Vec3.squareDistanceTo(var6) < par1Vec3.squareDistanceTo(var9)))
386            {
387                var9 = var6;
388            }
389    
390            if (var7 != null && (var9 == null || par1Vec3.squareDistanceTo(var7) < par1Vec3.squareDistanceTo(var9)))
391            {
392                var9 = var7;
393            }
394    
395            if (var8 != null && (var9 == null || par1Vec3.squareDistanceTo(var8) < par1Vec3.squareDistanceTo(var9)))
396            {
397                var9 = var8;
398            }
399    
400            if (var9 == null)
401            {
402                return null;
403            }
404            else
405            {
406                byte var10 = -1;
407    
408                if (var9 == var3)
409                {
410                    var10 = 4;
411                }
412    
413                if (var9 == var4)
414                {
415                    var10 = 5;
416                }
417    
418                if (var9 == var5)
419                {
420                    var10 = 0;
421                }
422    
423                if (var9 == var6)
424                {
425                    var10 = 1;
426                }
427    
428                if (var9 == var7)
429                {
430                    var10 = 2;
431                }
432    
433                if (var9 == var8)
434                {
435                    var10 = 3;
436                }
437    
438                return new MovingObjectPosition(0, 0, 0, var10, var9);
439            }
440        }
441    
442        /**
443         * Checks if the specified vector is within the YZ dimensions of the bounding box. Args: Vec3D
444         */
445        private boolean isVecInYZ(Vec3 par1Vec3)
446        {
447            return par1Vec3 == null ? false : par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY && par1Vec3.zCoord >= this.minZ && par1Vec3.zCoord <= this.maxZ;
448        }
449    
450        /**
451         * Checks if the specified vector is within the XZ dimensions of the bounding box. Args: Vec3D
452         */
453        private boolean isVecInXZ(Vec3 par1Vec3)
454        {
455            return par1Vec3 == null ? false : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.zCoord >= this.minZ && par1Vec3.zCoord <= this.maxZ;
456        }
457    
458        /**
459         * Checks if the specified vector is within the XY dimensions of the bounding box. Args: Vec3D
460         */
461        private boolean isVecInXY(Vec3 par1Vec3)
462        {
463            return par1Vec3 == null ? false : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY;
464        }
465    
466        /**
467         * Sets the bounding box to the same bounds as the bounding box passed in. Args: axisAlignedBB
468         */
469        public void setBB(AxisAlignedBB par1AxisAlignedBB)
470        {
471            this.minX = par1AxisAlignedBB.minX;
472            this.minY = par1AxisAlignedBB.minY;
473            this.minZ = par1AxisAlignedBB.minZ;
474            this.maxX = par1AxisAlignedBB.maxX;
475            this.maxY = par1AxisAlignedBB.maxY;
476            this.maxZ = par1AxisAlignedBB.maxZ;
477        }
478    
479        public String toString()
480        {
481            return "box[" + this.minX + ", " + this.minY + ", " + this.minZ + " -> " + this.maxX + ", " + this.maxY + ", " + this.maxZ + "]";
482        }
483    }