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