blusunrize.immersiveengineering.common.util.compat.jei.arcfurnace.ArcFurnaceRecipeWrapper.java Source code

Java tutorial

Introduction

Here is the source code for blusunrize.immersiveengineering.common.util.compat.jei.arcfurnace.ArcFurnaceRecipeWrapper.java

Source

/*
 * BluSunrize
 * Copyright (c) 2017
 *
 * This code is licensed under "Blu's License of Common Sense"
 * Details can be found in the license file in the root folder of this project
 */

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.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 + " IF/t";
        minecraft.fontRenderer.drawString(s, 54, 38, 0x777777);
        s = time + " ticks";
        minecraft.fontRenderer.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);
                //Can't add Categories dynamically anymore =c
                //ArcFurnaceRecipeCategory cat = new ArcFurnaceRecipeCategory(JEIHelper.jeiHelpers.getGuiHelper(), subtype, subWrapper);
                //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);
        }
    }
}