package net.minecraft.client.renderer;
import cpw.mods.fml.client.TextureFXManager;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import net.minecraft.client.renderer.texturefx.TextureFX;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.texturepacks.ITexturePack;
import net.minecraft.client.texturepacks.TexturePackList;
import net.minecraft.util.IntHashMap;
import org.lwjgl.opengl.GL11;
import net.minecraftforge.client.ForgeHooksClient;
@SideOnly(Side.CLIENT)
public class RenderEngine
{
private HashMap textureMap = new HashMap();
/** Texture contents map (key: texture name, value: int[] contents) */
private HashMap textureContentsMap = new HashMap();
/** A mapping from GL texture names (integers) to BufferedImage instances */
private IntHashMap textureNameToImageMap = new IntHashMap();
/** An IntBuffer storing 1 int used as scratch space in RenderEngine */
private IntBuffer singleIntBuffer = GLAllocation.createDirectIntBuffer(1);
/** Stores the image data for the texture. */
private ByteBuffer imageData = GLAllocation.createDirectByteBuffer(16777216);
public List textureList = new ArrayList();
/** A mapping from image URLs to ThreadDownloadImageData instances */
private Map urlToImageDataMap = new HashMap();
/** Reference to the GameSettings object */
private GameSettings options;
/** Flag set when a texture should not be repeated */
public boolean clampTexture = false;
/** Flag set when a texture should use blurry resizing */
public boolean blurTexture = false;
/** Texture pack */
public TexturePackList texturePack;
/** Missing texture image */
private BufferedImage missingTextureImage = new BufferedImage(64, 64, 2);
public static Logger log = FMLLog.getLogger();
public RenderEngine(TexturePackList par1TexturePackList, GameSettings par2GameSettings)
{
this.texturePack = par1TexturePackList;
this.options = par2GameSettings;
Graphics var3 = this.missingTextureImage.getGraphics();
var3.setColor(Color.WHITE);
var3.fillRect(0, 0, 64, 64);
var3.setColor(Color.BLACK);
var3.drawString("missingtex", 1, 10);
var3.dispose();
}
public int[] getTextureContents(String par1Str)
{
ITexturePack var2 = this.texturePack.getSelectedTexturePack();
int[] var3 = (int[])this.textureContentsMap.get(par1Str);
if (var3 != null)
{
return var3;
}
else
{
try
{
Object var4 = null;
int[] var7;
if (par1Str.startsWith("##"))
{
var7 = this.getImageContentsAndAllocate(this.unwrapImageByColumns(this.readTextureImage(var2.getResourceAsStream(par1Str.substring(2)))));
}
else if (par1Str.startsWith("%clamp%"))
{
this.clampTexture = true;
var7 = this.getImageContentsAndAllocate(this.readTextureImage(var2.getResourceAsStream(par1Str.substring(7))));
this.clampTexture = false;
}
else if (par1Str.startsWith("%blur%"))
{
this.blurTexture = true;
this.clampTexture = true;
var7 = this.getImageContentsAndAllocate(this.readTextureImage(var2.getResourceAsStream(par1Str.substring(6))));
this.clampTexture = false;
this.blurTexture = false;
}
else
{
InputStream var8 = var2.getResourceAsStream(par1Str);
if (var8 == null)
{
var7 = this.getImageContentsAndAllocate(this.missingTextureImage);
}
else
{
var7 = this.getImageContentsAndAllocate(this.readTextureImage(var8));
}
}
this.textureContentsMap.put(par1Str, var7);
return var7;
}
catch (Exception var6)
{
log.log(Level.INFO, String.format("An error occured reading texture file %s (getTexture)", par1Str), var6);
var6.printStackTrace();
int[] var5 = this.getImageContentsAndAllocate(this.missingTextureImage);
this.textureContentsMap.put(par1Str, var5);
return var5;
}
}
}
private int[] getImageContentsAndAllocate(BufferedImage par1BufferedImage)
{
int var2 = par1BufferedImage.getWidth();
int var3 = par1BufferedImage.getHeight();
int[] var4 = new int[var2 * var3];
par1BufferedImage.getRGB(0, 0, var2, var3, var4, 0, var2);
return var4;
}
private int[] getImageContents(BufferedImage par1BufferedImage, int[] par2ArrayOfInteger)
{
int var3 = par1BufferedImage.getWidth();
int var4 = par1BufferedImage.getHeight();
par1BufferedImage.getRGB(0, 0, var3, var4, par2ArrayOfInteger, 0, var3);
return par2ArrayOfInteger;
}
public int getTexture(String par1Str)
{
Integer var2 = (Integer)this.textureMap.get(par1Str);
if (var2 != null)
{
return var2.intValue();
}
else
{
ITexturePack var6 = this.texturePack.getSelectedTexturePack();
try
{
ForgeHooksClient.onTextureLoadPre(par1Str);
this.singleIntBuffer.clear();
GLAllocation.generateTextureNames(this.singleIntBuffer);
int var3 = this.singleIntBuffer.get(0);
if (par1Str.startsWith("##"))
{
this.setupTexture(this.unwrapImageByColumns(this.readTextureImage(var6.getResourceAsStream(par1Str.substring(2)))), var3);
}
else if (par1Str.startsWith("%clamp%"))
{
this.clampTexture = true;
this.setupTexture(this.readTextureImage(var6.getResourceAsStream(par1Str.substring(7))), var3);
this.clampTexture = false;
}
else if (par1Str.startsWith("%blur%"))
{
this.blurTexture = true;
this.setupTexture(this.readTextureImage(var6.getResourceAsStream(par1Str.substring(6))), var3);
this.blurTexture = false;
}
else if (par1Str.startsWith("%blurclamp%"))
{
this.blurTexture = true;
this.clampTexture = true;
this.setupTexture(this.readTextureImage(var6.getResourceAsStream(par1Str.substring(11))), var3);
this.blurTexture = false;
this.clampTexture = false;
}
else
{
InputStream var7 = var6.getResourceAsStream(par1Str);
if (var7 == null)
{
this.setupTexture(this.missingTextureImage, var3);
}
else
{
this.setupTexture(this.readTextureImage(var7), var3);
}
}
this.textureMap.put(par1Str, Integer.valueOf(var3));
ForgeHooksClient.onTextureLoad(par1Str, var6);
return var3;
}
catch (Exception var5)
{
var5.printStackTrace();
GLAllocation.generateTextureNames(this.singleIntBuffer);
int var4 = this.singleIntBuffer.get(0);
this.setupTexture(this.missingTextureImage, var4);
this.textureMap.put(par1Str, Integer.valueOf(var4));
return var4;
}
}
}
/**
* Takes an image with multiple 16-pixel-wide columns and creates a new 16-pixel-wide image where the columns are
* stacked vertically
*/
private BufferedImage unwrapImageByColumns(BufferedImage par1BufferedImage)
{
int var2 = par1BufferedImage.getWidth() / 16;
BufferedImage var3 = new BufferedImage(16, par1BufferedImage.getHeight() * var2, 2);
Graphics var4 = var3.getGraphics();
for (int var5 = 0; var5 < var2; ++var5)
{
var4.drawImage(par1BufferedImage, -var5 * 16, var5 * par1BufferedImage.getHeight(), (ImageObserver)null);
}
var4.dispose();
return var3;
}
/**
* Copy the supplied image onto a newly-allocated OpenGL texture, returning the allocated texture name
*/
public int allocateAndSetupTexture(BufferedImage par1BufferedImage)
{
this.singleIntBuffer.clear();
GLAllocation.generateTextureNames(this.singleIntBuffer);
int var2 = this.singleIntBuffer.get(0);
this.setupTexture(par1BufferedImage, var2);
this.textureNameToImageMap.addKey(var2, par1BufferedImage);
return var2;
}
/**
* Copy the supplied image onto the specified OpenGL texture
*/
public void setupTexture(BufferedImage par1BufferedImage, int par2)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, par2);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
if (this.blurTexture)
{
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
}
if (this.clampTexture)
{
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
}
else
{
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
}
int var3 = par1BufferedImage.getWidth();
int var4 = par1BufferedImage.getHeight();
TextureFXManager.instance().setTextureDimensions(par2, var3, var4, (List<TextureFX>)textureList);
int[] var5 = new int[var3 * var4];
byte[] var6 = new byte[var3 * var4 * 4];
par1BufferedImage.getRGB(0, 0, var3, var4, var5, 0, var3);
for (int var7 = 0; var7 < var5.length; ++var7)
{
int var8 = var5[var7] >> 24 & 255;
int var9 = var5[var7] >> 16 & 255;
int var10 = var5[var7] >> 8 & 255;
int var11 = var5[var7] & 255;
if (this.options != null && this.options.anaglyph)
{
int var12 = (var9 * 30 + var10 * 59 + var11 * 11) / 100;
int var13 = (var9 * 30 + var10 * 70) / 100;
int var14 = (var9 * 30 + var11 * 70) / 100;
var9 = var12;
var10 = var13;
var11 = var14;
}
var6[var7 * 4 + 0] = (byte)var9;
var6[var7 * 4 + 1] = (byte)var10;
var6[var7 * 4 + 2] = (byte)var11;
var6[var7 * 4 + 3] = (byte)var8;
}
this.imageData.clear();
this.imageData.put(var6);
this.imageData.position(0).limit(var6.length);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, var3, var4, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, this.imageData);
}
public void createTextureFromBytes(int[] par1ArrayOfInteger, int par2, int par3, int par4)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, par4);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
if (this.blurTexture)
{
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
}
if (this.clampTexture)
{
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
}
else
{
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
}
byte[] var5 = new byte[par2 * par3 * 4];
for (int var6 = 0; var6 < par1ArrayOfInteger.length; ++var6)
{
int var7 = par1ArrayOfInteger[var6] >> 24 & 255;
int var8 = par1ArrayOfInteger[var6] >> 16 & 255;
int var9 = par1ArrayOfInteger[var6] >> 8 & 255;
int var10 = par1ArrayOfInteger[var6] & 255;
if (this.options != null && this.options.anaglyph)
{
int var11 = (var8 * 30 + var9 * 59 + var10 * 11) / 100;
int var12 = (var8 * 30 + var9 * 70) / 100;
int var13 = (var8 * 30 + var10 * 70) / 100;
var8 = var11;
var9 = var12;
var10 = var13;
}
var5[var6 * 4 + 0] = (byte)var8;
var5[var6 * 4 + 1] = (byte)var9;
var5[var6 * 4 + 2] = (byte)var10;
var5[var6 * 4 + 3] = (byte)var7;
}
this.imageData.clear();
this.imageData.put(var5);
this.imageData.position(0).limit(var5.length);
GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, par2, par3, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, this.imageData);
}
/**
* Deletes a single GL texture
*/
public void deleteTexture(int par1)
{
this.textureNameToImageMap.removeObject(par1);
this.singleIntBuffer.clear();
this.singleIntBuffer.put(par1);
this.singleIntBuffer.flip();
GL11.glDeleteTextures(this.singleIntBuffer);
}
/**
* Takes a URL of a downloadable image and the name of the local image to be used as a fallback. If the image has
* been downloaded, returns the GL texture of the downloaded image, otherwise returns the GL texture of the fallback
* image.
*/
public int getTextureForDownloadableImage(String par1Str, String par2Str)
{
ThreadDownloadImageData var3 = (ThreadDownloadImageData)this.urlToImageDataMap.get(par1Str);
if (var3 != null && var3.image != null && !var3.textureSetupComplete)
{
if (var3.textureName < 0)
{
var3.textureName = this.allocateAndSetupTexture(var3.image);
}
else
{
this.setupTexture(var3.image, var3.textureName);
}
var3.textureSetupComplete = true;
}
return var3 != null && var3.textureName >= 0 ? var3.textureName : (par2Str == null ? -1 : this.getTexture(par2Str));
}
/**
* Checks if urlToImageDataMap has image data for the given key
*/
public boolean hasImageData(String par1Str)
{
return this.urlToImageDataMap.containsKey(par1Str);
}
/**
* Return a ThreadDownloadImageData instance for the given URL. If it does not already exist, it is created and
* uses the passed ImageBuffer. If it does, its reference count is incremented.
*/
public ThreadDownloadImageData obtainImageData(String par1Str, IImageBuffer par2IImageBuffer)
{
ThreadDownloadImageData var3 = (ThreadDownloadImageData)this.urlToImageDataMap.get(par1Str);
if (var3 == null)
{
this.urlToImageDataMap.put(par1Str, new ThreadDownloadImageData(par1Str, par2IImageBuffer));
}
else
{
++var3.referenceCount;
}
return var3;
}
/**
* Decrements the reference count for a given URL, deleting the image data if the reference count hits 0
*/
public void releaseImageData(String par1Str)
{
ThreadDownloadImageData var2 = (ThreadDownloadImageData)this.urlToImageDataMap.get(par1Str);
if (var2 != null)
{
--var2.referenceCount;
if (var2.referenceCount == 0)
{
if (var2.textureName >= 0)
{
this.deleteTexture(var2.textureName);
}
this.urlToImageDataMap.remove(par1Str);
}
}
}
public void registerTextureFX(TextureFX par1TextureFX)
{
TextureFXManager.instance().onPreRegisterEffect(par1TextureFX);
this.textureList.add(par1TextureFX);
par1TextureFX.onTick();
}
public void updateDynamicTextures()
{
int var1 = -1;
for (int var2 = 0; var2 < this.textureList.size(); ++var2)
{
TextureFX var3 = (TextureFX)this.textureList.get(var2);
var3.anaglyphEnabled = this.options.anaglyph;
if (TextureFXManager.instance().onUpdateTextureEffect(var3))
{
var1 = this.updateDynamicTexture(var3, var1);
}
}
}
/**
* Updates a single dynamic texture
*/
public int updateDynamicTexture(TextureFX par1TextureFX, int par2)
{
Dimension dim = TextureFXManager.instance().getTextureDimensions(par1TextureFX);
int tWidth = dim.width >> 4;
int tHeight = dim.height >> 4;
int tLen = tWidth * tHeight << 2;
if (par1TextureFX.imageData.length == tLen)
{
this.imageData.clear();
this.imageData.put(par1TextureFX.imageData);
this.imageData.position(0).limit(par1TextureFX.imageData.length);
}
else
{
TextureFXManager.instance().scaleTextureFXData(par1TextureFX.imageData, imageData, tWidth, tLen);
}
if (par1TextureFX.textureId != par2)
{
par1TextureFX.bindImage(this);
par2 = par1TextureFX.textureId;
}
for (int var3 = 0; var3 < par1TextureFX.tileSize; ++var3)
{
int xOffset = par1TextureFX.iconIndex % 16 * tWidth + var3 * tWidth;
for (int var4 = 0; var4 < par1TextureFX.tileSize; ++var4)
{
int yOffset = par1TextureFX.iconIndex / 16 * tHeight + var4 * tHeight;
GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, xOffset, yOffset, tWidth, tHeight, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, this.imageData);
}
}
return par2;
}
/**
* Call setupTexture on all currently-loaded textures again to account for changes in rendering options
*/
public void refreshTextures()
{
ITexturePack var1 = this.texturePack.getSelectedTexturePack();
Iterator var2 = this.textureNameToImageMap.getKeySet().iterator();
BufferedImage var4;
while (var2.hasNext())
{
int var3 = ((Integer)var2.next()).intValue();
var4 = (BufferedImage)this.textureNameToImageMap.lookup(var3);
this.setupTexture(var4, var3);
}
ThreadDownloadImageData var8;
for (var2 = this.urlToImageDataMap.values().iterator(); var2.hasNext(); var8.textureSetupComplete = false)
{
var8 = (ThreadDownloadImageData)var2.next();
}
var2 = this.textureMap.keySet().iterator();
String var9;
while (var2.hasNext())
{
var9 = (String)var2.next();
try
{
if (var9.startsWith("##"))
{
var4 = this.unwrapImageByColumns(this.readTextureImage(var1.getResourceAsStream(var9.substring(2))));
}
else if (var9.startsWith("%clamp%"))
{
this.clampTexture = true;
var4 = this.readTextureImage(var1.getResourceAsStream(var9.substring(7)));
}
else if (var9.startsWith("%blur%"))
{
this.blurTexture = true;
var4 = this.readTextureImage(var1.getResourceAsStream(var9.substring(6)));
}
else if (var9.startsWith("%blurclamp%"))
{
this.blurTexture = true;
this.clampTexture = true;
var4 = this.readTextureImage(var1.getResourceAsStream(var9.substring(11)));
}
else
{
var4 = this.readTextureImage(var1.getResourceAsStream(var9));
}
int var5 = ((Integer)this.textureMap.get(var9)).intValue();
this.setupTexture(var4, var5);
this.blurTexture = false;
this.clampTexture = false;
}
catch (Exception var7)
{
log.log(Level.INFO,String.format("An error occured reading texture file %s (refreshTexture)", var9), var7);
var7.printStackTrace();
}
}
var2 = this.textureContentsMap.keySet().iterator();
while (var2.hasNext())
{
var9 = (String)var2.next();
try
{
if (var9.startsWith("##"))
{
var4 = this.unwrapImageByColumns(this.readTextureImage(var1.getResourceAsStream(var9.substring(2))));
}
else if (var9.startsWith("%clamp%"))
{
this.clampTexture = true;
var4 = this.readTextureImage(var1.getResourceAsStream(var9.substring(7)));
}
else if (var9.startsWith("%blur%"))
{
this.blurTexture = true;
var4 = this.readTextureImage(var1.getResourceAsStream(var9.substring(6)));
}
else
{
var4 = this.readTextureImage(var1.getResourceAsStream(var9));
}
this.getImageContents(var4, (int[])this.textureContentsMap.get(var9));
this.blurTexture = false;
this.clampTexture = false;
}
catch (Exception var6)
{
log.log(Level.INFO,String.format("An error occured reading texture file data %s (refreshTexture)", var9), var6);
var6.printStackTrace();
}
}
}
/**
* Returns a BufferedImage read off the provided input stream. Args: inputStream
*/
private BufferedImage readTextureImage(InputStream par1InputStream) throws IOException
{
BufferedImage var2 = ImageIO.read(par1InputStream);
par1InputStream.close();
return var2;
}
public void bindTexture(int par1)
{
if (par1 >= 0)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, par1);
}
}
}