feat: 适配新版API更新

This commit is contained in:
2023-06-16 21:55:23 +08:00
parent 1fec3fb429
commit 4a76b774d1
64 changed files with 30 additions and 37 deletions

View File

@@ -0,0 +1,41 @@
setArchivesBaseName("HamsterBall-BungeeCord")
evaluationDependsOn(':ball-common')
dependencies {
apiShade project(":ball-common") transitive false
//noinspection VulnerableLibrariesLocal
compileOnly 'net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT' exclude group: 'io.netty'
compileOnly "cn.hamster3.mc.plugin:core-bungeecord:${hamster_core_version}"
}
processResources {
inputs.property "version", project.version
filesMatching("bungee.yml") {
expand "version": project.version
}
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
}
tasks.compileJava.dependsOn(":ball-common:build")
tasks.register("shadowJar", Jar) {
dependsOn("jar")
from([
tasks.jar.outputs.files.collect {
it.isDirectory() ? it : zipTree(it)
},
configurations.shade.collect {
it.isDirectory() ? it : zipTree(it)
},
configurations.apiShade.collect {
it.isDirectory() ? it : zipTree(it)
},
configurations.implementationShade.collect {
it.isDirectory() ? it : zipTree(it)
}
])
destinationDir(rootProject.buildDir)
}
tasks.build.dependsOn(shadowJar)

View File

@@ -0,0 +1,69 @@
package cn.hamster3.mc.plugin.core.bungee;
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.event.server.ServerOnlineEvent;
import cn.hamster3.mc.plugin.core.bungee.api.BallBungeeCordAPI;
import cn.hamster3.mc.plugin.core.bungee.listener.BallBungeeCordListener;
import cn.hamster3.mc.plugin.core.bungee.util.BallBungeeCordUtils;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import java.util.logging.Logger;
public class HamsterBallPlugin extends Plugin {
private static HamsterBallPlugin instance;
public static HamsterBallPlugin getInstance() {
return instance;
}
@Override
public void onLoad() {
instance = this;
Logger logger = getLogger();
BallBungeeCordAPI.init();
logger.info("BallBungeeCordAPI 已初始化.");
try {
BallBungeeCordAPI.getInstance().enable();
logger.info("BallBungeeCordAPI 已启动.");
} catch (Exception e) {
e.printStackTrace();
ProxyServer.getInstance().stop();
}
}
@Override
public void onEnable() {
Logger logger = getLogger();
if (!BallAPI.getInstance().isConnected()) {
ProxyServer.getInstance().stop("由于 HamsterBall 未能成功连接, 服务器将立即关闭.");
return;
}
ProxyServer.getInstance().getPluginManager().registerListener(this, BallBungeeCordListener.INSTANCE);
logger.info("已注册 BallBungeeCordListener.");
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
ServerOnlineEvent.ACTION,
new ServerOnlineEvent(BallAPI.getInstance().getLocalServerInfo())
);
logger.info("HamsterBall 已启动.");
BallAPI.getInstance().getAllPlayerInfo().values()
.stream()
.filter(BallPlayerInfo::isOnline)
.filter(o -> BallAPI.getInstance().isLocalServer(o.getProxyServer()))
.forEach(playerInfo -> {
playerInfo.setOnline(false);
BallBungeeCordUtils.uploadPlayerInfo(playerInfo);
});
}
@Override
public void onDisable() {
try {
BallBungeeCordAPI.getInstance().disable();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,81 @@
package cn.hamster3.mc.plugin.core.bungee.api;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.config.BallConfig;
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.listener.BallDebugListener;
import cn.hamster3.mc.plugin.core.bungee.HamsterBallPlugin;
import cn.hamster3.mc.plugin.core.bungee.listener.BallBungeeCordListener;
import cn.hamster3.mc.plugin.core.bungee.util.CoreBungeeCordUtils;
import net.md_5.bungee.config.Configuration;
import org.jetbrains.annotations.NotNull;
import java.sql.SQLException;
import java.util.Map;
import java.util.logging.Logger;
public class BallBungeeCordAPI extends BallAPI {
public BallBungeeCordAPI(@NotNull BallConfig config) {
super(config);
}
public static BallBungeeCordAPI getInstance() {
return (BallBungeeCordAPI) instance;
}
public static void init() {
if (instance != null) {
return;
}
HamsterBallPlugin plugin = HamsterBallPlugin.getInstance();
Configuration pluginConfig = CoreBungeeCordUtils.getPluginConfig(plugin);
Map<String, String> env = System.getenv();
String serverInfoID = env.getOrDefault("BALL_SERVER_INFO_ID",
pluginConfig.getString("server-info.id"));
String serverInfoName = env.getOrDefault("BALL_SERVER_INFO_NAME",
pluginConfig.getString("server-info.name"));
String serverInfoHost = env.getOrDefault("SERVER_IP",
pluginConfig.getString("server-info.host", "0.0.0.0"));
int serverInfoPort = Integer.parseInt(env.getOrDefault("SERVER_PORT",
String.valueOf(pluginConfig.getInt("server-info.port", 25577))));
BallServerInfo serverInfo = new BallServerInfo(
serverInfoID,
serverInfoName,
BallServerType.PROXY,
serverInfoHost,
serverInfoPort
);
String serverHost = env.getOrDefault("BALL_SERVER_HOST",
pluginConfig.getString("ball-server.host", "ball.hamster3.cn"));
int serverPort = Integer.parseInt(env.getOrDefault("BALL_SERVER_PORT",
String.valueOf(pluginConfig.getInt("ball-server.port", 58888))));
int eventLoopThread = Integer.parseInt(env.getOrDefault("BALL_EVENT_LOOP_THREAD",
String.valueOf(pluginConfig.getInt("ball-server.event-loop-thread", 2))));
BallConfig config = new BallConfig(serverInfo, serverHost, serverPort, eventLoopThread);
instance = new BallBungeeCordAPI(config);
instance.addListener(BallBungeeCordListener.INSTANCE);
if (pluginConfig.getBoolean("debug", false)) {
instance.addListener(BallDebugListener.INSTANCE);
}
}
@Override
public void enable() throws SQLException, InterruptedException {
super.enable();
}
@Override
public void disable() throws SQLException, InterruptedException {
super.disable();
}
@Override
public @NotNull Logger getLogger() {
return HamsterBallPlugin.getInstance().getLogger();
}
}

View File

@@ -0,0 +1,211 @@
package cn.hamster3.mc.plugin.core.bungee.listener;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.data.BallMessageInfo;
import cn.hamster3.mc.plugin.ball.common.entity.BallPlayerInfo;
import cn.hamster3.mc.plugin.ball.common.entity.BallServerType;
import cn.hamster3.mc.plugin.ball.common.event.operate.*;
import cn.hamster3.mc.plugin.ball.common.event.player.*;
import cn.hamster3.mc.plugin.ball.common.listener.BallListener;
import cn.hamster3.mc.plugin.core.bungee.HamsterBallPlugin;
import cn.hamster3.mc.plugin.core.bungee.util.BallBungeeCordUtils;
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import cn.hamster3.mc.plugin.core.common.util.CoreUtils;
import cn.hamster3.mc.plugin.core.lib.net.kyori.adventure.audience.Audience;
import cn.hamster3.mc.plugin.core.lib.net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.*;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public final class BallBungeeCordListener implements Listener, BallListener {
public static final BallBungeeCordListener INSTANCE = new BallBungeeCordListener();
private BallBungeeCordListener() {
}
@Override
public void onMessageReceived(@NotNull BallMessageInfo info) {
switch (info.getAction()) {
case DispatchConsoleCommandEvent.ACTION: {
DispatchConsoleCommandEvent event = CoreUtils.GSON.fromJson(info.getContent(), DispatchConsoleCommandEvent.class);
if (event.getType() != null && event.getType() != BallServerType.PROXY) {
return;
}
if (event.getServerID() != null && !BallAPI.getInstance().isLocalServer(event.getServerID())) {
return;
}
ProxyServer server = ProxyServer.getInstance();
server.getPluginManager().dispatchCommand(server.getConsole(), event.getCommand());
break;
}
case DispatchPlayerCommandEvent.ACTION: {
DispatchPlayerCommandEvent event = CoreUtils.GSON.fromJson(info.getContent(), DispatchPlayerCommandEvent.class);
if (event.getType() != null && event.getType() != BallServerType.GAME) {
return;
}
ProxyServer server = ProxyServer.getInstance();
if (event.getUuid() != null) {
ProxiedPlayer player = server.getPlayer(event.getUuid());
if (player == null) {
return;
}
server.getPluginManager().dispatchCommand(player, event.getCommand());
return;
}
for (ProxiedPlayer player : server.getPlayers()) {
server.getPluginManager().dispatchCommand(player, event.getCommand());
}
break;
}
case KickPlayerEvent.ACTION: {
KickPlayerEvent event = CoreUtils.GSON.fromJson(info.getContent(), KickPlayerEvent.class);
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(event.getUuid());
BaseComponent[] components = BungeeComponentSerializer.get().serialize(event.getReason());
player.disconnect(components);
break;
}
case SendMessageToPlayerEvent.ACTION: {
SendMessageToPlayerEvent event = CoreUtils.GSON.fromJson(info.getContent(), SendMessageToPlayerEvent.class);
for (UUID receiver : event.getReceivers()) {
Audience audience = CoreAPI.getInstance().getAudienceProvider().player(receiver);
event.getMessage().show(audience);
}
break;
}
case SendPlayerToLocationEvent.ACTION: {
SendPlayerToLocationEvent event = CoreUtils.GSON.fromJson(info.getContent(), SendPlayerToLocationEvent.class);
String serverID = event.getLocation().getServerID();
ServerInfo serverInfo = ProxyServer.getInstance().getServerInfo(serverID);
if (serverInfo == null) {
HamsterBallPlugin.getInstance().getLogger().warning("试图传送玩家时失败: 服务器 " + serverID + " 不在线!");
break;
}
for (UUID uuid : event.getSendPlayerUUID()) {
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
if (player == null) {
continue;
}
if (player.getServer().getInfo().getName().equals(serverID)) {
continue;
}
player.connect(serverInfo);
}
break;
}
case SendPlayerToPlayerEvent.ACTION: {
SendPlayerToPlayerEvent event = CoreUtils.GSON.fromJson(info.getContent(), SendPlayerToPlayerEvent.class);
UUID toPlayerUUID = event.getToPlayerUUID();
ProxiedPlayer toPlayer = ProxyServer.getInstance().getPlayer(toPlayerUUID);
if (toPlayer == null) {
HamsterBallPlugin.getInstance().getLogger().warning("试图传送玩家时失败: 目标玩家 " + toPlayerUUID + " 不在线!");
break;
}
ServerInfo toServer = toPlayer.getServer().getInfo();
for (UUID uuid : event.getSendPlayerUUID()) {
ProxiedPlayer sendPlayer = ProxyServer.getInstance().getPlayer(uuid);
if (sendPlayer.getServer().getInfo().getName().equals(toServer.getName())) {
continue;
}
sendPlayer.connect(toServer);
}
}
}
}
@Override
public void onServiceDead() {
ProxyServer.getInstance().stop("HamsterBall 重连失败.");
}
@EventHandler(priority = EventPriority.HIGH)
public void onPreLogin(PreLoginEvent event) {
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
BallPlayerPreLoginEvent.ACTION,
new BallPlayerPreLoginEvent(event.getConnection().getName())
);
}
@EventHandler(priority = EventPriority.HIGH)
public void onLogin(LoginEvent event) {
if (event.isCancelled()) {
return;
}
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
BallPlayerLoginEvent.ACTION,
new BallPlayerLoginEvent(new BallPlayerInfo(
event.getConnection().getUniqueId(),
event.getConnection().getName(),
"connecting",
BallAPI.getInstance().getLocalServerId(),
true
))
);
}
@EventHandler(priority = EventPriority.HIGH)
public void onPostLogin(PostLoginEvent event) {
ProxiedPlayer player = event.getPlayer();
BallPlayerInfo playerInfo = BallBungeeCordUtils.getPlayerInfo(player, true);
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
BallPlayerPostLoginEvent.ACTION,
new BallPlayerPostLoginEvent(playerInfo)
);
}
@EventHandler(priority = EventPriority.HIGH)
public void onServerConnect(ServerConnectEvent event) {
ProxiedPlayer player = event.getPlayer();
BallPlayerInfo playerInfo = BallBungeeCordUtils.getPlayerInfo(player, true);
playerInfo.setGameServer(event.getTarget().getName());
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
BallPlayerPreConnectServerEvent.ACTION,
new BallPlayerPreConnectServerEvent(playerInfo, playerInfo.getGameServer(), event.getTarget().getName())
);
BallBungeeCordUtils.uploadPlayerInfo(playerInfo);
}
@EventHandler(priority = EventPriority.HIGH)
public void onServerConnected(ServerConnectedEvent event) {
ProxiedPlayer player = event.getPlayer();
BallPlayerInfo playerInfo = BallBungeeCordUtils.getPlayerInfo(player, true);
playerInfo.setGameServer(event.getServer().getInfo().getName());
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
BallPlayerPostConnectServerEvent.ACTION,
new BallPlayerPostConnectServerEvent(playerInfo)
);
BallBungeeCordUtils.uploadPlayerInfo(playerInfo);
}
@EventHandler
public void onServerSwitch(ServerSwitchEvent event) {
}
@EventHandler(priority = EventPriority.HIGH)
public void onServerDisconnect(ServerDisconnectEvent event) {
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
ProxiedPlayer player = event.getPlayer();
BallPlayerInfo playerInfo = BallBungeeCordUtils.getPlayerInfo(player, false);
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
BallPlayerLogoutEvent.ACTION,
new BallPlayerLogoutEvent(playerInfo)
);
BallBungeeCordUtils.uploadPlayerInfo(playerInfo);
}
}

View File

@@ -0,0 +1,53 @@
package cn.hamster3.mc.plugin.core.bungee.util;
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.event.player.BallPlayerInfoUpdateEvent;
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import cn.hamster3.mc.plugin.core.common.util.CoreUtils;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public final class BallBungeeCordUtils {
private BallBungeeCordUtils() {
}
@NotNull
public static BallPlayerInfo getPlayerInfo(@NotNull ProxiedPlayer player, boolean online) {
Server server = player.getServer();
return new BallPlayerInfo(
player.getUniqueId(),
player.getName(),
server == null ? "connecting" : server.getInfo().getName(),
BallAPI.getInstance().getLocalServerId(),
online
);
}
public static void uploadPlayerInfo(@NotNull BallPlayerInfo playerInfo) {
CoreUtils.WORKER_EXECUTOR.execute(() -> {
try (Connection connection = CoreAPI.getInstance().getConnection()) {
PreparedStatement statement = connection.prepareStatement("REPLACE INTO `hamster_ball_player_info` VALUES(?, ?, ?, ?, ?);");
statement.setString(1, playerInfo.getUuid().toString());
statement.setString(2, playerInfo.getName());
statement.setString(3, playerInfo.getGameServer());
statement.setString(4, playerInfo.getProxyServer());
statement.setBoolean(5, playerInfo.isOnline());
statement.executeUpdate();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
BallPlayerInfoUpdateEvent.ACTION,
new BallPlayerInfoUpdateEvent(playerInfo)
);
});
}
}

View File

@@ -0,0 +1,9 @@
name: HamsterBall
main: cn.hamster3.mc.plugin.core.bungee.HamsterBallPlugin
version: ${version}
author: MiniDay
description: 仓鼠球:一个基于 Netty 的 Minecraft 服务端通用消息中间件原HamsterService
depend:
- HamsterCore

View File

@@ -0,0 +1,15 @@
# 是否允许在控制台输出调试信息
debug: false
ball-server:
host: "ball.hamster3.cn"
port: 58888
event-loop-thread: 5
server-info:
# 服务器唯一识别码,最长 32 字符
id: "BungeeCord"
# 服务端名称,用于展示给玩家看
name: "代理端"
host: 0.0.0.0
port: 25577