package blusunrize.immersiveengineering.common.util.compat.jei.arcfurnace; import blusunrize.immersiveengineering.api.crafting.ArcFurnaceRecipe; import blusunrize.immersiveengineering.common.util.IELogger; import blusunrize.immersiveengineering.common.util.compat.jei.JEIHelper; import blusunrize.immersiveengineering.common.util.compat.jei.MultiblockRecipeWrapper; import net.minecraft.client.Minecraft; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.util.HashMap; public class ArcFurnaceRecipeWrapper extends MultiblockRecipeWrapper { public String specialRecipeType; int time; int energy; public ArcFurnaceRecipeWrapper(ArcFurnaceRecipe recipe) { super(recipe); String name = this.getClass().getName(); int idx = name.indexOf("ArcFurnaceRecipeWrapper"); if(idx>=0 && idx+"ArcFurnaceRecipeWrapper".length()<name.length()) specialRecipeType = name.substring(idx+"ArcFurnaceRecipeWrapper".length()); time = recipe.getTotalProcessTime(); energy = recipe.getTotalProcessEnergy()/time; } @Override public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { String s = energy+" RF/t"; minecraft.fontRendererObj.drawString(s, 54,38, 0x777777); s = time+" ticks"; minecraft.fontRendererObj.drawString(s, 54,48, 0x777777); } public static ArcFurnaceRecipeWrapper getWrapper(ArcFurnaceRecipe recipe) { if(recipe.specialRecipeType==null) return new ArcFurnaceRecipeWrapper(recipe); else { try { return getWrapperClass(recipe.specialRecipeType).getConstructor(ArcFurnaceRecipe.class).newInstance(recipe); } catch (Exception e) { IELogger.error("Adding an ArcFurnaceRecipe: "+recipe.specialRecipeType+", threw an error! Report this!"); e.printStackTrace(); } } return new ArcFurnaceRecipeWrapper(recipe); } private static HashMap<String, Class<? extends ArcFurnaceRecipeWrapper>> dynamicSubclasses = new HashMap(); public static Class<? extends ArcFurnaceRecipeWrapper> getWrapperClass(String subtype) { if(subtype==null) return ArcFurnaceRecipeWrapper.class; if(dynamicSubclasses.containsKey(subtype)) return dynamicSubclasses.get(subtype); try { Class<? extends ArcFurnaceRecipeWrapper> subWrapper = createSubWrapper(subtype); if(subWrapper!=null) { dynamicSubclasses.put(subtype, subWrapper); ArcFurnaceRecipeCategory cat = new ArcFurnaceRecipeCategory(JEIHelper.jeiHelpers.getGuiHelper(), subtype, subWrapper); //Can't add Categories dynamically anymore =c //JEIHelper.modRegistry.addRecipeCategories(cat); //JEIHelper.modRegistry.addRecipeHandlers(cat); return subWrapper; } } catch(Exception e) { IELogger.error("The dynamic JEI recipe handler for the ArcFurnace - "+subtype+", threw an error! Report this!"); e.printStackTrace(); } return ArcFurnaceRecipeWrapper.class; } private static Class<? extends ArcFurnaceRecipeWrapper> createSubWrapper(String subtype) throws Exception { String entitySuperClassName = Type.getInternalName(ArcFurnaceRecipeWrapper.class); String entityProxySubClassName = ArcFurnaceRecipeWrapper.class.getSimpleName().concat(subtype); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(Opcodes.V1_6,Opcodes.ACC_PUBLIC+Opcodes.ACC_SUPER,entityProxySubClassName,null,entitySuperClassName,null); cw.visitSource(entityProxySubClassName.concat(".java"),null); //create constructor String methodDescriptor = "(L"+Type.getInternalName(ArcFurnaceRecipe.class)+";)V"; MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,"<init>",methodDescriptor,null,null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD,0); mv.visitVarInsn(Opcodes.ALOAD,1); mv.visitMethodInsn(Opcodes.INVOKESPECIAL,entitySuperClassName,"<init>",methodDescriptor, false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0,0); mv.visitEnd(); cw.visitEnd(); return (Class<? extends ArcFurnaceRecipeWrapper>) new ProxyClassLoader(Thread.currentThread().getContextClassLoader(),cw.toByteArray()).loadClass(entityProxySubClassName.replaceAll("/",".")); } public static class ProxyClassLoader extends ClassLoader { private byte[] rawClassBytes; public ProxyClassLoader(ClassLoader parentClassLoader,byte[] classBytes) { super(parentClassLoader); this.rawClassBytes = classBytes; } @Override public Class findClass(String name) { return defineClass(name,this.rawClassBytes, 0,this.rawClassBytes.length); } } }