You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clojure开发Spigot/Slimefun插件:服务器启动后初始化类问题

问题:Clojure开发Spigot/Slimefun插件时初始化ItemStack类的编译报错问题

我是Clojure新手,想要开发Slimefun插件并使用Clojure配置物品。但Minecraft开发中,ItemStack这类类需在服务器启动后才能初始化,构造时会检查服务器运行状态。而Clojure编译时似乎会执行代码,导致涉及此类的代码编译失败,报错显示org.bukkit.Bukkit.server为null,抛出空指针异常。请问使用Clojure开发Spigot插件该如何解决此问题?

编译日志

freeze-dolphin@stardust:~/Documents/workspace/idea/Dumortierite/clj-module$ lein jar
Compiling io.sn.dumortierite.clj-module.items
Reflection warning, io/sn/dumortierite/clj_module/items.clj:15:1 - call to io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack ctor can't be resolved.
Syntax error macroexpanding def at (items.clj:15:1).
Execution error (NullPointerException) at org.bukkit.Bukkit/getItemFactory (Bukkit.java:1831).
Cannot invoke "org.bukkit.Server.getItemFactory()" because "org.bukkit.Bukkit.server" is null

Full report at:
/tmp/clojure-2943387361270522517.edn
Compilation failed: Subprocess failed (exit code: 1)

解决方法

核心思路是延迟初始化依赖服务器状态的对象,避免在Clojure编译阶段执行需要服务器环境的代码,具体有以下几种实现方式:

1. 使用delay宏延迟加载

把创建SlimefunItemStack或ItemStack的代码包裹在delay中,代码只会在首次调用deref(或@符号)时执行,而非编译阶段:

(def my-item (delay (SlimefunItemStack. "MY_ITEM" Material/DIAMOND "My Custom Item")))

;; 在服务器启动后的回调(如onEnable方法)中初始化并使用
(defn on-enable []
  (let [item @my-item]
    ;; 执行物品注册等操作
    ))

2. 用函数包装初始化逻辑

将物品创建逻辑放在函数内部,仅在服务器启动后调用该函数,避免直接用def定义全局变量:

(defn create-my-item []
  (SlimefunItemStack. "MY_ITEM" Material/DIAMOND "My Custom Item"))

;; 在onEnable中调用函数创建物品
(defn on-enable []
  (let [item (create-my-item)]
    ;; 执行物品注册等操作
    ))

3. defonce结合原子变量实现全局延迟初始化

如果需要全局可访问的物品实例,用defonce配合原子变量,避免代码重载时重复初始化:

(defonce my-item (atom nil))

(defn init-items []
  (reset! my-item (SlimefunItemStack. "MY_ITEM" Material/DIAMOND "My Custom Item")))

;; 在onEnable中触发初始化
(defn on-enable []
  (init-items)
  ;; 使用@my-item进行后续操作
  )

4. 调整Leiningen编译配置(可选)

如果部分代码无需编译阶段执行,可在project.clj中设置:aot(提前编译)仅处理必要命名空间,让物品定义代码在运行时动态加载:

(defproject dumortierite/clj-module "0.1.0-SNAPSHOT"
  ;; 其他配置项...
  :aot [io.sn.dumortierite.clj-module.main] ; 仅编译主入口命名空间
  )

额外注意事项

  • 所有涉及Bukkit/Spigot API的代码,都要放在服务器生命周期回调(如onEnable、onLoad)中执行,不要放在顶级代码块内。
  • 处理反射警告:可添加类型提示减少反射,比如给构造函数参数标注类型:
(defn create-my-item []
  (SlimefunItemStack. ^String "MY_ITEM" ^Material Material/DIAMOND ^String "My Custom Item"))

内容的提问来源于stack exchange,提问作者Freeze Dolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 22:12:22