001    package net.minecraft.client.renderer;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.ArrayList;
006    import java.util.HashSet;
007    import java.util.List;
008    import net.minecraft.block.Block;
009    import net.minecraft.client.renderer.culling.ICamera;
010    import net.minecraft.client.renderer.entity.RenderItem;
011    import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
012    import net.minecraft.entity.Entity;
013    import net.minecraft.tileentity.TileEntity;
014    import net.minecraft.util.AxisAlignedBB;
015    import net.minecraft.world.ChunkCache;
016    import net.minecraft.world.World;
017    import net.minecraft.world.chunk.Chunk;
018    import org.lwjgl.opengl.GL11;
019    
020    import net.minecraftforge.client.ForgeHooksClient;
021    
022    @SideOnly(Side.CLIENT)
023    public class WorldRenderer
024    {
025        /** Reference to the World object. */
026        public World worldObj;
027        private int glRenderList = -1;
028        //private static Tessellator tessellator = Tessellator.instance;
029        public static int chunksUpdated = 0;
030        public int posX;
031        public int posY;
032        public int posZ;
033    
034        /** Pos X minus */
035        public int posXMinus;
036    
037        /** Pos Y minus */
038        public int posYMinus;
039    
040        /** Pos Z minus */
041        public int posZMinus;
042    
043        /** Pos X clipped */
044        public int posXClip;
045    
046        /** Pos Y clipped */
047        public int posYClip;
048    
049        /** Pos Z clipped */
050        public int posZClip;
051        public boolean isInFrustum = false;
052    
053        /** Should this renderer skip this render pass */
054        public boolean[] skipRenderPass = new boolean[2];
055    
056        /** Pos X plus */
057        public int posXPlus;
058    
059        /** Pos Y plus */
060        public int posYPlus;
061    
062        /** Pos Z plus */
063        public int posZPlus;
064    
065        /** Boolean for whether this renderer needs to be updated or not */
066        public boolean needsUpdate;
067    
068        /** Axis aligned bounding box */
069        public AxisAlignedBB rendererBoundingBox;
070    
071        /** Chunk index */
072        public int chunkIndex;
073    
074        /** Is this renderer visible according to the occlusion query */
075        public boolean isVisible = true;
076    
077        /** Is this renderer waiting on the result of the occlusion query */
078        public boolean isWaitingOnOcclusionQuery;
079    
080        /** OpenGL occlusion query */
081        public int glOcclusionQuery;
082    
083        /** Is the chunk lit */
084        public boolean isChunkLit;
085        private boolean isInitialized = false;
086    
087        /** All the tile entities that have special rendering code for this chunk */
088        public List tileEntityRenderers = new ArrayList();
089        private List tileEntities;
090    
091        /** Bytes sent to the GPU */
092        private int bytesDrawn;
093    
094        public WorldRenderer(World par1World, List par2List, int par3, int par4, int par5, int par6)
095        {
096            this.worldObj = par1World;
097            this.tileEntities = par2List;
098            this.glRenderList = par6;
099            this.posX = -999;
100            this.setPosition(par3, par4, par5);
101            this.needsUpdate = false;
102        }
103    
104        /**
105         * Sets a new position for the renderer and setting it up so it can be reloaded with the new data for that position
106         */
107        public void setPosition(int par1, int par2, int par3)
108        {
109            if (par1 != this.posX || par2 != this.posY || par3 != this.posZ)
110            {
111                this.setDontDraw();
112                this.posX = par1;
113                this.posY = par2;
114                this.posZ = par3;
115                this.posXPlus = par1 + 8;
116                this.posYPlus = par2 + 8;
117                this.posZPlus = par3 + 8;
118                this.posXClip = par1 & 1023;
119                this.posYClip = par2;
120                this.posZClip = par3 & 1023;
121                this.posXMinus = par1 - this.posXClip;
122                this.posYMinus = par2 - this.posYClip;
123                this.posZMinus = par3 - this.posZClip;
124                float var4 = 6.0F;
125                this.rendererBoundingBox = AxisAlignedBB.getBoundingBox((double)((float)par1 - var4), (double)((float)par2 - var4), (double)((float)par3 - var4), (double)((float)(par1 + 16) + var4), (double)((float)(par2 + 16) + var4), (double)((float)(par3 + 16) + var4));
126                GL11.glNewList(this.glRenderList + 2, GL11.GL_COMPILE);
127                RenderItem.renderAABB(AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)((float)this.posXClip - var4), (double)((float)this.posYClip - var4), (double)((float)this.posZClip - var4), (double)((float)(this.posXClip + 16) + var4), (double)((float)(this.posYClip + 16) + var4), (double)((float)(this.posZClip + 16) + var4)));
128                GL11.glEndList();
129                this.markDirty();
130            }
131        }
132    
133        private void setupGLTranslation()
134        {
135            GL11.glTranslatef((float)this.posXClip, (float)this.posYClip, (float)this.posZClip);
136        }
137    
138        /**
139         * Will update this chunk renderer
140         */
141        public void updateRenderer()
142        {
143            if (this.needsUpdate)
144            {
145                this.needsUpdate = false;
146                int var1 = this.posX;
147                int var2 = this.posY;
148                int var3 = this.posZ;
149                int var4 = this.posX + 16;
150                int var5 = this.posY + 16;
151                int var6 = this.posZ + 16;
152    
153                for (int var7 = 0; var7 < 2; ++var7)
154                {
155                    this.skipRenderPass[var7] = true;
156                }
157    
158                Chunk.isLit = false;
159                HashSet var21 = new HashSet();
160                var21.addAll(this.tileEntityRenderers);
161                this.tileEntityRenderers.clear();
162                byte var8 = 1;
163                ChunkCache var9 = new ChunkCache(this.worldObj, var1 - var8, var2 - var8, var3 - var8, var4 + var8, var5 + var8, var6 + var8);
164    
165                if (!var9.extendedLevelsInChunkCache())
166                {
167                    ++chunksUpdated;
168                    RenderBlocks var10 = new RenderBlocks(var9);
169                    this.bytesDrawn = 0;
170    
171                    for (int var11 = 0; var11 < 2; ++var11)
172                    {
173                        boolean var12 = false;
174                        boolean var13 = false;
175                        boolean var14 = false;
176    
177                        for (int var15 = var2; var15 < var5; ++var15)
178                        {
179                            for (int var16 = var3; var16 < var6; ++var16)
180                            {
181                                for (int var17 = var1; var17 < var4; ++var17)
182                                {
183                                    int var18 = var9.getBlockId(var17, var15, var16);
184    
185                                    if (var18 > 0)
186                                    {
187                                        if (!var14)
188                                        {
189                                            var14 = true;
190                                            GL11.glNewList(this.glRenderList + var11, GL11.GL_COMPILE);
191                                            GL11.glPushMatrix();
192                                            this.setupGLTranslation();
193                                            float var19 = 1.000001F;
194                                            GL11.glTranslatef(-8.0F, -8.0F, -8.0F);
195                                            GL11.glScalef(var19, var19, var19);
196                                            GL11.glTranslatef(8.0F, 8.0F, 8.0F);
197                                            ForgeHooksClient.beforeRenderPass(var11);
198                                            Tessellator.instance.startDrawingQuads();
199                                            Tessellator.instance.setTranslation((double)(-this.posX), (double)(-this.posY), (double)(-this.posZ));
200                                        }
201    
202                                        Block var23 = Block.blocksList[var18];
203    
204                                        if (var23 != null)
205                                        {
206                                            if (var11 == 0 && var23.hasTileEntity(var9.getBlockMetadata(var17, var15, var16)))
207                                            {
208                                                TileEntity var20 = var9.getBlockTileEntity(var17, var15, var16);
209    
210                                                if (TileEntityRenderer.instance.hasSpecialRenderer(var20))
211                                                {
212                                                    this.tileEntityRenderers.add(var20);
213                                                }
214                                            }
215    
216                                            int var24 = var23.getRenderBlockPass();
217    
218                                            if (var24 > var11)
219                                            {
220                                                var12 = true;
221                                            }
222                                            if (!var23.canRenderInPass(var11))
223                                            {
224                                                continue;
225                                            }
226                                            ForgeHooksClient.beforeBlockRender(var23, var10);
227                                            var13 |= var10.renderBlockByRenderType(var23, var17, var15, var16);
228                                            ForgeHooksClient.afterBlockRender(var23, var10);
229                                        }
230                                    }
231                                }
232                            }
233                        }
234    
235                        if (var14)
236                        {
237                            ForgeHooksClient.afterRenderPass(var11);
238                            this.bytesDrawn += Tessellator.instance.draw();
239                            GL11.glPopMatrix();
240                            GL11.glEndList();
241                            Tessellator.instance.setTranslation(0.0D, 0.0D, 0.0D);
242                        }
243                        else
244                        {
245                            var13 = false;
246                        }
247    
248                        if (var13)
249                        {
250                            this.skipRenderPass[var11] = false;
251                        }
252    
253                        if (!var12)
254                        {
255                            break;
256                        }
257                    }
258                }
259    
260                HashSet var22 = new HashSet();
261                var22.addAll(this.tileEntityRenderers);
262                var22.removeAll(var21);
263                this.tileEntities.addAll(var22);
264                var21.removeAll(this.tileEntityRenderers);
265                this.tileEntities.removeAll(var21);
266                this.isChunkLit = Chunk.isLit;
267                this.isInitialized = true;
268            }
269        }
270    
271        /**
272         * Returns the distance of this chunk renderer to the entity without performing the final normalizing square root,
273         * for performance reasons.
274         */
275        public float distanceToEntitySquared(Entity par1Entity)
276        {
277            float var2 = (float)(par1Entity.posX - (double)this.posXPlus);
278            float var3 = (float)(par1Entity.posY - (double)this.posYPlus);
279            float var4 = (float)(par1Entity.posZ - (double)this.posZPlus);
280            return var2 * var2 + var3 * var3 + var4 * var4;
281        }
282    
283        /**
284         * When called this renderer won't draw anymore until its gets initialized again
285         */
286        public void setDontDraw()
287        {
288            for (int var1 = 0; var1 < 2; ++var1)
289            {
290                this.skipRenderPass[var1] = true;
291            }
292    
293            this.isInFrustum = false;
294            this.isInitialized = false;
295        }
296    
297        public void stopRendering()
298        {
299            this.setDontDraw();
300            this.worldObj = null;
301        }
302    
303        /**
304         * Takes in the pass the call list is being requested for. Args: renderPass
305         */
306        public int getGLCallListForPass(int par1)
307        {
308            return !this.isInFrustum ? -1 : (!this.skipRenderPass[par1] ? this.glRenderList + par1 : -1);
309        }
310    
311        public void updateInFrustum(ICamera par1ICamera)
312        {
313            this.isInFrustum = par1ICamera.isBoundingBoxInFrustum(this.rendererBoundingBox);
314        }
315    
316        /**
317         * Renders the occlusion query GL List
318         */
319        public void callOcclusionQueryList()
320        {
321            GL11.glCallList(this.glRenderList + 2);
322        }
323    
324        /**
325         * Checks if all render passes are to be skipped. Returns false if the renderer is not initialized
326         */
327        public boolean skipAllRenderPasses()
328        {
329            return !this.isInitialized ? false : this.skipRenderPass[0] && this.skipRenderPass[1];
330        }
331    
332        /**
333         * Marks the current renderer data as dirty and needing to be updated.
334         */
335        public void markDirty()
336        {
337            this.needsUpdate = true;
338        }
339    }