Paper Minecraft Kotlin插件CommandExecutor与EventListener异常求助
问题分析:Kotlin开发Paper插件运行时抛出NoClassDefFoundError
核心问题
触发PlayerJumpEvent或执行/jump命令时,服务器抛出java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics异常,本质是插件jar包中未包含Kotlin标准库依赖,导致Paper的类加载器找不到Kotlin运行必需的核心类。
解决方案
1. 使用Shadow插件打包(Gradle)
如果用Gradle构建项目,通过Shadow插件将Kotlin标准库与插件代码打包到同一个jar中,避免依赖缺失:
- 在
build.gradle.kts中添加插件依赖:
plugins { id("java") id("org.jetbrains.kotlin.jvm") version "1.9.0" id("com.github.johnrengelman.shadow") version "8.1.1" }
- 配置Shadow插件(重定位Kotlin包避免版本冲突):
shadowJar { archiveBaseName.set("MyFirstPlugin") archiveVersion.set("1.0") relocate("kotlin", "me.kotia.myfirstplugin.libs.kotlin") }
- 执行
./gradlew shadowJar,生成的完整jar包位于build/libs/目录。
2. 使用maven-shade-plugin打包(Maven)
Maven项目通过shade插件打包依赖:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <relocations> <relocation> <pattern>kotlin</pattern> <shadedPattern>me.kotia.myfirstplugin.libs.kotlin</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build>
执行mvn package,生成的shaded jar包含所有依赖。
注意事项
- 不要使用普通
jar任务生成的包,必须使用shadow/shade插件生成的包含依赖的jar。 - 重定位Kotlin包可避免不同插件间的Kotlin版本冲突,建议开启。
插件代码优化参考
主类MyFirstPlugin.kt
package me.kotia.myfirstplugin import me.kotia.myfirstplugin.commands.JumpCommand import me.kotia.myfirstplugin.listeners.jumpListener import org.bukkit.plugin.java.JavaPlugin class MyFirstPlugin : JavaPlugin() { override fun onEnable() { logger.info("Loaded!") registerCommand() registerListener() } private fun registerListener(){ server.pluginManager.registerEvents(jumpListener(), this) logger.info("Listener successfully registered") } private fun registerCommand(){ getCommand("jump")?.setExecutor(JumpCommand()) logger.info("Command successfully registered") } override fun onDisable() { logger.info("Unloaded!") } }
事件监听器jumpListener.kt
package me.kotia.myfirstplugin.listeners import com.destroystokyo.paper.event.player.PlayerJumpEvent import org.bukkit.event.EventHandler import org.bukkit.event.Listener class jumpListener : Listener { @EventHandler fun playerJumpEvent(event: PlayerJumpEvent){ event.player.sendMessage("You have jumped!") } }
(移除了多余的java.util.EventListener导入)
命令执行器JumpCommand.kt
package me.kotia.myfirstplugin.commands import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.TextColor import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.entity.Player import org.bukkit.util.Vector class JumpCommand : CommandExecutor { override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>?): Boolean { if(sender is Player){ if(sender.isOp){ sender.sendMessage("Success") sender.velocity = sender.velocity.add(Vector(0.0, 5.0, 0.0)) } else { sender.sendMessage(Component.text("You do not have permission to run this command").color(TextColor.color(255, 0, 0))) } } return true } }
(修复拼写错误,改用Double类型参数,命令处理完成返回true)
plugin.yml配置
name: MyFirstPlugin version: '1.0' main: me.kotia.myfirstplugin.MyFirstPlugin api-version: '1.19' commands: jump: description: launches player in air
(修复拼写错误,修正命令配置缩进)
内容的提问来源于stack exchange,提问作者Saul
相关产品推荐
相关产品推荐

