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 }