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

Kotlin开发Minecraft Paper插件:跨类访问StaffChat变量异常排查

问题根源与解决方法

你的问题核心是SC类的单例实现错误,导致监听类拿到的StaffChat对象和命令执行时操作的不是同一个实例。

为什么会出错?

你在SC类的companion object里用lazy { SC() }创建了一个独立的SC实例,但在Paper插件中,你注册命令执行器时肯定是单独new了一个SC实例(比如在插件主类里getCommand("sc")?.setExecutor(SC()))。这就导致存在两个完全独立的SC对象:

  • 命令切换状态时,修改的是插件注册的那个SC实例里的sc对象的状态
  • 监听类通过SC.getSC()拿到的却是companion object里懒加载的另一个SC实例的sc对象,这个sc的状态从未被修改过,所以sc.getState(p)永远返回false,自然不会触发staff chat逻辑,消息就以普通形式发送了。

两种修复方案

方案1:修正SC类的单例,让所有地方共用同一个实例

修改SC类,让单例指向插件注册的那个实例:

class SC(private val plugin: Plugin) : CommandExecutor {
    companion object {
        private lateinit var instance: SC

        fun getSC(): StaffChat {
            return instance.sc
        }

        // 插件启动时调用这个方法初始化单例
        fun init(pluginInstance: Plugin) {
            instance = SC(pluginInstance)
        }
    }
    
    var sc = StaffChat()

    // 你的命令执行方法onCommand实现...
}

然后在插件主类的onEnable()里初始化并注册命令:

override fun onEnable() {
    // 初始化SC单例
    SC.init(this)
    // 用单例注册命令执行器
    getCommand("sc")?.setExecutor(SC.instance)
}

方案2:让StaffChat本身成为单例(更简洁)

直接把StaffChat改成单例,这样不管从哪里获取都是同一个对象,彻底避免实例不一致问题:

class StaffChat private constructor() {
    companion object {
        // 全局唯一的StaffChat实例
        val instance: StaffChat by lazy { StaffChat() }
    }

    // 你的原有方法,比如getState、sendMsg等
    fun getState(p: Player): Boolean { /* ... */ }
    fun sendMsg(p: Player, msg: String) { /* ... */ }
}

然后SC类和监听类都直接使用这个单例:

  • SC类里:val sc = StaffChat.instance
  • 监听类里:val sc = StaffChat.instance

这样不管是命令切换还是消息监听,操作的都是同一个StaffChat实例,状态就能正常同步了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 00:27:38