3 Commits

Author SHA1 Message Date
68747f76bb feat: 为 BungeeCord 添加完整的 netty 并重定向
All checks were successful
Publish Project / build (push) Successful in 1m26s
2025-07-03 03:52:50 +08:00
1c83615b7e docs: 修正文档
[skip ci]
2025-07-03 02:33:16 +08:00
1648a56453 feat: 添加 lettuce-core 用于连接 redis
All checks were successful
Publish Project / build (push) Successful in 2m43s
2025-07-03 02:29:02 +08:00
12 changed files with 111 additions and 35 deletions

View File

@@ -9,8 +9,6 @@
3. 命令行窗口中执行`./gradlew clean build`
4. 构建成品在 `build` 文件夹
也可访问我的[Jenkins网站](https://jenkins.airgame.net/job/opensource/job/hamster-core/)获取最新版
# 开发
## 添加依赖
@@ -26,9 +24,9 @@ repositories {
dependencies {
// 对于 Bukkit 插件
compileOnly("cn.hamster3.mc.plugin:core-bukkit:1.3.4-SNAPSHOT")
compileOnly("cn.hamster3.mc.plugin:core-bukkit:1.4.0")
// 对于 BungeeCord 插件
compileOnly("cn.hamster3.mc.plugin:core-bungee:1.3.4-SNAPSHOT")
compileOnly("cn.hamster3.mc.plugin:core-bungee:1.4.0")
}
```
@@ -54,13 +52,13 @@ dependencies {
<dependency>
<groupId>cn.hamster3.mc.plugin</groupId>
<artifactId>core-bukkit</artifactId>
<version>1.3.4-SNAPSHOT</version>
<version>1.4.0</version>
</dependency>
<!--对于 BungeeCord 插件-->
<dependency>
<groupId>cn.hamster3.mc.plugin</groupId>
<artifactId>core-bungee</artifactId>
<version>1.3.4-SNAPSHOT</version>
<version>1.4.0</version>
</dependency>
</dependencies>
</project>
@@ -74,10 +72,4 @@ dependencies {
- 使用方法为:`CoreAPI.getInstance().xxx()`
- 部分通用的工具代码在 `cn.hamster3.mc.plugin.core.common.util` 包中
- 部分Bukkit的工具代码在 `cn.hamster3.mc.plugin.core.bukkit.util` 包中
- 部分BungeeCord的工具代码在 `cn.hamster3.mc.plugin.core.bungee.util` 包中
# 已知问题
部分 Windows 服务器在启动时偶尔会遇到 Redis 链接失败的问题
如果服务器启动时遇到报错 `Caused by: java.io.IOException: Unable to establish loopback connection`
可以通过在启动脚本中添加 `-Djava.net.preferIPv4Stack=true` 参数解决
- 部分BungeeCord的工具代码在 `cn.hamster3.mc.plugin.core.bungee.util` 包中

View File

@@ -5,7 +5,7 @@ plugins {
}
group = "cn.hamster3.mc.plugin"
version = "1.3.5"
version = "1.4.0"
description = "叁只仓鼠的 Minecraft 插件开发通用工具包"
subprojects {

View File

@@ -1,6 +1,9 @@
@file:Suppress("VulnerableLibrariesLocal")
evaluationDependsOn(":core-common")
evaluationDependsOn(":core-relocate-lettuce")
val shade = configurations.create("shade")
dependencies {
api(project(":core-common")) { isTransitive = false }
@@ -10,26 +13,31 @@ dependencies {
compileOnly("org.black_ixx:playerpoints:3.2.6") { isTransitive = false }
compileOnly("me.clip:placeholderapi:2.11.5") { isTransitive = false }
// https://www.spigotmc.org/resources/nbt-api.7939/
implementation("de.tr7zw:item-nbt-api:2.15.1")
api("net.kyori:adventure-platform-bukkit:4.3.2") {
exclude(group = "org.jetbrains")
exclude(group = "com.google.code.gson")
exclude(group = "io.netty")
}
api("net.kyori:adventure-text-minimessage:4.15.0") {
exclude(module = "adventure-api")
exclude(group = "org.jetbrains")
exclude(group = "io.netty")
}
// https://mvnrepository.com/artifact/redis.clients/jedis
implementation("com.zaxxer:HikariCP:4.0.3") { exclude(group = "org.slf4j") }
api("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
// https://www.spigotmc.org/resources/nbt-api.7939/
implementation("de.tr7zw:item-nbt-api:2.13.2")
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
implementation("com.zaxxer:HikariCP:4.0.3") { exclude(group = "org.slf4j") }
compileOnlyApi("io.lettuce:lettuce-core:6.7.1.RELEASE") {
exclude(group = "org.slf4j")
exclude(group = "io.netty")
}
shade(project(":core-relocate-lettuce"))
}
tasks {
processResources {
filesMatching("plugin.yml") {
@@ -40,6 +48,13 @@ tasks {
archiveBaseName = "HamsterCore-Bukkit"
}
shadowJar {
dependsOn(":core-relocate-lettuce:shadowJar")
val task = project(":core-relocate-lettuce").tasks.shadowJar.get()
from(task.outputs.files.map {
if (it.isDirectory) it else zipTree(
it
)
})
destinationDirectory = rootProject.layout.buildDirectory
relocate("de.tr7zw.changeme.nbtapi", "cn.hamster3.mc.plugin.core.lib.de.tr7zw.nbtapi")
relocate("de.tr7zw.annotations", "cn.hamster3.mc.plugin.core.lib.de.tr7zw.nbtapi.annotations")

View File

@@ -132,6 +132,7 @@ public class HamsterCorePlugin extends JavaPlugin {
long start = System.currentTimeMillis();
if (CoreAPI.getInstance().isEnableRedis()) {
CoreAPI.getInstance().getJedisPool().close();
CoreAPI.getInstance().getRedisClient().close();
simpleLogger.info("已关闭 Redis 连接池");
}
if (CoreAPI.getInstance().isEnableDatabase()) {

View File

@@ -1,6 +1,9 @@
@file:Suppress("VulnerableLibrariesLocal")
evaluationDependsOn(":core-common")
evaluationDependsOn(":core-relocate-lettuce")
val shade = configurations.create("shade")
dependencies {
api(project(":core-common")) { isTransitive = false }
@@ -14,13 +17,17 @@ dependencies {
exclude(module = "adventure-api")
exclude(group = "org.jetbrains")
}
// https://mvnrepository.com/artifact/redis.clients/jedis
implementation("com.zaxxer:HikariCP:4.0.3") { exclude(group = "org.slf4j") }
api("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
implementation("com.zaxxer:HikariCP:4.0.3") { exclude(group = "org.slf4j") }
compileOnlyApi("io.lettuce:lettuce-core:6.7.1.RELEASE") {
exclude(group = "org.slf4j")
exclude(group = "io.netty")
}
shade(project(":core-relocate-lettuce"))
}
tasks {
@@ -33,6 +40,13 @@ tasks {
archiveBaseName = "HamsterCore-BungeeCord"
}
shadowJar {
dependsOn(":core-relocate-lettuce:shadowJar")
val task = project(":core-relocate-lettuce").tasks.shadowJar.get()
from(task.outputs.files.map {
if (it.isDirectory) it else zipTree(
it
)
})
destinationDirectory = rootProject.layout.buildDirectory
}
}

View File

@@ -72,6 +72,7 @@ public class HamsterCorePlugin extends Plugin {
long start = System.currentTimeMillis();
if (CoreAPI.getInstance().isEnableRedis()) {
CoreAPI.getInstance().getJedisPool().close();
CoreAPI.getInstance().getRedisClient().close();
simpleLogger.info("已关闭 Redis 连接池");
}
if (CoreAPI.getInstance().isEnableDatabase()) {

View File

@@ -17,14 +17,18 @@ dependencies {
exclude(group = "com.google.code.gson")
}
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
compileOnly("com.zaxxer:HikariCP:4.0.3") { isTransitive = false }
// https://mvnrepository.com/artifact/redis.clients/jedis
compileOnlyApi("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
compileOnly("com.zaxxer:HikariCP:4.0.3") { isTransitive = false }
// https://mvnrepository.com/artifact/io.lettuce/lettuce-core
compileOnlyApi("io.lettuce:lettuce-core:6.7.1.RELEASE") {
exclude(group = "io.netty")
exclude(group = "org.slf4j")
}
}
tasks {

View File

@@ -6,6 +6,9 @@ import cn.hamster3.mc.plugin.core.common.util.CoreUtils;
import cn.hamster3.mc.plugin.core.common.util.SimpleLogger;
import com.google.gson.Gson;
import com.zaxxer.hikari.HikariDataSource;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import lombok.Getter;
import net.kyori.adventure.platform.AudienceProvider;
import org.jetbrains.annotations.NotNull;
@@ -41,6 +44,11 @@ public abstract class CoreAPI {
*/
@Nullable
private JedisPool jedisPool;
/**
* Lettuce Redis 连接池
*/
@Nullable
private RedisClient redisClient;
/**
* 公用数据库连接池
*/
@@ -57,6 +65,7 @@ public abstract class CoreAPI {
if (enableRedis) {
logger.info("正在创建 Redis 连接池");
jedisPool = new JedisPool(config.getString("redis-url"));
redisClient = RedisClient.create(config.getString("redis-url"));
logger.info("Redis 连接池创建完成");
} else {
logger.info("未启用 Redis 功能");
@@ -108,6 +117,24 @@ public abstract class CoreAPI {
throw new IllegalStateException("仓鼠核心未启用 Redis 功能");
}
@NotNull
public RedisClient getRedisClient() {
if (redisClient != null) {
return redisClient;
}
throw new IllegalStateException("仓鼠核心未启用 Redis 功能");
}
@NotNull
public StatefulRedisConnection<String, String> getRedisConnect() {
return getRedisClient().connect();
}
@NotNull
public StatefulRedisPubSubConnection<String, String> getRedisPubSub() {
return getRedisClient().connectPubSub();
}
@NotNull
public abstract SimpleLogger getLogger();

View File

@@ -0,0 +1,21 @@
// lettuce-core 需要使用 netty但低版本 bukkit 服务端核心自带的 netty 版本 lettuce 需要的版本有冲突
// 所以必须 shadow 并 relocate 依赖 io.netty才能保证两个版本互不冲突
// 但由于 core-bukkit 同时也 shadow 了 adventure-platform-bukkit且 adventure 内部通过反射调用 netty
// 如果在 core-bukkit 中直接 relocate netty会导致 adventure 的反射调用也指向 relocate 后的 netty
// 此时会导致 shadow 后的 adventure 与服务端中其他同样需要使用 netty 的插件关联时发生冲突
// 例如:服务端上安装了 ViaVersion 时core-bukkit 内置的 adventure 将会与其发生冲突
// 因为 adventure 使用 relocate 之后的类路径ViaVersion 在将类转换成原版 netty 类时,会发生 ClassCastException
// 所以只能先将 lettuce-core 与其需要的 netty 一起打包,并 relocate netty然后再使 core-bukkit 依赖这个打包后的版本
// 才能使得 adventure 与 lettuce-core 正常运行
dependencies {
implementation("io.lettuce:lettuce-core:6.7.1.RELEASE") {
exclude(group = "org.slf4j")
}
}
tasks {
shadowJar {
relocate("io.netty", "cn.hamster3.mc.plugin.core.lib.io.netty")
}
}

View File

@@ -9,17 +9,18 @@ dependencies {
compileOnlyApi("net.kyori:adventure-platform-api:4.3.2") { isTransitive = false }
// https://mvnrepository.com/artifact/redis.clients/jedis
implementation("com.zaxxer:HikariCP:5.1.0") { isTransitive = false }
api("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
implementation("com.zaxxer:HikariCP:5.1.0") { isTransitive = false }
api("io.lettuce:lettuce-core:6.7.1.RELEASE") {
exclude(group = "io.netty")
exclude(group = "org.slf4j")
}
// https://mvnrepository.com/artifact/com.mysql/mysql-connector-j
runtimeOnly("com.mysql:mysql-connector-j:8.3.0")
runtimeOnly("com.mysql:mysql-connector-j:8.4.0")
}
sourceSets.create("templates") {

View File

@@ -85,6 +85,7 @@ public class HamsterCorePlugin {
long start = System.currentTimeMillis();
if (CoreAPI.getInstance().isEnableRedis()) {
CoreAPI.getInstance().getJedisPool().close();
CoreAPI.getInstance().getRedisClient().close();
simpleLogger.info("已关闭 Redis 连接池");
}
if (CoreAPI.getInstance().isEnableDatabase()) {

View File

@@ -1,8 +1,6 @@
pluginManagement {
repositories {
maven {
url = uri("https://maven.airgame.net/maven-public/")
}
maven("https://maven.airgame.net/maven-public/")
}
}
rootProject.name = "hamster-core"
@@ -10,3 +8,4 @@ include("core-common")
include("core-bukkit")
include("core-bungee")
include("core-velocity")
include("core-relocate-lettuce")