Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
d38bd5e41f | |||
52e25a0433 | |||
cc33304ad4 | |||
6d2abfa44b | |||
bc49510c46 | |||
74f1a4557d | |||
84721e31ee | |||
4e29246441 | |||
aa0e94c7b7 | |||
aac7248994 | |||
54461173c0 | |||
54f9e5cbc6 | |||
8dae4f7667 | |||
47a183f4ca | |||
b0e149febb |
10
README.md
10
README.md
@@ -1,6 +1,6 @@
|
|||||||
# [HamsterBall](https://git.airgame.net/MiniDay/hamster-ball)
|
# [HamsterBall](https://git.airgame.net/MiniDay/hamster-ball)
|
||||||
|
|
||||||
仓鼠球:一个基于 Redis 的 Minecraft 服务端通用消息中间件(原HamsterService)
|
基于 Redis 的 Minecraft 服务端通用消息中间件
|
||||||
|
|
||||||
该插件依赖于 [仓鼠核心](https://git.airgame.net/MiniDay/hamster-core)
|
该插件依赖于 [仓鼠核心](https://git.airgame.net/MiniDay/hamster-core)
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// 对于 Bukkit 插件
|
// 对于 Bukkit 插件
|
||||||
compileOnly("cn.hamster3.mc.plugin:ball-bukkit:1.6.1")
|
compileOnly("cn.hamster3.mc.plugin:ball-bukkit:1.6.4")
|
||||||
// 对于 BungeeCord 插件
|
// 对于 BungeeCord 插件
|
||||||
compileOnly("cn.hamster3.mc.plugin:ball-bungee:1.6.1")
|
compileOnly("cn.hamster3.mc.plugin:ball-bungee:1.6.4")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -77,13 +77,13 @@ dependencies {
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hamster3.mc.plugin</groupId>
|
<groupId>cn.hamster3.mc.plugin</groupId>
|
||||||
<artifactId>ball-bukkit</artifactId>
|
<artifactId>ball-bukkit</artifactId>
|
||||||
<version>1.6.1</version>
|
<version>1.6.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--对于 BungeeCord 插件-->
|
<!--对于 BungeeCord 插件-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hamster3.mc.plugin</groupId>
|
<groupId>cn.hamster3.mc.plugin</groupId>
|
||||||
<artifactId>ball-bungee</artifactId>
|
<artifactId>ball-bungee</artifactId>
|
||||||
<version>1.6.1</version>
|
<version>1.6.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@@ -9,6 +9,7 @@ import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
|
|||||||
import cn.hamster3.mc.plugin.ball.common.entity.BallPlayerInfo;
|
import cn.hamster3.mc.plugin.ball.common.entity.BallPlayerInfo;
|
||||||
import cn.hamster3.mc.plugin.ball.common.event.BallActions;
|
import cn.hamster3.mc.plugin.ball.common.event.BallActions;
|
||||||
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
||||||
|
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
@@ -55,7 +56,8 @@ public class HamsterBallPlugin extends JavaPlugin {
|
|||||||
StandardCopyOption.REPLACE_EXISTING
|
StandardCopyOption.REPLACE_EXISTING
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
BallBukkitAPI.init(configFile);
|
YamlConfig config = YamlConfig.load(configFile);
|
||||||
|
BallBukkitAPI.init(config);
|
||||||
logger.info("已初始化 BallAPI");
|
logger.info("已初始化 BallAPI");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "BallAPI 初始化失败", e);
|
logger.log(Level.SEVERE, "BallAPI 初始化失败", e);
|
||||||
@@ -98,7 +100,7 @@ public class HamsterBallPlugin extends JavaPlugin {
|
|||||||
BallBukkitUtils.uploadPlayerInfo(playerInfo);
|
BallBukkitUtils.uploadPlayerInfo(playerInfo);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
BallAPI.getInstance().subscribeIgnorePrefix(BallAPI.PLAYER_INFO_CHANNEL);
|
BallAPI.getInstance().subscribeRaw(BallAPI.PLAYER_INFO_CHANNEL);
|
||||||
}
|
}
|
||||||
sync(() -> {
|
sync(() -> {
|
||||||
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||||
|
@@ -8,8 +8,6 @@ import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -22,11 +20,10 @@ public class BallBukkitAPI extends BallAPI {
|
|||||||
return (BallBukkitAPI) instance;
|
return (BallBukkitAPI) instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(@NotNull File configFile) throws IOException {
|
public static void init(@NotNull YamlConfig config) {
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
YamlConfig config = YamlConfig.load(configFile);
|
|
||||||
instance = new BallBukkitAPI(config);
|
instance = new BallBukkitAPI(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@ channel-prefix: ""
|
|||||||
# 如果一个群组服同时拥有多个 BC 入口
|
# 如果一个群组服同时拥有多个 BC 入口
|
||||||
# 且每个 BC 入口为不同的玩家名称分配不同的 UUID
|
# 且每个 BC 入口为不同的玩家名称分配不同的 UUID
|
||||||
# (例如正版、盗版双入口,或网易多入口接同一个子服)
|
# (例如正版、盗版双入口,或网易多入口接同一个子服)
|
||||||
# 则可以启用该功能以防止 UUID 紊乱的问题
|
# 则可以启用该功能以防止同一个名称占用多个 UUID 的问题
|
||||||
game-server-update-player-info: false
|
game-server-update-player-info: false
|
||||||
|
|
||||||
# 该选项仅在 game-server-update-player-info 为 true 时有效
|
# 该选项仅在 game-server-update-player-info 为 true 时有效
|
||||||
@@ -41,16 +41,18 @@ server-info:
|
|||||||
# 如果你需要让每个服务器单独存储仓鼠球信息
|
# 如果你需要让每个服务器单独存储仓鼠球信息
|
||||||
# 这个选项就会很有用
|
# 这个选项就会很有用
|
||||||
#datasource:
|
#datasource:
|
||||||
# # 数据库链接驱动地址
|
# # 数据库链接驱动地址,旧版服务端(低于1.13)请使用:com.mysql.jdbc.Driver
|
||||||
# driver: "com.mysql.jdbc.Driver"
|
# driver: "com.mysql.cj.jdbc.Driver"
|
||||||
# # 数据库链接填写格式:
|
# # MySQL数据库链接填写格式:
|
||||||
# # jdbc:mysql://{数据库地址}:{数据库端口}/{使用的库名}?参数
|
# # jdbc:mysql://{数据库地址}:{数据库端口}/{使用的库名}?参数
|
||||||
# # 除非你知道自己在做什么,否则不建议随意更改参数
|
# url: "jdbc:mysql://localhost:3306/Test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true"
|
||||||
# url: "jdbc:mysql://localhost:3306/Test1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true"
|
# # 如果你不需要做多端跨服,那么请使用 sqlite 作本地数据库 ↓
|
||||||
|
# # driver: "org.sqlite.JDBC"
|
||||||
|
# # url: "jdbc:sqlite:./plugins/HamsterCore/database.db"
|
||||||
# # 用户名
|
# # 用户名
|
||||||
# username: "Test"
|
# username: "root"
|
||||||
# # 密码
|
# # 密码
|
||||||
# password: "Test123.."
|
# password: "Root123.."
|
||||||
# # 最小闲置链接数
|
# # 最小闲置链接数
|
||||||
# # 推荐值:1~3
|
# # 推荐值:1~3
|
||||||
# minimum-idle: 0
|
# minimum-idle: 0
|
||||||
|
@@ -4,8 +4,15 @@ version: ${version}
|
|||||||
api-version: 1.13
|
api-version: 1.13
|
||||||
|
|
||||||
author: MiniDay
|
author: MiniDay
|
||||||
|
description: ${description}
|
||||||
website: https://git.airgame.net/MiniDay/hamster-ball
|
website: https://git.airgame.net/MiniDay/hamster-ball
|
||||||
description: 仓鼠球:一个基于 Redis 的 Minecraft 服务端通用消息中间件(原HamsterService)
|
|
||||||
|
UPDATE_CHECKER:
|
||||||
|
VERSION: ${version}
|
||||||
|
CHECK_TYPE: GITEA_RELEASES
|
||||||
|
GIT_BASE_URL: https://git.airgame.net
|
||||||
|
GIT_REPO: MiniDay/hamster-ball
|
||||||
|
DOWNLOAD_URL: https://jenkins.airgame.net/job/opensource/job/hamster-ball/
|
||||||
|
|
||||||
load: STARTUP
|
load: STARTUP
|
||||||
|
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
version: ${version}
|
|
||||||
CHECK_TYPE: GITEA_RELEASES
|
|
||||||
GIT_BASE_URL: https://git.airgame.net
|
|
||||||
GIT_REPO: MiniDay/hamster-ball
|
|
||||||
GIT_TOKEN: a44a69a4d1b8601bf6091403247759cd28764d5e
|
|
||||||
DOWNLOAD_URL: https://jenkins.airgame.net/job/opensource/job/hamster-ball/
|
|
@@ -3,12 +3,14 @@ package cn.hamster3.mc.plugin.ball.bungee;
|
|||||||
import cn.hamster3.mc.plugin.ball.bungee.api.BallBungeeCordAPI;
|
import cn.hamster3.mc.plugin.ball.bungee.api.BallBungeeCordAPI;
|
||||||
import cn.hamster3.mc.plugin.ball.bungee.listener.BallBungeeListener;
|
import cn.hamster3.mc.plugin.ball.bungee.listener.BallBungeeListener;
|
||||||
import cn.hamster3.mc.plugin.ball.bungee.listener.BallBungeeMainListener;
|
import cn.hamster3.mc.plugin.ball.bungee.listener.BallBungeeMainListener;
|
||||||
|
import cn.hamster3.mc.plugin.ball.bungee.listener.BungeeServerListener;
|
||||||
import cn.hamster3.mc.plugin.ball.bungee.listener.UpdatePlayerInfoListener;
|
import cn.hamster3.mc.plugin.ball.bungee.listener.UpdatePlayerInfoListener;
|
||||||
import cn.hamster3.mc.plugin.ball.bungee.util.BallBungeeCordUtils;
|
import cn.hamster3.mc.plugin.ball.bungee.util.BallBungeeCordUtils;
|
||||||
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
|
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
|
||||||
import cn.hamster3.mc.plugin.ball.common.entity.BallPlayerInfo;
|
import cn.hamster3.mc.plugin.ball.common.entity.BallPlayerInfo;
|
||||||
import cn.hamster3.mc.plugin.ball.common.event.BallActions;
|
import cn.hamster3.mc.plugin.ball.common.event.BallActions;
|
||||||
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
||||||
|
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
@@ -22,6 +24,8 @@ import java.util.logging.Logger;
|
|||||||
public class HamsterBallPlugin extends Plugin {
|
public class HamsterBallPlugin extends Plugin {
|
||||||
@Getter
|
@Getter
|
||||||
private static HamsterBallPlugin instance;
|
private static HamsterBallPlugin instance;
|
||||||
|
@Getter
|
||||||
|
private YamlConfig config;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
@@ -42,7 +46,8 @@ public class HamsterBallPlugin extends Plugin {
|
|||||||
StandardCopyOption.REPLACE_EXISTING
|
StandardCopyOption.REPLACE_EXISTING
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
BallBungeeCordAPI.init(configFile);
|
config = YamlConfig.load(configFile);
|
||||||
|
BallBungeeCordAPI.init(config);
|
||||||
logger.info("已初始化 BallAPI");
|
logger.info("已初始化 BallAPI");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "BallAPI 初始化失败", e);
|
logger.log(Level.SEVERE, "BallAPI 初始化失败", e);
|
||||||
@@ -72,11 +77,16 @@ public class HamsterBallPlugin extends Plugin {
|
|||||||
logger.info("已注册监听器 BallBungeeMainListener");
|
logger.info("已注册监听器 BallBungeeMainListener");
|
||||||
ProxyServer.getInstance().getPluginManager().registerListener(this, UpdatePlayerInfoListener.INSTANCE);
|
ProxyServer.getInstance().getPluginManager().registerListener(this, UpdatePlayerInfoListener.INSTANCE);
|
||||||
logger.info("已注册监听器 UpdatePlayerInfoListener");
|
logger.info("已注册监听器 UpdatePlayerInfoListener");
|
||||||
|
if (config.getBoolean("auto-register-game-server", false)) {
|
||||||
|
BallAPI.getInstance().getEventBus().register(BungeeServerListener.INSTANCE);
|
||||||
|
logger.info("已注册监听器 BungeeServerListener");
|
||||||
|
BungeeServerListener.INSTANCE.onEnable();
|
||||||
|
}
|
||||||
|
|
||||||
if (BallAPI.getInstance().getBallConfig().isGameServerUpdatePlayerInfo()) {
|
if (BallAPI.getInstance().getBallConfig().isGameServerUpdatePlayerInfo()) {
|
||||||
BallAPI.getInstance().subscribePatterns("*" + BallAPI.PLAYER_INFO_CHANNEL);
|
BallAPI.getInstance().subscribePatterns("*" + BallAPI.PLAYER_INFO_CHANNEL);
|
||||||
} else {
|
} else {
|
||||||
BallAPI.getInstance().subscribeIgnorePrefix(BallAPI.PLAYER_INFO_CHANNEL);
|
BallAPI.getInstance().subscribeRaw(BallAPI.PLAYER_INFO_CHANNEL);
|
||||||
}
|
}
|
||||||
BallAPI.getInstance().sendRawBallMessage(
|
BallAPI.getInstance().sendRawBallMessage(
|
||||||
BallAPI.BALL_CHANNEL, BallActions.ServerOnline.name(),
|
BallAPI.BALL_CHANNEL, BallActions.ServerOnline.name(),
|
||||||
|
@@ -9,8 +9,6 @@ import net.md_5.bungee.api.ProxyServer;
|
|||||||
import net.md_5.bungee.api.config.ListenerInfo;
|
import net.md_5.bungee.api.config.ListenerInfo;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -24,11 +22,10 @@ public class BallBungeeCordAPI extends BallAPI {
|
|||||||
return (BallBungeeCordAPI) instance;
|
return (BallBungeeCordAPI) instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(@NotNull File configFile) throws IOException {
|
public static void init(@NotNull YamlConfig config) {
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
YamlConfig config = YamlConfig.load(configFile);
|
|
||||||
instance = new BallBungeeCordAPI(config);
|
instance = new BallBungeeCordAPI(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,59 @@
|
|||||||
|
package cn.hamster3.mc.plugin.ball.bungee.listener;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.entity.BallServerType;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOfflineEvent;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BungeeServerListener {
|
||||||
|
public static final BungeeServerListener INSTANCE = new BungeeServerListener();
|
||||||
|
|
||||||
|
private BungeeServerListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEnable() {
|
||||||
|
for (BallServerInfo info : BallAPI.getInstance().getAllServerInfo().values()) {
|
||||||
|
if (info.getType() != BallServerType.GAME) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ProxyServer.getInstance().getServers().put(info.getId(), getServerInfo(info));
|
||||||
|
BallAPI.getInstance().getLogger().info("已添加服务器入口: " + info.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onServerOnline(ServerOnlineEvent event) {
|
||||||
|
if (event.getType() != BallServerType.GAME) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProxyServer.getInstance().getServers().put(event.getId(), getServerInfo(event));
|
||||||
|
BallAPI.getInstance().getLogger().info("已添加服务器入口: " + event.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onServerOffline(ServerOfflineEvent event) {
|
||||||
|
if (event.getType() != BallServerType.GAME) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, ServerInfo> map = ProxyServer.getInstance().getServers();
|
||||||
|
if (map.remove(event.getId()) != null) {
|
||||||
|
BallAPI.getInstance().getLogger().info("已移除服务器入口: " + event.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServerInfo getServerInfo(BallServerInfo serverInfo) {
|
||||||
|
return ProxyServer.getInstance().constructServerInfo(
|
||||||
|
serverInfo.getId(),
|
||||||
|
new InetSocketAddress(serverInfo.getHost(), serverInfo.getPort()),
|
||||||
|
serverInfo.getName(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,15 @@ main: cn.hamster3.mc.plugin.ball.bungee.HamsterBallPlugin
|
|||||||
version: ${version}
|
version: ${version}
|
||||||
|
|
||||||
author: MiniDay
|
author: MiniDay
|
||||||
description: 仓鼠球:一个基于 Redis 的 Minecraft 服务端通用消息中间件(原HamsterService)
|
description: ${description}
|
||||||
|
website: https://git.airgame.net/MiniDay/hamster-ball
|
||||||
|
|
||||||
|
UPDATE_CHECKER:
|
||||||
|
VERSION: ${version}
|
||||||
|
CHECK_TYPE: GITEA_RELEASES
|
||||||
|
GIT_BASE_URL: https://git.airgame.net
|
||||||
|
GIT_REPO: MiniDay/hamster-ball
|
||||||
|
DOWNLOAD_URL: https://jenkins.airgame.net/job/opensource/job/hamster-ball/
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
- HamsterCore
|
- HamsterCore
|
||||||
|
@@ -8,12 +8,14 @@ channel-prefix: ""
|
|||||||
|
|
||||||
# 是否在子服端更新玩家信息
|
# 是否在子服端更新玩家信息
|
||||||
# 默认情况下,BC 统一管理玩家信息,包括记录 UUID 和玩家名称
|
# 默认情况下,BC 统一管理玩家信息,包括记录 UUID 和玩家名称
|
||||||
# 如果一个群组服同时拥有多个 BC 入口
|
# 如果一个群组服同时拥有多个 BC 入口,且每个 BC 入口为不同的玩家名称分配不同的 UUID
|
||||||
# 且每个 BC 入口为不同的玩家名称分配不同的 UUID
|
|
||||||
# (例如正版、盗版双入口,或网易多入口接同一个子服)
|
# (例如正版、盗版双入口,或网易多入口接同一个子服)
|
||||||
# 则可以启用该功能以防止 UUID 紊乱的问题
|
# 则可以启用该功能以防止同一个名称占用多个 UUID 的问题
|
||||||
game-server-update-player-info: false
|
game-server-update-player-info: false
|
||||||
|
|
||||||
|
# 启用后,子服启动时会自动注册该子服的入口配置,关闭时也会自动移除该子服的入口配置
|
||||||
|
auto-register-game-server: false
|
||||||
|
|
||||||
# 本服务器信息
|
# 本服务器信息
|
||||||
server-info:
|
server-info:
|
||||||
# 服务器唯一识别码,最长 32 字符
|
# 服务器唯一识别码,最长 32 字符
|
||||||
@@ -34,21 +36,20 @@ server-info:
|
|||||||
# 这个选项就会很有用
|
# 这个选项就会很有用
|
||||||
#datasource:
|
#datasource:
|
||||||
# # 数据库链接驱动地址
|
# # 数据库链接驱动地址
|
||||||
# driver: "com.mysql.jdbc.Driver"
|
# driver: "com.mysql.cj.jdbc.Driver"
|
||||||
# # 数据库链接填写格式:
|
# # MySQL数据库链接填写格式:
|
||||||
# # jdbc:mysql://{数据库地址}:{数据库端口}/{使用的库名}?参数
|
# # jdbc:mysql://{数据库地址}:{数据库端口}/{使用的库名}?参数
|
||||||
# # 除非你知道自己在做什么,否则不建议随意更改参数
|
# url: "jdbc:mysql://localhost:3306/Test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true"
|
||||||
# url: "jdbc:mysql://localhost:3306/Test1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true"
|
|
||||||
# # 用户名
|
# # 用户名
|
||||||
# username: "Test"
|
# username: "root"
|
||||||
# # 密码
|
# # 密码
|
||||||
# password: "Test123.."
|
# password: "Root123.."
|
||||||
# # 最小闲置链接数
|
# # 最小闲置链接数
|
||||||
# # 推荐值:1~3
|
# # 推荐值:1~3
|
||||||
# minimum-idle: 0
|
# minimum-idle: 0
|
||||||
# # 最大链接数
|
# # 最大链接数
|
||||||
# # 推荐值:不低于3
|
# # 推荐值:不低于5
|
||||||
# maximum-pool-size: 3
|
# maximum-pool-size: 5
|
||||||
# # 保持连接池可用的间隔
|
# # 保持连接池可用的间隔
|
||||||
# # 除非你的服务器数据库连接经常断开,否则不建议启用该选项
|
# # 除非你的服务器数据库连接经常断开,否则不建议启用该选项
|
||||||
# # 单位:毫秒
|
# # 单位:毫秒
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
version: ${version}
|
|
||||||
CHECK_TYPE: GITEA_RELEASES
|
|
||||||
GIT_BASE_URL: https://git.airgame.net
|
|
||||||
GIT_REPO: MiniDay/hamster-ball
|
|
||||||
GIT_TOKEN: a44a69a4d1b8601bf6091403247759cd28764d5e
|
|
||||||
DOWNLOAD_URL: https://jenkins.airgame.net/job/opensource/job/hamster-ball/
|
|
@@ -73,7 +73,7 @@ public abstract class BallAPI {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private ScheduledFuture<?> lockUpdater;
|
private ScheduledFuture<?> lockUpdater;
|
||||||
|
|
||||||
public BallAPI(@NotNull ConfigSection config, BallServerType type) {
|
public BallAPI(@NotNull ConfigSection config, @NotNull BallServerType type) {
|
||||||
ConfigSection serverInfoConfig = config.getSection("server-info");
|
ConfigSection serverInfoConfig = config.getSection("server-info");
|
||||||
if (serverInfoConfig == null) {
|
if (serverInfoConfig == null) {
|
||||||
throw new IllegalArgumentException("配置文件中未找到 server-info 节点");
|
throw new IllegalArgumentException("配置文件中未找到 server-info 节点");
|
||||||
@@ -88,7 +88,7 @@ public abstract class BallAPI {
|
|||||||
datasource = CoreAPI.getInstance().getDataSource();
|
datasource = CoreAPI.getInstance().getDataSource();
|
||||||
}
|
}
|
||||||
ballConfig = new BallConfig(config);
|
ballConfig = new BallConfig(config);
|
||||||
eventBus = new AsyncEventBus("HamsterBall - EventBus", CoreAPI.getInstance().getExecutorService());
|
eventBus = new AsyncEventBus("HamsterBall", CoreAPI.getInstance().getExecutorService());
|
||||||
eventBus.register(BallCommonListener.INSTANCE);
|
eventBus.register(BallCommonListener.INSTANCE);
|
||||||
allServerInfo = new ConcurrentHashMap<>();
|
allServerInfo = new ConcurrentHashMap<>();
|
||||||
allPlayerInfo = new ConcurrentHashMap<>();
|
allPlayerInfo = new ConcurrentHashMap<>();
|
||||||
@@ -105,6 +105,7 @@ public abstract class BallAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void enable() throws SQLException, InterruptedException {
|
protected void enable() throws SQLException, InterruptedException {
|
||||||
|
CoreAPI.getInstance().getExecutorService().submit(() -> redisSub.subscribe(BallRedisListener.INSTANCE, BALL_CHANNEL));
|
||||||
try (Jedis jedis = CoreAPI.getInstance().getJedisPool().getResource()) {
|
try (Jedis jedis = CoreAPI.getInstance().getJedisPool().getResource()) {
|
||||||
String key = "HamsterBall:ServerInfo:" + localServerInfo.getId();
|
String key = "HamsterBall:ServerInfo:" + localServerInfo.getId();
|
||||||
if (jedis.exists(key)) {
|
if (jedis.exists(key)) {
|
||||||
@@ -179,7 +180,6 @@ public abstract class BallAPI {
|
|||||||
}
|
}
|
||||||
getLogger().info("从数据库中加载了 " + allServerInfo.size() + " 条服务器信息");
|
getLogger().info("从数据库中加载了 " + allServerInfo.size() + " 条服务器信息");
|
||||||
getLogger().info("从数据库中加载了 " + allPlayerInfo.size() + " 条玩家信息");
|
getLogger().info("从数据库中加载了 " + allPlayerInfo.size() + " 条玩家信息");
|
||||||
subscribeIgnorePrefix(BALL_CHANNEL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void disable() throws SQLException, InterruptedException {
|
protected void disable() throws SQLException, InterruptedException {
|
||||||
@@ -506,26 +506,29 @@ public abstract class BallAPI {
|
|||||||
* <p>
|
* <p>
|
||||||
* 会自动加上 config 中设置的频道前缀
|
* 会自动加上 config 中设置的频道前缀
|
||||||
*
|
*
|
||||||
* @param channel 频道名称
|
* @param channels 频道名称
|
||||||
*/
|
*/
|
||||||
public void subscribe(@NotNull String... channel) {
|
public void subscribe(@NotNull String... channels) {
|
||||||
for (int i = 0; i < channel.length; i++) {
|
for (int i = 0; i < channels.length; i++) {
|
||||||
channel[i] = ballConfig.getChannelPrefix() + channel[i];
|
channels[i] = ballConfig.getChannelPrefix() + channels[i];
|
||||||
}
|
}
|
||||||
CoreAPI.getInstance().getExecutorService().submit(
|
subscribeRaw(channels);
|
||||||
() -> redisSub.subscribe(BallRedisListener.INSTANCE, channel)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 忽略频道前缀配置,订阅 redis 消息频道
|
* 忽略频道前缀配置,订阅 redis 消息频道
|
||||||
*
|
*
|
||||||
* @param channel 频道名称
|
* @param channels 频道名称
|
||||||
*/
|
*/
|
||||||
public void subscribeIgnorePrefix(@NotNull String... channel) {
|
public void subscribeRaw(@NotNull String... channels) {
|
||||||
CoreAPI.getInstance().getExecutorService().submit(
|
BallRedisListener.INSTANCE.subscribe(channels);
|
||||||
() -> redisSub.subscribe(BallRedisListener.INSTANCE, channel)
|
// CoreAPI.getInstance().getExecutorService().submit(() -> {
|
||||||
);
|
// try {
|
||||||
|
// redisSub.subscribe(BallRedisListener.INSTANCE, channels);
|
||||||
|
// } catch (Exception | Error e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -534,9 +537,10 @@ public abstract class BallAPI {
|
|||||||
* @param patterns 频道名称正则表达式
|
* @param patterns 频道名称正则表达式
|
||||||
*/
|
*/
|
||||||
public void subscribePatterns(@NotNull String patterns) {
|
public void subscribePatterns(@NotNull String patterns) {
|
||||||
CoreAPI.getInstance().getExecutorService().submit(
|
BallRedisListener.INSTANCE.psubscribe(patterns);
|
||||||
() -> redisSub.psubscribe(BallRedisListener.INSTANCE, patterns)
|
// CoreAPI.getInstance().getExecutorService().submit(
|
||||||
);
|
// () -> redisSub.psubscribe(BallRedisListener.INSTANCE, patterns)
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -544,22 +548,22 @@ public abstract class BallAPI {
|
|||||||
* <p>
|
* <p>
|
||||||
* 会自动加上 config 中设置的频道前缀
|
* 会自动加上 config 中设置的频道前缀
|
||||||
*
|
*
|
||||||
* @param channel 频道名称
|
* @param channels 频道名称
|
||||||
*/
|
*/
|
||||||
public void unsubscribe(@NotNull String... channel) {
|
public void unsubscribe(@NotNull String... channels) {
|
||||||
for (int i = 0; i < channel.length; i++) {
|
for (int i = 0; i < channels.length; i++) {
|
||||||
channel[i] = ballConfig.getChannelPrefix() + channel[i];
|
channels[i] = ballConfig.getChannelPrefix() + channels[i];
|
||||||
}
|
}
|
||||||
BallRedisListener.INSTANCE.unsubscribe(channel);
|
unsubscribeRaw(channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 忽略频道前缀配置,取消订阅 redis 消息频道
|
* 忽略频道前缀配置,取消订阅 redis 消息频道
|
||||||
*
|
*
|
||||||
* @param channel 频道名称
|
* @param channels 频道名称
|
||||||
*/
|
*/
|
||||||
public void unsubscribeIgnorePrefix(@NotNull String... channel) {
|
public void unsubscribeRaw(@NotNull String... channels) {
|
||||||
BallRedisListener.INSTANCE.unsubscribe(channel);
|
BallRedisListener.INSTANCE.unsubscribe(channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -43,7 +43,7 @@ public class BallServerInfo {
|
|||||||
*/
|
*/
|
||||||
private int port;
|
private int port;
|
||||||
|
|
||||||
public BallServerInfo(@NotNull ConfigSection config, BallServerType type) {
|
public BallServerInfo(@NotNull ConfigSection config, @NotNull BallServerType type) {
|
||||||
Map<String, String> env = System.getenv();
|
Map<String, String> env = System.getenv();
|
||||||
id = env.getOrDefault("BALL_SERVER_ID", config.getString("id"));
|
id = env.getOrDefault("BALL_SERVER_ID", config.getString("id"));
|
||||||
name = env.getOrDefault("BALL_SERVER_NAME", config.getString("name"));
|
name = env.getOrDefault("BALL_SERVER_NAME", config.getString("name"));
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
package cn.hamster3.mc.plugin.ball.common.event.server;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务器上线
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class BallServerEvent extends BallServerInfo {
|
||||||
|
public BallServerEvent(BallServerInfo info) {
|
||||||
|
super(info.getId(), info.getName(), info.getType(), info.getHost(), info.getPort());
|
||||||
|
}
|
||||||
|
}
|
@@ -3,19 +3,16 @@ package cn.hamster3.mc.plugin.ball.common.event.server;
|
|||||||
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务器离线
|
* 服务器离线
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ServerOfflineEvent {
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@NotNull
|
public class ServerOfflineEvent extends BallServerEvent {
|
||||||
private final BallServerInfo serverInfo;
|
public ServerOfflineEvent(BallServerInfo info) {
|
||||||
|
super(info);
|
||||||
@NotNull
|
|
||||||
public String getServerID() {
|
|
||||||
return serverInfo.getId();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,15 +3,16 @@ package cn.hamster3.mc.plugin.ball.common.event.server;
|
|||||||
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务器上线
|
* 服务器上线
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ServerOnlineEvent {
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@NotNull
|
public class ServerOnlineEvent extends BallServerEvent {
|
||||||
private final BallServerInfo serverInfo;
|
public ServerOnlineEvent(BallServerInfo info) {
|
||||||
|
super(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -128,12 +128,11 @@ public class BallCommonListener {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onServerOnline(ServerOnlineEvent event) {
|
public void onServerOnline(ServerOnlineEvent event) {
|
||||||
BallServerInfo info = event.getServerInfo();
|
BallAPI.getInstance().getAllServerInfo().put(event.getId(), event);
|
||||||
BallAPI.getInstance().getAllServerInfo().put(info.getId(), info);
|
switch (event.getType()) {
|
||||||
switch (info.getType()) {
|
|
||||||
case GAME: {
|
case GAME: {
|
||||||
BallAPI.getInstance().getAllPlayerInfo().forEach((uuid, playerInfo) -> {
|
BallAPI.getInstance().getAllPlayerInfo().forEach((uuid, playerInfo) -> {
|
||||||
if (playerInfo.getGameServer().equals(info.getId())) {
|
if (playerInfo.getGameServer().equals(event.getId())) {
|
||||||
playerInfo.setOnline(false);
|
playerInfo.setOnline(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -141,7 +140,7 @@ public class BallCommonListener {
|
|||||||
}
|
}
|
||||||
case PROXY: {
|
case PROXY: {
|
||||||
BallAPI.getInstance().getAllPlayerInfo().forEach((uuid, playerInfo) -> {
|
BallAPI.getInstance().getAllPlayerInfo().forEach((uuid, playerInfo) -> {
|
||||||
if (playerInfo.getProxyServer().equals(info.getId())) {
|
if (playerInfo.getProxyServer().equals(event.getId())) {
|
||||||
playerInfo.setOnline(false);
|
playerInfo.setOnline(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -152,7 +151,7 @@ public class BallCommonListener {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onServerOffline(ServerOfflineEvent event) {
|
public void onServerOffline(ServerOfflineEvent event) {
|
||||||
String serverID = event.getServerID();
|
String serverID = event.getId();
|
||||||
BallServerInfo info = BallAPI.getInstance().getAllServerInfo().remove(serverID);
|
BallServerInfo info = BallAPI.getInstance().getAllServerInfo().remove(serverID);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
return;
|
return;
|
||||||
|
@@ -15,19 +15,26 @@ public class BallRedisListener extends JedisPubSub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(String channel, String message) {
|
public void onMessage(String channel, String message) {
|
||||||
if (channel.startsWith(BallAPI.getInstance().getBallConfig().getChannelPrefix())) {
|
CoreAPI.getInstance().getExecutorService().submit(() -> {
|
||||||
channel = channel.substring(BallAPI.getInstance().getBallConfig().getChannelPrefix().length());
|
try {
|
||||||
}
|
String finalChannel = channel;
|
||||||
BallMessage ballMessage = CoreAPI.getInstance().getGson().fromJson(message, BallMessage.class);
|
if (finalChannel.startsWith(BallAPI.getInstance().getBallConfig().getChannelPrefix())) {
|
||||||
BallAPI ballAPI = BallAPI.getInstance();
|
finalChannel = finalChannel.substring(BallAPI.getInstance().getBallConfig().getChannelPrefix().length());
|
||||||
EventBus eventBus = ballAPI.getEventBus();
|
}
|
||||||
if (ballMessage.getReceiverType() != null && ballMessage.getReceiverType() != ballAPI.getLocalServerInfo().getType()) {
|
BallMessage ballMessage = CoreAPI.getInstance().getGson().fromJson(message, BallMessage.class);
|
||||||
return;
|
BallAPI ballAPI = BallAPI.getInstance();
|
||||||
}
|
EventBus eventBus = ballAPI.getEventBus();
|
||||||
if (ballMessage.getReceiverID() != null && !ballAPI.isLocalServer(ballMessage.getReceiverID())) {
|
if (ballMessage.getReceiverType() != null && ballMessage.getReceiverType() != ballAPI.getLocalServerInfo().getType()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eventBus.post(new MessageReceivedEvent(channel, ballMessage));
|
if (ballMessage.getReceiverID() != null && !ballAPI.isLocalServer(ballMessage.getReceiverID())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eventBus.post(new MessageReceivedEvent(finalChannel, ballMessage));
|
||||||
|
} catch (Exception | Error e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -8,7 +8,9 @@ import cn.hamster3.mc.plugin.ball.velocity.api.CoreVelocityAPI;
|
|||||||
import cn.hamster3.mc.plugin.ball.velocity.listener.BallVelocityListener;
|
import cn.hamster3.mc.plugin.ball.velocity.listener.BallVelocityListener;
|
||||||
import cn.hamster3.mc.plugin.ball.velocity.listener.BallVelocityMainListener;
|
import cn.hamster3.mc.plugin.ball.velocity.listener.BallVelocityMainListener;
|
||||||
import cn.hamster3.mc.plugin.ball.velocity.listener.UpdatePlayerInfoListener;
|
import cn.hamster3.mc.plugin.ball.velocity.listener.UpdatePlayerInfoListener;
|
||||||
|
import cn.hamster3.mc.plugin.ball.velocity.listener.VelocityServerListener;
|
||||||
import cn.hamster3.mc.plugin.ball.velocity.util.BallVelocityUtils;
|
import cn.hamster3.mc.plugin.ball.velocity.util.BallVelocityUtils;
|
||||||
|
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.velocitypowered.api.event.PostOrder;
|
import com.velocitypowered.api.event.PostOrder;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
@@ -48,6 +50,8 @@ public class HamsterBallPlugin {
|
|||||||
private final ProxyServer proxyServer;
|
private final ProxyServer proxyServer;
|
||||||
@Getter
|
@Getter
|
||||||
private final File dataFolder;
|
private final File dataFolder;
|
||||||
|
@Getter
|
||||||
|
private YamlConfig config;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HamsterBallPlugin(Logger slf4jLogger, ProxyServer proxyServer, @DataDirectory Path dataPath) {
|
public HamsterBallPlugin(Logger slf4jLogger, ProxyServer proxyServer, @DataDirectory Path dataPath) {
|
||||||
@@ -71,7 +75,8 @@ public class HamsterBallPlugin {
|
|||||||
StandardCopyOption.REPLACE_EXISTING
|
StandardCopyOption.REPLACE_EXISTING
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
CoreVelocityAPI.init(configFile);
|
config = YamlConfig.load(configFile);
|
||||||
|
CoreVelocityAPI.init(config);
|
||||||
logger.info("已初始化 BallAPI");
|
logger.info("已初始化 BallAPI");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
slf4jLogger.error("BallAPI 初始化失败", e);
|
slf4jLogger.error("BallAPI 初始化失败", e);
|
||||||
@@ -95,16 +100,21 @@ public class HamsterBallPlugin {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BallAPI.getInstance().getEventBus().register(BallVelocityListener.INSTANCE);
|
BallAPI.getInstance().getEventBus().register(BallVelocityListener.INSTANCE);
|
||||||
logger.info("已注册监听器 BallBungeeListener");
|
logger.info("已注册监听器 BallVelocityListener");
|
||||||
proxyServer.getEventManager().register(this, BallVelocityMainListener.INSTANCE);
|
proxyServer.getEventManager().register(this, BallVelocityMainListener.INSTANCE);
|
||||||
logger.info("已注册监听器 BallBungeeMainListener");
|
logger.info("已注册监听器 BallVelocityMainListener");
|
||||||
proxyServer.getEventManager().register(this, UpdatePlayerInfoListener.INSTANCE);
|
proxyServer.getEventManager().register(this, UpdatePlayerInfoListener.INSTANCE);
|
||||||
logger.info("已注册监听器 UpdatePlayerInfoListener");
|
logger.info("已注册监听器 UpdatePlayerInfoListener");
|
||||||
|
if (config.getBoolean("auto-register-game-server", false)) {
|
||||||
|
BallAPI.getInstance().getEventBus().register(VelocityServerListener.INSTANCE);
|
||||||
|
logger.info("已注册监听器 VelocityServerListener");
|
||||||
|
VelocityServerListener.INSTANCE.onEnable();
|
||||||
|
}
|
||||||
|
|
||||||
if (BallAPI.getInstance().getBallConfig().isGameServerUpdatePlayerInfo()) {
|
if (BallAPI.getInstance().getBallConfig().isGameServerUpdatePlayerInfo()) {
|
||||||
BallAPI.getInstance().subscribePatterns("*" + BallAPI.PLAYER_INFO_CHANNEL);
|
BallAPI.getInstance().subscribePatterns("*" + BallAPI.PLAYER_INFO_CHANNEL);
|
||||||
} else {
|
} else {
|
||||||
BallAPI.getInstance().subscribeIgnorePrefix(BallAPI.PLAYER_INFO_CHANNEL);
|
BallAPI.getInstance().subscribeRaw(BallAPI.PLAYER_INFO_CHANNEL);
|
||||||
}
|
}
|
||||||
BallAPI.getInstance().sendRawBallMessage(
|
BallAPI.getInstance().sendRawBallMessage(
|
||||||
BallAPI.BALL_CHANNEL, BallActions.ServerOnline.name(),
|
BallAPI.BALL_CHANNEL, BallActions.ServerOnline.name(),
|
||||||
|
@@ -8,8 +8,6 @@ import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
|
|||||||
import com.velocitypowered.api.proxy.config.ProxyConfig;
|
import com.velocitypowered.api.proxy.config.ProxyConfig;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -24,11 +22,10 @@ public final class CoreVelocityAPI extends BallAPI {
|
|||||||
return (CoreVelocityAPI) instance;
|
return (CoreVelocityAPI) instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(@NotNull File configFile) throws IOException {
|
public static void init(@NotNull YamlConfig config) {
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
YamlConfig config = YamlConfig.load(configFile);
|
|
||||||
instance = new CoreVelocityAPI(config);
|
instance = new CoreVelocityAPI(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,65 @@
|
|||||||
|
package cn.hamster3.mc.plugin.ball.velocity.listener;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.entity.BallServerType;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOfflineEvent;
|
||||||
|
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
||||||
|
import cn.hamster3.mc.plugin.ball.velocity.HamsterBallPlugin;
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
public class VelocityServerListener {
|
||||||
|
public static final VelocityServerListener INSTANCE = new VelocityServerListener();
|
||||||
|
|
||||||
|
private VelocityServerListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEnable() {
|
||||||
|
for (BallServerInfo info : BallAPI.getInstance().getAllServerInfo().values()) {
|
||||||
|
if (info.getType() != BallServerType.GAME) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ProxyServer server = HamsterBallPlugin.getInstance().getProxyServer();
|
||||||
|
server.getServer(info.getId())
|
||||||
|
.map(RegisteredServer::getServerInfo)
|
||||||
|
.ifPresent(server::unregisterServer);
|
||||||
|
ServerInfo serverInfo = new ServerInfo(info.getId(), new InetSocketAddress(info.getHost(), info.getPort()));
|
||||||
|
server.registerServer(serverInfo);
|
||||||
|
BallAPI.getInstance().getLogger().info("已添加服务器入口: " + info.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onServerOnline(ServerOnlineEvent event) {
|
||||||
|
if (event.getType() != BallServerType.GAME) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProxyServer server = HamsterBallPlugin.getInstance().getProxyServer();
|
||||||
|
server.getServer(event.getId())
|
||||||
|
.map(RegisteredServer::getServerInfo)
|
||||||
|
.ifPresent(server::unregisterServer);
|
||||||
|
ServerInfo serverInfo = new ServerInfo(event.getId(), new InetSocketAddress(event.getHost(), event.getPort()));
|
||||||
|
server.registerServer(serverInfo);
|
||||||
|
BallAPI.getInstance().getLogger().info("已添加服务器入口: " + event.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onServerOffline(ServerOfflineEvent event) {
|
||||||
|
if (event.getType() != BallServerType.GAME) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProxyServer server = HamsterBallPlugin.getInstance().getProxyServer();
|
||||||
|
ServerInfo serverInfo = server.getServer(event.getId())
|
||||||
|
.map(RegisteredServer::getServerInfo)
|
||||||
|
.orElse(null);
|
||||||
|
if (serverInfo != null) {
|
||||||
|
server.unregisterServer(serverInfo);
|
||||||
|
BallAPI.getInstance().getLogger().info("已移除服务器入口: " + event.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -8,12 +8,14 @@ channel-prefix: ""
|
|||||||
|
|
||||||
# 是否在子服端更新玩家信息
|
# 是否在子服端更新玩家信息
|
||||||
# 默认情况下,BC 统一管理玩家信息,包括记录 UUID 和玩家名称
|
# 默认情况下,BC 统一管理玩家信息,包括记录 UUID 和玩家名称
|
||||||
# 如果一个群组服同时拥有多个 BC 入口
|
# 如果一个群组服同时拥有多个 BC 入口,且每个 BC 入口为不同的玩家名称分配不同的 UUID
|
||||||
# 且每个 BC 入口为不同的玩家名称分配不同的 UUID
|
|
||||||
# (例如正版、盗版双入口,或网易多入口接同一个子服)
|
# (例如正版、盗版双入口,或网易多入口接同一个子服)
|
||||||
# 则可以启用该功能以防止 UUID 紊乱的问题
|
# 则可以启用该功能以防止同一个名称占用多个 UUID 的问题
|
||||||
game-server-update-player-info: false
|
game-server-update-player-info: false
|
||||||
|
|
||||||
|
# 启用后,子服启动时会自动注册该子服的入口配置,关闭时也会自动移除该子服的入口配置
|
||||||
|
auto-register-game-server: false
|
||||||
|
|
||||||
# 本服务器信息
|
# 本服务器信息
|
||||||
server-info:
|
server-info:
|
||||||
# 服务器唯一识别码,最长 32 字符
|
# 服务器唯一识别码,最长 32 字符
|
||||||
@@ -34,21 +36,20 @@ server-info:
|
|||||||
# 这个选项就会很有用
|
# 这个选项就会很有用
|
||||||
#datasource:
|
#datasource:
|
||||||
# # 数据库链接驱动地址
|
# # 数据库链接驱动地址
|
||||||
# driver: "com.mysql.jdbc.Driver"
|
# driver: "com.mysql.cj.jdbc.Driver"
|
||||||
# # 数据库链接填写格式:
|
# # MySQL数据库链接填写格式:
|
||||||
# # jdbc:mysql://{数据库地址}:{数据库端口}/{使用的库名}?参数
|
# # jdbc:mysql://{数据库地址}:{数据库端口}/{使用的库名}?参数
|
||||||
# # 除非你知道自己在做什么,否则不建议随意更改参数
|
# url: "jdbc:mysql://localhost:3306/Test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true"
|
||||||
# url: "jdbc:mysql://localhost:3306/Test1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true"
|
|
||||||
# # 用户名
|
# # 用户名
|
||||||
# username: "Test"
|
# username: "root"
|
||||||
# # 密码
|
# # 密码
|
||||||
# password: "Test123.."
|
# password: "Root123.."
|
||||||
# # 最小闲置链接数
|
# # 最小闲置链接数
|
||||||
# # 推荐值:1~3
|
# # 推荐值:1~3
|
||||||
# minimum-idle: 0
|
# minimum-idle: 0
|
||||||
# # 最大链接数
|
# # 最大链接数
|
||||||
# # 推荐值:不低于3
|
# # 推荐值:不低于5
|
||||||
# maximum-pool-size: 3
|
# maximum-pool-size: 5
|
||||||
# # 保持连接池可用的间隔
|
# # 保持连接池可用的间隔
|
||||||
# # 除非你的服务器数据库连接经常断开,否则不建议启用该选项
|
# # 除非你的服务器数据库连接经常断开,否则不建议启用该选项
|
||||||
# # 单位:毫秒
|
# # 单位:毫秒
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
version: ${version}
|
VERSION: ${version}
|
||||||
CHECK_TYPE: GITEA_RELEASES
|
CHECK_TYPE: GITEA_RELEASES
|
||||||
GIT_BASE_URL: https://git.airgame.net
|
GIT_BASE_URL: https://git.airgame.net
|
||||||
GIT_REPO: MiniDay/hamster-ball
|
GIT_REPO: MiniDay/hamster-ball
|
||||||
GIT_TOKEN: a44a69a4d1b8601bf6091403247759cd28764d5e
|
|
||||||
DOWNLOAD_URL: https://jenkins.airgame.net/job/opensource/job/hamster-ball/
|
DOWNLOAD_URL: https://jenkins.airgame.net/job/opensource/job/hamster-ball/
|
||||||
|
@@ -5,7 +5,8 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "cn.hamster3.mc.plugin"
|
group = "cn.hamster3.mc.plugin"
|
||||||
version = "1.6.1"
|
version = "1.6.4"
|
||||||
|
description = "基于 Redis 的 Minecraft 服务端通用消息中间件"
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
apply {
|
apply {
|
||||||
@@ -16,6 +17,7 @@ subprojects {
|
|||||||
|
|
||||||
group = rootProject.group
|
group = rootProject.group
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
description = rootProject.description
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://maven.airgame.net/maven-public/")
|
maven("https://maven.airgame.net/maven-public/")
|
||||||
@@ -43,11 +45,6 @@ subprojects {
|
|||||||
from(rootProject.file("LICENSE"))
|
from(rootProject.file("LICENSE"))
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
}
|
}
|
||||||
processResources {
|
|
||||||
filesMatching("update.yml") {
|
|
||||||
expand(rootProject.properties)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
build {
|
build {
|
||||||
dependsOn(shadowJar)
|
dependsOn(shadowJar)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user