001package net.minecraftforge.client;
002
003import java.util.HashMap;
004import java.util.Random;
005import java.util.TreeSet;
006
007import org.lwjgl.opengl.GL11;
008import org.lwjgl.opengl.GL12;
009
010import cpw.mods.fml.client.FMLClientHandler;
011
012import net.minecraft.client.Minecraft;
013import net.minecraft.block.Block;
014import net.minecraft.entity.item.EntityItem;
015import net.minecraft.entity.EntityLiving;
016import net.minecraft.entity.player.EntityPlayer;
017import net.minecraft.client.texturepacks.ITexturePack;
018import net.minecraft.item.Item;
019import net.minecraft.item.ItemBlock;
020import net.minecraft.item.ItemStack;
021import net.minecraft.util.MathHelper;
022import net.minecraft.util.MovingObjectPosition;
023import net.minecraft.client.renderer.RenderBlocks;
024import net.minecraft.client.renderer.RenderEngine;
025import net.minecraft.client.renderer.RenderGlobal;
026import net.minecraft.client.renderer.Tessellator;
027import net.minecraft.client.renderer.entity.RenderItem;
028import net.minecraft.client.renderer.texture.TextureMap;
029import net.minecraftforge.client.event.DrawBlockHighlightEvent;
030import net.minecraftforge.client.event.RenderWorldLastEvent;
031import net.minecraftforge.client.event.TextureLoadEvent;
032import net.minecraftforge.client.event.TextureStitchEvent;
033import net.minecraftforge.common.IArmorTextureProvider;
034import net.minecraftforge.common.MinecraftForge;
035import static net.minecraftforge.client.IItemRenderer.ItemRenderType.*;
036import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.*;
037
038public class ForgeHooksClient
039{
040    static RenderEngine engine()
041    {
042        return FMLClientHandler.instance().getClient().renderEngine;
043    }
044
045    public static String getArmorTexture(ItemStack armor, String _default)
046    {
047        if (armor.getItem() instanceof IArmorTextureProvider)
048        {
049            return ((IArmorTextureProvider)armor.getItem()).getArmorTextureFile(armor);
050        }
051        return _default;
052    }
053
054    public static boolean renderEntityItem(EntityItem entity, ItemStack item, float bobing, float rotation, Random random, RenderEngine engine, RenderBlocks renderBlocks)
055    {
056        IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, ENTITY);
057        if (customRenderer == null)
058        {
059            return false;
060        }
061
062        if (customRenderer.shouldUseRenderHelper(ENTITY, item, ENTITY_ROTATION))
063        {
064            GL11.glRotatef(rotation, 0.0F, 1.0F, 0.0F);
065        }
066        if (!customRenderer.shouldUseRenderHelper(ENTITY, item, ENTITY_BOBBING))
067        {
068            GL11.glTranslatef(0.0F, -bobing, 0.0F);
069        }
070        boolean is3D = customRenderer.shouldUseRenderHelper(ENTITY, item, BLOCK_3D);
071
072        if (item.getItem() instanceof ItemBlock && (is3D || RenderBlocks.renderItemIn3d(Block.blocksList[item.itemID].getRenderType())))
073        {
074            engine.func_98187_b("/terrain.png");
075            int renderType = Block.blocksList[item.itemID].getRenderType();
076            float scale = (renderType == 1 || renderType == 19 || renderType == 12 || renderType == 2 ? 0.5F : 0.25F);
077
078            if (RenderItem.field_82407_g)
079            {
080                GL11.glScalef(1.25F, 1.25F, 1.25F);
081                GL11.glTranslatef(0.0F, 0.05F, 0.0F);
082                GL11.glRotatef(-90.0F, 0.0F, 1.0F, 0.0F);
083            }
084
085            GL11.glScalef(scale, scale, scale);
086            
087            int size = item.stackSize;
088            int count = (size > 20 ? 4 : (size > 5 ? 3 : (size > 1 ? 2 : 1)));
089
090            for(int j = 0; j < count; j++)
091            {
092                GL11.glPushMatrix();
093                if (j > 0)
094                {
095                    GL11.glTranslatef(
096                        ((random.nextFloat() * 2.0F - 1.0F) * 0.2F) / 0.5F,
097                        ((random.nextFloat() * 2.0F - 1.0F) * 0.2F) / 0.5F,
098                        ((random.nextFloat() * 2.0F - 1.0F) * 0.2F) / 0.5F);
099                }
100                customRenderer.renderItem(ENTITY, item, renderBlocks, entity);
101                GL11.glPopMatrix();
102            }
103        }
104        else
105        {
106            engine.func_98187_b(item.func_94608_d() == 0 ? "/terrain.png" : "/gui/items.png");
107            GL11.glScalef(0.5F, 0.5F, 0.5F);
108            customRenderer.renderItem(ENTITY, item, renderBlocks, entity);
109        }
110        return true;
111    }
112
113    public static boolean renderInventoryItem(RenderBlocks renderBlocks, RenderEngine engine, ItemStack item, boolean inColor, float zLevel, float x, float y)
114    {
115        IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, INVENTORY);
116        if (customRenderer == null)
117        {
118                return false;
119        }
120
121        engine.func_98187_b(item.func_94608_d() == 0 ? "/terrain.png" : "/gui/items.png");
122        if (customRenderer.shouldUseRenderHelper(INVENTORY, item, INVENTORY_BLOCK))
123        {
124            GL11.glPushMatrix();
125            GL11.glTranslatef(x - 2, y + 3, -3.0F + zLevel);
126            GL11.glScalef(10F, 10F, 10F);
127            GL11.glTranslatef(1.0F, 0.5F, 1.0F);
128            GL11.glScalef(1.0F, 1.0F, -1F);
129            GL11.glRotatef(210F, 1.0F, 0.0F, 0.0F);
130            GL11.glRotatef(45F, 0.0F, 1.0F, 0.0F);
131
132            if(inColor)
133            {
134                int color = Item.itemsList[item.itemID].getColorFromItemStack(item, 0);
135                float r = (float)(color >> 16 & 0xff) / 255F;
136                float g = (float)(color >> 8 & 0xff) / 255F;
137                float b = (float)(color & 0xff) / 255F;
138                GL11.glColor4f(r, g, b, 1.0F);
139            }
140
141            GL11.glRotatef(-90F, 0.0F, 1.0F, 0.0F);
142            renderBlocks.useInventoryTint = inColor;
143            customRenderer.renderItem(INVENTORY, item, renderBlocks);
144            renderBlocks.useInventoryTint = true;
145            GL11.glPopMatrix();
146        }
147        else
148        {
149            GL11.glDisable(GL11.GL_LIGHTING);
150            GL11.glPushMatrix();
151            GL11.glTranslatef(x, y, -3.0F + zLevel);
152
153            if (inColor)
154            {
155                int color = Item.itemsList[item.itemID].getColorFromItemStack(item, 0);
156                float r = (float)(color >> 16 & 255) / 255.0F;
157                float g = (float)(color >> 8 & 255) / 255.0F;
158                float b = (float)(color & 255) / 255.0F;
159                GL11.glColor4f(r, g, b, 1.0F);
160            }
161
162            customRenderer.renderItem(INVENTORY, item, renderBlocks);
163            GL11.glPopMatrix();
164            GL11.glEnable(GL11.GL_LIGHTING);
165        }
166        return true;
167    }
168
169    public static void renderEquippedItem(IItemRenderer customRenderer, RenderBlocks renderBlocks, EntityLiving entity, ItemStack item)
170    {
171        if (customRenderer.shouldUseRenderHelper(EQUIPPED, item, EQUIPPED_BLOCK))
172        {
173            GL11.glPushMatrix();
174            GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
175            customRenderer.renderItem(EQUIPPED, item, renderBlocks, entity);
176            GL11.glPopMatrix();
177        }
178        else
179        {
180            GL11.glPushMatrix();
181            GL11.glEnable(GL12.GL_RESCALE_NORMAL);
182            GL11.glTranslatef(0.0F, -0.3F, 0.0F);
183            GL11.glScalef(1.5F, 1.5F, 1.5F);
184            GL11.glRotatef(50.0F, 0.0F, 1.0F, 0.0F);
185            GL11.glRotatef(335.0F, 0.0F, 0.0F, 1.0F);
186            GL11.glTranslatef(-0.9375F, -0.0625F, 0.0F);
187            customRenderer.renderItem(EQUIPPED, item, renderBlocks, entity);
188            GL11.glDisable(GL12.GL_RESCALE_NORMAL);
189            GL11.glPopMatrix();
190        }
191    }
192
193    //Optifine Helper Functions u.u, these are here specifically for Optifine
194    //Note: When using Optfine, these methods are invoked using reflection, which
195    //incurs a major performance penalty.
196    public static void orientBedCamera(Minecraft mc, EntityLiving entity)
197    {
198        int x = MathHelper.floor_double(entity.posX);
199        int y = MathHelper.floor_double(entity.posY);
200        int z = MathHelper.floor_double(entity.posZ);
201        Block block = Block.blocksList[mc.theWorld.getBlockId(x, y, z)];
202
203        if (block != null && block.isBed(mc.theWorld, x, y, z, entity))
204        {
205            int var12 = block.getBedDirection(mc.theWorld, x, y, z);
206            GL11.glRotatef((float)(var12 * 90), 0.0F, 1.0F, 0.0F);
207        }
208    }
209
210    public static boolean onDrawBlockHighlight(RenderGlobal context, EntityPlayer player, MovingObjectPosition target, int subID, ItemStack currentItem, float partialTicks)
211    {
212        return MinecraftForge.EVENT_BUS.post(new DrawBlockHighlightEvent(context, player, target, subID, currentItem, partialTicks));
213    }
214
215    public static void dispatchRenderLast(RenderGlobal context, float partialTicks)
216    {
217        MinecraftForge.EVENT_BUS.post(new RenderWorldLastEvent(context, partialTicks));
218    }
219
220    public static void onTextureLoad(String texture, ITexturePack pack)
221    {
222        MinecraftForge.EVENT_BUS.post(new TextureLoadEvent(texture, pack));
223    }
224
225    public static void onTextureStitchedPre(TextureMap map)
226    {
227        MinecraftForge.EVENT_BUS.post(new TextureStitchEvent.Pre(map));
228    }
229
230    public static void onTextureStitchedPost(TextureMap map)
231    {
232        MinecraftForge.EVENT_BUS.post(new TextureStitchEvent.Post(map));
233    }
234
235    /**
236     * This is added for Optifine's convenience. And to explode if a ModMaker is developing.
237     * @param texture
238     */
239    public static void onTextureLoadPre(String texture)
240    {
241        if (Tessellator.renderingWorldRenderer)
242        {
243            String msg = String.format("Warning: Texture %s not preloaded, will cause render glitches!", texture);
244            System.out.println(msg);
245            if (Tessellator.class.getPackage() != null)
246            {
247                if (Tessellator.class.getPackage().getName().startsWith("net.minecraft."))
248                {
249                    Minecraft mc = FMLClientHandler.instance().getClient();
250                    if (mc.ingameGUI != null)
251                    {
252                        mc.ingameGUI.getChatGUI().printChatMessage(msg);
253                    }
254                }
255            }
256        }
257    }
258
259    static int renderPass = -1;
260    public static void setRenderPass(int pass)
261    {
262        renderPass = pass;
263    }
264}