001package net.minecraft.client.renderer;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.nio.IntBuffer;
006import java.util.ArrayList;
007import java.util.Arrays;
008import java.util.Collections;
009import java.util.HashMap;
010import java.util.Iterator;
011import java.util.List;
012import java.util.Map;
013import java.util.Random;
014import net.minecraft.block.Block;
015import net.minecraft.block.material.Material;
016import net.minecraft.client.Minecraft;
017import net.minecraft.client.multiplayer.WorldClient;
018import net.minecraft.client.particle.EntityAuraFX;
019import net.minecraft.client.particle.EntityBreakingFX;
020import net.minecraft.client.particle.EntityBubbleFX;
021import net.minecraft.client.particle.EntityCloudFX;
022import net.minecraft.client.particle.EntityCritFX;
023import net.minecraft.client.particle.EntityDiggingFX;
024import net.minecraft.client.particle.EntityDropParticleFX;
025import net.minecraft.client.particle.EntityEnchantmentTableParticleFX;
026import net.minecraft.client.particle.EntityExplodeFX;
027import net.minecraft.client.particle.EntityFX;
028import net.minecraft.client.particle.EntityFireworkSparkFX;
029import net.minecraft.client.particle.EntityFlameFX;
030import net.minecraft.client.particle.EntityFootStepFX;
031import net.minecraft.client.particle.EntityHeartFX;
032import net.minecraft.client.particle.EntityHugeExplodeFX;
033import net.minecraft.client.particle.EntityLargeExplodeFX;
034import net.minecraft.client.particle.EntityLavaFX;
035import net.minecraft.client.particle.EntityNoteFX;
036import net.minecraft.client.particle.EntityPortalFX;
037import net.minecraft.client.particle.EntityReddustFX;
038import net.minecraft.client.particle.EntitySmokeFX;
039import net.minecraft.client.particle.EntitySnowShovelFX;
040import net.minecraft.client.particle.EntitySpellParticleFX;
041import net.minecraft.client.particle.EntitySplashFX;
042import net.minecraft.client.particle.EntitySuspendFX;
043import net.minecraft.client.renderer.culling.ICamera;
044import net.minecraft.client.renderer.entity.RenderManager;
045import net.minecraft.client.renderer.texture.IconRegister;
046import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
047import net.minecraft.crash.CrashReport;
048import net.minecraft.crash.CrashReportCategory;
049import net.minecraft.entity.Entity;
050import net.minecraft.entity.EntityLiving;
051import net.minecraft.entity.player.EntityPlayer;
052import net.minecraft.item.Item;
053import net.minecraft.item.ItemDye;
054import net.minecraft.item.ItemRecord;
055import net.minecraft.item.ItemStack;
056import net.minecraft.tileentity.TileEntity;
057import net.minecraft.util.AxisAlignedBB;
058import net.minecraft.util.EnumMovingObjectType;
059import net.minecraft.util.Icon;
060import net.minecraft.util.MathHelper;
061import net.minecraft.util.MovingObjectPosition;
062import net.minecraft.util.ReportedException;
063import net.minecraft.util.Vec3;
064import net.minecraft.world.IWorldAccess;
065import org.lwjgl.opengl.ARBOcclusionQuery;
066import org.lwjgl.opengl.GL11;
067
068import net.minecraftforge.client.IRenderHandler;
069import net.minecraftforge.client.MinecraftForgeClient;
070
071@SideOnly(Side.CLIENT)
072public class RenderGlobal implements IWorldAccess
073{
074    public List tileEntities = new ArrayList();
075    public WorldClient theWorld;
076
077    /** The RenderEngine instance used by RenderGlobal */
078    public final RenderEngine renderEngine;
079    private List worldRenderersToUpdate = new ArrayList();
080    private WorldRenderer[] sortedWorldRenderers;
081    private WorldRenderer[] worldRenderers;
082    private int renderChunksWide;
083    private int renderChunksTall;
084    private int renderChunksDeep;
085
086    /** OpenGL render lists base */
087    private int glRenderListBase;
088
089    /** A reference to the Minecraft object. */
090    public Minecraft mc;
091
092    /** Global render blocks */
093    public RenderBlocks globalRenderBlocks;
094
095    /** OpenGL occlusion query base */
096    private IntBuffer glOcclusionQueryBase;
097
098    /** Is occlusion testing enabled */
099    private boolean occlusionEnabled = false;
100
101    /**
102     * counts the cloud render updates. Used with mod to stagger some updates
103     */
104    private int cloudTickCounter = 0;
105
106    /** The star GL Call list */
107    private int starGLCallList;
108
109    /** OpenGL sky list */
110    private int glSkyList;
111
112    /** OpenGL sky list 2 */
113    private int glSkyList2;
114
115    /** Minimum block X */
116    private int minBlockX;
117
118    /** Minimum block Y */
119    private int minBlockY;
120
121    /** Minimum block Z */
122    private int minBlockZ;
123
124    /** Maximum block X */
125    private int maxBlockX;
126
127    /** Maximum block Y */
128    private int maxBlockY;
129
130    /** Maximum block Z */
131    private int maxBlockZ;
132
133    /**
134     * Stores blocks currently being broken. Key is entity ID of the thing doing the breaking. Value is a
135     * DestroyBlockProgress
136     */
137    public Map damagedBlocks = new HashMap();
138    private Icon[] destroyBlockIcons;
139    private int renderDistance = -1;
140
141    /** Render entities startup counter (init value=2) */
142    private int renderEntitiesStartupCounter = 2;
143
144    /** Count entities total */
145    private int countEntitiesTotal;
146
147    /** Count entities rendered */
148    private int countEntitiesRendered;
149
150    /** Count entities hidden */
151    private int countEntitiesHidden;
152
153    /** Dummy buffer (50k) not used */
154    int[] dummyBuf50k = new int[50000];
155
156    /** Occlusion query result */
157    IntBuffer occlusionResult = GLAllocation.createDirectIntBuffer(64);
158
159    /** How many renderers are loaded this frame that try to be rendered */
160    private int renderersLoaded;
161
162    /** How many renderers are being clipped by the frustrum this frame */
163    private int renderersBeingClipped;
164
165    /** How many renderers are being occluded this frame */
166    private int renderersBeingOccluded;
167
168    /** How many renderers are actually being rendered this frame */
169    private int renderersBeingRendered;
170
171    /**
172     * How many renderers are skipping rendering due to not having a render pass this frame
173     */
174    private int renderersSkippingRenderPass;
175
176    /** Dummy render int */
177    private int dummyRenderInt;
178
179    /** World renderers check index */
180    private int worldRenderersCheckIndex;
181
182    /** List of OpenGL lists for the current render pass */
183    private List glRenderLists = new ArrayList();
184
185    /** All render lists (fixed length 4) */
186    private RenderList[] allRenderLists = new RenderList[] {new RenderList(), new RenderList(), new RenderList(), new RenderList()};
187
188    /**
189     * Previous x position when the renderers were sorted. (Once the distance moves more than 4 units they will be
190     * resorted)
191     */
192    double prevSortX = -9999.0D;
193
194    /**
195     * Previous y position when the renderers were sorted. (Once the distance moves more than 4 units they will be
196     * resorted)
197     */
198    double prevSortY = -9999.0D;
199
200    /**
201     * Previous Z position when the renderers were sorted. (Once the distance moves more than 4 units they will be
202     * resorted)
203     */
204    double prevSortZ = -9999.0D;
205
206    /**
207     * The offset used to determine if a renderer is one of the sixteenth that are being updated this frame
208     */
209    int frustumCheckOffset = 0;
210
211    public RenderGlobal(Minecraft par1Minecraft, RenderEngine par2RenderEngine)
212    {
213        this.mc = par1Minecraft;
214        this.renderEngine = par2RenderEngine;
215        byte b0 = 34;
216        byte b1 = 32;
217        this.glRenderListBase = GLAllocation.generateDisplayLists(b0 * b0 * b1 * 3);
218        this.occlusionEnabled = OpenGlCapsChecker.checkARBOcclusion();
219
220        if (this.occlusionEnabled)
221        {
222            this.occlusionResult.clear();
223            this.glOcclusionQueryBase = GLAllocation.createDirectIntBuffer(b0 * b0 * b1);
224            this.glOcclusionQueryBase.clear();
225            this.glOcclusionQueryBase.position(0);
226            this.glOcclusionQueryBase.limit(b0 * b0 * b1);
227            ARBOcclusionQuery.glGenQueriesARB(this.glOcclusionQueryBase);
228        }
229
230        this.starGLCallList = GLAllocation.generateDisplayLists(3);
231        GL11.glPushMatrix();
232        GL11.glNewList(this.starGLCallList, GL11.GL_COMPILE);
233        this.renderStars();
234        GL11.glEndList();
235        GL11.glPopMatrix();
236        Tessellator tessellator = Tessellator.instance;
237        this.glSkyList = this.starGLCallList + 1;
238        GL11.glNewList(this.glSkyList, GL11.GL_COMPILE);
239        byte b2 = 64;
240        int i = 256 / b2 + 2;
241        float f = 16.0F;
242        int j;
243        int k;
244
245        for (j = -b2 * i; j <= b2 * i; j += b2)
246        {
247            for (k = -b2 * i; k <= b2 * i; k += b2)
248            {
249                tessellator.startDrawingQuads();
250                tessellator.addVertex((double)(j + 0), (double)f, (double)(k + 0));
251                tessellator.addVertex((double)(j + b2), (double)f, (double)(k + 0));
252                tessellator.addVertex((double)(j + b2), (double)f, (double)(k + b2));
253                tessellator.addVertex((double)(j + 0), (double)f, (double)(k + b2));
254                tessellator.draw();
255            }
256        }
257
258        GL11.glEndList();
259        this.glSkyList2 = this.starGLCallList + 2;
260        GL11.glNewList(this.glSkyList2, GL11.GL_COMPILE);
261        f = -16.0F;
262        tessellator.startDrawingQuads();
263
264        for (j = -b2 * i; j <= b2 * i; j += b2)
265        {
266            for (k = -b2 * i; k <= b2 * i; k += b2)
267            {
268                tessellator.addVertex((double)(j + b2), (double)f, (double)(k + 0));
269                tessellator.addVertex((double)(j + 0), (double)f, (double)(k + 0));
270                tessellator.addVertex((double)(j + 0), (double)f, (double)(k + b2));
271                tessellator.addVertex((double)(j + b2), (double)f, (double)(k + b2));
272            }
273        }
274
275        tessellator.draw();
276        GL11.glEndList();
277    }
278
279    private void renderStars()
280    {
281        Random random = new Random(10842L);
282        Tessellator tessellator = Tessellator.instance;
283        tessellator.startDrawingQuads();
284
285        for (int i = 0; i < 1500; ++i)
286        {
287            double d0 = (double)(random.nextFloat() * 2.0F - 1.0F);
288            double d1 = (double)(random.nextFloat() * 2.0F - 1.0F);
289            double d2 = (double)(random.nextFloat() * 2.0F - 1.0F);
290            double d3 = (double)(0.15F + random.nextFloat() * 0.1F);
291            double d4 = d0 * d0 + d1 * d1 + d2 * d2;
292
293            if (d4 < 1.0D && d4 > 0.01D)
294            {
295                d4 = 1.0D / Math.sqrt(d4);
296                d0 *= d4;
297                d1 *= d4;
298                d2 *= d4;
299                double d5 = d0 * 100.0D;
300                double d6 = d1 * 100.0D;
301                double d7 = d2 * 100.0D;
302                double d8 = Math.atan2(d0, d2);
303                double d9 = Math.sin(d8);
304                double d10 = Math.cos(d8);
305                double d11 = Math.atan2(Math.sqrt(d0 * d0 + d2 * d2), d1);
306                double d12 = Math.sin(d11);
307                double d13 = Math.cos(d11);
308                double d14 = random.nextDouble() * Math.PI * 2.0D;
309                double d15 = Math.sin(d14);
310                double d16 = Math.cos(d14);
311
312                for (int j = 0; j < 4; ++j)
313                {
314                    double d17 = 0.0D;
315                    double d18 = (double)((j & 2) - 1) * d3;
316                    double d19 = (double)((j + 1 & 2) - 1) * d3;
317                    double d20 = d18 * d16 - d19 * d15;
318                    double d21 = d19 * d16 + d18 * d15;
319                    double d22 = d20 * d12 + d17 * d13;
320                    double d23 = d17 * d12 - d20 * d13;
321                    double d24 = d23 * d9 - d21 * d10;
322                    double d25 = d21 * d9 + d23 * d10;
323                    tessellator.addVertex(d5 + d24, d6 + d22, d7 + d25);
324                }
325            }
326        }
327
328        tessellator.draw();
329    }
330
331    /**
332     * set null to clear
333     */
334    public void setWorldAndLoadRenderers(WorldClient par1WorldClient)
335    {
336        if (this.theWorld != null)
337        {
338            this.theWorld.removeWorldAccess(this);
339        }
340
341        this.prevSortX = -9999.0D;
342        this.prevSortY = -9999.0D;
343        this.prevSortZ = -9999.0D;
344        RenderManager.instance.set(par1WorldClient);
345        this.theWorld = par1WorldClient;
346        this.globalRenderBlocks = new RenderBlocks(par1WorldClient);
347
348        if (par1WorldClient != null)
349        {
350            par1WorldClient.addWorldAccess(this);
351            this.loadRenderers();
352        }
353    }
354
355    /**
356     * Loads all the renderers and sets up the basic settings usage
357     */
358    public void loadRenderers()
359    {
360        if (this.theWorld != null)
361        {
362            Block.leaves.setGraphicsLevel(this.mc.gameSettings.fancyGraphics);
363            this.renderDistance = this.mc.gameSettings.renderDistance;
364            int i;
365
366            if (this.worldRenderers != null)
367            {
368                for (i = 0; i < this.worldRenderers.length; ++i)
369                {
370                    this.worldRenderers[i].stopRendering();
371                }
372            }
373
374            i = 64 << 3 - this.renderDistance;
375
376            if (i > 400)
377            {
378                i = 400;
379            }
380
381            this.renderChunksWide = i / 16 + 1;
382            this.renderChunksTall = 16;
383            this.renderChunksDeep = i / 16 + 1;
384            this.worldRenderers = new WorldRenderer[this.renderChunksWide * this.renderChunksTall * this.renderChunksDeep];
385            this.sortedWorldRenderers = new WorldRenderer[this.renderChunksWide * this.renderChunksTall * this.renderChunksDeep];
386            int j = 0;
387            int k = 0;
388            this.minBlockX = 0;
389            this.minBlockY = 0;
390            this.minBlockZ = 0;
391            this.maxBlockX = this.renderChunksWide;
392            this.maxBlockY = this.renderChunksTall;
393            this.maxBlockZ = this.renderChunksDeep;
394            int l;
395
396            for (l = 0; l < this.worldRenderersToUpdate.size(); ++l)
397            {
398                ((WorldRenderer)this.worldRenderersToUpdate.get(l)).needsUpdate = false;
399            }
400
401            this.worldRenderersToUpdate.clear();
402            this.tileEntities.clear();
403
404            for (l = 0; l < this.renderChunksWide; ++l)
405            {
406                for (int i1 = 0; i1 < this.renderChunksTall; ++i1)
407                {
408                    for (int j1 = 0; j1 < this.renderChunksDeep; ++j1)
409                    {
410                        this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l] = new WorldRenderer(this.theWorld, this.tileEntities, l * 16, i1 * 16, j1 * 16, this.glRenderListBase + j);
411
412                        if (this.occlusionEnabled)
413                        {
414                            this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l].glOcclusionQuery = this.glOcclusionQueryBase.get(k);
415                        }
416
417                        this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l].isWaitingOnOcclusionQuery = false;
418                        this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l].isVisible = true;
419                        this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l].isInFrustum = true;
420                        this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l].chunkIndex = k++;
421                        this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l].markDirty();
422                        this.sortedWorldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l] = this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l];
423                        this.worldRenderersToUpdate.add(this.worldRenderers[(j1 * this.renderChunksTall + i1) * this.renderChunksWide + l]);
424                        j += 3;
425                    }
426                }
427            }
428
429            if (this.theWorld != null)
430            {
431                EntityLiving entityliving = this.mc.renderViewEntity;
432
433                if (entityliving != null)
434                {
435                    this.markRenderersForNewPosition(MathHelper.floor_double(entityliving.posX), MathHelper.floor_double(entityliving.posY), MathHelper.floor_double(entityliving.posZ));
436                    Arrays.sort(this.sortedWorldRenderers, new EntitySorter(entityliving));
437                }
438            }
439
440            this.renderEntitiesStartupCounter = 2;
441        }
442    }
443
444    /**
445     * Renders all entities within range and within the frustrum. Args: pos, frustrum, partialTickTime
446     */
447    public void renderEntities(Vec3 par1Vec3, ICamera par2ICamera, float par3)
448    {
449        int pass = MinecraftForgeClient.getRenderPass();
450        if (this.renderEntitiesStartupCounter > 0)
451        {
452            if (pass > 0)
453            {
454                return;
455            }
456            --this.renderEntitiesStartupCounter;
457        }
458        else
459        {
460            this.theWorld.theProfiler.startSection("prepare");
461            if (pass == 0)
462            {
463                TileEntityRenderer.instance.cacheActiveRenderInfo(this.theWorld, this.renderEngine, this.mc.fontRenderer, this.mc.renderViewEntity, par3);
464                RenderManager.instance.cacheActiveRenderInfo(this.theWorld, this.renderEngine, this.mc.fontRenderer, this.mc.renderViewEntity, this.mc.pointedEntityLiving, this.mc.gameSettings, par3);
465                this.countEntitiesTotal = 0;
466                this.countEntitiesRendered = 0;
467                this.countEntitiesHidden = 0;
468                EntityLiving entityliving = this.mc.renderViewEntity;
469                RenderManager.renderPosX = entityliving.lastTickPosX + (entityliving.posX - entityliving.lastTickPosX) * (double)par3;
470                RenderManager.renderPosY = entityliving.lastTickPosY + (entityliving.posY - entityliving.lastTickPosY) * (double)par3;
471                RenderManager.renderPosZ = entityliving.lastTickPosZ + (entityliving.posZ - entityliving.lastTickPosZ) * (double)par3;
472                TileEntityRenderer.staticPlayerX = entityliving.lastTickPosX + (entityliving.posX - entityliving.lastTickPosX) * (double)par3;
473                TileEntityRenderer.staticPlayerY = entityliving.lastTickPosY + (entityliving.posY - entityliving.lastTickPosY) * (double)par3;
474                TileEntityRenderer.staticPlayerZ = entityliving.lastTickPosZ + (entityliving.posZ - entityliving.lastTickPosZ) * (double)par3;
475            }
476            this.mc.entityRenderer.enableLightmap((double)par3);
477            this.theWorld.theProfiler.endStartSection("global");
478            List list = this.theWorld.getLoadedEntityList();
479            if (pass == 0)
480            {
481                this.countEntitiesTotal = list.size();
482            }
483            int i;
484            Entity entity;
485
486            for (i = 0; i < this.theWorld.weatherEffects.size(); ++i)
487            {
488                entity = (Entity)this.theWorld.weatherEffects.get(i);
489                if (!entity.shouldRenderInPass(pass)) continue;
490                ++this.countEntitiesRendered;
491
492                if (entity.isInRangeToRenderVec3D(par1Vec3))
493                {
494                    RenderManager.instance.renderEntity(entity, par3);
495                }
496            }
497
498            this.theWorld.theProfiler.endStartSection("entities");
499
500            for (i = 0; i < list.size(); ++i)
501            {
502                entity = (Entity)list.get(i);
503                if (!entity.shouldRenderInPass(pass)) continue;
504
505                if (entity.isInRangeToRenderVec3D(par1Vec3) && (entity.ignoreFrustumCheck || par2ICamera.isBoundingBoxInFrustum(entity.boundingBox) || entity.riddenByEntity == this.mc.thePlayer) && (entity != this.mc.renderViewEntity || this.mc.gameSettings.thirdPersonView != 0 || this.mc.renderViewEntity.isPlayerSleeping()) && this.theWorld.blockExists(MathHelper.floor_double(entity.posX), 0, MathHelper.floor_double(entity.posZ)))
506                {
507                    ++this.countEntitiesRendered;
508                    RenderManager.instance.renderEntity(entity, par3);
509                }
510            }
511
512            this.theWorld.theProfiler.endStartSection("tileentities");
513            RenderHelper.enableStandardItemLighting();
514
515            for (i = 0; i < this.tileEntities.size(); ++i)
516            {
517                TileEntity tile = (TileEntity)tileEntities.get(i);
518                if (tile.shouldRenderInPass(pass) && par2ICamera.isBoundingBoxInFrustum(tile.getRenderBoundingBox()))
519                {
520                    TileEntityRenderer.instance.renderTileEntity(tile, par3);
521                }
522            }
523
524            this.mc.entityRenderer.disableLightmap((double)par3);
525            this.theWorld.theProfiler.endSection();
526        }
527    }
528
529    /**
530     * Gets the render info for use on the Debug screen
531     */
532    public String getDebugInfoRenders()
533    {
534        return "C: " + this.renderersBeingRendered + "/" + this.renderersLoaded + ". F: " + this.renderersBeingClipped + ", O: " + this.renderersBeingOccluded + ", E: " + this.renderersSkippingRenderPass;
535    }
536
537    /**
538     * Gets the entities info for use on the Debug screen
539     */
540    public String getDebugInfoEntities()
541    {
542        return "E: " + this.countEntitiesRendered + "/" + this.countEntitiesTotal + ". B: " + this.countEntitiesHidden + ", I: " + (this.countEntitiesTotal - this.countEntitiesHidden - this.countEntitiesRendered);
543    }
544
545    /**
546     * Goes through all the renderers setting new positions on them and those that have their position changed are
547     * adding to be updated
548     */
549    private void markRenderersForNewPosition(int par1, int par2, int par3)
550    {
551        par1 -= 8;
552        par2 -= 8;
553        par3 -= 8;
554        this.minBlockX = Integer.MAX_VALUE;
555        this.minBlockY = Integer.MAX_VALUE;
556        this.minBlockZ = Integer.MAX_VALUE;
557        this.maxBlockX = Integer.MIN_VALUE;
558        this.maxBlockY = Integer.MIN_VALUE;
559        this.maxBlockZ = Integer.MIN_VALUE;
560        int l = this.renderChunksWide * 16;
561        int i1 = l / 2;
562
563        for (int j1 = 0; j1 < this.renderChunksWide; ++j1)
564        {
565            int k1 = j1 * 16;
566            int l1 = k1 + i1 - par1;
567
568            if (l1 < 0)
569            {
570                l1 -= l - 1;
571            }
572
573            l1 /= l;
574            k1 -= l1 * l;
575
576            if (k1 < this.minBlockX)
577            {
578                this.minBlockX = k1;
579            }
580
581            if (k1 > this.maxBlockX)
582            {
583                this.maxBlockX = k1;
584            }
585
586            for (int i2 = 0; i2 < this.renderChunksDeep; ++i2)
587            {
588                int j2 = i2 * 16;
589                int k2 = j2 + i1 - par3;
590
591                if (k2 < 0)
592                {
593                    k2 -= l - 1;
594                }
595
596                k2 /= l;
597                j2 -= k2 * l;
598
599                if (j2 < this.minBlockZ)
600                {
601                    this.minBlockZ = j2;
602                }
603
604                if (j2 > this.maxBlockZ)
605                {
606                    this.maxBlockZ = j2;
607                }
608
609                for (int l2 = 0; l2 < this.renderChunksTall; ++l2)
610                {
611                    int i3 = l2 * 16;
612
613                    if (i3 < this.minBlockY)
614                    {
615                        this.minBlockY = i3;
616                    }
617
618                    if (i3 > this.maxBlockY)
619                    {
620                        this.maxBlockY = i3;
621                    }
622
623                    WorldRenderer worldrenderer = this.worldRenderers[(i2 * this.renderChunksTall + l2) * this.renderChunksWide + j1];
624                    boolean flag = worldrenderer.needsUpdate;
625                    worldrenderer.setPosition(k1, i3, j2);
626
627                    if (!flag && worldrenderer.needsUpdate)
628                    {
629                        this.worldRenderersToUpdate.add(worldrenderer);
630                    }
631                }
632            }
633        }
634    }
635
636    /**
637     * Sorts all renderers based on the passed in entity. Args: entityLiving, renderPass, partialTickTime
638     */
639    public int sortAndRender(EntityLiving par1EntityLiving, int par2, double par3)
640    {
641        this.theWorld.theProfiler.startSection("sortchunks");
642
643        for (int j = 0; j < 10; ++j)
644        {
645            this.worldRenderersCheckIndex = (this.worldRenderersCheckIndex + 1) % this.worldRenderers.length;
646            WorldRenderer worldrenderer = this.worldRenderers[this.worldRenderersCheckIndex];
647
648            if (worldrenderer.needsUpdate && !this.worldRenderersToUpdate.contains(worldrenderer))
649            {
650                this.worldRenderersToUpdate.add(worldrenderer);
651            }
652        }
653
654        if (this.mc.gameSettings.renderDistance != this.renderDistance)
655        {
656            this.loadRenderers();
657        }
658
659        if (par2 == 0)
660        {
661            this.renderersLoaded = 0;
662            this.dummyRenderInt = 0;
663            this.renderersBeingClipped = 0;
664            this.renderersBeingOccluded = 0;
665            this.renderersBeingRendered = 0;
666            this.renderersSkippingRenderPass = 0;
667        }
668
669        double d1 = par1EntityLiving.lastTickPosX + (par1EntityLiving.posX - par1EntityLiving.lastTickPosX) * par3;
670        double d2 = par1EntityLiving.lastTickPosY + (par1EntityLiving.posY - par1EntityLiving.lastTickPosY) * par3;
671        double d3 = par1EntityLiving.lastTickPosZ + (par1EntityLiving.posZ - par1EntityLiving.lastTickPosZ) * par3;
672        double d4 = par1EntityLiving.posX - this.prevSortX;
673        double d5 = par1EntityLiving.posY - this.prevSortY;
674        double d6 = par1EntityLiving.posZ - this.prevSortZ;
675
676        if (d4 * d4 + d5 * d5 + d6 * d6 > 16.0D)
677        {
678            this.prevSortX = par1EntityLiving.posX;
679            this.prevSortY = par1EntityLiving.posY;
680            this.prevSortZ = par1EntityLiving.posZ;
681            this.markRenderersForNewPosition(MathHelper.floor_double(par1EntityLiving.posX), MathHelper.floor_double(par1EntityLiving.posY), MathHelper.floor_double(par1EntityLiving.posZ));
682            Arrays.sort(this.sortedWorldRenderers, new EntitySorter(par1EntityLiving));
683        }
684
685        RenderHelper.disableStandardItemLighting();
686        byte b0 = 0;
687        int k;
688
689        if (this.occlusionEnabled && this.mc.gameSettings.advancedOpengl && !this.mc.gameSettings.anaglyph && par2 == 0)
690        {
691            byte b1 = 0;
692            int l = 16;
693            this.checkOcclusionQueryResult(b1, l);
694
695            for (int i1 = b1; i1 < l; ++i1)
696            {
697                this.sortedWorldRenderers[i1].isVisible = true;
698            }
699
700            this.theWorld.theProfiler.endStartSection("render");
701            k = b0 + this.renderSortedRenderers(b1, l, par2, par3);
702
703            do
704            {
705                this.theWorld.theProfiler.endStartSection("occ");
706                int j1 = l;
707                l *= 2;
708
709                if (l > this.sortedWorldRenderers.length)
710                {
711                    l = this.sortedWorldRenderers.length;
712                }
713
714                GL11.glDisable(GL11.GL_TEXTURE_2D);
715                GL11.glDisable(GL11.GL_LIGHTING);
716                GL11.glDisable(GL11.GL_ALPHA_TEST);
717                GL11.glDisable(GL11.GL_FOG);
718                GL11.glColorMask(false, false, false, false);
719                GL11.glDepthMask(false);
720                this.theWorld.theProfiler.startSection("check");
721                this.checkOcclusionQueryResult(j1, l);
722                this.theWorld.theProfiler.endSection();
723                GL11.glPushMatrix();
724                float f = 0.0F;
725                float f1 = 0.0F;
726                float f2 = 0.0F;
727
728                for (int k1 = j1; k1 < l; ++k1)
729                {
730                    if (this.sortedWorldRenderers[k1].skipAllRenderPasses())
731                    {
732                        this.sortedWorldRenderers[k1].isInFrustum = false;
733                    }
734                    else
735                    {
736                        if (!this.sortedWorldRenderers[k1].isInFrustum)
737                        {
738                            this.sortedWorldRenderers[k1].isVisible = true;
739                        }
740
741                        if (this.sortedWorldRenderers[k1].isInFrustum && !this.sortedWorldRenderers[k1].isWaitingOnOcclusionQuery)
742                        {
743                            float f3 = MathHelper.sqrt_float(this.sortedWorldRenderers[k1].distanceToEntitySquared(par1EntityLiving));
744                            int l1 = (int)(1.0F + f3 / 128.0F);
745
746                            if (this.cloudTickCounter % l1 == k1 % l1)
747                            {
748                                WorldRenderer worldrenderer1 = this.sortedWorldRenderers[k1];
749                                float f4 = (float)((double)worldrenderer1.posXMinus - d1);
750                                float f5 = (float)((double)worldrenderer1.posYMinus - d2);
751                                float f6 = (float)((double)worldrenderer1.posZMinus - d3);
752                                float f7 = f4 - f;
753                                float f8 = f5 - f1;
754                                float f9 = f6 - f2;
755
756                                if (f7 != 0.0F || f8 != 0.0F || f9 != 0.0F)
757                                {
758                                    GL11.glTranslatef(f7, f8, f9);
759                                    f += f7;
760                                    f1 += f8;
761                                    f2 += f9;
762                                }
763
764                                this.theWorld.theProfiler.startSection("bb");
765                                ARBOcclusionQuery.glBeginQueryARB(ARBOcclusionQuery.GL_SAMPLES_PASSED_ARB, this.sortedWorldRenderers[k1].glOcclusionQuery);
766                                this.sortedWorldRenderers[k1].callOcclusionQueryList();
767                                ARBOcclusionQuery.glEndQueryARB(ARBOcclusionQuery.GL_SAMPLES_PASSED_ARB);
768                                this.theWorld.theProfiler.endSection();
769                                this.sortedWorldRenderers[k1].isWaitingOnOcclusionQuery = true;
770                            }
771                        }
772                    }
773                }
774
775                GL11.glPopMatrix();
776
777                if (this.mc.gameSettings.anaglyph)
778                {
779                    if (EntityRenderer.anaglyphField == 0)
780                    {
781                        GL11.glColorMask(false, true, true, true);
782                    }
783                    else
784                    {
785                        GL11.glColorMask(true, false, false, true);
786                    }
787                }
788                else
789                {
790                    GL11.glColorMask(true, true, true, true);
791                }
792
793                GL11.glDepthMask(true);
794                GL11.glEnable(GL11.GL_TEXTURE_2D);
795                GL11.glEnable(GL11.GL_ALPHA_TEST);
796                GL11.glEnable(GL11.GL_FOG);
797                this.theWorld.theProfiler.endStartSection("render");
798                k += this.renderSortedRenderers(j1, l, par2, par3);
799            }
800            while (l < this.sortedWorldRenderers.length);
801        }
802        else
803        {
804            this.theWorld.theProfiler.endStartSection("render");
805            k = b0 + this.renderSortedRenderers(0, this.sortedWorldRenderers.length, par2, par3);
806        }
807
808        this.theWorld.theProfiler.endSection();
809        return k;
810    }
811
812    private void checkOcclusionQueryResult(int par1, int par2)
813    {
814        for (int k = par1; k < par2; ++k)
815        {
816            if (this.sortedWorldRenderers[k].isWaitingOnOcclusionQuery)
817            {
818                this.occlusionResult.clear();
819                ARBOcclusionQuery.glGetQueryObjectuARB(this.sortedWorldRenderers[k].glOcclusionQuery, ARBOcclusionQuery.GL_QUERY_RESULT_AVAILABLE_ARB, this.occlusionResult);
820
821                if (this.occlusionResult.get(0) != 0)
822                {
823                    this.sortedWorldRenderers[k].isWaitingOnOcclusionQuery = false;
824                    this.occlusionResult.clear();
825                    ARBOcclusionQuery.glGetQueryObjectuARB(this.sortedWorldRenderers[k].glOcclusionQuery, ARBOcclusionQuery.GL_QUERY_RESULT_ARB, this.occlusionResult);
826                    this.sortedWorldRenderers[k].isVisible = this.occlusionResult.get(0) != 0;
827                }
828            }
829        }
830    }
831
832    /**
833     * Renders the sorted renders for the specified render pass. Args: startRenderer, numRenderers, renderPass,
834     * partialTickTime
835     */
836    private int renderSortedRenderers(int par1, int par2, int par3, double par4)
837    {
838        this.glRenderLists.clear();
839        int l = 0;
840
841        for (int i1 = par1; i1 < par2; ++i1)
842        {
843            if (par3 == 0)
844            {
845                ++this.renderersLoaded;
846
847                if (this.sortedWorldRenderers[i1].skipRenderPass[par3])
848                {
849                    ++this.renderersSkippingRenderPass;
850                }
851                else if (!this.sortedWorldRenderers[i1].isInFrustum)
852                {
853                    ++this.renderersBeingClipped;
854                }
855                else if (this.occlusionEnabled && !this.sortedWorldRenderers[i1].isVisible)
856                {
857                    ++this.renderersBeingOccluded;
858                }
859                else
860                {
861                    ++this.renderersBeingRendered;
862                }
863            }
864
865            if (!this.sortedWorldRenderers[i1].skipRenderPass[par3] && this.sortedWorldRenderers[i1].isInFrustum && (!this.occlusionEnabled || this.sortedWorldRenderers[i1].isVisible))
866            {
867                int j1 = this.sortedWorldRenderers[i1].getGLCallListForPass(par3);
868
869                if (j1 >= 0)
870                {
871                    this.glRenderLists.add(this.sortedWorldRenderers[i1]);
872                    ++l;
873                }
874            }
875        }
876
877        EntityLiving entityliving = this.mc.renderViewEntity;
878        double d1 = entityliving.lastTickPosX + (entityliving.posX - entityliving.lastTickPosX) * par4;
879        double d2 = entityliving.lastTickPosY + (entityliving.posY - entityliving.lastTickPosY) * par4;
880        double d3 = entityliving.lastTickPosZ + (entityliving.posZ - entityliving.lastTickPosZ) * par4;
881        int k1 = 0;
882        int l1;
883
884        for (l1 = 0; l1 < this.allRenderLists.length; ++l1)
885        {
886            this.allRenderLists[l1].func_78421_b();
887        }
888
889        for (l1 = 0; l1 < this.glRenderLists.size(); ++l1)
890        {
891            WorldRenderer worldrenderer = (WorldRenderer)this.glRenderLists.get(l1);
892            int i2 = -1;
893
894            for (int j2 = 0; j2 < k1; ++j2)
895            {
896                if (this.allRenderLists[j2].func_78418_a(worldrenderer.posXMinus, worldrenderer.posYMinus, worldrenderer.posZMinus))
897                {
898                    i2 = j2;
899                }
900            }
901
902            if (i2 < 0)
903            {
904                i2 = k1++;
905                this.allRenderLists[i2].func_78422_a(worldrenderer.posXMinus, worldrenderer.posYMinus, worldrenderer.posZMinus, d1, d2, d3);
906            }
907
908            this.allRenderLists[i2].func_78420_a(worldrenderer.getGLCallListForPass(par3));
909        }
910
911        this.renderAllRenderLists(par3, par4);
912        return l;
913    }
914
915    /**
916     * Render all render lists
917     */
918    public void renderAllRenderLists(int par1, double par2)
919    {
920        this.mc.entityRenderer.enableLightmap(par2);
921
922        for (int j = 0; j < this.allRenderLists.length; ++j)
923        {
924            this.allRenderLists[j].func_78419_a();
925        }
926
927        this.mc.entityRenderer.disableLightmap(par2);
928    }
929
930    public void updateClouds()
931    {
932        ++this.cloudTickCounter;
933
934        if (this.cloudTickCounter % 20 == 0)
935        {
936            Iterator iterator = this.damagedBlocks.values().iterator();
937
938            while (iterator.hasNext())
939            {
940                DestroyBlockProgress destroyblockprogress = (DestroyBlockProgress)iterator.next();
941                int i = destroyblockprogress.getCreationCloudUpdateTick();
942
943                if (this.cloudTickCounter - i > 400)
944                {
945                    iterator.remove();
946                }
947            }
948        }
949    }
950
951    /**
952     * Renders the sky with the partial tick time. Args: partialTickTime
953     */
954    public void renderSky(float par1)
955    {
956        IRenderHandler skyProvider = null;
957        if ((skyProvider = this.mc.theWorld.provider.getSkyRenderer()) != null)
958        {
959            skyProvider.render(par1, this.theWorld, mc);
960            return;
961        }
962        if (this.mc.theWorld.provider.dimensionId == 1)
963        {
964            GL11.glDisable(GL11.GL_FOG);
965            GL11.glDisable(GL11.GL_ALPHA_TEST);
966            GL11.glEnable(GL11.GL_BLEND);
967            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
968            RenderHelper.disableStandardItemLighting();
969            GL11.glDepthMask(false);
970            this.renderEngine.bindTexture("/misc/tunnel.png");
971            Tessellator tessellator = Tessellator.instance;
972
973            for (int i = 0; i < 6; ++i)
974            {
975                GL11.glPushMatrix();
976
977                if (i == 1)
978                {
979                    GL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F);
980                }
981
982                if (i == 2)
983                {
984                    GL11.glRotatef(-90.0F, 1.0F, 0.0F, 0.0F);
985                }
986
987                if (i == 3)
988                {
989                    GL11.glRotatef(180.0F, 1.0F, 0.0F, 0.0F);
990                }
991
992                if (i == 4)
993                {
994                    GL11.glRotatef(90.0F, 0.0F, 0.0F, 1.0F);
995                }
996
997                if (i == 5)
998                {
999                    GL11.glRotatef(-90.0F, 0.0F, 0.0F, 1.0F);
1000                }
1001
1002                tessellator.startDrawingQuads();
1003                tessellator.setColorOpaque_I(2631720);
1004                tessellator.addVertexWithUV(-100.0D, -100.0D, -100.0D, 0.0D, 0.0D);
1005                tessellator.addVertexWithUV(-100.0D, -100.0D, 100.0D, 0.0D, 16.0D);
1006                tessellator.addVertexWithUV(100.0D, -100.0D, 100.0D, 16.0D, 16.0D);
1007                tessellator.addVertexWithUV(100.0D, -100.0D, -100.0D, 16.0D, 0.0D);
1008                tessellator.draw();
1009                GL11.glPopMatrix();
1010            }
1011
1012            GL11.glDepthMask(true);
1013            GL11.glEnable(GL11.GL_TEXTURE_2D);
1014            GL11.glEnable(GL11.GL_ALPHA_TEST);
1015        }
1016        else if (this.mc.theWorld.provider.isSurfaceWorld())
1017        {
1018            GL11.glDisable(GL11.GL_TEXTURE_2D);
1019            Vec3 vec3 = this.theWorld.getSkyColor(this.mc.renderViewEntity, par1);
1020            float f1 = (float)vec3.xCoord;
1021            float f2 = (float)vec3.yCoord;
1022            float f3 = (float)vec3.zCoord;
1023            float f4;
1024
1025            if (this.mc.gameSettings.anaglyph)
1026            {
1027                float f5 = (f1 * 30.0F + f2 * 59.0F + f3 * 11.0F) / 100.0F;
1028                float f6 = (f1 * 30.0F + f2 * 70.0F) / 100.0F;
1029                f4 = (f1 * 30.0F + f3 * 70.0F) / 100.0F;
1030                f1 = f5;
1031                f2 = f6;
1032                f3 = f4;
1033            }
1034
1035            GL11.glColor3f(f1, f2, f3);
1036            Tessellator tessellator1 = Tessellator.instance;
1037            GL11.glDepthMask(false);
1038            GL11.glEnable(GL11.GL_FOG);
1039            GL11.glColor3f(f1, f2, f3);
1040            GL11.glCallList(this.glSkyList);
1041            GL11.glDisable(GL11.GL_FOG);
1042            GL11.glDisable(GL11.GL_ALPHA_TEST);
1043            GL11.glEnable(GL11.GL_BLEND);
1044            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1045            RenderHelper.disableStandardItemLighting();
1046            float[] afloat = this.theWorld.provider.calcSunriseSunsetColors(this.theWorld.getCelestialAngle(par1), par1);
1047            float f7;
1048            float f8;
1049            float f9;
1050            float f10;
1051
1052            if (afloat != null)
1053            {
1054                GL11.glDisable(GL11.GL_TEXTURE_2D);
1055                GL11.glShadeModel(GL11.GL_SMOOTH);
1056                GL11.glPushMatrix();
1057                GL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F);
1058                GL11.glRotatef(MathHelper.sin(this.theWorld.getCelestialAngleRadians(par1)) < 0.0F ? 180.0F : 0.0F, 0.0F, 0.0F, 1.0F);
1059                GL11.glRotatef(90.0F, 0.0F, 0.0F, 1.0F);
1060                f4 = afloat[0];
1061                f7 = afloat[1];
1062                f8 = afloat[2];
1063                float f11;
1064
1065                if (this.mc.gameSettings.anaglyph)
1066                {
1067                    f9 = (f4 * 30.0F + f7 * 59.0F + f8 * 11.0F) / 100.0F;
1068                    f10 = (f4 * 30.0F + f7 * 70.0F) / 100.0F;
1069                    f11 = (f4 * 30.0F + f8 * 70.0F) / 100.0F;
1070                    f4 = f9;
1071                    f7 = f10;
1072                    f8 = f11;
1073                }
1074
1075                tessellator1.startDrawing(6);
1076                tessellator1.setColorRGBA_F(f4, f7, f8, afloat[3]);
1077                tessellator1.addVertex(0.0D, 100.0D, 0.0D);
1078                byte b0 = 16;
1079                tessellator1.setColorRGBA_F(afloat[0], afloat[1], afloat[2], 0.0F);
1080
1081                for (int j = 0; j <= b0; ++j)
1082                {
1083                    f11 = (float)j * (float)Math.PI * 2.0F / (float)b0;
1084                    float f12 = MathHelper.sin(f11);
1085                    float f13 = MathHelper.cos(f11);
1086                    tessellator1.addVertex((double)(f12 * 120.0F), (double)(f13 * 120.0F), (double)(-f13 * 40.0F * afloat[3]));
1087                }
1088
1089                tessellator1.draw();
1090                GL11.glPopMatrix();
1091                GL11.glShadeModel(GL11.GL_FLAT);
1092            }
1093
1094            GL11.glEnable(GL11.GL_TEXTURE_2D);
1095            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1096            GL11.glPushMatrix();
1097            f4 = 1.0F - this.theWorld.getRainStrength(par1);
1098            f7 = 0.0F;
1099            f8 = 0.0F;
1100            f9 = 0.0F;
1101            GL11.glColor4f(1.0F, 1.0F, 1.0F, f4);
1102            GL11.glTranslatef(f7, f8, f9);
1103            GL11.glRotatef(-90.0F, 0.0F, 1.0F, 0.0F);
1104            GL11.glRotatef(this.theWorld.getCelestialAngle(par1) * 360.0F, 1.0F, 0.0F, 0.0F);
1105            f10 = 30.0F;
1106            this.renderEngine.bindTexture("/environment/sun.png");
1107            tessellator1.startDrawingQuads();
1108            tessellator1.addVertexWithUV((double)(-f10), 100.0D, (double)(-f10), 0.0D, 0.0D);
1109            tessellator1.addVertexWithUV((double)f10, 100.0D, (double)(-f10), 1.0D, 0.0D);
1110            tessellator1.addVertexWithUV((double)f10, 100.0D, (double)f10, 1.0D, 1.0D);
1111            tessellator1.addVertexWithUV((double)(-f10), 100.0D, (double)f10, 0.0D, 1.0D);
1112            tessellator1.draw();
1113            f10 = 20.0F;
1114            this.renderEngine.bindTexture("/environment/moon_phases.png");
1115            int k = this.theWorld.getMoonPhase();
1116            int l = k % 4;
1117            int i1 = k / 4 % 2;
1118            float f14 = (float)(l + 0) / 4.0F;
1119            float f15 = (float)(i1 + 0) / 2.0F;
1120            float f16 = (float)(l + 1) / 4.0F;
1121            float f17 = (float)(i1 + 1) / 2.0F;
1122            tessellator1.startDrawingQuads();
1123            tessellator1.addVertexWithUV((double)(-f10), -100.0D, (double)f10, (double)f16, (double)f17);
1124            tessellator1.addVertexWithUV((double)f10, -100.0D, (double)f10, (double)f14, (double)f17);
1125            tessellator1.addVertexWithUV((double)f10, -100.0D, (double)(-f10), (double)f14, (double)f15);
1126            tessellator1.addVertexWithUV((double)(-f10), -100.0D, (double)(-f10), (double)f16, (double)f15);
1127            tessellator1.draw();
1128            GL11.glDisable(GL11.GL_TEXTURE_2D);
1129            float f18 = this.theWorld.getStarBrightness(par1) * f4;
1130
1131            if (f18 > 0.0F)
1132            {
1133                GL11.glColor4f(f18, f18, f18, f18);
1134                GL11.glCallList(this.starGLCallList);
1135            }
1136
1137            GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
1138            GL11.glDisable(GL11.GL_BLEND);
1139            GL11.glEnable(GL11.GL_ALPHA_TEST);
1140            GL11.glEnable(GL11.GL_FOG);
1141            GL11.glPopMatrix();
1142            GL11.glDisable(GL11.GL_TEXTURE_2D);
1143            GL11.glColor3f(0.0F, 0.0F, 0.0F);
1144            double d0 = this.mc.thePlayer.getPosition(par1).yCoord - this.theWorld.getHorizon();
1145
1146            if (d0 < 0.0D)
1147            {
1148                GL11.glPushMatrix();
1149                GL11.glTranslatef(0.0F, 12.0F, 0.0F);
1150                GL11.glCallList(this.glSkyList2);
1151                GL11.glPopMatrix();
1152                f8 = 1.0F;
1153                f9 = -((float)(d0 + 65.0D));
1154                f10 = -f8;
1155                tessellator1.startDrawingQuads();
1156                tessellator1.setColorRGBA_I(0, 255);
1157                tessellator1.addVertex((double)(-f8), (double)f9, (double)f8);
1158                tessellator1.addVertex((double)f8, (double)f9, (double)f8);
1159                tessellator1.addVertex((double)f8, (double)f10, (double)f8);
1160                tessellator1.addVertex((double)(-f8), (double)f10, (double)f8);
1161                tessellator1.addVertex((double)(-f8), (double)f10, (double)(-f8));
1162                tessellator1.addVertex((double)f8, (double)f10, (double)(-f8));
1163                tessellator1.addVertex((double)f8, (double)f9, (double)(-f8));
1164                tessellator1.addVertex((double)(-f8), (double)f9, (double)(-f8));
1165                tessellator1.addVertex((double)f8, (double)f10, (double)(-f8));
1166                tessellator1.addVertex((double)f8, (double)f10, (double)f8);
1167                tessellator1.addVertex((double)f8, (double)f9, (double)f8);
1168                tessellator1.addVertex((double)f8, (double)f9, (double)(-f8));
1169                tessellator1.addVertex((double)(-f8), (double)f9, (double)(-f8));
1170                tessellator1.addVertex((double)(-f8), (double)f9, (double)f8);
1171                tessellator1.addVertex((double)(-f8), (double)f10, (double)f8);
1172                tessellator1.addVertex((double)(-f8), (double)f10, (double)(-f8));
1173                tessellator1.addVertex((double)(-f8), (double)f10, (double)(-f8));
1174                tessellator1.addVertex((double)(-f8), (double)f10, (double)f8);
1175                tessellator1.addVertex((double)f8, (double)f10, (double)f8);
1176                tessellator1.addVertex((double)f8, (double)f10, (double)(-f8));
1177                tessellator1.draw();
1178            }
1179
1180            if (this.theWorld.provider.isSkyColored())
1181            {
1182                GL11.glColor3f(f1 * 0.2F + 0.04F, f2 * 0.2F + 0.04F, f3 * 0.6F + 0.1F);
1183            }
1184            else
1185            {
1186                GL11.glColor3f(f1, f2, f3);
1187            }
1188
1189            GL11.glPushMatrix();
1190            GL11.glTranslatef(0.0F, -((float)(d0 - 16.0D)), 0.0F);
1191            GL11.glCallList(this.glSkyList2);
1192            GL11.glPopMatrix();
1193            GL11.glEnable(GL11.GL_TEXTURE_2D);
1194            GL11.glDepthMask(true);
1195        }
1196    }
1197
1198    public void renderClouds(float par1)
1199    {
1200        IRenderHandler renderer = null;
1201        if ((renderer = theWorld.provider.getCloudRenderer()) != null)
1202        {
1203            renderer.render(par1, theWorld, mc);
1204            return;
1205        }
1206
1207        if (this.mc.theWorld.provider.isSurfaceWorld())
1208        {
1209            if (this.mc.gameSettings.fancyGraphics)
1210            {
1211                this.renderCloudsFancy(par1);
1212            }
1213            else
1214            {
1215                GL11.glDisable(GL11.GL_CULL_FACE);
1216                float f1 = (float)(this.mc.renderViewEntity.lastTickPosY + (this.mc.renderViewEntity.posY - this.mc.renderViewEntity.lastTickPosY) * (double)par1);
1217                byte b0 = 32;
1218                int i = 256 / b0;
1219                Tessellator tessellator = Tessellator.instance;
1220                this.renderEngine.bindTexture("/environment/clouds.png");
1221                GL11.glEnable(GL11.GL_BLEND);
1222                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1223                Vec3 vec3 = this.theWorld.getCloudColour(par1);
1224                float f2 = (float)vec3.xCoord;
1225                float f3 = (float)vec3.yCoord;
1226                float f4 = (float)vec3.zCoord;
1227                float f5;
1228
1229                if (this.mc.gameSettings.anaglyph)
1230                {
1231                    f5 = (f2 * 30.0F + f3 * 59.0F + f4 * 11.0F) / 100.0F;
1232                    float f6 = (f2 * 30.0F + f3 * 70.0F) / 100.0F;
1233                    float f7 = (f2 * 30.0F + f4 * 70.0F) / 100.0F;
1234                    f2 = f5;
1235                    f3 = f6;
1236                    f4 = f7;
1237                }
1238
1239                f5 = 4.8828125E-4F;
1240                double d0 = (double)((float)this.cloudTickCounter + par1);
1241                double d1 = this.mc.renderViewEntity.prevPosX + (this.mc.renderViewEntity.posX - this.mc.renderViewEntity.prevPosX) * (double)par1 + d0 * 0.029999999329447746D;
1242                double d2 = this.mc.renderViewEntity.prevPosZ + (this.mc.renderViewEntity.posZ - this.mc.renderViewEntity.prevPosZ) * (double)par1;
1243                int j = MathHelper.floor_double(d1 / 2048.0D);
1244                int k = MathHelper.floor_double(d2 / 2048.0D);
1245                d1 -= (double)(j * 2048);
1246                d2 -= (double)(k * 2048);
1247                float f8 = this.theWorld.provider.getCloudHeight() - f1 + 0.33F;
1248                float f9 = (float)(d1 * (double)f5);
1249                float f10 = (float)(d2 * (double)f5);
1250                tessellator.startDrawingQuads();
1251                tessellator.setColorRGBA_F(f2, f3, f4, 0.8F);
1252
1253                for (int l = -b0 * i; l < b0 * i; l += b0)
1254                {
1255                    for (int i1 = -b0 * i; i1 < b0 * i; i1 += b0)
1256                    {
1257                        tessellator.addVertexWithUV((double)(l + 0), (double)f8, (double)(i1 + b0), (double)((float)(l + 0) * f5 + f9), (double)((float)(i1 + b0) * f5 + f10));
1258                        tessellator.addVertexWithUV((double)(l + b0), (double)f8, (double)(i1 + b0), (double)((float)(l + b0) * f5 + f9), (double)((float)(i1 + b0) * f5 + f10));
1259                        tessellator.addVertexWithUV((double)(l + b0), (double)f8, (double)(i1 + 0), (double)((float)(l + b0) * f5 + f9), (double)((float)(i1 + 0) * f5 + f10));
1260                        tessellator.addVertexWithUV((double)(l + 0), (double)f8, (double)(i1 + 0), (double)((float)(l + 0) * f5 + f9), (double)((float)(i1 + 0) * f5 + f10));
1261                    }
1262                }
1263
1264                tessellator.draw();
1265                GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
1266                GL11.glDisable(GL11.GL_BLEND);
1267                GL11.glEnable(GL11.GL_CULL_FACE);
1268            }
1269        }
1270    }
1271
1272    /**
1273     * Checks if the given position is to be rendered with cloud fog
1274     */
1275    public boolean hasCloudFog(double par1, double par3, double par5, float par7)
1276    {
1277        return false;
1278    }
1279
1280    /**
1281     * Renders the 3d fancy clouds
1282     */
1283    public void renderCloudsFancy(float par1)
1284    {
1285        GL11.glDisable(GL11.GL_CULL_FACE);
1286        float f1 = (float)(this.mc.renderViewEntity.lastTickPosY + (this.mc.renderViewEntity.posY - this.mc.renderViewEntity.lastTickPosY) * (double)par1);
1287        Tessellator tessellator = Tessellator.instance;
1288        float f2 = 12.0F;
1289        float f3 = 4.0F;
1290        double d0 = (double)((float)this.cloudTickCounter + par1);
1291        double d1 = (this.mc.renderViewEntity.prevPosX + (this.mc.renderViewEntity.posX - this.mc.renderViewEntity.prevPosX) * (double)par1 + d0 * 0.029999999329447746D) / (double)f2;
1292        double d2 = (this.mc.renderViewEntity.prevPosZ + (this.mc.renderViewEntity.posZ - this.mc.renderViewEntity.prevPosZ) * (double)par1) / (double)f2 + 0.33000001311302185D;
1293        float f4 = this.theWorld.provider.getCloudHeight() - f1 + 0.33F;
1294        int i = MathHelper.floor_double(d1 / 2048.0D);
1295        int j = MathHelper.floor_double(d2 / 2048.0D);
1296        d1 -= (double)(i * 2048);
1297        d2 -= (double)(j * 2048);
1298        this.renderEngine.bindTexture("/environment/clouds.png");
1299        GL11.glEnable(GL11.GL_BLEND);
1300        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1301        Vec3 vec3 = this.theWorld.getCloudColour(par1);
1302        float f5 = (float)vec3.xCoord;
1303        float f6 = (float)vec3.yCoord;
1304        float f7 = (float)vec3.zCoord;
1305        float f8;
1306        float f9;
1307        float f10;
1308
1309        if (this.mc.gameSettings.anaglyph)
1310        {
1311            f8 = (f5 * 30.0F + f6 * 59.0F + f7 * 11.0F) / 100.0F;
1312            f10 = (f5 * 30.0F + f6 * 70.0F) / 100.0F;
1313            f9 = (f5 * 30.0F + f7 * 70.0F) / 100.0F;
1314            f5 = f8;
1315            f6 = f10;
1316            f7 = f9;
1317        }
1318
1319        f8 = (float)(d1 * 0.0D);
1320        f10 = (float)(d2 * 0.0D);
1321        f9 = 0.00390625F;
1322        f8 = (float)MathHelper.floor_double(d1) * f9;
1323        f10 = (float)MathHelper.floor_double(d2) * f9;
1324        float f11 = (float)(d1 - (double)MathHelper.floor_double(d1));
1325        float f12 = (float)(d2 - (double)MathHelper.floor_double(d2));
1326        byte b0 = 8;
1327        byte b1 = 4;
1328        float f13 = 9.765625E-4F;
1329        GL11.glScalef(f2, 1.0F, f2);
1330
1331        for (int k = 0; k < 2; ++k)
1332        {
1333            if (k == 0)
1334            {
1335                GL11.glColorMask(false, false, false, false);
1336            }
1337            else if (this.mc.gameSettings.anaglyph)
1338            {
1339                if (EntityRenderer.anaglyphField == 0)
1340                {
1341                    GL11.glColorMask(false, true, true, true);
1342                }
1343                else
1344                {
1345                    GL11.glColorMask(true, false, false, true);
1346                }
1347            }
1348            else
1349            {
1350                GL11.glColorMask(true, true, true, true);
1351            }
1352
1353            for (int l = -b1 + 1; l <= b1; ++l)
1354            {
1355                for (int i1 = -b1 + 1; i1 <= b1; ++i1)
1356                {
1357                    tessellator.startDrawingQuads();
1358                    float f14 = (float)(l * b0);
1359                    float f15 = (float)(i1 * b0);
1360                    float f16 = f14 - f11;
1361                    float f17 = f15 - f12;
1362
1363                    if (f4 > -f3 - 1.0F)
1364                    {
1365                        tessellator.setColorRGBA_F(f5 * 0.7F, f6 * 0.7F, f7 * 0.7F, 0.8F);
1366                        tessellator.setNormal(0.0F, -1.0F, 0.0F);
1367                        tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + 0.0F), (double)(f17 + (float)b0), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1368                        tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + 0.0F), (double)(f17 + (float)b0), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1369                        tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + 0.0F), (double)(f17 + 0.0F), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1370                        tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + 0.0F), (double)(f17 + 0.0F), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1371                    }
1372
1373                    if (f4 <= f3 + 1.0F)
1374                    {
1375                        tessellator.setColorRGBA_F(f5, f6, f7, 0.8F);
1376                        tessellator.setNormal(0.0F, 1.0F, 0.0F);
1377                        tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + f3 - f13), (double)(f17 + (float)b0), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1378                        tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + f3 - f13), (double)(f17 + (float)b0), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1379                        tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + f3 - f13), (double)(f17 + 0.0F), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1380                        tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + f3 - f13), (double)(f17 + 0.0F), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1381                    }
1382
1383                    tessellator.setColorRGBA_F(f5 * 0.9F, f6 * 0.9F, f7 * 0.9F, 0.8F);
1384                    int j1;
1385
1386                    if (l > -1)
1387                    {
1388                        tessellator.setNormal(-1.0F, 0.0F, 0.0F);
1389
1390                        for (j1 = 0; j1 < b0; ++j1)
1391                        {
1392                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 0.0F), (double)(f4 + 0.0F), (double)(f17 + (float)b0), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1393                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 0.0F), (double)(f4 + f3), (double)(f17 + (float)b0), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1394                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 0.0F), (double)(f4 + f3), (double)(f17 + 0.0F), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1395                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 0.0F), (double)(f4 + 0.0F), (double)(f17 + 0.0F), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1396                        }
1397                    }
1398
1399                    if (l <= 1)
1400                    {
1401                        tessellator.setNormal(1.0F, 0.0F, 0.0F);
1402
1403                        for (j1 = 0; j1 < b0; ++j1)
1404                        {
1405                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 1.0F - f13), (double)(f4 + 0.0F), (double)(f17 + (float)b0), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1406                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 1.0F - f13), (double)(f4 + f3), (double)(f17 + (float)b0), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + (float)b0) * f9 + f10));
1407                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 1.0F - f13), (double)(f4 + f3), (double)(f17 + 0.0F), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1408                            tessellator.addVertexWithUV((double)(f16 + (float)j1 + 1.0F - f13), (double)(f4 + 0.0F), (double)(f17 + 0.0F), (double)((f14 + (float)j1 + 0.5F) * f9 + f8), (double)((f15 + 0.0F) * f9 + f10));
1409                        }
1410                    }
1411
1412                    tessellator.setColorRGBA_F(f5 * 0.8F, f6 * 0.8F, f7 * 0.8F, 0.8F);
1413
1414                    if (i1 > -1)
1415                    {
1416                        tessellator.setNormal(0.0F, 0.0F, -1.0F);
1417
1418                        for (j1 = 0; j1 < b0; ++j1)
1419                        {
1420                            tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + f3), (double)(f17 + (float)j1 + 0.0F), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1421                            tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + f3), (double)(f17 + (float)j1 + 0.0F), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1422                            tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + 0.0F), (double)(f17 + (float)j1 + 0.0F), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1423                            tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + 0.0F), (double)(f17 + (float)j1 + 0.0F), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1424                        }
1425                    }
1426
1427                    if (i1 <= 1)
1428                    {
1429                        tessellator.setNormal(0.0F, 0.0F, 1.0F);
1430
1431                        for (j1 = 0; j1 < b0; ++j1)
1432                        {
1433                            tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + f3), (double)(f17 + (float)j1 + 1.0F - f13), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1434                            tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + f3), (double)(f17 + (float)j1 + 1.0F - f13), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1435                            tessellator.addVertexWithUV((double)(f16 + (float)b0), (double)(f4 + 0.0F), (double)(f17 + (float)j1 + 1.0F - f13), (double)((f14 + (float)b0) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1436                            tessellator.addVertexWithUV((double)(f16 + 0.0F), (double)(f4 + 0.0F), (double)(f17 + (float)j1 + 1.0F - f13), (double)((f14 + 0.0F) * f9 + f8), (double)((f15 + (float)j1 + 0.5F) * f9 + f10));
1437                        }
1438                    }
1439
1440                    tessellator.draw();
1441                }
1442            }
1443        }
1444
1445        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
1446        GL11.glDisable(GL11.GL_BLEND);
1447        GL11.glEnable(GL11.GL_CULL_FACE);
1448    }
1449
1450    /**
1451     * Updates some of the renderers sorted by distance from the player
1452     */
1453    public boolean updateRenderers(EntityLiving par1EntityLiving, boolean par2)
1454    {
1455        byte b0 = 2;
1456        RenderSorter rendersorter = new RenderSorter(par1EntityLiving);
1457        WorldRenderer[] aworldrenderer = new WorldRenderer[b0];
1458        ArrayList arraylist = null;
1459        int i = this.worldRenderersToUpdate.size();
1460        int j = 0;
1461        this.theWorld.theProfiler.startSection("nearChunksSearch");
1462        int k;
1463        WorldRenderer worldrenderer;
1464        int l;
1465        int i1;
1466        label136:
1467
1468        for (k = 0; k < i; ++k)
1469        {
1470            worldrenderer = (WorldRenderer)this.worldRenderersToUpdate.get(k);
1471
1472            if (worldrenderer != null)
1473            {
1474                if (!par2)
1475                {
1476                    if (worldrenderer.distanceToEntitySquared(par1EntityLiving) > 256.0F)
1477                    {
1478                        for (l = 0; l < b0 && (aworldrenderer[l] == null || rendersorter.doCompare(aworldrenderer[l], worldrenderer) <= 0); ++l)
1479                        {
1480                            ;
1481                        }
1482
1483                        --l;
1484
1485                        if (l > 0)
1486                        {
1487                            i1 = l;
1488
1489                            while (true)
1490                            {
1491                                --i1;
1492
1493                                if (i1 == 0)
1494                                {
1495                                    aworldrenderer[l] = worldrenderer;
1496                                    continue label136;
1497                                }
1498
1499                                aworldrenderer[i1 - 1] = aworldrenderer[i1];
1500                            }
1501                        }
1502
1503                        continue;
1504                    }
1505                }
1506                else if (!worldrenderer.isInFrustum)
1507                {
1508                    continue;
1509                }
1510
1511                if (arraylist == null)
1512                {
1513                    arraylist = new ArrayList();
1514                }
1515
1516                ++j;
1517                arraylist.add(worldrenderer);
1518                this.worldRenderersToUpdate.set(k, (Object)null);
1519            }
1520        }
1521
1522        this.theWorld.theProfiler.endSection();
1523        this.theWorld.theProfiler.startSection("sort");
1524
1525        if (arraylist != null)
1526        {
1527            if (arraylist.size() > 1)
1528            {
1529                Collections.sort(arraylist, rendersorter);
1530            }
1531
1532            for (k = arraylist.size() - 1; k >= 0; --k)
1533            {
1534                worldrenderer = (WorldRenderer)arraylist.get(k);
1535                worldrenderer.updateRenderer();
1536                worldrenderer.needsUpdate = false;
1537            }
1538        }
1539
1540        this.theWorld.theProfiler.endSection();
1541        k = 0;
1542        this.theWorld.theProfiler.startSection("rebuild");
1543        int j1;
1544
1545        for (j1 = b0 - 1; j1 >= 0; --j1)
1546        {
1547            WorldRenderer worldrenderer1 = aworldrenderer[j1];
1548
1549            if (worldrenderer1 != null)
1550            {
1551                if (!worldrenderer1.isInFrustum && j1 != b0 - 1)
1552                {
1553                    aworldrenderer[j1] = null;
1554                    aworldrenderer[0] = null;
1555                    break;
1556                }
1557
1558                aworldrenderer[j1].updateRenderer();
1559                aworldrenderer[j1].needsUpdate = false;
1560                ++k;
1561            }
1562        }
1563
1564        this.theWorld.theProfiler.endSection();
1565        this.theWorld.theProfiler.startSection("cleanup");
1566        j1 = 0;
1567        l = 0;
1568
1569        for (i1 = this.worldRenderersToUpdate.size(); j1 != i1; ++j1)
1570        {
1571            WorldRenderer worldrenderer2 = (WorldRenderer)this.worldRenderersToUpdate.get(j1);
1572
1573            if (worldrenderer2 != null)
1574            {
1575                boolean flag1 = false;
1576
1577                for (int k1 = 0; k1 < b0 && !flag1; ++k1)
1578                {
1579                    if (worldrenderer2 == aworldrenderer[k1])
1580                    {
1581                        flag1 = true;
1582                    }
1583                }
1584
1585                if (!flag1)
1586                {
1587                    if (l != j1)
1588                    {
1589                        this.worldRenderersToUpdate.set(l, worldrenderer2);
1590                    }
1591
1592                    ++l;
1593                }
1594            }
1595        }
1596
1597        this.theWorld.theProfiler.endSection();
1598        this.theWorld.theProfiler.startSection("trim");
1599
1600        while (true)
1601        {
1602            --j1;
1603
1604            if (j1 < l)
1605            {
1606                this.theWorld.theProfiler.endSection();
1607                return i == j + k;
1608            }
1609
1610            this.worldRenderersToUpdate.remove(j1);
1611        }
1612    }
1613
1614    public void drawBlockBreaking(EntityPlayer par1EntityPlayer, MovingObjectPosition par2MovingObjectPosition, int par3, ItemStack par4ItemStack, float par5)
1615    {
1616        Tessellator tessellator = Tessellator.instance;
1617        GL11.glEnable(GL11.GL_BLEND);
1618        GL11.glEnable(GL11.GL_ALPHA_TEST);
1619        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1620        GL11.glColor4f(1.0F, 1.0F, 1.0F, (MathHelper.sin((float)Minecraft.getSystemTime() / 100.0F) * 0.2F + 0.4F) * 0.5F);
1621
1622        if (par3 != 0 && par4ItemStack != null)
1623        {
1624            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1625            float f1 = MathHelper.sin((float)Minecraft.getSystemTime() / 100.0F) * 0.2F + 0.8F;
1626            GL11.glColor4f(f1, f1, f1, MathHelper.sin((float)Minecraft.getSystemTime() / 200.0F) * 0.2F + 0.5F);
1627            this.renderEngine.bindTexture("/terrain.png");
1628        }
1629
1630        GL11.glDisable(GL11.GL_BLEND);
1631        GL11.glDisable(GL11.GL_ALPHA_TEST);
1632    }
1633
1634    public void drawBlockDamageTexture(Tessellator par1Tessellator, EntityPlayer par2EntityPlayer, float par3)
1635    {
1636        drawBlockDamageTexture(par1Tessellator, (EntityLiving)par2EntityPlayer, par3);
1637    }
1638
1639    public void drawBlockDamageTexture(Tessellator par1Tessellator, EntityLiving par2EntityPlayer, float par3)
1640    {
1641        double d0 = par2EntityPlayer.lastTickPosX + (par2EntityPlayer.posX - par2EntityPlayer.lastTickPosX) * (double)par3;
1642        double d1 = par2EntityPlayer.lastTickPosY + (par2EntityPlayer.posY - par2EntityPlayer.lastTickPosY) * (double)par3;
1643        double d2 = par2EntityPlayer.lastTickPosZ + (par2EntityPlayer.posZ - par2EntityPlayer.lastTickPosZ) * (double)par3;
1644
1645        if (!this.damagedBlocks.isEmpty())
1646        {
1647            GL11.glBlendFunc(GL11.GL_DST_COLOR, GL11.GL_SRC_COLOR);
1648            this.renderEngine.bindTexture("/terrain.png");
1649            GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.5F);
1650            GL11.glPushMatrix();
1651            GL11.glDisable(GL11.GL_ALPHA_TEST);
1652            GL11.glPolygonOffset(-3.0F, -3.0F);
1653            GL11.glEnable(GL11.GL_POLYGON_OFFSET_FILL);
1654            GL11.glEnable(GL11.GL_ALPHA_TEST);
1655            par1Tessellator.startDrawingQuads();
1656            par1Tessellator.setTranslation(-d0, -d1, -d2);
1657            par1Tessellator.disableColor();
1658            Iterator iterator = this.damagedBlocks.values().iterator();
1659
1660            while (iterator.hasNext())
1661            {
1662                DestroyBlockProgress destroyblockprogress = (DestroyBlockProgress)iterator.next();
1663                double d3 = (double)destroyblockprogress.getPartialBlockX() - d0;
1664                double d4 = (double)destroyblockprogress.getPartialBlockY() - d1;
1665                double d5 = (double)destroyblockprogress.getPartialBlockZ() - d2;
1666
1667                if (d3 * d3 + d4 * d4 + d5 * d5 > 1024.0D)
1668                {
1669                    iterator.remove();
1670                }
1671                else
1672                {
1673                    int i = this.theWorld.getBlockId(destroyblockprogress.getPartialBlockX(), destroyblockprogress.getPartialBlockY(), destroyblockprogress.getPartialBlockZ());
1674                    Block block = i > 0 ? Block.blocksList[i] : null;
1675
1676                    if (block == null)
1677                    {
1678                        block = Block.stone;
1679                    }
1680
1681                    this.globalRenderBlocks.renderBlockUsingTexture(block, destroyblockprogress.getPartialBlockX(), destroyblockprogress.getPartialBlockY(), destroyblockprogress.getPartialBlockZ(), this.destroyBlockIcons[destroyblockprogress.getPartialBlockDamage()]);
1682                }
1683            }
1684
1685            par1Tessellator.draw();
1686            par1Tessellator.setTranslation(0.0D, 0.0D, 0.0D);
1687            GL11.glDisable(GL11.GL_ALPHA_TEST);
1688            GL11.glPolygonOffset(0.0F, 0.0F);
1689            GL11.glDisable(GL11.GL_POLYGON_OFFSET_FILL);
1690            GL11.glEnable(GL11.GL_ALPHA_TEST);
1691            GL11.glDepthMask(true);
1692            GL11.glPopMatrix();
1693        }
1694    }
1695
1696    /**
1697     * Draws the selection box for the player. Args: entityPlayer, rayTraceHit, i, itemStack, partialTickTime
1698     */
1699    public void drawSelectionBox(EntityPlayer par1EntityPlayer, MovingObjectPosition par2MovingObjectPosition, int par3, ItemStack par4ItemStack, float par5)
1700    {
1701        if (par3 == 0 && par2MovingObjectPosition.typeOfHit == EnumMovingObjectType.TILE)
1702        {
1703            GL11.glEnable(GL11.GL_BLEND);
1704            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1705            GL11.glColor4f(0.0F, 0.0F, 0.0F, 0.4F);
1706            GL11.glLineWidth(2.0F);
1707            GL11.glDisable(GL11.GL_TEXTURE_2D);
1708            GL11.glDepthMask(false);
1709            float f1 = 0.002F;
1710            int j = this.theWorld.getBlockId(par2MovingObjectPosition.blockX, par2MovingObjectPosition.blockY, par2MovingObjectPosition.blockZ);
1711
1712            if (j > 0)
1713            {
1714                Block.blocksList[j].setBlockBoundsBasedOnState(this.theWorld, par2MovingObjectPosition.blockX, par2MovingObjectPosition.blockY, par2MovingObjectPosition.blockZ);
1715                double d0 = par1EntityPlayer.lastTickPosX + (par1EntityPlayer.posX - par1EntityPlayer.lastTickPosX) * (double)par5;
1716                double d1 = par1EntityPlayer.lastTickPosY + (par1EntityPlayer.posY - par1EntityPlayer.lastTickPosY) * (double)par5;
1717                double d2 = par1EntityPlayer.lastTickPosZ + (par1EntityPlayer.posZ - par1EntityPlayer.lastTickPosZ) * (double)par5;
1718                this.drawOutlinedBoundingBox(Block.blocksList[j].getSelectedBoundingBoxFromPool(this.theWorld, par2MovingObjectPosition.blockX, par2MovingObjectPosition.blockY, par2MovingObjectPosition.blockZ).expand((double)f1, (double)f1, (double)f1).getOffsetBoundingBox(-d0, -d1, -d2));
1719            }
1720
1721            GL11.glDepthMask(true);
1722            GL11.glEnable(GL11.GL_TEXTURE_2D);
1723            GL11.glDisable(GL11.GL_BLEND);
1724        }
1725    }
1726
1727    /**
1728     * Draws lines for the edges of the bounding box.
1729     */
1730    private void drawOutlinedBoundingBox(AxisAlignedBB par1AxisAlignedBB)
1731    {
1732        Tessellator tessellator = Tessellator.instance;
1733        tessellator.startDrawing(3);
1734        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
1735        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
1736        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
1737        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
1738        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
1739        tessellator.draw();
1740        tessellator.startDrawing(3);
1741        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
1742        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
1743        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
1744        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
1745        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
1746        tessellator.draw();
1747        tessellator.startDrawing(1);
1748        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
1749        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
1750        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
1751        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
1752        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
1753        tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
1754        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
1755        tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
1756        tessellator.draw();
1757    }
1758
1759    /**
1760     * Marks the blocks in the given range for update
1761     */
1762    public void markBlocksForUpdate(int par1, int par2, int par3, int par4, int par5, int par6)
1763    {
1764        int k1 = MathHelper.bucketInt(par1, 16);
1765        int l1 = MathHelper.bucketInt(par2, 16);
1766        int i2 = MathHelper.bucketInt(par3, 16);
1767        int j2 = MathHelper.bucketInt(par4, 16);
1768        int k2 = MathHelper.bucketInt(par5, 16);
1769        int l2 = MathHelper.bucketInt(par6, 16);
1770
1771        for (int i3 = k1; i3 <= j2; ++i3)
1772        {
1773            int j3 = i3 % this.renderChunksWide;
1774
1775            if (j3 < 0)
1776            {
1777                j3 += this.renderChunksWide;
1778            }
1779
1780            for (int k3 = l1; k3 <= k2; ++k3)
1781            {
1782                int l3 = k3 % this.renderChunksTall;
1783
1784                if (l3 < 0)
1785                {
1786                    l3 += this.renderChunksTall;
1787                }
1788
1789                for (int i4 = i2; i4 <= l2; ++i4)
1790                {
1791                    int j4 = i4 % this.renderChunksDeep;
1792
1793                    if (j4 < 0)
1794                    {
1795                        j4 += this.renderChunksDeep;
1796                    }
1797
1798                    int k4 = (j4 * this.renderChunksTall + l3) * this.renderChunksWide + j3;
1799                    WorldRenderer worldrenderer = this.worldRenderers[k4];
1800
1801                    if (worldrenderer != null && !worldrenderer.needsUpdate)
1802                    {
1803                        this.worldRenderersToUpdate.add(worldrenderer);
1804                        worldrenderer.markDirty();
1805                    }
1806                }
1807            }
1808        }
1809    }
1810
1811    /**
1812     * On the client, re-renders the block. On the server, sends the block to the client (which will re-render it),
1813     * including the tile entity description packet if applicable. Args: x, y, z
1814     */
1815    public void markBlockForUpdate(int par1, int par2, int par3)
1816    {
1817        this.markBlocksForUpdate(par1 - 1, par2 - 1, par3 - 1, par1 + 1, par2 + 1, par3 + 1);
1818    }
1819
1820    /**
1821     * On the client, re-renders this block. On the server, does nothing. Used for lighting updates.
1822     */
1823    public void markBlockForRenderUpdate(int par1, int par2, int par3)
1824    {
1825        this.markBlocksForUpdate(par1 - 1, par2 - 1, par3 - 1, par1 + 1, par2 + 1, par3 + 1);
1826    }
1827
1828    /**
1829     * On the client, re-renders all blocks in this range, inclusive. On the server, does nothing. Args: min x, min y,
1830     * min z, max x, max y, max z
1831     */
1832    public void markBlockRangeForRenderUpdate(int par1, int par2, int par3, int par4, int par5, int par6)
1833    {
1834        this.markBlocksForUpdate(par1 - 1, par2 - 1, par3 - 1, par4 + 1, par5 + 1, par6 + 1);
1835    }
1836
1837    /**
1838     * Checks all renderers that previously weren't in the frustum and 1/16th of those that previously were in the
1839     * frustum for frustum clipping Args: frustum, partialTickTime
1840     */
1841    public void clipRenderersByFrustum(ICamera par1ICamera, float par2)
1842    {
1843        for (int i = 0; i < this.worldRenderers.length; ++i)
1844        {
1845            if (!this.worldRenderers[i].skipAllRenderPasses() && (!this.worldRenderers[i].isInFrustum || (i + this.frustumCheckOffset & 15) == 0))
1846            {
1847                this.worldRenderers[i].updateInFrustum(par1ICamera);
1848            }
1849        }
1850
1851        ++this.frustumCheckOffset;
1852    }
1853
1854    /**
1855     * Plays the specified record. Arg: recordName, x, y, z
1856     */
1857    public void playRecord(String par1Str, int par2, int par3, int par4)
1858    {
1859        ItemRecord itemrecord = ItemRecord.getRecord(par1Str);
1860
1861        if (par1Str != null && itemrecord != null)
1862        {
1863            this.mc.ingameGUI.setRecordPlayingMessage(itemrecord.getRecordTitle());
1864        }
1865
1866        this.mc.sndManager.playStreaming(par1Str, (float)par2, (float)par3, (float)par4);
1867    }
1868
1869    /**
1870     * Plays the specified sound. Arg: soundName, x, y, z, volume, pitch
1871     */
1872    public void playSound(String par1Str, double par2, double par4, double par6, float par8, float par9) {}
1873
1874    /**
1875     * Plays sound to all near players except the player reference given
1876     */
1877    public void playSoundToNearExcept(EntityPlayer par1EntityPlayer, String par2Str, double par3, double par5, double par7, float par9, float par10) {}
1878
1879    /**
1880     * Spawns a particle. Arg: particleType, x, y, z, velX, velY, velZ
1881     */
1882    public void spawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10, double par12)
1883    {
1884        try
1885        {
1886            this.doSpawnParticle(par1Str, par2, par4, par6, par8, par10, par12);
1887        }
1888        catch (Throwable throwable)
1889        {
1890            CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception while adding particle");
1891            CrashReportCategory crashreportcategory = crashreport.makeCategory("Particle being added");
1892            crashreportcategory.addCrashSection("Name", par1Str);
1893            crashreportcategory.addCrashSectionCallable("Position", new CallableParticlePositionInfo(this, par2, par4, par6));
1894            throw new ReportedException(crashreport);
1895        }
1896    }
1897
1898    /**
1899     * Spawns a particle. Arg: particleType, x, y, z, velX, velY, velZ
1900     */
1901    public EntityFX doSpawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10, double par12)
1902    {
1903        if (this.mc != null && this.mc.renderViewEntity != null && this.mc.effectRenderer != null)
1904        {
1905            int i = this.mc.gameSettings.particleSetting;
1906
1907            if (i == 1 && this.theWorld.rand.nextInt(3) == 0)
1908            {
1909                i = 2;
1910            }
1911
1912            double d6 = this.mc.renderViewEntity.posX - par2;
1913            double d7 = this.mc.renderViewEntity.posY - par4;
1914            double d8 = this.mc.renderViewEntity.posZ - par6;
1915            EntityFX entityfx = null;
1916
1917            if (par1Str.equals("hugeexplosion"))
1918            {
1919                this.mc.effectRenderer.addEffect(entityfx = new EntityHugeExplodeFX(this.theWorld, par2, par4, par6, par8, par10, par12));
1920            }
1921            else if (par1Str.equals("largeexplode"))
1922            {
1923                this.mc.effectRenderer.addEffect(entityfx = new EntityLargeExplodeFX(this.renderEngine, this.theWorld, par2, par4, par6, par8, par10, par12));
1924            }
1925            else if (par1Str.equals("fireworksSpark"))
1926            {
1927                this.mc.effectRenderer.addEffect(entityfx = new EntityFireworkSparkFX(this.theWorld, par2, par4, par6, par8, par10, par12, this.mc.effectRenderer));
1928            }
1929
1930            if (entityfx != null)
1931            {
1932                return (EntityFX)entityfx;
1933            }
1934            else
1935            {
1936                double d9 = 16.0D;
1937
1938                if (d6 * d6 + d7 * d7 + d8 * d8 > d9 * d9)
1939                {
1940                    return null;
1941                }
1942                else if (i > 1)
1943                {
1944                    return null;
1945                }
1946                else
1947                {
1948                    if (par1Str.equals("bubble"))
1949                    {
1950                        entityfx = new EntityBubbleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1951                    }
1952                    else if (par1Str.equals("suspended"))
1953                    {
1954                        entityfx = new EntitySuspendFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1955                    }
1956                    else if (par1Str.equals("depthsuspend"))
1957                    {
1958                        entityfx = new EntityAuraFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1959                    }
1960                    else if (par1Str.equals("townaura"))
1961                    {
1962                        entityfx = new EntityAuraFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1963                    }
1964                    else if (par1Str.equals("crit"))
1965                    {
1966                        entityfx = new EntityCritFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1967                    }
1968                    else if (par1Str.equals("magicCrit"))
1969                    {
1970                        entityfx = new EntityCritFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1971                        ((EntityFX)entityfx).setRBGColorF(((EntityFX)entityfx).getRedColorF() * 0.3F, ((EntityFX)entityfx).getGreenColorF() * 0.8F, ((EntityFX)entityfx).getBlueColorF());
1972                        ((EntityFX)entityfx).nextTextureIndexX();
1973                    }
1974                    else if (par1Str.equals("smoke"))
1975                    {
1976                        entityfx = new EntitySmokeFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1977                    }
1978                    else if (par1Str.equals("mobSpell"))
1979                    {
1980                        entityfx = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, 0.0D, 0.0D, 0.0D);
1981                        ((EntityFX)entityfx).setRBGColorF((float)par8, (float)par10, (float)par12);
1982                    }
1983                    else if (par1Str.equals("mobSpellAmbient"))
1984                    {
1985                        entityfx = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, 0.0D, 0.0D, 0.0D);
1986                        ((EntityFX)entityfx).setAlphaF(0.15F);
1987                        ((EntityFX)entityfx).setRBGColorF((float)par8, (float)par10, (float)par12);
1988                    }
1989                    else if (par1Str.equals("spell"))
1990                    {
1991                        entityfx = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1992                    }
1993                    else if (par1Str.equals("instantSpell"))
1994                    {
1995                        entityfx = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
1996                        ((EntitySpellParticleFX)entityfx).setBaseSpellTextureIndex(144);
1997                    }
1998                    else if (par1Str.equals("witchMagic"))
1999                    {
2000                        entityfx = new EntitySpellParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2001                        ((EntitySpellParticleFX)entityfx).setBaseSpellTextureIndex(144);
2002                        float f = this.theWorld.rand.nextFloat() * 0.5F + 0.35F;
2003                        ((EntityFX)entityfx).setRBGColorF(1.0F * f, 0.0F * f, 1.0F * f);
2004                    }
2005                    else if (par1Str.equals("note"))
2006                    {
2007                        entityfx = new EntityNoteFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2008                    }
2009                    else if (par1Str.equals("portal"))
2010                    {
2011                        entityfx = new EntityPortalFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2012                    }
2013                    else if (par1Str.equals("enchantmenttable"))
2014                    {
2015                        entityfx = new EntityEnchantmentTableParticleFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2016                    }
2017                    else if (par1Str.equals("explode"))
2018                    {
2019                        entityfx = new EntityExplodeFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2020                    }
2021                    else if (par1Str.equals("flame"))
2022                    {
2023                        entityfx = new EntityFlameFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2024                    }
2025                    else if (par1Str.equals("lava"))
2026                    {
2027                        entityfx = new EntityLavaFX(this.theWorld, par2, par4, par6);
2028                    }
2029                    else if (par1Str.equals("footstep"))
2030                    {
2031                        entityfx = new EntityFootStepFX(this.renderEngine, this.theWorld, par2, par4, par6);
2032                    }
2033                    else if (par1Str.equals("splash"))
2034                    {
2035                        entityfx = new EntitySplashFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2036                    }
2037                    else if (par1Str.equals("largesmoke"))
2038                    {
2039                        entityfx = new EntitySmokeFX(this.theWorld, par2, par4, par6, par8, par10, par12, 2.5F);
2040                    }
2041                    else if (par1Str.equals("cloud"))
2042                    {
2043                        entityfx = new EntityCloudFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2044                    }
2045                    else if (par1Str.equals("reddust"))
2046                    {
2047                        entityfx = new EntityReddustFX(this.theWorld, par2, par4, par6, (float)par8, (float)par10, (float)par12);
2048                    }
2049                    else if (par1Str.equals("snowballpoof"))
2050                    {
2051                        entityfx = new EntityBreakingFX(this.theWorld, par2, par4, par6, Item.snowball, this.renderEngine);
2052                    }
2053                    else if (par1Str.equals("dripWater"))
2054                    {
2055                        entityfx = new EntityDropParticleFX(this.theWorld, par2, par4, par6, Material.water);
2056                    }
2057                    else if (par1Str.equals("dripLava"))
2058                    {
2059                        entityfx = new EntityDropParticleFX(this.theWorld, par2, par4, par6, Material.lava);
2060                    }
2061                    else if (par1Str.equals("snowshovel"))
2062                    {
2063                        entityfx = new EntitySnowShovelFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2064                    }
2065                    else if (par1Str.equals("slime"))
2066                    {
2067                        entityfx = new EntityBreakingFX(this.theWorld, par2, par4, par6, Item.slimeBall, this.renderEngine);
2068                    }
2069                    else if (par1Str.equals("heart"))
2070                    {
2071                        entityfx = new EntityHeartFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2072                    }
2073                    else if (par1Str.equals("angryVillager"))
2074                    {
2075                        entityfx = new EntityHeartFX(this.theWorld, par2, par4 + 0.5D, par6, par8, par10, par12);
2076                        ((EntityFX)entityfx).setParticleTextureIndex(81);
2077                        ((EntityFX)entityfx).setRBGColorF(1.0F, 1.0F, 1.0F);
2078                    }
2079                    else if (par1Str.equals("happyVillager"))
2080                    {
2081                        entityfx = new EntityAuraFX(this.theWorld, par2, par4, par6, par8, par10, par12);
2082                        ((EntityFX)entityfx).setParticleTextureIndex(82);
2083                        ((EntityFX)entityfx).setRBGColorF(1.0F, 1.0F, 1.0F);
2084                    }
2085                    else if (par1Str.startsWith("iconcrack_"))
2086                    {
2087                        int j = Integer.parseInt(par1Str.substring(par1Str.indexOf("_") + 1));
2088                        entityfx = new EntityBreakingFX(this.theWorld, par2, par4, par6, par8, par10, par12, Item.itemsList[j], this.renderEngine);
2089                    }
2090                    else if (par1Str.startsWith("tilecrack_"))
2091                    {
2092                        String[] astring = par1Str.split("_", 3);
2093                        int k = Integer.parseInt(astring[1]);
2094                        int l = Integer.parseInt(astring[2]);
2095                        entityfx = (new EntityDiggingFX(this.theWorld, par2, par4, par6, par8, par10, par12, Block.blocksList[k], 0, l, this.renderEngine)).applyRenderColor(l);
2096                    }
2097
2098                    if (entityfx != null)
2099                    {
2100                        this.mc.effectRenderer.addEffect((EntityFX)entityfx);
2101                    }
2102
2103                    return (EntityFX)entityfx;
2104                }
2105            }
2106        }
2107        else
2108        {
2109            return null;
2110        }
2111    }
2112
2113    /**
2114     * Called on all IWorldAccesses when an entity is created or loaded. On client worlds, starts downloading any
2115     * necessary textures. On server worlds, adds the entity to the entity tracker.
2116     */
2117    public void onEntityCreate(Entity par1Entity)
2118    {
2119        par1Entity.updateCloak();
2120
2121        if (par1Entity.skinUrl != null)
2122        {
2123            this.renderEngine.obtainImageData(par1Entity.skinUrl, new ImageBufferDownload());
2124        }
2125
2126        if (par1Entity.cloakUrl != null)
2127        {
2128            this.renderEngine.obtainImageData(par1Entity.cloakUrl, new ImageBufferDownload());
2129        }
2130    }
2131
2132    /**
2133     * Called on all IWorldAccesses when an entity is unloaded or destroyed. On client worlds, releases any downloaded
2134     * textures. On server worlds, removes the entity from the entity tracker.
2135     */
2136    public void onEntityDestroy(Entity par1Entity)
2137    {
2138        if (par1Entity.skinUrl != null)
2139        {
2140            this.renderEngine.releaseImageData(par1Entity.skinUrl);
2141        }
2142
2143        if (par1Entity.cloakUrl != null)
2144        {
2145            this.renderEngine.releaseImageData(par1Entity.cloakUrl);
2146        }
2147    }
2148
2149    /**
2150     * Deletes all display lists
2151     */
2152    public void deleteAllDisplayLists()
2153    {
2154        GLAllocation.deleteDisplayLists(this.glRenderListBase);
2155    }
2156
2157    public void broadcastSound(int par1, int par2, int par3, int par4, int par5)
2158    {
2159        Random random = this.theWorld.rand;
2160
2161        switch (par1)
2162        {
2163            case 1013:
2164            case 1018:
2165                if (this.mc.renderViewEntity != null)
2166                {
2167                    double d0 = (double)par2 - this.mc.renderViewEntity.posX;
2168                    double d1 = (double)par3 - this.mc.renderViewEntity.posY;
2169                    double d2 = (double)par4 - this.mc.renderViewEntity.posZ;
2170                    double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
2171                    double d4 = this.mc.renderViewEntity.posX;
2172                    double d5 = this.mc.renderViewEntity.posY;
2173                    double d6 = this.mc.renderViewEntity.posZ;
2174
2175                    if (d3 > 0.0D)
2176                    {
2177                        d4 += d0 / d3 * 2.0D;
2178                        d5 += d1 / d3 * 2.0D;
2179                        d6 += d2 / d3 * 2.0D;
2180                    }
2181
2182                    if (par1 == 1013)
2183                    {
2184                        this.theWorld.playSound(d4, d5, d6, "mob.wither.spawn", 1.0F, 1.0F, false);
2185                    }
2186                    else if (par1 == 1018)
2187                    {
2188                        this.theWorld.playSound(d4, d5, d6, "mob.enderdragon.end", 5.0F, 1.0F, false);
2189                    }
2190                }
2191            default:
2192        }
2193    }
2194
2195    /**
2196     * Plays a pre-canned sound effect along with potentially auxiliary data-driven one-shot behaviour (particles, etc).
2197     */
2198    public void playAuxSFX(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5, int par6)
2199    {
2200        Random random = this.theWorld.rand;
2201        double d0;
2202        double d1;
2203        double d2;
2204        String s;
2205        int j1;
2206        int k1;
2207        double d3;
2208        double d4;
2209        double d5;
2210        double d6;
2211        double d7;
2212
2213        switch (par2)
2214        {
2215            case 1000:
2216                this.theWorld.playSound((double)par3, (double)par4, (double)par5, "random.click", 1.0F, 1.0F, false);
2217                break;
2218            case 1001:
2219                this.theWorld.playSound((double)par3, (double)par4, (double)par5, "random.click", 1.0F, 1.2F, false);
2220                break;
2221            case 1002:
2222                this.theWorld.playSound((double)par3, (double)par4, (double)par5, "random.bow", 1.0F, 1.2F, false);
2223                break;
2224            case 1003:
2225                if (Math.random() < 0.5D)
2226                {
2227                    this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "random.door_open", 1.0F, this.theWorld.rand.nextFloat() * 0.1F + 0.9F, false);
2228                }
2229                else
2230                {
2231                    this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "random.door_close", 1.0F, this.theWorld.rand.nextFloat() * 0.1F + 0.9F, false);
2232                }
2233
2234                break;
2235            case 1004:
2236                this.theWorld.playSound((double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), (double)((float)par5 + 0.5F), "random.fizz", 0.5F, 2.6F + (random.nextFloat() - random.nextFloat()) * 0.8F, false);
2237                break;
2238            case 1005:
2239                if (Item.itemsList[par6] instanceof ItemRecord)
2240                {
2241                    this.theWorld.playRecord(((ItemRecord)Item.itemsList[par6]).recordName, par3, par4, par5);
2242                }
2243                else
2244                {
2245                    this.theWorld.playRecord((String)null, par3, par4, par5);
2246                }
2247
2248                break;
2249            case 1007:
2250                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.ghast.charge", 10.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2251                break;
2252            case 1008:
2253                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.ghast.fireball", 10.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2254                break;
2255            case 1009:
2256                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.ghast.fireball", 2.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2257                break;
2258            case 1010:
2259                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.zombie.wood", 2.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2260                break;
2261            case 1011:
2262                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.zombie.metal", 2.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2263                break;
2264            case 1012:
2265                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.zombie.woodbreak", 2.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2266                break;
2267            case 1014:
2268                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.wither.shoot", 2.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2269                break;
2270            case 1015:
2271                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.bat.takeoff", 0.05F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2272                break;
2273            case 1016:
2274                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.zombie.infect", 2.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2275                break;
2276            case 1017:
2277                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "mob.zombie.unfect", 2.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F, false);
2278                break;
2279            case 1020:
2280                this.theWorld.playSound((double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), (double)((float)par5 + 0.5F), "random.anvil_break", 1.0F, this.theWorld.rand.nextFloat() * 0.1F + 0.9F, false);
2281                break;
2282            case 1021:
2283                this.theWorld.playSound((double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), (double)((float)par5 + 0.5F), "random.anvil_use", 1.0F, this.theWorld.rand.nextFloat() * 0.1F + 0.9F, false);
2284                break;
2285            case 1022:
2286                this.theWorld.playSound((double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), (double)((float)par5 + 0.5F), "random.anvil_land", 0.3F, this.theWorld.rand.nextFloat() * 0.1F + 0.9F, false);
2287                break;
2288            case 2000:
2289                int l1 = par6 % 3 - 1;
2290                int i2 = par6 / 3 % 3 - 1;
2291                d1 = (double)par3 + (double)l1 * 0.6D + 0.5D;
2292                d2 = (double)par4 + 0.5D;
2293                double d8 = (double)par5 + (double)i2 * 0.6D + 0.5D;
2294
2295                for (int j2 = 0; j2 < 10; ++j2)
2296                {
2297                    double d9 = random.nextDouble() * 0.2D + 0.01D;
2298                    double d10 = d1 + (double)l1 * 0.01D + (random.nextDouble() - 0.5D) * (double)i2 * 0.5D;
2299                    d7 = d2 + (random.nextDouble() - 0.5D) * 0.5D;
2300                    d3 = d8 + (double)i2 * 0.01D + (random.nextDouble() - 0.5D) * (double)l1 * 0.5D;
2301                    d4 = (double)l1 * d9 + random.nextGaussian() * 0.01D;
2302                    d5 = -0.03D + random.nextGaussian() * 0.01D;
2303                    d6 = (double)i2 * d9 + random.nextGaussian() * 0.01D;
2304                    this.spawnParticle("smoke", d10, d7, d3, d4, d5, d6);
2305                }
2306
2307                return;
2308            case 2001:
2309                k1 = par6 & 4095;
2310
2311                if (k1 > 0)
2312                {
2313                    Block block = Block.blocksList[k1];
2314                    this.mc.sndManager.playSound(block.stepSound.getBreakSound(), (float)par3 + 0.5F, (float)par4 + 0.5F, (float)par5 + 0.5F, (block.stepSound.getVolume() + 1.0F) / 2.0F, block.stepSound.getPitch() * 0.8F);
2315                }
2316
2317                this.mc.effectRenderer.addBlockDestroyEffects(par3, par4, par5, par6 & 4095, par6 >> 12 & 255);
2318                break;
2319            case 2002:
2320                d0 = (double)par3;
2321                d1 = (double)par4;
2322                d2 = (double)par5;
2323                s = "iconcrack_" + Item.potion.itemID;
2324
2325                for (j1 = 0; j1 < 8; ++j1)
2326                {
2327                    this.spawnParticle(s, d0, d1, d2, random.nextGaussian() * 0.15D, random.nextDouble() * 0.2D, random.nextGaussian() * 0.15D);
2328                }
2329
2330                j1 = Item.potion.getColorFromDamage(par6);
2331                float f = (float)(j1 >> 16 & 255) / 255.0F;
2332                float f1 = (float)(j1 >> 8 & 255) / 255.0F;
2333                float f2 = (float)(j1 >> 0 & 255) / 255.0F;
2334                String s1 = "spell";
2335
2336                if (Item.potion.isEffectInstant(par6))
2337                {
2338                    s1 = "instantSpell";
2339                }
2340
2341                for (k1 = 0; k1 < 100; ++k1)
2342                {
2343                    d7 = random.nextDouble() * 4.0D;
2344                    d3 = random.nextDouble() * Math.PI * 2.0D;
2345                    d4 = Math.cos(d3) * d7;
2346                    d5 = 0.01D + random.nextDouble() * 0.5D;
2347                    d6 = Math.sin(d3) * d7;
2348                    EntityFX entityfx = this.doSpawnParticle(s1, d0 + d4 * 0.1D, d1 + 0.3D, d2 + d6 * 0.1D, d4, d5, d6);
2349
2350                    if (entityfx != null)
2351                    {
2352                        float f3 = 0.75F + random.nextFloat() * 0.25F;
2353                        entityfx.setRBGColorF(f * f3, f1 * f3, f2 * f3);
2354                        entityfx.multiplyVelocity((float)d7);
2355                    }
2356                }
2357
2358                this.theWorld.playSound((double)par3 + 0.5D, (double)par4 + 0.5D, (double)par5 + 0.5D, "random.glass", 1.0F, this.theWorld.rand.nextFloat() * 0.1F + 0.9F, false);
2359                break;
2360            case 2003:
2361                d0 = (double)par3 + 0.5D;
2362                d1 = (double)par4;
2363                d2 = (double)par5 + 0.5D;
2364                s = "iconcrack_" + Item.eyeOfEnder.itemID;
2365
2366                for (j1 = 0; j1 < 8; ++j1)
2367                {
2368                    this.spawnParticle(s, d0, d1, d2, random.nextGaussian() * 0.15D, random.nextDouble() * 0.2D, random.nextGaussian() * 0.15D);
2369                }
2370
2371                for (double d11 = 0.0D; d11 < (Math.PI * 2D); d11 += 0.15707963267948966D)
2372                {
2373                    this.spawnParticle("portal", d0 + Math.cos(d11) * 5.0D, d1 - 0.4D, d2 + Math.sin(d11) * 5.0D, Math.cos(d11) * -5.0D, 0.0D, Math.sin(d11) * -5.0D);
2374                    this.spawnParticle("portal", d0 + Math.cos(d11) * 5.0D, d1 - 0.4D, d2 + Math.sin(d11) * 5.0D, Math.cos(d11) * -7.0D, 0.0D, Math.sin(d11) * -7.0D);
2375                }
2376
2377                return;
2378            case 2004:
2379                for (int k2 = 0; k2 < 20; ++k2)
2380                {
2381                    double d12 = (double)par3 + 0.5D + ((double)this.theWorld.rand.nextFloat() - 0.5D) * 2.0D;
2382                    double d13 = (double)par4 + 0.5D + ((double)this.theWorld.rand.nextFloat() - 0.5D) * 2.0D;
2383                    double d14 = (double)par5 + 0.5D + ((double)this.theWorld.rand.nextFloat() - 0.5D) * 2.0D;
2384                    this.theWorld.spawnParticle("smoke", d12, d13, d14, 0.0D, 0.0D, 0.0D);
2385                    this.theWorld.spawnParticle("flame", d12, d13, d14, 0.0D, 0.0D, 0.0D);
2386                }
2387
2388                return;
2389            case 2005:
2390                ItemDye.func_96603_a(this.theWorld, par3, par4, par5, par6);
2391        }
2392    }
2393
2394    /**
2395     * Starts (or continues) destroying a block with given ID at the given coordinates for the given partially destroyed
2396     * value
2397     */
2398    public void destroyBlockPartially(int par1, int par2, int par3, int par4, int par5)
2399    {
2400        if (par5 >= 0 && par5 < 10)
2401        {
2402            DestroyBlockProgress destroyblockprogress = (DestroyBlockProgress)this.damagedBlocks.get(Integer.valueOf(par1));
2403
2404            if (destroyblockprogress == null || destroyblockprogress.getPartialBlockX() != par2 || destroyblockprogress.getPartialBlockY() != par3 || destroyblockprogress.getPartialBlockZ() != par4)
2405            {
2406                destroyblockprogress = new DestroyBlockProgress(par1, par2, par3, par4);
2407                this.damagedBlocks.put(Integer.valueOf(par1), destroyblockprogress);
2408            }
2409
2410            destroyblockprogress.setPartialBlockDamage(par5);
2411            destroyblockprogress.setCloudUpdateTick(this.cloudTickCounter);
2412        }
2413        else
2414        {
2415            this.damagedBlocks.remove(Integer.valueOf(par1));
2416        }
2417    }
2418
2419    public void registerDestroyBlockIcons(IconRegister par1IconRegister)
2420    {
2421        this.destroyBlockIcons = new Icon[10];
2422
2423        for (int i = 0; i < this.destroyBlockIcons.length; ++i)
2424        {
2425            this.destroyBlockIcons[i] = par1IconRegister.registerIcon("destroy_" + i);
2426        }
2427    }
2428}