From ecf2d457b7863549818dd50ce0670029a264d243 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:46:31 +0100 Subject: [PATCH] allow non-public subscribed methods in @EventBusSubscriber classes --- .../transformer/EventBusSubTransformer.java | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/gtnewhorizon/gtnhlib/core/transformer/EventBusSubTransformer.java b/src/main/java/com/gtnewhorizon/gtnhlib/core/transformer/EventBusSubTransformer.java index 5706a5c..4910610 100644 --- a/src/main/java/com/gtnewhorizon/gtnhlib/core/transformer/EventBusSubTransformer.java +++ b/src/main/java/com/gtnewhorizon/gtnhlib/core/transformer/EventBusSubTransformer.java @@ -10,6 +10,7 @@ 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.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AnnotationNode; @@ -54,8 +55,9 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) final ClassReader cr = new ClassReader(basicClass); final ClassNode cn = new ClassNode(); - cr.accept(cn, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE); + cr.accept(cn, 0); + boolean changed = false; // Processing all of this from the ASMDataTable is way too slow for (MethodNode mn : cn.methods) { Object2ObjectMap usableAnnotations = getUsableAnnotations(mn.visibleAnnotations); @@ -63,7 +65,7 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) if (!matchesSide(usableAnnotations.get(SIDEONLY_DESC))) { if (DEBUG_EVENT_BUS) { - LOGGER.info("Skipping method {} due to side mismatch", transformedName); + LOGGER.info("Skipping method {} due to side mismatch", getMethodKey(transformedName, mn)); } continue; } @@ -72,8 +74,8 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) boolean condition = usableAnnotations.containsKey(CONDITION_DESC); if ((mn.access & Opcodes.ACC_STATIC) == 0) { if (!condition && subscribe != null) { - EventBusUtil.getInvalidMethods().add( - "Encountered unexpected non-static method: " + transformedName + " " + mn.name + mn.desc); + EventBusUtil.getInvalidMethods() + .add("Encountered unexpected non-static method: " + getMethodKey(transformedName, mn)); } continue; } @@ -81,12 +83,10 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) if (condition) { if (mn.desc.equals("()Z")) { EventBusUtil.getConditionsToCheck().put(transformedName, mn.name + mn.desc); + changed |= changeAccess(transformedName, mn); } else { EventBusUtil.getInvalidMethods().add( - "Invalid condition method: " + transformedName - + " " - + mn.name - + mn.desc + "Invalid condition method: " + getMethodKey(transformedName, mn) + ". Condition method must have no parameters and return a boolean."); } continue; @@ -96,11 +96,14 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) if (DEBUG_EVENT_BUS) { LOGGER.info( "Skipping method {} with annotations {}. No @SubscribeEvent found.", - transformedName, + getMethodKey(transformedName, mn), usableAnnotations.keySet()); } continue; } + + changed |= changeAccess(transformedName, mn); + Object[] subscribeInfo = getSubscribeInfo(subscribe); MethodInfo methodInfo = new MethodInfo( transformedName, @@ -127,6 +130,12 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) } } + if (changed) { + final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + cn.accept(cw); + return cw.toByteArray(); + } + return basicClass; } @@ -171,4 +180,22 @@ private static Object[] getSubscribeInfo(AnnotationNode annotation) { } return info; } + + private static boolean changeAccess(String className, MethodNode mn) { + if ((mn.access & Opcodes.ACC_PUBLIC) == 0) { + if (DEBUG_EVENT_BUS) { + LOGGER.info( + "Encountered condition or subscriber method with non-public access {}. Making it public.", + getMethodKey(className, mn)); + } + mn.access = (mn.access | Opcodes.ACC_PUBLIC) & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); + return true; + } + + return false; + } + + private static String getMethodKey(String className, MethodNode mn) { + return className + " " + mn.name + mn.desc; + } }