From 913987a0389dca43977be2b8fcb5935cdb7e2d58 Mon Sep 17 00:00:00 2001 From: Adrian Siekierka Date: Tue, 21 Feb 2017 17:07:03 +0100 Subject: [PATCH] FoamFix 0.6.1 --- build.gradle | 2 +- .../java/pl/asie/foamfix/ProxyClient.java | 4 +- .../client/FoamyDefaultResourcePack.java | 37 ++--- .../client/FoamyDefaultResourcePackLight.java | 32 +++++ .../pl/asie/foamfix/coremod/FoamFixCore.java | 2 + .../foamfix/coremod/FoamFixTransformer.java | 133 +++++++++++------- .../foamfix/coremod/TransformerFunction.java | 5 + .../pl/asie/foamfix/shared/FoamFixConfig.java | 5 +- .../pl/asie/foamfix/shared/FoamFixShared.java | 8 ++ 9 files changed, 156 insertions(+), 72 deletions(-) create mode 100644 src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePackLight.java create mode 100644 src/main/java/pl/asie/foamfix/coremod/TransformerFunction.java diff --git a/build.gradle b/build.gradle index 1e2642b..9f4c033 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { apply plugin: 'net.minecraftforge.gradle.forge' apply plugin: 'com.github.johnrengelman.shadow' -version = "0.6.0" +version = "0.6.1" group= "pl.asie.foamfix" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = "foamfix" diff --git a/src/main/java/pl/asie/foamfix/ProxyClient.java b/src/main/java/pl/asie/foamfix/ProxyClient.java index 9594864..dbd3c44 100644 --- a/src/main/java/pl/asie/foamfix/ProxyClient.java +++ b/src/main/java/pl/asie/foamfix/ProxyClient.java @@ -104,7 +104,7 @@ public void preInit() { FoamFixDynamicItemModels.register(); } - if (FoamFixShared.config.clFasterResourceLoading && !FoamFixShared.coremodEnabled) { + if (FoamFixShared.config.clFasterResourceLoading > 0 && !FoamFixShared.coremodEnabled) { try { Field f1 = ReflectionHelper.findField(Minecraft.class, "mcDefaultResourcePack", "field_110450_ap"); Field f2 = ReflectionHelper.findField(Minecraft.class, "defaultResourcePacks", "field_110449_ao"); @@ -112,7 +112,7 @@ public void preInit() { Object o = f1.get(Minecraft.getMinecraft()); List l = (List) f2.get(Minecraft.getMinecraft()); int i = l.indexOf(o); - o = new FoamyDefaultResourcePack((ResourceIndex) f3.get(o)); + o = FoamyDefaultResourcePack.create((ResourceIndex) f3.get(o)); l.set(i, o); f1.set(Minecraft.getMinecraft(), o); } catch (Exception e) { diff --git a/src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePack.java b/src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePack.java index 78af04f..9be14dc 100644 --- a/src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePack.java +++ b/src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePack.java @@ -4,7 +4,10 @@ import com.google.common.cache.CacheBuilder; import net.minecraft.client.resources.DefaultResourcePack; import net.minecraft.client.resources.ResourceIndex; +import net.minecraft.launchwrapper.LaunchClassLoader; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.client.FMLClientHandler; +import pl.asie.foamfix.shared.FoamFixShared; import java.io.IOException; import java.io.InputStream; @@ -14,9 +17,8 @@ import java.util.concurrent.TimeUnit; public class FoamyDefaultResourcePack extends DefaultResourcePack { -// private final Cache cache = -// CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(); - private final Set foundResources = new HashSet<>(); + private final Cache cache = + CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(); private final ResourceIndex resourceIndex; public FoamyDefaultResourcePack(ResourceIndex resourceIndexIn) { @@ -24,10 +26,10 @@ public FoamyDefaultResourcePack(ResourceIndex resourceIndexIn) { this.resourceIndex = resourceIndexIn; } - // TODO: Verify what happens when non-mod files get added in this manner - /* @Override + @Override public InputStream getInputStream(ResourceLocation location) throws IOException { - if (!resourceExists(location)) { + Boolean b = cache.getIfPresent(location); + if (b != null && !b) { return null; } @@ -47,18 +49,21 @@ public Boolean call() throws Exception { } catch (Exception e) { return DefaultResourcePack.class.getResource("/assets/" + loc.getResourceDomain() + "/" + loc.getResourcePath()) != null || FoamyDefaultResourcePack.this.resourceIndex.isFileExisting(loc); } - } */ - - // I can still cache resources, however, as it's unlikely for something to get *removed* from the ClassLoader - @Override - public boolean resourceExists(ResourceLocation loc) { - if (foundResources.contains(loc)) return true; + } - if (DefaultResourcePack.class.getResource("/assets/" + loc.getResourceDomain() + "/" + loc.getResourcePath()) != null || FoamyDefaultResourcePack.this.resourceIndex.isFileExisting(loc)) { - foundResources.add(loc); - return true; + public static String getClassName() { + if (FoamFixShared.hasOptifine() || FoamFixShared.config.clFasterResourceLoading == 1) { + return "pl.asie.foamfix.client.FoamyDefaultResourcePackLight"; + } else { + return "pl.asie.foamfix.client.FoamyDefaultResourcePack"; } + } - return false; + public static DefaultResourcePack create(ResourceIndex resourceIndex) { + if (FoamFixShared.hasOptifine() || FoamFixShared.config.clFasterResourceLoading == 1) { + return new FoamyDefaultResourcePackLight(resourceIndex); + } else { + return new FoamyDefaultResourcePack(resourceIndex); + } } } diff --git a/src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePackLight.java b/src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePackLight.java new file mode 100644 index 0000000..7689b78 --- /dev/null +++ b/src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePackLight.java @@ -0,0 +1,32 @@ +package pl.asie.foamfix.client; + +import net.minecraft.client.resources.DefaultResourcePack; +import net.minecraft.client.resources.ResourceIndex; +import net.minecraft.util.ResourceLocation; + +import java.util.HashSet; +import java.util.Set; + +/** + * More compatibility-friendly version of FoamyDefaultResourcePack, used + * for example by OptiFine. + */ +public class FoamyDefaultResourcePackLight extends DefaultResourcePack { + private final Set foundResources = new HashSet<>(); + + public FoamyDefaultResourcePackLight(ResourceIndex resourceIndexIn) { + super(resourceIndexIn); + } + + @Override + public boolean resourceExists(ResourceLocation loc) { + if (foundResources.contains(loc)) return true; + + if (super.resourceExists(loc)) { + foundResources.add(loc); + return true; + } + + return false; + } +} diff --git a/src/main/java/pl/asie/foamfix/coremod/FoamFixCore.java b/src/main/java/pl/asie/foamfix/coremod/FoamFixCore.java index 34f4c3b..7ab65c9 100644 --- a/src/main/java/pl/asie/foamfix/coremod/FoamFixCore.java +++ b/src/main/java/pl/asie/foamfix/coremod/FoamFixCore.java @@ -65,6 +65,8 @@ public void injectData(final Map data) { classLoader.addTransformerExclusion("oshi."); classLoader.addTransformerExclusion("scala."); } + + FoamFixTransformer.init(); } public String getAccessTransformerClass() { diff --git a/src/main/java/pl/asie/foamfix/coremod/FoamFixTransformer.java b/src/main/java/pl/asie/foamfix/coremod/FoamFixTransformer.java index 2d93524..f57704f 100644 --- a/src/main/java/pl/asie/foamfix/coremod/FoamFixTransformer.java +++ b/src/main/java/pl/asie/foamfix/coremod/FoamFixTransformer.java @@ -26,11 +26,16 @@ package pl.asie.foamfix.coremod; import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; +import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; import com.google.common.collect.Sets; +import net.minecraft.launchwrapper.LaunchClassLoader; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.RemappingClassAdapter; import org.objectweb.asm.commons.Remapper; @@ -41,28 +46,31 @@ import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodNode; +import pl.asie.foamfix.client.FoamyDefaultResourcePack; import pl.asie.foamfix.shared.FoamFixShared; +import javax.annotation.Nullable; + public class FoamFixTransformer implements IClassTransformer { // TODO: NEW, INVOKESPECIAL. PATCHER - public byte[] replaceConstructor(final byte[] data, final String className, final String from, final String to, final String... methods) { + public static byte[] replaceConstructor(final byte[] data, final String className, final String from, final String to, final String... methods) { final ClassReader reader = new ClassReader(data); final ClassWriter writer = new ClassWriter(8); reader.accept(new FoamFixConstructorReplacer(from, to, methods).getClassVisitor(Opcodes.ASM5, writer), 8); return writer.toByteArray(); } - public byte[] spliceClasses(final byte[] data, final String className, final String targetClassName, final String... methods) { + public static byte[] spliceClasses(final byte[] data, final String className, final String targetClassName, final String... methods) { try { - final byte[] dataSplice = ByteStreams.toByteArray(this.getClass().getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class")); + final byte[] dataSplice = ((LaunchClassLoader) FoamFixTransformer.class.getClassLoader()).getClassBytes(className); return spliceClasses(data, dataSplice, className, targetClassName, methods); } catch (IOException e) { throw new RuntimeException(e); } } - public byte[] spliceClasses(final byte[] data, final byte[] dataSplice, final String className, final String targetClassName, final String... methods) { + public static byte[] spliceClasses(final byte[] data, final byte[] dataSplice, final String className, final String targetClassName, final String... methods) { // System.out.println("Splicing from " + className + " to " + targetClassName); final Set methodSet = Sets.newHashSet(methods); @@ -135,74 +143,97 @@ public String map(final String name) { return writer.toByteArray(); } - public byte[] transform(final String name, final String transformedName, final byte[] dataOrig) { - byte[] data = dataOrig; - if (data == null) - return data; - - if (FoamFixShared.config.geBlockPosPatch) { - if ("net.minecraft.util.math.Vec3i".equals(transformedName)) { - data = BlockPosPatch.patchVec3i(data); - } else { - data = BlockPosPatch.patchOtherClass(data, "net.minecraft.util.math.BlockPos$MutableBlockPos".equals(transformedName)); - } - } + private static final Multimap transformFunctions = HashMultimap.create(); + public static void init() { if (FoamFixShared.config.clBlockInfoPatch) { - if ("net.minecraftforge.client.model.pipeline.BlockInfo".equals(transformedName)) { - data = spliceClasses(data, "pl.asie.foamfix.coremod.blockinfo.BlockInfoPatch", transformedName, - "updateLightMatrix", "updateLightMatrix"); - } + transformFunctions.put("net.minecraftforge.client.model.pipeline.BlockInfo", new TransformerFunction() { + @Override + public byte[] transform(byte[] data, String transformedName) { + return spliceClasses(data, "pl.asie.foamfix.coremod.blockinfo.BlockInfoPatch", transformedName, + "updateLightMatrix", "updateLightMatrix"); + } + }); } if (FoamFixShared.config.geSmallPropertyStorage) { - if ("net.minecraft.block.state.BlockStateContainer".equals(transformedName)) { - data = spliceClasses(data, "pl.asie.foamfix.common.FoamyBlockStateContainer", transformedName, - "createState", "createState"); - } + transformFunctions.put("net.minecraft.block.state.BlockStateContainer", new TransformerFunction() { + @Override + public byte[] transform(byte[] data, String transformedName) { + return spliceClasses(data, "pl.asie.foamfix.common.FoamyBlockStateContainer", transformedName, + "createState", "createState"); + } + }); - if ("net.minecraftforge.common.property.ExtendedBlockState".equals(transformedName)) { - data = spliceClasses(data, "pl.asie.foamfix.common.FoamyExtendedBlockStateContainer", transformedName, - "createState", "createState"); - } + transformFunctions.put("net.minecraftforge.common.property.ExtendedBlockState", new TransformerFunction() { + @Override + public byte[] transform(byte[] data, String transformedName) { + return spliceClasses(data, "pl.asie.foamfix.common.FoamyExtendedBlockStateContainer", transformedName, + "createState", "createState"); + } + }); } if (FoamFixShared.config.geSmallLightingOptimize) { - if ("net.minecraft.world.World".equals(transformedName)) { - data = spliceClasses(data, "pl.asie.foamfix.coremod.WorldLightingPatch", transformedName, - "checkLightFor","func_180500_c"); - } + transformFunctions.put("net.minecraft.world.World", new TransformerFunction() { + @Override + public byte[] transform(byte[] data, String transformedName) { + return spliceClasses(data, "pl.asie.foamfix.coremod.WorldLightingPatch", transformedName, + "checkLightFor","func_180500_c"); + } + }); } if (FoamFixShared.config.geImmediateLightingUpdates) { - if ("net.minecraft.client.renderer.RenderGlobal".equals(transformedName)) { - data = spliceClasses(data, "pl.asie.foamfix.coremod.RenderGlobalImmediatePatch", transformedName, - "notifyLightSet","func_174959_b"); - } + transformFunctions.put("net.minecraft.client.renderer.RenderGlobal", new TransformerFunction() { + @Override + public byte[] transform(byte[] data, String transformedName) { + return spliceClasses(data, "pl.asie.foamfix.coremod.RenderGlobalImmediatePatch", transformedName, + "notifyLightSet","func_174959_b"); + } + }); } if (FoamFixShared.config.clDynamicItemModels) { - if ("net.minecraftforge.client.model.ItemLayerModel".equals(transformedName)) { - data = spliceClasses(data, "pl.asie.foamfix.client.FoamFixDynamicItemModels", transformedName, - "bake", "bake"); - } + transformFunctions.put("net.minecraftforge.client.model.ItemLayerModel", new TransformerFunction() { + @Override + public byte[] transform(byte[] data, String transformedName) { + return spliceClasses(data, "pl.asie.foamfix.client.FoamFixDynamicItemModels", transformedName, + "bake", "bake"); + } + }); } - if (FoamFixShared.config.clFasterResourceLoading) { - if ("net.minecraft.client.Minecraft".equals(transformedName)) { - data = replaceConstructor(data, transformedName, "net.minecraft.client.resources.DefaultResourcePack", - "pl.asie.foamfix.client.FoamyDefaultResourcePack", ""); + if (FoamFixShared.config.clFasterResourceLoading > 0) { + final String className = FoamyDefaultResourcePack.getClassName(); + transformFunctions.put("net.minecraft.client.Minecraft", new TransformerFunction() { + @Override + public byte[] transform(byte[] data, String transformedName) { + return replaceConstructor(data, transformedName, "net.minecraft.client.resources.DefaultResourcePack", + className, ""); + } + }); + } + } + + public byte[] transform(final String name, final String transformedName, final byte[] dataOrig) { + if (dataOrig == null) + return null; + + byte[] data = dataOrig; + + if (FoamFixShared.config.geBlockPosPatch) { + if ("net.minecraft.util.math.Vec3i".equals(transformedName)) { + data = BlockPosPatch.patchVec3i(data); + } else { + data = BlockPosPatch.patchOtherClass(data, "net.minecraft.util.math.BlockPos$MutableBlockPos".equals(transformedName)); } } - /* if ("net.minecraftforge.client.model.pipeline.VertexLighterSmoothAo".equals(transformedName)) { - data = spliceClasses(data, "pl.asie.foamfix.coremod.VertexLighterSmoothAoPatch", transformedName, - "updateLightmap", "setBlockPos", "lightmapCache"); - } */ + for (TransformerFunction function : transformFunctions.get(transformedName)) { + data = function.transform(data, transformedName); + } - /* if ("net.minecraft.client.Minecraft".equals(transformedName)) { - data = MinecraftPatch.patchMinecraft(data); - } */ return data; } } diff --git a/src/main/java/pl/asie/foamfix/coremod/TransformerFunction.java b/src/main/java/pl/asie/foamfix/coremod/TransformerFunction.java new file mode 100644 index 0000000..2a1ae1b --- /dev/null +++ b/src/main/java/pl/asie/foamfix/coremod/TransformerFunction.java @@ -0,0 +1,5 @@ +package pl.asie.foamfix.coremod; + +public interface TransformerFunction { + byte[] transform(byte[] data, String transformedName); +} diff --git a/src/main/java/pl/asie/foamfix/shared/FoamFixConfig.java b/src/main/java/pl/asie/foamfix/shared/FoamFixConfig.java index 8fbe249..93db81a 100644 --- a/src/main/java/pl/asie/foamfix/shared/FoamFixConfig.java +++ b/src/main/java/pl/asie/foamfix/shared/FoamFixConfig.java @@ -36,7 +36,7 @@ public class FoamFixConfig { public boolean lwWeakenResourceCache, lwDummyPackageManifestMap; public boolean clDeduplicate, clCleanRedundantModelRegistry, clDynamicItemModels; - public boolean clFasterResourceLoading; + public int clFasterResourceLoading; public boolean geBlacklistLibraryTransformers; public boolean geBlockPosPatch, clBlockInfoPatch, clTextureDoubleBuffering; public boolean geDynamicRegistrySizeScaling; @@ -72,7 +72,6 @@ public void init(File file, boolean isCoremod) { clDeduplicate = getBoolean("deduplicateModels", "client", true, "Enable deduplication of redundant objects in memory."); clDeduplicateRecursionLevel = config.getInt("deduplicateModelsMaxRecursion", "client", 6, 1, Integer.MAX_VALUE, "The maximum amount of levels of recursion for the deduplication process. Smaller values will deduplicate less data, but make the process run faster."); clCleanRedundantModelRegistry = getBoolean("clearDuplicateModelRegistry", "client", true, "Clears the baked models generated in the first pass *before* entering the second pass, instead of *after*. While this doesn't reduce memory usage in-game, it does reduce it noticeably during loading."); - clFasterResourceLoading = getBoolean("fasterResourceLoading", "client", true, "Slight optimizations to resource loading."); geDynamicRegistrySizeScaling = getBoolean("dynamicRegistrySizeScaling", "general", true, "Makes large FML registries scale their availability BitSets dynamically, saving ~48MB of RAM.", "(,13.19.1.2190)"); geImmediateLightingUpdates = getBoolean("immediateLightingUpdates", "expert", false, "Do not delay lighting updates over other types of updates."); @@ -86,6 +85,8 @@ public void init(File file, boolean isCoremod) { geSmallLightingOptimize = getBoolean("smallLightingOptimize", "experimental", true, "Not fully benchmarked, experimental minor lighting calculation code optimization - according to preliminary tests, it doesn't impact performance while reducing GC churn."); } + // clFasterResourceLoading = config.getInt("fasterResourceLoading", "client", 2, 0, 2, "Slight optimizations to resource loading. Set to 0 to disable, set to 1 to enable a more compatibility-friendly version in case you're having resource issues (missing textures, etc)."); + config.save(); } } diff --git a/src/main/java/pl/asie/foamfix/shared/FoamFixShared.java b/src/main/java/pl/asie/foamfix/shared/FoamFixShared.java index 0156dd4..b6c0754 100644 --- a/src/main/java/pl/asie/foamfix/shared/FoamFixShared.java +++ b/src/main/java/pl/asie/foamfix/shared/FoamFixShared.java @@ -29,4 +29,12 @@ public class FoamFixShared { public static final FoamFixConfig config = new FoamFixConfig(); public static boolean coremodEnabled = false; public static int ramSaved = 0; + + public static boolean hasOptifine() { + try { + return Class.forName("optifine.OptiFineTweaker") != null; + } catch (ClassNotFoundException e) { + return false; + } + } }