001package net.minecraft.client.renderer;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.ArrayList;
006import java.util.HashSet;
007import java.util.List;
008import net.minecraft.block.Block;
009import net.minecraft.client.renderer.culling.ICamera;
010import net.minecraft.client.renderer.entity.RenderItem;
011import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
012import net.minecraft.entity.Entity;
013import net.minecraft.tileentity.TileEntity;
014import net.minecraft.util.AxisAlignedBB;
015import net.minecraft.world.ChunkCache;
016import net.minecraft.world.World;
017import net.minecraft.world.chunk.Chunk;
018import org.lwjgl.opengl.GL11;
019
020import net.minecraftforge.client.ForgeHooksClient;
021
022@SideOnly(Side.CLIENT)
023public 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}