正在载入

等待时间过长时请刷新页面

编写于

最近更新

初始化

Linlang 运行时为每一个使用它的插件创建独立的服务副本。您需要在插件启用时完成初始化,保存返回的 Linlang 实例,并在插件卸载时关闭它。

在 Bukkit 平台中,初始化入口是 Lin

import api.linlang.runtime.Lin;
import api.linlang.runtime.Linlang;

基本初始化

最简单的初始化方式是在插件主类的 onEnable() 中调用 Lin.init(this)

public final class MyPlugin extends JavaPlugin {

    private Linlang lin;

    @Override
    public void onEnable() {
        lin = Lin.init(this);
    }

    @Override
    public void onDisable() {
        if (lin != null) {
            lin.close();
            lin = null;
        }
    }
}

这里的 this 是当前插件的 JavaPlugin 实例,也是 Linlang 在 Bukkit 平台中的「平台上下文」。运行时使用它确定文件根目录、日志通道、命令所有者和事件监听器所属插件。

Lin.init(this) 会先从 Maven 构建元数据或 META-INF/linlang/required-api.properties 检测插件编译时使用的 API 版本,然后完成以下操作:

  1. 从 Bukkit ServicesManager 中发现 Linlang 运行时。
  2. 为当前插件创建一个独立的 Bukkit Facade。
  3. 将当前 JavaPlugin 注入为平台上下文。
  4. 创建或刷新文件、命令、消息和界面等服务。
  5. 返回可以直接使用的 Linlang 实例。

如果服务器没有安装可用的运行时,初始化会抛出 IllegalStateException。因此,请先按照 依赖引入 ⇱ 的说明,在 plugin.yml 中声明 LinlangRuntimeBukkit 为前置插件。

初始化并设置选项

如果您在启动时已经知道语言、消息前缀和日志方式,我们推荐使用 Lin.setup(...)。它会在一次初始化流程中应用 LinOptions,最后统一刷新服务:

import api.linlang.runtime.Lin;
import api.linlang.runtime.LinOptions;
import api.linlang.runtime.Linlang;

public final class MyPlugin extends JavaPlugin {

    private Linlang lin;

    @Override
    public void onEnable() {
        lin = Lin.setup(this, new LinOptions()
                .pluginLogger(true)
                .totalPrefix("§7[§dMyPlugin§7]§r")
                .totalLocale("zh_CN"));
    }

    @Override
    public void onDisable() {
        if (lin != null) {
            lin.close();
            lin = null;
        }
    }
}

这些方法的含义是:

  1. pluginLogger(true):让 Linlang 日志通过当前插件的 Logger 输出。
  2. totalPrefix(...):设置 Linlang 内建消息使用的前缀。
  3. totalLocale(...):设置当前 Linlang 实例的全局语言。

如果前缀需要根据平台上下文动态生成,可以使用:

lin = Lin.setup(this, new LinOptions()
        .dynamicTotalPrefix(context -> {
            JavaPlugin plugin = (JavaPlugin) context;
            return "§7[§a" + plugin.getName() + "§7]§r";
        })
        .totalLocale("zh_CN"));

您应该在固定前缀与动态前缀中选择一种方式。对同一个 LinOptions 先后调用两者时,后调用的会覆盖前一个的设置。

从配置文件决定选项

部分插件需要先读取自己的配置文件,再决定 Linlang 使用的语言或前缀。此时可以使用带回调的 Lin.setup(...)

lin = Lin.setup(this, current -> {
    MainConfig config = current.linFile().config().bind(MainConfig.class);

    return new LinOptions()
            .pluginLogger(true)
            .totalPrefix(config.prefix)
            .totalLocale(config.language);
});

回调参数 current 是已经创建、但尚未执行最终刷新流程的 Linlang 门面。您可以从中绑定配置对象,然后返回需要应用的 LinOptions。回调结束后,Linlang 会统一应用运行参数和个性化设置,再完成刷新。

这种写法可以减少「初始化一次、读取配置、修改设置、再次重载」带来的重复工作。配置对象的定义和绑定方式请见:配置文件 ⇱

初始化流程

sequenceDiagram
    participant Plugin as "您的插件"
    participant Lin as "Lin"
    participant Services as "Bukkit ServicesManager"
    participant Runtime as "LinlangRuntimeBukkit"
    participant Facade as "插件专属 Facade"

    Plugin->>Lin: Lin.init(this) 或 Lin.setup(this, options)
    Lin->>Services: 查找 Linlang 服务
    Services-->>Lin: 返回运行时入口
    Lin->>Runtime: createFacade(JavaPlugin)
    Runtime-->>Lin: 返回插件专属 Facade
    Lin->>Facade: 注入上下文并刷新服务
    Facade-->>Plugin: 返回 Linlang 实例

运行时入口是所有插件共享的,但 Facade 不是。每个 Facade 持有当前插件对应的文件服务、命令服务、消息服务、界面服务与语言状态。这种结构使 Linlang 可以复用底层运行能力,同时隔离不同插件的资源和生命周期。

Runtime 的启动顺序、资源所有权、软重载、设置更新和服务器关闭流程请见:琳琅运行时 ⇱

获取服务

初始化完成后,所有开发者服务均通过保存的 lin 实例获取:

lin.linFile();
lin.linCommand();
lin.linMessenger();
lin.linView();

建议在插件主类或专门的上下文类中保存同一个 Linlang 实例,再将其传递给需要使用服务的模块。不要在每次执行命令或处理事件时重复调用 Lin.init(this),否则会创建额外的 Facade,并增加重复注册和资源释放的复杂度。

重新应用设置

初始化完成后,仍可通过统一的 settings() 修改设置:

lin.settings()
        .totalPrefix("§7[§bNewPrefix§7]§r")
        .apply();

lin.settings()
        .totalLocale("en_GB")
        .apply();

settings().apply() 原地应用语言、前缀及日志等设置,保留服务与命令注册。需要重新读取文件时,显式调用 lin.reload()。详见重载机制 ⇱

关闭服务

插件卸载时调用 lin.close()。该方法会注销当前插件创建的 Facade,并释放它持有的命令、监听器、文件监视器和其他运行资源。

请不要关闭由 Lin.find() 返回的共享运行时入口,也不要自行实例化 Core 或 Bukkit 实现类。插件开发代码应始终通过 Lin.init(...)Lin.setup(...) 获取自己的服务门面。

讨论

请登录账号