Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross Server support #202

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
7 changes: 7 additions & 0 deletions api/src/main/java/at/helpch/chatchat/api/channel/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ public interface Channel {
*/
int radius();

/**
* Check if this channel is cross server.
*
* @return True if this channel is cross server, false otherwise.
*/
boolean crossServer();

/**
* Get a set of {@link ChatUser}s that can see this channel.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ interface Builder<T extends Channel> {
@NotNull final List<String> toggleCommands,
@NotNull final String channelPrefix,
@NotNull final FormatsHolder formats,
final int radius);
final int radius,
final boolean crossServer);
}

/**
Expand Down
26 changes: 26 additions & 0 deletions plugin/src/main/java/at/helpch/chatchat/ChatChatPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
import at.helpch.chatchat.command.WhisperToggleCommand;
import at.helpch.chatchat.api.hook.Hook;
import at.helpch.chatchat.config.ConfigManager;
import at.helpch.chatchat.cs.receiver.BungeeMessageReceiver;
import at.helpch.chatchat.cs.receiver.RemoteMessageReceiver;
import at.helpch.chatchat.cs.sender.BungeeMessageSender;
import at.helpch.chatchat.cs.sender.RemoteMessageSender;
import at.helpch.chatchat.data.base.Database;
import at.helpch.chatchat.data.impl.gson.GsonDatabase;
import at.helpch.chatchat.hooks.HookManagerImpl;
Expand Down Expand Up @@ -53,6 +57,8 @@
import java.util.List;
import java.util.stream.Collectors;

import static at.helpch.chatchat.util.Constants.BUNGEE_CROSS_SERVER_CHANNEL;

@BukkitMain
public final class ChatChatPlugin extends JavaPlugin {

Expand All @@ -76,6 +82,9 @@ public final class ChatChatPlugin extends JavaPlugin {
private @NotNull
final ChatChatAPIImpl api = new ChatChatAPIImpl(this);

private RemoteMessageSender remoteMessageSender;
private RemoteMessageReceiver remoteMessageReceiver;


private static BukkitAudiences audiences;
private BukkitCommandManager<User> commandManager;
Expand All @@ -99,6 +108,12 @@ public void onEnable() {
hookManager.init();
configManager.reload();

// TODO: Make cross server type configurable
remoteMessageSender = new BungeeMessageSender(this);
remoteMessageReceiver = new BungeeMessageReceiver(this);
this.getServer().getMessenger().registerOutgoingPluginChannel(this, BUNGEE_CROSS_SERVER_CHANNEL);
this.getServer().getMessenger().registerIncomingPluginChannel(this, BUNGEE_CROSS_SERVER_CHANNEL, remoteMessageReceiver);

// bStats
Metrics metrics = new Metrics(this, 14781);
metrics.addCustomChart(new SimpleBarChart("channelTypes", () ->
Expand Down Expand Up @@ -142,6 +157,9 @@ public void onEnable() {

@Override
public void onDisable() {
this.getServer().getMessenger().unregisterOutgoingPluginChannel(this);
this.getServer().getMessenger().unregisterIncomingPluginChannel(this);

hookManager().hooks().forEach(Hook::disable);
hookManager().vanishHooks().forEach(Hook::disable);
hookManager().muteHooks().forEach(Hook::disable);
Expand Down Expand Up @@ -205,6 +223,14 @@ public static long cacheDuration() {
return api;
}

public @NotNull RemoteMessageSender remoteMessageSender() {
return remoteMessageSender;
}

public @NotNull RemoteMessageReceiver remoteMessageReceiver() {
return remoteMessageReceiver;
}

private void registerArguments() {
commandManager.registerArgument(PriorityFormat.class, (sender, argument) ->
configManager().formats().formats().get(argument));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,24 @@ public abstract class AbstractChannel implements Channel {

private final int radius;

private final boolean crossServer;

protected AbstractChannel(
@NotNull final String name,
@NotNull final String messagePrefix,
@NotNull final List<String> toggleCommands,
@NotNull final String channelPrefix,
@NotNull final FormatsHolder formats,
final int radius
final int radius,
final boolean crossServer
) {
this.name = name;
this.messagePrefix = messagePrefix;
this.toggleCommands = toggleCommands;
this.channelPrefix = channelPrefix;
this.formats = formats;
this.radius = radius;
this.crossServer = crossServer;
}

@Override
Expand Down Expand Up @@ -68,6 +72,11 @@ public int radius() {
return radius;
}

@Override
public boolean crossServer() {
return crossServer;
}

@Override
public boolean isUsableBy(@NotNull final ChatUser user) {
if (ChatChannel.defaultChannel().equals(this)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ public ChatChannel(
@NotNull final List<String> toggleCommands,
@NotNull final String channelPrefix,
@NotNull final FormatsHolder formats,
final int radius
final int radius,
final boolean crossServer
) {
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius);
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius, crossServer);
}

public static @NotNull Channel defaultChannel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import at.helpch.chatchat.placeholder.MiniPlaceholderContext;
import at.helpch.chatchat.user.ConsoleUser;
import at.helpch.chatchat.util.FormatUtils;
import at.helpch.chatchat.util.MessageProcessor;
import at.helpch.chatchat.processor.LocalToLocalMessageProcessor;
import dev.triumphteam.cmd.bukkit.annotation.Permission;
import dev.triumphteam.cmd.core.annotation.Join;
import dev.triumphteam.cmd.core.annotation.SubCommand;
Expand Down Expand Up @@ -39,7 +39,7 @@ public void testFormat(
format,
sender.player(),
sender.player(),
MessageProcessor.processMessage(plugin, sender, ConsoleUser.INSTANCE, message),
LocalToLocalMessageProcessor.processMessage(plugin, sender, ConsoleUser.INSTANCE, message),
plugin.miniPlaceholdersManager().compileTags(MiniPlaceholderContext.builder().inMessage(false).sender(sender).recipient(sender).build())
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
public final class MainCommand extends ChatChatCommand {

private static final JavaPlugin PLUGIN = JavaPlugin.getProvidingPlugin(ChatChatPlugin.class);
private static final Component TEXT = MessageUtils.parseToMiniMessage(
private static final Component TEXT = MessageUtils.parseFromMiniMessage(
"<aqua><click:open_url:'https://helpch.at'>A Chat Plugin <gray>by <#3dbbe4>Help<#f3af4b>Chat<br><gray>Version: <aqua>" + PLUGIN.getDescription().getVersion());

@Default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import at.helpch.chatchat.ChatChatPlugin;
import at.helpch.chatchat.api.user.ChatUser;
import at.helpch.chatchat.hooks.towny.AbstractTownyChannel;
import at.helpch.chatchat.util.MessageProcessor;
import at.helpch.chatchat.processor.MessageProcessor;
import com.palmergames.bukkit.towny.TownyUniverse;
import com.palmergames.bukkit.towny.object.Resident;
import dev.triumphteam.cmd.core.BaseCommand;
Expand Down Expand Up @@ -57,6 +57,6 @@ public void switchChannel(final ChatUser user, @Join @Optional @NotNull final St
return;
}

MessageProcessor.process(plugin, user, channel, message, false);
MessageProcessor.processMessageEvent(plugin, user, channel, message, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ public final class DefaultConfigObjects {

public static @NotNull Channel createDefaultChannel() {
return new ChatChannel("default", "",
List.of("global"), "<gray>[<blue>Global<gray>]", new FormatsHolderImpl(), -1);
List.of("global"), "<gray>[<blue>Global<gray>]", new FormatsHolderImpl(), -1, false);
}

public static @NotNull Channel createStaffChannel() {
return new ChatChannel("staff", "@",
List.of("staffchat"), "<gray>[<green>Staff<gray>]", new FormatsHolderImpl(), -1);
List.of("staffchat"), "<gray>[<green>Staff<gray>]", new FormatsHolderImpl(), -1, false);
}

public static @NotNull SimpleFormat createDefaultConsoleFormat() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public final class ChannelMapper implements TypeSerializer<Channel> {
private static final String CHANNEL_PREFIX = "channel-prefix";
private static final String FORMATS = "formats";
private static final String RADIUS = "radius";
private static final String CROSS_SERVER = "cross-server";
private static final String TYPE = "type";
private static final TypeToken<Map<String, PriorityFormat>> FORMATS_MAP_TYPE = new TypeToken<>() {};

Expand Down Expand Up @@ -55,6 +56,7 @@ public Channel deserialize(Type type, ConfigurationNode node) throws Serializati
final var formatsMap = node.node(FORMATS).get(FORMATS_MAP_TYPE, Map.of());
final var formats = new FormatsHolderImpl(formatsMap);
final var radius = node.node(RADIUS).getInt(-1);
final var crossServer = node.node(CROSS_SERVER).getBoolean(false);

final var channelType = node.node(TYPE).getString("default").toLowerCase();

Expand All @@ -63,7 +65,7 @@ public Channel deserialize(Type type, ConfigurationNode node) throws Serializati
throw new SerializationException("Channel " + key + " has unknown channel type " + channelType + ", " +
"ignoring.");
}
return builder.build(key, messagePrefix, commandName, channelPrefix, formats, radius);
return builder.build(key, messagePrefix, commandName, channelPrefix, formats, radius, crossServer);
}

@Override
Expand All @@ -78,5 +80,6 @@ public void serialize(Type type, @Nullable Channel channel, ConfigurationNode ta
target.node(CHANNEL_PREFIX).set(channel.channelPrefix());
target.node(FORMATS).set(channel.formats().formats());
target.node(RADIUS).set(channel.radius());
target.node(CROSS_SERVER).set(channel.crossServer());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package at.helpch.chatchat.cs.receiver;

import at.helpch.chatchat.ChatChatPlugin;
import at.helpch.chatchat.processor.RemoteToLocalMessageProcessor;
import at.helpch.chatchat.util.Constants;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.logging.Level;

import static at.helpch.chatchat.util.Constants.BUNGEE_CROSS_SERVER_CHANNEL;
import static at.helpch.chatchat.util.Constants.CROSS_SERVER_SUB_CHANNEL;

public class BungeeMessageReceiver implements RemoteMessageReceiver {

private final @NotNull ChatChatPlugin plugin;

public BungeeMessageReceiver(final @NotNull ChatChatPlugin plugin) {
this.plugin = plugin;
}

@Override
public void onPluginMessageReceived(final @NotNull String channel, @NotNull Player player, final byte[] message) {
if (!channel.equals(BUNGEE_CROSS_SERVER_CHANNEL)) return;

final ByteArrayDataInput in = ByteStreams.newDataInput(message);
final String subChannel = in.readUTF();

if (!subChannel.equals(CROSS_SERVER_SUB_CHANNEL)) return;

final short length = in.readShort();
final byte[] messageBytes = new byte[length];
in.readFully(messageBytes);

final DataInputStream messageIn = new DataInputStream(new ByteArrayInputStream(messageBytes));
try {
final String messageType = messageIn.readUTF();
if (!messageType.equals(Constants.PUBLIC_MESSAGE_TYPE) && !messageType.equals(Constants.PRIVATE_MESSAGE_TYPE)) {
plugin.getLogger().warning("Got cross server message but the message type was invalid: " + messageType);
return;
}

// TODO: Add private message support

final String channelName = messageIn.readUTF();
final String messageContent = messageIn.readUTF();

RemoteToLocalMessageProcessor.processRemoteMessageEvent(plugin, channelName, messageContent);

} catch (final IOException exception) {
plugin.getLogger().log(Level.WARNING, "Got cross server message but could not read it.", exception);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package at.helpch.chatchat.cs.receiver;

import org.bukkit.plugin.messaging.PluginMessageListener;

public interface RemoteMessageReceiver extends PluginMessageListener {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package at.helpch.chatchat.cs.sender;

import at.helpch.chatchat.ChatChatPlugin;
import at.helpch.chatchat.util.Constants;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.logging.Level;

import static at.helpch.chatchat.util.Constants.BUNGEE_CROSS_SERVER_CHANNEL;
import static at.helpch.chatchat.util.Constants.CROSS_SERVER_SUB_CHANNEL;

public class BungeeMessageSender implements RemoteMessageSender {
private final @NotNull ChatChatPlugin plugin;

public BungeeMessageSender(final @NotNull ChatChatPlugin plugin) {
this.plugin = plugin;
}

@Override
public boolean send(String channel, String message) {
final ByteArrayDataOutput out = ByteStreams.newDataOutput();

out.writeUTF("Forward");
out.writeUTF("ALL");
out.writeUTF(CROSS_SERVER_SUB_CHANNEL);

final ByteArrayOutputStream messageBytes = new ByteArrayOutputStream();
final DataOutputStream messageOut = new DataOutputStream(messageBytes);

try {
messageOut.writeUTF(Constants.PUBLIC_MESSAGE_TYPE);
messageOut.writeUTF(channel);
messageOut.writeUTF(message);
} catch (final IOException exception){
plugin.getLogger().log(Level.WARNING, "Could not write cross server message.", exception);
return false;
}

out.writeShort(messageBytes.toByteArray().length);
out.write(messageBytes.toByteArray());

Bukkit.getServer().sendPluginMessage(plugin, BUNGEE_CROSS_SERVER_CHANNEL, out.toByteArray());
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package at.helpch.chatchat.cs.sender;

public interface RemoteMessageSender {
boolean send(String channel, String message);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ protected AbstractTownyChannel(@NotNull final String name,
@NotNull final List<String> toggleCommands,
@NotNull final String channelPrefix,
@NotNull final FormatsHolder formats,
final int radius) {
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius);
final int radius,
final boolean crossServer) {
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius, crossServer);
if (Bukkit.getPluginManager().getPlugin("Towny") == null) {
throw new RuntimeException("Attempting to use a Towny channel but Towny is not installed.");
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ public TownyNationChannel(@NotNull final String name,
@NotNull final List<String> toggleCommands,
@NotNull final String channelPrefix,
@NotNull final FormatsHolder formats,
final int radius) {
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius);
final int radius,
final boolean crossServer) {
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius, crossServer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ public TownyTownChannel(@NotNull final String name,
@NotNull final List<String> toggleCommands,
@NotNull final String channelPrefix,
@NotNull final FormatsHolder formats,
final int radius) {
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius);
final int radius,
final boolean crossServer) {
super(name, messagePrefix, toggleCommands, channelPrefix, formats, radius, crossServer);
}

@Override
Expand Down
Loading