aboutsummaryrefslogtreecommitdiff
path: root/src/Java/gtPlusPlus/preloader/asm
diff options
context:
space:
mode:
authorDraknyte1 <Draknyte1@hotmail.com>2017-08-09 18:13:54 +1000
committerDraknyte1 <Draknyte1@hotmail.com>2017-08-09 18:13:54 +1000
commitf329a56cfc49be13de84523bee9990ee14597b62 (patch)
tree5c6b24987035a880749e4d62692d42cc7ab563cf /src/Java/gtPlusPlus/preloader/asm
parentd99058863bb4c717f6c63926d555811df48558af (diff)
downloadGT5-Unofficial-f329a56cfc49be13de84523bee9990ee14597b62.tar.gz
GT5-Unofficial-f329a56cfc49be13de84523bee9990ee14597b62.tar.bz2
GT5-Unofficial-f329a56cfc49be13de84523bee9990ee14597b62.zip
% Rewrote the Preloader mod to now be a dummy mod.
+ Added ASM usage to Preloader. + MC Version annotations to both GT++ and it's child mod GT++ Dark world.
Diffstat (limited to 'src/Java/gtPlusPlus/preloader/asm')
-rw-r--r--src/Java/gtPlusPlus/preloader/asm/Modify_OreDict.java93
-rw-r--r--src/Java/gtPlusPlus/preloader/asm/Preloader_ClassTransformer.java88
-rw-r--r--src/Java/gtPlusPlus/preloader/asm/Preloader_DummyContainer.java78
-rw-r--r--src/Java/gtPlusPlus/preloader/asm/Preloader_FMLLoadingPlugin.java38
4 files changed, 297 insertions, 0 deletions
diff --git a/src/Java/gtPlusPlus/preloader/asm/Modify_OreDict.java b/src/Java/gtPlusPlus/preloader/asm/Modify_OreDict.java
new file mode 100644
index 0000000000..b4a8bf5c00
--- /dev/null
+++ b/src/Java/gtPlusPlus/preloader/asm/Modify_OreDict.java
@@ -0,0 +1,93 @@
+package gtPlusPlus.preloader.asm;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+import com.google.common.collect.Lists;
+
+import cpw.mods.fml.common.FMLLog;
+import cpw.mods.fml.common.Loader;
+import cpw.mods.fml.common.registry.GameData;
+import gtPlusPlus.core.util.reflect.ReflectionUtils;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.oredict.OreDictionary;
+
+@SuppressWarnings("unchecked")
+public class Modify_OreDict extends OreDictionary{
+
+ static Field stack;
+ static Field id;
+
+ private static Map<Integer, List<Integer>> stackToId; // Calculated from 128 * 0.75
+ private static List<ArrayList<ItemStack>> idToStack; //ToDo: Unqualify to List when possible {1.8}
+
+
+ static {
+ try {
+ stack = ReflectionUtils.getField(OreDictionary.class, "stackToId");
+ id = ReflectionUtils.getField(OreDictionary.class, "idToStack");
+ stackToId = (Map<Integer, List<Integer>>) stack.get(OreDictionary.class);
+ idToStack = (List<ArrayList<ItemStack>>) stack.get(OreDictionary.class);
+ }
+ catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {}
+ }
+
+ //Utils.LOG_INFO("O-"+(byte) nameField.get(clazz) + " | "+newValue);
+
+ /**
+ * Registers a ore item into the dictionary.
+ * Raises the registerOre function in all registered handlers.
+ *
+ * @param name The name of the ore
+ * @param id The ID of the ore
+ * @param ore The ore's ItemStack
+ */
+ private static void registerOreImpl(String name, ItemStack ore)
+ {
+ if (name == null || name.isEmpty() || "Unknown".equals(name)) return; //prevent bad IDs.
+ if (ore == null || ore.getItem() == null)
+ {
+ FMLLog.bigWarning("Invalid registration attempt for an Ore Dictionary item with name %s has occurred. The registration has been denied to prevent crashes. The mod responsible for the registration needs to correct this.", name);
+ return; //prevent bad ItemStacks.
+ }
+
+ int oreID = getOreID(name);
+ // HACK: use the registry name's ID. It is unique and it knows about substitutions. Fallback to a -1 value (what Item.getIDForItem would have returned) in the case where the registry is not aware of the item yet
+ // IT should be noted that -1 will fail the gate further down, if an entry already exists with value -1 for this name. This is what is broken and being warned about.
+ // APPARENTLY it's quite common to do this. OreDictionary should be considered alongside Recipes - you can't make them properly until you've registered with the game.
+ String registryName = ore.getItem().delegate.name();
+ int hash;
+ if (registryName == null)
+ {
+ FMLLog.bigWarning("A broken ore dictionary registration with name %s has occurred. It adds an item (type: %s) which is currently unknown to the game registry. This dictionary item can only support a single value when"
+ + " registered with ores like this, and NO I am not going to turn this spam off. Just register your ore dictionary entries after the GameRegistry.\n"
+ + "TO USERS: YES this is a BUG in the mod "+Loader.instance().activeModContainer().getName()+" report it to them!", name, ore.getItem().getClass());
+ hash = -1;
+ }
+ else
+ {
+ hash = GameData.getItemRegistry().getId(registryName);
+ }
+ if (ore.getItemDamage() != WILDCARD_VALUE)
+ {
+ hash |= ((ore.getItemDamage() + 1) << 16); // +1 so 0 is significant
+ }
+
+ //Add things to the baked version, and prevent duplicates
+ List<Integer> ids = stackToId.get(hash);
+ if (ids != null && ids.contains(oreID)) return;
+ if (ids == null)
+ {
+ ids = Lists.newArrayList();
+ stackToId.put(hash, ids);
+ }
+ ids.add(oreID);
+
+ //Add to the unbaked version
+ ore = ore.copy();
+ idToStack.get(oreID).add(ore);
+ MinecraftForge.EVENT_BUS.post(new OreRegisterEvent(name, ore));
+ }
+
+}
diff --git a/src/Java/gtPlusPlus/preloader/asm/Preloader_ClassTransformer.java b/src/Java/gtPlusPlus/preloader/asm/Preloader_ClassTransformer.java
new file mode 100644
index 0000000000..330aef318a
--- /dev/null
+++ b/src/Java/gtPlusPlus/preloader/asm/Preloader_ClassTransformer.java
@@ -0,0 +1,88 @@
+package gtPlusPlus.preloader.asm;
+
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+
+import java.util.Iterator;
+
+import org.objectweb.asm.*;
+import org.objectweb.asm.tree.*;
+
+import gtPlusPlus.core.util.Utils;
+import net.minecraft.launchwrapper.IClassTransformer;
+
+public class Preloader_ClassTransformer implements IClassTransformer {
+
+ @Override
+ public byte[] transform(String name, String transformedName, byte[] basicClass) {
+
+ /*if (name.equals("abq")) {
+ Utils.LOG_ASM("[ASM] INSIDE OBFUSCATED EXPLOSION TRANSFORMER ABOUT TO PATCH: " + name);
+ return patchClassASM(name, basicClass, true);
+ }
+
+ else if (name.equals("net.minecraftforge.oredict.OreDictionary")) {
+ Utils.LOG_ASM("[ASM] INSIDE OREDICT TRANSFORMER ABOUT TO PATCH: " + name);
+ return patchClassASM(name, basicClass, false);
+ }*/
+ return basicClass;
+ }
+
+ public byte[] patchClassASM(String name, byte[] bytes, boolean obfuscated) {
+
+ String targetMethodName = "";
+
+ if(obfuscated == true)
+ targetMethodName ="a";
+ else
+ targetMethodName ="registerOreImpl";
+
+
+ //set up ASM class manipulation stuff. Consult the ASM docs for details
+ ClassNode classNode = new ClassNode();
+ ClassReader classReader = new ClassReader(bytes);
+ classReader.accept(classNode, 0);
+
+
+
+ //Now we loop over all of the methods declared inside the Explosion class until we get to the targetMethodName "doExplosionB"
+
+ // find method to inject into
+ Iterator<MethodNode> methods = classNode.methods.iterator();
+ while(methods.hasNext())
+ {
+ MethodNode m = methods.next();
+ Utils.LOG_ASM("[ASM] Method Name: "+m.name + " Desc:" + m.desc);
+
+ //Check if this is doExplosionB and it's method signature is (Z)V which means that it accepts a boolean (Z) and returns a void (V)
+ if ((m.name.equals(targetMethodName) && m.desc.equals("(Ljava/lang/String;Lnet/minecraft/item/ItemStack;)V")))
+ {
+ Utils.LOG_ASM("[ASM] Inside target method!");
+ // find interesting instructions in method, there is a single FDIV instruction we use as target
+
+ // make new instruction list
+ InsnList toInject = new InsnList();
+
+ //toInject.add(new VarInsnNode(ALOAD, 0));
+
+ toInject.add(new VarInsnNode(ALOAD, 1));
+ toInject.add(new MethodInsnNode(INVOKESTATIC, "gtPlusPlus/preloader/Preloader_GT_OreDict", "removeCircuit", "(Lnet/minecraft/item/ItemStack;)Z, false"));
+ toInject.add(new VarInsnNode(Opcodes.IFEQ, 1));
+ toInject.add(new VarInsnNode(Opcodes.RETURN, 0));
+ //toInject.add(new VarInsnNode(org.objectweb.asm.Opcodes.LABEL END, 0));
+
+ // inject new instruction list into method instruction list
+ m.instructions.insert(toInject);
+
+ Utils.LOG_ASM("Patching Complete!");
+ break;
+ }
+ }
+
+ //ASM specific for cleaning up and returning the final bytes for JVM processing.
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ classNode.accept(writer);
+ return writer.toByteArray();
+ }
+
+}
diff --git a/src/Java/gtPlusPlus/preloader/asm/Preloader_DummyContainer.java b/src/Java/gtPlusPlus/preloader/asm/Preloader_DummyContainer.java
new file mode 100644
index 0000000000..74289f2cf3
--- /dev/null
+++ b/src/Java/gtPlusPlus/preloader/asm/Preloader_DummyContainer.java
@@ -0,0 +1,78 @@
+package gtPlusPlus.preloader.asm;
+
+import java.io.File;
+import java.util.Arrays;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+import cpw.mods.fml.common.*;
+import cpw.mods.fml.common.Mod.EventHandler;
+import cpw.mods.fml.common.event.*;
+import gtPlusPlus.core.util.Utils;
+import gtPlusPlus.preloader.CORE_Preloader;
+import net.minecraftforge.common.config.Configuration;
+
+public class Preloader_DummyContainer extends DummyModContainer {
+
+ public Preloader_DummyContainer() {
+
+ super(new ModMetadata());
+ ModMetadata meta = getMetadata();
+ meta.modId = CORE_Preloader.MODID;
+ meta.name = CORE_Preloader.NAME;
+ meta.version = CORE_Preloader.VERSION;
+ meta.credits = "Roll Credits ...";
+ meta.authorList = Arrays.asList("Alkalus");
+ meta.description = "";
+ meta.url = "";
+ meta.updateUrl = "";
+ meta.screenshots = new String[0];
+ meta.logoFile = "";
+ meta.dependencies = CORE_Preloader.DEPENDENCIES;
+
+ }
+
+ @Override
+ public boolean registerBus(EventBus bus, LoadController controller) {
+ bus.register(this);
+ return true;
+ }
+
+ @Subscribe
+ public void modConstruction(FMLConstructionEvent evt){
+
+ }
+
+ @Subscribe
+ public void init(FMLInitializationEvent evt) {
+
+ }
+
+ @EventHandler
+ public void load(final FMLInitializationEvent e) {
+ Utils.LOG_INFO("Begin resource allocation for " + CORE_Preloader.MODID + " V" + CORE_Preloader.VERSION);
+ }
+
+ @Subscribe
+ public void preInit(FMLPreInitializationEvent event) {
+ Utils.LOG_INFO("Loading " + CORE_Preloader.MODID + " V" + CORE_Preloader.VERSION);
+ // Handle GT++ Config
+ handleConfigFile(event);
+ }
+
+ @Subscribe
+ public void postInit(FMLPostInitializationEvent evt) {
+ Utils.LOG_INFO("Finished loading GT++ Pre-Loader.");
+ }
+
+ public static void handleConfigFile(final FMLPreInitializationEvent event) {
+ final Configuration config = new Configuration(
+ new File(event.getModConfigurationDirectory(), "GTplusplus/GTplusplus.cfg"));
+ config.load();
+
+ // Circuits
+ CORE_Preloader.enableOldGTcircuits = config.getBoolean("enableOldGTcircuits", "gregtech", false,
+ "Restores circuits and their recipes from Pre-5.09.28 times.");
+ }
+} \ No newline at end of file
diff --git a/src/Java/gtPlusPlus/preloader/asm/Preloader_FMLLoadingPlugin.java b/src/Java/gtPlusPlus/preloader/asm/Preloader_FMLLoadingPlugin.java
new file mode 100644
index 0000000000..9070e880e6
--- /dev/null
+++ b/src/Java/gtPlusPlus/preloader/asm/Preloader_FMLLoadingPlugin.java
@@ -0,0 +1,38 @@
+package gtPlusPlus.preloader.asm;
+
+import java.util.Map;
+
+import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
+import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
+
+@MCVersion(value = "1.7.10")
+public class Preloader_FMLLoadingPlugin implements IFMLLoadingPlugin {
+
+ @Override
+ public String getAccessTransformerClass() {
+ return null;
+ }
+
+ @Override
+ public String[] getASMTransformerClass() {
+ //This will return the name of the class
+ return new String[]{Preloader_ClassTransformer.class.getName()};
+ }
+
+ @Override
+ public String getModContainerClass() {
+ //This is the name of our dummy container
+ return Preloader_DummyContainer.class.getName();
+ }
+
+ @Override
+ public String getSetupClass() {
+ return null;
+ }
+
+ @Override
+ public void injectData(Map<String, Object> data) {
+
+ }
+
+} \ No newline at end of file