Search in sources :

Example 1 with BackendInteractiveChatData

use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.

the class InteractiveChatVelocity method onBungeeChat.

@Subscribe(order = PostOrder.LATE)
public void onBungeeChat(PlayerChatEvent event) {
    if (!event.getResult().isAllowed()) {
        return;
    }
    Player player = event.getPlayer();
    UUID uuid = player.getUniqueId();
    String message = event.getMessage();
    if (!player.getCurrentServer().isPresent()) {
        return;
    }
    String newMessage = event.getMessage();
    boolean hasInteractiveChat = false;
    BackendInteractiveChatData data = serverInteractiveChatInfo.get(player.getCurrentServer().get().getServerInfo().getName());
    if (data != null) {
        hasInteractiveChat = data.hasInteractiveChat();
    }
    boolean usage = false;
    outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
        for (ICPlaceholder icplaceholder : serverPlaceholders) {
            if (icplaceholder.getKeyword().matcher(message).find()) {
                usage = true;
                break outer;
            }
        }
    }
    if (newMessage.startsWith("/")) {
        if (usage && hasInteractiveChat) {
            for (String parsecommand : InteractiveChatVelocity.parseCommands) {
                if (newMessage.matches(parsecommand)) {
                    String command = newMessage.trim();
                    outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
                        for (ICPlaceholder icplaceholder : serverPlaceholders) {
                            Pattern placeholder = icplaceholder.getKeyword();
                            Matcher matcher = placeholder.matcher(command);
                            if (matcher.find()) {
                                String uuidmatch = "<cmd=" + uuid + ":" + Registry.ID_ESCAPE_PATTERN.matcher(command.substring(matcher.start(), matcher.end())).replaceAll("\\>") + ":>";
                                command = command.substring(0, matcher.start()) + uuidmatch + command.substring(matcher.end());
                                if (command.length() > 256) {
                                    command = command.substring(0, 256);
                                }
                                event.setResult(ChatResult.message(command));
                                break outer;
                            }
                        }
                    }
                    break;
                }
            }
        }
    } else {
        if (usage && InteractiveChatBungee.useAccurateSenderFinder && hasInteractiveChat) {
            outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
                for (ICPlaceholder icplaceholder : serverPlaceholders) {
                    Pattern placeholder = icplaceholder.getKeyword();
                    Matcher matcher = placeholder.matcher(message);
                    if (matcher.find()) {
                        String uuidmatch = "<chat=" + uuid + ":" + Registry.ID_ESCAPE_PATTERN.matcher(message.substring(matcher.start(), matcher.end())).replaceAll("\\>") + ":>";
                        message = message.substring(0, matcher.start()) + uuidmatch + message.substring(matcher.end());
                        if (message.length() > 256) {
                            message = message.substring(0, 256);
                        }
                        event.setResult(ChatResult.message(message));
                        break outer;
                    }
                }
            }
        }
        proxyServer.getScheduler().buildTask(plugin, () -> {
            Map<String, Long> messages = forwardedMessages.get(uuid);
            if (messages != null && messages.remove(newMessage) != null) {
                try {
                    PluginMessageSendingVelocity.sendMessagePair(uuid, newMessage);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).delay(100, TimeUnit.MILLISECONDS).schedule();
    }
}
Also used : Pattern(java.util.regex.Pattern) ConnectedPlayer(com.velocitypowered.proxy.connection.client.ConnectedPlayer) ParsePlayer(com.loohp.interactivechat.objectholders.CustomPlaceholder.ParsePlayer) Player(com.velocitypowered.api.proxy.Player) ICPlaceholder(com.loohp.interactivechat.objectholders.ICPlaceholder) Matcher(java.util.regex.Matcher) BackendInteractiveChatData(com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) ArrayList(java.util.ArrayList) IOException(java.io.IOException) UUID(java.util.UUID) Subscribe(com.velocitypowered.api.event.Subscribe)

Example 2 with BackendInteractiveChatData

use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.

the class CommandsVelocity method createBrigadierCommand.

public static void createBrigadierCommand() {
    LiteralCommandNode<CommandSource> backendinfoNode = LiteralArgumentBuilder.<CommandSource>literal("backendinfo").requires(sender -> {
        return sender.hasPermission("interactivechat.backendinfo");
    }).executes(command -> {
        try {
            CommandSource sender = command.getSource();
            if (InteractiveChatVelocity.hasPermission(sender, "interactivechat.backendinfo").get()) {
                InteractiveChatVelocity.sendMessage(sender, Component.text(TextColor.AQUA + "Proxy -> InteractiveChat: " + InteractiveChatVelocity.plugin.getDescription().getVersion() + " (PM Protocol: " + Registry.PLUGIN_MESSAGING_PROTOCOL_VERSION + ")"));
                InteractiveChatVelocity.sendMessage(sender, Component.text(TextColor.AQUA + "Expected latency: " + InteractiveChatVelocity.delay + " ms"));
                InteractiveChatVelocity.sendMessage(sender, Component.text(TextColor.AQUA + "Backends under this proxy:"));
                InteractiveChatVelocity.plugin.getServer().getAllServers().stream().sorted(Comparator.comparing(each -> each.getServerInfo().getName())).forEach(server -> {
                    String name = server.getServerInfo().getName();
                    BackendInteractiveChatData data = InteractiveChatVelocity.serverInteractiveChatInfo.get(name);
                    if (data == null) {
                        InteractiveChatVelocity.sendMessage(sender, Component.text(TextColor.RED + name + " -> Attempting to retrieve data from backend..."));
                    } else {
                        String minecraftVersion = data.getExactMinecraftVersion();
                        if (data.isOnline()) {
                            if (!data.hasInteractiveChat()) {
                                InteractiveChatVelocity.sendMessage(sender, Component.text(TextColor.YELLOW + name + " -> InteractiveChat: NOT INSTALLED (PM Protocol: -1) | Minecraft: " + minecraftVersion + " | Ping: " + (data.getPing() < 0 ? "N/A" : (data.getPing() + " ms"))));
                            } else {
                                InteractiveChatVelocity.sendMessage(sender, Component.text(TextColor.GREEN + name + " -> InteractiveChat: " + data.getVersion() + " (PM Protocol: " + data.getProtocolVersion() + ") | Minecraft: " + minecraftVersion + " | Ping: " + (data.getPing() < 0 ? "N/A" : (data.getPing() + " ms"))));
                            }
                        } else {
                            InteractiveChatVelocity.sendMessage(sender, Component.text(TextColor.RED + name + " -> Status: OFFLINE"));
                        }
                    }
                });
            }
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return 1;
    }).build();
    LiteralCommandNode<CommandSource> rootNode = LiteralArgumentBuilder.<CommandSource>literal("interactivechatproxy").then(backendinfoNode).executes(command -> {
        defaultMessage(command.getSource());
        return 1;
    }).build();
    LiteralCommandNode<CommandSource> aliasNode1 = LiteralArgumentBuilder.<CommandSource>literal("icp").then(backendinfoNode).executes(command -> {
        defaultMessage(command.getSource());
        return 1;
    }).build();
    BrigadierCommand command = new BrigadierCommand(rootNode);
    BrigadierCommand alias1 = new BrigadierCommand(aliasNode1);
    CommandManager commandManager = InteractiveChatVelocity.plugin.getServer().getCommandManager();
    commandManager.register(command);
    commandManager.register(alias1);
}
Also used : ExecutionException(java.util.concurrent.ExecutionException) TextComponent(net.kyori.adventure.text.TextComponent) LiteralCommandNode(com.mojang.brigadier.tree.LiteralCommandNode) CommandManager(com.velocitypowered.api.command.CommandManager) Component(net.kyori.adventure.text.Component) BackendInteractiveChatData(com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData) Registry(com.loohp.interactivechat.registry.Registry) BrigadierCommand(com.velocitypowered.api.command.BrigadierCommand) ClickEvent(net.kyori.adventure.text.event.ClickEvent) CommandSource(com.velocitypowered.api.command.CommandSource) Comparator(java.util.Comparator) LiteralArgumentBuilder(com.mojang.brigadier.builder.LiteralArgumentBuilder) CommandManager(com.velocitypowered.api.command.CommandManager) BackendInteractiveChatData(com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData) CommandSource(com.velocitypowered.api.command.CommandSource) BrigadierCommand(com.velocitypowered.api.command.BrigadierCommand)

Example 3 with BackendInteractiveChatData

use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.

the class InteractiveChatBungee method onPlayerConnected.

@EventHandler
public void onPlayerConnected(PostLoginEvent event) {
    if (!filtersAdded) {
        addFilters();
    }
    ProxiedPlayer player = event.getPlayer();
    forwardedMessages.put(player.getUniqueId(), new ConcurrentHashMap<>());
    if (player.hasPermission("interactivechat.backendinfo")) {
        String proxyVersion = plugin.getDescription().getVersion();
        for (BackendInteractiveChatData data : serverInteractiveChatInfo.values()) {
            if (data.isOnline() && data.getProtocolVersion() != Registry.PLUGIN_MESSAGING_PROTOCOL_VERSION) {
                String msg = ChatColor.RED + "[InteractiveChat] Warning: Backend Server " + data.getServer() + " is not running a version of InteractiveChat which has the same plugin messaging protocol version as the proxy!";
                Component text = LegacyComponentSerializer.legacySection().deserialize(msg);
                text = text.hoverEvent(HoverEvent.showText(LegacyComponentSerializer.legacySection().deserialize(ChatColor.YELLOW + "Proxy Version: " + proxyVersion + " (" + Registry.PLUGIN_MESSAGING_PROTOCOL_VERSION + ")\n" + ChatColor.RED + data.getServer() + " Version: " + data.getVersion() + " (" + data.getProtocolVersion() + ")")));
                sendMessage(player, text);
                sendMessage(ProxyServer.getInstance().getConsole(), text);
            }
        }
    }
    UserConnection userConnection = (UserConnection) player;
    ChannelWrapper channelWrapper;
    Field channelField = null;
    try {
        channelField = userConnection.getClass().getDeclaredField("ch");
        channelField.setAccessible(true);
        channelWrapper = (ChannelWrapper) channelField.get(userConnection);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        throw new RuntimeException(e);
    } finally {
        if (channelField != null) {
            channelField.setAccessible(false);
        }
    }
    ChannelPipeline pipeline = channelWrapper.getHandle().pipeline();
    pipeline.addBefore(PipelineUtils.BOSS_HANDLER, "interactivechat_interceptor", new ChannelDuplexHandler() {

        @Override
        public void write(ChannelHandlerContext channelHandlerContext, Object obj, ChannelPromise channelPromise) throws Exception {
            try {
                if (obj instanceof Chat) {
                    Chat packet = (Chat) obj;
                    String message = packet.getMessage();
                    byte position = packet.getPosition();
                    if ((position == 0 || position == 1) && message != null) {
                        if (message.contains("<QUxSRUFEWVBST0NFU1NFRA==>")) {
                            message = message.replace("<QUxSRUFEWVBST0NFU1NFRA==>", "");
                            if (Registry.ID_PATTERN.matcher(message).find()) {
                                message = Registry.ID_PATTERN.matcher(message).replaceAll("").trim();
                            }
                            packet.setMessage(message);
                        } else if (hasInteractiveChat(player.getServer())) {
                            messageForwardingHandler.processMessage(player.getUniqueId(), message, position);
                            return;
                        }
                    }
                }
            } catch (Throwable e) {
                e.printStackTrace();
            }
            super.write(channelHandlerContext, obj, channelPromise);
        }
    });
}
Also used : ProxiedPlayer(net.md_5.bungee.api.connection.ProxiedPlayer) BackendInteractiveChatData(com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData) ChannelWrapper(net.md_5.bungee.netty.ChannelWrapper) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ChannelPromise(io.netty.channel.ChannelPromise) UserConnection(net.md_5.bungee.UserConnection) ChannelPipeline(io.netty.channel.ChannelPipeline) IOException(java.io.IOException) Field(java.lang.reflect.Field) ChannelDuplexHandler(io.netty.channel.ChannelDuplexHandler) Chat(net.md_5.bungee.protocol.packet.Chat) InteractiveChat(com.loohp.interactivechat.InteractiveChat) Component(net.kyori.adventure.text.Component) EventHandler(net.md_5.bungee.event.EventHandler)

Example 4 with BackendInteractiveChatData

use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.

the class PluginMessageSendingBungee method sendPlayerListData.

public static void sendPlayerListData() throws IOException {
    ByteArrayDataOutput output = ByteStreams.newDataOutput();
    Collection<ProxiedPlayer> players = ProxyServer.getInstance().getPlayers();
    List<PlayerListPlayerData> dataList = new ArrayList<>();
    for (ProxiedPlayer player : players) {
        if (player.getServer() != null) {
            String server = player.getServer().getInfo().getName();
            BackendInteractiveChatData info = InteractiveChatBungee.serverInteractiveChatInfo.get(server);
            if (info != null && info.hasInteractiveChat()) {
                dataList.add(new PlayerListPlayerData(server, player.getUniqueId(), player.getName()));
            }
        }
    }
    output.writeInt(dataList.size());
    for (PlayerListPlayerData data : dataList) {
        DataTypeIO.writeString(output, data.getServer(), StandardCharsets.UTF_8);
        DataTypeIO.writeUUID(output, data.getUniqueId());
        DataTypeIO.writeString(output, data.getName(), StandardCharsets.UTF_8);
    }
    int packetNumber = InteractiveChatBungee.random.nextInt();
    int packetId = 0x00;
    byte[] data = output.toByteArray();
    byte[][] dataArray = CustomArrayUtils.divideArray(data, 32700);
    for (int i = 0; i < dataArray.length; i++) {
        byte[] chunk = dataArray[i];
        ByteArrayDataOutput out = ByteStreams.newDataOutput();
        out.writeInt(packetNumber);
        out.writeShort(packetId);
        out.writeBoolean(i == (dataArray.length - 1));
        out.write(chunk);
        for (ServerInfo server : ProxyServer.getInstance().getServers().values()) {
            if (!server.getPlayers().isEmpty()) {
                server.sendData("interchat:main", out.toByteArray());
                InteractiveChatBungee.pluginMessagesCounter.incrementAndGet();
            }
        }
    }
}
Also used : ProxiedPlayer(net.md_5.bungee.api.connection.ProxiedPlayer) ServerInfo(net.md_5.bungee.api.config.ServerInfo) ByteArrayDataOutput(com.google.common.io.ByteArrayDataOutput) ArrayList(java.util.ArrayList) BackendInteractiveChatData(com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData)

Example 5 with BackendInteractiveChatData

use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.

the class InteractiveChatVelocity method onPlayerConnected.

@Subscribe
public void onPlayerConnected(PostLoginEvent event) {
    if (!filtersAdded) {
        addFilters();
    }
    Player player = event.getPlayer();
    forwardedMessages.put(player.getUniqueId(), new ConcurrentHashMap<>());
    if (player.hasPermission("interactivechat.backendinfo")) {
        String proxyVersion = getDescription().getVersion();
        for (BackendInteractiveChatData data : serverInteractiveChatInfo.values()) {
            if (data.isOnline() && data.getProtocolVersion() != Registry.PLUGIN_MESSAGING_PROTOCOL_VERSION) {
                String msg = TextColor.RED + "[InteractiveChat] Warning: Backend Server " + data.getServer() + " is not running a version of InteractiveChat which has the same plugin messaging protocol version as the proxy!";
                HoverEvent<Component> hoverComponent = Component.text(TextColor.YELLOW + "Proxy Version: " + proxyVersion + " (" + Registry.PLUGIN_MESSAGING_PROTOCOL_VERSION + ")\n" + TextColor.RED + data.getServer() + " Version: " + data.getVersion() + " (" + data.getProtocolVersion() + ")").asHoverEvent();
                TextComponent text = Component.text(msg).hoverEvent(hoverComponent);
                sendMessage(player, text);
                sendMessage(getServer().getConsoleCommandSource(), text);
            }
        }
    }
    ConnectedPlayer userConnection = (ConnectedPlayer) player;
    ChannelPipeline pipeline = userConnection.getConnection().getChannel().pipeline();
    pipeline.addBefore(Connections.HANDLER, "interactivechat_interceptor", new ChannelDuplexHandler() {

        @Override
        public void write(ChannelHandlerContext channelHandlerContext, Object obj, ChannelPromise channelPromise) throws Exception {
            try {
                if (obj instanceof Chat) {
                    Chat packet = (Chat) obj;
                    String message = packet.getMessage();
                    byte position = packet.getType();
                    if ((position == 0 || position == 1) && message != null) {
                        if (message.contains("<QUxSRUFEWVBST0NFU1NFRA==>")) {
                            message = message.replace("<QUxSRUFEWVBST0NFU1NFRA==>", "");
                            if (Registry.ID_PATTERN.matcher(message).find()) {
                                message = Registry.ID_PATTERN.matcher(message).replaceAll("").trim();
                            }
                            packet.setMessage(message);
                        } else if (player.getCurrentServer().isPresent() && hasInteractiveChat(player.getCurrentServer().get().getServer())) {
                            messageForwardingHandler.processMessage(player.getUniqueId(), message, position);
                            return;
                        }
                    }
                }
            } catch (Throwable e) {
                e.printStackTrace();
            }
            super.write(channelHandlerContext, obj, channelPromise);
        }
    });
}
Also used : TextComponent(net.kyori.adventure.text.TextComponent) ConnectedPlayer(com.velocitypowered.proxy.connection.client.ConnectedPlayer) ParsePlayer(com.loohp.interactivechat.objectholders.CustomPlaceholder.ParsePlayer) Player(com.velocitypowered.api.proxy.Player) BackendInteractiveChatData(com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ChannelPromise(io.netty.channel.ChannelPromise) ConnectedPlayer(com.velocitypowered.proxy.connection.client.ConnectedPlayer) ChannelPipeline(io.netty.channel.ChannelPipeline) ParseException(org.json.simple.parser.ParseException) IOException(java.io.IOException) ChannelDuplexHandler(io.netty.channel.ChannelDuplexHandler) Chat(com.velocitypowered.proxy.protocol.packet.Chat) JSONObject(org.json.simple.JSONObject) TextComponent(net.kyori.adventure.text.TextComponent) Component(net.kyori.adventure.text.Component) Subscribe(com.velocitypowered.api.event.Subscribe)

Aggregations

BackendInteractiveChatData (com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData)12 IOException (java.io.IOException)8 ArrayList (java.util.ArrayList)6 ICPlaceholder (com.loohp.interactivechat.objectholders.ICPlaceholder)4 Player (com.velocitypowered.api.proxy.Player)4 List (java.util.List)4 UUID (java.util.UUID)4 AtomicLong (java.util.concurrent.atomic.AtomicLong)4 Matcher (java.util.regex.Matcher)4 Pattern (java.util.regex.Pattern)4 ProxiedPlayer (net.md_5.bungee.api.connection.ProxiedPlayer)4 ParsePlayer (com.loohp.interactivechat.objectholders.CustomPlaceholder.ParsePlayer)3 ConnectedPlayer (com.velocitypowered.proxy.connection.client.ConnectedPlayer)3 Component (net.kyori.adventure.text.Component)3 JSONObject (org.json.simple.JSONObject)3 ByteArrayDataOutput (com.google.common.io.ByteArrayDataOutput)2 MCVersion (com.loohp.interactivechat.utils.MCVersion)2 Subscribe (com.velocitypowered.api.event.Subscribe)2 ChannelDuplexHandler (io.netty.channel.ChannelDuplexHandler)2 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2