🌙 NightCore-API 开发指南
📖 项目概述
NightCore 是一个轻量级的 Spigot/Paper 插件开发框架,为 Java 21+ 环境设计,提供完整的工具集来简化插件开发流程。
✨ 核心特性
-
🚀 现代化架构:基于 Java 21,支持 Spigot/Paper 1.20+
-
🔧 完整工具集:UI 系统、命令框架、配置管理、数据库支持
-
🏗️ 多模块架构:Manager 系统支持复杂插件开发
-
🌐 国际化支持:内置多语言系统
-
📦 模块化设计:按需使用各个功能模块
-
⚡ 生命周期管理:自动化的资源管理和清理
项目架构
nightcore/
├── main/ # 主模块 - 核心功能集成
├── bridge/ # 桥接模块 - 平台兼容性
├── utils/ # 工具模块 - 实用工具类
├── spigot/ # Spigot专用功能
└── paper/ # Paper专用功能
🚀 快速开始
1. 项目依赖配置
Maven 配置
<repositories>
<repository>
<id>nightexpress</id>
<url>https://repo.nightexpressdev.com/releases</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>su.nightexpress.nightcore</groupId>
<artifactId>nightcore</artifactId>
<version>2.7.16</version>
<scope>provided</scope>
</dependency>
</dependencies>
系统要求
-
Java 21 或更高版本
-
Spigot/Paper 1.20+
-
NightCore 插件 安装在服务器上
2. 创建插件主类
package com.yourname.yourplugin;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.nightcore.NightPlugin;
import su.nightexpress.nightcore.config.PluginDetails;
public class YourPlugin extends NightPlugin {
@Override
@NotNull
protected PluginDetails getDefaultDetails() {
return PluginDetails.create("YourPlugin", new String[]{"yourplugin", "yp"})
.setConfigClass(YourConfig.class)
.setPermissionsClass(YourPerms.class);
}
@Override
public void enable() {
// 插件启用逻辑
this.info("YourPlugin 已启用!");
}
@Override
public void disable() {
// 插件禁用逻辑
this.info("YourPlugin 已禁用!");
}
}
3. plugin.yml 配置
name: YourPlugin
main: com.yourname.yourplugin.YourPlugin
version: '1.0.0'
api-version: 1.20
depend: [nightcore]
author: YourName
description: 基于NightCore开发的插件
🔧 核心功能
📋 配置管理系统
创建配置类
public class YourConfig {
@ConfigValue(path = "Settings.Debug_Mode")
public static boolean DEBUG_MODE = false;
@ConfigValue(path = "Settings.Max_Players")
public static int MAX_PLAYERS = 100;
@ConfigValue(path = "Messages.Welcome")
public static String WELCOME_MESSAGE = "欢迎来到服务器!";
}
使用配置
// 读取配置
boolean debug = YourConfig.DEBUG_MODE;
int maxPlayers = YourConfig.MAX_PLAYERS;
// 保存配置更改
this.getConfig().saveChanges();
🎯 命令系统
import su.nightexpress.nightcore.command.experimental.builder.DirectNodeBuilder;
public class YourCommands {
public static void register(YourPlugin plugin) {
DirectNodeBuilder.create(plugin, "yourcommand")
.description("你的插件主命令")
.permission("yourplugin.command")
.executes((context, arguments) -> {
context.getSender().sendMessage("Hello from YourPlugin!");
})
.then("reload")
.description("重载插件")
.permission("yourplugin.admin")
.executes((context, arguments) -> {
plugin.reload();
context.getSender().sendMessage("插件已重载!");
});
}
}
🎨 GUI 菜单系统
import su.nightexpress.nightcore.menu.impl.AbstractMenu;
import su.nightexpress.nightcore.menu.MenuSize;
public class YourMenu extends AbstractMenu<YourPlugin> {
public YourMenu(YourPlugin plugin) {
super(plugin, "你的菜单", MenuSize.CHEST_54);
}
@Override
public void onPrepare(@NotNull MenuViewer viewer, @NotNull MenuOptions options) {
// 设置菜单项
this.addItem(Material.DIAMOND, 22)
.setDisplayName("§b钻石道具")
.setLore("§7点击获取奖励")
.setClickHandler((viewer1, event) -> {
Player player = viewer1.getPlayer();
player.getInventory().addItem(new ItemStack(Material.DIAMOND));
player.sendMessage("§a你获得了一颗钻石!");
return ClickResult.CLOSE;
});
}
@Override
public void onReady(@NotNull MenuViewer viewer, @NotNull Inventory inventory) {
// 菜单准备完成
}
}
🌐 国际化支持
定义语言文件
public class YourLang {
public static final LangElement WELCOME_MESSAGE = LangElement.of("welcome_message",
"§a欢迎 %player% 来到服务器!");
public static final LangElement INSUFFICIENT_PERMISSION = LangElement.of("no_permission",
"§c你没有权限执行此命令!");
}
使用多语言消息
// 发送本地化消息
YourLang.WELCOME_MESSAGE
.replace("%player%", player.getName())
.send(player);
🏗️ 多模块插件架构
Manager 系统层次结构
SimpleManager<P> // 基础管理器
↓
AbstractManager<P> // 完整功能管理器
↓
AbstractDataManager<P> // 数据管理器
AbstractUserManager<P, U> // 用户数据管理器
基础 Manager 实现
import su.nightexpress.nightcore.manager.AbstractManager;
public class AdvancedManager extends AbstractManager<YourPlugin> {
private SomeListener listener;
public AdvancedManager(@NotNull YourPlugin plugin) {
super(plugin);
}
@Override
protected void onLoad() {
// 1. 注册监听器
this.listener = new SomeListener(this.plugin);
this.addListener(this.listener);
// 2. 添加定时任务
this.addTask(() -> {
// 每秒执行一次的任务
}, 20L);
// 3. 添加异步任务
this.addAsyncTask(() -> {
// 异步处理重任务
}, 200L);
}
@Override
protected void onShutdown() {
// AbstractManager会自动清理监听器、菜单和任务
}
}
多模块插件示例
public class MultiModulePlugin extends NightPlugin {
private EconomyManager economyManager;
private ShopManager shopManager;
private DatabaseManager databaseManager;
@Override
public void enable() {
// 按依赖顺序启动模块
this.databaseManager = new DatabaseManager(this);
this.databaseManager.setup();
this.economyManager = new EconomyManager(this);
this.economyManager.setup();
this.shopManager = new ShopManager(this);
this.shopManager.setup();
// 后加载任务
this.onPostLoad(() -> {
this.performCrossModuleInitialization();
});
}
@Override
public void disable() {
// 按相反顺序关闭模块
if (this.shopManager != null) this.shopManager.shutdown();
if (this.economyManager != null) this.economyManager.shutdown();
if (this.databaseManager != null) this.databaseManager.shutdown();
}
private void performCrossModuleInitialization() {
// 模块间的交互初始化
this.shopManager.setEconomyProvider(this.economyManager);
}
}
🎯 事件处理系统
事件监听器基类
AbstractListener 实现
import su.nightexpress.nightcore.manager.AbstractListener;
public class YourListener extends AbstractListener<YourPlugin> {
public YourListener(@NotNull YourPlugin plugin) {
super(plugin);
}
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
this.plugin.info("玩家 " + player.getName() + " 加入了服务器");
}
}
在 Manager 中使用事件监听器
public class EventManager extends AbstractManager<YourPlugin> {
@Override
protected void onLoad() {
// 自动管理事件监听器
this.addListener(new YourListener(this.plugin));
this.addListener(new CustomListener(this.plugin));
}
}
🔐 权限控制系统
UniPermission 权限定义
import su.nightexpress.nightcore.util.wrapper.UniPermission;
public class MyPluginPerms {
// 基础权限定义
public static final UniPermission ADMIN = new UniPermission("myplugin.admin");
// 带描述的权限
public static final UniPermission RELOAD = new UniPermission("myplugin.reload", "重载插件配置");
// 自定义默认值的权限
public static final UniPermission USER_BASIC = new UniPermission("myplugin.user",
"基础用户权限", PermissionDefault.TRUE);
}
权限校验方法
基础权限检查
public class PermissionCheck {
public boolean checkPlayerPermission(Player player, String permission) {
if (!player.hasPermission(permission)) {
player.sendMessage("§c你没有权限执行此操作!");
return false;
}
return true;
}
public boolean opOrPermission(Player player, String permission) {
// OP或特定权限二选一
if (!player.isOp() && !player.hasPermission(permission)) {
player.sendMessage("§c需要管理员权限或权限: " + permission);
return false;
}
return true;
}
}
权限组校验
import su.nightexpress.nightcore.util.Players;
public boolean checkPrimaryGroup(Player player, String requiredGroup) {
String primaryGroup = Players.getPrimaryGroup(player);
if (primaryGroup == null || !primaryGroup.equalsIgnoreCase(requiredGroup)) {
player.sendMessage("§c需要权限组: " + requiredGroup);
return false;
}
return true;
}
public boolean checkInAnyGroup(Player player, String... allowedGroups) {
Set<String> playerGroups = Players.getInheritanceGroups(player);
for (String allowedGroup : allowedGroups) {
if (playerGroups.contains(allowedGroup.toLowerCase())) {
return true;
}
}
return false;
}
📨 消息发送系统
基础消息发送
使用插件前缀
public class MessageSending {
private final MyPlugin plugin;
public void sendPrefixedMessages(CommandSender sender) {
String prefix = plugin.getPrefix();
sender.sendMessage(prefix + "§a这是带前缀的消息");
}
public void sendSuccessMessage(CommandSender sender, String message) {
String prefix = plugin.getPrefix();
sender.sendMessage(prefix + "§a" + message);
}
public void sendErrorMessage(CommandSender sender, String message) {
String prefix = plugin.getPrefix();
sender.sendMessage(prefix + "§c" + message);
}
}
国际化消息发送
public class InternationalMessageSending {
public void sendLocalizedMessages(Player player) {
// 发送带占位符的消息
MyPluginLang.WELCOME_MESSAGE
.replace("%player%", player.getName())
.send(player);
// 自动带前缀的消息
MyPluginLang.COMMAND_SUCCESS.send(player);
}
}
现代化消息组件
import su.nightexpress.nightcore.util.text.night.NightMessage;
public void sendInteractiveMessages(Player player) {
// 点击消息
NightMessage.create("§a点击这里传送到出生点")
.clickEvent(ClickEventType.RUN_COMMAND, "/spawn")
.hoverEvent(HoverEventType.SHOW_TEXT, "§7点击执行 /spawn 命令")
.send(player);
// 多功能消息
NightMessage.create("§7选择操作: ")
.append("§a[传送]")
.clickEvent(ClickEventType.RUN_COMMAND, "/spawn")
.hoverEvent(HoverEventType.SHOW_TEXT, "§7传送到出生点")
.append(" ")
.append("§c[商店]")
.clickEvent(ClickEventType.RUN_COMMAND, "/shop")
.hoverEvent(HoverEventType.SHOW_TEXT, "§7打开商店")
.send(player);
}
特殊消息类型
// ActionBar消息
player.sendActionBar("§a血量: " + player.getHealth() + "/20");
// Title消息
player.sendTitle(
"§a欢迎!", // 主标题
"§7享受游戏时光", // 副标题
10, 70, 20 // 淡入、显示、淡出时间
);
// 广播消息
Bukkit.broadcastMessage("§e[系统公告] 服务器将在5分钟后重启!");
Bukkit.broadcast("§a[VIP消息] VIP专属活动开始了!", "server.vip");
📱 全息消息系统
基础全息文本实现
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
import su.nightexpress.nightcore.util.EntityUtil;
public class HologramManager extends AbstractManager<YourPlugin> {
private final Map<String, List<ArmorStand>> holograms = new HashMap<>();
public void createHologram(@NotNull String id, @NotNull Location location, @NotNull List<String> lines) {
this.removeHologram(id); // 移除已存在的
List<ArmorStand> stands = new ArrayList<>();
double yOffset = 0.0;
for (int i = lines.size() - 1; i >= 0; i--) {
String line = lines.get(i);
Location standLocation = location.clone().add(0, yOffset, 0);
ArmorStand stand = (ArmorStand) location.getWorld().spawnEntity(standLocation, EntityType.ARMOR_STAND);
// 配置ArmorStand
stand.setVisible(false);
stand.setCustomNameVisible(true);
stand.setGravity(false);
stand.setInvulnerable(true);
stand.setMarker(true);
EntityUtil.setCustomName(stand, line);
stands.add(stand);
yOffset += 0.25;
}
this.holograms.put(id, stands);
}
public void updateHologram(@NotNull String id, @NotNull List<String> newLines) {
List<ArmorStand> stands = this.holograms.get(id);
if (stands == null) return;
for (int i = 0; i < Math.min(stands.size(), newLines.size()); i++) {
ArmorStand stand = stands.get(i);
String newLine = newLines.get(newLines.size() - 1 - i);
EntityUtil.setCustomName(stand, newLine);
}
}
public void removeHologram(@NotNull String id) {
List<ArmorStand> stands = this.holograms.remove(id);
if (stands != null) {
stands.forEach(ArmorStand::remove);
}
}
@Override
protected void onShutdown() {
this.holograms.values().forEach(stands ->
stands.forEach(ArmorStand::remove));
this.holograms.clear();
}
}
实用全息文本示例
public class HologramExamples {
public static void createWelcomeHologram(HologramManager manager, Location location) {
List<String> welcomeLines = List.of(
"§e§l=== 欢迎来到服务器 ===",
"§7当前在线: §a" + Bukkit.getOnlinePlayers().size(),
"§7输入 §e/help §7获取帮助",
"§b祝你游戏愉快!"
);
manager.createHologram("spawn_welcome", location, welcomeLines);
}
public static void createShopHologram(HologramManager manager, Location location, String shopName) {
List<String> shopLines = List.of(
"§6§l🏪 " + shopName,
"§7━━━━━━━━━━━━━━━━",
"§f• 武器装备",
"§f• 食物药水",
"§f• 建筑材料",
"§7━━━━━━━━━━━━━━━━",
"§e点击商店NPC进行购买"
);
manager.createHologram("shop_" + shopName.toLowerCase(), location, shopLines);
}
}
🛠️ 实用工具类
字符串和数字处理
import su.nightexpress.nightcore.util.Strings;
import su.nightexpress.nightcore.util.Numbers;
// 颜色代码转换
String colored = Strings.color("&a这是绿色文本");
// 格式化数字
String formatted = Numbers.format(1234567); // "1,234,567"
// 时间格式化
String timeStr = TimeUtil.formatTime(System.currentTimeMillis());
物品处理
import su.nightexpress.nightcore.util.bukkit.NightItem;
// 创建物品
ItemStack item = NightItem.builder(Material.DIAMOND_SWORD)
.setDisplayName("§b传奇之剑")
.setLore("§7一把强大的武器")
.addEnchantment(Enchantment.SHARPNESS, 5)
.build();
声音播放
import su.nightexpress.nightcore.util.bukkit.NightSound;
// 播放声音
NightSound.of(Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f).play(player);
📝 开发最佳实践
项目结构建议
src/main/java/com/yourname/yourplugin/
├── YourPlugin.java # 主插件类
├── config/
│ ├── YourConfig.java # 配置类
│ └── YourLang.java # 语言类
├── command/
│ └── YourCommands.java # 命令类
├── menu/
│ └── YourMenu.java # 菜单类
├── listener/
│ └── YourListener.java # 事件监听器
└── manager/
└── YourManager.java # 管理器类
生命周期管理
@Override
public void enable() {
// 1. 加载管理器
this.yourManager = new YourManager(this);
this.yourManager.setup();
// 2. 注册命令
YourCommands.register(this);
// 3. 后加载任务
this.onPostLoad(() -> {
this.info("插件后加载完成!");
});
}
@Override
public void disable() {
if (this.yourManager != null) {
this.yourManager.shutdown();
}
}
权限管理
public class YourPerms {
public static final UniPermission ADMIN = new UniPermission("yourplugin.admin");
public static final UniPermission USE = new UniPermission("yourplugin.use");
public static final UniPermission RELOAD = new UniPermission("yourplugin.reload");
}
📋 快速参考
常用类导入
// 核心类
import su.nightexpress.nightcore.NightPlugin;
import su.nightexpress.nightcore.config.FileConfig;
import su.nightexpress.nightcore.config.PluginDetails;
// 菜单系统
import su.nightexpress.nightcore.menu.impl.AbstractMenu;
import su.nightexpress.nightcore.menu.MenuSize;
// 命令系统
import su.nightexpress.nightcore.command.experimental.builder.DirectNodeBuilder;
// 工具类
import su.nightexpress.nightcore.util.Strings;
import su.nightexpress.nightcore.util.Numbers;
import su.nightexpress.nightcore.util.Players;
常用方法速查
// 插件基础
this.info("消息"); // 输出信息
this.warn("警告"); // 输出警告
this.error("错误"); // 输出错误
// 配置操作
this.getConfig().saveChanges(); // 保存配置
this.reload(); // 重载插件
// 任务调度
this.runTask(() -> {}); // 同步任务
this.runTaskAsync(() -> {}); // 异步任务
this.runTaskLater(() -> {}, 20L); // 延迟任务
// 消息发送
player.sendMessage(prefix + "消息"); // 带前缀消息
YourLang.MESSAGE.send(player); // 国际化消息
💡 开发提示
-
遵循 NightCore 生命周期 - 使用 enable()/disable() 方法
-
利用工具类 - 避免重复造轮子
-
模块化设计 - 将功能分解为独立的管理器
-
配置外部化 - 可配置项放在配置文件中
-
权限检查 - 为所有功能添加适当的权限检查
-
错误处理 - 使用 try-catch 处理异常
-
资源管理 - 使用 AbstractManager 自动管理资源
-
性能意识 - 长时间操作使用异步任务
// 使用内置序列化工具
public class PlayerData {
@NotNull
public String toJson() {
return GsonUtil.toJson(this);
}
@NotNull
public static PlayerData fromJson(@NotNull String json) {
return GsonUtil.fromJson(json, PlayerData.class);
}
}
🐛 调试和测试
调试模式
// 在配置中启用调试
if (YourConfig.DEBUG_MODE) {
this.debug("这是调试信息: " + data);
}
性能监控
// 测量执行时间
long start = System.currentTimeMillis();
// 你的代码
long took = System.currentTimeMillis() - start;
this.info("操作耗时: " + took + "ms");
📚 参考资源
官方文档
示例插件
基于 NightCore 的成功插件案例:
-
ExcellentCrates - 箱子系统
-
ExcellentShop - 商店系统
-
CoinsEngine - 货币系统
依赖管理
<!-- Maven仓库 -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>