YRDatabase

原创 YRDatabase 1.0.2

完成注册/登录后下载
版权类型
原创
API版本
1.13
版权链接
#
语言支持
中文(简体)
[MD] # YRDatabase - Nukkit 通用数据库前置插件 > 🔥 高性能 Redis + MySQL 数据库管理前置插件,支持智能事件系统 --- ## 📖 插件简介 YRDatabase 是一个为 Nukkit 服务器设计的通用数据库管理前置插件,提供了简洁易用的 API 来操作 Redis 和 MySQL 数据库。 **核心特性**: - ⚡ **高性能连接池** - 使用 HikariCP 和 Lettuce 连接池,性能优异 - 🎯 **智能事件系统** - 自动适配单服/多服环境,避免转服触发持久化 - 🔌 **简单易用 API** - 封装常用操作,开发者无需关心底层细节 - 🌐 **跨服支持** - 配合 WaterdogPE 实现真正的跨服数据同步 - 📦 **完全开源** - MIT 协议,可自由修改和分发 --- ## 🎮 适用场景 ### 单服环境 - 使用 Redis 缓存玩家数据,减少数据库查询 - 使用 MySQL 持久化玩家数据 - 监听 `PlayerDataInitializeEvent` 和 `PlayerDataPersistEvent` 进行数据管理 ### 多服环境(配合 WaterdogPE) - 区分玩家真实加入/退出和服务器转服 - 仅在真实退出时持久化数据,避免转服卡顿 - 使用 Redis Pub/Sub 同步跨服数据 --- ## 📥 下载安装 ### 下载地址 **GitHub Releases**:[YRDatabase Releases](https://github.com/MufHead/YRDatabase/releases) **Jenkins CI 构建**:[最新构建](https://motci.cn/job/YRDatabase/) ### 安装步骤 1. 下载 `YRDatabase.jar` 2. 放入服务器 `plugins/` 目录 3. 启动服务器,插件会自动生成配置文件 4. 编辑 `plugins/YRDatabase/config.yml` 配置数据库 5. 重启服务器 --- ## ⚙️ 配置文件 ```yaml # YRDatabase 配置文件 # MySQL 配置 mysql: enabled: true host: localhost port: 3306 database: minecraft username: root password: your_password # 连接池配置 pool: maximum-pool-size: 10 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 # Redis 配置 redis: enabled: true host: localhost port: 6379 password: "" database: 0 timeout: 3000 # 连接池配置 pool: max-total: 20 max-idle: 10 min-idle: 5 # 网易 UID 记录功能(需要 NukkitMaster) netease-uid: enabled: true # 是否将网易UID存入数据库(需要MySQL启用) save-to-database: true # Redis Pub/Sub 配置(仅在使用 WaterdogPE 时启用) pubsub: enabled: false ``` --- ## 👨‍💻 开发者 API ### 1. 添加依赖 #### Gradle (Kotlin DSL) ```kotlin repositories { mavenCentral() maven("https://jitpack.io") } dependencies { // 只依赖 API(推荐) compileOnly("com.github.MufHead.YRDatabase:yrdatabase-common:v1.0.3") } ``` 在 `plugin.yml` 中添加依赖: ```yaml depend: [YRDatabase] ``` ### 2. 获取插件实例 ```java public class MyPlugin extends PluginBase { private YRDatabase yrDatabase; @Override public void onEnable() { // 获取 YRDatabase 实例 yrDatabase = (YRDatabase) getServer().getPluginManager().getPlugin("YRDatabase"); if (yrDatabase == null) { getLogger().error("YRDatabase 未安装!"); getServer().getPluginManager().disablePlugin(this); return; } } } ``` ### 3. Redis 操作 #### 基础操作 ```java // 获取 Redis 管理器 RedisManager redis = yrDatabase.getRedisManager(); // 设置值 redis.set("player:data:Steve", "{\"level\":10,\"money\":1000}"); // 设置值(带过期时间,单位:秒) redis.setex("player:session:Steve", 3600, "online"); // 获取值 String data = redis.get("player:data:Steve"); // 删除值 redis.del("player:data:Steve"); // 检查键是否存在 boolean exists = redis.exists("player:data:Steve"); ``` #### Hash 操作 ```java // 设置 Hash 字段 redis.hset("player:Steve", "level", "10"); redis.hset("player:Steve", "money", "1000"); // 获取 Hash 字段 String level = redis.hget("player:Steve", "level"); // 获取整个 Hash Map<String, String> playerData = redis.hgetAll("player:Steve"); // 删除 Hash 字段 redis.hdel("player:Steve", "level"); ``` #### 异步操作(推荐) ```java // 异步获取数据 redis.getAsync("player:data:Steve").thenAccept(data -> { if (data != null) { getLogger().info("玩家数据: " + data); } }); // 异步设置数据 redis.setAsync("player:data:Steve", "{\"level\":10}").thenAccept(success -> { if (success) { getLogger().info("数据保存成功"); } }); ``` ### 4. MySQL 操作 #### 执行查询 ```java // 获取 MySQL 管理器 MySQLManager mysql = yrDatabase.getMySQLManager(); // 查询数据 mysql.queryAsync("SELECT * FROM players WHERE name = ?", "Steve").thenAccept(result -> { try { if (result.next()) { int level = result.getInt("level"); int money = result.getInt("money"); getLogger().info("玩家等级: " + level + ", 金币: " + money); } } catch (SQLException e) { e.printStackTrace(); } }); ``` #### 执行更新 ```java // 插入数据 mysql.updateAsync( "INSERT IGNORE INTO players (name, level, money) VALUES (?, ?, ?)", "Steve", 10, 1000 ).thenAccept(affectedRows -> { getLogger().info("插入了 " + affectedRows + " 行数据"); }); // 更新数据 mysql.updateAsync( "UPDATE players SET level = ? WHERE name = ?", 20, "Steve" ).thenAccept(affectedRows -> { getLogger().info("更新了 " + affectedRows + " 行数据"); }); ``` ### 5. 智能事件系统(核心功能) #### 监听玩家数据初始化事件 ```java @EventHandler(priority = EventPriority.LOW) public void onPlayerDataInitialize(PlayerDataInitializeEvent event) { Player player = event.getPlayer(); String uid = event.getUid(); // 判断是否为真实加入(非转服) if (event.isRealJoin()) { // 真实加入:从数据库加载数据 loadPlayerDataFromDatabase(player, uid); } else { // 转服:从 Redis 缓存加载数据(更快) loadPlayerDataFromCache(player, uid); } } ``` #### 监听玩家数据持久化事件 ```java @EventHandler(priority = EventPriority.HIGH) public void onPlayerDataPersist(PlayerDataPersistEvent event) { Player player = event.getPlayer(); String uid = event.getUid(); // 判断是否应该持久化 if (event.shouldPersist()) { // 真实退出或服务器关闭:保存到数据库 savePlayerDataToDatabase(player, uid); } else { // 转服:只保存到 Redis 缓存 savePlayerDataToCache(player, uid); } } ``` #### 完整示例:玩家等级系统 ```java public class LevelPlugin extends PluginBase implements Listener { private YRDatabase yrDatabase; private Map<String, Integer> playerLevels = new HashMap<>(); @Override public void onEnable() { yrDatabase = (YRDatabase) getServer().getPluginManager().getPlugin("YRDatabase"); getServer().getPluginManager().registerEvents(this, this); } @EventHandler(priority = EventPriority.LOW) public void onPlayerDataInitialize(PlayerDataInitializeEvent event) { Player player = event.getPlayer(); String uid = event.getUid(); if (event.isRealJoin()) { // 真实加入:从数据库加载 yrDatabase.getMySQLManager().queryAsync( "SELECT level FROM player_levels WHERE uid = ?", uid ).thenAccept(rs -> { try { int level = rs.next() ? rs.getInt("level") : 1; playerLevels.put(uid, level); player.sendMessage("§a欢迎回来!你的等级:" + level); } catch (SQLException e) { e.printStackTrace(); } }); } else { // 转服:从 Redis 加载 yrDatabase.getRedisManager().getAsync("level:" + uid).thenAccept(levelStr -> { int level = levelStr != null ? Integer.parseInt(levelStr) : 1; playerLevels.put(uid, level); }); } } @EventHandler(priority = EventPriority.HIGH) public void onPlayerDataPersist(PlayerDataPersistEvent event) { String uid = event.getUid(); Integer level = playerLevels.get(uid); if (level == null) return; if (event.shouldPersist()) { // 真实退出:保存到数据库 yrDatabase.getMySQLManager().updateAsync( "INSERT IGNORE INTO player_levels (uid, level) VALUES (?, ?) ON DUPLICATE KEY UPDATE level = ?", uid, level, level ); } // 无论如何都保存到 Redis(用于转服) yrDatabase.getRedisManager().setexAsync("level:" + uid, 3600, level.toString()); playerLevels.remove(uid); } } ``` --- ## 🌐 多服环境配置 ### 1. WaterdogPE 端配置 在 WaterdogPE 服务器上安装 `YRDatabase-Waterdog.jar`,并配置: ```yaml redis: enabled: true host: localhost port: 6379 password: "" database: 0 pubsub: enabled: true ``` ### 2. Nukkit 子服配置 在所有 Nukkit 子服上安装 `YRDatabase.jar`,并启用 Pub/Sub: ```yaml pubsub: enabled: true ``` ### 3. 工作原理 1. 玩家在 WaterdogPE 登录 → WaterdogPE 发送 `REAL_JOIN` 消息 2. 所有子服收到消息 → 标记玩家为"真实在线" 3. 玩家加入子服 → 触发 `PlayerDataInitializeEvent` (REAL_JOIN) 4. 玩家转服 → 触发 `PlayerDataInitializeEvent` (SERVER_TRANSFER) 5. 玩家从 WaterdogPE 退出 → 发送 `REAL_QUIT` 消息 6. 玩家所在子服触发 `PlayerDataPersistEvent` (REAL_QUIT) --- ## 📊 事件原因说明 ### PlayerDataInitializeEvent 初始化原因 | 原因 | 说明 | 应该做什么 | |------|------|-----------| | `REAL_JOIN` | 玩家真实加入(确认非转服) | 从数据库加载完整数据 | | `LOCAL_JOIN` | 本地加入(无法判断是否转服) | 从数据库或缓存加载 | | `SERVER_TRANSFER` | 服务器转服(已确认) | 从 Redis 缓存快速加载 | ### PlayerDataPersistEvent 持久化原因 | 原因 | 说明 | 应该做什么 | |------|------|-----------| | `REAL_QUIT` | 玩家真实退出(确认非转服) | 保存到数据库 + Redis | | `LOCAL_QUIT` | 本地退出(无法判断是否转服) | 保存到数据库 + Redis | | `SERVER_TRANSFER` | 服务器转服(已确认) | 只保存到 Redis 缓存 | | `SERVER_SHUTDOWN` | 服务器关闭 | 保存到数据库 + Redis | --- ## 🔧 常见问题 ### Q: 我的服务器是单服,需要配置 WaterdogPE 吗? **A:** 不需要。单服环境下,YRDatabase 会自动使用 `LOCAL_JOIN` 和 `LOCAL_QUIT` 事件,你只需要监听事件即可。 ### Q: 如何判断玩家是否使用网易账号登录? **A:** 使用 `yrDatabase.resolvePlayerId(player)` 方法: ```java String uid = yrDatabase.resolvePlayerId(player); // 如果安装了 NukkitMaster 且玩家是网易登录,返回网易UID(数字) // 否则返回 UUID 字符串 ``` ### Q: 如何在不使用事件的情况下直接操作数据库? **A:** 直接使用 `RedisManager` 和 `MySQLManager`: ```java RedisManager redis = yrDatabase.getRedisManager(); MySQLManager mysql = yrDatabase.getMySQLManager(); ``` ### Q: 数据库连接失败怎么办? **A:** 检查以下几点: 1. MySQL/Redis 服务是否启动 2. 配置文件中的地址、端口、密码是否正确 3. 防火墙是否允许连接 4. 查看 `logs/` 目录中的错误日志 ### Q: 如何优化性能? **A:** 1. 使用异步操作(`xxxAsync` 方法) 2. 使用 Redis 缓存热数据 3. 批量操作使用事务 4. 合理配置连接池大小 --- ## 📚 更多资源 - **GitHub 仓库**:https://github.com/MufHead/YRDatabase - **问题反馈**:https://github.com/MufHead/YRDatabase/issues - **JitPack Maven**:https://jitpack.io/#MufHead/YRDatabase - **完整文档**:查看项目 README.md --- ## 📜 开源协议 本插件使用 **MIT License** 开源协议。 你可以自由: - ✅ 商业使用 - ✅ 修改代码 - ✅ 分发 - ✅ 私人使用 唯一要求:保留原作者版权声明。 --- ## 💖 支持作者 如果这个插件对你有帮助,请: - ⭐ 在 GitHub 上给项目点个 Star - 📢 分享给其他服主 - 🐛 提交 Bug 和建议 --- **插件版本**:v1.0.3 **支持的 Nukkit 版本**:1.0+ **最后更新**:2026-01-14 [/MD]
作者
亦染KUMA
下载
6
查看
292
首次发布
最后更新

评分

0.00 星 0 次评分

亦染KUMA 的其他资源

最新更新

  1. 支持对redis的sub pub功能 以及对waterdog端插件的接入

    支持对redis的sub pub功能 以及对waterdog端插件的接入
  2. 稳定性更新

    稳定性更新
后退
顶部 底部