Skip to content

Commit

Permalink
rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
MukjepScarlet committed Feb 24, 2025
1 parent db441bf commit 8a9d1e9
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import net.ccbluex.liquidbounce.features.command.CommandManager
import net.ccbluex.liquidbounce.features.module.ClientModule
import net.ccbluex.liquidbounce.features.module.ModuleManager
import net.ccbluex.liquidbounce.lang.translation
import net.ccbluex.liquidbounce.script.bindings.api.ScriptContextProvider
import net.ccbluex.liquidbounce.script.bindings.api.ScriptContextProvider.setupContext
import net.ccbluex.liquidbounce.script.bindings.features.ScriptChoice
import net.ccbluex.liquidbounce.script.bindings.features.ScriptCommandBuilder
import net.ccbluex.liquidbounce.script.bindings.features.ScriptModule
Expand Down Expand Up @@ -111,20 +111,14 @@ class PolyglotScript(
// Global instances
val bindings = getBindings(language)

ScriptContextProvider.setupContext(bindings)
this.setupContext(language, bindings)

// Global functions
bindings.putMember("registerScript", RegisterScript())
}

private val scriptText: String = file.readText()

internal val promiseConstructor: Value? = if (language.equals("js", true)) {
context.getBindings(language).getMember("Promise")
} else {
null
}

// Script information
lateinit var scriptName: String
lateinit var scriptVersion: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package net.ccbluex.liquidbounce.script
import com.mojang.blaze3d.systems.RenderSystem
import net.ccbluex.liquidbounce.config.ConfigSystem
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleClickGui
import net.ccbluex.liquidbounce.script.bindings.api.ScriptAsyncUtil
import net.ccbluex.liquidbounce.utils.client.logger
import org.graalvm.polyglot.Engine
import org.graalvm.polyglot.Source
Expand Down Expand Up @@ -50,6 +51,8 @@ object ScriptManager {
}

init {
ScriptAsyncUtil.TickScheduler

try {
// Initialize the script engine and log its version and supported languages.
val engine = Engine.create()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce)
*
* Copyright (c) 2015 - 2025 CCBlueX
*
* LiquidBounce is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiquidBounce is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LiquidBounce. If not, see <https://www.gnu.org/licenses/>.
*/
package net.ccbluex.liquidbounce.script.bindings.api

import net.ccbluex.liquidbounce.event.EventListener
import net.ccbluex.liquidbounce.event.events.GameTickEvent
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.script.ScriptApiRequired
import net.ccbluex.liquidbounce.utils.client.mc
import net.ccbluex.liquidbounce.utils.kotlin.EventPriorityConvention.FIRST_PRIORITY
import org.graalvm.polyglot.Value
import org.graalvm.polyglot.proxy.ProxyExecutable
import java.util.function.BooleanSupplier

/**
* @author MukjepScarlet
*/
class ScriptAsyncUtil(
private val jsPromiseConstructor: Value
) {

companion object TickScheduler : EventListener {
private val schedules = arrayListOf<BooleanSupplier>()

@Suppress("unused")
private val tickHandler = handler<GameTickEvent>(priority = FIRST_PRIORITY) {
schedules.removeIf { it.asBoolean }
}

private fun schedule(breakLoop: BooleanSupplier) {
mc.execute { schedules += breakLoop }
}
}

private val defaultPromise: Value = jsPromiseConstructor.invokeMember("resolve", 0);

/**
* Example: `await ticks(10)`
*
* @return `Promise<number>`
*/
@ScriptApiRequired
fun ticks(n: Int): Value {
if (n == 0) {
return defaultPromise
}

var remains = n
return until { --remains == 0 }
}

/**
* Example: `await seconds(1)`
*
* @return `Promise<number>`
*/
@ScriptApiRequired
fun seconds(n: Int): Value = ticks(n * 20)

/**
* Example: `const duration = await until(() => mc.player.isOnGround())`
*
* @return `Promise<number>`
*/
@ScriptApiRequired
fun until(condition: BooleanSupplier): Value = jsPromiseConstructor.newInstance(
ProxyExecutable { (onResolve, onReject) ->
var waitingTick = 0
schedule {
waitingTick++
try {
if (condition.asBoolean) {
onResolve.executeVoid(waitingTick)
true
} else {
false
}
} catch (e: Throwable) {
onReject.executeVoid(e)
true
}
}
}
)

/**
* Example: `const result = await conditional(20, () => mc.player.isOnGround())`
*
* @return `Promise<number>`
*/
@JvmOverloads
@ScriptApiRequired
fun conditional(
ticks: Int,
breakLoop: BooleanSupplier = BooleanSupplier { false }
): Value {
if (ticks == 0) {
return defaultPromise
}

var remains = ticks
return until { --remains == 0 || breakLoop.asBoolean }
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,61 @@ import net.ccbluex.liquidbounce.script.bindings.features.ScriptSetting
import net.ccbluex.liquidbounce.utils.client.mc
import net.minecraft.util.Hand
import net.minecraft.util.math.*
import org.graalvm.polyglot.Context
import org.graalvm.polyglot.Value
import java.util.function.BiFunction
import java.util.function.Function
import java.util.function.IntFunction

/**
* The main hub of the ScriptAPI that provides access to a useful set of members.
*/
object ScriptContextProvider {

internal fun setupContext(bindings: Value) = bindings.apply {
// Class bindings
// -> Client API
putMember("Setting", ScriptSetting)

// -> Minecraft API
putMember("Vec3i", Vec3i::class.java)
putMember("Vec3d", Vec3d::class.java)
putMember("MathHelper", MathHelper::class.java)
putMember("BlockPos", BlockPos::class.java)
putMember("Hand", Hand::class.java)
putMember("RotationAxis", RotationAxis::class.java)

// Variable bindings
putMember("mc", mc)
putMember("Client", ScriptClient)

// Register utilities
putMember("RotationUtil", ScriptRotationUtil)
putMember("ItemUtil", ScriptItemUtil)
putMember("NetworkUtil", ScriptNetworkUtil)
putMember("InteractionUtil", ScriptInteractionUtil)
putMember("BlockUtil", ScriptBlockUtil)
putMember("MovementUtil", ScriptMovementUtil)
putMember("ReflectionUtil", ScriptReflectionUtil())
putMember("ParameterValidator", ScriptParameterValidator(bindings))
putMember("UnsafeThread", ScriptUnsafeThread)
private lateinit var scriptAsyncUtil: ScriptAsyncUtil

internal fun Context.setupContext(language: String, bindings: Value) {
if (!::scriptAsyncUtil.isInitialized && language.equals("js", true)) {
// Init Promise constructor
scriptAsyncUtil = ScriptAsyncUtil(this.getBindings(language).getMember("Promise"))
}

bindings.apply {
// Class bindings
// -> Client API
putMember("Setting", ScriptSetting)

// -> Minecraft API
putMember("Vec3i", Vec3i::class.java)
putMember("Vec3d", Vec3d::class.java)
putMember("MathHelper", MathHelper::class.java)
putMember("BlockPos", BlockPos::class.java)
putMember("Hand", Hand::class.java)
putMember("RotationAxis", RotationAxis::class.java)

// Variable bindings
putMember("mc", mc)
putMember("Client", ScriptClient)

// Register utilities
putMember("RotationUtil", ScriptRotationUtil)
putMember("ItemUtil", ScriptItemUtil)
putMember("NetworkUtil", ScriptNetworkUtil)
putMember("InteractionUtil", ScriptInteractionUtil)
putMember("BlockUtil", ScriptBlockUtil)
putMember("MovementUtil", ScriptMovementUtil)
putMember("ReflectionUtil", ScriptReflectionUtil())
putMember("ParameterValidator", ScriptParameterValidator(bindings))
putMember("UnsafeThread", ScriptUnsafeThread)

// Async support
if (::scriptAsyncUtil.isInitialized) {
putMember("ticks", IntFunction(scriptAsyncUtil::ticks))
putMember("seconds", IntFunction(scriptAsyncUtil::seconds))
putMember("until", Function(scriptAsyncUtil::until))
putMember("conditional", BiFunction(scriptAsyncUtil::conditional))
}
}
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import net.ccbluex.liquidbounce.event.*
import net.ccbluex.liquidbounce.features.module.Category
import net.ccbluex.liquidbounce.features.module.ClientModule
import net.ccbluex.liquidbounce.script.PolyglotScript
import net.ccbluex.liquidbounce.script.bindings.async.JsSequenceHandler
import net.ccbluex.liquidbounce.utils.client.*
import java.util.function.Supplier
import kotlin.reflect.KClass
Expand All @@ -34,7 +33,6 @@ class ScriptModule(val script: PolyglotScript, moduleObject: Map<String, Any>) :
) {

private val events = hashMapOf<String, org.graalvm.polyglot.Value>()
private val eventSequences = hashMapOf<String, JsSequenceHandler>()
private val _values = linkedMapOf<String, Value<*>>()
private var _tag: String? = null
override val tag: String?
Expand Down Expand Up @@ -80,16 +78,7 @@ class ScriptModule(val script: PolyglotScript, moduleObject: Map<String, Any>) :
return
}

when (handler.getMember("constructor").getMember("name").asString()) {
"Function" -> {
events[eventName] = handler
}
"AsyncFunction" -> script.promiseConstructor?.let {
eventSequences[eventName] = JsSequenceHandler(this, it, handler)
}
else -> { /* ??? */ }
}

events[eventName] = handler
hookHandler(eventName)
}

Expand All @@ -105,7 +94,6 @@ class ScriptModule(val script: PolyglotScript, moduleObject: Map<String, Any>) :
private fun callEvent(event: String, payload: Event? = null) {
try {
events[event]?.executeVoid(payload)
eventSequences[event]?.startWith(payload)
} catch (throwable: Throwable) {
if (inGame) {
chat(
Expand Down

0 comments on commit 8a9d1e9

Please sign in to comment.