feat: 使用 redission 作为消息中间件

This commit is contained in:
2023-08-20 22:17:32 +08:00
parent fa7f07657f
commit b8d35f3fce
39 changed files with 435 additions and 1380 deletions

View File

@@ -30,9 +30,9 @@ public class HamsterBallPlugin extends JavaPlugin {
public void onLoad() {
instance = this;
Logger logger = getLogger();
BallBukkitAPI.init();
logger.info("BallBukkitAPI 已初始化.");
try {
BallBukkitAPI.init();
logger.info("BallBukkitAPI 已初始化.");
BallBukkitAPI.getInstance().enable();
logger.info("BallBukkitAPI 已启动.");
} catch (Exception e) {
@@ -43,7 +43,7 @@ public class HamsterBallPlugin extends JavaPlugin {
@Override
public void onEnable() {
Logger logger = getLogger();
if (!BallAPI.getInstance().isConnected()) {
if (!BallAPI.getInstance().isEnabled()) {
sync(() -> {
logger.info("由于 HamsterBall 未能成功连接, 服务器将立即关闭.");
Bukkit.shutdown();

View File

@@ -1,10 +1,10 @@
package cn.hamster3.mc.plugin.ball.bukkit.api;
import cn.hamster3.mc.plugin.ball.bukkit.HamsterBallPlugin;
import cn.hamster3.mc.plugin.ball.bukkit.listener.BallBukkitListener;
import cn.hamster3.mc.plugin.ball.bukkit.util.BallBukkitUtils;
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.codec.BallMessageInfoCodec;
import cn.hamster3.mc.plugin.ball.common.data.BallMessageInfo;
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;
@@ -12,63 +12,74 @@ import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.redisson.Redisson;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.sql.SQLException;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Logger;
public class BallBukkitAPI extends BallAPI {
private DataSource datasource;
@Nullable
private final DataSource datasource;
@NotNull
private final RedissonClient redissonClient;
public BallBukkitAPI(@NotNull BallConfig config) {
super(config);
public BallBukkitAPI(@NotNull BallServerInfo localServerInfo, @Nullable DataSource datasource, @NotNull RedissonClient redissonClient) {
super(localServerInfo);
this.datasource = datasource;
this.redissonClient = redissonClient;
}
public static BallBukkitAPI getInstance() {
return (BallBukkitAPI) instance;
}
public static void init() {
public static void init() throws IOException {
if (instance != null) {
return;
}
HamsterBallPlugin plugin = HamsterBallPlugin.getInstance();
plugin.saveDefaultConfig();
plugin.reloadConfig();
FileConfiguration pluginConfig = plugin.getConfig();
FileConfiguration config = plugin.getConfig();
Map<String, String> env = System.getenv();
String serverInfoID = env.getOrDefault("BALL_LOCAL_SERVER_INFO_ID",
pluginConfig.getString("server-info.id"));
String serverInfoName = env.getOrDefault("BALL_LOCAL_SERVER_INFO_NAME",
pluginConfig.getString("server-info.name"));
String serverInfoHost = env.getOrDefault("BALL_LOCAL_SERVER_IP",
pluginConfig.getString("server-info.host", Bukkit.getIp()));
int serverInfoPort = Integer.parseInt(env.getOrDefault("BALL_LOCAL_SERVER_PORT",
String.valueOf(pluginConfig.getInt("server-info.port", Bukkit.getPort()))));
BallServerInfo serverInfo = new BallServerInfo(
serverInfoID,
serverInfoName,
env.getOrDefault("BALL_LOCAL_SERVER_INFO_ID", config.getString("server-info.id")),
env.getOrDefault("BALL_LOCAL_SERVER_INFO_NAME", config.getString("server-info.name")),
BallServerType.GAME,
serverInfoHost.isEmpty() ? "127.0.0.1" : serverInfoHost,
serverInfoPort
env.getOrDefault("BALL_LOCAL_SERVER_IP", config.getString("server-info.host", Bukkit.getIp())),
Integer.parseInt(
env.getOrDefault("BALL_LOCAL_SERVER_PORT", String.valueOf(config.getInt("server-info.port", Bukkit.getPort())))
)
);
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);
DataSource datasource = BallBukkitUtils.getDataSource(config.getConfigurationSection("datasource"));
File redissionConfig = new File(plugin.getDataFolder(), "redission.yml");
if (!redissionConfig.exists()) {
Files.copy(
Objects.requireNonNull(plugin.getResource("redission.yml")),
redissionConfig.toPath(),
StandardCopyOption.REPLACE_EXISTING
);
}
RedissonClient redissonClient = Redisson.create(Config.fromYAML(redissionConfig));
BallBukkitAPI apiInstance = new BallBukkitAPI(serverInfo, datasource, redissonClient);
BallBukkitAPI apiInstance = new BallBukkitAPI(config);
apiInstance.datasource = BallBukkitUtils.getDataSource(pluginConfig.getConfigurationSection("datasource"));
apiInstance.addListener(BallBukkitListener.INSTANCE);
if (pluginConfig.getBoolean("debug", false)) {
apiInstance.addListener(BallDebugListener.INSTANCE);
RTopic topic = redissonClient.getTopic(BALL_CHANNEL, BallMessageInfoCodec.INSTANCE);
if (config.getBoolean("debug", false)) {
topic.addListener(BallMessageInfo.class, BallDebugListener.INSTANCE);
}
instance = apiInstance;
@@ -93,4 +104,9 @@ public class BallBukkitAPI extends BallAPI {
public @NotNull DataSource getDatasource() {
return datasource == null ? CoreAPI.getInstance().getDataSource() : datasource;
}
@Override
public @NotNull RedissonClient getRedissonClient() {
return redissonClient;
}
}

View File

@@ -11,7 +11,6 @@ import cn.hamster3.mc.plugin.core.bukkit.api.CoreBukkitAPI;
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import cn.hamster3.mc.plugin.core.common.data.DisplayMessage;
import cn.hamster3.mc.plugin.core.common.util.CoreUtils;
import cn.hamster3.mc.plugin.core.common.util.Pair;
import cn.hamster3.mc.plugin.core.lib.net.kyori.adventure.audience.Audience;
import cn.hamster3.mc.plugin.core.lib.net.kyori.adventure.text.TextReplacementConfig;
import lombok.AllArgsConstructor;
@@ -26,7 +25,11 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
@@ -34,8 +37,8 @@ import java.util.UUID;
public class BallBukkitListener implements Listener, BallListener {
public static final BallBukkitListener INSTANCE = new BallBukkitListener();
private final HashMap<UUID, Pair<Location, DisplayMessage>> playerToLocation = new HashMap<>();
private final HashMap<UUID, ToPlayerData> playerToPlayer = new HashMap<>();
private final HashMap<UUID, ToLocation> playerToLocation = new HashMap<>();
private final HashMap<UUID, ToPlayer> playerToPlayer = new HashMap<>();
private BallBukkitListener() {
}
@@ -99,7 +102,7 @@ public class BallBukkitListener implements Listener, BallListener {
}
});
} else {
playerToLocation.put(uuid, new Pair<>(location.toBukkitLocation(), event.getDoneMessage()));
playerToLocation.put(uuid, new ToLocation(location.toBukkitLocation(), event.getDoneMessage()));
}
}
}
@@ -133,7 +136,7 @@ public class BallBukkitListener implements Listener, BallListener {
}
});
} else {
ToPlayerData data = new ToPlayerData(
ToPlayer data = new ToPlayer(
toPlayer.getUniqueId(),
toPlayer.getLocation(),
event.getDoneMessage(),
@@ -151,15 +154,16 @@ public class BallBukkitListener implements Listener, BallListener {
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
Pair<Location, DisplayMessage> pair = playerToLocation.remove(uuid);
if (pair != null) {
player.teleport(pair.getKey(), PlayerTeleportEvent.TeleportCause.PLUGIN);
if (pair.getValue() != null) {
ToLocation toLocationData = playerToLocation.remove(uuid);
if (toLocationData != null) {
player.teleport(toLocationData.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
DisplayMessage doneMessage = toLocationData.getDoneMessage();
if (doneMessage != null) {
Audience audience = CoreBukkitAPI.getInstance().getAudienceProvider().player(player);
pair.getValue().show(audience);
doneMessage.show(audience);
}
}
ToPlayerData toPlayerData = playerToPlayer.remove(uuid);
ToPlayer toPlayerData = playerToPlayer.remove(uuid);
if (toPlayerData != null) {
player.teleport(toPlayerData.location);
if (toPlayerData.doneMessage != null) {
@@ -179,21 +183,58 @@ public class BallBukkitListener implements Listener, BallListener {
}
HamsterBallPlugin.async(() -> {
try {
List<DisplayMessage> cachedPlayerMessage = BallAPI.getInstance().getCachedPlayerMessage(uuid);
List<DisplayMessage> cachedPlayerMessage = getCachedPlayerMessage(uuid);
Audience audience = CoreAPI.getInstance().getAudienceProvider().player(uuid);
for (DisplayMessage message : cachedPlayerMessage) {
message.show(audience);
}
BallAPI.getInstance().removeCachedPlayerMessage(uuid);
removeCachedPlayerMessage(uuid);
} catch (SQLException e) {
e.printStackTrace();
}
});
}
@NotNull
private List<DisplayMessage> getCachedPlayerMessage(@NotNull UUID uuid) throws SQLException {
ArrayList<DisplayMessage> list = new ArrayList<>();
try (Connection connection = BallAPI.getInstance().getDatasource().getConnection()) {
try (PreparedStatement statement = connection.prepareStatement(
"SELECT message FROM `hamster_ball_cached_message` WHERE `uuid`=?;"
)) {
statement.setString(1, uuid.toString());
try (ResultSet set = statement.executeQuery()) {
while (set.next()) {
DisplayMessage msg = CoreUtils.GSON.fromJson(set.getString("message"), DisplayMessage.class);
list.add(msg);
}
}
}
}
return list;
}
private void removeCachedPlayerMessage(@NotNull UUID uuid) throws SQLException {
try (Connection connection = BallAPI.getInstance().getDatasource().getConnection()) {
try (PreparedStatement statement = connection.prepareStatement(
"DELETE FROM `hamster_ball_cached_message` WHERE `uuid`=?;"
)) {
statement.setString(1, uuid.toString());
statement.executeUpdate();
}
}
}
@Data
@AllArgsConstructor
private static class ToPlayerData {
private static class ToLocation {
private Location location;
private DisplayMessage doneMessage;
}
@Data
@AllArgsConstructor
private static class ToPlayer {
private UUID toPlayerUUID;
private Location location;
private DisplayMessage doneMessage;

View File

@@ -1,11 +1,6 @@
# 是否允许在控制台输出调试信息
debug: false
ball-server:
host: "ball.hamster3.cn"
port: 58888
event-loop-thread: 2
server-info:
# 服务器唯一识别码,最长 32 字符
# 推荐格式:全小写英文+横杠+数字尾号
@@ -19,8 +14,6 @@ server-info:
# 当前子服的内网地址
# 不填则自动获取 server.properties 文件中的设置
# 若都为空,则自动设定为 127.0.0.1
# BC 端的插件会自动将这个服务器的地址和端口加入到列表
# 因此只需在这里配置好,以后新增子服时无需每次都手动更改 BC 的配置文件
# host: "127.0.0.1"
# 当前子服的内网端口
# 不填则自动获取 server.properties 文件中的设置