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
相关产品推荐
相关产品推荐

