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