diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ActionManager.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ActionManager.kt index 6a01398d..b9b46962 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ActionManager.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ActionManager.kt @@ -1,11 +1,12 @@ package cn.fd.ratziel.module.item.impl.feature.action import cn.fd.ratziel.core.Identifier +import cn.fd.ratziel.function.argument.SimpleArgumentContext import cn.fd.ratziel.module.item.api.feature.ItemTrigger import cn.fd.ratziel.module.item.impl.feature.action.triggers.* import cn.fd.ratziel.module.item.impl.service.NativeServiceRegistry -import cn.fd.ratziel.script.ScriptEnvironment -import cn.fd.ratziel.script.SimpleScriptEnv +import cn.fd.ratziel.script.api.ScriptEnvironment +import cn.fd.ratziel.script.impl.SimpleScriptEnvironment import java.util.concurrent.ConcurrentHashMap /** @@ -42,15 +43,17 @@ object ActionManager { fun trigger(identifier: Identifier, trigger: ItemTrigger, environment: ScriptEnvironment) { // 获取物品动作 val action = actionMap[identifier]?.get(trigger) - // 设置绑定键 - environment.context.add(environment.bindings) +// // 设置绑定键 +// environment.context.add(environment.bindings) +// // 执行物品动作 +// action?.execute(environment.context)// // 执行物品动作 - action?.execute(environment.context) + action?.execute(SimpleArgumentContext(environment)) } @JvmStatic fun trigger(identifier: Identifier, trigger: ItemTrigger, function: ScriptEnvironment.() -> Unit) = - trigger(identifier, trigger, SimpleScriptEnv().apply(function)) + trigger(identifier, trigger, SimpleScriptEnvironment().apply(function)) /** * 匹配 [TriggerMap] diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ScriptedAction.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ScriptedAction.kt index ca549cc9..3c4135b9 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ScriptedAction.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/feature/action/ScriptedAction.kt @@ -2,11 +2,10 @@ package cn.fd.ratziel.module.item.impl.feature.action import cn.fd.ratziel.function.argument.ArgumentContext import cn.fd.ratziel.module.item.api.feature.ItemAction -import cn.fd.ratziel.script.ScriptBlockBuilder -import cn.fd.ratziel.script.ScriptManager -import cn.fd.ratziel.script.SimpleScriptEnv -import javax.script.Bindings -import javax.script.SimpleBindings +import cn.fd.ratziel.script.ScriptTypes +import cn.fd.ratziel.script.api.EvaluableScript +import cn.fd.ratziel.script.api.ScriptEnvironment +import cn.fd.ratziel.script.impl.SimpleScriptEnvironment /** * ScriptedAction @@ -18,16 +17,14 @@ open class ScriptedAction( /** * 脚本动作块 */ - val script: ScriptBlockBuilder.Block, + val script: EvaluableScript, ) : ItemAction { override fun execute(context: ArgumentContext) { - // 获取绑定键 - val bindings: Bindings = context.popOr(Bindings::class.java, SimpleBindings()) // 环境 - val env = SimpleScriptEnv(bindings, context) - // 执行 - script.evaluate(ScriptManager.defaultLang, env) + val env = context.popOr(ScriptEnvironment::class.java, SimpleScriptEnvironment()) + // 评估 + script.evaluate(ScriptTypes.KETHER.executor, env) } } \ No newline at end of file diff --git a/project/module-script/build.gradle.kts b/project/module-script/build.gradle.kts index 01c8bd24..ce6666f1 100644 --- a/project/module-script/build.gradle.kts +++ b/project/module-script/build.gradle.kts @@ -1,6 +1,5 @@ dependencies { // Kotlin Script - compileOnly(kotlin("main-kts")) compileOnly(kotlin("scripting-common")) compileOnly(kotlin("scripting-jvm")) compileOnly(kotlin("scripting-jvm-host")) diff --git a/project/module-script/src/main/java/cn/fd/ratziel/core/env/ScriptEnv.java b/project/module-script/src/main/java/cn/fd/ratziel/core/env/ScriptEnv.java index 342b1311..9848bfe9 100644 --- a/project/module-script/src/main/java/cn/fd/ratziel/core/env/ScriptEnv.java +++ b/project/module-script/src/main/java/cn/fd/ratziel/core/env/ScriptEnv.java @@ -17,7 +17,7 @@ transitive = false ), @RuntimeDependency( - value = "!org.jetbrains.kotlin:kotlin-compiler-embeddable:" + CoreEnv.KOTLIN_VERSION, + value = "!org.jetbrains.kotlin:kotlin-compiler:" + CoreEnv.KOTLIN_VERSION, transitive = false ), @RuntimeDependency( @@ -33,19 +33,19 @@ transitive = false ), @RuntimeDependency( - value = "!org.jetbrains.kotlin:kotlin-scripting-jvm-host:" + CoreEnv.KOTLIN_VERSION, + value = "!org.jetbrains.kotlin:kotlin-scripting-jvm-host-unshaded:" + CoreEnv.KOTLIN_VERSION, transitive = false ), @RuntimeDependency( - value = "!org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:" + CoreEnv.KOTLIN_VERSION, + value = "!org.jetbrains.kotlin:kotlin-scripting-compiler:" + CoreEnv.KOTLIN_VERSION, transitive = false ), @RuntimeDependency( - value = "!org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:" + CoreEnv.KOTLIN_VERSION, + value = "!org.jetbrains.kotlin:kotlin-scripting-compiler-impl:" + CoreEnv.KOTLIN_VERSION, transitive = false ), @RuntimeDependency( - value = "!org.jetbrains.kotlin:kotlin-scripting-jsr223:" + CoreEnv.KOTLIN_VERSION, + value = "!org.jetbrains.kotlin:kotlin-scripting-jsr223-unshaded:" + CoreEnv.KOTLIN_VERSION, transitive = false ), @RuntimeDependency( diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/EnginedScriptLanguage.java b/project/module-script/src/main/java/cn/fd/ratziel/script/EnginedScriptLanguage.java deleted file mode 100644 index 5efcfbba..00000000 --- a/project/module-script/src/main/java/cn/fd/ratziel/script/EnginedScriptLanguage.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.fd.ratziel.script; - -import org.jetbrains.annotations.NotNull; - -import javax.script.*; - -/** - * EnginedScriptLanguage - * - * @author TheFloodDragon - * @since 2024/6/30 16:39 - */ -public abstract class EnginedScriptLanguage extends ReleasableScriptLanguage { - - public EnginedScriptLanguage(@NotNull String engine, @NotNull String... names) { - super(names); - this.ENGINE_NAME = engine; - } - - @NotNull - private final String ENGINE_NAME; - - @Override - public Object eval(@NotNull ScriptStorage script, @NotNull ScriptEnvironment environment) throws ScriptException { - // 创建脚本引擎 - ScriptEngine engine = newEngine(); - // 获取编译后的脚本 - CompiledScript compiled = script.getCompiled(); - if (compiled == null) { - // 没有时编译一份 - CompiledScript newCompiled = ((Compilable) engine).compile(script.getContent()); - script.setCompiled(newCompiled); // 将其设置到 ScriptStorage 中 - compiled = newCompiled; - } - // 评估脚本 - return compiled.eval(environment.getBindings()); - } - - public ScriptEngine newEngine() { - ClassLoader classLoader = this.getClass().getClassLoader(); - ScriptEngine engine = new ScriptEngineManager(classLoader).getEngineByName(ENGINE_NAME); - if (engine != null) return engine; - else throw new NullPointerException("Cannot get ScriptEngine by name: " + ENGINE_NAME + " !"); - } - -} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/RawScript.java b/project/module-script/src/main/java/cn/fd/ratziel/script/RawScript.java deleted file mode 100644 index ccf3d4e6..00000000 --- a/project/module-script/src/main/java/cn/fd/ratziel/script/RawScript.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.fd.ratziel.script; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.script.CompiledScript; - -/** - * RawScript - * - * @author TheFloodDragon - * @since 2024/6/30 12:02 - */ -public class RawScript implements ScriptStorage { - - public RawScript(@NotNull String script) { - this.content = script; - } - - @NotNull - private final String content; - @Nullable - private CompiledScript compiledScript = null; - - @Override - public @NotNull String getContent() { - return content; - } - - @Override - public @Nullable CompiledScript getCompiled() { - return compiledScript; - } - - @Override - public void setCompiled(@NotNull CompiledScript compiled) { - this.compiledScript = compiled; - } - -} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/ReleasableScriptLanguage.java b/project/module-script/src/main/java/cn/fd/ratziel/script/ReleasableScriptLanguage.java deleted file mode 100644 index 66fb6f1a..00000000 --- a/project/module-script/src/main/java/cn/fd/ratziel/script/ReleasableScriptLanguage.java +++ /dev/null @@ -1,63 +0,0 @@ -package cn.fd.ratziel.script; - -import org.jetbrains.annotations.NotNull; - -import javax.script.ScriptException; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * ReleasableScriptLanguage - * - * @author TheFloodDragon - * @since 2024/7/3 15:41 - */ -public abstract class ReleasableScriptLanguage implements ScriptLanguage { - - public interface ScriptEnvReleaser { - - void release(@NotNull ScriptEnvironment env); - - } - - public ReleasableScriptLanguage(@NotNull String... names) { - this.NAMES = names; - this.releasers = new CopyOnWriteArrayList<>(); - } - - @NotNull - private final String[] NAMES; - - @NotNull - protected List releasers; - - abstract Object eval(@NotNull ScriptStorage script, @NotNull ScriptEnvironment env) throws ScriptException; - - @Override - public Object evaluate(@NotNull ScriptStorage script, @NotNull ScriptEnvironment environment) throws ScriptException { - // 释放环境中的参数变量到脚本变量中 - for (ScriptEnvReleaser releaser : releasers) { - releaser.release(environment); - } - // 评估脚本 - return eval(script, environment); - } - - public void addReleaser(@NotNull ScriptEnvReleaser releaser) { - releasers.add(releaser); - } - - public void removeReleaser(@NotNull ScriptEnvReleaser releaser) { - releasers.remove(releaser); - } - - public @NotNull List getReleasers() { - return releasers; - } - - @Override - public @NotNull String[] getNames() { - return NAMES; - } - -} \ No newline at end of file diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/ScriptEnvironment.java b/project/module-script/src/main/java/cn/fd/ratziel/script/ScriptEnvironment.java deleted file mode 100644 index 63013d1a..00000000 --- a/project/module-script/src/main/java/cn/fd/ratziel/script/ScriptEnvironment.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.fd.ratziel.script; - -import cn.fd.ratziel.function.argument.ArgumentContext; -import org.jetbrains.annotations.NotNull; - -import javax.script.Bindings; - -/** - * ScriptEnvironment - 脚本环境 - * - * @author TheFloodDragon - * @since 2024/6/30 09:33 - */ -public interface ScriptEnvironment { - - /** - * 获取环境中的绑定键 - */ - @NotNull - Bindings getBindings(); - - /** - * 获取环境中的参数上下文 - */ - @NotNull - ArgumentContext getContext(); - - /** - * 设置绑定内容 - */ - default void set(String key, Object value) { - getBindings().put(key, value); - } - -} \ No newline at end of file diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/SimpleScriptEnv.java b/project/module-script/src/main/java/cn/fd/ratziel/script/SimpleScriptEnv.java deleted file mode 100644 index e4d7f776..00000000 --- a/project/module-script/src/main/java/cn/fd/ratziel/script/SimpleScriptEnv.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.fd.ratziel.script; - -import cn.fd.ratziel.function.argument.ArgumentContext; -import cn.fd.ratziel.function.argument.SimpleArgumentContext; -import org.jetbrains.annotations.NotNull; - -import javax.script.Bindings; -import javax.script.SimpleBindings; - -/** - * SimpleScriptEnv - * - * @author TheFloodDragon - * @since 2024/6/30 11:31 - */ -public class SimpleScriptEnv implements ScriptEnvironment { - - public SimpleScriptEnv() { - this(new SimpleBindings()); - } - - public SimpleScriptEnv(@NotNull Bindings bindings) { - this(bindings, new SimpleArgumentContext()); - } - - public SimpleScriptEnv(@NotNull Bindings bindings, @NotNull ArgumentContext argumentContext) { - this.bindings = bindings; - this.context = argumentContext; - } - - @NotNull - private final Bindings bindings; - @NotNull - private final ArgumentContext context; - - @Override - public @NotNull Bindings getBindings() { - return bindings; - } - - @Override - public @NotNull ArgumentContext getContext() { - return context; - } - -} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/api/EvaluableScript.java b/project/module-script/src/main/java/cn/fd/ratziel/script/api/EvaluableScript.java new file mode 100644 index 00000000..ec36be1b --- /dev/null +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/api/EvaluableScript.java @@ -0,0 +1,27 @@ +package cn.fd.ratziel.script.api; + + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.script.ScriptException; + +/** + * EvaluableScript + * + * @author TheFloodDragon + * @since 2024/7/15 13:14 + */ +public interface EvaluableScript { + + /** + * 评估脚本 + * + * @param executor 覆写的脚本执行器 + * @param environment 覆写的的脚本环境 + * @throws ScriptException 当脚本评估中产生错误时抛出 + */ + @Nullable + Object evaluate(@NotNull ScriptExecutor executor, @NotNull ScriptEnvironment environment) throws ScriptException; + +} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptContent.java b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptContent.java new file mode 100644 index 00000000..5c210edd --- /dev/null +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptContent.java @@ -0,0 +1,16 @@ +package cn.fd.ratziel.script.api; + +/** + * ScriptContent + * + * @author TheFloodDragon + * @since 2024/7/14 21:28 + */ +public interface ScriptContent { + + /** + * 获取脚本原始内容 + */ + String getContent(); + +} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptEnvironment.java b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptEnvironment.java new file mode 100644 index 00000000..6bb2f50f --- /dev/null +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptEnvironment.java @@ -0,0 +1,37 @@ +package cn.fd.ratziel.script.api; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.script.Bindings; + +/** + * ScriptEnvironment - 脚本环境 + * + * @author TheFloodDragon + * @since 2024/7/15 13:20 + */ +public interface ScriptEnvironment { + + /** + * 获取脚本的所有绑定 + */ + @NotNull + Bindings getBindings(); + + /** + * 设置脚本的所有绑定 + */ + void setBindings(@NotNull Bindings bindings); + + /** + * 设置绑定内容 + * + * @param key 绑定键 + * @param value 绑定内容 + */ + default void set(@NotNull String key, @Nullable Object value) { + getBindings().put(key, value); + } + +} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/ScriptLanguage.java b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptExecutor.java similarity index 58% rename from project/module-script/src/main/java/cn/fd/ratziel/script/ScriptLanguage.java rename to project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptExecutor.java index 729d2053..6de73177 100644 --- a/project/module-script/src/main/java/cn/fd/ratziel/script/ScriptLanguage.java +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptExecutor.java @@ -1,22 +1,17 @@ -package cn.fd.ratziel.script; +package cn.fd.ratziel.script.api; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.script.ScriptException; /** - * ScriptLanguage + * ScriptExecutor - 脚本执行者 * * @author TheFloodDragon - * @since 2024/6/30 08:16 + * @since 2024/7/14 21:26 */ -public interface ScriptLanguage { - - /** - * 获取脚本的所有名称 - */ - @NotNull - String[] getNames(); +public interface ScriptExecutor { /** * 评估脚本 @@ -25,6 +20,7 @@ public interface ScriptLanguage { * @param environment 脚本环境 * @throws ScriptException 当脚本评估中产生错误时抛出 */ - Object evaluate(@NotNull ScriptStorage script, @NotNull ScriptEnvironment environment) throws ScriptException; + @Nullable + Object evaluate(@NotNull ScriptContent script, @NotNull ScriptEnvironment environment) throws ScriptException; -} \ No newline at end of file +} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptType.java b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptType.java new file mode 100644 index 00000000..2b7377b4 --- /dev/null +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/api/ScriptType.java @@ -0,0 +1,25 @@ +package cn.fd.ratziel.script.api; + +import org.jetbrains.annotations.NotNull; + +/** + * ScriptType - 脚本类型 + * + * @author TheFloodDragon + * @since 2024/7/14 21:23 + */ +public interface ScriptType { + + /** + * 获取脚本的所有名称 + */ + @NotNull + String[] getNames(); + + /** + * 获取脚本执行器 + */ + @NotNull + ScriptExecutor getExecutor(); + +} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/ScriptStorage.java b/project/module-script/src/main/java/cn/fd/ratziel/script/api/StorableScript.java similarity index 59% rename from project/module-script/src/main/java/cn/fd/ratziel/script/ScriptStorage.java rename to project/module-script/src/main/java/cn/fd/ratziel/script/api/StorableScript.java index 99efbed4..54cf0307 100644 --- a/project/module-script/src/main/java/cn/fd/ratziel/script/ScriptStorage.java +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/api/StorableScript.java @@ -1,4 +1,4 @@ -package cn.fd.ratziel.script; +package cn.fd.ratziel.script.api; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -6,23 +6,15 @@ import javax.script.CompiledScript; /** - * ScriptStorage - 脚本 + * StorableScript * * @author TheFloodDragon - * @since 2024/6/30 08:14 + * @since 2024/7/15 13:18 */ -public interface ScriptStorage { +public interface StorableScript { /** - * 获取脚本内容 - * - * @return 脚本的字符串形式 - */ - @NotNull - String getContent(); - - /** - * 编译过后的脚本 + * 获取编译过后的脚本 * * @return 如果此脚本不能被编译, 则返回空 */ @@ -34,4 +26,4 @@ public interface ScriptStorage { */ void setCompiled(@NotNull CompiledScript compiled); -} \ No newline at end of file +} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/impl/SimpleScript.java b/project/module-script/src/main/java/cn/fd/ratziel/script/impl/SimpleScript.java new file mode 100644 index 00000000..5bea48cc --- /dev/null +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/impl/SimpleScript.java @@ -0,0 +1,62 @@ +package cn.fd.ratziel.script.impl; + +import cn.fd.ratziel.script.api.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptException; + +/** + * SimpleScript + * + * @author TheFloodDragon + * @since 2024/7/15 13:25 + */ +public class SimpleScript implements EvaluableScript, StorableScript, ScriptContent { + + public SimpleScript(@NotNull String content) { + this.content = content; + } + + private final String content; + private CompiledScript compiledScript = null; + + @Override + public @Nullable Object evaluate(@NotNull ScriptExecutor executor, @NotNull ScriptEnvironment environment) throws ScriptException { + // 若脚本没经过编译, 并且该脚本执行器可以编译此脚本 + if (compiledScript == null && executor instanceof Compilable) { + // 编译脚本 + CompiledScript compiled = ((Compilable) executor).compile(getContent()); + // 存储编译后的脚本 + setCompiled(compiled); + // 直接评估脚本 + return compiled.eval(environment.getBindings()); + } else { + // 通过执行器评估脚本 + return executor.evaluate(this, environment); + } + } + + @Override + public @Nullable CompiledScript getCompiled() { + return compiledScript; + } + + @Override + public void setCompiled(@NotNull CompiledScript compiled) { + this.compiledScript = compiled; + } + + @Override + public String getContent() { + return content; + } + + @Override + public String toString() { + return getContent(); + } + +} diff --git a/project/module-script/src/main/java/cn/fd/ratziel/script/impl/SimpleScriptEnvironment.java b/project/module-script/src/main/java/cn/fd/ratziel/script/impl/SimpleScriptEnvironment.java new file mode 100644 index 00000000..bfa4be39 --- /dev/null +++ b/project/module-script/src/main/java/cn/fd/ratziel/script/impl/SimpleScriptEnvironment.java @@ -0,0 +1,37 @@ +package cn.fd.ratziel.script.impl; + +import cn.fd.ratziel.script.api.ScriptEnvironment; +import org.jetbrains.annotations.NotNull; + +import javax.script.Bindings; +import javax.script.SimpleBindings; + +/** + * SimpleScriptEnvironment + * + * @author TheFloodDragon + * @since 2024/7/15 13:41 + */ +public class SimpleScriptEnvironment implements ScriptEnvironment { + + public SimpleScriptEnvironment() { + this(new SimpleBindings()); + } + + public SimpleScriptEnvironment(@NotNull Bindings bindings) { + this.bindings = bindings; + } + + private Bindings bindings; + + @Override + public @NotNull Bindings getBindings() { + return bindings; + } + + @Override + public void setBindings(@NotNull Bindings bindings) { + this.bindings = bindings; + } + +} diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/JavaScriptLang.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/JavaScriptLang.kt deleted file mode 100644 index 858890c0..00000000 --- a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/JavaScriptLang.kt +++ /dev/null @@ -1,12 +0,0 @@ -package cn.fd.ratziel.script - -/** - * JavaScriptLang - * - * @author TheFloodDragon - * @since 2024/6/30 15:57 - */ -object JavaScriptLang : EnginedScriptLanguage( - "nashorn", // 引擎名称 - "js", "JavaScript", "javascript", "java-script", "JS" // 语言名称 -) \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/JexlLang.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/JexlLang.kt deleted file mode 100644 index 701b059e..00000000 --- a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/JexlLang.kt +++ /dev/null @@ -1,12 +0,0 @@ -package cn.fd.ratziel.script - -/** - * JexlLang - * - * @author TheFloodDragon - * @since 2024/6/30 16:03 - */ -object JexlLang : EnginedScriptLanguage( - "Jexl", // 引擎名称 - "jexl", "Jexl", "Jexl3", "jexl3" // 语言名称 -) \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/KetherLang.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/KetherLang.kt deleted file mode 100644 index 7e72daf4..00000000 --- a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/KetherLang.kt +++ /dev/null @@ -1,20 +0,0 @@ -package cn.fd.ratziel.script - -import taboolib.module.kether.KetherShell -import taboolib.module.kether.ScriptOptions - -/** - * KetherLang - * - * @author TheFloodDragon - * @since 2024/6/30 10:14 - */ -object KetherLang : ReleasableScriptLanguage( - "kether", "Kether", "ke", "ks" // 语言名称 -) { - - override fun eval(script: ScriptStorage, environment: ScriptEnvironment): Any { - return KetherShell.eval(script.content, ScriptOptions.new { vars(environment.bindings) }) - } - -} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/KotlinScriptLang.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/KotlinScriptLang.kt deleted file mode 100644 index 21b9be26..00000000 --- a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/KotlinScriptLang.kt +++ /dev/null @@ -1,12 +0,0 @@ -package cn.fd.ratziel.script - -/** - * KotlinScriptLang - * - * @author TheFloodDragon - * @since 2024/7/14 15:40 - */ -object KotlinScriptLang : EnginedScriptLanguage( - "kotlin", // 引擎名称 - "Kotlin", "kotlin", "kts", "KTS" // 语言名称 -) \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/Releasers.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/Releasers.kt deleted file mode 100644 index ed267ae1..00000000 --- a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/Releasers.kt +++ /dev/null @@ -1,35 +0,0 @@ -package cn.fd.ratziel.script - -import taboolib.common.platform.Awake -import taboolib.common.platform.ProxyCommandSender -import javax.script.Bindings - -/** - * Releasers - * - * @author TheFloodDragon - * @since 2024/7/8 15:32 - */ -@Awake -internal object Releasers { - - @Awake - fun init() { - // CommandSender - releaserFor(KetherLang) { - put("@Sender", it) - } - releaserFor(JavaScriptLang, JexlLang) { - put("sender", it) - } - } - - private inline fun releaserFor(vararg languages: ReleasableScriptLanguage, crossinline action: Bindings.(T?) -> Unit) { - for (lang in languages) { - lang.addReleaser { - it.bindings.action(it.context.popOrNull(T::class.java)) - } - } - } - -} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptBlockBuilder.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptBlockBuilder.kt index 3d842807..66f40aa8 100644 --- a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptBlockBuilder.kt +++ b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptBlockBuilder.kt @@ -1,5 +1,11 @@ package cn.fd.ratziel.script +import cn.fd.ratziel.script.api.EvaluableScript +import cn.fd.ratziel.script.api.ScriptContent +import cn.fd.ratziel.script.api.ScriptEnvironment +import cn.fd.ratziel.script.api.ScriptExecutor +import cn.fd.ratziel.script.impl.SimpleScript + /** * ScriptBlockBuilder @@ -9,10 +15,10 @@ package cn.fd.ratziel.script */ object ScriptBlockBuilder { - fun build(section: Any): Block { + fun build(section: Any): ScriptBlock { when (section) { - // ScriptBlock - is String -> return ScriptBlock(RawScript(section)) + // Block + is String -> return Block(SimpleScript(section)) // ListBlock is Iterable<*> -> return ListBlock(section.mapNotNull { l -> l?.let { build(it) } }) is Map<*, *> -> { @@ -27,13 +33,13 @@ object ScriptBlockBuilder { elseValue?.let { build(it) } ) } else { - // ToggleLangBlock + // OverrideExecutorBlock for (e in section) { val key = e.key.toString().trim() if (key.startsWith(MARK_TOGGLE)) { - val lang = ScriptManager.findLang(key.drop(MARK_TOGGLE.length)) + val type = ScriptTypes.matchOrThrow(key.drop(MARK_TOGGLE.length)) val value = e.value - if (value != null) return ToggleLangBlock(lang, build(value)) + if (value != null) return OverrideExecutorBlock(type.executor, build(value)) } } } @@ -46,39 +52,38 @@ object ScriptBlockBuilder { const val MARK_TOGGLE = "\$" - interface Block { - fun evaluate(lang: ScriptLanguage, env: ScriptEnvironment): Any? - } + interface ScriptBlock : EvaluableScript - data class PrimitiveBlock(val value: Any?) : Block { - override fun evaluate(lang: ScriptLanguage, env: ScriptEnvironment) = value + data class Block(val content: ScriptContent) : ScriptBlock { + override fun evaluate(executor: ScriptExecutor, env: ScriptEnvironment): Any? = executor.evaluate(content, env) } - data class ScriptBlock(val raw: ScriptStorage) : Block { - override fun evaluate(lang: ScriptLanguage, env: ScriptEnvironment): Any? = lang.evaluate(raw, env) + data class PrimitiveBlock(val value: Any?) : ScriptBlock { + override fun evaluate(executor: ScriptExecutor, env: ScriptEnvironment) = value } - data class ListBlock(val list: Iterable) : Block { - override fun evaluate(lang: ScriptLanguage, env: ScriptEnvironment): Any? { + data class ListBlock(val list: Iterable) : ScriptBlock { + override fun evaluate(executor: ScriptExecutor, env: ScriptEnvironment): Any? { var result: Any? = null for (raw in list) { - result = raw.evaluate(lang, env) + result = raw.evaluate(executor, env) } return result } } - data class ToggleLangBlock(val newLang: ScriptLanguage, val block: Block) : Block { - override fun evaluate(lang: ScriptLanguage, env: ScriptEnvironment): Any? = block.evaluate(newLang, env) + data class OverrideExecutorBlock(val newExecutor: ScriptExecutor, val block: ScriptBlock) : ScriptBlock { + override fun evaluate(executor: ScriptExecutor, env: ScriptEnvironment): Any? = evaluate(env) + fun evaluate(env: ScriptEnvironment): Any? = block.evaluate(newExecutor, env) } data class ConditionBlock( - val ifBlock: Block, - val thenBlock: Block?, - val elseBlock: Block? - ) : Block { - override fun evaluate(lang: ScriptLanguage, env: ScriptEnvironment): Any? { - return if (ifBlock.evaluate(lang, env) == true) thenBlock?.evaluate(lang, env) else elseBlock?.evaluate(lang, env) + val ifBlock: ScriptBlock, + val thenBlock: ScriptBlock?, + val elseBlock: ScriptBlock? + ) : ScriptBlock { + override fun evaluate(executor: ScriptExecutor, env: ScriptEnvironment): Any? { + return if (ifBlock.evaluate(executor, env) == true) thenBlock?.evaluate(executor, env) else elseBlock?.evaluate(executor, env) } } diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptManager.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptManager.kt deleted file mode 100644 index a4ef97c5..00000000 --- a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptManager.kt +++ /dev/null @@ -1,45 +0,0 @@ -package cn.fd.ratziel.script - -/** - * ScriptManager - * - * @author TheFloodDragon - * @since 2024/6/30 12:06 - */ -object ScriptManager { - - /** - * 使用的脚本语言 - * |- Kether, JavaScript, Jexl3, Kotlin Script - */ - @JvmStatic - var scriptLanguages: Array = arrayOf(KetherLang, JavaScriptLang, JexlLang, KotlinScriptLang) - private set - - /** - * 默认语言 - */ - var defaultLang: ScriptLanguage = scriptLanguages.first() - - /** - * 通过ID获取 [ScriptLanguage] - */ - @JvmStatic - fun findLang(id: String): ScriptLanguage { - for (lang in scriptLanguages) { - if (lang.names.contains(id)) return lang - } - throw IllegalArgumentException("Couldn't find ScriptLanguage with id: $id") - } - - @JvmStatic - fun register(lang: ScriptLanguage) { - scriptLanguages = scriptLanguages.plus(lang) - } - - @JvmStatic - fun unregister(lang: ScriptLanguage) { - scriptLanguages = scriptLanguages.toMutableSet().also { it.remove(lang) }.toTypedArray() - } - -} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptTypes.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptTypes.kt new file mode 100644 index 00000000..c1ae3e15 --- /dev/null +++ b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/ScriptTypes.kt @@ -0,0 +1,44 @@ +package cn.fd.ratziel.script + +import cn.fd.ratziel.script.api.ScriptExecutor +import cn.fd.ratziel.script.api.ScriptType +import cn.fd.ratziel.script.executors.JavaScriptExecutor +import cn.fd.ratziel.script.executors.JexlExecutor +import cn.fd.ratziel.script.executors.KetherExecutor +import cn.fd.ratziel.script.executors.KotlinScriptExecutor + +/** + * ScriptTypes + * + * @author TheFloodDragon + * @since 2024/7/14 21:35 + */ +enum class ScriptTypes(private val executor: ScriptExecutor, private vararg val names: String) : ScriptType { + + JAVASCRIPT(JavaScriptExecutor, "js", "JavaScript", "javascript", "java-script", "JS"), + KETHER(KetherExecutor, "Kether", "kether", "ke", "ks"), + JEXL(JexlExecutor, "Jexl", "jexl", "Jexl3", "jexl3"), + KOTLIN_SCRIPTING(KotlinScriptExecutor, "Kotlin", "kotlin", "kts", "KTS"); + + override fun getExecutor() = executor + + override fun getNames() = names + + companion object { + + /** + * 匹配脚本类型 (无法找到时抛出异常) + */ + @JvmStatic + fun matchOrThrow(name: String): ScriptType = + match(name) ?: throw IllegalArgumentException("Couldn't find ScriptLanguage with id: $name") + + /** + * 匹配脚本类型 + */ + @JvmStatic + fun match(name: String): ScriptType? = entries.find { it.names.contains(name) } + + } + +} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/JavaScriptExecutor.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/JavaScriptExecutor.kt new file mode 100644 index 00000000..185837c9 --- /dev/null +++ b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/JavaScriptExecutor.kt @@ -0,0 +1,32 @@ +package cn.fd.ratziel.script.executors + +import cn.fd.ratziel.script.api.ScriptContent +import cn.fd.ratziel.script.api.ScriptEnvironment +import cn.fd.ratziel.script.impl.CompilableScriptExecutor +import javax.script.Compilable +import javax.script.CompiledScript +import javax.script.ScriptEngine +import javax.script.ScriptEngineManager + +/** + * JavaScriptExecutor + * + * @author TheFloodDragon + * @since 2024/7/14 21:40 + */ +object JavaScriptExecutor : CompilableScriptExecutor { + + override fun compile(script: String?): CompiledScript { + return (engine as Compilable).compile(script) + } + + override fun evaluate(script: ScriptContent, environment: ScriptEnvironment): Any? { + return engine.eval(script.content, environment.bindings) + } + + val engine: ScriptEngine by lazy { + ScriptEngineManager(this::class.java.classLoader).getEngineByName("js") + ?: throw NullPointerException("Cannot find ScriptEngine for JavaScriptExecutor") + } + +} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/JexlExecutor.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/JexlExecutor.kt new file mode 100644 index 00000000..122ac6ff --- /dev/null +++ b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/JexlExecutor.kt @@ -0,0 +1,32 @@ +package cn.fd.ratziel.script.executors + +import cn.fd.ratziel.script.api.ScriptContent +import cn.fd.ratziel.script.api.ScriptEnvironment +import cn.fd.ratziel.script.impl.CompilableScriptExecutor +import javax.script.Compilable +import javax.script.CompiledScript +import javax.script.ScriptEngine +import javax.script.ScriptEngineManager + +/** + * JexlExecutor + * + * @author TheFloodDragon + * @since 2024/7/14 21:41 + */ +object JexlExecutor : CompilableScriptExecutor { + + override fun compile(script: String?): CompiledScript { + return (engine as Compilable).compile(script) + } + + override fun evaluate(script: ScriptContent, environment: ScriptEnvironment): Any? { + return engine.eval(script.content, environment.bindings) + } + + val engine: ScriptEngine by lazy { + ScriptEngineManager(this::class.java.classLoader).getEngineByName("Jexl") + ?: throw NullPointerException("Cannot find ScriptEngine for JexlExecutor") + } + +} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/KetherExecutor.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/KetherExecutor.kt new file mode 100644 index 00000000..40384db6 --- /dev/null +++ b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/KetherExecutor.kt @@ -0,0 +1,21 @@ +package cn.fd.ratziel.script.executors + +import cn.fd.ratziel.script.api.ScriptContent +import cn.fd.ratziel.script.api.ScriptEnvironment +import cn.fd.ratziel.script.api.ScriptExecutor +import taboolib.module.kether.KetherShell +import taboolib.module.kether.ScriptOptions + +/** + * KetherExecutor + * + * @author TheFloodDragon + * @since 2024/7/14 21:40 + */ +object KetherExecutor : ScriptExecutor { + + override fun evaluate(script: ScriptContent, environment: ScriptEnvironment): Any { + return KetherShell.eval(script.content, ScriptOptions.new { vars(environment.bindings) }) + } + +} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/KotlinScriptExecutor.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/KotlinScriptExecutor.kt new file mode 100644 index 00000000..23c595b9 --- /dev/null +++ b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/executors/KotlinScriptExecutor.kt @@ -0,0 +1,32 @@ +package cn.fd.ratziel.script.executors + +import cn.fd.ratziel.script.api.ScriptContent +import cn.fd.ratziel.script.api.ScriptEnvironment +import cn.fd.ratziel.script.impl.CompilableScriptExecutor +import javax.script.Compilable +import javax.script.CompiledScript +import javax.script.ScriptEngine +import javax.script.ScriptEngineManager + +/** + * KotlinScriptExecutor + * + * @author TheFloodDragon + * @since 2024/7/14 21:41 + */ +object KotlinScriptExecutor : CompilableScriptExecutor { + + override fun compile(script: String?): CompiledScript { + return (engine as Compilable).compile(script) + } + + override fun evaluate(script: ScriptContent, environment: ScriptEnvironment): Any? { + return engine.eval(script.content, environment.bindings) + } + + val engine: ScriptEngine by lazy { + ScriptEngineManager(this::class.java.classLoader).getEngineByName("kotlin") + ?: throw NullPointerException("Cannot find ScriptEngine for KotlinScriptExecutor") + } + +} \ No newline at end of file diff --git a/project/module-script/src/main/kotlin/cn/fd/ratziel/script/impl/CompilableScriptExecutor.kt b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/impl/CompilableScriptExecutor.kt new file mode 100644 index 00000000..69506aca --- /dev/null +++ b/project/module-script/src/main/kotlin/cn/fd/ratziel/script/impl/CompilableScriptExecutor.kt @@ -0,0 +1,20 @@ +package cn.fd.ratziel.script.impl + +import cn.fd.ratziel.script.api.ScriptExecutor +import java.io.Reader +import javax.script.Compilable +import javax.script.CompiledScript + +/** + * CompilableScriptExecutor + * + * @author TheFloodDragon + * @since 2024/7/15 13:49 + */ +interface CompilableScriptExecutor : ScriptExecutor, Compilable { + + override fun compile(script: Reader?): CompiledScript { + return compile(script?.readText()) + } + +} \ No newline at end of file