    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    }