From 5b28dc6deaeb85901205b5d2c54587a3184ab8b1 Mon Sep 17 00:00:00 2001 From: Keuin Date: Sun, 14 Aug 2022 13:04:39 +0800 Subject: Bugfix: history message replay is not working. Now its behavior is the same with legacy BungeeCross. --- .../messaging/config/router/RouterConfigurer.java | 13 +++++-- .../keuin/crosslink/messaging/filter/IFilter.java | 1 + .../messaging/history/HistoricMessageRecorder.java | 18 +++++++-- .../history/IHistoricMessageRecorder.java | 7 +++- .../messaging/rule/MessageListeningRule.java | 45 ++++++++++++++++++++++ .../crosslink/plugin/bungee/BungeeAccessor.java | 9 +++-- .../crosslink/plugin/bungee/BungeeEventBus.java | 27 +++++++++---- .../crosslink/plugin/bungee/BungeeMainWrapper.java | 37 +++++++++++------- .../plugin/bungee/module/BungeeEventBusModule.java | 12 ------ .../bungee/module/BungeeEventBusProvider.java | 19 +++++++++ .../keuin/crosslink/plugin/common/PluginMain.java | 45 +++++++++++++++++++--- .../plugin/velocity/VelocityEventBus.java | 5 +-- .../plugin/velocity/VelocityMainWrapper.java | 6 ++- .../velocity/module/VelocityEventBusModule.java | 12 ------ .../velocity/module/VelocityEventBusProvider.java | 19 +++++++++ .../java/com/keuin/crosslink/util/DateUtil.java | 45 ++++++++++++++++++++++ 16 files changed, 253 insertions(+), 67 deletions(-) create mode 100644 src/main/java/com/keuin/crosslink/messaging/rule/MessageListeningRule.java delete mode 100644 src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusModule.java create mode 100644 src/main/java/com/keuin/crosslink/plugin/bungee/module/BungeeEventBusProvider.java delete mode 100644 src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusModule.java create mode 100644 src/main/java/com/keuin/crosslink/plugin/velocity/module/VelocityEventBusProvider.java create mode 100644 src/main/java/com/keuin/crosslink/util/DateUtil.java (limited to 'src/main/java') 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 prefixRules = new ArrayList<>(); public RouterConfigurer(@NotNull JsonNode config) { Objects.requireNonNull(config); this.config = config; } + public RouterConfigurer(@NotNull JsonNode config, List 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> 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 getMessages() { + public List> 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 getMessages(); + List> 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> handlers = new ArrayList<>(); + + public void addHandler(Consumer 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 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 connectedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<>()); // all players connected to the proxy private final Map joiningServers = new HashMap<>(); private final Map 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(); + final var prefixRules = new ArrayList(); 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 connectedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<>()); // all players connected to the proxy @@ -30,7 +29,7 @@ public class VelocityEventBus implements IEventBus { private final List 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 + } +} + -- cgit v1.2.3