feat: 新增频道分组功能
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package cn.hamster3.mc.plugin.ball.common.api;
|
||||
|
||||
import cn.hamster3.mc.plugin.ball.common.config.BallConfig;
|
||||
import cn.hamster3.mc.plugin.ball.common.data.BallLocation;
|
||||
import cn.hamster3.mc.plugin.ball.common.data.BallMessage;
|
||||
import cn.hamster3.mc.plugin.ball.common.entity.BallPlayerInfo;
|
||||
@@ -36,41 +37,39 @@ public abstract class BallAPI {
|
||||
* API 使用的通信频道
|
||||
*/
|
||||
public static final String BALL_CHANNEL = "HamsterBall";
|
||||
/**
|
||||
* API 使用的玩家信息更新通信频道
|
||||
*/
|
||||
public static final String PLAYER_INFO_UPDATE_CHANNEL = "HamsterBall:PlayerInfo";
|
||||
/**
|
||||
* API 实例
|
||||
*/
|
||||
@Getter
|
||||
protected static BallAPI instance;
|
||||
@NotNull
|
||||
protected final Map<String, BallServerInfo> allServerInfo;
|
||||
private final BallConfig ballConfig;
|
||||
@NotNull
|
||||
protected final Map<UUID, BallPlayerInfo> allPlayerInfo;
|
||||
private final EventBus eventBus;
|
||||
@NotNull
|
||||
private final BallServerInfo localServerInfo;
|
||||
@Nullable
|
||||
private final DataSource datasource;
|
||||
private final Map<String, BallServerInfo> allServerInfo;
|
||||
@NotNull
|
||||
private final RedisClient redisClient;
|
||||
private final Map<UUID, BallPlayerInfo> allPlayerInfo;
|
||||
@NotNull
|
||||
private final StatefulRedisPubSubConnection<String, BallMessage> subConnection;
|
||||
@NotNull
|
||||
private final StatefulRedisPubSubConnection<String, BallMessage> pubConnection;
|
||||
@NotNull
|
||||
private final EventBus eventBus;
|
||||
|
||||
public BallAPI(@NotNull BallServerInfo localServerInfo, @Nullable DataSource datasource, @NotNull RedisClient redisClient, boolean debug) {
|
||||
this.localServerInfo = localServerInfo;
|
||||
this.datasource = datasource;
|
||||
this.redisClient = redisClient;
|
||||
subConnection = redisClient.connectPubSub(BallMessage.CODEC);
|
||||
pubConnection = redisClient.connectPubSub(BallMessage.CODEC);
|
||||
public BallAPI(@NotNull BallConfig ballConfig) {
|
||||
this.ballConfig = ballConfig;
|
||||
subConnection = ballConfig.getRedisClient().connectPubSub(BallMessage.CODEC);
|
||||
pubConnection = ballConfig.getRedisClient().connectPubSub(BallMessage.CODEC);
|
||||
allServerInfo = new ConcurrentHashMap<>();
|
||||
allPlayerInfo = new ConcurrentHashMap<>();
|
||||
eventBus = new AsyncEventBus("HamsterBall - EventBus", CoreAPI.getInstance().getExecutorService());
|
||||
eventBus.register(BallCommonListener.INSTANCE);
|
||||
if (debug) {
|
||||
if (ballConfig.isDebug()) {
|
||||
getLogger().warning("已启用调试模式");
|
||||
subConnection.addListener(BallDebugListener.INSTANCE);
|
||||
eventBus.register(BallDebugListener.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,11 +140,13 @@ public abstract class BallAPI {
|
||||
}
|
||||
}
|
||||
subConnection.addListener(BallRedisListener.INSTANCE);
|
||||
subscribe(BALL_CHANNEL);
|
||||
subConnection.sync().subscribe(BALL_CHANNEL);
|
||||
}
|
||||
|
||||
protected void disable() throws SQLException, InterruptedException {
|
||||
sendBallMessage(BALL_CHANNEL, new BallMessage(BallActions.ServerOffline.name(), new ServerOfflineEvent(localServerInfo)), true);
|
||||
sendBallMessage(BallAPI.BALL_CHANNEL, new BallMessage(
|
||||
BallActions.ServerOffline.name(), new ServerOfflineEvent(getLocalServerInfo())
|
||||
), false, true);
|
||||
|
||||
try (Connection connection = getDatasource().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement(
|
||||
@@ -163,7 +164,7 @@ public abstract class BallAPI {
|
||||
}
|
||||
}
|
||||
getLogger().info("正在关闭 redission");
|
||||
redisClient.close();
|
||||
ballConfig.getRedisClient().close();
|
||||
getLogger().info("已关闭 redission");
|
||||
}
|
||||
|
||||
@@ -205,10 +206,8 @@ public abstract class BallAPI {
|
||||
sendBallMessage(BALL_CHANNEL, new BallMessage(
|
||||
getLocalServerId(), null, BallServerType.PROXY,
|
||||
BallActions.BroadcastPlayerMessage.name(),
|
||||
CoreAPI.getInstance().getGson().toJsonTree(
|
||||
new BroadcastPlayerMessageEvent(message)
|
||||
)
|
||||
));
|
||||
CoreAPI.getInstance().getGson().toJsonTree(new BroadcastPlayerMessageEvent(message))
|
||||
), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,10 +221,9 @@ public abstract class BallAPI {
|
||||
sendBallMessage(BALL_CHANNEL, new BallMessage(
|
||||
getLocalServerId(), null, BallServerType.GAME,
|
||||
BallActions.DispatchConsoleCommand.name(),
|
||||
CoreAPI.getInstance().getGson().toJsonTree(
|
||||
new DispatchConsoleCommandEvent(type, serverID, command)
|
||||
)
|
||||
));
|
||||
CoreAPI.getInstance().getGson().toJsonTree(new DispatchConsoleCommandEvent(type, serverID, command))
|
||||
), false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,10 +237,8 @@ public abstract class BallAPI {
|
||||
sendBallMessage(BALL_CHANNEL, new BallMessage(
|
||||
getLocalServerId(), null, BallServerType.GAME,
|
||||
BallActions.DispatchPlayerCommand.name(),
|
||||
CoreAPI.getInstance().getGson().toJsonTree(
|
||||
new DispatchPlayerCommandEvent(type, uuid, command)
|
||||
)
|
||||
));
|
||||
CoreAPI.getInstance().getGson().toJsonTree(new DispatchPlayerCommandEvent(type, uuid, command))
|
||||
), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,10 +261,8 @@ public abstract class BallAPI {
|
||||
sendBallMessage(BALL_CHANNEL, new BallMessage(
|
||||
getLocalServerId(), null, BallServerType.PROXY,
|
||||
BallActions.KickPlayer.name(),
|
||||
CoreAPI.getInstance().getGson().toJsonTree(
|
||||
new KickPlayerEvent(uuid, reason)
|
||||
)
|
||||
));
|
||||
CoreAPI.getInstance().getGson().toJsonTree(new KickPlayerEvent(uuid, reason))
|
||||
), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,10 +306,8 @@ public abstract class BallAPI {
|
||||
sendBallMessage(BALL_CHANNEL, new BallMessage(
|
||||
getLocalServerId(), null, BallServerType.PROXY,
|
||||
BallActions.SendMessageToPlayer.name(),
|
||||
CoreAPI.getInstance().getGson().toJsonTree(
|
||||
new SendMessageToPlayerEvent(new HashSet<>(receivers), message)
|
||||
)
|
||||
));
|
||||
CoreAPI.getInstance().getGson().toJsonTree(new SendMessageToPlayerEvent(new HashSet<>(receivers), message))
|
||||
), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,7 +338,7 @@ public abstract class BallAPI {
|
||||
*/
|
||||
public void sendPlayerToLocation(@NotNull Collection<UUID> sendPlayerUUID, @NotNull BallLocation location, @Nullable DisplayMessage doneMessage) {
|
||||
sendBallMessage(BALL_CHANNEL, BallActions.SendPlayerToLocation.name(),
|
||||
new SendPlayerToLocationEvent(new HashSet<>(sendPlayerUUID), location, doneMessage)
|
||||
new SendPlayerToLocationEvent(new HashSet<>(sendPlayerUUID), location, doneMessage), false
|
||||
);
|
||||
}
|
||||
|
||||
@@ -375,25 +367,39 @@ public abstract class BallAPI {
|
||||
* @param doneTargetMessage 传送完成后目标玩家显示的消息,自动将 %player_name% 替换成被传送者的名称
|
||||
*/
|
||||
public void sendPlayerToPlayer(@NotNull Collection<UUID> sendPlayerUUID, @NotNull UUID toPlayer, @Nullable DisplayMessage doneMessage, @Nullable DisplayMessage doneTargetMessage) {
|
||||
sendBallMessage(BALL_CHANNEL, BallActions.SendPlayerToPlayer.name(),
|
||||
new SendPlayerToPlayerEvent(new HashSet<>(sendPlayerUUID), toPlayer, doneMessage, doneTargetMessage)
|
||||
sendBallMessage(
|
||||
BALL_CHANNEL,
|
||||
BallActions.SendPlayerToPlayer.name(),
|
||||
new SendPlayerToPlayerEvent(new HashSet<>(sendPlayerUUID), toPlayer, doneMessage, doneTargetMessage),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一条服务消息
|
||||
*
|
||||
* @param channel 消息标签
|
||||
* @param channel 消息频道
|
||||
* @param action 执行动作
|
||||
*/
|
||||
public void sendBallMessage(@NotNull String channel, @NotNull String action) {
|
||||
sendBallMessage(channel, new BallMessage(action));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一条服务消息
|
||||
*
|
||||
* @param channel 消息频道
|
||||
* @param action 执行动作
|
||||
* @param prefix 是否自动为消息频道添加分组前缀
|
||||
*/
|
||||
public void sendBallMessage(@NotNull String channel, @NotNull String action, boolean prefix) {
|
||||
sendBallMessage(channel, new BallMessage(action), prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一条有附加参数的服务消息
|
||||
*
|
||||
* @param channel 消息标签
|
||||
* @param channel 消息频道
|
||||
* @param action 执行动作
|
||||
* @param content 附加参数
|
||||
*/
|
||||
@@ -401,37 +407,67 @@ public abstract class BallAPI {
|
||||
sendBallMessage(channel, new BallMessage(action, content));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一条有附加参数的服务消息
|
||||
*
|
||||
* @param channel 消息频道
|
||||
* @param action 执行动作
|
||||
* @param content 附加参数
|
||||
* @param prefix 是否自动为消息频道添加分组前缀
|
||||
*/
|
||||
public void sendBallMessage(@NotNull String channel, @NotNull String action, @NotNull Object content, boolean prefix) {
|
||||
sendBallMessage(channel, new BallMessage(action, content), prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送自定义消息
|
||||
*
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public void sendBallMessage(@NotNull String channel, @NotNull BallMessage message) {
|
||||
sendBallMessage(channel, message, false);
|
||||
sendBallMessage(channel, message, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送自定义消息
|
||||
*
|
||||
* @param message 消息内容
|
||||
* @param prefix 是否自动为消息频道添加分组前缀
|
||||
*/
|
||||
public void sendBallMessage(@NotNull String channel, @NotNull BallMessage message, boolean prefix) {
|
||||
sendBallMessage(channel, message, prefix, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义服务消息信息并发送
|
||||
*
|
||||
* @param channel 消息标签
|
||||
* @param channel 消息频道
|
||||
* @param message 消息内容
|
||||
* @param prefix 是否自动为消息频道添加分组前缀
|
||||
* @param block 是否阻塞(设置为 true 则必须等待消息写入网络的操作完成后,该方法才会退出)
|
||||
*/
|
||||
public void sendBallMessage(@NotNull String channel, @NotNull BallMessage message, boolean block) {
|
||||
public void sendBallMessage(@NotNull String channel, @NotNull BallMessage message, boolean prefix, boolean block) {
|
||||
if (prefix) {
|
||||
channel = ballConfig.getChannelPrefix() + ":" + channel;
|
||||
}
|
||||
if (block) {
|
||||
pubConnection.sync().publish(channel, message);
|
||||
eventBus.post(new MessageSentEvent(channel, message));
|
||||
} else {
|
||||
@NotNull String finalChannel = channel;
|
||||
pubConnection.async().publish(channel, message).whenComplete((aLong, throwable) -> {
|
||||
if (throwable != null) {
|
||||
return;
|
||||
}
|
||||
eventBus.post(new MessageSentEvent(channel, message));
|
||||
eventBus.post(new MessageSentEvent(finalChannel, message));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void subscribe(@NotNull String... channel) {
|
||||
for (int i = 0; i < channel.length; i++) {
|
||||
channel[i] = ballConfig.getChannelPrefix() + ":" + channel[i];
|
||||
}
|
||||
subConnection.sync().subscribe(channel);
|
||||
}
|
||||
|
||||
@@ -440,6 +476,9 @@ public abstract class BallAPI {
|
||||
}
|
||||
|
||||
public void unsubscribe(@NotNull String... channel) {
|
||||
for (int i = 0; i < channel.length; i++) {
|
||||
channel[i] = ballConfig.getChannelPrefix() + ":" + channel[i];
|
||||
}
|
||||
subConnection.sync().unsubscribe(channel);
|
||||
}
|
||||
|
||||
@@ -454,12 +493,12 @@ public abstract class BallAPI {
|
||||
*/
|
||||
@NotNull
|
||||
public BallServerInfo getLocalServerInfo() {
|
||||
return localServerInfo;
|
||||
return ballConfig.getServerInfo();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getLocalServerId() {
|
||||
return localServerInfo.getId();
|
||||
return ballConfig.getServerInfo().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,6 +618,11 @@ public abstract class BallAPI {
|
||||
|
||||
@NotNull
|
||||
public DataSource getDatasource() {
|
||||
return datasource == null ? CoreAPI.getInstance().getDataSource() : datasource;
|
||||
return ballConfig.getDatasource() == null ? CoreAPI.getInstance().getDataSource() : ballConfig.getDatasource();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public RedisClient getRedisClient() {
|
||||
return ballConfig.getRedisClient();
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,25 @@
|
||||
package cn.hamster3.mc.plugin.ball.common.config;
|
||||
|
||||
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Data
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class BallConfig {
|
||||
private boolean debug;
|
||||
@NotNull
|
||||
private BallServerInfo localInfo;
|
||||
private RedisClient redisClient;
|
||||
@NotNull
|
||||
private String host;
|
||||
private int port;
|
||||
private int eventLoopThread;
|
||||
private String channelPrefix;
|
||||
private boolean gameServerUpdatePlayerInfo;
|
||||
@NotNull
|
||||
private BallServerInfo serverInfo;
|
||||
@Nullable
|
||||
private DataSource datasource;
|
||||
}
|
||||
|
@@ -1,38 +1,23 @@
|
||||
package cn.hamster3.mc.plugin.ball.common.listener;
|
||||
|
||||
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
|
||||
import cn.hamster3.mc.plugin.ball.common.data.BallMessage;
|
||||
import io.lettuce.core.pubsub.RedisPubSubListener;
|
||||
import cn.hamster3.mc.plugin.ball.common.event.message.MessageReceivedEvent;
|
||||
import cn.hamster3.mc.plugin.ball.common.event.message.MessageSentEvent;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
public class BallDebugListener implements RedisPubSubListener<String, BallMessage> {
|
||||
public class BallDebugListener {
|
||||
public static final BallDebugListener INSTANCE = new BallDebugListener();
|
||||
|
||||
private BallDebugListener() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void message(String channel, BallMessage event) {
|
||||
BallAPI.getInstance().getLogger().info("从 " + channel + " 收到了一条消息: " + event);
|
||||
@Subscribe
|
||||
public void onMessageReceived(MessageReceivedEvent event) {
|
||||
BallAPI.getInstance().getLogger().info("从 " + event.getChannel() + " 收到了一条消息: " + event.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void message(String pattern, String channel, BallMessage event) {
|
||||
BallAPI.getInstance().getLogger().info("从 " + pattern + "(" + channel + ") 收到了一条消息: " + event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribed(String channel, long count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void psubscribed(String pattern, long count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribed(String channel, long count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void punsubscribed(String pattern, long count) {
|
||||
@Subscribe
|
||||
public void onMessageSent(MessageSentEvent event) {
|
||||
BallAPI.getInstance().getLogger().info("从 " + event.getChannel() + " 发送了了一条消息: " + event.getMessage());
|
||||
}
|
||||
}
|
||||
|
@@ -129,21 +129,21 @@ public class BallRedisListener implements RedisPubSubListener<String, BallMessag
|
||||
|
||||
@Override
|
||||
public void subscribed(String channel, long count) {
|
||||
BallAPI.getInstance().getLogger().info("已订阅 redis 频道: " + channel);
|
||||
BallAPI.getInstance().getLogger().info("已订阅 redis 频道 " + channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void psubscribed(String pattern, long count) {
|
||||
BallAPI.getInstance().getLogger().info("已取消订阅 redis 频道(正则): " + pattern);
|
||||
BallAPI.getInstance().getLogger().info("已取消订阅 redis 频道(正则) " + pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribed(String channel, long count) {
|
||||
BallAPI.getInstance().getLogger().info("已取消订阅 redis 频道: " + channel);
|
||||
BallAPI.getInstance().getLogger().info("已取消订阅 redis 频道 " + channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void punsubscribed(String pattern, long count) {
|
||||
BallAPI.getInstance().getLogger().info("已取消订阅 redis 频道(正则): " + pattern);
|
||||
BallAPI.getInstance().getLogger().info("已取消订阅 redis 频道(正则) " + pattern);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user