diff --git a/README.md b/README.md
index d25e42b..fa71896 100644
--- a/README.md
+++ b/README.md
@@ -27,12 +27,10 @@
为了适配 docker 环境,本插件除了从 `config.yml` 中配置服务器信息以外,还支持从环境变量中读取
-| 环境变量 | 描述 | 对应 config 值 |
-|:----------------------------|:-------------------|:-----------------|
-| BALL_LOCAL_SERVER_IP | 本服务器 IP | server-info.host |
-| BALL_LOCAL_SERVER_PORT | 本服务器端口 | server-info.port |
-| BALL_LOCAL_SERVER_INFO_ID | 本服务器唯一识别码,最长 32 字符 | server-info.id |
-| BALL_LOCAL_SERVER_INFO_NAME | 本服务端名称,用于展示给玩家看 | server-info.name |
+| 环境变量 | 描述 | 对应 config 值 |
+|:-----------------|:-------------------|:-----------------|
+| BALL_SERVER_ID | 本服务器唯一识别码,最长 32 字符 | server-info.id |
+| BALL_SERVER_NAME | 本服务端名称,用于展示给玩家看 | server-info.name |
# 开发
@@ -51,9 +49,9 @@ repositories {
dependencies {
// 对于 Bukkit 插件
- compileOnly("cn.hamster3.mc.plugin:ball-bukkit:1.5.7")
+ compileOnly("cn.hamster3.mc.plugin:ball-bukkit:1.6.0")
// 对于 BungeeCord 插件
- compileOnly("cn.hamster3.mc.plugin:ball-bungee:1.5.7")
+ compileOnly("cn.hamster3.mc.plugin:ball-bungee:1.6.0")
}
```
@@ -79,13 +77,13 @@ dependencies {
cn.hamster3.mc.plugin
ball-bukkit
- 1.5.7
+ 1.6.0
cn.hamster3.mc.plugin
ball-bungee
- 1.5.7
+ 1.6.0
diff --git a/ball-bukkit/src/main/java/cn/hamster3/mc/plugin/ball/bukkit/api/BallBukkitAPI.java b/ball-bukkit/src/main/java/cn/hamster3/mc/plugin/ball/bukkit/api/BallBukkitAPI.java
index 8b3e13b..8cc0bef 100644
--- a/ball-bukkit/src/main/java/cn/hamster3/mc/plugin/ball/bukkit/api/BallBukkitAPI.java
+++ b/ball-bukkit/src/main/java/cn/hamster3/mc/plugin/ball/bukkit/api/BallBukkitAPI.java
@@ -5,6 +5,7 @@ import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.entity.BallServerType;
import cn.hamster3.mc.plugin.core.common.config.ConfigSection;
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
+import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -31,6 +32,8 @@ public class BallBukkitAPI extends BallAPI {
@Override
public void enable() throws SQLException, InterruptedException {
+ instance.getLocalServerInfo().setHost(Bukkit.getIp().isEmpty() ? "127.0.0.1" : Bukkit.getIp());
+ instance.getLocalServerInfo().setPort(Bukkit.getPort());
super.enable();
}
diff --git a/ball-bungee/src/main/java/cn/hamster3/mc/plugin/ball/bungee/api/BallBungeeCordAPI.java b/ball-bungee/src/main/java/cn/hamster3/mc/plugin/ball/bungee/api/BallBungeeCordAPI.java
index 4f5aafb..a7f8102 100644
--- a/ball-bungee/src/main/java/cn/hamster3/mc/plugin/ball/bungee/api/BallBungeeCordAPI.java
+++ b/ball-bungee/src/main/java/cn/hamster3/mc/plugin/ball/bungee/api/BallBungeeCordAPI.java
@@ -5,10 +5,13 @@ import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.entity.BallServerType;
import cn.hamster3.mc.plugin.core.common.config.ConfigSection;
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.config.ListenerInfo;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
+import java.net.InetSocketAddress;
import java.sql.SQLException;
import java.util.logging.Logger;
@@ -31,6 +34,14 @@ public class BallBungeeCordAPI extends BallAPI {
@Override
public void enable() throws SQLException, InterruptedException {
+ for (ListenerInfo listenerInfo : ProxyServer.getInstance().getConfig().getListeners()) {
+ if (!(listenerInfo.getSocketAddress() instanceof InetSocketAddress)) {
+ continue;
+ }
+ InetSocketAddress address = (InetSocketAddress) listenerInfo.getSocketAddress();
+ instance.getLocalServerInfo().setHost(address.getHostString());
+ instance.getLocalServerInfo().setPort(address.getPort());
+ }
super.enable();
}
diff --git a/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/api/BallAPI.java b/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/api/BallAPI.java
index af9e218..1985911 100644
--- a/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/api/BallAPI.java
+++ b/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/api/BallAPI.java
@@ -13,6 +13,7 @@ import cn.hamster3.mc.plugin.ball.common.event.server.ServerOfflineEvent;
import cn.hamster3.mc.plugin.ball.common.listener.BallCommonListener;
import cn.hamster3.mc.plugin.ball.common.listener.BallDebugListener;
import cn.hamster3.mc.plugin.ball.common.listener.BallRedisListener;
+import cn.hamster3.mc.plugin.ball.common.thread.LockUpdateThread;
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import cn.hamster3.mc.plugin.core.common.config.ConfigSection;
import cn.hamster3.mc.plugin.core.common.data.DisplayMessage;
@@ -29,6 +30,8 @@ import javax.sql.DataSource;
import java.sql.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
@Getter
@@ -66,8 +69,8 @@ public abstract class BallAPI {
@NotNull
private final Jedis redisSub;
- @NotNull
- private final Jedis redisPub;
+ @Nullable
+ private ScheduledFuture> lockUpdater;
public BallAPI(@NotNull ConfigSection config, BallServerType type) {
ConfigSection serverInfoConfig = config.getSection("server-info");
@@ -89,7 +92,6 @@ public abstract class BallAPI {
allServerInfo = new ConcurrentHashMap<>();
allPlayerInfo = new ConcurrentHashMap<>();
redisSub = CoreAPI.getInstance().getJedisPool().getResource();
- redisPub = CoreAPI.getInstance().getJedisPool().getResource();
getLogger().info("频道前缀: " + ballConfig.getChannelPrefix());
getLogger().info("启用子服更新玩家状态: " + ballConfig.isGameServerUpdatePlayerInfo());
if (ballConfig.isGameServerUpdatePlayerInfo()) {
@@ -102,6 +104,29 @@ public abstract class BallAPI {
}
protected void enable() throws SQLException, InterruptedException {
+ try (Jedis jedis = CoreAPI.getInstance().getJedisPool().getResource()) {
+ String key = "HamsterBall:ServerInfo:" + localServerInfo.getId();
+ if (jedis.exists(key)) {
+ throw new IllegalStateException("已经有一个服务器占用了该 ID");
+ }
+ jedis.hset(key, "id", localServerInfo.getId());
+ jedis.hset(key, "name", localServerInfo.getName());
+ jedis.hset(key, "type", localServerInfo.getType().name());
+ jedis.hset(key, "host", localServerInfo.getHost());
+ jedis.hset(key, "port", String.valueOf(localServerInfo.getPort()));
+ jedis.expire(key, 180);
+ lockUpdater = CoreAPI.getInstance().getScheduledService().scheduleAtFixedRate(LockUpdateThread.INSTANCE, 1, 1, TimeUnit.MINUTES);
+ for (String serverInfoKey : jedis.keys("HamsterBall:ServerInfo:*")) {
+ BallServerInfo info = new BallServerInfo(
+ jedis.hget(serverInfoKey, "id"),
+ jedis.hget(serverInfoKey, "name"),
+ BallServerType.valueOf(jedis.hget(serverInfoKey, "type")),
+ jedis.hget(serverInfoKey, "host"),
+ Integer.parseInt(jedis.hget(serverInfoKey, "port"))
+ );
+ allServerInfo.put(info.getId(), info);
+ }
+ }
try (Connection connection = getDatasource().getConnection()) {
try (Statement statement = connection.createStatement()) {
statement.execute("CREATE TABLE IF NOT EXISTS `hamster_ball_player_info`(" +
@@ -111,44 +136,11 @@ public abstract class BallAPI {
"`proxy_server` VARCHAR(32) NOT NULL," +
"`online` BOOLEAN NOT NULL" +
") CHARSET utf8mb4;");
- statement.execute("CREATE TABLE IF NOT EXISTS `hamster_ball_server_info`(" +
- "`id` VARCHAR(32) PRIMARY KEY NOT NULL," +
- "`name` VARCHAR(32) NOT NULL," +
- "`type` VARCHAR(16) NOT NULL," +
- "`host` VARCHAR(32) NOT NULL," +
- "`port` INT NOT NULL" +
- ") CHARSET utf8mb4;");
statement.execute("CREATE TABLE IF NOT EXISTS `hamster_ball_cached_message`(" +
"`uuid` CHAR(36) NOT NULL," +
"`message` TEXT NOT NULL" +
") CHARSET utf8mb4;");
}
- try (PreparedStatement statement = connection.prepareStatement(
- "REPLACE INTO `hamster_ball_server_info` VALUES(?, ?, ?, ?, ?);"
- )) {
- statement.setString(1, localServerInfo.getId());
- statement.setString(2, localServerInfo.getName());
- statement.setString(3, localServerInfo.getType().name());
- statement.setString(4, localServerInfo.getHost());
- statement.setInt(5, localServerInfo.getPort());
- statement.executeUpdate();
- }
- try (PreparedStatement statement = connection.prepareStatement(
- "SELECT * FROM `hamster_ball_server_info`;"
- )) {
- try (ResultSet set = statement.executeQuery()) {
- while (set.next()) {
- String serverID = set.getString("id");
- allServerInfo.put(serverID, new BallServerInfo(
- serverID,
- set.getString("name"),
- BallServerType.valueOf(set.getString("type")),
- set.getString("host"),
- set.getInt("port")
- ));
- }
- }
- }
if (getBallConfig().isGameServerUpdatePlayerInfo()) {
try (Statement statement = connection.createStatement()) {
try (ResultSet set = statement.executeQuery(String.format(
@@ -193,14 +185,15 @@ public abstract class BallAPI {
sendBallMessage(BallAPI.BALL_CHANNEL, new BallMessage(
BallActions.ServerOffline.name(), new ServerOfflineEvent(getLocalServerInfo())
), false, true);
-
- try (Connection connection = getDatasource().getConnection()) {
- try (PreparedStatement statement = connection.prepareStatement(
- "DELETE FROM `hamster_ball_server_info` WHERE `id`=?;"
- )) {
- statement.setString(1, getLocalServerId());
- statement.executeUpdate();
+ if (lockUpdater != null) {
+ lockUpdater.cancel(true);
+ lockUpdater = null;
+ try (Jedis jedis = CoreAPI.getInstance().getJedisPool().getResource()) {
+ String key = "HamsterBall:ServerInfo:" + localServerInfo.getId();
+ jedis.del(key);
}
+ }
+ try (Connection connection = getDatasource().getConnection()) {
try (PreparedStatement statement = connection.prepareStatement(
"UPDATE `hamster_ball_player_info` SET `online`=false WHERE `game_server`=? OR `proxy_server`=?"
)) {
@@ -210,7 +203,6 @@ public abstract class BallAPI {
}
}
redisSub.close();
- redisPub.close();
}
/**
@@ -493,12 +485,17 @@ public abstract class BallAPI {
channel = ballConfig.getChannelPrefix() + channel;
}
if (block) {
- redisPub.publish(channel, CoreAPI.getInstance().getGson().toJson(message));
+ try (Jedis jedis = CoreAPI.getInstance().getJedisPool().getResource()) {
+ jedis.publish(channel, CoreAPI.getInstance().getGson().toJson(message));
+ }
eventBus.post(new MessageSentEvent(channel, message));
} else {
@NotNull String finalChannel = channel;
CoreAPI.getInstance().getExecutorService().submit(() -> {
- redisPub.publish(finalChannel, CoreAPI.getInstance().getGson().toJson(message));
+ try (Jedis jedis = CoreAPI.getInstance().getJedisPool().getResource()) {
+ jedis.publish(finalChannel, CoreAPI.getInstance().getGson().toJson(message));
+ }
+ eventBus.post(new MessageSentEvent(finalChannel, message));
});
}
}
diff --git a/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/entity/BallServerInfo.java b/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/entity/BallServerInfo.java
index d9f49ad..5490d2f 100644
--- a/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/entity/BallServerInfo.java
+++ b/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/entity/BallServerInfo.java
@@ -45,13 +45,11 @@ public class BallServerInfo {
public BallServerInfo(@NotNull ConfigSection config, BallServerType type) {
Map env = System.getenv();
- id = env.getOrDefault("BALL_LOCAL_SERVER_INFO_ID", config.getString("id"));
- name = env.getOrDefault("BALL_LOCAL_SERVER_INFO_NAME", config.getString("name"));
+ id = env.getOrDefault("BALL_SERVER_ID", config.getString("id"));
+ name = env.getOrDefault("BALL_SERVER_NAME", config.getString("name"));
this.type = type;
- host = env.getOrDefault("BALL_LOCAL_SERVER_IP", config.getString("host"));
- port = Integer.parseInt(
- env.getOrDefault("BALL_LOCAL_SERVER_PORT", String.valueOf(config.getInt("port")))
- );
+ host = "0.0.0.0";
+ port = 0;
}
@Override
diff --git a/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/thread/LockUpdateThread.java b/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/thread/LockUpdateThread.java
new file mode 100644
index 0000000..2c7b147
--- /dev/null
+++ b/ball-common/src/main/java/cn/hamster3/mc/plugin/ball/common/thread/LockUpdateThread.java
@@ -0,0 +1,20 @@
+package cn.hamster3.mc.plugin.ball.common.thread;
+
+import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
+import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
+import cn.hamster3.mc.plugin.core.lib.redis.clients.jedis.Jedis;
+
+public class LockUpdateThread implements Runnable {
+ public static final LockUpdateThread INSTANCE = new LockUpdateThread();
+
+ private LockUpdateThread() {
+ }
+
+ @Override
+ public void run() {
+ String key = "HamsterBall:ServerInfo:" + BallAPI.getInstance().getLocalServerInfo().getId();
+ try (Jedis jedis = CoreAPI.getInstance().getJedisPool().getResource()) {
+ jedis.expire(key, 180);
+ }
+ }
+}