diff options
Diffstat (limited to 'src/Java/gtPlusPlus/preloader/asm')
4 files changed, 262 insertions, 54 deletions
diff --git a/src/Java/gtPlusPlus/preloader/asm/AsmConfig.java b/src/Java/gtPlusPlus/preloader/asm/AsmConfig.java index b3fbcb2d61..88bcf6b28b 100644 --- a/src/Java/gtPlusPlus/preloader/asm/AsmConfig.java +++ b/src/Java/gtPlusPlus/preloader/asm/AsmConfig.java @@ -15,6 +15,7 @@ public class AsmConfig { public static boolean enableTiConFluidLighting; public static boolean enableGtTooltipFix; public static boolean enableGtNbtFix; + public static boolean enableGtCharcoalPitFix; public static boolean enableChunkDebugging; public static boolean enableCofhPatch; public static boolean enableGcFuelChanges; @@ -22,6 +23,7 @@ public class AsmConfig { public static boolean enableRcItemDupeFix; public static boolean enableTcAspectSafety; public static boolean enabledLwjglKeybindingFix; + public static boolean enabledFixEntitySetHealth; public static boolean disableAllLogging; @@ -51,6 +53,12 @@ public class AsmConfig { disableAllLogging = 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", "enableChunkDebugging", false); prop.comment = "Enable/Disable Chunk Debugging Features, Must Be enabled on Client and Server."; prop.setLanguageKey("gtpp.enableChunkDebugging").setRequiresMcRestart(true); @@ -91,6 +99,14 @@ public class AsmConfig { 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()); + prop = config.get("general", "enableGcFuelChanges", true); prop.comment = "Enable/Disable changes to Galacticraft Rocket Fuels."; prop.setLanguageKey("gtpp.enableGcFuelChanges").setRequiresMcRestart(true); @@ -137,6 +153,7 @@ public class AsmConfig { FMLLog.log(Level.INFO, "[GT++ ASM] Gc Fuel Changes Patch - Enabled: "+enableGcFuelChanges, new Object[0]); FMLLog.log(Level.INFO, "[GT++ ASM] Railcraft Fluid Flow Patch - Enabled: "+enableRcFlowFix, new Object[0]); FMLLog.log(Level.INFO, "[GT++ ASM] Thaumcraft Aspect Safety Patch - Enabled: "+enableTcAspectSafety, new Object[0]); + FMLLog.log(Level.INFO, "[GT++ ASM] Fix bad usage of EntityLivingBase.setHealth Patch - Enabled: "+enabledFixEntitySetHealth, new Object[0]); } catch (Exception var3) { FMLLog.log(Level.ERROR, var3, "GT++ ASM had a problem loading it's config", new Object[0]); diff --git a/src/Java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_Forge_EntityLivingBase_SetHealth.java b/src/Java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_Forge_EntityLivingBase_SetHealth.java new file mode 100644 index 0000000000..d56b9de059 --- /dev/null +++ b/src/Java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_Forge_EntityLivingBase_SetHealth.java @@ -0,0 +1,130 @@ +package gtPlusPlus.preloader.asm.transformers; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.DamageSource; + +public class ClassTransformer_Forge_EntityLivingBase_SetHealth { + + private boolean isValid = false; + private ClassReader mReader = null; + private ClassWriter mWriter = null; + private boolean didPatch = false; + + public ClassTransformer_Forge_EntityLivingBase_SetHealth(String aClassName, byte[] basicClass) { + if (basicClass == null) { + return; + } + + ClassReader reader = new ClassReader(basicClass); + ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS); + ClassVisitor visitor = writer; + SetHealthVisitor aVisitor = new SetHealthVisitor(visitor); + visitor = aVisitor; + reader.accept(visitor, 0); + if (reader != null && writer != null) { + isValid = true; + } + else { + isValid = false; + } + mReader = reader; + mWriter = writer; + didPatch = aVisitor.didPatchInternal; + } + + public boolean isValidTransformer() { + return isValid; + } + + public ClassReader getReader() { + return mReader; + } + + public ClassWriter getWriter() { + return mWriter; + } + + + public static class SetHealthVisitor extends ClassVisitor { + private String clsName = null; + private boolean didPatchInternal = false; + private static final String callbackOwner = org.objectweb.asm.Type.getInternalName(SetHealthVisitor.class); + + private SetHealthVisitor(ClassVisitor cv) { + super(Opcodes.ASM5, cv); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit( + version, access, name, signature, superName, interfaces + ); + this.clsName = name; + } + + @Override + public MethodVisitor visitMethod( + int mAccess, final String mName, final String mDesc, String mSignature, String[] mExceptions) { + final boolean warn = !(clsName.equals( + "net/minecraft/entity/EntityLivingBase" + )); + + return new MethodVisitor(Opcodes.ASM5, super.visitMethod(mAccess, mName, mDesc, mSignature, mExceptions)) { + @Override + public void visitMethodInsn( + int opcode, String owner, String name, String desc, boolean isIntf + ) { + if (owner.equals( + "net/minecraft/entity/EntityLivingBase" + ) && name.equals("setHealth") && desc.equals("(F)V")) { + if (warn) { + FMLRelaunchLog.warning( + "=============================================================" + ); + FMLRelaunchLog.warning( + "MOD HAS DIRECT REFERENCE Entity.setHealth() THIS IS NOT ALLOWED!" + ); + FMLRelaunchLog.warning( + "Offendor: %s.%s%s", SetHealthVisitor.this.clsName, mName, mDesc + ); + FMLRelaunchLog.warning( + "Use EntityLiving.attackEntityFrom(DamageSource, damageDealt) instead" + ); + FMLRelaunchLog.warning( + "=============================================================" + ); + } + didPatchInternal = true; + //opcode = Opcodes.INVOKESTATIC; // Set it static + //owner = SetHealthVisitor.callbackOwner; + //name = "setHealthGeneric"; // Replace the method name + //desc = "(Lnet/minecraft/entity/EntityLivingBase;F)V"; // Replace the method desc + + } + super.visitMethodInsn(opcode, owner, name, desc, isIntf); + } + }; + } + + + private final static DamageSource mGenericDamageSource = new DamageSource("gtpp.generic"); + + public static void setHealthGeneric(EntityLivingBase aEntity, float aValue) { + aEntity.attackEntityFrom(mGenericDamageSource, aValue); + } + + } + + + public boolean didPatchClass() { + return didPatch; + } + +} diff --git a/src/Java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_GT_CharcoalPit.java b/src/Java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_GT_CharcoalPit.java index 9c79db265d..1e54bd3632 100644 --- a/src/Java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_GT_CharcoalPit.java +++ b/src/Java/gtPlusPlus/preloader/asm/transformers/ClassTransformer_GT_CharcoalPit.java @@ -1,10 +1,6 @@ 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.ASM5; -import static org.objectweb.asm.Opcodes.INVOKESTATIC; -import static org.objectweb.asm.Opcodes.IRETURN; +import static org.objectweb.asm.Opcodes.*; import java.util.ArrayList; @@ -17,10 +13,10 @@ import org.objectweb.asm.MethodVisitor; import cpw.mods.fml.relauncher.FMLRelaunchLog; import gregtech.api.enums.OrePrefixes; -import gtPlusPlus.api.objects.Logger; +import gregtech.api.util.GT_Utility; import gtPlusPlus.core.util.minecraft.ItemUtils; +import gtPlusPlus.core.util.reflect.ReflectionUtils; import net.minecraft.block.Block; -import net.minecraft.block.material.Material; import net.minecraft.item.ItemStack; import net.minecraftforge.oredict.OreDictionary; @@ -31,35 +27,58 @@ public class ClassTransformer_GT_CharcoalPit { private final ClassWriter writer; public static boolean isWoodLog(Block log) { - //Logger.INFO("checking for log"); - boolean isLog1 = OrePrefixes.log.contains(new ItemStack(log, 1)); - if (isLog1) { - //Logger.INFO("Found 1"); - return true; + return isWoodLog(log, Short.MAX_VALUE); + } + + public static boolean isWoodLog(Block log, int meta) { + ItemStack aLogStack = ItemUtils.getSimpleStack(log, meta, 1); + ArrayList<ItemStack> aData = OrePrefixes.log.mPrefixedItems; + for (ItemStack aStack : aData) { + if (GT_Utility.areStacksEqual(aStack, aLogStack)) { + return true; + } + } + aData.clear(); + aData = OreDictionary.getOres("logWood"); + for (ItemStack aStack : aData) { + if (GT_Utility.areStacksEqual(aStack, aLogStack)) { + return true; + } } - ArrayList<ItemStack> oredict = OreDictionary.getOres("logWood"); - if (oredict.contains(ItemUtils.getSimpleStack(log))) { - //Logger.INFO("found 2"); - return true; - } - //Logger.INFO("Did not find. "+(log != null ? ""+log.getLocalizedName() : "Null or invalid block?")); return false; } - + public ClassTransformer_GT_CharcoalPit(byte[] basicClass, boolean obfuscated) { ClassReader aTempReader = null; ClassWriter aTempWriter = null; + boolean aBadTime = false; + if (ReflectionUtils.doesClassExist("aji")) { + obfuscated = true; + } + else { + if (ReflectionUtils.doesClassExist("net.minecraft.block.Block")) { + obfuscated = false; + } + else { + // Bad... Like.. very bad.. + FMLRelaunchLog.log("[GT++ ASM] GT Charcoal Pit Fix", Level.INFO, "Unable to find Block.class/aji.class, this is BAD. Not Patching."); + } + } aTempReader = new ClassReader(basicClass); aTempWriter = new ClassWriter(aTempReader, ClassWriter.COMPUTE_FRAMES); - aTempReader.accept(new AddFieldAdapter(aTempWriter), 0); - injectMethod("isWoodLog", obfuscated, aTempWriter); - if (aTempReader != null && aTempWriter != null) { - isValid = true; - } else { + if (!aBadTime) { + aTempReader.accept(new CustomClassVisitor(aTempWriter), 0); + injectMethod("isWoodLog", obfuscated, aTempWriter); + if (aTempReader != null && aTempWriter != null) { + isValid = true; + } else { + isValid = false; + } + } + else { isValid = false; } - FMLRelaunchLog.log("[GT++ ASM] GT Charcoal Pit Fix", Level.INFO, - "Valid? " + isValid + "."); + FMLRelaunchLog.log("[GT++ ASM] GT Charcoal Pit Fix", Level.INFO, "Valid? " + isValid + "."); reader = aTempReader; writer = aTempWriter; } @@ -80,17 +99,19 @@ public class ClassTransformer_GT_CharcoalPit { MethodVisitor mv; boolean didInject = false; FMLRelaunchLog.log("[GT++ ASM] GT Charcoal Pit Fix", Level.INFO, "Injecting " + aMethodName + "."); - + String aBlockClassName = "net/minecraft/block/Block"; if (obfuscated) { aBlockClassName = "aji"; } if (aMethodName.equals("isWoodLog")) { + + // Inject original Method with only block arg. mv = cw.visitMethod(ACC_PUBLIC, "isWoodLog", "(L"+aBlockClassName+";)Z", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); - mv.visitLineNumber(49, l0); + mv.visitLineNumber(197, l0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKESTATIC, "gtPlusPlus/preloader/asm/transformers/ClassTransformer_GT_CharcoalPit", "isWoodLog", "(L"+aBlockClassName+";)Z", false); mv.visitInsn(IRETURN); @@ -100,15 +121,36 @@ public class ClassTransformer_GT_CharcoalPit { mv.visitLocalVariable("log", "L"+aBlockClassName+";", null, l0, l1, 1); mv.visitMaxs(1, 2); mv.visitEnd(); + + + // Inject better Method with block & meta arg. + mv = cw.visitMethod(ACC_PUBLIC, "isWoodLog", "(L"+aBlockClassName+";I)Z", null, null); + mv.visitCode(); + Label label0 = new Label(); + mv.visitLabel(label0); + mv.visitLineNumber(201, label0); + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ILOAD, 2); + mv.visitMethodInsn(INVOKESTATIC, "gtPlusPlus/preloader/asm/transformers/ClassTransformer_GT_CharcoalPit", "isWoodLog", "(L"+aBlockClassName+";I)Z", false); + mv.visitInsn(IRETURN); + Label label1 = new Label(); + mv.visitLabel(label1); + mv.visitLocalVariable("this", "Lgregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit;", null, label0, label1, 0); + mv.visitLocalVariable("log", "L"+aBlockClassName+";", null, label0, label1, 1); + mv.visitLocalVariable("meta", "I", null, label0, label1, 2); + mv.visitMaxs(2, 3); + mv.visitEnd(); + didInject = true; + } FMLRelaunchLog.log("[GT++ ASM] GT Charcoal Pit Fix", Level.INFO, "Method injection complete."); return didInject; } - public class AddFieldAdapter extends ClassVisitor { + public class CustomClassVisitor extends ClassVisitor { - public AddFieldAdapter(ClassVisitor cv) { + public CustomClassVisitor(ClassVisitor cv) { super(ASM5, cv); this.cv = cv; } diff --git a/src/Java/gtPlusPlus/preloader/asm/transformers/Preloader_Transformer_Handler.java b/src/Java/gtPlusPlus/preloader/asm/transformers/Preloader_Transformer_Handler.java index d81c96dcca..d8dc71dff0 100644 --- a/src/Java/gtPlusPlus/preloader/asm/transformers/Preloader_Transformer_Handler.java +++ b/src/Java/gtPlusPlus/preloader/asm/transformers/Preloader_Transformer_Handler.java @@ -30,9 +30,9 @@ public class Preloader_Transformer_Handler implements IClassTransformer { System.out.println("[GT++ ASM] Asm Config Location: "+mConfig.config.getConfigFile().getAbsolutePath()); System.out.println("[GT++ ASM] Is DevHelper Valid? "+gtPlusPlus.preloader.DevHelper.mIsValidHelper); } - + private static Boolean mObf = null; - + public boolean checkObfuscated() { if (mObf != null) { return mObf; @@ -60,6 +60,25 @@ public class Preloader_Transformer_Handler implements IClassTransformer { } public byte[] transform(String name, String transformedName, byte[] basicClass) { + /* + * Here we patch all instances of entity.setHealth and replace them with a static function. + * Only EntityLivingBase is left untouched, as nothing else truly needs to be calling this method and avoiding forge hooks. + * May exclude all vanilla/forge class if this causes issues though. + */ + PatchForge : if (mConfig.enabledFixEntitySetHealth && !transformedName.contains("gtPlusPlus.preloader")) { + + //Skip Vanilla/Forge Classes + if (transformedName.contains("net.minecraft.") || transformedName.contains("cpw.")) { + //break PatchForge; + } + + ClassTransformer_Forge_EntityLivingBase_SetHealth aForgeHealthFix = new ClassTransformer_Forge_EntityLivingBase_SetHealth(transformedName, basicClass); + if (aForgeHealthFix.isValidTransformer() && aForgeHealthFix.didPatchClass()) { + FMLRelaunchLog.log("[GT++ ASM] Fix EntityLivingBase.setHealth misuse", Level.INFO, "Transforming %s", transformedName); + basicClass = aForgeHealthFix.getWriter().toByteArray(); + } + } + // Is this environment obfuscated? (Extra checks just in case some weird shit happens during the check) boolean obfuscated = checkObfuscated(); boolean probablyShouldBeFalse = false; @@ -69,7 +88,7 @@ public class Preloader_Transformer_Handler implements IClassTransformer { FMLRelaunchLog.log("[GT++ ASM] LWJGL Keybinding index out of bounds fix", Level.INFO, "Transforming %s", transformedName); return new ClassTransformer_LWJGL_Keyboard(basicClass).getWriter().toByteArray(); } - + //Enable mapping of Tickets and loaded chunks. - Forge if (transformedName.equals("net.minecraftforge.common.ForgeChunkManager") && mConfig.enableChunkDebugging) { FMLRelaunchLog.log("[GT++ ASM] Chunkloading Patch", Level.INFO, "Transforming %s", transformedName); @@ -94,7 +113,7 @@ public class Preloader_Transformer_Handler implements IClassTransformer { FMLRelaunchLog.log("[GT++ ASM] Bright Fluids", Level.INFO, "Transforming %s", transformedName); return new ClassTransformer_TiConFluids("getLightValue", obfuscated, basicClass).getWriter().toByteArray(); } - + //Fix RC stuff //Patching PROCESS_VOLUME to allow 4x more transfer limits if (transformedName.equals("mods.railcraft.common.fluids.FluidHelper") && mConfig.enableRcFlowFix) { @@ -123,15 +142,15 @@ public class Preloader_Transformer_Handler implements IClassTransformer { } } - - - - - + + + + + /** * Gregtech ASM Patches */ - + //Make GT_Utilities safer if (transformedName.equals("gtPlusPlus.preloader.asm.transformers.ClassTransformer_GT_Utility")) { FMLRelaunchLog.log("[GT++ ASM] Gregtech Utilities Patch", Level.INFO, "Transforming %s", transformedName); @@ -147,7 +166,7 @@ public class Preloader_Transformer_Handler implements IClassTransformer { FMLRelaunchLog.log("[GT++ ASM] Gregtech Achievements Patch", Level.INFO, "Transforming %s", transformedName); return new ClassTransformer_GT_Achievements_CrashFix(basicClass, obfuscated).getWriter().toByteArray(); } - + //Fix bad handling of a loop left from original decompilation //Also Fix Achievements, although currently disabled. if (transformedName.equals("gregtech.common.GT_Client")) { @@ -165,16 +184,16 @@ public class Preloader_Transformer_Handler implements IClassTransformer { FMLRelaunchLog.log("[GT++ ASM] Gregtech setMetaTileEntity Patch", Level.INFO, "Transforming %s", transformedName); return new ClassTransformer_GT_BaseMetaTileEntity(basicClass).getWriter().toByteArray(); } - + //Fix log handling on the charcoal pit - if (transformedName.equals("gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_Charcoal_Pit")) { + if (transformedName.equals("gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_Charcoal_Pit") && mConfig.enableGtCharcoalPitFix) { FMLRelaunchLog.log("[GT++ ASM] GT Charcoal Pit Fix", Level.INFO, "Transforming %s", transformedName); return new ClassTransformer_GT_CharcoalPit(basicClass, obfuscated).getWriter().toByteArray(); } - - - - + + + + //Patching Meta Tile Tooltips if (transformedName.equals("gregtech.common.blocks.GT_Item_Machines") && mConfig.enableGtTooltipFix) { FMLRelaunchLog.log("[GT++ ASM] Gregtech Tooltip Patch", Level.INFO, "Transforming %s", transformedName); @@ -203,7 +222,7 @@ public class Preloader_Transformer_Handler implements IClassTransformer { } return new ClassTransformer_GT_BlockMachines_MetaPipeEntity(basicClass, probablyShouldBeFalse, mode).getWriter().toByteArray(); } - + String[] aIC2ClassNames = new String[] { "ic2.core.block.BlockTileEntity", "ic2.core.block.machine.BlockMachine", @@ -230,24 +249,24 @@ public class Preloader_Transformer_Handler implements IClassTransformer { return new ClassTransformer_IC2_GetHarvestTool(basicClass, obfuscated, transformedName).getWriter().toByteArray(); } } - + //Fix IC2 Hazmat if (transformedName.equals("ic2.core.item.armor.ItemArmorHazmat")) { FMLRelaunchLog.log("[GT++ ASM] IC2 Hazmat Patch", Level.INFO, "Transforming %s", transformedName); return new ClassTransformer_IC2_Hazmat(basicClass, transformedName).getWriter().toByteArray(); } - + //Fix Thaumcraft Shit //Patching ItemWispEssence to allow invalid item handling if (transformedName.equals("thaumcraft.common.items.ItemWispEssence") && mConfig.enableTcAspectSafety) { FMLRelaunchLog.log("[GT++ ASM] Thaumcraft WispEssence_Patch", Level.INFO, "Transforming %s", transformedName); return new ClassTransformer_TC_ItemWispEssence(basicClass, obfuscated).getWriter().toByteArray(); } - - + + return basicClass; } - - + + } |