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