跳转至

📋 脚本引擎 - 特定脚本语言开发须知

🌏 开发语言支持情况

通过 ScriptX 项目的支持,脚本引擎使用同一套源代码,对多种开发语言进行了适配。
同时,由于API保持一致,使各种语言得以共享一份开发文档,大大降低了维护难度。

目前,脚本引擎支持使用如下语言编写插件:

语言后端 备注
JavaScript 使用 QuickJS 引擎运行插件,支持 ES Module 机制
Lua 使用 CLua 引擎运行插件
Node.js 改造 Node.js 使其适合嵌入工作,支持 npm 包管理
Python 使用 CPython 引擎运行插件,支持 pip 包管理

Tip

如果需要使用 C++、Go、Rust 等原生语言编写插件,请移步 主页 查看其他语言文档

JavaScript 语言支持说明

  • 使用 QuickJS 引擎对简单的 JavaScript 插件提供支持,轻量级引擎资源占用较少
  • QuickJS 当前版本支持到 ES2020 语言特性,同时原生支持 ESModule 模块机制,可以方便开发者进行项目管理
  • 暂不支持包管理机制,如果需要请使用 Node.js 进行插件开发,使用 npm 包管理
  • 在BDS控制台中使用jsdebug命令进入和退出 QuickJs 交互式命令行环境。此功能便于编写插件时进行一些简单的测试

Lua 语言支持说明

  • 使用 CLua 引擎,支持使用 require 进行简单的项目管理
  • 由于 Rocks 包管理机制需要引入编译器,因此暂不提供相关实现。如果需要依赖扩展可以手动编译后引入项目进行使用(如 SQLite 等常用库)
  • 在BDS控制台中使用luadebug命令进入和退出 Lua 交互式命令行环境。此功能便于编写插件时进行一些简单的测试

Node.js 支持说明

  • LSE 通过自行实现 Node.js 启动代码,使其可以在嵌入式模式下工作,并实现了不同插件的执行环境隔离
  • 自行编写接口实现了对 npm 的 programmic 支持。支持通过 package.json 安装第三方扩展依赖包

Node.js 插件开发方法

  1. 首先,安装NodeJs
  2. 创建一个新的目录进行插件开发。在此目录启动终端执行npm init命令。根据 npm 的提示创建新项目,填写项目的相关信息。
  3. 在填写的入口点文件中编写插件代码
  4. 如果有需要,可以创建多个源码文件,并且通过 require 来引入他们。合理的对源码进行分文件拆分编写有助于提高项目结构的清晰度,方便后续对插件进行进一步的维护和扩展。

Node.js 插件打包 & 部署方法

  • 在插件编写完成之后,请将 package.json 以及所有插件源码打包为一个zip压缩包,并将文件名后缀修改为 .llplugin
  • node_modules 目录请勿打包在压缩包之中
  • .llplugin 文件作为插件分发,安装插件时直接将此文件放置到 plugins 目录即可
  • 在开服时,脚本引擎会自动识别 .llplugin 文件,将其解压到plugins/nodejs/插件名目录,并在目录中自动执行 npm install安装依赖包,整个过程无需人工干预

Python 语言支持说明

  • 使用 CPython 引擎,Python版本为3.10.9。支持使用 pip 包管理机制为插件安装第三方扩展依赖包,支持多文件插件开发和 import,支持现代项目管理机制
  • 在BDS控制台中使用pydebug命令进入和退出 Python 交互式命令行环境。此功能便于编写插件时进行一些简单的测试

Python 单文件插件开发方法

  • 为了方便不熟悉Python的开发者快速上手,我们提供了一种简单的 Python 插件支持:单文件插件。
  • 单文件插件类似QuickJs和Lua插件。只要编写单个.py文件作为插件,将插件直接放置到 plugins目录中,在开服时就会被加载运行
  • 单文件插件缺点:不支持插件元数据储存、不支持源码分文件、不支持pip第三方包。单文件插件仅用于开发者熟悉LSE的Python环境,或者开发非常简易的插件而使用。

Python 多文件插件开发方法

  • 对于大型、正式的Python插件,强烈建议使用此方法进行开发。多文件插件支持所有完整的Python特性。
  • LSE 使用pyproject.toml 项目文件进行元数据储存(类似 Node.Js 的package.json)。此项目文件推荐使用支持现代项目特性的 PDM 包管理器(pdm-project/pdm)自动生成,以便于进行插件项目的创建和维护。
下面是具体的插件开发流程:
  1. 首先,安装Python 3.10.9

  2. 在终端中执行pip install --user pdm命令安装 pdm 包管理工具

  3. 创建一个新的目录进行插件开发。在此目录启动终端执行pdm init命令。根据pdm工具的提示创建新项目,填写项目的相关信息。

  4. 如果需要安装依赖包,在项目目录执行pdm add <依赖包名>即可

  5. 所有的项目元数据和依赖数据都会被自动储存在pyproject.toml 中,无需手动编写。你也可以打开此文件修改版本号、描述等元数据信息

  6. 除了使用pdm add命令之外,你也可以直接把项目依赖手动写在requirements.txt当中。在安装插件时,pyproject.tomlrequirements.txt中描述的依赖都将被处理并自动安装。

  7. 接下来创建__init__.py文件,并在其中编写插件代码。加载插件时,Python解释器会首先读取并执行这个文件。

  8. 如果有需要,可以创建多个源码文件,并且通过 import 来引入他们。合理的对源码进行分文件拆分编写有助于提高项目结构的清晰度,方便后续对插件进行进一步的维护和扩展。

Python 多文件插件打包 & 部署方法

  • 在插件编写完成之后,请将 pyproject.toml以及所有插件源码打包为一个zip压缩包,并将文件名后缀修改为 .llplugin
  • __pycache____pypackages__ 等目录请勿打包在压缩包之中
  • .llplugin 文件作为插件分发,安装插件时直接将此文件放置到 plugins 目录即可
  • 在开服时,脚本引擎会自动识别 .llplugin 文件,将其解压到plugins/python/插件名目录,并在目录中自动执行 pip install安装依赖包,整个过程无需人工干预

Python插件开发的已知问题

平心而论,CPython的代码质量和维护状况有些堪忧。下面给出了一些开发Python插件时需要注意的地方,其中有不少都是由CPython本身的Bug引起的:

  1. 暂时不要使用threading asyncio等特性
  2. LSE使用CPython的子解释器作为引擎调度的核心单位,然而CPython自身长期以来对子解释器机制的支持并不完善,存在众多Bug,令人一言难尽。目前上面这些机制所需要使用到的GIL api内部并没有考虑到子解释器的存在,因此一旦使用会发生死锁、崩溃等问题。
  3. 如果有并行计算需求的开发者可以暂时使用multiprocess进行多进程并行
  4. Python3.12 按计划将对子解释器和GIL相关bug做出针对性的修复,届时LSE将对CPython3.12进行适配,解决此问题。Py3.12预计在2023年10月份左右推出,请耐心等待
  5. 所有Python引擎的sys.stdin被禁用
  6. 这是另外一个CPython的bug,具体详见:https://github.com/python/cpython/issues/83526
  7. 另外,即使不是上述情况下加载的CPython引擎,也会出现抢夺stdin的问题,导致部分使用了输入重定向机制的工具失效
  8. 因此我们打patch禁用了所有Python引擎的sys.stdin,等待后续版本CPython将此系列bug彻底解决之后,再视情况恢复