Dashloader: use ASM instead of wrapping the class

This commit is contained in:
JFronny 2021-08-26 23:30:55 +02:00
parent 649ca78d6c
commit b336a8cb36
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
9 changed files with 149 additions and 55 deletions

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.respackopts;
import io.gitlab.jfronny.respackopts.integration.dashloader.DashLoaderCompat;
import io.gitlab.jfronny.respackopts.integration.DashLoaderCompat;
import io.gitlab.jfronny.respackopts.data.entry.ConfigBranch;
import io.gitlab.jfronny.respackopts.data.entry.ConfigEntry;
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;

View File

@ -3,7 +3,6 @@ package io.gitlab.jfronny.respackopts;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.gitlab.jfronny.libjf.data.WrappedPack;
import io.gitlab.jfronny.respackopts.integration.dashloader.DashLoaderCompat;
import io.gitlab.jfronny.respackopts.data.DirRpo;
import io.gitlab.jfronny.respackopts.data.PackCapability;
import io.gitlab.jfronny.respackopts.data.Respackmeta;
@ -54,8 +53,6 @@ public class Respackopts implements ClientModInitializer {
public static Starscript STAR_SCRIPT;
public static final Boolean DASHLOADER_PRESENT = FabricLoader.getInstance().isModLoaded("dashloader");
public static final Gson GSON;
public static GuiFactory factory = new GuiFactory();
public static boolean forceRespackReload = false;
@ -101,7 +98,7 @@ public class Respackopts implements ClientModInitializer {
} catch (IOException e) {
LOGGER.error("Could not initialize config directory", e);
}
if (DASHLOADER_PRESENT) DashLoaderCompat.hookDashLoader();
//if (DASHLOADER_PRESENT) DashLoaderCompat.hookDashLoader();
if (FabricLoader.getInstance().isDevelopmentEnvironment())
SAVE_ACTIONS.add(() -> LOGGER.info("Save"));
SAVE_ACTIONS.add(() -> {

View File

@ -0,0 +1,21 @@
package io.gitlab.jfronny.respackopts.integration;
import net.oskarstrom.dashloader.util.enums.DashCachePaths;
import java.io.IOException;
import java.nio.file.Files;
public class DashLoaderCompat {
public static boolean forceReload = false;
public static void injection() {
if (DashLoaderCompat.forceReload)
for (DashCachePaths value : DashCachePaths.values()) {
try {
Files.deleteIfExists(value.getPath());
} catch (IOException e) {
e.printStackTrace();
}
}
DashLoaderCompat.forceReload = false;
}
}

View File

@ -3,7 +3,6 @@ package io.gitlab.jfronny.respackopts.integration;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.integration.dashloader.DashLoaderCompat;
import me.shedaniel.clothconfig2.api.ConfigBuilder;
import me.shedaniel.clothconfig2.api.ConfigCategory;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;

View File

@ -1,19 +0,0 @@
package io.gitlab.jfronny.respackopts.integration.dashloader;
import net.oskarstrom.dashloader.DashLoader;
import java.lang.reflect.Field;
public class DashLoaderCompat {
public static boolean forceReload = false;
public static void hookDashLoader() {
try {
Field instance = DashLoader.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(null, new HackedDashLoader((DashLoader) instance.get(null)));
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}

View File

@ -1,29 +0,0 @@
package io.gitlab.jfronny.respackopts.integration.dashloader;
import net.oskarstrom.dashloader.DashLoader;
import net.oskarstrom.dashloader.util.enums.DashCachePaths;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collection;
public class HackedDashLoader extends DashLoader {
public HackedDashLoader(DashLoader previous) {
super(previous.getAssignedClassLoader().getParent());
initialize();
}
@Override
public void reload(Collection<String> resourcePacks) {
if (DashLoaderCompat.forceReload)
for (DashCachePaths value : DashCachePaths.values()) {
try {
Files.deleteIfExists(value.getPath());
} catch (IOException e) {
e.printStackTrace();
}
}
super.reload(resourcePacks);
DashLoaderCompat.forceReload = false;
}
}

View File

@ -0,0 +1,110 @@
package io.gitlab.jfronny.respackopts.mixin.dashloader;
import io.gitlab.jfronny.respackopts.Respackopts;
import net.fabricmc.loader.api.FabricLoader;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import org.spongepowered.asm.mixin.transformer.FabricMixinTransformerProxy;
import org.spongepowered.asm.transformers.MixinClassWriter;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
public class Plugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
if (FabricLoader.getInstance().isModLoaded("dashloader")) {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> classLoaderClass = classLoader.getClass();
Field delegateField = classLoaderClass.getDeclaredField("delegate");
delegateField.setAccessible(true);
Object delegate = delegateField.get(classLoader);
Class<?> delegateClass = delegate.getClass();
Field mixinTransformerField = delegateClass.getDeclaredField("mixinTransformer");
mixinTransformerField.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
Transformer mixinTransformer = (Transformer) unsafe.allocateInstance(Transformer.class);
mixinTransformer.delegate = (FabricMixinTransformerProxy) mixinTransformerField.get(delegate);
mixinTransformerField.set(delegate, mixinTransformer);
} catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
}
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return true;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
private static class Transformer extends FabricMixinTransformerProxy {
private FabricMixinTransformerProxy delegate;
@Override
public byte[] transformClassBytes(String name, String transformedName, byte[] basicClass) {
basicClass = delegate.transformClassBytes(name, transformedName, basicClass);
if (name.equals("net.oskarstrom.dashloader.DashLoader")) {
ClassNode klass = new ClassNode();
ClassReader reader = new ClassReader(basicClass);
reader.accept(klass, ClassReader.EXPAND_FRAMES);
boolean found = false;
for (MethodNode method : klass.methods) {
if (method.name.equals("reload")) {
method.instructions.insert(new MethodInsnNode(Opcodes.INVOKESTATIC, "io/gitlab/jfronny/respackopts/integration/dashloader/DashLoaderCompat", "injection", "()V"));
found = true;
}
}
if (!found) Respackopts.LOGGER.error("Could not hack into dashloader");
ClassWriter writer = new MixinClassWriter(reader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
klass.accept(writer);
basicClass = writer.toByteArray();
}
return basicClass;
}
}
}

View File

@ -23,7 +23,8 @@
]
},
"mixins": [
"respackopts.mixins.json"
"respackopts.mixins.json",
"respackotps.dashloader.mixins.json"
],
"depends": {
"fabricloader": ">=0.10.8",

View File

@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "io.gitlab.jfronny.respackopts.mixin.dashloader",
"plugin": "io.gitlab.jfronny.respackopts.mixin.dashloader.Plugin",
"compatibilityLevel": "JAVA_8",
"mixins": [
],
"client": [
],
"injectors": {
"defaultRequire": 1
}
}