Dashloader: use ASM instead of wrapping the class
This commit is contained in:
parent
649ca78d6c
commit
b336a8cb36
|
@ -1,6 +1,6 @@
|
||||||
package io.gitlab.jfronny.respackopts;
|
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.ConfigBranch;
|
||||||
import io.gitlab.jfronny.respackopts.data.entry.ConfigEntry;
|
import io.gitlab.jfronny.respackopts.data.entry.ConfigEntry;
|
||||||
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
|
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
|
||||||
|
|
|
@ -3,7 +3,6 @@ package io.gitlab.jfronny.respackopts;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import io.gitlab.jfronny.libjf.data.WrappedPack;
|
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.DirRpo;
|
||||||
import io.gitlab.jfronny.respackopts.data.PackCapability;
|
import io.gitlab.jfronny.respackopts.data.PackCapability;
|
||||||
import io.gitlab.jfronny.respackopts.data.Respackmeta;
|
import io.gitlab.jfronny.respackopts.data.Respackmeta;
|
||||||
|
@ -54,8 +53,6 @@ public class Respackopts implements ClientModInitializer {
|
||||||
|
|
||||||
public static Starscript STAR_SCRIPT;
|
public static Starscript STAR_SCRIPT;
|
||||||
|
|
||||||
public static final Boolean DASHLOADER_PRESENT = FabricLoader.getInstance().isModLoaded("dashloader");
|
|
||||||
|
|
||||||
public static final Gson GSON;
|
public static final Gson GSON;
|
||||||
public static GuiFactory factory = new GuiFactory();
|
public static GuiFactory factory = new GuiFactory();
|
||||||
public static boolean forceRespackReload = false;
|
public static boolean forceRespackReload = false;
|
||||||
|
@ -101,7 +98,7 @@ public class Respackopts implements ClientModInitializer {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.error("Could not initialize config directory", e);
|
LOGGER.error("Could not initialize config directory", e);
|
||||||
}
|
}
|
||||||
if (DASHLOADER_PRESENT) DashLoaderCompat.hookDashLoader();
|
//if (DASHLOADER_PRESENT) DashLoaderCompat.hookDashLoader();
|
||||||
if (FabricLoader.getInstance().isDevelopmentEnvironment())
|
if (FabricLoader.getInstance().isDevelopmentEnvironment())
|
||||||
SAVE_ACTIONS.add(() -> LOGGER.info("Save"));
|
SAVE_ACTIONS.add(() -> LOGGER.info("Save"));
|
||||||
SAVE_ACTIONS.add(() -> {
|
SAVE_ACTIONS.add(() -> {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ package io.gitlab.jfronny.respackopts.integration;
|
||||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||||
import io.gitlab.jfronny.respackopts.Respackopts;
|
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.ConfigBuilder;
|
||||||
import me.shedaniel.clothconfig2.api.ConfigCategory;
|
import me.shedaniel.clothconfig2.api.ConfigCategory;
|
||||||
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
|
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,8 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"respackopts.mixins.json"
|
"respackopts.mixins.json",
|
||||||
|
"respackotps.dashloader.mixins.json"
|
||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.10.8",
|
"fabricloader": ">=0.10.8",
|
||||||
|
|
14
src/main/resources/respackotps.dashloader.mixins.json
Normal file
14
src/main/resources/respackotps.dashloader.mixins.json
Normal 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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user