diff --git a/README.md b/README.md index aa715ba..9dbc974 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,6 @@ Fixing Intel rendering on even older Minecraft versions! +This bug was introduced in Beta 1.9 Prerelease (1) + This mod should work on all versions with FML coremods (1.3+). diff --git a/build.gradle b/build.gradle index 3b10525..c09b9a6 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,11 @@ tasks.withType(JavaCompile).configureEach { } } +jar.manifest.attributes([ + "FMLCorePlugin": 'net.anawesomguy.intelfix.IntelFixPlugin', + "Premain-Class`": 'net.anawesomguy.intelfix.IntelFixPatcher$JA' +]) + processResources { inputs.property "version", project.version diff --git a/src/main/java/net/anawesomguy/intelfix/IntelFix.java b/src/main/java/net/anawesomguy/intelfix/IntelFix.java index 6b2176f..2e03448 100644 --- a/src/main/java/net/anawesomguy/intelfix/IntelFix.java +++ b/src/main/java/net/anawesomguy/intelfix/IntelFix.java @@ -1,10 +1,217 @@ package net.anawesomguy.intelfix; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + public final class IntelFix { + public static final Logger LOGGER = Logger.getLogger("IntelFix"); + + static { + init: + { + try { + LOGGER.setParent(FMLLog.getLogger()); + break init; + } catch (NoClassDefFoundError e) { + } catch (NoSuchMethodError e) { + } + Level level; + try { + level = Level.parse(System.getProperty("intelfix.loglevel")); + } catch (Exception e) { + level = Level.INFO; + } + LOGGER.setLevel(level); + } + } + + static File configFile; + public static boolean isFML; + static boolean deobfEnv; + static String modFile; + + static String injectedClass, injectedMethod, glHelperClass, setClientTexture; + static boolean obfuscatedNames; + static boolean useLegacy; + private IntelFix() { } - public static class Log { + // properties: injected_class, injected_method, gl_helper_class, set_client_texture, obfuscated_names, use_legacy + static void loadConfig() { + LOGGER.fine("Initializing IntelFixSetup from " + modFile); + + // read config + Properties config = new Properties(); + String comment = " ONLY CHANGE THESE IF YOU KNOW WHAT YOU'RE DOING!\n\n" + + " injected_class: the class to inject the fix into\n" + + " injected_method: the name and descriptor of the method to inject the fix into\n" + + " gl_helper_class: the name of the `OpenGLHelper class\n" + + " set_client_texture: the name WITHOUT descriptor of the `OpenGlHelper.setClientActiveTexture(I)V` method\n" + + " obfuscated_names: if the above names are obfuscated and unmapped\n" + + " use_legacy: whether the legacy fix is used (inject into `OpenGlHelper.setActiveTexture` instead of `Tessellator#draw`)\n"; + List configVals = Arrays.asList( + "injected_class", "injected_method", "gl_helper_class", + "set_client_texture", "obfuscated_names", "use_legacy"); + String injectedClass = "", injectedMethod = "", glHelperClass = "", setClientTexture = ""; + boolean obfuscatedNames = false, useLegacy = false; + try { + File file = configFile; + if (file.exists()) { + config.load(new FileInputStream(file)); + for (Entry entry : config.entrySet().toArray(new Entry[0])) { + Object key = entry.getKey(); + int index; + if (key instanceof String && (index = configVals.indexOf(key)) > -1) { + configVals.set(index, null); + Object value = entry.getValue(); + if (value instanceof String) { + String val = ((String)value).trim(); + if (!val.isEmpty()) + switch (index) { + case 0: + injectedClass = val; + break; + case 1: + injectedMethod = val; + break; + case 2: + glHelperClass = val; + break; + case 3: + setClientTexture = val; + break; + case 4: + obfuscatedNames = parseBool(val); + break; + case 5: + useLegacy = parseBool(val); + break; + } + } + } else { + LOGGER.log(Level.INFO, "Found bad config value \"{0}\"", key); + config.remove(key); + } + } + + boolean modified = false; + for (String val : configVals) + if (val != null) { + LOGGER.log(Level.WARNING, "Missing config value \"{0}\", replacing with defaults!", val); + config.put(val, val.equals("use_legacy") || val.equals("obfuscated_names") ? "false" : ""); + modified = true; + } + if (modified) + config.store(new FileWriter(file), comment); + } else { + LOGGER.info("Config does not exist! Creating from defaults."); + config.setProperty("injected_class", ""); + config.setProperty("injected_method", ""); + config.setProperty("gl_helper_class", ""); + config.setProperty("set_client_texture", ""); + config.setProperty("use_legacy", "false"); + config.setProperty("obfuscated_names", "false"); + config.store(new FileWriter(file), comment); + } + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "Could not load or write to config file at \"" + configFile.getAbsolutePath() + + "\", will use defaults!", e); + } + + // set config values + IntelFix.useLegacy = useLegacy; + IntelFix.obfuscatedNames = obfuscatedNames; + IntelFix.injectedClass = !injectedClass.isEmpty() ? + injectedClass : + maybeUnmap( + useLegacy ? "net.minecraft.client.renderer.OpenGlHelper" : "net.minecraft.client.renderer.Tessellator", + obfuscatedNames); + + if (!injectedMethod.isEmpty()) + IntelFix.injectedMethod = injectedMethod; + else { + if (obfuscatedNames) + LOGGER.severe( + "Cannot set `obfuscated_names` without also specifying a method! This mod will not function!"); + if (useLegacy) + IntelFix.injectedMethod = deobfEnv ? "setActiveTexture(I)V" : "func_77473_a(I)V"; + else + IntelFix.injectedMethod = deobfEnv ? "draw()I" : "func_78381_a()I"; + } + + IntelFix.glHelperClass = ( + !glHelperClass.isEmpty() ? + glHelperClass : + maybeUnmap("net.minecraft.client.renderer.OpenGlHelper", obfuscatedNames) + ).replace('.', '/'); + + if (!setClientTexture.isEmpty()) + IntelFix.setClientTexture = setClientTexture; + else { + if (obfuscatedNames) + LOGGER.severe( + "Cannot set `obfuscated_names` without also specifying `set_client_texture`! This mod will not function!"); + IntelFix.setClientTexture = deobfEnv ? "setClientActiveTexture" : "func_77472_b"; + } + + LOGGER.finer("Config values read, parsed, and stored!"); + LOGGER.log(Level.FINER, + "use_legacy: {0}, injected_class: {1}, injected_method: {2}, gl_helper_class: {3}, set_client_texture: {4}, obfuscated_names: {5}", + new Object[]{useLegacy, IntelFix.injectedClass, IntelFix.injectedMethod, IntelFix.glHelperClass, IntelFix.setClientTexture, obfuscatedNames}); + } + + public static String injectedClass() { + return injectedClass; + } + + public static String injectedMethod() { + return injectedMethod; + } + + public static String glHelperClass() { + return glHelperClass; + } + + public static String setClientTexture() { + return setClientTexture; + } + + public static boolean obfuscatedNames() { + return obfuscatedNames; + } + + public static boolean useLegacy() { + return useLegacy; + } + + private static boolean parseBool(String val) { + if ("true".equalsIgnoreCase(val)) + return true; + + if (!val.isEmpty() && !"false".equalsIgnoreCase(val)) + LOGGER.log(Level.INFO, "Parsing weird boolean value \"{0}\" as false!", val); + return false; + } + + private static String maybeUnmap(String clazz, boolean obfuscatedNames) { + if (!deobfEnv && obfuscatedNames) { + String unmapped = FMLDeobfuscatingRemapper.INSTANCE.unmap(clazz); + LOGGER.log(Level.FINER, "Unmapped class \"{0}\" to \"{1}\"", new Object[]{clazz, unmapped}); + return unmapped; + } + return clazz; } } diff --git a/src/main/java/net/anawesomguy/intelfix/IntelFixPatcher.java b/src/main/java/net/anawesomguy/intelfix/IntelFixPatcher.java index 487c689..a1f429f 100644 --- a/src/main/java/net/anawesomguy/intelfix/IntelFixPatcher.java +++ b/src/main/java/net/anawesomguy/intelfix/IntelFixPatcher.java @@ -10,7 +10,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; -import static net.anawesomguy.intelfix.IntelFixPlugin.*; +import static net.anawesomguy.intelfix.IntelFix.*; // https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/1294926-themastercavers-world?page=13#c294 public final class IntelFixPatcher { diff --git a/src/main/java/net/anawesomguy/intelfix/IntelFixPlugin.java b/src/main/java/net/anawesomguy/intelfix/IntelFixPlugin.java index ada4194..8cfbe52 100644 --- a/src/main/java/net/anawesomguy/intelfix/IntelFixPlugin.java +++ b/src/main/java/net/anawesomguy/intelfix/IntelFixPlugin.java @@ -1,32 +1,16 @@ package net.anawesomguy.intelfix; -import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import cpw.mods.fml.relauncher.FMLInjectionData; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import net.minecraft.launchwrapper.Launch; import java.io.File; -import java.lang.reflect.Field; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -public final class IntelFixPlugin implements IFMLLoadingPlugin { - public static final Logger LOGGER = Logger.getLogger("IntelFix"); - static boolean deobfEnv; - static String modFile; - static File configFile; - - static { - LOGGER.setParent(FMLLog.getLogger()); - } - - static String injectedClass, injectedMethod, glHelperClass, setClientTexture; - static boolean obfuscatedNames; - static boolean useLegacy; +import static net.anawesomguy.intelfix.IntelFix.*; +public final class IntelFixPlugin implements IFMLLoadingPlugin { @Deprecated @Override public String[] getLibraryRequestClass() { @@ -49,7 +33,6 @@ public String getSetupClass() { } @Override - @SuppressWarnings("JavaReflectionMemberAccess") public void injectData(Map map) { Object obfEnv = map.get("runtimeDeobfuscationEnabled"); if (obfEnv instanceof Boolean) @@ -67,7 +50,6 @@ public void injectData(Map map) { * get config dir from `Loader.instance().getConfigDir()` * get mc home from `Launch.minecraftHome` (only exists when using launchwrapper) * get mc home from `FMLInjectionData.data()`'s 7th element - * get `cfgdir` from `ModLoader` class using reflection (it's private) */ File mcDir; Object mcLoc = map.get("mcLocation"); @@ -92,94 +74,11 @@ public void injectData(Map map) { } catch (NoClassDefFoundError err) { } catch (RuntimeException ex) { } - try { - Class c = Class.forName("ModLoader"); - Field f = c.getDeclaredField("cfgdir"); - configFile = new File((File)f.get(null), "INTELFIX.properties"); - return; - } catch (Exception ex) { - mcDir = new File(System.getProperty("user.dir", ".")); - } + mcDir = new File(System.getProperty("user.dir", ".")); } } } } - IntelFixPlugin.configFile = new File(new File(mcDir, "config"), "INTELFIX.properties"); - } - - public static boolean useLegacy() { - return useLegacy; - } - - public static String injectedClass() { - return injectedClass; - } - - public static String injectedMethod() { - return injectedMethod; - } - - public static String glHelperClass() { - return glHelperClass; - } - - public static String setClientTextureMethod() { - return setClientTexture; - } - - public static boolean obfuscatedNames() { - return obfuscatedNames; - } - - static void setConfigVals(boolean useLegacy, String injectedClass, String injectedMethod, String glHelperClass, - String setClientTexture, boolean obfuscatedNames) { - IntelFixPlugin.useLegacy = useLegacy; - IntelFixPlugin.obfuscatedNames = obfuscatedNames; - - IntelFixPlugin.injectedClass = injectedClass != null && !injectedClass.isEmpty() ? - injectedClass : - maybeUnmap( - useLegacy ? "net.minecraft.client.renderer.OpenGlHelper" : "net.minecraft.client.renderer.Tessellator", - obfuscatedNames); - - if (injectedMethod != null && !injectedMethod.isEmpty()) - IntelFixPlugin.injectedMethod = injectedMethod; - else { - if (obfuscatedNames) - LOGGER.severe( - "Cannot set `obfuscated_names` without also specifying a method! This mod will not function!"); - if (useLegacy) - IntelFixPlugin.injectedMethod = deobfEnv ? "setActiveTexture(I)V" : "func_77473_a(I)V"; - else - IntelFixPlugin.injectedMethod = deobfEnv ? "draw()I" : "func_78381_a()I"; - } - - IntelFixPlugin.glHelperClass = (glHelperClass != null && !glHelperClass.isEmpty() ? - glHelperClass : - maybeUnmap("net.minecraft.client.renderer.OpenGlHelper", - obfuscatedNames)).replace('.', '/'); - - if (setClientTexture != null && !setClientTexture.isEmpty()) - IntelFixPlugin.setClientTexture = setClientTexture; - else { - if (obfuscatedNames) - LOGGER.severe("Cannot set `obfuscated_names` without also specifying `set_client_texture`! This mod will not function!"); - IntelFixPlugin.setClientTexture = deobfEnv ? "setClientActiveTexture" : "func_77472_b"; - } - - LOGGER.finer("Config values read, parsed, and stored!"); - LOGGER.log(Level.FINER, - "use_legacy: {0}, injected_class: {1}, injected_method: {2}, gl_helper_class: {3}, set_client_texture: {4}, obfuscated_names: {5}", - new Object[]{useLegacy, IntelFixPlugin.injectedClass, IntelFixPlugin.injectedMethod, IntelFixPlugin.glHelperClass, IntelFixPlugin.setClientTexture, obfuscatedNames}); - } - - private static String maybeUnmap(String clazz, boolean obfuscatedNames) { - if (!deobfEnv && obfuscatedNames) { - String unmapped = FMLDeobfuscatingRemapper.INSTANCE.unmap(clazz); - LOGGER.log(Level.FINER, "Unmapped class \"{0}\" to \"{1}\"", new Object[]{clazz, unmapped}); - return unmapped; - } - - return clazz; + configFile = new File(new File(mcDir, "config"), "INTELFIX.properties"); } } diff --git a/src/main/java/net/anawesomguy/intelfix/IntelFixSetup.java b/src/main/java/net/anawesomguy/intelfix/IntelFixSetup.java index 0e63d42..ca18056 100644 --- a/src/main/java/net/anawesomguy/intelfix/IntelFixSetup.java +++ b/src/main/java/net/anawesomguy/intelfix/IntelFixSetup.java @@ -1,107 +1,19 @@ package net.anawesomguy.intelfix; -import com.google.common.collect.ImmutableSet; import cpw.mods.fml.relauncher.IFMLCallHook; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; import java.util.logging.Level; -import static net.anawesomguy.intelfix.IntelFixPlugin.LOGGER; - public final class IntelFixSetup implements IFMLCallHook { @Override public void injectData(Map map) { } - // properties: injected_class, injected_method, gl_helper_class, set_client_texture, obfuscated_names, use_legacy @Override public Void call() { - LOGGER.fine("Initializing IntelFixSetup from " + IntelFixPlugin.modFile); - - // config section below - Properties config = new Properties(); - String comment = " ONLY CHANGE THESE IF YOU KNOW WHAT YOU'RE DOING!\n\n" + - " injected_class: the class to inject the fix into\n" + - " injected_method: the name and descriptor of the method to inject the fix into\n" + - " gl_helper_class: the name of the `OpenGLHelper class\n" + - " set_client_texture: the name WITHOUT descriptor of the `OpenGlHelper.setClientActiveTexture(I)V` method\n" + - " obfuscated_names: if the above names are obfuscated and unmapped\n" + - " use_legacy: whether the legacy fix is used (inject into `OpenGlHelper.setActiveTexture` instead of `Tessellator#draw`)\n"; - List configVals = Arrays.asList("injected_class", "injected_method", "gl_helper_class", "set_client_texture", "obfuscated_names", "use_legacy"); - String injectedClass = "", injectedMethod = "", glHelperClass = "", setClientTexture = ""; - boolean obfuscatedNames = false, useLegacy = false; - try { - File file = IntelFixPlugin.configFile; - if (file.exists()) { - config.load(new FileInputStream(file)); - for (Entry entry : ImmutableSet.copyOf(config.entrySet())) { - Object key = entry.getKey(); - int index; - if (key instanceof String && (index = configVals.indexOf(key)) > -1) { - configVals.set(index, null); - Object value = entry.getValue(); - if (value instanceof String) { - String val = ((String)value).trim(); - switch (index) { - case 0: - injectedClass = val; - break; - case 1: - injectedMethod = val; - break; - case 2: - glHelperClass = val; - break; - case 3: - setClientTexture = val; - break; - case 4: - obfuscatedNames = parseBool(val); - break; - case 5: - useLegacy = parseBool(val); - break; - } - } - } else { - LOGGER.log(Level.INFO, "Found bad config value \"{0}\"", key); - config.remove(key); - } - } - - boolean modified = false; - for (String val : configVals) { - if (val != null) { - LOGGER.log(Level.WARNING, "Missing config value \"{0}\", replacing with defaults!", val); - config.put(val, val.equals("use_legacy") || val.equals("obfuscated_names") ? "false" : ""); - modified = true; - } - } - if (modified) - config.store(new FileWriter(file), comment); - } else { - LOGGER.info("Config does not exist! Creating from defaults."); - config.setProperty("injected_class", ""); - config.setProperty("injected_method", ""); - config.setProperty("gl_helper_class", ""); - config.setProperty("set_client_texture", ""); - config.setProperty("use_legacy", "false"); - config.setProperty("obfuscated_names", "false"); - config.store(new FileWriter(file), comment); - } - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Could not load or write to config file INTELFIX.properties, will use defaults!", e); - } - - IntelFixPlugin.setConfigVals(useLegacy, injectedClass, injectedMethod, glHelperClass, setClientTexture, obfuscatedNames); + IntelFix.isFML = true; + IntelFix.loadConfig(); return null; } @@ -110,7 +22,7 @@ private boolean parseBool(String val) { return true; if (!val.isEmpty() && !"false".equalsIgnoreCase(val)) - LOGGER.log(Level.INFO, "Parsing weird boolean value \"{0}\" as false!", val); + IntelFix.LOGGER.log(Level.INFO, "Parsing weird boolean value \"{0}\" as false!", val); return false; } } diff --git a/src/main/java/net/anawesomguy/intelfix/PatchCV.java b/src/main/java/net/anawesomguy/intelfix/PatchCV.java index fcc5f8d..4b0833b 100644 --- a/src/main/java/net/anawesomguy/intelfix/PatchCV.java +++ b/src/main/java/net/anawesomguy/intelfix/PatchCV.java @@ -7,9 +7,7 @@ import java.util.logging.Level; -import static net.anawesomguy.intelfix.IntelFixPlugin.*; - -public class PatchCV extends ClassVisitor { +class PatchCV extends ClassVisitor { final boolean[] patch; final String cls; final boolean isObf; @@ -31,11 +29,11 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si method = name.concat(desc); else { method = FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(cls, name, desc).concat(desc); - LOGGER.log(Level.FINER, "Remapped \"{0}{1}\" in \"{2}\" to \"{3}\"", - new Object[]{name, desc, cls, method}); + IntelFix.LOGGER.log(Level.FINER, "Remapped \"{0}{1}\" in \"{2}\" to \"{3}\"", + new Object[]{name, desc, cls, method}); } - if (method.equals(injectedMethod)) + if (method.equals(IntelFix.injectedMethod)) return new PatchMV(visitor, patch, method); } diff --git a/src/main/java/net/anawesomguy/intelfix/PatchMV.java b/src/main/java/net/anawesomguy/intelfix/PatchMV.java index ff9d859..d729a9e 100644 --- a/src/main/java/net/anawesomguy/intelfix/PatchMV.java +++ b/src/main/java/net/anawesomguy/intelfix/PatchMV.java @@ -7,10 +7,6 @@ import java.util.logging.Level; -import static net.anawesomguy.intelfix.IntelFixPlugin.*; -import static org.objectweb.asm.Opcodes.ILOAD; -import static org.objectweb.asm.Opcodes.INVOKESTATIC; - class PatchMV extends MethodVisitor { final boolean[] patch; final String mth; @@ -24,13 +20,13 @@ class PatchMV extends MethodVisitor { @Override public void visitCode() { super.visitCode(); - LOGGER.log(Level.FINE, "Injecting patch into \"{0}\"", mth); + IntelFix.LOGGER.log(Level.FINE, "Injecting patch into \"{0}\"", mth); patch[0] = true; mv.visitLabel(new Label()); - if (useLegacy) - mv.visitVarInsn(ILOAD, 0); + if (IntelFix.useLegacy) + mv.visitVarInsn(Opcodes.ILOAD, 0); else mv.visitLdcInsn(GL13.GL_TEXTURE0); - mv.visitMethodInsn(INVOKESTATIC, glHelperClass, setClientTexture, "(I)V"); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, IntelFix.glHelperClass, IntelFix.setClientTexture, "(I)V"); } }