CCBlueX / LiquidBounce

A free mixin-based injection hacked client for Minecraft using the Fabric API
https://liquidbounce.net/
GNU General Public License v3.0
1.52k stars 488 forks source link

[BUG] Scripting APIs undefined #1811

Closed fineless71 closed 10 months ago

fineless71 commented 10 months ago

LiquidBounce Branch

Nextgen

LiquidBounce Build/Version

96f3064

Operating System

Linux

Minecraft Version

1.20.4

Describe the bug

Not sure if anyone saw my comment at https://github.com/CCBlueX/LiquidBounce/issues/1552#issuecomment-1872401912, so I'm moving this to an issue:

I couldn't get this fully working. I got some stuff working like adding chat messages (via the client object) and jumping (via mc.player.jump()), but I couldn't get any of the APIs working, even the rotation examples from the comments. For example, api.movementUtil.jump() resulted in the error org.graalvm.polyglot.PolyglotException: TypeError: undefined has no such function "jump"

Steps to reproduce

Try to use one of the scripting APIs, like so:

module.on("enable", function() {
    api.movementUtil.jump()
});

Client Log

[13:23:48] [Render thread/ERROR]: Script caused exception in module REDACTED on enable event!
org.graalvm.polyglot.PolyglotException: TypeError: undefined has no such function "jump"
    at <js>.:anonymous(Unnamed:29) ~[?:?]
    at com.oracle.truffle.polyglot.PolyglotFunctionProxyHandler.invoke(PolyglotFunctionProxyHandler.java:155) ~[liquidbounce.jar:?]
    at jdk.proxy2.$Proxy56.invoke(Unknown Source) ~[?:?]
    at net.ccbluex.liquidbounce.script.bindings.features.JsModule.callEvent(JsModule.kt:85) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.bindings.features.JsModule.callEvent$default(JsModule.kt:83) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.bindings.features.JsModule.enable(JsModule.kt:76) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.module.Module$enabled$2.invoke(Module.kt:78) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.module.Module$enabled$2.invoke(Module.kt:68) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.config.Value.set(Value.kt:108) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.config.Value.setValue(Value.kt:93) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.module.Module.setEnabled(Module.kt:68) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.commands.client.CommandToggle$createCommand$1.invoke(CommandToggle.kt:52) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.commands.client.CommandToggle$createCommand$1.invoke(CommandToggle.kt:46) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.CommandManager.execute(CommandManager.kt:323) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.CommandExecutor$chatEventHandler$1.invoke(CommandManager.kt:57) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.CommandExecutor$chatEventHandler$1.invoke(CommandManager.kt:54) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.event.EventManager.callEvent(EventManager.kt:164) ~[liquidbounce.jar:?]
    at net.minecraft.class_408.handler$clj000$liquidbounce$handleChatMessage(class_408.java:1551) ~[client-intermediary.jar:?]
    at net.minecraft.class_408.method_44056(class_408.java) ~[client-intermediary.jar:?]
    at net.minecraft.class_408.method_25404(class_408.java:98) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_1454(class_309.java:407) ~[client-intermediary.jar:?]
    at net.minecraft.class_437.method_25412(class_437.java:414) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_1466(class_309.java:403) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_22678(class_309.java:492) ~[client-intermediary.jar:?]
    at net.minecraft.class_1255.execute(class_1255.java:102) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.redirect$cah000$viafabricplus$storeEvent(class_309.java:1136) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_22676(class_309.java:492) ~[client-intermediary.jar:?]
    at org.lwjgl.glfw.GLFWKeyCallbackI.callback(GLFWKeyCallbackI.java:44) ~[lwjgl-glfw-3.3.2.jar:?]
    at org.lwjgl.system.JNI.invokeV(Native Method) ~[lwjgl-3.3.2.jar:?]
    at org.lwjgl.glfw.GLFW.glfwWaitEventsTimeout(GLFW.java:3509) ~[lwjgl-glfw-3.3.2.jar:?]
    at com.mojang.blaze3d.systems.RenderSystem.limitDisplayFPS(RenderSystem.java:238) ~[client-intermediary.jar:?]
    at net.minecraft.class_310.method_1523(class_310.java:1352) ~[client-intermediary.jar:?]
    at net.minecraft.class_310.method_1514(class_310.java:888) ~[client-intermediary.jar:?]
    at net.minecraft.client.main.Main.main(Main.java:265) ~[minecraft-1.20.4-client.jar:?]
    at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:470) ~[fabric-loader-0.15.3.jar:?]
    at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:74) ~[fabric-loader-0.15.3.jar:?]
    at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) ~[fabric-loader-0.15.3.jar:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
    at org.polymc.impl.OneSixLauncher.invokeMain(OneSixLauncher.java:104) ~[NewLaunch.jar:?]
    at org.polymc.impl.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:176) ~[NewLaunch.jar:?]
    at org.polymc.impl.OneSixLauncher.launch(OneSixLauncher.java:186) ~[NewLaunch.jar:?]
    at org.polymc.EntryPoint.listen(EntryPoint.java:144) ~[NewLaunch.jar:?]
    at org.polymc.EntryPoint.main(EntryPoint.java:74) ~[NewLaunch.jar:?]

Screenshots

No response

1zun4 commented 10 months ago

Looking into it now.

1zun4 commented 10 months ago
const script = registerScript({
    name: "MyScript",
    version: "1.0.0",
    authors: ["My Name"]
});

script.registerModule({
    name: "SpeedModule",
    category: "Misc",
    description: "An example module created with LiquidBounce's script API."
}, function (module) {
    module.on("enable", function() {
        client.displayChatMessage("§aHallo - du solltest funktionieren.");
    });

    module.on("disable", function() {
        client.displayChatMessage("§cTschüss - du solltest nicht mehr funktionieren.");
    });

    module.on("playerTick", function(event) {
        if (movementUtil.moving()) {
            movementUtil.strafeWithSpeed(0.3);
        }

        const speed = movementUtil.speed();
        client.displayChatMessage(speed.toString());

        // add velocity
        if (mc.player.onGround) {
            mc.player.jump();
            client.displayChatMessage("jump! :)");
        } else if (mc.player.velocity.y < 0) {
            mc.player.addVelocity(new Vec3d(0.0, 0.0002, 0.0));
        } else {
            mc.player.velocity.y -= 0.1;
        }
    });
});

image

It works well. :)

fineless71 commented 10 months ago

Thanks, the API is working now. But in your script, the line mc.player.velocity.y -= 0.1; gives me an error:

org.graalvm.polyglot.PolyglotException: TypeError: Cannot read property "y" from undefined
    at <js>.:anonymous(Unnamed:26) ~[?:?]
    at com.oracle.truffle.polyglot.PolyglotFunctionProxyHandler.invoke(PolyglotFunctionProxyHandler.java:155) ~[liquidbounce.jar:?]
    at jdk.proxy2.$Proxy56.invoke(Unknown Source) ~[?:?]
    at net.ccbluex.liquidbounce.script.bindings.features.JsModule.callEvent(JsModule.kt:85) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.bindings.features.JsModule.access$callEvent(JsModule.kt:28) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.bindings.features.JsModule$hookHandler$1.invoke(JsModule.kt:103) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.bindings.features.JsModule$hookHandler$1.invoke(JsModule.kt:98) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.event.EventManager.callEvent(EventManager.kt:170) ~[liquidbounce.jar:?]
    at net.minecraft.class_746.handler$cle001$liquidbounce$hookTickEvent(class_746.java:1396) ~[client-intermediary.jar:?]
    at net.minecraft.class_746.method_5773(class_746.java:218) ~[client-intermediary.jar:?]
    at net.minecraft.class_638.method_18646(class_638.java:1184) ~[client-intermediary.jar:?]
    at net.minecraft.class_1937.method_18472(class_1937.java:492) ~[client-intermediary.jar:?]
    at net.minecraft.class_638.method_32124(class_638.java:260) ~[client-intermediary.jar:?]
    at net.minecraft.class_5574.method_31791(class_5574.java:54) ~[client-intermediary.jar:?]
    at net.minecraft.class_638.method_18116(class_638.java:256) ~[client-intermediary.jar:?]
    at net.minecraft.class_310.method_1574(class_310.java:2011) ~[client-intermediary.jar:?]
    at net.minecraft.class_310.method_1523(class_310.java:1289) ~[client-intermediary.jar:?]
    at net.minecraft.class_310.method_1514(class_310.java:888) ~[client-intermediary.jar:?]
    at net.minecraft.client.main.Main.main(Main.java:265) ~[minecraft-1.20.4-client.jar:?]
    at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:470) ~[fabric-loader-0.15.3.jar:?]
    at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:74) ~[fabric-loader-0.15.3.jar:?]
    at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) ~[fabric-loader-0.15.3.jar:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
    at org.polymc.impl.OneSixLauncher.invokeMain(OneSixLauncher.java:104) ~[NewLaunch.jar:?]
    at org.polymc.impl.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:176) ~[NewLaunch.jar:?]
    at org.polymc.impl.OneSixLauncher.launch(OneSixLauncher.java:186) ~[NewLaunch.jar:?]
    at org.polymc.EntryPoint.listen(EntryPoint.java:144) ~[NewLaunch.jar:?]
    at org.polymc.EntryPoint.main(EntryPoint.java:74) ~[NewLaunch.jar:?]
fineless71 commented 10 months ago

It looks like it worked in your screenshot but for me it seems some things under player is undefined. It doesn't jump for me (nor print the jump message) and client.displayChatMessage(typeof mc.player.onGround); prints undefined. Printing the player itself does give object though. mc.player.jump() it works, I'm not sure why onGround doesn't.

Random guess but maybe it's due to mappings?

1zun4 commented 10 months ago

Yes it might be. I actually tested on the dev environment, instead of the release version, so it's likely something with the remapper.

1zun4 commented 10 months ago

It seems the remapper we can access the field of MinecraftClient.player in the remapped name, however after this, we cannot access Entity.onGround, but we can access ClientPlayerEntity.lastOnGround

image

const script = registerScript({
    name: "MyScript",
    version: "1.0.0",
    authors: ["My Name"]
});

script.registerModule({
    name: "SpeedModule",
    category: "Misc",
    description: "An example module created with LiquidBounce's script API."
}, function (module) {
    module.on("enable", function() {
        client.displayChatMessage("§aHallo - du solltest funktionieren.");
        //client.displayChatMessage(JSON.stringify(mc.player));
    });

    module.on("disable", function() {
        client.displayChatMessage("§cTschüss - du solltest nicht mehr funktionieren.");
    });

    module.on("playerTick", function(event) {
        if (movementUtil.moving()) {
            movementUtil.strafeWithSpeed(0.3);
        }

        const speed = movementUtil.speed();
        client.displayChatMessage(speed.toString());

        client.displayChatMessage(typeof mc.player);
        client.displayChatMessage(typeof mc);
        client.displayChatMessage(typeof mc.player.onGround);
        client.displayChatMessage(typeof mc.player.aJ);
        client.displayChatMessage(typeof mc.player.field_5952);
        client.displayChatMessage(typeof mc.player.lastOnGround);
    });
});

I will further debug on what is exactly going on, but since we cannot even access the obfuscated name of it, this means it is likely being remapped, however something else goes wrong.

1zun4 commented 10 months ago

So, my guess is the Remapper does not really function as intended. However we can write a better one by injection into Members, which collects all methods and fields of an class and translate there.

1zun4 commented 10 months ago

It seems the remapper we can access the field of MinecraftClient.player in the remapped name, however after this, we cannot access Entity.onGround, but we can access ClientPlayerEntity.lastOnGround

image

const script = registerScript({
    name: "MyScript",
    version: "1.0.0",
    authors: ["My Name"]
});

script.registerModule({
    name: "SpeedModule",
    category: "Misc",
    description: "An example module created with LiquidBounce's script API."
}, function (module) {
    module.on("enable", function() {
        client.displayChatMessage("§aHallo - du solltest funktionieren.");
        //client.displayChatMessage(JSON.stringify(mc.player));
    });

    module.on("disable", function() {
        client.displayChatMessage("§cTschüss - du solltest nicht mehr funktionieren.");
    });

    module.on("playerTick", function(event) {
        if (movementUtil.moving()) {
            movementUtil.strafeWithSpeed(0.3);
        }

        const speed = movementUtil.speed();
        client.displayChatMessage(speed.toString());

        client.displayChatMessage(typeof mc.player);
        client.displayChatMessage(typeof mc);
        client.displayChatMessage(typeof mc.player.onGround);
        client.displayChatMessage(typeof mc.player.aJ);
        client.displayChatMessage(typeof mc.player.field_5952);
        client.displayChatMessage(typeof mc.player.lastOnGround);
    });
});

I will further debug on what is exactly going on, but since we cannot even access the obfuscated name of it, this means it is likely being remapped, however something else goes wrong.

image

It is now fixed.

fineless71 commented 10 months ago

Thanks, but I can't use the mapped names with reflection, is this a bug?

// Works
const PlayerMoveC2SPacket = reflectionUtil.classByName("net.minecraft.class_2828");
// Doesn't work, causes error on load
const PlayerMoveC2SPacket = reflectionUtil.classByName("net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket");
org.graalvm.polyglot.PolyglotException: net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket
    at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[?:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[?:?]
    at net.fabricmc.loader.impl.launch.knot.KnotClassDelegate.loadClass(KnotClassDelegate.java:226) ~[fabric-loader-0.15.3.jar:?]
    at net.fabricmc.loader.impl.launch.knot.KnotClassLoader.loadClass(KnotClassLoader.java:119) ~[fabric-loader-0.15.3.jar:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[?:?]
    at java.lang.Class.forName0(Native Method) ~[?:?]
    at java.lang.Class.forName(Class.java:375) ~[?:?]
    at net.ccbluex.liquidbounce.script.bindings.api.JsReflectionUtil.classByName(JsReflectionUtil.kt:24) ~[liquidbounce.jar:?]
    at <js>.:program(Unnamed:10) ~[?:?]
    at org.graalvm.polyglot.Context.eval(Context.java:429) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.Script.initScript(Script.kt:74) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.ScriptManager.loadScript(ScriptManager.kt:67) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.ScriptManager.loadSafely(ScriptManager.kt:57) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.ScriptManager.loadScripts(ScriptManager.kt:42) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.ScriptManager.reloadScripts(ScriptManager.kt:121) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.CommandScript$createCommand$1.invoke(CommandScript.kt:36) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.script.CommandScript$createCommand$1.invoke(CommandScript.kt:34) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.CommandManager.execute(CommandManager.kt:322) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.CommandExecutor$chatEventHandler$1.invoke(CommandManager.kt:59) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.features.command.CommandExecutor$chatEventHandler$1.invoke(CommandManager.kt:56) ~[liquidbounce.jar:?]
    at net.ccbluex.liquidbounce.event.EventManager.callEvent(EventManager.kt:169) ~[liquidbounce.jar:?]
    at net.minecraft.class_408.handler$clk000$liquidbounce$handleChatMessage(class_408.java:1551) ~[client-intermediary.jar:?]
    at net.minecraft.class_408.method_44056(class_408.java) ~[client-intermediary.jar:?]
    at net.minecraft.class_408.method_25404(class_408.java:98) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_1454(class_309.java:407) ~[client-intermediary.jar:?]
    at net.minecraft.class_437.method_25412(class_437.java:414) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_1466(class_309.java:403) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_22678(class_309.java:492) ~[client-intermediary.jar:?]
    at net.minecraft.class_1255.execute(class_1255.java:102) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.redirect$cah000$viafabricplus$storeEvent(class_309.java:1136) ~[client-intermediary.jar:?]
    at net.minecraft.class_309.method_22676(class_309.java:492) ~[client-intermediary.jar:?]
    at org.lwjgl.glfw.GLFWKeyCallbackI.callback(GLFWKeyCallbackI.java:44) ~[lwjgl-glfw-3.3.2.jar:?]
    at org.lwjgl.system.JNI.invokeV(Native Method) ~[lwjgl-3.3.2.jar:?]
    at org.lwjgl.glfw.GLFW.glfwPollEvents(GLFW.java:3438) ~[lwjgl-glfw-3.3.2.jar:?]
    at com.mojang.blaze3d.systems.RenderSystem.pollEvents(RenderSystem.java:202) ~[client-intermediary.jar:?]
    at com.mojang.blaze3d.systems.RenderSystem.flipFrame(RenderSystem.java:220) ~[client-intermediary.jar:?]
    at net.minecraft.class_1041.method_15998(class_1041.java:287) ~[client-intermediary.jar:?]
    at net.minecraft.class_310.method_1523(class_310.java:1349) ~[client-intermediary.jar:?]
    at net.minecraft.class_310.method_1514(class_310.java:888) ~[client-intermediary.jar:?]
    at net.minecraft.client.main.Main.main(Main.java:265) ~[minecraft-1.20.4-client.jar:?]
    at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:470) ~[fabric-loader-0.15.3.jar:?]
    at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:74) ~[fabric-loader-0.15.3.jar:?]
    at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) ~[fabric-loader-0.15.3.jar:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
    at org.polymc.impl.OneSixLauncher.invokeMain(OneSixLauncher.java:104) ~[NewLaunch.jar:?]
    at org.polymc.impl.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:176) ~[NewLaunch.jar:?]
    at org.polymc.impl.OneSixLauncher.launch(OneSixLauncher.java:186) ~[NewLaunch.jar:?]
    at org.polymc.EntryPoint.listen(EntryPoint.java:144) ~[NewLaunch.jar:?]
    at org.polymc.EntryPoint.main(EntryPoint.java:74) ~[NewLaunch.jar:?]
1zun4 commented 10 months ago

Oh, I missed this! Please create another issue, since this was closed now. Yes, I forgot about remapping the input of the reflection util.

Otherwise use the GraalJS Java.type(...) function.

var BigDecimal = Java.type('java.math.BigDecimal');
var point1 = new BigDecimal("0.1");
var two = BigDecimal.TWO;
console.log(point1.multiply(two).toString());