BlockBBEvent in scripts?
-
@idk-my-name
Indeed there is noonBlockBB
provided.
Before this someone showed me the matrix fly (rewinside + jump, patched) made by aftery in scriptapi(obf), it would be almost impossible to implement without blockBB. I didn't figure out back then
It took me a long time to finally figured out a way to subscribe to arbitrary event in scriptAPI with reflection andJava.extend
.
Hint:Java.extend(Listenable, Consumer, { handleEvents: function() { return true}, accept: function(e) { } })
and this.
-
@commandblock2
I understood from your tutorial that I should somewhere use registerListener, prob like this:onEnable: function() { LiquidBounce.INSTANCE.eventManager.registerListener(listener) }, onDisable: function() { LiquidBounce.INSTANCE.eventManager.unregisterListener(listener) } listener = Java.extend(Listenable, Consumer, { handleEvents: function() { return true}, accept: function(e) { e instanceof BlockBBEvent && print("Hello from BlockBBEvent!") } })
-
@commandblock2 waait that's cool never had that idea
I might automatize that via Core.
-
@idk-my-name you should probably register it on load, unregister it on unload and handle if it gets triggered in handleEvents method
-
@idk-my-name
Indeed something like that.val eventClass = method.parameterTypes[0] as Class<out Event> val eventTarget = method.getAnnotation(EventTarget::class.java)
Unfortunately, nashorn/reflection does not have any capability of adding annotations.
method.getAnnotation(EventTarget::class.java)
and we will have to make our ownregisterListener()
.The 3 lines actually does the work is here.
val invokableEventTargets = registry.getOrDefault(eventClass, ArrayList()) invokableEventTargets.add(EventHook(listener, method, eventTarget)) registry[eventClass] = invokableEventTargets
You only need to convert this 3 line to js and it would be fine.
Note the second line
EventHook(listener, method, eventTarget)
thelistener
is just the listener,
themethod
isaccept
acquired using reflection
but for theeventTarget
, I borrowed it with reflection from a function in other class thatextends Listener
already presented in LB.As for the performance issue, it's true, in my case, putting a print every time it is called makes the frame rate goes from 80(limited) to less than 1.
-
@commandblock2 I currently did this:
///api_version=2 (script = registerScript({ name: "BlockBBEvent", authors: ["xWhitey"], version: "1.337" })).import("Core.lib"); module = { category: "Core", onLoad: function() { registerListener(Java.extend((Java.type('net.ccbluex.liquidbounce.event.Listenable')), (Java.type('java.util.function.Consumer')), { handleEvents: function() { return true }, accept: function(e) { e instanceof BlockBBEvent && print("Hello from BlockBBEvent!") } })) } } function registerListener(listener) { for each(method in listener.class.getDeclaredMethods()) { if (method.getParameterTypes().length == 1) { if (!method.isAccessible()) method.setAccessible(true); var eventClass = method.getParameterTypes()[0]; var adaptedEventManager = new Reflector(LiquidBounce.INSTANCE.eventManager); var invokableEventTargets = adaptedEventManager.registry.getOrDefault(eventClass, new ArrayList()); var onTickMethod = (Java.type('net.ccbluex.liquidbounce.utils.RotationUtils')).class.getDeclaredMethod("onTick", TickEvent.class); var annotations = onTickMethod.getDeclaredAnnotations(); var annotation = null; for each(a in annotations) { annotation = a; } invokableEventTargets.add(new EventHook(listener, method, annotation)); adaptedEventManager.registry.put(eventClass, invokableEventTargets); } } } var TickEvent = Java.type('net.ccbluex.liquidbounce.event.TickEvent'), BlockBBEvent = Java.type('net.ccbluex.liquidbounce.event.BlockBBEvent'), EventHook = Java.type('net.ccbluex.liquidbounce.event.EventHook'), ArrayList = Java.type('java.util.ArrayList');
but it throws an error:
[23:01:10] [Client thread/ERROR] [LiquidBounce]: [ScriptAPI] Exception in script 'BlockBBEvent'! java.lang.ClassCastException: Cannot cast jdk.internal.dynalink.beans.StaticClass to net.ccbluex.liquidbounce.event.Listenable at java.lang.invoke.MethodHandleImpl.newClassCastException(Unknown Source) ~[?:1.8.0_144] at java.lang.invoke.MethodHandleImpl.castReference(Unknown Source) ~[?:1.8.0_144] at jdk.nashorn.internal.scripts.Script$Recompilation$6736$598A$\^eval\_.registerListener(<eval>:37) ~[?:?] at jdk.nashorn.internal.scripts.Script$Recompilation$6733$207$\^eval\_.onLoad(<eval>:11) ~[?:?] at jdk.nashorn.internal.scripts.Script$Recompilation$6546$\^eval\_.L:611#L:629(<eval>:631) ~[?:?] at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:628) ~[ScriptFunctionData.class:?] at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494) ~[ScriptFunction.class:?] at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393) ~[ScriptRuntime.class:?] at jdk.nashorn.api.scripting.ScriptObjectMirror.call(ScriptObjectMirror.java:117) ~[ScriptObjectMirror.class:?] at net.ccbluex.liquidbounce.script.Script.callEvent(Script.kt:203) [Script.class:?] at net.ccbluex.liquidbounce.script.Script.onEnable(Script.kt:171) [Script.class:?] at net.ccbluex.liquidbounce.script.ScriptManager.enableScripts(ScriptManager.kt:53) [ScriptManager.class:?] at net.ccbluex.liquidbounce.LiquidBounce.startClient(LiquidBounce.kt:130) [LiquidBounce.class:?] at net.minecraft.client.Minecraft.handler$zze000$startGame(Minecraft.java:3428) [bib.class:?] at net.minecraft.client.Minecraft.func_71384_a(Minecraft.java:536) [bib.class:?] at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:378) [bib.class:?] at net.minecraft.client.main.Main.main(SourceFile:123) [Main.class:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_144] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_144] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_144] at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_144] at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [game.jar:?] at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [game.jar:?]
-
@idk-my-name said in BlockBBEvent in scripts?:
authors: ["xWhitey"],
-
@fartcheese and? who asked?
-
@idk-my-name who did
-
@fartcheese wdym
-
@idk-my-name WHO asked
the guy named WHO asked
-
@fartcheese lmao
-
-
@idk-my-name
WhatJava.extend()
returns is something that behaves like a type (Forgot what it really is, probably a JSAdaptor or something).
Similar to what you will get from usingJava.type()
.ArrayList = Java.type("java.util.ArrayList") arrayList = new ArrayList()
BBConsumer = Java.extend(Listenable, Consumer, { handleEvents: function() { return true}, accept: function(e) { // onBlockBB here } }) consumer = new BBConsumer() registerListener(consumer) // not registerListener(BBConsumer) /* I am sure there would be a better name for BBConsumer And if you want to use it like a anonymous class in Java you could just read the BlockAnimations.js or better, nashorn document https://github.com/CzechHek/Core/blob/879f36d7e41ccc7868285b0a808866b360f30822/Scripts/BlockAnimations.js#L35 */
Not sure if the type from
Java.extend
would have other unexpected methods that only takes 1 parameters, you might want to check if the parameter's super class isEvent
.Or you could just explicitly specify the
accept
method in it.
method = consumer.class.getMethod("accept", java.lang.Object.class)
Edit:
Nvm, I forgot that this was scriptAPI, theConsumer
here is aConsumer<?>
, notConsumer<BlockBBEvent>
which means theaccepct()
takes anjava.lang.Object
, and it will register a Listener that listens to any event that is anjava.lang.Object
, which probably means all events.'Here is what I did
registry = getField(LiquidBounce.eventManager, "registry").get(LiquidBounce.eventManager) BBs = registry.getOrDefault(BlockBBEvent.class, new ArrayList()) BBs.add(new EventHook(consumer, consumer.class.getMethod("accept", java.lang.Object.class), LiquidBounce.moduleManager.class .getDeclaredMethod("onKey", KeyEvent.class) .getAnnotation(EventTarget.class))) registry[BlockBBEvent.class] = BBs
-
@commandblock2 Thank you
-
-
This is what I came up with without seeing @commandblock2's solution.
I had to reverse engineer a bunch of stuff and then put all together and it worked.I was wondering what the hell was annotation in Nashorn and it turns out that
print(annotation.class)
literally returns
I'll try to simplify it and automize it via Core.
///api_version=2 (script = registerScript({ name: "Test", authors: ["CzechHek"], version: "1.0" })).import("Core.lib"); module = { onClickGuiLoaded: function () { listener = new (Java.extend(Listenable, Consumer, { handleEvents: function() { return TestModule.state }, accept: function(e) { print(e) } })); method = getMethod(listener, "accept"); annotation = getMethod(TestModule, "onUpdate").getDeclaredAnnotations()[0]; AeventManager = new Reflector(LiquidBounce.eventManager) invocableEventTargets = AeventManager.registry.getOrDefault(BlockBBEvent.class, new ArrayList()); invocableEventTargets.add(new EventHook(listener, method, annotation)); AeventManager.registry[BlockBBEvent.class] = invocableEventTargets; } } Listenable = Java.type("net.ccbluex.liquidbounce.event.Listenable"); Consumer = Java.type("java.util.function.Consumer"); BlockBBEvent = Java.type("net.ccbluex.liquidbounce.event.BlockBBEvent"); EventHook = Java.type("net.ccbluex.liquidbounce.event.EventHook"); ArrayList = Java.type("java.util.ArrayList")
-
@idk-my-name you forgor