diff options
Diffstat (limited to 'gtpp/src/main/java/gtPlusPlus/preloader')
13 files changed, 1786 insertions, 0 deletions
diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/CORE_Preloader.java b/gtpp/src/main/java/gtPlusPlus/preloader/CORE_Preloader.java new file mode 100644 index 0000000000..146c92764b --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/CORE_Preloader.java @@ -0,0 +1,33 @@ +package gtPlusPlus.preloader; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import cpw.mods.fml.common.versioning.ArtifactVersion; + +public class CORE_Preloader { + + public static final String NAME = "GT++ Preloader"; + public static final String MODID = "GT++_Preloader"; + public static final String VERSION = "0.5-Beta"; + public static final List<ArtifactVersion> DEPENDENCIES; + public static final String JAVA_VERSION = System.getProperty("java.version"); + + public static File MC_DIR; + public static boolean DEV_ENVIRONMENT = false; + public static boolean DEBUG_MODE = false; + public static boolean enableOldGTcircuits = false; + public static int enableWatchdogBGM = 0; + + public static void setMinecraftDirectory(File aDir) { + MC_DIR = aDir; + } + + static { + ArrayList<ArtifactVersion> deps = new ArrayList<>(); + // deps.add("required-before:gregtech;"); + DEPENDENCIES = Collections.unmodifiableList(deps); + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/Preloader_GT_OreDict.java b/gtpp/src/main/java/gtPlusPlus/preloader/Preloader_GT_OreDict.java new file mode 100644 index 0000000000..9a350ab5e4 --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/Preloader_GT_OreDict.java @@ -0,0 +1,103 @@ +package gtPlusPlus.preloader; + +import static gregtech.api.enums.Mods.GregTech; + +import net.minecraft.item.ItemStack; + +import org.apache.logging.log4j.Level; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; +import gregtech.common.items.GT_MetaGenerated_Item_01; +import gtPlusPlus.core.lib.CORE; +import gtPlusPlus.core.util.minecraft.ItemUtils; +import gtPlusPlus.core.util.reflect.ReflectionUtils; + +public class Preloader_GT_OreDict { + + public static boolean shouldPreventRegistration(final String string, final ItemStack bannedItem) { + + if (bannedItem == null) { + return false; + } else if (!CORE_Preloader.enableOldGTcircuits) { + return false; + } + + try { + if (CORE_Preloader.enableOldGTcircuits) { + if ((bannedItem != null) && ItemUtils.getModId(bannedItem) + .toLowerCase() + .equals(GregTech.ID)) { + final int damageValue = bannedItem.getItemDamage() - 32000; + if (bannedItem.getItem() instanceof GT_MetaGenerated_Item_01) { // 700-720 + if ((damageValue >= 700) && (damageValue <= 720)) { + return true; + } + } else { + if (ReflectionUtils.doesClassExist("gregtech.common.items.GT_MetaGenerated_Item_03")) { // 6/11/12/14/16/20/30-57/69-73/79-96 + final Class<?> MetaItem03 = ReflectionUtils + .getClass("gregtech.common.items.GT_MetaGenerated_Item_03"); + if (isInstanceOf(MetaItem03, bannedItem.getItem())) { + if ((damageValue == 6) || (damageValue == 7) + || (damageValue == 11) + || (damageValue == 12) + || (damageValue == 14) + || (damageValue == 16) + || (damageValue == 20) + || (damageValue == 21) + || (damageValue == 22)) { + return true; + } else if ((damageValue >= 30) && (damageValue <= 57)) { + return true; + } else if ((damageValue >= 69) && (damageValue <= 73)) { + return true; + } else if ((damageValue >= 78) && (damageValue <= 96)) { + return true; + } + } + } + } + } + } + + } catch (final Throwable e) { + if (CORE.ConfigSwitches.showHiddenNEIItems) { + FMLRelaunchLog.log( + "[GT++ ASM] OreDictTransformer", + Level.INFO, + "A mod tried to register an invalid item with the OreDictionary."); + if (bannedItem != null) { + FMLRelaunchLog.log( + "[GT++ ASM] OreDictTransformer", + Level.INFO, + "Please report this issue to the authors of %s", + ItemUtils.getModId(bannedItem)); + try { + if (bannedItem.getItemDamage() <= Short.MAX_VALUE - 1) { + FMLRelaunchLog.log( + "[GT++ ASM] OreDictTransformer", + Level.INFO, + "Item was not null, but still invalidly registering: %s", + bannedItem.getDisplayName() != null ? bannedItem.getDisplayName() + : "INVALID ITEM FOUND"); + } else { + FMLRelaunchLog.log( + "[GT++ ASM] OreDictTransformer", + Level.INFO, + "Item was not null, but still invalidly registering: %s", + "Found Wildcard item that is being registered too early."); + } + } catch (Exception h) { + h.printStackTrace(); + } + } + } + // FMLRelaunchLog.log("[GT++ ASM] OreDictTransformer", Level.INFO, "%s", e.getMessage()); + } + return false; + } + + // Simplification of Life. + private static boolean isInstanceOf(final Class<?> clazz, final Object obj) { + return clazz.isInstance(obj); + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/Preloader_Logger.java b/gtpp/src/main/java/gtPlusPlus/preloader/Preloader_Logger.java new file mode 100644 index 0000000000..477e1371e3 --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/Preloader_Logger.java @@ -0,0 +1,50 @@ +package gtPlusPlus.preloader; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class Preloader_Logger { + + private Preloader_Logger() {} + + // Logging Functions + public static final Logger MODLOGGER = LogManager.getLogger("GT++ ASM"); + + public static Logger getLogger() { + return MODLOGGER; + } + + // Non-Dev Comments + + public static void INFO(final String s, final String s2) { + INFO(s); + INFO(s2); + } + + public static void INFO(final String s) { + MODLOGGER.info(s); + } + + // Developer Comments + public static void WARNING(final String s) { + MODLOGGER.warn(s); + } + + // Errors + public static void ERROR(final String s) { + MODLOGGER.fatal(s); + } + + public static void LOG(String string, Level info, String string2) { + if (info.equals(Level.INFO)) { + INFO("[" + string + "] " + string2); + } + if (info.equals(Level.WARN)) { + WARNING("[" + string + "] " + string2); + } + if (info.equals(Level.ERROR)) { + ERROR("[" + string + "] " + string2); + } + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/AsmConfig.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/AsmConfig.java new file mode 100644 index 0000000000..b4a49c275c --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/AsmConfig.java @@ -0,0 +1,144 @@ +package gtPlusPlus.preloader.asm; + +import java.io.File; +import java.util.ArrayList; + +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.common.config.Property; + +import org.apache.logging.log4j.Level; + +import cpw.mods.fml.common.FMLLog; +import gtPlusPlus.preloader.Preloader_Logger; + +public class AsmConfig { + + public static Configuration config; + + public static boolean enableOreDictPatch; + public static boolean enableGtTooltipFix; + public static boolean enableGtNbtFix; + public static boolean enableGtCharcoalPitFix; + public static boolean enableCofhPatch; + public static boolean enableTcAspectSafety; + public static boolean enabledLwjglKeybindingFix; + public static boolean enabledFixEntitySetHealth; + public static boolean enableThaumicTinkererRepairFix; + + public static boolean disableAllLogging; + public static boolean debugMode; + + static { + config = new Configuration(new File("config/GTplusplus/asm.cfg")); + syncConfig(true); + } + + public static void syncConfig(boolean load) { + ArrayList<String> propOrder = new ArrayList<>(); + ArrayList<String> propOrderDebug = new ArrayList<>(); + + try { + if (!config.isChild && load) { + config.load(); + } + + Property prop; + + // Debug + prop = config.get("debug", "disableAllLogging", true); + prop.comment = "Disables ALL logging from GT++."; + prop.setLanguageKey("gtpp.disableAllLogging") + .setRequiresMcRestart(false); + disableAllLogging = prop.getBoolean(true); + propOrderDebug.add(prop.getName()); + + prop = config.get("debug", "debugMode", false); + prop.comment = "Enables all sorts of debug logging. (Don't use unless told to, breaks other things.)"; + prop.setLanguageKey("gtpp.debugMode") + .setRequiresMcRestart(false); + debugMode = prop.getBoolean(false); + propOrderDebug.add(prop.getName()); + + prop = config.get("debug", "enabledFixEntitySetHealth", false); + prop.comment = "Enable/Disable entity setHealth() fix."; + prop.setLanguageKey("gtpp.enabledFixEntitySetHealth") + .setRequiresMcRestart(true); + enabledFixEntitySetHealth = prop.getBoolean(false); + propOrderDebug.add(prop.getName()); + + prop = config.get("debug", "enableGtNbtFix", true); + prop.comment = "Enable/Disable GT NBT Persistency Fix"; + prop.setLanguageKey("gtpp.enableGtNbtFix") + .setRequiresMcRestart(true); + enableGtNbtFix = prop.getBoolean(true); + propOrderDebug.add(prop.getName()); + + prop = config.get("debug", "enableCofhPatch", false); + prop.comment = "Enable/Disable COFH OreDictionaryArbiter Patch (Useful for Development)"; + prop.setLanguageKey("gtpp.enableCofhPatch") + .setRequiresMcRestart(true); + enableCofhPatch = prop.getBoolean(false); + propOrderDebug.add(prop.getName()); + + prop = config.get("debug", "enableOreDictPatch", false); + prop.comment = "Enable/Disable Forge OreDictionary Patch (Useful for Development)"; + prop.setLanguageKey("gtpp.enableOreDictPatch") + .setRequiresMcRestart(true); + enableOreDictPatch = prop.getBoolean(false); + propOrderDebug.add(prop.getName()); + + prop = config.get("debug", "enableThaumicTinkererRepairFix", false); + prop.comment = "Enable/Disable Patch for Thaumic Repairer"; + prop.setLanguageKey("gtpp.enableThaumicTinkererRepairFix") + .setRequiresMcRestart(true); + enableThaumicTinkererRepairFix = prop.getBoolean(false); + propOrderDebug.add(prop.getName()); + + // General Features + prop = config.get("general", "enabledLwjglKeybindingFix", true); + prop.comment = "Prevents the game crashing from having invalid keybinds. https://github.com/alkcorp/GTplusplus/issues/544"; + prop.setLanguageKey("gtpp.enabledLwjglKeybindingFix") + .setRequiresMcRestart(true); + enabledLwjglKeybindingFix = prop.getBoolean(true); + propOrder.add(prop.getName()); + + prop = config.get("general", "enableGtTooltipFix", true); + prop.comment = "Enable/Disable Custom GT Tooltips"; + prop.setLanguageKey("gtpp.enableGtTooltipFix") + .setRequiresMcRestart(true); + enableGtTooltipFix = prop.getBoolean(true); + propOrder.add(prop.getName()); + + prop = config.get("general", "enableGtCharcoalPitFix", true); + prop.comment = "Makes the Charcoal Pile Igniter work better."; + prop.setLanguageKey("gtpp.enableGtCharcoalPitFix") + .setRequiresMcRestart(true); + enableGtCharcoalPitFix = prop.getBoolean(true); + propOrder.add(prop.getName()); + + // TC Aspect Safety + prop = config.get("general", "enableTcAspectSafety", true); + prop.comment = "Fixes small oversights in Thaumcraft 4."; + prop.setLanguageKey("gtpp.enableTcAspectSafety") + .setRequiresMcRestart(true); + enableTcAspectSafety = prop.getBoolean(true); + propOrder.add(prop.getName()); + + config.setCategoryPropertyOrder("general", propOrder); + config.setCategoryPropertyOrder("debug", propOrderDebug); + if (config.hasChanged()) { + config.save(); + } + + Preloader_Logger.INFO("Gt Nbt Fix - Enabled: " + enableGtNbtFix); + Preloader_Logger.INFO("Gt Tooltip Fix - Enabled: " + enableGtTooltipFix); + Preloader_Logger.INFO("COFH Patch - Enabled: " + enableCofhPatch); + Preloader_Logger.INFO("Thaumcraft Aspect Safety Patch - Enabled: " + enableTcAspectSafety); + Preloader_Logger + .INFO("Fix bad usage of EntityLivingBase.setHealth Patch - Enabled: " + enabledFixEntitySetHealth); + + } catch (Exception var3) { + FMLLog.log(Level.ERROR, var3, "GT++ ASM had a problem loading it's config", new Object[0]); + } + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/Preloader_DummyContainer.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/Preloader_DummyContainer.java new file mode 100644 index 0000000000..c77f570a8d --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/Preloader_DummyContainer.java @@ -0,0 +1,70 @@ +package gtPlusPlus.preloader.asm; + +import static gregtech.api.enums.Mods.GTPlusPlus; +import static gregtech.api.enums.Mods.GregTech; + +import java.io.File; +import java.util.Collections; + +import net.minecraftforge.common.config.Configuration; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +import cpw.mods.fml.common.DummyModContainer; +import cpw.mods.fml.common.LoadController; +import cpw.mods.fml.common.ModMetadata; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import gtPlusPlus.preloader.CORE_Preloader; +import gtPlusPlus.preloader.Preloader_Logger; + +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 = Collections.singletonList("Alkalus"); + meta.screenshots = new String[0]; + meta.parent = GTPlusPlus.ID; + } + + @Override + public boolean registerBus(EventBus bus, LoadController controller) { + bus.register(this); + return true; + } + + @Subscribe + public void preInit(FMLPreInitializationEvent event) { + Preloader_Logger.INFO("Loading " + CORE_Preloader.MODID + " V" + CORE_Preloader.VERSION); + // Handle GT++ Config + handleConfigFile(event); + } + + public static void handleConfigFile(final FMLPreInitializationEvent event) { + final Configuration config = new Configuration( + new File(event.getModConfigurationDirectory(), "GTplusplus/GTplusplus.cfg")); + config.load(); + + // BGM Watchdog + CORE_Preloader.enableWatchdogBGM = config.getInt( + "enableWatchdogBGM", + "features", + 0, + 0, + Short.MAX_VALUE, + "Set to a value greater than 0 to reduce the ticks taken to delay between BGM tracks. Acceptable Values are 1-32767, where 0 is disabled. Vanilla Uses 12,000 & 24,000. 200 is 10s."); + + // Circuits + CORE_Preloader.enableOldGTcircuits = config.getBoolean( + "enableOldGTcircuits", + GregTech.ID, + false, + "Restores circuits and their recipes from Pre-5.09.28 times."); + } + +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/Preloader_FMLLoadingPlugin.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/Preloader_FMLLoadingPlugin.java new file mode 100644 index 0000000000..cdd25bb268 --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/Preloader_FMLLoadingPlugin.java @@ -0,0 +1,47 @@ +package gtPlusPlus.preloader.asm; + +import java.io.File; +import java.util.Map; + +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.SortingIndex; +import gtPlusPlus.preloader.CORE_Preloader; +import gtPlusPlus.preloader.asm.transformers.Preloader_Transformer_Handler; + +@SortingIndex(10097) +@MCVersion(value = "1.7.10") +@IFMLLoadingPlugin.TransformerExclusions("gtPlusPlus.preloader") +@IFMLLoadingPlugin.Name(CORE_Preloader.NAME) +public class Preloader_FMLLoadingPlugin implements IFMLLoadingPlugin { + + @Override + public String getAccessTransformerClass() { + return null; + } + + @Override + public String[] getASMTransformerClass() { + return new String[] { Preloader_Transformer_Handler.class.getName() }; + } + + @Override + public String getModContainerClass() { + return Preloader_DummyContainer.class.getName(); + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map<String, Object> data) { + CORE_Preloader.DEV_ENVIRONMENT = !(boolean) data.get("runtimeDeobfuscationEnabled"); + File mcDir = (File) data.get("mcLocation"); + if (mcDir != null && mcDir.exists()) { + CORE_Preloader.setMinecraftDirectory(mcDir); + } + CORE_Preloader.DEBUG_MODE = AsmConfig.debugMode; + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_COFH_OreDictionaryArbiter.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_COFH_OreDictionaryArbiter.java new file mode 100644 index 0000000000..0b41846928 --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_COFH_OreDictionaryArbiter.java @@ -0,0 +1,187 @@ +package gtPlusPlus.preloader.asm.transformers; + +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACC_STATIC; +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ASM5; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.RETURN; + +import java.util.ArrayList; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +import org.apache.logging.log4j.Level; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import com.google.common.base.Strings; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +import cofh.core.util.oredict.OreDictionaryArbiter; +import cofh.lib.util.ItemWrapper; +import cpw.mods.fml.relauncher.FMLRelaunchLog; +import gnu.trove.map.TMap; +import gnu.trove.map.hash.THashMap; +import gtPlusPlus.core.util.reflect.ReflectionUtils; + +public class ClassTransformer_COFH_OreDictionaryArbiter { + + // The qualified name of the class we plan to transform. + private static final String className = "cofh.core.util.oredict.OreDictionaryArbiter"; + // cofh/core/util/oredict/OreDictionaryArbiter + + private final boolean isValid; + private final ClassReader reader; + private final ClassWriter writer; + + public ClassTransformer_COFH_OreDictionaryArbiter(byte[] basicClass) { + ClassReader aTempReader = null; + ClassWriter aTempWriter = null; + aTempReader = new ClassReader(basicClass); + aTempWriter = new ClassWriter(aTempReader, ClassWriter.COMPUTE_FRAMES); + aTempReader.accept(new localClassVisitor(aTempWriter), 0); + + if (aTempReader != null && aTempWriter != null) { + isValid = true; + } else { + isValid = false; + } + reader = aTempReader; + writer = aTempWriter; + + if (reader != null && writer != null) { + injectMethod("registerOreDictionaryEntry"); + } + } + + public boolean isValidTransformer() { + return isValid; + } + + public ClassReader getReader() { + return reader; + } + + public ClassWriter getWriter() { + return writer; + } + + public void injectMethod(String aMethodName) { + + String aItemStack = "net/minecraft/item/ItemStack"; + MethodVisitor mv; + if (aMethodName.equals("registerOreDictionaryEntry")) { + FMLRelaunchLog.log( + "[GT++ ASM] COFH OreDictionaryArbiter Patch", + Level.INFO, + "Injecting " + aMethodName + " into " + className + ". ItemStack: " + aItemStack); + mv = getWriter().visitMethod( + ACC_PUBLIC + ACC_STATIC, + "registerOreDictionaryEntry", + "(L" + aItemStack + ";Ljava/lang/String;)V", + null, + null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(61, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/asm/transformers/ClassTransformer_COFH_OreDictionaryArbiter$FixCOFH", + "registerOreDictionaryEntry", + "(L" + aItemStack + ";Ljava/lang/String;)V", + false); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLineNumber(62, l1); + mv.visitInsn(RETURN); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitLocalVariable("arg", "L" + aItemStack + ";", null, l0, l2, 0); + mv.visitLocalVariable("arg0", "Ljava/lang/String;", null, l0, l2, 1); + mv.visitMaxs(2, 2); + mv.visitEnd(); + } + FMLRelaunchLog.log("[GT++ ASM] COFH OreDictionaryArbiter Patch", Level.INFO, "Method injection complete."); + } + + public static final class localClassVisitor extends ClassVisitor { + + public localClassVisitor(ClassVisitor cv) { + super(ASM5, cv); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if (name.equals("registerOreDictionaryEntry")) { + FMLRelaunchLog.log("[GT++ ASM] COFH OreDictionaryArbiter Patch", Level.INFO, "Removing method " + name); + return null; + } + MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + return methodVisitor; + } + } + + @SuppressWarnings("unchecked") + public static class FixCOFH { + + private static BiMap<String, Integer> oreIDs; + private static TMap<Integer, ArrayList<ItemStack>> oreStacks; + private static TMap<ItemWrapper, ArrayList<Integer>> stackIDs; + private static TMap<ItemWrapper, ArrayList<String>> stackNames; + + static { + try { + oreIDs = (BiMap<String, Integer>) ReflectionUtils.getField(OreDictionaryArbiter.class, "oreIDs") + .get(null); + oreStacks = (TMap<Integer, ArrayList<ItemStack>>) ReflectionUtils + .getField(OreDictionaryArbiter.class, "oreStacks") + .get(null); + stackIDs = (TMap<ItemWrapper, ArrayList<Integer>>) ReflectionUtils + .getField(OreDictionaryArbiter.class, "stackIDs") + .get(null); + stackNames = (TMap<ItemWrapper, ArrayList<String>>) ReflectionUtils + .getField(OreDictionaryArbiter.class, "stackNames") + .get(null); + } catch (Throwable t) { + oreIDs = HashBiMap.create(); + oreStacks = new THashMap<>(); + stackIDs = new THashMap<>(); + stackNames = new THashMap<>(); + } + } + + public static void registerOreDictionaryEntry(ItemStack arg, String arg0) { + try { + if (arg == null) { + return; + } + if (arg.getItem() != null && !Strings.isNullOrEmpty(arg0)) { + int arg1 = OreDictionary.getOreID(arg0); + oreIDs.put(arg0, Integer.valueOf(arg1)); + if (!oreStacks.containsKey(Integer.valueOf(arg1))) { + oreStacks.put(Integer.valueOf(arg1), new ArrayList<>()); + } + ((ArrayList<ItemStack>) oreStacks.get(Integer.valueOf(arg1))).add(arg); + ItemWrapper arg2 = ItemWrapper.fromItemStack(arg); + if (!stackIDs.containsKey(arg2)) { + stackIDs.put(arg2, new ArrayList<>()); + stackNames.put(arg2, new ArrayList<>()); + } + ((ArrayList<Integer>) stackIDs.get(arg2)).add(Integer.valueOf(arg1)); + ((ArrayList<String>) stackNames.get(arg2)).add(arg0); + } + } catch (Throwable t) { + return; + } + } + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_IC2_GetHarvestTool.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_IC2_GetHarvestTool.java new file mode 100644 index 0000000000..7aa5ff4f90 --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_IC2_GetHarvestTool.java @@ -0,0 +1,233 @@ +package gtPlusPlus.preloader.asm.transformers; + +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ARETURN; +import static org.objectweb.asm.Opcodes.ASM5; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.IRETURN; + +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; + +import org.apache.logging.log4j.Level; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; + +public class ClassTransformer_IC2_GetHarvestTool { + + private final boolean isValid; + private final ClassReader reader; + private final ClassWriter writer; + private final String className; + + private final String aName_getItemDropped; + private final String aName_damageDropped; + + public static String getHarvestTool(int aMeta) { + return "wrench"; + } + + public static Item getItemDropped(Block aBlock, int meta, Random random, int fortune) { + return Item.getItemFromBlock(aBlock); + } + + public static int damageDropped(int aMeta) { + return aMeta; + } + + public ClassTransformer_IC2_GetHarvestTool(byte[] basicClass, boolean obfuscated, String aClassName) { + className = aClassName; + ClassReader aTempReader = null; + ClassWriter aTempWriter = null; + + aName_getItemDropped = obfuscated ? "func_149650_a" : "getItemDropped"; + aName_damageDropped = obfuscated ? "func_149692_a" : "damageDropped"; + + FMLRelaunchLog.log( + "[GT++ ASM] IC2 getHarvestTool Patch", + Level.INFO, + "Attempting to patch in mode " + className + ". Obfuscated? " + obfuscated); + + aTempReader = new ClassReader(basicClass); + aTempWriter = new ClassWriter(aTempReader, ClassWriter.COMPUTE_FRAMES); + aTempReader.accept(new localClassVisitor(aTempWriter, className), 0); + + if (aTempReader != null && aTempWriter != null) { + isValid = true; + } else { + isValid = false; + } + + FMLRelaunchLog.log("[GT++ ASM] IC2 getHarvestTool Patch", Level.INFO, "Valid patch? " + isValid + "."); + reader = aTempReader; + writer = aTempWriter; + + if (reader != null && writer != null) { + FMLRelaunchLog.log("[GT++ ASM] IC2 getHarvestTool Patch", Level.INFO, "Attempting Method Injection."); + injectMethod("getHarvestTool"); + if (aClassName.equals("ic2.core.block.machine.BlockMachine2") + || aClassName.equals("ic2.core.block.machine.BlockMachine3") + || aClassName.equals("ic2.core.block.wiring.BlockElectric")) { + injectMethod(aName_getItemDropped); + injectMethod(aName_damageDropped); + } else if (aClassName.equals("ic2.core.block.generator.block.BlockGenerator") + || aClassName.equals("ic2.core.block.machine.BlockMachine")) { + injectMethod(aName_damageDropped); + } + } + } + + public boolean isValidTransformer() { + return isValid; + } + + public ClassReader getReader() { + return reader; + } + + public ClassWriter getWriter() { + return writer; + } + + public boolean injectMethod(String aMethodName) { + MethodVisitor mv; + boolean didInject = false; + String aFormattedClassName = className.replace('.', '/'); + ClassWriter cw = getWriter(); + + FMLRelaunchLog.log("[GT++ ASM] IC2 getHarvestTool Patch", Level.INFO, "Injecting " + aMethodName + "."); + if (aMethodName.equals("getHarvestTool")) { + mv = getWriter().visitMethod(ACC_PUBLIC, "getHarvestTool", "(I)Ljava/lang/String;", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(63, l0); + mv.visitVarInsn(ILOAD, 1); + mv.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/asm/transformers/ClassTransformer_IC2_GetHarvestTool", + "getHarvestTool", + "(I)Ljava/lang/String;", + false); + mv.visitInsn(ARETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", "L" + aFormattedClassName + ";", null, l0, l1, 0); + mv.visitLocalVariable("aMeta", "I", null, l0, l1, 1); + mv.visitMaxs(1, 2); + mv.visitEnd(); + didInject = true; + } else if (aMethodName.equals(aName_getItemDropped)) { + mv = cw.visitMethod( + ACC_PUBLIC, + aName_getItemDropped, + "(ILjava/util/Random;I)Lnet/minecraft/item/Item;", + null, + null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(44, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ILOAD, 1); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ILOAD, 3); + mv.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/asm/transformers/ClassTransformer_IC2_GetHarvestTool", + "getItemDropped", + "(Lnet/minecraft/block/Block;ILjava/util/Random;I)Lnet/minecraft/item/Item;", + false); + mv.visitInsn(ARETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", "L" + aFormattedClassName + ";", null, l0, l1, 0); + mv.visitLocalVariable("meta", "I", null, l0, l1, 1); + mv.visitLocalVariable("random", "Ljava/util/Random;", null, l0, l1, 2); + mv.visitLocalVariable("fortune", "I", null, l0, l1, 3); + mv.visitMaxs(4, 4); + mv.visitEnd(); + didInject = true; + } else if (aMethodName.equals(aName_damageDropped)) { + mv = cw.visitMethod(ACC_PUBLIC, aName_damageDropped, "(I)I", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(48, l0); + mv.visitVarInsn(ILOAD, 1); + mv.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/asm/transformers/ClassTransformer_IC2_GetHarvestTool", + "damageDropped", + "(I)I", + false); + mv.visitInsn(IRETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", "L" + aFormattedClassName + ";", null, l0, l1, 0); + mv.visitLocalVariable("meta", "I", null, l0, l1, 1); + mv.visitMaxs(1, 2); + mv.visitEnd(); + didInject = true; + } + FMLRelaunchLog.log("[GT++ ASM] IC2 getHarvestTool Patch", Level.INFO, "Method injection complete."); + return didInject; + } + + public final class localClassVisitor extends ClassVisitor { + + String aClassName; + + public localClassVisitor(ClassVisitor cv, String aName) { + super(ASM5, cv); + aClassName = aName; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor methodVisitor; + if (aClassName.equals("ic2.core.block.machine.BlockMachine2") + || aClassName.equals("ic2.core.block.machine.BlockMachine3") + || aClassName.equals("ic2.core.block.wiring.BlockElectric")) { + if (name.equals(aName_getItemDropped)) { + methodVisitor = null; + } else if (name.equals(aName_damageDropped)) { + methodVisitor = null; + } else if (name.equals("getHarvestTool")) { + methodVisitor = null; + } else { + methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + } + } else if (aClassName.equals("ic2.core.block.generator.block.BlockGenerator") + || aClassName.equals("ic2.core.block.machine.BlockMachine")) { + if (name.equals(aName_damageDropped)) { + methodVisitor = null; + } else if (name.equals("getHarvestTool")) { + methodVisitor = null; + } else { + methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + } + } else { + if (name.equals("getHarvestTool")) { + methodVisitor = null; + } else { + methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + } + } + if (methodVisitor == null) { + FMLRelaunchLog + .log("[GT++ ASM] IC2 getHarvestTool Patch", Level.INFO, "Found method " + name + ", removing."); + } + return methodVisitor; + } + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_LWJGL_Keyboard.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_LWJGL_Keyboard.java new file mode 100644 index 0000000000..4d3c78e6bd --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_LWJGL_Keyboard.java @@ -0,0 +1,297 @@ +package gtPlusPlus.preloader.asm.transformers; + +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACC_STATIC; +import static org.objectweb.asm.Opcodes.ACC_SYNCHRONIZED; +import static org.objectweb.asm.Opcodes.ARETURN; +import static org.objectweb.asm.Opcodes.ASM5; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; + +import java.lang.reflect.Field; +import java.util.HashMap; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; + +import org.apache.logging.log4j.Level; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; +import gtPlusPlus.core.util.Utils; +import gtPlusPlus.core.util.reflect.ReflectionUtils; + +public class ClassTransformer_LWJGL_Keyboard { + + private final boolean isValid; + private final ClassReader reader; + private final ClassWriter writer; + + private static final HashMap<String, String> mBadKeyCache = new HashMap<>(); + + /** + * Gets a key's name + * + * @param key The key + * @return a String with the key's human readable name in it or null if the key is unnamed + */ + public static synchronized String getKeyName(int key) { + if (init()) { + String[] aTemp = getKeyName(); + if (key < aTemp.length && key >= 0) { + return aTemp[key]; + } + } + String aCachedValue = mBadKeyCache.get("key-" + key); + if (aCachedValue == null) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Unable to map key code " + key + " to LWJGL keymap."); + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Caching key value to be empty."); + // mBadKeyCache.put("key-"+key, getKeyName()[0x00]); + aCachedValue = "FIX!"; + mBadKeyCache.put("key-" + key, aCachedValue); + trySetClientKey(key); + } + return aCachedValue; // Return nothing + } + + public static void trySetClientKey(int aKey) { + if (Utils.isClient() && ReflectionUtils.doesClassExist("net.minecraft.client.Minecraft")) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Trying to set key value to be empty."); + GameSettings options = Minecraft.getMinecraft().gameSettings; + KeyBinding[] akeybinding = Minecraft.getMinecraft().gameSettings.keyBindings; + int i = akeybinding.length; + for (KeyBinding keybinding : akeybinding) { + if (keybinding != null && keybinding.getKeyCode() == aKey) { + options.setOptionKeyBinding(keybinding, 0); + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Set keybind " + aKey + " to 0."); + break; + } + } + } + } + + @SuppressWarnings("rawtypes") + private static Class mKeyboard; + + private static Field mKeyName; + + @SuppressWarnings("rawtypes") + private static boolean init() { + if (mKeyName != null) { + return true; + } + Class aKeyboard = ReflectionUtils.getClass("org.lwjgl.input.Keyboard"); + if (aKeyboard != null) { + mKeyboard = aKeyboard; + Field aKeyName = ReflectionUtils.getField(mKeyboard, "keyName"); + if (aKeyName != null) { + mKeyName = aKeyName; + } + } + return mKeyName != null; + } + + private static String[] getKeyName() { + if (init()) { + try { + Object o = mKeyName.get(null); + if (o instanceof String[]y) { + return y; + } + } catch (IllegalArgumentException | IllegalAccessException e) {} + } + return new String[] {}; + } + + public ClassTransformer_LWJGL_Keyboard(byte[] basicClass, boolean isClientSettings) { + ClassReader aTempReader = null; + ClassWriter aTempWriter = null; + aTempReader = new ClassReader(basicClass); + aTempWriter = new ClassWriter(aTempReader, ClassWriter.COMPUTE_FRAMES); + if (!isClientSettings) { + // gtPlusPlus.preloader.keyboard.BetterKeyboard.init(); + aTempReader.accept(new PatchLWJGL(aTempWriter), 0); + injectLWJGLPatch(aTempWriter); + } else { + // gtPlusPlus.preloader.keyboard.BetterKeyboard.init(); + aTempReader.accept(new PatchClientSettings(aTempWriter), 0); + injectClientSettingPatch(aTempWriter); + } + if (aTempReader != null && aTempWriter != null) { + isValid = true; + } else { + isValid = false; + } + FMLRelaunchLog + .log("[GT++ ASM] LWJGL Keybinding index out of bounds fix", Level.INFO, "Valid? " + isValid + "."); + reader = aTempReader; + writer = aTempWriter; + } + + public boolean isValidTransformer() { + return isValid; + } + + public ClassReader getReader() { + return reader; + } + + public ClassWriter getWriter() { + return writer; + } + + private boolean isClientSettingsObfuscated = false; + + public boolean injectLWJGLPatch(ClassWriter cw) { + MethodVisitor mv; + boolean didInject = false; + FMLRelaunchLog + .log("[GT++ ASM] LWJGL Keybinding index out of bounds fix", Level.INFO, "Injecting " + "getKeyName" + "."); + mv = cw + .visitMethod(ACC_PUBLIC + ACC_STATIC + ACC_SYNCHRONIZED, "getKeyName", "(I)Ljava/lang/String;", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(49, l0); + mv.visitVarInsn(ILOAD, 0); + mv.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/asm/transformers/ClassTransformer_LWJGL_Keyboard", + "getKeyName", + "(I)Ljava/lang/String;", + false); + mv.visitInsn(ARETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("key", "I", null, l0, l1, 0); + mv.visitMaxs(1, 1); + mv.visitEnd(); + didInject = true; + + FMLRelaunchLog + .log("[GT++ ASM] LWJGL Keybinding index out of bounds fix", Level.INFO, "Method injection complete."); + return didInject; + } + + public boolean injectClientSettingPatch(ClassWriter cw) { + MethodVisitor mv; + boolean didInject = false; + String aMethodName = this.isClientSettingsObfuscated ? "func_74298_c" : "getKeyDisplayString"; + FMLRelaunchLog + .log("[GT++ ASM] LWJGL Keybinding index out of bounds fix", Level.INFO, "Injecting " + aMethodName + "."); + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, aMethodName, "(I)Ljava/lang/String;", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(130, l0); + mv.visitVarInsn(ILOAD, 0); + mv.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/keyboard/BetterKeyboard", + "getKeyDisplayString", + "(I)Ljava/lang/String;", + false); + mv.visitInsn(ARETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("p_74298_0_", "I", null, l0, l1, 0); + mv.visitMaxs(1, 1); + mv.visitEnd(); + didInject = true; + FMLRelaunchLog + .log("[GT++ ASM] LWJGL Keybinding index out of bounds fix", Level.INFO, "Method injection complete."); + return didInject; + } + + public class PatchClientSettings extends ClassVisitor { + + public PatchClientSettings(ClassVisitor cv) { + super(ASM5, cv); + this.cv = cv; + } + + private final String[] aMethodsToStrip = new String[] { "func_74298_c", "getKeyDisplayString" }; + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor methodVisitor; + boolean found = false; + + for (String s : aMethodsToStrip) { + if (name.equals(s)) { + if (name.equals(aMethodsToStrip[0])) { + isClientSettingsObfuscated = true; + } else { + isClientSettingsObfuscated = false; + } + found = true; + break; + } + } + if (!found) { + methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + } else { + methodVisitor = null; + } + if (found) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Found method " + name + ", removing."); + } + return methodVisitor; + } + } + + public class PatchLWJGL extends ClassVisitor { + + public PatchLWJGL(ClassVisitor cv) { + super(ASM5, cv); + this.cv = cv; + } + + private final String[] aMethodsToStrip = new String[] { "getKeyName" }; + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor methodVisitor; + boolean found = false; + + for (String s : aMethodsToStrip) { + if (name.equals(s)) { + found = true; + break; + } + } + if (!found) { + methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + } else { + methodVisitor = null; + } + if (found) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Found method " + name + ", removing."); + } + return methodVisitor; + } + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_TC_ItemWispEssence.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_TC_ItemWispEssence.java new file mode 100644 index 0000000000..cf8b08d40c --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_TC_ItemWispEssence.java @@ -0,0 +1,317 @@ +package gtPlusPlus.preloader.asm.transformers; + +import static org.objectweb.asm.Opcodes.AALOAD; +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACONST_NULL; +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ARETURN; +import static org.objectweb.asm.Opcodes.ARRAYLENGTH; +import static org.objectweb.asm.Opcodes.ASM5; +import static org.objectweb.asm.Opcodes.ASTORE; +import static org.objectweb.asm.Opcodes.DUP; +import static org.objectweb.asm.Opcodes.F_APPEND; +import static org.objectweb.asm.Opcodes.F_CHOP; +import static org.objectweb.asm.Opcodes.F_SAME; +import static org.objectweb.asm.Opcodes.F_SAME1; +import static org.objectweb.asm.Opcodes.GETSTATIC; +import static org.objectweb.asm.Opcodes.GOTO; +import static org.objectweb.asm.Opcodes.I2L; +import static org.objectweb.asm.Opcodes.ICONST_0; +import static org.objectweb.asm.Opcodes.IFEQ; +import static org.objectweb.asm.Opcodes.IFLE; +import static org.objectweb.asm.Opcodes.IFNONNULL; +import static org.objectweb.asm.Opcodes.IFNULL; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; +import static org.objectweb.asm.Opcodes.IRETURN; +import static org.objectweb.asm.Opcodes.ISTORE; +import static org.objectweb.asm.Opcodes.L2I; +import static org.objectweb.asm.Opcodes.LDIV; +import static org.objectweb.asm.Opcodes.LREM; +import static org.objectweb.asm.Opcodes.NEW; + +import org.apache.logging.log4j.Level; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; + +public class ClassTransformer_TC_ItemWispEssence { + + private final boolean isValid; + private final ClassReader reader; + private final ClassWriter writer; + + public ClassTransformer_TC_ItemWispEssence(byte[] basicClass, boolean obfuscated2) { + ClassReader aTempReader = null; + ClassWriter aTempWriter = null; + FMLRelaunchLog.log( + "[GT++ ASM] Thaumcraft WispEssence_Patch", + Level.INFO, + "Are we patching obfuscated methods? " + obfuscated2); + String aGetColour = obfuscated2 ? "func_82790_a" : "getColorFromItemStack"; + aTempReader = new ClassReader(basicClass); + aTempWriter = new ClassWriter(aTempReader, ClassWriter.COMPUTE_FRAMES); + aTempReader.accept(new AddAdapter(aTempWriter, new String[] { "getAspects", aGetColour }), 0); + injectMethod("getAspects", aTempWriter, obfuscated2); + injectMethod(aGetColour, aTempWriter, obfuscated2); + if (aTempReader != null && aTempWriter != null) { + isValid = true; + } else { + isValid = false; + } + FMLRelaunchLog.log("[GT++ ASM] Thaumcraft WispEssence_Patch", Level.INFO, "Valid? " + isValid + "."); + reader = aTempReader; + writer = aTempWriter; + } + + public boolean isValidTransformer() { + return isValid; + } + + public ClassReader getReader() { + return reader; + } + + public ClassWriter getWriter() { + return writer; + } + + public boolean injectMethod(String aMethodName, ClassWriter cw, boolean obfuscated) { + MethodVisitor mv; + boolean didInject = false; + FMLRelaunchLog.log("[GT++ ASM] Thaumcraft WispEssence_Patch", Level.INFO, "Injecting " + aMethodName + "."); + + String aGetColour = obfuscated ? "func_82790_a" : "getColorFromItemStack"; + String aHasTagCompound = obfuscated ? "func_77942_o" : "hasTagCompound"; + String aGetTagCompound = obfuscated ? "func_77978_p" : "getTagCompound"; + + if (aMethodName.equals("getAspects")) { + mv = cw.visitMethod( + ACC_PUBLIC, + "getAspects", + "(Lnet/minecraft/item/ItemStack;)Lthaumcraft/api/aspects/AspectList;", + null, + null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(141, l0); + mv.visitVarInsn(ALOAD, 1); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitLineNumber(142, l2); + mv.visitInsn(ACONST_NULL); + mv.visitInsn(ARETURN); + mv.visitLabel(l1); + mv.visitLineNumber(144, l1); + mv.visitFrame(F_SAME, 0, null, 0, null); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, "net/minecraft/item/ItemStack", aHasTagCompound, "()Z", false); + Label l3 = new Label(); + mv.visitJumpInsn(IFEQ, l3); + Label l4 = new Label(); + mv.visitLabel(l4); + mv.visitLineNumber(145, l4); + mv.visitTypeInsn(NEW, "thaumcraft/api/aspects/AspectList"); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, "thaumcraft/api/aspects/AspectList", "<init>", "()V", false); + mv.visitVarInsn(ASTORE, 2); + Label l5 = new Label(); + mv.visitLabel(l5); + mv.visitLineNumber(146, l5); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn( + INVOKEVIRTUAL, + "net/minecraft/item/ItemStack", + aGetTagCompound, + "()Lnet/minecraft/nbt/NBTTagCompound;", + false); + mv.visitMethodInsn( + INVOKEVIRTUAL, + "thaumcraft/api/aspects/AspectList", + "readFromNBT", + "(Lnet/minecraft/nbt/NBTTagCompound;)V", + false); + Label l6 = new Label(); + mv.visitLabel(l6); + mv.visitLineNumber(147, l6); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(INVOKEVIRTUAL, "thaumcraft/api/aspects/AspectList", "size", "()I", false); + Label l7 = new Label(); + mv.visitJumpInsn(IFLE, l7); + mv.visitVarInsn(ALOAD, 2); + Label l8 = new Label(); + mv.visitJumpInsn(GOTO, l8); + mv.visitLabel(l7); + mv.visitFrame(F_APPEND, 1, new Object[] { "thaumcraft/api/aspects/AspectList" }, 0, null); + mv.visitInsn(ACONST_NULL); + mv.visitLabel(l8); + mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { "thaumcraft/api/aspects/AspectList" }); + mv.visitInsn(ARETURN); + mv.visitLabel(l3); + mv.visitLineNumber(149, l3); + mv.visitFrame(F_CHOP, 1, null, 0, null); + mv.visitInsn(ACONST_NULL); + mv.visitInsn(ARETURN); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitLocalVariable( + "this", + "LgtPlusPlus/preloader/asm/transformers/ClassTransformer_TC_ItemWispEssence;", + null, + l0, + l9, + 0); + mv.visitLocalVariable("itemstack", "Lnet/minecraft/item/ItemStack;", null, l0, l9, 1); + mv.visitLocalVariable("aspects", "Lthaumcraft/api/aspects/AspectList;", null, l5, l3, 2); + mv.visitMaxs(2, 3); + mv.visitEnd(); + didInject = true; + } else if (aMethodName.equals(aGetColour)) { + + // thaumcraft/common/items/ItemWispEssence + mv = cw.visitMethod(ACC_PUBLIC, aGetColour, "(Lnet/minecraft/item/ItemStack;I)I", null, null); + AnnotationVisitor av0; + { + av0 = mv.visitAnnotation("Lcpw/mods/fml/relauncher/SideOnly;", true); + av0.visitEnum("value", "Lcpw/mods/fml/relauncher/Side;", "CLIENT"); + av0.visitEnd(); + } + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(197, l0); + mv.visitVarInsn(ALOAD, 1); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitLineNumber(198, l2); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + mv.visitLabel(l1); + mv.visitLineNumber(200, l1); + mv.visitFrame(F_SAME, 0, null, 0, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn( + INVOKEVIRTUAL, + "thaumcraft/common/items/ItemWispEssence", + "getAspects", + "(Lnet/minecraft/item/ItemStack;)Lthaumcraft/api/aspects/AspectList;", + false); + Label l3 = new Label(); + mv.visitJumpInsn(IFNULL, l3); + Label l4 = new Label(); + mv.visitLabel(l4); + mv.visitLineNumber(201, l4); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn( + INVOKEVIRTUAL, + "thaumcraft/common/items/ItemWispEssence", + "getAspects", + "(Lnet/minecraft/item/ItemStack;)Lthaumcraft/api/aspects/AspectList;", + false); + mv.visitMethodInsn( + INVOKEVIRTUAL, + "thaumcraft/api/aspects/AspectList", + "getAspects", + "()[Lthaumcraft/api/aspects/Aspect;", + false); + mv.visitInsn(ICONST_0); + mv.visitInsn(AALOAD); + mv.visitMethodInsn(INVOKEVIRTUAL, "thaumcraft/api/aspects/Aspect", "getColor", "()I", false); + mv.visitInsn(IRETURN); + mv.visitLabel(l3); + mv.visitLineNumber(203, l3); + mv.visitFrame(F_SAME, 0, null, 0, null); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false); + mv.visitLdcInsn(new Long(500L)); + mv.visitInsn(LDIV); + mv.visitFieldInsn( + GETSTATIC, + "thaumcraft/common/items/ItemWispEssence", + "displayAspects", + "[Lthaumcraft/api/aspects/Aspect;"); + mv.visitInsn(ARRAYLENGTH); + mv.visitInsn(I2L); + mv.visitInsn(LREM); + mv.visitInsn(L2I); + mv.visitVarInsn(ISTORE, 3); + Label l5 = new Label(); + mv.visitLabel(l5); + mv.visitLineNumber(204, l5); + mv.visitFieldInsn( + GETSTATIC, + "thaumcraft/common/items/ItemWispEssence", + "displayAspects", + "[Lthaumcraft/api/aspects/Aspect;"); + mv.visitVarInsn(ILOAD, 3); + mv.visitInsn(AALOAD); + mv.visitMethodInsn(INVOKEVIRTUAL, "thaumcraft/api/aspects/Aspect", "getColor", "()I", false); + mv.visitInsn(IRETURN); + Label l6 = new Label(); + mv.visitLabel(l6); + mv.visitLocalVariable("this", "Lthaumcraft/common/items/ItemWispEssence;", null, l0, l6, 0); + mv.visitLocalVariable("stack", "Lnet/minecraft/item/ItemStack;", null, l0, l6, 1); + mv.visitLocalVariable("par2", "I", null, l0, l6, 2); + mv.visitLocalVariable("idx", "I", null, l5, l6, 3); + mv.visitMaxs(4, 4); + mv.visitEnd(); + didInject = true; + } + + FMLRelaunchLog.log( + "[GT++ ASM] Thaumcraft WispEssence_Patch", + Level.INFO, + "Method injection complete. " + (obfuscated ? "Obfuscated" : "Non-Obfuscated")); + return didInject; + } + + public class AddAdapter extends ClassVisitor { + + public AddAdapter(ClassVisitor cv, String[] aMethods) { + super(ASM5, cv); + this.cv = cv; + this.aMethodsToStrip = aMethods; + } + + private final String[] aMethodsToStrip; + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + + MethodVisitor methodVisitor; + boolean found = false; + + for (String s : aMethodsToStrip) { + if (name.equals(s)) { + found = true; + break; + } + } + if (!found) { + methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + } else { + methodVisitor = null; + } + + if (found) { + FMLRelaunchLog + .log("[GT++ ASM] Thaumcraft WispEssence_Patch", Level.INFO, "Found method " + name + ", removing."); + } + return methodVisitor; + } + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/Preloader_ClassTransformer.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/Preloader_ClassTransformer.java new file mode 100644 index 0000000000..82526b1290 --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/Preloader_ClassTransformer.java @@ -0,0 +1,79 @@ +package gtPlusPlus.preloader.asm.transformers; + +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ASM5; +import static org.objectweb.asm.Opcodes.IFEQ; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.RETURN; + +import org.apache.logging.log4j.Level; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; + +public class Preloader_ClassTransformer { + + public static final class OreDictionaryVisitor extends ClassVisitor { + + public OreDictionaryVisitor(ClassVisitor cv) { + super(ASM5, cv); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + if (name.equals("registerOreImpl") && desc.equals("(Ljava/lang/String;Lnet/minecraft/item/ItemStack;)V")) { + FMLRelaunchLog.log("[GT++ ASM] OreDictTransformer", Level.INFO, "Found target method. [Unobfuscated]"); + return new RegisterOreImplVisitor(methodVisitor, false); + } else if (name.equals("registerOreImpl") && desc.equals("(Ljava/lang/String;Ladd;)V")) { + FMLRelaunchLog.log("[GT++ ASM] OreDictTransformer", Level.INFO, "Found target method. [Obfuscated]"); + return new RegisterOreImplVisitor(methodVisitor, true); + } + return methodVisitor; + } + } + + private static final class RegisterOreImplVisitor extends MethodVisitor { + + private final boolean mObfuscated; + + public RegisterOreImplVisitor(MethodVisitor mv, boolean obfuscated) { + super(ASM5, mv); + this.mObfuscated = obfuscated; + } + + @Override + public void visitCode() { + FMLRelaunchLog + .log("[GT++ ASM] OreDictTransformer", Level.INFO, "Fixing Forge's poor attempt at an oreDictionary."); + super.visitCode(); + super.visitVarInsn(ALOAD, 0); + super.visitVarInsn(ALOAD, 1); + if (!mObfuscated) { + FMLRelaunchLog + .log("[GT++ ASM] OreDictTransformer", Level.INFO, "Injecting target method. [Unobfuscated]"); + super.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/Preloader_GT_OreDict", + "shouldPreventRegistration", + "(Ljava/lang/String;Lnet/minecraft/item/ItemStack;)Z", + false); + } else { + FMLRelaunchLog + .log("[GT++ ASM] OreDictTransformer", Level.INFO, "Injecting target method. [Obfuscated]"); + super.visitMethodInsn( + INVOKESTATIC, + "gtPlusPlus/preloader/Preloader_GT_OreDict", + "shouldPreventRegistration", + "(Ljava/lang/String;Ladd;)Z", + false); + } + Label endLabel = new Label(); + super.visitJumpInsn(IFEQ, endLabel); + super.visitInsn(RETURN); + super.visitLabel(endLabel); + } + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/Preloader_Transformer_Handler.java b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/Preloader_Transformer_Handler.java new file mode 100644 index 0000000000..922ce88e27 --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/asm/transformers/Preloader_Transformer_Handler.java @@ -0,0 +1,92 @@ +package gtPlusPlus.preloader.asm.transformers; + +import java.util.HashSet; +import java.util.Set; + +import net.minecraft.launchwrapper.IClassTransformer; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + +import gtPlusPlus.core.util.reflect.ReflectionUtils; +import gtPlusPlus.preloader.CORE_Preloader; +import gtPlusPlus.preloader.Preloader_Logger; +import gtPlusPlus.preloader.asm.AsmConfig; +import gtPlusPlus.preloader.asm.transformers.Preloader_ClassTransformer.OreDictionaryVisitor; + +public class Preloader_Transformer_Handler implements IClassTransformer { + + private static final Set<String> IC2_WRENCH_PATCH_CLASS_NAMES = new HashSet<>(); + private static final String LWJGL_KEYBOARD = "org.lwjgl.input.Keyboard"; + private static final String MINECRAFT_GAMESETTINGS = "net.minecraft.client.settings.GameSettings"; + private static final String FORGE_CHUNK_MANAGER = "net.minecraftforge.common.ForgeChunkManager"; + private static final String FORGE_ORE_DICTIONARY = "net.minecraftforge.oredict.OreDictionary"; + private static final String COFH_ORE_DICTIONARY_ARBITER = "cofh.core.util.oredict.OreDictionaryArbiter"; + private static final String THAUMCRAFT_ITEM_WISP_ESSENCE = "thaumcraft.common.items.ItemWispEssence"; + + static { + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.BlockTileEntity"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.machine.BlockMachine"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.machine.BlockMachine2"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.machine.BlockMachine3"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.kineticgenerator.block.BlockKineticGenerator"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.heatgenerator.block.BlockHeatGenerator"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.generator.block.BlockGenerator"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.reactor.block.BlockReactorAccessHatch"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.reactor.block.BlockReactorChamber"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.reactor.block.BlockReactorFluidPort"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.reactor.block.BlockReactorRedstonePort"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.reactor.block.BlockReactorVessel"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.personal.BlockPersonal.class"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.wiring.BlockChargepad.class"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.wiring.BlockElectric.class"); + IC2_WRENCH_PATCH_CLASS_NAMES.add("ic2.core.block.wiring.BlockLuminator.class"); + } + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + // Fix LWJGL index array out of bounds on keybinding IDs + if ((transformedName.equals(LWJGL_KEYBOARD) || transformedName.equals(MINECRAFT_GAMESETTINGS)) + && AsmConfig.enabledLwjglKeybindingFix + // Do not transform if using lwjgl3 + && !ReflectionUtils.doesClassExist("org.lwjgl.system.Platform")) { + boolean isClientSettingsClass = !transformedName.equals("org.lwjgl.input.Keyboard"); + Preloader_Logger.INFO("LWJGL Keybinding index out of bounds fix", "Transforming " + transformedName); + return new ClassTransformer_LWJGL_Keyboard(basicClass, isClientSettingsClass).getWriter() + .toByteArray(); + } + + // Fix the OreDictionary - Forge + if (transformedName.equals(FORGE_ORE_DICTIONARY) && AsmConfig.enableOreDictPatch) { + Preloader_Logger.INFO("OreDictTransformer", "Transforming " + transformedName); + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + new ClassReader(basicClass).accept(new OreDictionaryVisitor(classWriter), 0); + return classWriter.toByteArray(); + } + + // Fix the OreDictionary COFH + if (transformedName.equals(COFH_ORE_DICTIONARY_ARBITER) + && (AsmConfig.enableCofhPatch || CORE_Preloader.DEV_ENVIRONMENT)) { + Preloader_Logger.INFO("COFH", "Transforming " + transformedName); + return new ClassTransformer_COFH_OreDictionaryArbiter(basicClass).getWriter() + .toByteArray(); + } + + if (IC2_WRENCH_PATCH_CLASS_NAMES.contains(transformedName)) { + Preloader_Logger.INFO("IC2 getHarvestTool Patch", "Transforming " + transformedName); + return new ClassTransformer_IC2_GetHarvestTool(basicClass, !CORE_Preloader.DEV_ENVIRONMENT, transformedName) + .getWriter() + .toByteArray(); + } + + // Fix Thaumcraft stuff + // Patching ItemWispEssence to allow invalid item handling + if (transformedName.equals(THAUMCRAFT_ITEM_WISP_ESSENCE) && AsmConfig.enableTcAspectSafety) { + Preloader_Logger.INFO("Thaumcraft WispEssence_Patch", "Transforming " + transformedName); + return new ClassTransformer_TC_ItemWispEssence(basicClass, !CORE_Preloader.DEV_ENVIRONMENT).getWriter() + .toByteArray(); + } + + return basicClass; + } +} diff --git a/gtpp/src/main/java/gtPlusPlus/preloader/keyboard/BetterKeyboard.java b/gtpp/src/main/java/gtPlusPlus/preloader/keyboard/BetterKeyboard.java new file mode 100644 index 0000000000..510689911c --- /dev/null +++ b/gtpp/src/main/java/gtPlusPlus/preloader/keyboard/BetterKeyboard.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2002-2008 LWJGL Project All rights reserved. Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following conditions are met: * Redistributions of source code + * must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in + * binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package gtPlusPlus.preloader.keyboard; + +import java.lang.reflect.Field; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import net.minecraft.client.resources.I18n; + +import org.apache.logging.log4j.Level; +import org.lwjgl.BufferUtils; +import org.lwjgl.input.Keyboard; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; +import gtPlusPlus.core.util.reflect.ReflectionUtils; +import gtPlusPlus.preloader.asm.transformers.ClassTransformer_LWJGL_Keyboard; + +/** + * <br> + * A raw Keyboard interface. This can be used to poll the current state of the keys, or read all the keyboard presses / + * releases since the last read. + * + * DO NOT REMOVE. CALLED BY ASM CODE. + * + * @author cix_foo <cix_foo@users.sourceforge.net> + * @author elias_naur <elias_naur@users.sourceforge.net> + * @author Brian Matzon <brian@matzon.dk> + * @version $Revision$ $Id$ + */ +@SuppressWarnings("unused") +public class BetterKeyboard { + + public static final int KEYBOARD_SIZE = Short.MAX_VALUE; + + private static boolean init = false; + + public static void init() { + if (!init) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Trying to patch out LWJGL internal arrays with larger ones."); + Field aKeyNameSize = ReflectionUtils.getField(Keyboard.class, "keyName"); + Field aKeyMapSize = ReflectionUtils.getField(Keyboard.class, "keyMap"); + Field aKeyDownBuffer = ReflectionUtils.getField(Keyboard.class, "keyDownBuffer"); + String[] aOldKeyNameArray = ReflectionUtils.getFieldValue(aKeyNameSize); + if (aOldKeyNameArray != null && aOldKeyNameArray.length < Short.MAX_VALUE) { + String[] aNewKeyNameArray = new String[Short.MAX_VALUE]; + for (int i = 0; i < aOldKeyNameArray.length; i++) { + aNewKeyNameArray[i] = aOldKeyNameArray[i]; + } + try { + ReflectionUtils.setFinalFieldValue(Keyboard.class, aKeyNameSize.getName(), aNewKeyNameArray); + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Patched Field: " + aKeyNameSize.getName()); + } catch (Throwable t) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Failed Patching Field: " + aKeyDownBuffer.getName()); + } + } + Map<String, Integer> aOldKeyMapArray = ReflectionUtils.getFieldValue(aKeyMapSize); + if (aOldKeyNameArray != null && aOldKeyMapArray.size() < Short.MAX_VALUE) { + Map<String, Integer> aNewKeyMapArray = new HashMap<String, Integer>(Short.MAX_VALUE); + aNewKeyMapArray.putAll(aOldKeyMapArray); + try { + ReflectionUtils.setFinalFieldValue(Keyboard.class, aKeyMapSize.getName(), aNewKeyMapArray); + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Patched Field: " + aKeyMapSize.getName()); + } catch (Throwable t) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Failed Patching Field: " + aKeyDownBuffer.getName()); + } + } + ByteBuffer aOldByteBuffer = ReflectionUtils.getFieldValue(aKeyDownBuffer); + if (aOldByteBuffer != null && aOldByteBuffer.capacity() == Keyboard.KEYBOARD_SIZE) { + ByteBuffer aNewByteBuffer = BufferUtils.createByteBuffer(Short.MAX_VALUE); + try { + ReflectionUtils.setFinalFieldValue(Keyboard.class, aKeyDownBuffer.getName(), aNewByteBuffer); + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Patched Field: " + aKeyDownBuffer.getName()); + } catch (Throwable t) { + FMLRelaunchLog.log( + "[GT++ ASM] LWJGL Keybinding index out of bounds fix", + Level.INFO, + "Failed Patching Field: " + aKeyDownBuffer.getName()); + } + } + init = true; + } + } + + /** + * Gets a key's name + * + * @param key The key + * @return a String with the key's human readable name in it or null if the key is unnamed + */ + public static synchronized String getKeyName(int key) { + return ClassTransformer_LWJGL_Keyboard.getKeyName(key); + } + + /** + * Represents a key or mouse button as a string. Args: key + */ + public static String getKeyDisplayString(int aKeyValue) { + return aKeyValue < 0 ? I18n.format("key.mouseButton", new Object[] { Integer.valueOf(aKeyValue + 101) }) + : getKeyName(aKeyValue); + } +} |