aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/moe/nea/firmament/init
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/moe/nea/firmament/init')
-rw-r--r--src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java324
-rw-r--r--src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java75
-rw-r--r--src/main/java/moe/nea/firmament/init/EarlyRiser.java3
-rw-r--r--src/main/java/moe/nea/firmament/init/HandledScreenRiser.java114
-rw-r--r--src/main/java/moe/nea/firmament/init/Intermediary.java115
-rw-r--r--src/main/java/moe/nea/firmament/init/ItemColorsSodiumRiser.java64
-rw-r--r--src/main/java/moe/nea/firmament/init/MixinPlugin.java103
-rw-r--r--src/main/java/moe/nea/firmament/init/RiserUtils.java7
-rw-r--r--src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java181
9 files changed, 458 insertions, 528 deletions
diff --git a/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java
index 9b891a4..07e4549 100644
--- a/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java
+++ b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java
@@ -1,6 +1,9 @@
package moe.nea.firmament.init;
+import moe.nea.firmament.util.ErrorUtil;
+import moe.nea.firmament.util.compatloader.ICompatMeta;
+
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -16,160 +19,171 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class AutoDiscoveryPlugin {
- private static final List<AutoDiscoveryPlugin> mixinPlugins = new ArrayList<>();
-
- public static List<AutoDiscoveryPlugin> getMixinPlugins() {
- return mixinPlugins;
- }
-
- private String mixinPackage;
-
- public void setMixinPackage(String mixinPackage) {
- this.mixinPackage = mixinPackage;
- mixinPlugins.add(this);
- }
-
- /**
- * Resolves the base class root for a given class URL. This resolves either the JAR root, or the class file root.
- * In either case the return value of this + the class name will resolve back to the original class url, or to other
- * class urls for other classes.
- */
- public URL getBaseUrlForClassUrl(URL classUrl) {
- String string = classUrl.toString();
- if (classUrl.getProtocol().equals("jar")) {
- try {
- return new URL(string.substring(4).split("!")[0]);
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
- if (string.endsWith(".class")) {
- try {
- return new URL(string.replace("\\", "/")
- .replace(getClass().getCanonicalName()
- .replace(".", "/") + ".class", ""));
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
- return classUrl;
- }
-
- /**
- * Get the package that contains all the mixins. This value is set using {@link #setMixinPackage}.
- */
- public String getMixinPackage() {
- return mixinPackage;
- }
-
- /**
- * Get the path inside the class root to the mixin package
- */
- public String getMixinBaseDir() {
- return mixinPackage.replace(".", "/");
- }
-
- /**
- * A list of all discovered mixins.
- */
- private List<String> mixins = null;
-
- /**
- * Try to add mixin class ot the mixins based on the filepath inside of the class root.
- * Removes the {@code .class} file suffix, as well as the base mixin package.
- * <p><b>This method cannot be called after mixin initialization.</p>
- *
- * @param className the name or path of a class to be registered as a mixin.
- */
- public void tryAddMixinClass(String className) {
- if (!className.endsWith(".class")) return;
- String norm = (className.substring(0, className.length() - ".class".length()))
- .replace("\\", "/")
- .replace("/", ".");
- if (norm.startsWith(getMixinPackage() + ".") && !norm.endsWith(".")) {
- mixins.add(norm.substring(getMixinPackage().length() + 1));
- }
- }
-
- private void tryDiscoverFromContentFile(URL url) {
- Path file;
- try {
- file = Paths.get(getBaseUrlForClassUrl(url).toURI());
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
- System.out.println("Base directory found at " + file);
- if (!Files.exists(file)) {
- System.out.println("Skipping non-existing mixin root: " + file);
- return;
- }
- if (Files.isDirectory(file)) {
- walkDir(file);
- } else {
- walkJar(file);
- }
- System.out.println("Found mixins: " + mixins);
-
- }
-
- /**
- * Search through the JAR or class directory to find mixins contained in {@link #getMixinPackage()}
- */
- public List<String> getMixins() {
- if (mixins != null) return mixins;
- System.out.println("Trying to discover mixins");
- mixins = new ArrayList<>();
- URL classUrl = getClass().getProtectionDomain().getCodeSource().getLocation();
- System.out.println("Found classes at " + classUrl);
- tryDiscoverFromContentFile(classUrl);
- var classRoots = System.getProperty("firmament.classroots");
- if (classRoots != null && !classRoots.isBlank()) {
- System.out.println("Found firmament class roots: " + classRoots);
- for (String s : classRoots.split(File.pathSeparator)) {
- if (s.isBlank()) {
- continue;
- }
- try {
- tryDiscoverFromContentFile(new File(s).toURI().toURL());
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
- }
- return mixins;
- }
-
- /**
- * Search through directory for mixin classes based on {@link #getMixinBaseDir}.
- *
- * @param classRoot The root directory in which classes are stored for the default package.
- */
- private void walkDir(Path classRoot) {
- System.out.println("Trying to find mixins from directory");
- var path = classRoot.resolve(getMixinBaseDir());
- if (!Files.exists(path)) return;
- try (Stream<Path> classes = Files.walk(path)) {
- classes.map(it -> classRoot.relativize(it).toString())
- .forEach(this::tryAddMixinClass);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Read through a JAR file, trying to find all mixins inside.
- */
- private void walkJar(Path file) {
- System.out.println("Trying to find mixins from jar file");
- try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(file))) {
- ZipEntry next;
- while ((next = zis.getNextEntry()) != null) {
- tryAddMixinClass(next.getName());
- zis.closeEntry();
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
+ public static List<String> getDefaultAllMixinClassesFQNs() {
+ var defaultName = "moe.nea.firmament.mixins";
+ var plugin = new AutoDiscoveryPlugin();
+ plugin.setMixinPackage(defaultName);
+ var mixins = plugin.getMixins();
+ return mixins.stream().map(it -> defaultName + "." + it).toList();
+ }
+
+ // TODO: remove println
+
+ private static final List<AutoDiscoveryPlugin> mixinPlugins = new ArrayList<>();
+
+ public static List<AutoDiscoveryPlugin> getMixinPlugins() {
+ return mixinPlugins;
+ }
+
+ private String mixinPackage;
+
+ public void setMixinPackage(String mixinPackage) {
+ this.mixinPackage = mixinPackage;
+ mixinPlugins.add(this);
+ }
+
+ /**
+ * Resolves the base class root for a given class URL. This resolves either the JAR root, or the class file root.
+ * In either case the return value of this + the class name will resolve back to the original class url, or to other
+ * class urls for other classes.
+ */
+ public URL getBaseUrlForClassUrl(URL classUrl) {
+ String string = classUrl.toString();
+ if (classUrl.getProtocol().equals("jar")) {
+ try {
+ return new URL(string.substring(4).split("!")[0]);
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ if (string.endsWith(".class")) {
+ try {
+ return new URL(string.replace("\\", "/")
+ .replace(getClass().getCanonicalName()
+ .replace(".", "/") + ".class", ""));
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return classUrl;
+ }
+
+ /**
+ * Get the package that contains all the mixins. This value is set using {@link #setMixinPackage}.
+ */
+ public String getMixinPackage() {
+ return mixinPackage;
+ }
+
+ /**
+ * Get the path inside the class root to the mixin package
+ */
+ public String getMixinBaseDir() {
+ return mixinPackage.replace(".", "/");
+ }
+
+ /**
+ * A list of all discovered mixins.
+ */
+ private List<String> mixins = null;
+
+ /**
+ * Try to add mixin class ot the mixins based on the filepath inside of the class root.
+ * Removes the {@code .class} file suffix, as well as the base mixin package.
+ * <p><b>This method cannot be called after mixin initialization.</p>
+ *
+ * @param className the name or path of a class to be registered as a mixin.
+ */
+ public void tryAddMixinClass(String className) {
+ if (!className.endsWith(".class")) return;
+ String norm = (className.substring(0, className.length() - ".class".length()))
+ .replace("\\", "/")
+ .replace("/", ".");
+ if (norm.startsWith(getMixinPackage() + ".") && !norm.endsWith(".") && ICompatMeta.Companion.shouldLoad(norm)) {
+ mixins.add(norm.substring(getMixinPackage().length() + 1));
+ }
+ }
+
+ private void tryDiscoverFromContentFile(URL url) {
+ Path file;
+ try {
+ file = Paths.get(getBaseUrlForClassUrl(url).toURI());
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ System.out.println("Base directory found at " + file);
+ if (!Files.exists(file)) {
+ System.out.println("Skipping non-existing mixin root: " + file);
+ return;
+ }
+ if (Files.isDirectory(file)) {
+ walkDir(file);
+ } else {
+ walkJar(file);
+ }
+ System.out.println("Found mixins: " + mixins);
+
+ }
+
+ /**
+ * Search through the JAR or class directory to find mixins contained in {@link #getMixinPackage()}
+ */
+ public List<String> getMixins() {
+ if (mixins != null) return mixins;
+ try {
+ System.out.println("Trying to discover mixins");
+ mixins = new ArrayList<>();
+ URL classUrl = getClass().getProtectionDomain().getCodeSource().getLocation();
+ System.out.println("Found classes at " + classUrl);
+ tryDiscoverFromContentFile(classUrl);
+ var classRoots = System.getProperty("firmament.classroots");
+ if (classRoots != null && !classRoots.isBlank()) {
+ System.out.println("Found firmament class roots: " + classRoots);
+ for (String s : classRoots.split(File.pathSeparator)) {
+ if (s.isBlank()) {
+ continue;
+ }
+ tryDiscoverFromContentFile(new File(s).toURI().toURL());
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ return mixins;
+ }
+
+ /**
+ * Search through directory for mixin classes based on {@link #getMixinBaseDir}.
+ *
+ * @param classRoot The root directory in which classes are stored for the default package.
+ */
+ private void walkDir(Path classRoot) {
+ System.out.println("Trying to find mixins from directory");
+ var path = classRoot.resolve(getMixinBaseDir());
+ if (!Files.exists(path)) return;
+ try (Stream<Path> classes = Files.walk(path)) {
+ classes.map(it -> classRoot.relativize(it).toString())
+ .forEach(this::tryAddMixinClass);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Read through a JAR file, trying to find all mixins inside.
+ */
+ private void walkJar(Path file) {
+ System.out.println("Trying to find mixins from jar file");
+ try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(file))) {
+ ZipEntry next;
+ while ((next = zis.getNextEntry()) != null) {
+ tryAddMixinClass(next.getName());
+ zis.closeEntry();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java b/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java
deleted file mode 100644
index d60e3e7..0000000
--- a/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package moe.nea.firmament.init;
-
-import me.shedaniel.mm.api.ClassTinkerers;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.InsnNode;
-import org.objectweb.asm.tree.MethodInsnNode;
-import org.objectweb.asm.tree.MethodNode;
-import org.objectweb.asm.tree.VarInsnNode;
-
-import java.lang.reflect.Modifier;
-import java.util.Objects;
-
-public class ClientPlayerRiser extends RiserUtils {
- @IntermediaryName(net.minecraft.entity.player.PlayerEntity.class)
- String PlayerEntity;
- @IntermediaryName(net.minecraft.world.World.class)
- String World;
- String GameProfile = "com.mojang.authlib.GameProfile";
- @IntermediaryName(net.minecraft.util.math.BlockPos.class)
- String BlockPos;
- @IntermediaryName(net.minecraft.client.network.AbstractClientPlayerEntity.class)
- String AbstractClientPlayerEntity;
- String GuiPlayer = "moe.nea.firmament.gui.entity.GuiPlayer";
- // World world, BlockPos pos, float yaw, GameProfile gameProfile
- Type constructorDescriptor = Type.getMethodType(Type.VOID_TYPE, getTypeForClassName(World), getTypeForClassName(BlockPos), Type.FLOAT_TYPE, getTypeForClassName(GameProfile));
-
-
- private void mapClassNode(ClassNode classNode, Type superClass) {
- for (MethodNode method : classNode.methods) {
- if (Objects.equals(method.name, "<init>") && Type.getMethodType(method.desc).equals(constructorDescriptor)) {
- modifyConstructor(method, superClass);
- return;
- }
- }
- var node = new MethodNode(Opcodes.ASM9, "<init>", constructorDescriptor.getDescriptor(), null, null);
- classNode.methods.add(node);
- modifyConstructor(node, superClass);
- }
-
-
- private void modifyConstructor(MethodNode method, Type superClass) {
- method.access = (method.access | Modifier.PUBLIC) & ~Modifier.PRIVATE & ~Modifier.PROTECTED;
- if (method.instructions.size() != 0) return; // Some other mod has already made a constructor here
-
- // World world, BlockPos pos, float yaw, GameProfile gameProfile
- // ALOAD this
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
-
- // ALOAD World
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
-
- // ALOAD BlockPos
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
-
- // ALOAD yaw
- method.instructions.add(new VarInsnNode(Opcodes.FLOAD, 3));
-
- // ALOAD gameProfile
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 4));
-
- // Call super
- method.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, superClass.getInternalName(), "<init>", constructorDescriptor.getDescriptor(), false));
-
- // Return
- method.instructions.add(new InsnNode(Opcodes.RETURN));
- }
-
- @Override
- public void addTinkerers() {
- ClassTinkerers.addTransformation(AbstractClientPlayerEntity, it -> mapClassNode(it, getTypeForClassName(PlayerEntity)), true);
- ClassTinkerers.addTransformation(GuiPlayer, it -> mapClassNode(it, getTypeForClassName(AbstractClientPlayerEntity)), true);
- }
-}
diff --git a/src/main/java/moe/nea/firmament/init/EarlyRiser.java b/src/main/java/moe/nea/firmament/init/EarlyRiser.java
index 9734e94..ae26bd7 100644
--- a/src/main/java/moe/nea/firmament/init/EarlyRiser.java
+++ b/src/main/java/moe/nea/firmament/init/EarlyRiser.java
@@ -4,9 +4,8 @@ package moe.nea.firmament.init;
public class EarlyRiser implements Runnable {
@Override
public void run() {
- new ClientPlayerRiser().addTinkerers();
new HandledScreenRiser().addTinkerers();
new SectionBuilderRiser().addTinkerers();
- new ItemColorsSodiumRiser().addTinkerers();
+// TODO: new ItemColorsSodiumRiser().addTinkerers();
}
}
diff --git a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java
index 355a666..98be517 100644
--- a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java
+++ b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java
@@ -2,8 +2,13 @@
package moe.nea.firmament.init;
import me.shedaniel.mm.api.ClassTinkerers;
-import net.minecraft.client.gui.Element;
-import net.minecraft.client.gui.ParentElement;
+import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
+import net.minecraft.client.input.CharacterEvent;
+import net.minecraft.client.input.KeyEvent;
+import net.minecraft.client.input.MouseButtonEvent;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
@@ -20,30 +25,46 @@ import java.lang.reflect.Modifier;
import java.util.function.Consumer;
public class HandledScreenRiser extends RiserUtils {
- @IntermediaryName(net.minecraft.client.gui.screen.Screen.class)
- String Screen;
- @IntermediaryName(net.minecraft.client.gui.screen.ingame.HandledScreen.class)
- String HandledScreen;
- Type mouseScrolledDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE);
- String mouseScrolled = remapper.mapMethodName("intermediary", "net.minecraft.class_364", "method_25401",
- mouseScrolledDesc.getDescriptor());
- // boolean keyReleased(int keyCode, int scanCode, int modifiers)
- Type keyReleasedDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.INT_TYPE);
- String keyReleased = remapper.mapMethodName("intermediary", Intermediary.<Element>className(),
- Intermediary.methodName(Element::keyReleased),
- keyReleasedDesc.getDescriptor());
- // public boolean charTyped(char chr, int modifiers)
- Type charTypedDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.CHAR_TYPE, Type.INT_TYPE);
- String charTyped = remapper.mapMethodName("intermediary", Intermediary.<Element>className(),
- Intermediary.methodName(Element::charTyped),
- charTypedDesc.getDescriptor());
+ Intermediary.InterClass Screen = Intermediary.<Screen>intermediaryClass();
+ Intermediary.InterClass KeyInput = Intermediary.<KeyEvent>intermediaryClass();
+ Intermediary.InterClass CharInput = Intermediary.<CharacterEvent>intermediaryClass();
+ Intermediary.InterClass HandledScreen = Intermediary.<AbstractContainerScreen>intermediaryClass();
+ Intermediary.InterClass AbstractContainerEventHandler = Intermediary.<AbstractContainerEventHandler>intermediaryClass();
+ Intermediary.InterClass MouseButtonEvent = Intermediary.<MouseButtonEvent>intermediaryClass();
+ Intermediary.InterMethod mouseScrolled = Intermediary.intermediaryMethod(
+ GuiEventListener::mouseScrolled,
+ Intermediary.ofClass(boolean.class),
+ Intermediary.ofClass(double.class),
+ Intermediary.ofClass(double.class),
+ Intermediary.ofClass(double.class),
+ Intermediary.ofClass(double.class)
+ );
+ Intermediary.InterMethod mouseClickedScreen = Intermediary.intermediaryMethod(
+ //onMouseClicked$firmament
+ GuiEventListener::mouseClicked,
+ Intermediary.ofClass(boolean.class),
+ MouseButtonEvent,
+ Intermediary.ofClass(boolean.class)
+ );
+ ;
+ Intermediary.InterMethod keyReleased = Intermediary.intermediaryMethod(
+ GuiEventListener::keyReleased,
+ Intermediary.ofClass(boolean.class),
+ KeyInput
+ );
+ Intermediary.InterMethod charTyped = Intermediary.intermediaryMethod(
+ GuiEventListener::charTyped,
+ Intermediary.ofClass(boolean.class),
+ CharInput
+ );
@Override
public void addTinkerers() {
- ClassTinkerers.addTransformation(HandledScreen, this::addMouseScroll, true);
- ClassTinkerers.addTransformation(HandledScreen, this::addKeyReleased, true);
- ClassTinkerers.addTransformation(HandledScreen, this::addCharTyped, true);
+ addTransformation(HandledScreen, this::addMouseScroll, true);
+ addTransformation(HandledScreen, this::addKeyReleased, true);
+ addTransformation(HandledScreen, this::addCharTyped, true);
+ addTransformation(Screen, this::addMouseClicked, true);
}
/**
@@ -57,8 +78,8 @@ public class HandledScreenRiser extends RiserUtils {
* @param insertInvoke insert the invokevirtual/invokestatic call
*/
void insertTrueHandler(MethodNode node,
- Consumer<InsnList> insertLoads,
- Consumer<InsnList> insertInvoke) {
+ Consumer<InsnList> insertLoads,
+ Consumer<InsnList> insertInvoke) {
var insns = new InsnList();
insertLoads.accept(insns);
@@ -77,26 +98,39 @@ public class HandledScreenRiser extends RiserUtils {
void addKeyReleased(ClassNode classNode) {
addSuperInjector(
- classNode, keyReleased, keyReleasedDesc, "keyReleased_firmament",
+ classNode, keyReleased.mapped(), keyReleased.mappedDesc(), HandledScreen, Screen, "keyReleased_firmament",
insns -> {
// ALOAD 0, load this
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
- // ILOAD 1-3, load args
- insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
- insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
- insns.add(new VarInsnNode(Opcodes.ILOAD, 3));
+ // ALOAD 1, load args
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 1));
});
}
+ void addMouseClicked(ClassNode classNode) {
+ addSuperInjector(
+ classNode, mouseClickedScreen.mapped(), mouseClickedScreen.mappedDesc(),
+ Screen, AbstractContainerEventHandler, "onMouseClicked$firmament",
+ insns -> {
+ // load this
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ // load mouse event
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 1));
+ // load doubled
+ insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
+ }
+ );
+ }
+
void addCharTyped(ClassNode classNode) {
addSuperInjector(
- classNode, charTyped, charTypedDesc, "charTyped_firmament",
+ classNode, charTyped.mapped(), charTyped.mappedDesc(),
+ HandledScreen, Screen, "charTyped_firmament",
insns -> {
// ALOAD 0, load this
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
- // ILOAD 1-2, load args. chars = ints
- insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
- insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
+ // ALOAD 1, load args
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 1));
});
}
@@ -104,6 +138,8 @@ public class HandledScreenRiser extends RiserUtils {
ClassNode classNode,
String name,
Type desc,
+ Intermediary.InterClass currentClass,
+ Intermediary.InterClass parentClass,
String firmamentName,
Consumer<InsnList> loadArgs
) {
@@ -119,8 +155,8 @@ public class HandledScreenRiser extends RiserUtils {
var insns = keyReleasedNode.instructions;
loadArgs.accept(insns);
// INVOKESPECIAL call super method
- insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, getTypeForClassName(Screen).getInternalName(),
- name, desc.getDescriptor()));
+ insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, parentClass.mapped().getInternalName(),
+ name, desc.getDescriptor()));
// IRETURN return int on stack (booleans are int at runtime)
insns.add(new InsnNode(Opcodes.IRETURN));
classNode.methods.add(keyReleasedNode);
@@ -128,16 +164,16 @@ public class HandledScreenRiser extends RiserUtils {
insertTrueHandler(keyReleasedNode, loadArgs, insns -> {
// INVOKEVIRTUAL call custom handler
insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
- getTypeForClassName(HandledScreen).getInternalName(),
- firmamentName,
- desc.getDescriptor()));
+ currentClass.mapped().getInternalName(),
+ firmamentName,
+ desc.getDescriptor()));
});
}
void addMouseScroll(ClassNode classNode) {
addSuperInjector(
- classNode, mouseScrolled, mouseScrolledDesc, "mouseScrolled_firmament",
+ classNode, mouseScrolled.mapped(), mouseScrolled.mappedDesc(), HandledScreen, Screen, "mouseScrolled_firmament",
insns -> {
// ALOAD 0, load this
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
diff --git a/src/main/java/moe/nea/firmament/init/Intermediary.java b/src/main/java/moe/nea/firmament/init/Intermediary.java
index 61494d7..3513a6b 100644
--- a/src/main/java/moe/nea/firmament/init/Intermediary.java
+++ b/src/main/java/moe/nea/firmament/init/Intermediary.java
@@ -7,57 +7,66 @@ import org.objectweb.asm.Type;
import java.util.List;
public class Intermediary {
- private static final MappingResolver RESOLVER = FabricLoader.getInstance().getMappingResolver();
-
- static String methodName(Object object) {
- throw new AssertionError("Cannot be called at runtime");
- }
-
- static <T> String className() {
- throw new AssertionError("Cannot be called at runtime");
- }
-
- static String id(String source) {
- return source;
- }
-
-// public record Class(
-// Type intermediaryClass
-// ) {
-// public Class(String intermediaryClass) {
-// this(Type.getObjectType(intermediaryClass.replace('.', '/')));
-// }
-//
-// public String getMappedName() {
-// return RESOLVER.mapClassName("intermediary", intermediaryClass.getInternalName()
-// .replace('/', '.'));
-// }
-// }
-//
-// public record Method(
-// Type intermediaryClassName,
-// String intermediaryMethodName,
-// Type intermediaryReturnType,
-// List<Type> intermediaryArgumentTypes
-// ) {
-// public Method(
-// String intermediaryClassName,
-// String intermediaryMethodName,
-// String intermediaryReturnType,
-// String... intermediaryArgumentTypes
-// ) {
-// this(intermediaryClassName, intermediaryMethodName, intermediaryReturnType, List.of(intermediaryArgumentTypes));
-// }
-//
-// public String getMappedMethodName() {
-// return RESOLVER.mapMethodName("intermediary",
-// intermediaryClassName.getInternalName().replace('/', '.'));
-// }
-//
-// public Type getIntermediaryDescriptor() {
-// return Type.getMethodType(intermediaryReturnType, intermediaryArgumentTypes.toArray(Type[]::new));
-// }
-//
-//
-// }
+ private static final MappingResolver RESOLVER = FabricLoader.getInstance().getMappingResolver();
+
+ static InterMethod intermediaryMethod(Object object, InterClass returnType, InterClass... args) {
+ throw new AssertionError("Cannot be called at runtime");
+ }
+
+ static <T> InterClass intermediaryClass() {
+ throw new AssertionError("Cannot be called at runtime");
+ }
+
+ public static InterClass ofIntermediaryClass(String interClass) {
+ return new InterClass(Type.getObjectType(interClass.replace('.', '/')));
+ }
+
+ public static InterClass ofClass(Class<?> unmappedClass) {
+ return new InterClass(Type.getType(unmappedClass));
+ }
+
+ public static InterMethod ofMethod(String intermediary, String ownerType, InterClass returnType, InterClass... argTypes) {
+ return new InterMethod(intermediary, ofIntermediaryClass(ownerType), returnType, List.of(argTypes));
+ }
+
+ public record InterClass(
+ Type intermediary
+ ) {
+ public Type mapped() {
+ if (intermediary().getSort() != Type.OBJECT)
+ return intermediary();
+ return Type.getObjectType(RESOLVER.mapClassName("intermediary", intermediary().getClassName())
+ .replace('.', '/'));
+ }
+ }
+
+ public record InterMethod(
+ String intermediary,
+ InterClass ownerType,
+ InterClass returnType,
+ List<InterClass> argumentTypes
+ ) {
+ public Type intermediaryDesc() {
+ return Type.getMethodType(
+ returnType.intermediary(),
+ argumentTypes().stream().map(InterClass::intermediary).toArray(Type[]::new)
+ );
+ }
+
+ public Type mappedDesc() {
+ return Type.getMethodType(
+ returnType.mapped(),
+ argumentTypes().stream().map(InterClass::mapped).toArray(Type[]::new)
+ );
+ }
+
+ public String mapped() {
+ return RESOLVER.mapMethodName(
+ "intermediary",
+ ownerType.intermediary().getClassName(),
+ intermediary(),
+ intermediaryDesc().getDescriptor()
+ );
+ }
+ }
}
diff --git a/src/main/java/moe/nea/firmament/init/ItemColorsSodiumRiser.java b/src/main/java/moe/nea/firmament/init/ItemColorsSodiumRiser.java
deleted file mode 100644
index 80ee9aa..0000000
--- a/src/main/java/moe/nea/firmament/init/ItemColorsSodiumRiser.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package moe.nea.firmament.init;
-
-import me.shedaniel.mm.api.ClassTinkerers;
-import moe.nea.firmament.util.ErrorUtil;
-import net.fabricmc.loader.api.FabricLoader;
-import net.minecraft.client.color.item.ItemColorProvider;
-import net.minecraft.client.color.item.ItemColors;
-import net.minecraft.item.ItemStack;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.InsnList;
-import org.objectweb.asm.tree.InsnNode;
-import org.objectweb.asm.tree.MethodInsnNode;
-import org.objectweb.asm.tree.VarInsnNode;
-
-public class ItemColorsSodiumRiser extends RiserUtils {
- @IntermediaryName(ItemColors.class)
- String ItemColors;
- @IntermediaryName(ItemColorProvider.class)
- String ItemColorProvider;
- @IntermediaryName(ItemStack.class)
- String ItemStack;
- String getColorProvider = "sodium$getColorProvider";
- Type getColorProviderDesc = Type.getMethodType(getTypeForClassName(ItemColorProvider),
- getTypeForClassName(ItemStack));
-
- @Override
- public void addTinkerers() {
- ClassTinkerers.addTransformation(ItemColors, this::addSodiumOverride, true);
- }
-
- private void addSodiumOverride(ClassNode classNode) {
- var node = findMethod(classNode, getColorProvider, getColorProviderDesc);
- if (node == null) {
- if (!FabricLoader.getInstance().isModLoaded("sodium"))
- ErrorUtil.INSTANCE.softError("Sodium is present, but sodium color override could not be injected.");
- return;
- }
- var p = node.instructions.getFirst();
- while (p != null) {
- if (p.getOpcode() == Opcodes.ARETURN) {
- node.instructions.insertBefore(
- p,
- mkOverrideSodiumCall()
- );
- }
- p = p.getNext();
- }
- }
-
- private InsnList mkOverrideSodiumCall() {
- var insnList = new InsnList();
- insnList.add(new VarInsnNode(Opcodes.ALOAD, 0));
- insnList.add(new InsnNode(Opcodes.SWAP));
- insnList.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
- getTypeForClassName(ItemColors).getInternalName(),
- "overrideSodium_firmament",
- Type.getMethodType(getTypeForClassName(ItemColorProvider),
- getTypeForClassName(ItemColorProvider)).getDescriptor(),
- false));
- return insnList;
- }
-}
diff --git a/src/main/java/moe/nea/firmament/init/MixinPlugin.java b/src/main/java/moe/nea/firmament/init/MixinPlugin.java
index 61e8f14..d48139b 100644
--- a/src/main/java/moe/nea/firmament/init/MixinPlugin.java
+++ b/src/main/java/moe/nea/firmament/init/MixinPlugin.java
@@ -8,54 +8,69 @@ import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class MixinPlugin implements IMixinConfigPlugin {
- AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin();
- public static String mixinPackage;
- @Override
- public void onLoad(String mixinPackage) {
- MixinExtrasBootstrap.init();
- MixinPlugin.mixinPackage = mixinPackage;
- autoDiscoveryPlugin.setMixinPackage(mixinPackage);
- }
-
- @Override
- public String getRefMapperConfig() {
- return null;
- }
-
- @Override
- public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
- if (!Boolean.getBoolean("firmament.debug") && mixinClassName.contains("devenv.")) {
- return false;
- }
- return true;
- }
-
- @Override
- public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
-
- }
-
- @Override
- public List<String> getMixins() {
- return autoDiscoveryPlugin.getMixins().stream().filter(it -> this.shouldApplyMixin(null, it))
- .toList();
- }
-
- @Override
- public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
-
- }
-
- public static List<String> appliedMixins = new ArrayList<>();
-
- @Override
- public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
- appliedMixins.add(mixinClassName);
- }
+ AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin();
+ public static List<MixinPlugin> instances = new ArrayList<>();
+ public String mixinPackage;
+
+ @Override
+ public void onLoad(String mixinPackage) {
+ MixinExtrasBootstrap.init();
+ instances.add(this);
+ this.mixinPackage = mixinPackage;
+ autoDiscoveryPlugin.setMixinPackage(mixinPackage);
+ }
+
+ @Override