summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/keuin/crosslink/messaging/config/router/RouterConfigurer.java13
-rw-r--r--src/main/java/com/keuin/crosslink/messaging/filter/IFilter.java1
-rw-r--r--src/main/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorder.java18
-rw-r--r--src/main/java/com/keuin/crosslink/messaging/history/IHistoricMessageRecorder.java7
-rw-r--r--src/main/java/com/keuin/crosslink/messaging/rule/MessageListeningRule.java45
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/bungee/BungeeAccessor.java9
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/bungee/BungeeEventBus.java27
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/bungee/BungeeMainWrapper.java37
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusModule.java12
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusProvider.java19
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/common/PluginMain.java45
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/velocity/VelocityEventBus.java5
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/velocity/VelocityMainWrapper.java6
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusModule.java12
-rw-r--r--src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusProvider.java19
-rw-r--r--src/main/java/com/keuin/crosslink/util/DateUtil.java45
-rw-r--r--src/test/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorderTest.java2
17 files changed, 254 insertions, 68 deletions
diff --git a/src/main/java/com/keuin/crosslink/messaging/config/router/RouterConfigurer.java b/src/main/java/com/keuin/crosslink/messaging/config/router/RouterConfigurer.java
index 1e4e718..d230c2e 100644
--- a/src/main/java/com/keuin/crosslink/messaging/config/router/RouterConfigurer.java
+++ b/src/main/java/com/keuin/crosslink/messaging/config/router/RouterConfigurer.java
@@ -32,12 +32,19 @@ public class RouterConfigurer implements IRouterConfigurer {
private final JsonNode config;
private static final Logger logger =
LoggerFactory.getLogger(LoggerNaming.name().of("config").of("router").toString());
+ private final List<IRule> prefixRules = new ArrayList<>();
public RouterConfigurer(@NotNull JsonNode config) {
Objects.requireNonNull(config);
this.config = config;
}
+ public RouterConfigurer(@NotNull JsonNode config, List<IRule> prefixRules) {
+ Objects.requireNonNull(config);
+ this.config = config;
+ this.prefixRules.addAll(prefixRules);
+ }
+
private static class ActionConstructionException extends Exception {
public ActionConstructionException() {
}
@@ -243,9 +250,9 @@ public class RouterConfigurer implements IRouterConfigurer {
@Override
public void configure(IRouterConfigurable router) throws JsonProcessingException, ConfigSyntaxError {
+ var rules = new ArrayList<>(prefixRules);
+ rules.addAll(loadRuleChain(router, config));
router.clearEndpoints();
- router.updateRuleChain(loadRuleChain(router, config));
+ router.updateRuleChain(rules);
}
-
-
}
diff --git a/src/main/java/com/keuin/crosslink/messaging/filter/IFilter.java b/src/main/java/com/keuin/crosslink/messaging/filter/IFilter.java
index 5f1bb67..add492e 100644
--- a/src/main/java/com/keuin/crosslink/messaging/filter/IFilter.java
+++ b/src/main/java/com/keuin/crosslink/messaging/filter/IFilter.java
@@ -12,6 +12,7 @@ import java.util.regex.PatternSyntaxException;
* Select endpoints.
*/
public interface IFilter {
+ static final IFilter filterAlwaysTrue = id -> true;
boolean filter(@NotNull IEndpoint id);
static @NotNull IFilter fromPatternString(@NotNull String pattern) throws ReIdFilter.InvalidPatternStringException {
diff --git a/src/main/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorder.java b/src/main/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorder.java
index ba18d83..152ac7a 100644
--- a/src/main/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorder.java
+++ b/src/main/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorder.java
@@ -1,18 +1,25 @@
package com.keuin.crosslink.messaging.history;
import com.keuin.crosslink.messaging.message.IMessage;
+import com.keuin.crosslink.util.LoggerNaming;
import com.keuin.crosslink.util.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
-import java.util.stream.Collectors;
public class HistoricMessageRecorder implements IHistoricMessageRecorder {
private long ttlMillis;
private final LinkedList<Pair<Long, IMessage>> que = new LinkedList<>();
private final Object lock = new Object();
+ private static final Logger logger =
+ LoggerFactory.getLogger(LoggerNaming.name()
+ .of("history").of("message_recorder").toString());
+
public HistoricMessageRecorder(long ttlMillis) {
this.ttlMillis = ttlMillis;
}
@@ -28,6 +35,7 @@ public class HistoricMessageRecorder implements IHistoricMessageRecorder {
head = que.peek()
) {
// head has expired, remove it
+ logger.debug("Remove expired history message " + head);
que.removeFirst();
}
}
@@ -41,6 +49,7 @@ public class HistoricMessageRecorder implements IHistoricMessageRecorder {
@Override
public void addMessage(IMessage message) {
Objects.requireNonNull(message);
+ logger.debug("Add message " + message);
synchronized (lock) {
que.add(new Pair<>(System.currentTimeMillis(), message));
clean();
@@ -48,10 +57,12 @@ public class HistoricMessageRecorder implements IHistoricMessageRecorder {
}
@Override
- public List<IMessage> getMessages() {
+ public List<Pair<Long, IMessage>> getMessages() {
synchronized (lock) {
clean();
- return que.stream().map(Pair::getV).collect(Collectors.toList());
+ var list = new ArrayList<>(que);
+ logger.debug("History messages: " + list);
+ return list;
}
}
@@ -62,6 +73,7 @@ public class HistoricMessageRecorder implements IHistoricMessageRecorder {
@Override
public void setTTL(long ttl) {
+ logger.debug("TTL is set to " + ttl + "ms");
this.ttlMillis = ttl;
}
}
diff --git a/src/main/java/com/keuin/crosslink/messaging/history/IHistoricMessageRecorder.java b/src/main/java/com/keuin/crosslink/messaging/history/IHistoricMessageRecorder.java
index 93a310a..3bcdd86 100644
--- a/src/main/java/com/keuin/crosslink/messaging/history/IHistoricMessageRecorder.java
+++ b/src/main/java/com/keuin/crosslink/messaging/history/IHistoricMessageRecorder.java
@@ -1,6 +1,7 @@
package com.keuin.crosslink.messaging.history;
import com.keuin.crosslink.messaging.message.IMessage;
+import com.keuin.crosslink.util.Pair;
import java.util.List;
@@ -13,24 +14,28 @@ import java.util.List;
public interface IHistoricMessageRecorder {
/**
* Add and memorize a message.
+ *
* @param message the message to save.
*/
void addMessage(IMessage message);
/**
* Get recent messages.
+ *
* @return an {@link List} containing all recent messages in the time scope.
*/
- List<IMessage> getMessages();
+ List<Pair<Long, IMessage>> getMessages();
/**
* Get message TTL.
+ *
* @return the message TTL milliseconds.
*/
long getTTL();
/**
* Set message TTL. (a workaround to implement later initialization)
+ *
* @param ttl the message TTL milliseconds.
*/
void setTTL(long ttl);
diff --git a/src/main/java/com/keuin/crosslink/messaging/rule/MessageListeningRule.java b/src/main/java/com/keuin/crosslink/messaging/rule/MessageListeningRule.java
new file mode 100644
index 0000000..075626f
--- /dev/null
+++ b/src/main/java/com/keuin/crosslink/messaging/rule/MessageListeningRule.java
@@ -0,0 +1,45 @@
+package com.keuin.crosslink.messaging.rule;
+
+import com.keuin.crosslink.messaging.action.IAction;
+import com.keuin.crosslink.messaging.action.result.IActionResult;
+import com.keuin.crosslink.messaging.filter.IFilter;
+import com.keuin.crosslink.messaging.message.IMessage;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Listen and record all global messages.
+ */
+public class MessageListeningRule implements IRule {
+ private final List<Consumer<IMessage>> handlers = new ArrayList<>();
+
+ public void addHandler(Consumer<IMessage> handler) {
+ handlers.add(handler);
+ }
+
+ @Override
+ public IActionResult process(@NotNull IMessage message) {
+ handlers.forEach(c -> c.accept(message));
+ return IActionResult.normal(message);
+ }
+
+ @Override
+ public @NotNull ObjectType object() {
+ return ObjectType.CHAT_MESSAGE;
+ }
+
+ @Override
+ public @NotNull IFilter from() {
+ return IFilter.filterAlwaysTrue;
+ }
+
+ @Override
+ public @NotNull List<IAction> actions() {
+ // this rule records all passing messages, and do nothing about message forwarding
+ return Collections.emptyList();
+ }
+}
diff --git a/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeAccessor.java b/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeAccessor.java
index f840137..dd3fd4f 100644
--- a/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeAccessor.java
+++ b/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeAccessor.java
@@ -1,7 +1,6 @@
package com.keuin.crosslink.plugin.bungee;
import com.google.inject.Inject;
-import com.keuin.crosslink.config.GlobalConfigManager;
import com.keuin.crosslink.data.PlayerInfo;
import com.keuin.crosslink.data.ServerInfo;
import com.keuin.crosslink.messaging.endpoint.IEndpoint;
@@ -9,7 +8,8 @@ import com.keuin.crosslink.messaging.endpoint.local.BungeeServerChatEndpoint;
import com.keuin.crosslink.plugin.bungee.checker.BungeeServerStatusChecker;
import com.keuin.crosslink.plugin.common.ICoreAccessor;
import net.kyori.adventure.text.Component;
-import net.md_5.bungee.api.chat.ComponentBuilder;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+import net.md_5.bungee.api.chat.TextComponent;
import java.util.List;
import java.util.Objects;
@@ -63,8 +63,9 @@ public class BungeeAccessor implements ICoreAccessor {
public void sendPlayerMessage(UUID playerUuid, Component message) {
var player = plugin.getProxy().getPlayer(playerUuid);
if (player == null) return;
- // FIXME keep color data
- var msg = new ComponentBuilder().append(message.toString()).create();
+ // convert between two incompatible Component objects using legacy string such as "&6Hello &b&lworld&c!"
+ var msg = TextComponent
+ .fromLegacyText(LegacyComponentSerializer.legacySection().serialize(message));
player.sendMessage(msg);
}
}
diff --git a/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeEventBus.java b/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeEventBus.java
index 4ccff85..5232937 100644
--- a/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeEventBus.java
+++ b/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeEventBus.java
@@ -3,6 +3,7 @@ package com.keuin.crosslink.plugin.bungee;
import com.google.inject.Inject;
import com.keuin.crosslink.plugin.common.IEventBus;
import com.keuin.crosslink.plugin.common.event.*;
+import com.keuin.crosslink.util.LoggerNaming;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -11,15 +12,17 @@ import net.md_5.bungee.api.event.*;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
-import java.util.logging.Logger;
public class BungeeEventBus implements Listener, IEventBus {
private final Plugin plugin;
- private final Logger logger = Logger.getLogger(BungeeEventBus.class.getName());
+ private final Logger logger = LoggerFactory.getLogger(LoggerNaming.name()
+ .of("bungee").of("eventbus").toString());
private final Set<UUID> connectedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<>()); // all players connected to the proxy
private final Map<UUID, ServerInfo> joiningServers = new HashMap<>();
private final Map<UUID, ServerInfo> serverPlayerLastJoined = new HashMap<>(); // the server players last connected to
@@ -29,6 +32,7 @@ public class BungeeEventBus implements Listener, IEventBus {
@Inject
public BungeeEventBus(Plugin plugin) {
this.plugin = Objects.requireNonNull(plugin);
+ logger.debug("Initializing.");
}
@Override
@@ -39,11 +43,15 @@ public class BungeeEventBus implements Listener, IEventBus {
@net.md_5.bungee.event.EventHandler
public void onServerDisconnect(ServerDisconnectEvent event) {
+ logger.debug("onServerDisconnect");
ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> {
+ var player = event.getPlayer().getName();
+ var server = event.getTarget().getName();
+ logger.debug("ServerDisconnectEvent: player: " + player + " server: " + server);
for (var handler : handlers) {
if (handler instanceof PlayerQuitServerEvent) {
((PlayerQuitServerEvent) handler).onPlayerQuitServer(
- event.getPlayer().getName(), event.getTarget().getName());
+ player, server);
}
}
});
@@ -51,6 +59,7 @@ public class BungeeEventBus implements Listener, IEventBus {
@net.md_5.bungee.event.EventHandler
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
+ logger.debug("onPlayerDisconnect");
try {
var player = event.getPlayer();
if (player != null) {
@@ -72,12 +81,13 @@ public class BungeeEventBus implements Listener, IEventBus {
});
}
} catch (Exception e) {
- logger.warning(String.format("An exception caught while handling player disconnect event: %s.", e));
+ logger.error(String.format("An exception caught while handling player disconnect event: %s.", e));
}
}
@net.md_5.bungee.event.EventHandler
public void onServerConnect(ServerConnectEvent event) {
+ logger.debug("onServerConnect");
ProxiedPlayer player = event.getPlayer();
if (player == null)
return;
@@ -87,7 +97,7 @@ public class BungeeEventBus implements Listener, IEventBus {
@net.md_5.bungee.event.EventHandler
public void onPlayerJoined(ServerConnectedEvent event) {
-
+ logger.debug("onPlayerJoined");
// after a player has joined the server
ProxiedPlayer player = event.getPlayer();
if (player == null)
@@ -96,7 +106,7 @@ public class BungeeEventBus implements Listener, IEventBus {
ServerInfo server = joiningServers.get(player.getUniqueId());
if (!joiningServers.containsKey(event.getPlayer().getUniqueId())) {
- logger.warning(String.format(
+ logger.warn(String.format(
"Unexpected player %s. Login broadcast will not be sent.",
event.getPlayer().getName()));
return;
@@ -127,13 +137,16 @@ public class BungeeEventBus implements Listener, IEventBus {
}
}
}, 100, TimeUnit.MILLISECONDS);
+ } else {
+ logger.debug("Player " + player.getName() + " is already connected. Skip message replaying.");
}
}
public void onPlayerChat(ChatEvent event) {
+ logger.debug("onPlayerChat");
var conn = event.getSender();
if (!(conn instanceof ProxiedPlayer)) {
- logger.severe(String.format("Sender is not a ProxiedPlayer instance: %s", event.getSender().toString()));
+ logger.error(String.format("Sender is not a ProxiedPlayer instance: %s", event.getSender().toString()));
return;
}
diff --git a/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeMainWrapper.java b/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeMainWrapper.java
index 294e574..2d1dbc4 100644
--- a/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeMainWrapper.java
+++ b/src/main/java/com/keuin/crosslink/plugin/bungee/BungeeMainWrapper.java
@@ -4,7 +4,7 @@ import com.google.inject.Guice;
import com.google.inject.Injector;
import com.keuin.crosslink.plugin.bungee.module.BungeeAccessorModule;
import com.keuin.crosslink.plugin.bungee.module.BungeeApiServerModule;
-import com.keuin.crosslink.plugin.bungee.module.BungeeEventBusModule;
+import com.keuin.crosslink.plugin.bungee.module.BungeeEventBusProvider;
import com.keuin.crosslink.plugin.common.PluginMain;
import com.keuin.crosslink.plugin.common.ProxyType;
import com.keuin.crosslink.plugin.common.environ.PluginEnvironment;
@@ -18,19 +18,28 @@ import org.slf4j.LoggerFactory;
public final class BungeeMainWrapper extends Plugin {
- private final Injector injector = Guice.createInjector(
- new BungeeAccessorModule(this),
- new BungeeApiServerModule(),
- new BungeeEventBusModule(),
- new CommonHistoricMessageRecorderModule(),
- new CommonIRouterModule(),
- new CommonPluginEnvironProvider(new PluginEnvironment(
- ProxyType.BUNGEECORD,
- LoggerFactory.getLogger(LoggerNaming.name().toString()),
- getDataFolder().toPath())),
- new CommonApiServerProvider()
- );
- private final PluginMain plugin = injector.getInstance(PluginMain.class);
+ private final BungeeEventBus eventBus;
+
+ private final Injector injector;
+ private final PluginMain plugin;
+
+ public BungeeMainWrapper() {
+ eventBus = new BungeeEventBus(this);
+ getProxy().getPluginManager().registerListener(this, eventBus);
+ injector = Guice.createInjector(
+ new BungeeAccessorModule(this),
+ new BungeeApiServerModule(),
+ new CommonHistoricMessageRecorderModule(),
+ new CommonIRouterModule(),
+ new CommonPluginEnvironProvider(new PluginEnvironment(
+ ProxyType.BUNGEECORD,
+ LoggerFactory.getLogger(LoggerNaming.name().toString()),
+ getDataFolder().toPath())),
+ new BungeeEventBusProvider(eventBus),
+ new CommonApiServerProvider()
+ );
+ plugin = injector.getInstance(PluginMain.class);
+ }
@Override
public void onLoad() {
diff --git a/src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusModule.java b/src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusModule.java
deleted file mode 100644
index e8c54f7..0000000
--- a/src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusModule.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.keuin.crosslink.plugin.bungee.module;
-
-import com.google.inject.AbstractModule;
-import com.keuin.crosslink.plugin.bungee.BungeeEventBus;
-import com.keuin.crosslink.plugin.common.IEventBus;
-
-public class BungeeEventBusModule extends AbstractModule {
- @Override
- protected void configure() {
- bind(IEventBus.class).to(BungeeEventBus.class);
- }
-} \ No newline at end of file
diff --git a/src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusProvider.java b/src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusProvider.java
new file mode 100644
index 0000000..b589ec3
--- /dev/null
+++ b/src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusProvider.java
@@ -0,0 +1,19 @@
+package com.keuin.crosslink.plugin.bungee.module;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.keuin.crosslink.plugin.bungee.BungeeEventBus;
+import com.keuin.crosslink.plugin.common.IEventBus;
+
+public class BungeeEventBusProvider extends AbstractModule {
+ private final BungeeEventBus bus;
+
+ public BungeeEventBusProvider(BungeeEventBus bus) {
+ this.bus = bus;
+ }
+
+ @Provides
+ public IEventBus provide() {
+ return bus;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/keuin/crosslink/plugin/common/PluginMain.java b/src/main/java/com/keuin/crosslink/plugin/common/PluginMain.java
index 8c3d70a..b84a4cf 100644
--- a/src/main/java/com/keuin/crosslink/plugin/common/PluginMain.java
+++ b/src/main/java/com/keuin/crosslink/plugin/common/PluginMain.java
@@ -15,19 +15,29 @@ import com.keuin.crosslink.messaging.endpoint.IEndpoint;
import com.keuin.crosslink.messaging.endpoint.system.ApiEndpoint;
import com.keuin.crosslink.messaging.history.IHistoricMessageRecorder;
import com.keuin.crosslink.messaging.router.IRouter;
+import com.keuin.crosslink.messaging.rule.IRule;
+import com.keuin.crosslink.messaging.rule.MessageListeningRule;
import com.keuin.crosslink.plugin.common.environ.PluginEnvironment;
import com.keuin.crosslink.plugin.common.event.PlayerConnectEvent;
+import com.keuin.crosslink.util.DateUtil;
import com.keuin.crosslink.util.LoggerNaming;
import com.keuin.crosslink.util.StartupMessagePrinter;
import com.keuin.crosslink.util.version.NewVersionChecker;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.JoinConfiguration;
+import net.kyori.adventure.text.format.TextColor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.Optional;
+import java.util.TimeZone;
import static com.keuin.crosslink.config.GlobalConfigManager.mapper;
@@ -44,8 +54,8 @@ public final class PluginMain {
public PluginMain(ICoreAccessor coreAccessor,
IRouter messageRouter,
IApiServer apiServer,
- PluginEnvironment pluginEnvironment,
IEventBus eventBus,
+ PluginEnvironment pluginEnvironment,
IHistoricMessageRecorder historicMessageRecorder) {
this.coreAccessor = coreAccessor;
this.messageRouter = messageRouter;
@@ -68,6 +78,7 @@ public final class PluginMain {
logger.info("Initializing message routing.");
// Contains all enabled endpoints, including local and remote ones. Remote endpoints will be added later.
final var endpoints = new HashSet<IEndpoint>();
+ final var prefixRules = new ArrayList<IRule>();
try {
var messaging = GlobalConfigManager.getInstance().messaging();
var local = Optional.ofNullable(messaging.get("local"))
@@ -79,22 +90,44 @@ public final class PluginMain {
// load local server endpoints
final var locals = coreAccessor.getServerEndpoints();
- final var ttlSeconds = Optional.ofNullable(local.get("message_playback_seconds"))
+ final long ttlSeconds = Optional.ofNullable(local.get("message_playback_seconds"))
.map(JsonNode::asLong).orElse(-1L);
if (ttlSeconds > 0) {
// enable message replay
- logger.info("Message replay is enabled. TTL: ");
+ historicMessageRecorder.setTTL(ttlSeconds * 1000);
+ logger.info("Message replay is enabled. TTL: " + ttlSeconds + "s.");
+ var ehLogger = LoggerFactory.getLogger(LoggerNaming.name()
+ .of("common").of("events").toString());
eventBus.registerEventHandler(
- (PlayerConnectEvent) (player, uuid) -> historicMessageRecorder.getMessages()
- .forEach(msg -> coreAccessor.sendPlayerMessage(uuid, msg.kyoriMessage()))
+ (PlayerConnectEvent) (player, uuid) -> {
+ var ms = historicMessageRecorder.getMessages();
+ ehLogger.info("Player " + player + " (" + uuid + ")" + " connected. " +
+ "Sending " + ms.size() + " history message(s).");
+ ms.stream()
+ .map(kv -> Component.join(
+ JoinConfiguration.separator(Component.text(" ")),
+ Component.text(
+ String.format(
+ "(%s)",
+ DateUtil.getOffsetString(LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(kv.getK()),
+ TimeZone.getDefault().toZoneId()))),
+ TextColor.color(0x00AA00)),
+ kv.getV().kyoriMessage()))
+ .forEach(msg -> coreAccessor.sendPlayerMessage(uuid, msg));
+ }
);
+ // record messages using a prefix rule
+ var rule = new MessageListeningRule();
+ rule.addHandler(historicMessageRecorder::addMessage);
+ prefixRules.add(rule);
}
endpoints.addAll(locals);
// load routing table
try {
logger.debug("Loading rule chain.");
- var rc = new RouterConfigurer(routing);
+ var rc = new RouterConfigurer(routing, prefixRules);
rc.configure(messageRouter); // update routing table, clear endpoints
logger.debug("Finish configuring message router.");
} catch (JsonProcessingException | ConfigSyntaxError ex) {
diff --git a/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityEventBus.java b/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityEventBus.java
index e47d9f2..2b6ddf8 100644
--- a/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityEventBus.java
+++ b/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityEventBus.java
@@ -11,7 +11,6 @@ import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.player.ServerConnectedEvent;
-import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
import org.jetbrains.annotations.NotNull;
@@ -21,7 +20,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
public class VelocityEventBus implements IEventBus {
- private final Plugin plugin;
+ private final Object plugin;
private final ProxyServer velocity;
private final Logger logger = Logger.getLogger(BungeeEventBus.class.getName());
private final Set<UUID> connectedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<>()); // all players connected to the proxy
@@ -30,7 +29,7 @@ public class VelocityEventBus implements IEventBus {
private final List<EventHandler> handlers = new ArrayList<>();
@Inject
- public VelocityEventBus(Plugin plugin, ProxyServer velocity) {
+ public VelocityEventBus(Object plugin, ProxyServer velocity) {
this.plugin = Objects.requireNonNull(plugin);
this.velocity = Objects.requireNonNull(velocity);
}
diff --git a/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityMainWrapper.java b/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityMainWrapper.java
index 9a1b177..b1f5881 100644
--- a/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityMainWrapper.java
+++ b/src/main/java/com/keuin/crosslink/plugin/velocity/VelocityMainWrapper.java
@@ -11,7 +11,7 @@ import com.keuin.crosslink.plugin.common.module.CommonIRouterModule;
import com.keuin.crosslink.plugin.common.module.CommonPluginEnvironProvider;
import com.keuin.crosslink.plugin.velocity.module.VelocityAccessorModule;
import com.keuin.crosslink.plugin.velocity.module.VelocityApiServerModule;
-import com.keuin.crosslink.plugin.velocity.module.VelocityEventBusModule;
+import com.keuin.crosslink.plugin.velocity.module.VelocityEventBusProvider;
import com.keuin.crosslink.util.LoggerNaming;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
@@ -46,15 +46,17 @@ public final class VelocityMainWrapper {
@Inject
public VelocityMainWrapper(ProxyServer proxy, Logger logger, @DataDirectory Path pluginDataPath) {
+ var eventBus = new VelocityEventBus(this, proxy);
+ proxy.getEventManager().register(this, eventBus);
this.proxy = proxy;
var injector = Guice.createInjector(
new VelocityAccessorModule(this),
new VelocityApiServerModule(),
- new VelocityEventBusModule(),
new CommonHistoricMessageRecorderModule(),
new CommonIRouterModule(),
new CommonPluginEnvironProvider(new PluginEnvironment(
ProxyType.VELOCITY, LoggerFactory.getLogger(LoggerNaming.name().toString()), pluginDataPath)),
+ new VelocityEventBusProvider(eventBus),
new CommonApiServerProvider()
);
this.plugin = injector.getInstance(PluginMain.class);
diff --git a/src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusModule.java b/src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusModule.java
deleted file mode 100644
index c0b90d7..0000000
--- a/src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusModule.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.keuin.crosslink.plugin.velocity.module;
-
-import com.google.inject.AbstractModule;
-import com.keuin.crosslink.plugin.common.IEventBus;
-import com.keuin.crosslink.plugin.velocity.VelocityEventBus;
-
-public class VelocityEventBusModule extends AbstractModule {
- @Override
- protected void configure() {
- bind(IEventBus.class).to(VelocityEventBus.class);
- }
-} \ No newline at end of file
diff --git a/src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusProvider.java b/src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusProvider.java
new file mode 100644
index 0000000..127b9c6
--- /dev/null
+++ b/src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusProvider.java
@@ -0,0 +1,19 @@
+package com.keuin.crosslink.plugin.velocity.module;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.keuin.crosslink.plugin.common.IEventBus;
+import com.keuin.crosslink.plugin.velocity.VelocityEventBus;
+
+public class VelocityEventBusProvider extends AbstractModule {
+ private final VelocityEventBus bus;
+
+ public VelocityEventBusProvider(VelocityEventBus bus) {
+ this.bus = bus;
+ }
+
+ @Provides
+ public IEventBus provide() {
+ return bus;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/keuin/crosslink/util/DateUtil.java b/src/main/java/com/keuin/crosslink/util/DateUtil.java
new file mode 100644
index 0000000..f163622
--- /dev/null
+++ b/src/main/java/com/keuin/crosslink/util/DateUtil.java
@@ -0,0 +1,45 @@
+package com.keuin.crosslink.util;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Copied from legacy BungeeCross codebase.
+ */
+public class DateUtil {
+
+ private static final DateTimeFormatter MONTH_DAY_HOUR_MINUTE_FORMATTER = DateTimeFormatter.ofPattern("MM.dd HH:mm");
+
+ public static String getMonthDayHourMinuteString(LocalDateTime localDateTime) {
+ return localDateTime.format(MONTH_DAY_HOUR_MINUTE_FORMATTER);
+ }
+
+ public static String getOffsetString(LocalDateTime localDateTime) {
+ // TODO: test this
+ LocalDateTime currentTime = LocalDateTime.now();
+ long seconds = currentTime.toEpochSecond(ZoneOffset.UTC)
+ - localDateTime.toEpochSecond(ZoneOffset.UTC);
+ String direction;
+ if (seconds < 0)
+ direction = "later";
+ else
+ direction = "ago";
+
+ StringBuilder absOffset = new StringBuilder();
+ String[] unitNames = new String[]{"y", "mo", "d", "h", "m", "s"};
+ long[] unitSeconds = new long[]{365 * 24 * 60 * 60, 30 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60, 1};
+ for (int i = 0; i < unitNames.length; i++) {
+ long c = seconds / unitSeconds[i];
+ seconds %= unitSeconds[i];
+ if (c > 0)
+ absOffset.append(c).append(unitNames[i]).append(" ");
+ }
+
+ if (absOffset.length() == 0)
+ return "now";
+ else
+ return absOffset + direction; // e.g. 1m3s ago
+ }
+}
+
diff --git a/src/test/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorderTest.java b/src/test/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorderTest.java
index 4dfdfd4..2d8dedf 100644
--- a/src/test/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorderTest.java
+++ b/src/test/java/com/keuin/crosslink/messaging/history/HistoricMessageRecorderTest.java
@@ -23,7 +23,7 @@ class HistoricMessageRecorderTest {
Thread.sleep(500);
var list = recorder.getMessages();
assertEquals(1, list.size());
- assertEquals(msg, list.get(0));
+ assertEquals(msg, list.get(0).getV());
Thread.sleep(510);
list = recorder.getMessages();
assertEquals(0, list.size());