diff options
Diffstat (limited to 'src/main/java/moe/nea/firmament/init')
7 files changed, 171 insertions, 204 deletions
diff --git a/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java index a9db7f9..07e4549 100644 --- a/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java +++ b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java @@ -27,6 +27,8 @@ public class AutoDiscoveryPlugin { return mixins.stream().map(it -> defaultName + "." + it).toList(); } + // TODO: remove println + private static final List<AutoDiscoveryPlugin> mixinPlugins = new ArrayList<>(); public static List<AutoDiscoveryPlugin> getMixinPlugins() { 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 5441255..ae26bd7 100644 --- a/src/main/java/moe/nea/firmament/init/EarlyRiser.java +++ b/src/main/java/moe/nea/firmament/init/EarlyRiser.java @@ -4,7 +4,6 @@ package moe.nea.firmament.init; public class EarlyRiser implements Runnable { @Override public void run() { - new ClientPlayerRiser().addTinkerers(); new HandledScreenRiser().addTinkerers(); new SectionBuilderRiser().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 f7db18c..98be517 100644 --- a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java +++ b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java @@ -2,7 +2,13 @@ package moe.nea.firmament.init; import me.shedaniel.mm.api.ClassTinkerers; -import net.minecraft.client.gui.Element; +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; @@ -19,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); } /** @@ -56,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); @@ -76,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)); }); } @@ -103,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 ) { @@ -118,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); @@ -127,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/RiserUtils.java b/src/main/java/moe/nea/firmament/init/RiserUtils.java index c1c8fd1..ad4ac8f 100644 --- a/src/main/java/moe/nea/firmament/init/RiserUtils.java +++ b/src/main/java/moe/nea/firmament/init/RiserUtils.java @@ -1,12 +1,15 @@ package moe.nea.firmament.init; +import me.shedaniel.mm.api.ClassTinkerers; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.MappingResolver; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; +import java.util.function.Consumer; + public abstract class RiserUtils { protected Type getTypeForClassName(String className) { return Type.getObjectType(className.replace('.', '/')); @@ -24,4 +27,8 @@ public abstract class RiserUtils { return null; } + public void addTransformation(Intermediary.InterClass interClass, Consumer<ClassNode> transformer, boolean post) { + ClassTinkerers.addTransformation(interClass.mapped().getClassName(), transformer, post); + } + } diff --git a/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java index 8b65946..a5d5c1d 100644 --- a/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java +++ b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java @@ -1,12 +1,11 @@ package moe.nea.firmament.init; -import me.shedaniel.mm.api.ClassTinkerers; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.block.BlockState; -import net.minecraft.client.render.block.BlockRenderManager; -import net.minecraft.client.render.chunk.SectionBuilder; -import net.minecraft.client.render.model.BlockStateModel; -import net.minecraft.util.math.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.client.renderer.chunk.SectionCompiler; +import net.minecraft.client.renderer.block.model.BlockStateModel; +import net.minecraft.core.BlockPos; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; @@ -19,36 +18,24 @@ import org.objectweb.asm.tree.VarInsnNode; public class SectionBuilderRiser extends RiserUtils { - @IntermediaryName(SectionBuilder.class) - String SectionBuilder; - @IntermediaryName(BlockPos.class) - String BlockPos; - @IntermediaryName(BlockRenderManager.class) - String BlockRenderManager; - @IntermediaryName(BlockState.class) - String BlockState; - @IntermediaryName(BlockStateModel.class) - String BlockStateModel; + Intermediary.InterClass SectionBuilder = Intermediary.<SectionCompiler>intermediaryClass(); + Intermediary.InterClass BlockPos = Intermediary.<BlockPos>intermediaryClass(); + Intermediary.InterClass BlockRenderManager = Intermediary.<BlockRenderDispatcher>intermediaryClass(); + Intermediary.InterClass BlockState = Intermediary.<BlockState>intermediaryClass(); + Intermediary.InterClass BlockStateModel = Intermediary.<BlockStateModel>intermediaryClass(); String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures"; - Type getModelDesc = Type.getMethodType( - getTypeForClassName(BlockRenderManager), - getTypeForClassName(BlockState) - ); - String getModel = remapper.mapMethodName( - "intermediary", - Intermediary.<BlockRenderManager>className(), - Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel), - Type.getMethodDescriptor( - getTypeForClassName(Intermediary.<BlockStateModel>className()), - getTypeForClassName(Intermediary.<BlockState>className()) - ) - ); + Intermediary.InterMethod getModel = + Intermediary.intermediaryMethod( + net.minecraft.client.renderer.block.BlockRenderDispatcher::getBlockModel, + BlockStateModel, + BlockState + ); @Override public void addTinkerers() { if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo")) - ClassTinkerers.addTransformation(SectionBuilder, this::handle, true); + addTransformation(SectionBuilder, this::handle, true); } private void handle(ClassNode classNode) { @@ -67,10 +54,10 @@ public class SectionBuilderRiser extends RiserUtils { private void handleIndigo(MethodNode method) { LocalVariableNode blockPosVar = null, blockStateVar = null; for (LocalVariableNode localVariable : method.localVariables) { - if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockPos))) { + if (Type.getType(localVariable.desc).equals(BlockPos.mapped())) { blockPosVar = localVariable; } - if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockState))) { + if (Type.getType(localVariable.desc).equals(BlockState.mapped())) { blockStateVar = localVariable; } } @@ -81,7 +68,8 @@ public class SectionBuilderRiser extends RiserUtils { for (AbstractInsnNode instruction : method.instructions) { if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) continue; var methodInsn = (MethodInsnNode) instruction; - if (!(methodInsn.name.equals(getModel) && Type.getObjectType(methodInsn.owner).equals(getTypeForClassName(BlockRenderManager)))) + if (!(methodInsn.name.equals(getModel.mapped()) && + Type.getObjectType(methodInsn.owner).equals(BlockRenderManager.mapped()))) continue; method.instructions.insertBefore( methodInsn, @@ -106,10 +94,10 @@ public class SectionBuilderRiser extends RiserUtils { getTypeForClassName(CustomBlockTextures).getInternalName(), "patchIndigo", Type.getMethodDescriptor( - getTypeForClassName(BlockStateModel), - getTypeForClassName(BlockStateModel), - getTypeForClassName(BlockPos), - getTypeForClassName(BlockState)), + (BlockStateModel).mapped(), + (BlockStateModel).mapped(), + (BlockPos).mapped(), + (BlockState).mapped()), false )); method.instructions.insert(methodInsn, insnList); |
