aboutsummaryrefslogtreecommitdiff
path: root/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin
diff options
context:
space:
mode:
authorWyvest <45589059+Wyvest@users.noreply.github.com>2022-07-02 06:12:23 +0700
committerWyvest <45589059+Wyvest@users.noreply.github.com>2022-07-02 06:12:23 +0700
commitd4bb5a94308d4379ef3d6cc7b9221ea0d98ff051 (patch)
tree9bb9b53e2823f73084780673763504f4098bae69 /versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin
parentd2b1d57120bb51e76191302a58d935afe52b89df (diff)
downloadOneConfig-d4bb5a94308d4379ef3d6cc7b9221ea0d98ff051.tar.gz
OneConfig-d4bb5a94308d4379ef3d6cc7b9221ea0d98ff051.tar.bz2
OneConfig-d4bb5a94308d4379ef3d6cc7b9221ea0d98ff051.zip
Separate Minecraft dependant and non-dependant code
Diffstat (limited to 'versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin')
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java102
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java24
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java117
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java47
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java89
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider.java47
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/OptifineConfigHook.java22
-rw-r--r--versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/VigilantHook.java26
8 files changed, 474 insertions, 0 deletions
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java
new file mode 100644
index 0000000..52256ca
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java
@@ -0,0 +1,102 @@
+package cc.polyfrost.oneconfig.internal.plugin.asm;
+
+import cc.polyfrost.oneconfig.internal.plugin.asm.tweakers.NanoVGGLConfigTransformer;
+import cc.polyfrost.oneconfig.internal.plugin.asm.tweakers.VigilantTransformer;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import net.minecraft.launchwrapper.IClassTransformer;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.tree.ClassNode;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Taken from LWJGLTwoPointFive under The Unlicense
+ * <a href="https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/">https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/</a>
+ * <p>also half taken from asmworkspace by asbyth ty</p>
+ */
+@SuppressWarnings("unused")
+public class ClassTransformer implements IClassTransformer {
+ private static final Logger logger = LogManager.getLogger("OneConfig ASM");
+ private final Multimap<String, ITransformer> transformerMap = ArrayListMultimap.create();
+ private static final boolean outputBytecode = Boolean.parseBoolean(System.getProperty("debugBytecode", "false"));
+
+ public ClassTransformer() {
+ registerTransformer(new NanoVGGLConfigTransformer());
+ registerTransformer(new VigilantTransformer());
+ }
+
+ private void registerTransformer(ITransformer transformer) {
+ // loop through names of classes
+ for (String cls : transformer.getClassName()) {
+ // put the classes into the transformer map
+ transformerMap.put(cls, transformer);
+ }
+ }
+
+ @Override
+ public byte[] transform(String name, String transformedName, byte[] bytes) {
+ if (bytes == null) return null;
+
+ Collection<ITransformer> transformers = transformerMap.get(transformedName);
+ if (transformers.isEmpty()) return bytes;
+
+ ClassReader reader = new ClassReader(bytes);
+ ClassNode node = new ClassNode();
+ reader.accept(node, ClassReader.EXPAND_FRAMES);
+
+ for (ITransformer transformer : transformers) {
+ transformer.transform(transformedName, node);
+ }
+
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+ try {
+ node.accept(cw);
+ } catch (Throwable t) {
+ logger.error("Exception when transforming " + transformedName + " : " + t.getClass().getSimpleName());
+ t.printStackTrace();
+ }
+
+ if (outputBytecode) {
+ File bytecodeDirectory = new File("bytecode");
+ String transformedClassName;
+
+ // anonymous classes
+ if (transformedName.contains("$")) {
+ transformedClassName = transformedName.replace('$', '.') + ".class";
+ } else {
+ transformedClassName = transformedName + ".class";
+ }
+
+ if (!bytecodeDirectory.exists()) {
+ bytecodeDirectory.mkdirs();
+ }
+
+ File bytecodeOutput = new File(bytecodeDirectory, transformedClassName);
+
+ try {
+ if (!bytecodeOutput.exists()) {
+ bytecodeOutput.createNewFile();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ try (FileOutputStream os = new FileOutputStream(bytecodeOutput)) {
+ // write to the generated class to /run/bytecode/classfile.class
+ // with the class bytes from transforming
+ os.write(cw.toByteArray());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return cw.toByteArray();
+ }
+} \ No newline at end of file
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java
new file mode 100644
index 0000000..1bc50d1
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java
@@ -0,0 +1,24 @@
+package cc.polyfrost.oneconfig.internal.plugin.asm;
+
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.MethodNode;
+
+public interface ITransformer {
+ String[] getClassName();
+
+ void transform(String transformedName, ClassNode node);
+
+ default void clearInstructions(MethodNode methodNode) {
+ methodNode.instructions.clear();
+
+ // dont waste time clearing local variables if they're empty
+ if (!methodNode.localVariables.isEmpty()) {
+ methodNode.localVariables.clear();
+ }
+
+ // dont waste time clearing try-catches if they're empty
+ if (!methodNode.tryCatchBlocks.isEmpty()) {
+ methodNode.tryCatchBlocks.clear();
+ }
+ }
+}
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java
new file mode 100644
index 0000000..d302b9d
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java
@@ -0,0 +1,117 @@
+package cc.polyfrost.oneconfig.internal.plugin.asm;
+
+import cc.polyfrost.oneconfig.internal.init.OneConfigInit;
+import net.minecraft.launchwrapper.ITweaker;
+import net.minecraft.launchwrapper.Launch;
+import net.minecraft.launchwrapper.LaunchClassLoader;
+import net.minecraftforge.fml.relauncher.CoreModManager;
+import org.spongepowered.asm.launch.MixinBootstrap;
+import org.spongepowered.asm.launch.MixinTweaker;
+import org.spongepowered.asm.mixin.Mixins;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+
+public class OneConfigTweaker implements ITweaker {
+
+ public OneConfigTweaker() {
+ for (URL url : Launch.classLoader.getSources()) {
+ doMagicMixinStuff(url);
+ }
+ }
+
+ private void doMagicMixinStuff(URL url) {
+ try {
+ URI uri = url.toURI();
+ if (Objects.equals(uri.getScheme(), "file")) {
+ File file = new File(uri);
+ if (file.exists() && file.isFile()) {
+ try (JarFile jarFile = new JarFile(file)) {
+ if (jarFile.getManifest() != null) {
+ Attributes attributes = jarFile.getManifest().getMainAttributes();
+ String tweakerClass = attributes.getValue("TweakClass");
+ if (Objects.equals(tweakerClass, "cc.polyfrost.oneconfigwrapper.OneConfigWrapper")) {
+ CoreModManager.getIgnoredMods().remove(file.getName());
+ CoreModManager.getReparseableCoremods().add(file.getName());
+ String mixinConfig = attributes.getValue("MixinConfigs");
+ if (mixinConfig != null) {
+ try {
+ try {
+ List<String> tweakClasses = (List<String>) Launch.blackboard.get("TweakClasses"); // tweak classes before other mod trolling
+ if (tweakClasses.contains("org.spongepowered.asm.launch.MixinTweaker")) { // if there's already a mixin tweaker, we'll just load it like "usual"
+ new MixinTweaker(); // also we might not need to make a new mixin tweawker all the time but im just making sure
+ } else if (!Launch.blackboard.containsKey("mixin.initialised")) { // if there isnt, we do our own trolling
+ List<ITweaker> tweaks = (List<ITweaker>) Launch.blackboard.get("Tweaks");
+ tweaks.add(new MixinTweaker());
+ }
+ } catch (Exception ignored) {
+ // if it fails i *think* we can just ignore it
+ }
+ MixinBootstrap.getPlatform().addContainer(uri);
+ } catch (Exception ignored) {
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception ignored) {
+
+ }
+ }
+
+ @Override
+ public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
+ MixinBootstrap.init();
+ boolean captureNext = false;
+ for (String arg : args) {
+ if (captureNext) {
+ Mixins.addConfiguration(arg);
+ }
+ captureNext = "--mixin".equals(arg);
+ }
+ }
+
+ @Override
+ public void injectIntoClassLoader(LaunchClassLoader classLoader) {
+ removeLWJGLException();
+ Launch.classLoader.registerTransformer(ClassTransformer.class.getName());
+ OneConfigInit.initialize(new String[]{});
+ Launch.blackboard.put("oneconfig.init.initialized", true);
+ Launch.classLoader.addClassLoaderExclusion("cc.polyfrost.oneconfig.internal.plugin.asm.");
+ }
+
+ /**
+ * Taken from LWJGLTwoPointFive under The Unlicense
+ * <a href="https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/">https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/</a>
+ */
+ private void removeLWJGLException() {
+ try {
+ Field f_exceptions = LaunchClassLoader.class.getDeclaredField("classLoaderExceptions");
+ f_exceptions.setAccessible(true);
+ Set<String> exceptions = (Set<String>) f_exceptions.get(Launch.classLoader);
+ exceptions.remove("org.lwjgl.");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String getLaunchTarget() {
+ return null;
+ }
+
+ @Override
+ public String[] getLaunchArguments() {
+ return new String[0];
+ }
+} \ No newline at end of file
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java
new file mode 100644
index 0000000..bbbf4a1
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java
@@ -0,0 +1,47 @@
+package cc.polyfrost.oneconfig.internal.plugin.asm.tweakers;
+
+import cc.polyfrost.oneconfig.internal.plugin.asm.ITransformer;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.*;
+
+/**
+ * Taken from LWJGLTwoPointFive under The Unlicense
+ * <a href="https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/">https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/</a>
+ */
+public class NanoVGGLConfigTransformer implements ITransformer {
+ @Override
+ public String[] getClassName() {
+ return new String[]{"org.lwjgl.nanovg.NanoVGGLConfig"};
+ }
+
+ @Override
+ public void transform(String transformedName, ClassNode node) {
+ for (MethodNode method : node.methods) {
+ if (method.name.equals("configGL")) {
+ InsnList list = new InsnList();
+
+ list.add(new VarInsnNode(Opcodes.LLOAD, 0));
+ list.add(new TypeInsnNode(Opcodes.NEW, "cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider"));
+ list.add(new InsnNode(Opcodes.DUP));
+ list.add(new MethodInsnNode(
+ Opcodes.INVOKESPECIAL,
+ "cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider",
+ "<init>",
+ "()V",
+ false
+ ));
+ list.add(new MethodInsnNode(
+ Opcodes.INVOKESTATIC,
+ "org/lwjgl/nanovg/NanoVGGLConfig",
+ "config",
+ "(JLorg/lwjgl/system/FunctionProvider;)V",
+ false
+ ));
+ list.add(new InsnNode(Opcodes.RETURN));
+
+ clearInstructions(method);
+ method.instructions.insert(list);
+ }
+ }
+ }
+}
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java
new file mode 100644
index 0000000..8dd60cf
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java
@@ -0,0 +1,89 @@
+package cc.polyfrost.oneconfig.internal.plugin.asm.tweakers;
+
+import cc.polyfrost.oneconfig.internal.plugin.asm.ITransformer;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.*;
+
+import java.io.File;
+
+public class VigilantTransformer implements ITransformer {
+
+ @Override
+ public String[] getClassName() {
+ return new String[]{"gg.essential.vigilance.Vigilant"};
+ }
+
+ /**
+ * If anything here is changed, edit the corresponding method in OneConfigMixinPlugin!
+ */
+ @Override
+ public void transform(String transformedName, ClassNode node) {
+ if (!node.interfaces.contains("cc/polyfrost/oneconfig/config/compatibility/vigilance/VigilantAccessor")) {
+ node.fields.add(new FieldNode(Opcodes.ACC_PUBLIC, "oneconfig$config", "Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;", null, null));
+ node.fields.add(new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "oneconfig$file", Type.getDescriptor(File.class), null, null));
+
+ node.interfaces.add("cc/polyfrost/oneconfig/config/compatibility/vigilance/VigilantAccessor");
+ MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC, "getPropertyCollector", "()Lgg/essential/vigilance/data/PropertyCollector;", null, null);
+ LabelNode labelNode = new LabelNode();
+ methodNode.instructions.add(labelNode);
+ methodNode.instructions.add(new LineNumberNode(421421, labelNode));
+ methodNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ methodNode.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "propertyCollector", "Lgg/essential/vigilance/data/PropertyCollector;"));
+ methodNode.instructions.add(new InsnNode(Opcodes.ARETURN));
+ node.methods.add(methodNode);
+
+ MethodNode methodNode2 = new MethodNode(Opcodes.ACC_PUBLIC, "handleOneConfigDependency", "(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V", null, null);
+ LabelNode labelNode2 = new LabelNode();
+ LabelNode labelNode3 = new LabelNode();
+ LabelNode labelNode4 = new LabelNode();
+ methodNode2.instructions.add(labelNode2);
+ methodNode2.instructions.add(new LineNumberNode(15636436, labelNode2));
+ methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ methodNode2.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$config", "Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;"));
+
+ methodNode2.instructions.add(new JumpInsnNode(Opcodes.IFNULL, labelNode4));
+
+ methodNode2.instructions.add(labelNode3);
+ methodNode2.instructions.add(new LineNumberNode(15636437, labelNode3));
+ methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ methodNode2.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$config", "Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;"));
+ methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
+ methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
+ methodNode2.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "cc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig", "addDependency", "(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V", false));
+
+ methodNode2.instructions.add(labelNode4);
+ methodNode2.instructions.add(new LineNumberNode(15636438, labelNode4));
+ methodNode2.instructions.add(new InsnNode(Opcodes.RETURN));
+ node.methods.add(methodNode2);
+
+ for (MethodNode method : node.methods) {
+ if (method.name.equals("initialize")) {
+ InsnList list = new InsnList();
+ list.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ list.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ list.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ list.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$file", Type.getDescriptor(File.class)));
+ list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "cc/polyfrost/oneconfig/internal/plugin/hooks/VigilantHook", "returnNewConfig", "(Lgg/essential/vigilance/Vigilant;Ljava/io/File;)Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;", false));
+ list.add(new FieldInsnNode(Opcodes.PUTFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$config", "Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;"));
+ method.instructions.insertBefore(method.instructions.getLast().getPrevious(), list);
+ } else if (method.name.equals("addDependency") && method.desc.equals("(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V")) {
+ InsnList list = new InsnList();
+
+ list.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ list.add(new VarInsnNode(Opcodes.ALOAD, 1));
+ list.add(new VarInsnNode(Opcodes.ALOAD, 2));
+ list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "gg/essential/vigilance/Vigilant", "handleOneConfigDependency", "(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V", false));
+
+ method.instructions.insertBefore(method.instructions.getLast().getPrevious(), list);
+ } else if (method.name.equals("<init>") && method.desc.equals("(Ljava/io/File;Ljava/lang/String;Lgg/essential/vigilance/data/PropertyCollector;Lgg/essential/vigilance/data/SortingBehavior;)V")) {
+ InsnList list = new InsnList();
+ list.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ list.add(new VarInsnNode(Opcodes.ALOAD, 1));
+ list.add(new FieldInsnNode(Opcodes.PUTFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$file", Type.getDescriptor(File.class)));
+ method.instructions.insertBefore(method.instructions.getLast().getPrevious(), list);
+ }
+ }
+ }
+ }
+}
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider.java
new file mode 100644
index 0000000..297c84d
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider.java
@@ -0,0 +1,47 @@
+package cc.polyfrost.oneconfig.internal.plugin.hooks;
+
+import org.lwjgl.system.FunctionProvider;
+
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+
+/**
+ * Taken from LWJGLTwoPointFive under The Unlicense
+ * <a href="https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/">https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/</a>
+ */
+public class Lwjgl2FunctionProvider implements FunctionProvider {
+
+ private static final Class<?> GLContext;
+ private final Method m_getFunctionAddress;
+
+ static {
+ try {
+ GLContext = Class.forName("org.lwjgl.opengl.GLContext");
+ } catch (Throwable t) {
+ throw new RuntimeException("Unable to initialize LWJGL2FunctionProvider", t);
+ }
+ }
+
+ public Lwjgl2FunctionProvider() {
+ try {
+ m_getFunctionAddress = GLContext.getDeclaredMethod("getFunctionAddress", String.class);
+ m_getFunctionAddress.setAccessible(true);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public long getFunctionAddress(CharSequence functionName) {
+ try {
+ return (long) m_getFunctionAddress.invoke(null, functionName.toString());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public long getFunctionAddress(ByteBuffer byteBuffer) {
+ throw new UnsupportedOperationException();
+ }
+} \ No newline at end of file
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/OptifineConfigHook.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/OptifineConfigHook.java
new file mode 100644
index 0000000..dea68cf
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/OptifineConfigHook.java
@@ -0,0 +1,22 @@
+package cc.polyfrost.oneconfig.internal.plugin.hooks;
+
+import cc.polyfrost.oneconfig.gui.OneConfigGui;
+import cc.polyfrost.oneconfig.platform.Platform;
+import cc.polyfrost.oneconfig.utils.gui.GuiUtils;
+
+import java.util.Optional;
+
+public class OptifineConfigHook {
+
+ public static boolean shouldNotApplyFastRender() {
+ if (Platform.getGuiPlatform().getCurrentScreen() instanceof OneConfigGui) {
+ return true;
+ }
+ for (Optional screen : GuiUtils.getScreenQueue()) {
+ if (screen.isPresent() && screen.get() instanceof OneConfigGui) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/VigilantHook.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/VigilantHook.java
new file mode 100644
index 0000000..a012773
--- /dev/null
+++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/VigilantHook.java
@@ -0,0 +1,26 @@
+package cc.polyfrost.oneconfig.internal.plugin.hooks;
+
+import cc.polyfrost.oneconfig.config.compatibility.vigilance.VigilanceConfig;
+import cc.polyfrost.oneconfig.config.data.Mod;
+import cc.polyfrost.oneconfig.config.data.ModType;
+import cc.polyfrost.oneconfig.internal.config.core.ConfigCore;
+import cc.polyfrost.oneconfig.platform.Platform;
+import gg.essential.vigilance.Vigilant;
+
+import java.io.File;
+
+@SuppressWarnings("unused")
+public class VigilantHook {
+ public static VigilanceConfig returnNewConfig(Vigilant vigilant, File file) {
+ if (vigilant != null && Platform.getInstance().isCallingFromMinecraftThread()) {
+ String name = !vigilant.getGuiTitle().equals("Settings") ? vigilant.getGuiTitle() : !Platform.getLoaderPlatform().hasActiveModContainer() ? "Unknown" : Platform.getLoaderPlatform().getActiveModContainer().name;
+ if (name.equals("OneConfig")) name = "Essential";
+ String finalName = name;
+ // duplicate fix
+ if (ConfigCore.mods.stream().anyMatch(mod -> mod.name.equals(finalName))) return null;
+ return new VigilanceConfig(new Mod(name, ModType.THIRD_PARTY), file.getAbsolutePath(), vigilant);
+ } else {
+ return null;
+ }
+ }
+}