package net.minecraft.client.renderer;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.culling.ICamera;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.shader.TesselatorVertexState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.world.ChunkCache;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
public class WorldRenderer
{
private TesselatorVertexState vertexState;
/** Reference to the World object. */
public World worldObj;
private int glRenderList = -1;
//private static Tessellator tessellator = Tessellator.instance;
public static int chunksUpdated;
public int posX;
public int posY;
public int posZ;
/** Pos X minus */
public int posXMinus;
/** Pos Y minus */
public int posYMinus;
/** Pos Z minus */
public int posZMinus;
/** Pos X clipped */
public int posXClip;
/** Pos Y clipped */
public int posYClip;
/** Pos Z clipped */
public int posZClip;
public boolean isInFrustum;
/** Should this renderer skip this render pass */
public boolean[] skipRenderPass = new boolean[2];
/** Pos X plus */
public int posXPlus;
/** Pos Y plus */
public int posYPlus;
/** Pos Z plus */
public int posZPlus;
/** Boolean for whether this renderer needs to be updated or not */
public boolean needsUpdate;
/** Axis aligned bounding box */
public AxisAlignedBB rendererBoundingBox;
/** Chunk index */
public int chunkIndex;
/** Is this renderer visible according to the occlusion query */
public boolean isVisible = true;
/** Is this renderer waiting on the result of the occlusion query */
public boolean isWaitingOnOcclusionQuery;
/** OpenGL occlusion query */
public int glOcclusionQuery;
/** Is the chunk lit */
public boolean isChunkLit;
private boolean isInitialized;
/** All the tile entities that have special rendering code for this chunk */
public List tileEntityRenderers = new ArrayList();
private List tileEntities;
/** Bytes sent to the GPU */
private int bytesDrawn;
private static final String __OBFID = "CL_00000942";
public WorldRenderer(World p_i1240_1_, List p_i1240_2_, int p_i1240_3_, int p_i1240_4_, int p_i1240_5_, int p_i1240_6_)
{
this.worldObj = p_i1240_1_;
this.vertexState = null;
this.tileEntities = p_i1240_2_;
this.glRenderList = p_i1240_6_;
this.posX = -999;
this.setPosition(p_i1240_3_, p_i1240_4_, p_i1240_5_);
this.needsUpdate = false;
}
/**
* Sets a new position for the renderer and setting it up so it can be reloaded with the new data for that position
*/
public void setPosition(int p_78913_1_, int p_78913_2_, int p_78913_3_)
{
if (p_78913_1_ != this.posX || p_78913_2_ != this.posY || p_78913_3_ != this.posZ)
{
this.setDontDraw();
this.posX = p_78913_1_;
this.posY = p_78913_2_;
this.posZ = p_78913_3_;
this.posXPlus = p_78913_1_ + 8;
this.posYPlus = p_78913_2_ + 8;
this.posZPlus = p_78913_3_ + 8;
this.posXClip = p_78913_1_ & 1023;
this.posYClip = p_78913_2_;
this.posZClip = p_78913_3_ & 1023;
this.posXMinus = p_78913_1_ - this.posXClip;
this.posYMinus = p_78913_2_ - this.posYClip;
this.posZMinus = p_78913_3_ - this.posZClip;
float f = 6.0F;
this.rendererBoundingBox = AxisAlignedBB.getBoundingBox((double)((float)p_78913_1_ - f), (double)((float)p_78913_2_ - f), (double)((float)p_78913_3_ - f), (double)((float)(p_78913_1_ + 16) + f), (double)((float)(p_78913_2_ + 16) + f), (double)((float)(p_78913_3_ + 16) + f));
GL11.glNewList(this.glRenderList + 2, GL11.GL_COMPILE);
RenderItem.renderAABB(AxisAlignedBB.getBoundingBox((double)((float)this.posXClip - f), (double)((float)this.posYClip - f), (double)((float)this.posZClip - f), (double)((float)(this.posXClip + 16) + f), (double)((float)(this.posYClip + 16) + f), (double)((float)(this.posZClip + 16) + f)));
GL11.glEndList();
this.markDirty();
}
}
private void setupGLTranslation()
{
GL11.glTranslatef((float)this.posXClip, (float)this.posYClip, (float)this.posZClip);
}
/**
* Will update this chunk renderer
*/
public void updateRenderer(EntityLivingBase p_147892_1_)
{
if (this.needsUpdate)
{
this.needsUpdate = false;
int i = this.posX;
int j = this.posY;
int k = this.posZ;
int l = this.posX + 16;
int i1 = this.posY + 16;
int j1 = this.posZ + 16;
for (int k1 = 0; k1 < 2; ++k1)
{
this.skipRenderPass[k1] = true;
}
Chunk.isLit = false;
HashSet hashset = new HashSet();
hashset.addAll(this.tileEntityRenderers);
this.tileEntityRenderers.clear();
Minecraft minecraft = Minecraft.getMinecraft();
EntityLivingBase entitylivingbase1 = minecraft.renderViewEntity;
int l1 = MathHelper.floor_double(entitylivingbase1.posX);
int i2 = MathHelper.floor_double(entitylivingbase1.posY);
int j2 = MathHelper.floor_double(entitylivingbase1.posZ);
byte b0 = 1;
ChunkCache chunkcache = new ChunkCache(this.worldObj, i - b0, j - b0, k - b0, l + b0, i1 + b0, j1 + b0, b0);
if (!chunkcache.extendedLevelsInChunkCache())
{
++chunksUpdated;
RenderBlocks renderblocks = new RenderBlocks(chunkcache);
net.minecraftforge.client.ForgeHooksClient.setWorldRendererRB(renderblocks);
this.bytesDrawn = 0;
this.vertexState = null;
for (int k2 = 0; k2 < 2; ++k2)
{
boolean flag = false;
boolean flag1 = false;
boolean flag2 = false;
for (int l2 = j; l2 < i1; ++l2)
{
for (int i3 = k; i3 < j1; ++i3)
{
for (int j3 = i; j3 < l; ++j3)
{
Block block = chunkcache.getBlock(j3, l2, i3);
if (block.getMaterial() != Material.air)
{
if (!flag2)
{
flag2 = true;
this.preRenderBlocks(k2);
}
if (k2 == 0 && block.hasTileEntity(chunkcache.getBlockMetadata(j3, l2, i3)))
{
TileEntity tileentity = chunkcache.getTileEntity(j3, l2, i3);
if (TileEntityRendererDispatcher.instance.hasSpecialRenderer(tileentity))
{
this.tileEntityRenderers.add(tileentity);
}
}
int k3 = block.getRenderBlockPass();
if (k3 > k2)
{
flag = true;
}
if (!block.canRenderInPass(k2)) continue;
{
flag1 |= renderblocks.renderBlockByRenderType(block, j3, l2, i3);
if (block.getRenderType() == 0 && j3 == l1 && l2 == i2 && i3 == j2)
{
renderblocks.setRenderFromInside(true);
renderblocks.setRenderAllFaces(true);
renderblocks.renderBlockByRenderType(block, j3, l2, i3);
renderblocks.setRenderFromInside(false);
renderblocks.setRenderAllFaces(false);
}
}
}
}
}
}
if (flag1)
{
this.skipRenderPass[k2] = false;
}
if (flag2)
{
this.postRenderBlocks(k2, p_147892_1_);
}
else
{
flag1 = false;
}
if (!flag)
{
break;
}
}
net.minecraftforge.client.ForgeHooksClient.setWorldRendererRB(null);
}
HashSet hashset1 = new HashSet();
hashset1.addAll(this.tileEntityRenderers);
hashset1.removeAll(hashset);
this.tileEntities.addAll(hashset1);
hashset.removeAll(this.tileEntityRenderers);
this.tileEntities.removeAll(hashset);
this.isChunkLit = Chunk.isLit;
this.isInitialized = true;
}
}
private void preRenderBlocks(int p_147890_1_)
{
GL11.glNewList(this.glRenderList + p_147890_1_, GL11.GL_COMPILE);
GL11.glPushMatrix();
this.setupGLTranslation();
float f = 1.000001F;
GL11.glTranslatef(-8.0F, -8.0F, -8.0F);
GL11.glScalef(f, f, f);
GL11.glTranslatef(8.0F, 8.0F, 8.0F);
net.minecraftforge.client.ForgeHooksClient.onPreRenderWorld(this, p_147890_1_);
Tessellator.instance.startDrawingQuads();
Tessellator.instance.setTranslation((double)(-this.posX), (double)(-this.posY), (double)(-this.posZ));
}
private void postRenderBlocks(int p_147891_1_, EntityLivingBase p_147891_2_)
{
if (p_147891_1_ == 1 && !this.skipRenderPass[p_147891_1_])
{
this.vertexState = Tessellator.instance.getVertexState((float)p_147891_2_.posX, (float)p_147891_2_.posY, (float)p_147891_2_.posZ);
}
this.bytesDrawn += Tessellator.instance.draw();
net.minecraftforge.client.ForgeHooksClient.onPostRenderWorld(this, p_147891_1_);
GL11.glPopMatrix();
GL11.glEndList();
Tessellator.instance.setTranslation(0.0D, 0.0D, 0.0D);
}
public void updateRendererSort(EntityLivingBase p_147889_1_)
{
if (this.vertexState != null && !this.skipRenderPass[1])
{
this.preRenderBlocks(1);
Tessellator.instance.setVertexState(this.vertexState);
this.postRenderBlocks(1, p_147889_1_);
}
}
/**
* Returns the distance of this chunk renderer to the entity without performing the final normalizing square root,
* for performance reasons.
*/
public float distanceToEntitySquared(Entity p_78912_1_)
{
float f = (float)(p_78912_1_.posX - (double)this.posXPlus);
float f1 = (float)(p_78912_1_.posY - (double)this.posYPlus);
float f2 = (float)(p_78912_1_.posZ - (double)this.posZPlus);
return f * f + f1 * f1 + f2 * f2;
}
/**
* When called this renderer won't draw anymore until its gets initialized again
*/
public void setDontDraw()
{
for (int i = 0; i < 2; ++i)
{
this.skipRenderPass[i] = true;
}
this.isInFrustum = false;
this.isInitialized = false;
this.vertexState = null;
}
public void stopRendering()
{
this.setDontDraw();
this.worldObj = null;
}
/**
* Takes in the pass the call list is being requested for. Args: renderPass
*/
public int getGLCallListForPass(int p_78909_1_)
{
return !this.isInFrustum ? -1 : (!this.skipRenderPass[p_78909_1_] ? this.glRenderList + p_78909_1_ : -1);
}
public void updateInFrustum(ICamera p_78908_1_)
{
this.isInFrustum = p_78908_1_.isBoundingBoxInFrustum(this.rendererBoundingBox);
}
/**
* Renders the occlusion query GL List
*/
public void callOcclusionQueryList()
{
GL11.glCallList(this.glRenderList + 2);
}
/**
* Checks if all render passes are to be skipped. Returns false if the renderer is not initialized
*/
public boolean skipAllRenderPasses()
{
return !this.isInitialized ? false : this.skipRenderPass[0] && this.skipRenderPass[1];
}
/**
* Marks the current renderer data as dirty and needing to be updated.
*/
public void markDirty()
{
this.needsUpdate = true;
}
}