如何制作兼具Discord机器人功能的Minecraft Spigot插件?解决org.javacord.api.DiscordApiBuilder类找不到的加载异常
Hey there! Let's tackle this problem step by step—first off, yes, you absolutely can build a Spigot plugin that doubles as a Discord bot; no need to switch APIs. The error you're seeing is just a classic dependency packaging issue, so let's fix that first.
为什么会出现NoClassDefFoundError?
The root cause here is that even though you added Javacord as a dependency in your Maven project, the classes aren't being included in your final plugin JAR. Spigot's class loader only looks for classes inside your plugin's JAR and the core Spigot libraries, so it can't find the Javacord classes unless you package them alongside your code.
用Maven正确导入并打包Javacord依赖
Here's how to fix this in Eclipse with Maven:
1. 添加Javacord依赖到pom.xml
First, make sure you have the correct Javacord dependency in your project's pom.xml. Since you're using Java 8 (from your error logs: java.lang.Thread.run(Unknown Source) [?:1.8.0_301]), pick a Javacord version that supports Java 8 (the v3.x series works well). Add this inside the <dependencies> block:
<dependency> <groupId>org.javacord</groupId> <artifactId>javacord</artifactId> <version>3.8.0</version> <scope>compile</scope> </dependency>
2. 配置Maven Shade插件来打包依赖
Next, you need to use the Maven Shade Plugin to bundle Javacord's classes into your plugin JAR. This ensures the server can find all required classes when loading your plugin. Add this inside the <build><plugins> block of your pom.xml:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <!-- Optional: Relocate Javacord classes to avoid conflicts with other plugins --> <relocations> <relocation> <pattern>org.javacord</pattern> <shadedPattern>adwidu.mainPackage.shaded.javacord</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin>
Replace adwidu.mainPackage with your actual plugin's base package to avoid class conflicts with other plugins that might also use Javacord.
3. 在Eclipse中更新项目并打包
- Right-click your project in Eclipse → Maven → Update Project to pull down the Javacord dependency.
- Then, right-click the project → Run As → Maven Package. The Shade plugin will build a JAR in the
target/directory that includes both your plugin code and all Javacord classes.
关于双功能插件的可行性
As I mentioned earlier, this setup works perfectly. You can initialize your Discord bot inside your Spigot plugin's onEnable() method—just make sure to run Discord-related code on an asynchronous thread to avoid blocking the main Minecraft server thread. For example:
@Override public void onEnable() { // Run Discord bot init in async thread to not block the server Bukkit.getScheduler().runTaskAsynchronously(this, () -> { try { DiscordApi api = new DiscordApiBuilder() .setToken("YOUR_DISCORD_BOT_TOKEN") .login() .join(); // Add your Discord event listeners here api.addMessageCreateListener(event -> { if (event.getMessageContent().equalsIgnoreCase("!hello")) { event.getChannel().sendMessage("Hello from your Spigot plugin!"); } }); getLogger().info("Discord bot connected successfully!"); } catch (Exception e) { getLogger().severe("Failed to start Discord bot: " + e.getMessage()); } }); }
需要更换Discord API吗?
Nope! Javacord is a great choice for this use case—it's lightweight, easy to use, and fully compatible with Spigot. Unless you have a specific feature need that Javacord doesn't support, stick with it. The only issue here was dependency packaging, not the API itself.
你的错误日志参考
error: Could not load 'plugins\StoneBot.jar' in folder 'plugins' org.bukkit.plugin.InvalidPluginException: java.lang.NoClassDefFoundError: org/javacord/api/DiscordApiBuilder at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:135) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.java:329) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager.java:251) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.craftbukkit.v1_8_R1.CraftServer.loadPlugins(CraftServer.java:291) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.craftbukkit.v1_8_R1.CraftServer.reload(CraftServer.java:744) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.Bukkit.reload(Bukkit.java:534) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:25) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchCommand(CraftServer.java:646) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchServerCommand(CraftServer.java:632) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at net.minecraft.server.v1_8_R1.DedicatedServer.aM(DedicatedServer.java:353) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:317) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:634) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:537) [spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at java.lang.Thread.run(Unknown Source) [?:1.8.0_301] Caused by: java.lang.NoClassDefFoundError: org/javacord/api/DiscordApiBuilder at adwidu.mainPackage.Main.<init>(Main.java:15) ~[?:?] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_301] at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_301] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_301] at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[?:1.8.0_301] at java.lang.Class.newInstance(Unknown Source) ~[?:1.8.0_301] at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:76) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:131) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] ... 14 more Caused by: java.lang.ClassNotFoundException: org.javacord.api.DiscordApiBuilder at java.net.URLClassLoader.findClass(Unknown Source) ~[?:1.8.0_301] at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:101) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:86) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_301] at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_301] at adwidu.mainPackage.Main.<init>(Main.java:15) ~[?:?] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_301] at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_301] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_301] at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[?:1.8.0_301] at java.lang.Class.newInstance(Unknown Source) ~[?:1.8.0_301] at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:76) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:131) ~[spigot-1.8-R0.1-SNAPSHOT-latest.jar:git-Spigot-c3c767f-33d5de3] ... 14 more
内容的提问来源于stack exchange,提问作者adwidu

