diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptAsyncApi.kt b/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptAsyncApi.kt new file mode 100644 index 00000000000..c95d67beb32 --- /dev/null +++ b/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptAsyncApi.kt @@ -0,0 +1,74 @@ +/* + * 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 . + */ +package net.ccbluex.liquidbounce.script.bindings.api + +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap +import kotlinx.coroutines.* +import net.ccbluex.liquidbounce.features.module.MinecraftShortcuts +import org.graalvm.polyglot.Value +import java.util.function.IntConsumer + +@Suppress("SpreadOperator", "unused") +object ScriptAsyncApi : MinecraftShortcuts { + + private val MainDispatcher = mc.asCoroutineDispatcher() + + private val scope = CoroutineScope(MainDispatcher + SupervisorJob()) + + private var idCounter = 0 + + private val timeoutMap = Int2ObjectOpenHashMap() + private val intervalMap = Int2ObjectOpenHashMap() + + @FunctionalInterface // this is needed for Polyglot script functions + internal fun interface SetFunction { + operator fun invoke(callback: Value, delay: Long, vararg arguments: Any?): Int + } + + internal val setTimeout = SetFunction { callback, delay, arguments -> + val id = ++idCounter + timeoutMap.put(id, scope.launch { + delay(delay) + callback.executeVoid(*arguments) + timeoutMap.remove(id) + }) + id + } + + internal val clearTimeout = IntConsumer { id -> + timeoutMap.remove(id)?.cancel() + } + + internal val setInterval = SetFunction { callback, delay, arguments -> + val id = ++idCounter + intervalMap.put(id, scope.launch { + while (isActive) { + delay(delay) + callback.executeVoid(*arguments) + intervalMap.remove(id) + } + }) + id + } + + internal val clearInterval = IntConsumer { id -> + intervalMap.remove(id)?.cancel() + } + +} diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptContextProvider.kt b/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptContextProvider.kt index ded2eebcc74..6f8e537a8c6 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptContextProvider.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/script/bindings/api/ScriptContextProvider.kt @@ -56,6 +56,12 @@ object ScriptContextProvider { putMember("ReflectionUtil", ScriptReflectionUtil()) putMember("ParameterValidator", ScriptParameterValidator(bindings)) putMember("UnsafeThread", ScriptUnsafeThread) + + // timeout and interval functions + putMember("setTimeout", ScriptAsyncApi.setTimeout) + putMember("clearTimeout", ScriptAsyncApi.clearTimeout) + putMember("setInterval", ScriptAsyncApi.setInterval) + putMember("clearInterval", ScriptAsyncApi.clearInterval) } }