Skip to content

Commit

Permalink
FoamFix 0.6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
asiekierka committed Feb 21, 2017
1 parent 4976960 commit 913987a
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 72 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/pl/asie/foamfix/ProxyClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,15 @@ 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");
Field f3 = ReflectionHelper.findField(DefaultResourcePack.class, "resourceIndex", "field_188549_b");
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) {
Expand Down
37 changes: 21 additions & 16 deletions src/main/java/pl/asie/foamfix/client/FoamyDefaultResourcePack.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -14,20 +17,19 @@
import java.util.concurrent.TimeUnit;

public class FoamyDefaultResourcePack extends DefaultResourcePack {
// private final Cache<ResourceLocation, Boolean> cache =
// CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
private final Set<ResourceLocation> foundResources = new HashSet<>();
private final Cache<ResourceLocation, Boolean> cache =
CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
private final ResourceIndex resourceIndex;

public FoamyDefaultResourcePack(ResourceIndex resourceIndexIn) {
super(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;
}

Expand All @@ -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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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<ResourceLocation> 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;
}
}
2 changes: 2 additions & 0 deletions src/main/java/pl/asie/foamfix/coremod/FoamFixCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public void injectData(final Map<String, Object> data) {
classLoader.addTransformerExclusion("oshi.");
classLoader.addTransformerExclusion("scala.");
}

FoamFixTransformer.init();
}

public String getAccessTransformerClass() {
Expand Down
133 changes: 82 additions & 51 deletions src/main/java/pl/asie/foamfix/coremod/FoamFixTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.<init> 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<String> methodSet = Sets.newHashSet(methods);
Expand Down Expand Up @@ -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<String, TransformerFunction> 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", "<init>");
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, "<init>");
}
});
}
}

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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package pl.asie.foamfix.coremod;

public interface TransformerFunction {
byte[] transform(byte[] data, String transformedName);
}
5 changes: 3 additions & 2 deletions src/main/java/pl/asie/foamfix/shared/FoamFixConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.");

Expand All @@ -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();
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/pl/asie/foamfix/shared/FoamFixShared.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}

0 comments on commit 913987a

Please sign in to comment.