Start working on the API before adding the server implementation

This commit is contained in:
len
2021-05-10 10:01:35 +02:00
parent 80afee0f2f
commit 0d15c40cb7
22 changed files with 658 additions and 205 deletions
+121
View File
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<parent>
<groupId>com.alttd.chat</groupId>
<artifactId>Chat</artifactId>
<version>1.0</version>
</parent>
<artifactId>velocity-chat</artifactId>
<packaging>jar</packaging>
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>${project.name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>net.kyori:*</artifact>
<excludes>
<exclude>META-INF/*.MF</exclude>
</excludes>
</filter>
</filters>
<artifactSet>
<includes>
<include>net.kyori:adventure-text-minimessage</include>
</includes>
<excludes>
<exclude>META-INF/*.MF</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>velocitypowered-repo</id>
<url>https://repo.velocitypowered.com/releases/</url>
</repository>
<repository>
<id>minecraft-libraries</id>
<url>https://libraries.minecraft.net/</url>
</repository>
<repository>
<id>jcenter</id>
<name>jcenter-bintray</name>
<url>https://jcenter.bintray.com</url>
</repository>
<repository> <!-- MiniMessage -->
<id>sonatype-oss-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>1.1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.luckperms</groupId>
<artifactId>api</artifactId>
<version>5.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alttd.chat</groupId>
<artifactId>chat-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,86 @@
package com.alttd.chat;
import com.alttd.chat.commands.GlobalAdminChat;
import com.alttd.chat.commands.GlobalChat;
import com.alttd.chat.commands.GlobalChatToggle;
import com.alttd.chat.config.Config;
import com.alttd.chat.handlers.ChatHandler;
import com.alttd.chat.listeners.ChatListener;
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Dependency;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import org.slf4j.Logger;
import java.io.File;
import java.nio.file.Path;
@Plugin(id = "chatplugin", name = "ChatPlugin", version = "1.0.0",
description = "A chat plugin for Altitude Minecraft Server",
authors = {"destro174", "teri"},
dependencies = {@Dependency(id = "luckperms")}
)
public class ChatPlugin {
private static ChatPlugin plugin;
private final ProxyServer server;
private final Logger logger;
private final Path dataDirectory;
private ChatAPI chatAPI;
private ChatHandler chatHandler;
@Inject
public ChatPlugin(ProxyServer proxyServer, Logger proxyLogger, @DataDirectory Path proxydataDirectory) {
plugin = this;
server = proxyServer;
logger = proxyLogger;
dataDirectory = proxydataDirectory;
}
@Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) {
Config.init(getDataDirectory());
loadCommands();
chatAPI = new ChatImplementation();
chatHandler = new ChatHandler();
server.getEventManager().register(this, new ChatListener());
}
public File getDataDirectory() {
return dataDirectory.toFile();
}
public static ChatPlugin getPlugin() {
return plugin;
}
public Logger getLogger() {
return logger;
}
public ProxyServer getProxy() {
return server;
}
public void loadCommands() {
new GlobalAdminChat(server);
new GlobalChatToggle(server);
new GlobalChat(server);
// all commands go here
}
public ChatAPI API() {
return chatAPI;
}
public ChatHandler getChatHandler() {
return chatHandler;
}
}
@@ -0,0 +1,21 @@
package com.alttd.chat.api;
import com.velocitypowered.api.command.CommandSource;
public class GlobalStaffChatEvent {
private final CommandSource sender;
private final String message;
public GlobalStaffChatEvent(CommandSource sender, String message) {
this.sender = sender;
this.message = message;
}
public CommandSource getSender() {
return sender;
}
public String getMessage() {
return message;
}
}
@@ -0,0 +1,29 @@
package com.alttd.chat.api;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
public class MessageEvent {
private final CommandSource sender;
private final Player recipient;
private final String message;
public MessageEvent(CommandSource sender, Player recipient, String message) {
this.sender = sender;
this.recipient = recipient;
this.message = message;
}
public CommandSource getSender() {
return sender;
}
public Player getRecipient() {
return recipient;
}
public String getMessage() {
return message;
}
}
@@ -0,0 +1,42 @@
package com.alttd.chat.commands;
import com.alttd.chat.api.GlobalStaffChatEvent;
import com.alttd.chat.config.Config;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.ProxyServer;
public class GlobalAdminChat {
public GlobalAdminChat(ProxyServer proxyServer) {
LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("globaladminchat")
.requires(ctx -> ctx.hasPermission("command.proxy.globaladminchat"))// TODO permission system? load permissions from config?
.then(RequiredArgumentBuilder
.<CommandSource, String>argument("message", StringArgumentType.greedyString())
.executes(context -> {
proxyServer.getEventManager().fire(new GlobalStaffChatEvent(context.getSource(), context.getArgument("message", String.class)));
return 1;
}) // TODO call in the same way as gc?
)
.executes(context -> 0)
.build();
BrigadierCommand brigadierCommand = new BrigadierCommand(command);
CommandMeta.Builder metaBuilder = proxyServer.getCommandManager().metaBuilder(brigadierCommand);
for (String alias : Config.GACECOMMANDALIASES) {
metaBuilder.aliases(alias);
}
CommandMeta meta = metaBuilder.build();
proxyServer.getCommandManager().register(meta, brigadierCommand);
}
}
@@ -0,0 +1,43 @@
package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.config.Config;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.ProxyServer;
public class GlobalChat {
public GlobalChat(ProxyServer proxyServer) {
LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("globalchat")
.requires(ctx -> ctx.hasPermission(Config.GCPERMISSION))
.requires(ctx -> ctx.hasPermission("command.proxy.globalchat"))// TODO permission system? load permissions from config?
.then(RequiredArgumentBuilder
.<CommandSource, String>argument("message", StringArgumentType.greedyString())
.executes(context -> {
ChatPlugin.getPlugin().getChatHandler().globalChat(context.getSource(), context.getArgument("message", String.class));
return 1;
})
)
.executes(context -> 0)
.build();
BrigadierCommand brigadierCommand = new BrigadierCommand(command);
CommandMeta.Builder metaBuilder = proxyServer.getCommandManager().metaBuilder(brigadierCommand);
for (String alias : Config.GCCOMMANDALIASES) {
metaBuilder.aliases(alias);
}
CommandMeta meta = metaBuilder.build();
proxyServer.getCommandManager().register(meta, brigadierCommand);
}
}
@@ -0,0 +1,51 @@
package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.config.Config;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.node.Node;
public class GlobalChatToggle {
public GlobalChatToggle(ProxyServer proxyServer) {
LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("toggleglobalchat")
.requires(ctx -> ctx instanceof Player)
.requires(ctx -> ctx.hasPermission("command.proxy.globalchat"))// TODO permission system? load permissions from config?
.then(RequiredArgumentBuilder
.<CommandSource, String>argument("message", StringArgumentType.greedyString())
.executes(context -> {
LuckPerms luckPerms = ChatPlugin.getPlugin().API().getLuckPerms();
Player player = (Player) context;
luckPerms.getUserManager().modifyUser(player.getUniqueId(), user -> {
if(player.hasPermission(Config.GCPERMISSION)) { //TODO THIS MUST BE A CONSTANT FROM CONFIG?
user.data().add(Node.builder(Config.GCPERMISSION).build());
} else {
user.data().remove(Node.builder(Config.GCPERMISSION).build());
}
});
return 1;
})
)
.executes(context -> 0)
.build();
BrigadierCommand brigadierCommand = new BrigadierCommand(command);
CommandMeta.Builder metaBuilder = proxyServer.getCommandManager().metaBuilder(brigadierCommand);
metaBuilder.aliases("togglegc");
CommandMeta meta = metaBuilder.build();
proxyServer.getCommandManager().register(meta, brigadierCommand);
}
}
@@ -0,0 +1,65 @@
package com.alttd.chat.commands;
import com.alttd.chat.api.MessageEvent;
import com.alttd.chat.config.Config;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import java.util.Optional;
public class Message {
public Message(ProxyServer proxyServer) {
LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("message")
.requires(ctx -> ctx.hasPermission("command.proxy.message"))// TODO permission system? load permissions from config?
.then(RequiredArgumentBuilder
.<CommandSource, String>argument("player", StringArgumentType.word())
.suggests((context, builder) -> {
for (Player player : proxyServer.getAllPlayers()) {
builder.suggest(player.getGameProfile().getName());
}
return builder.buildFuture();
})
.then(RequiredArgumentBuilder
.<CommandSource, String>argument("message", StringArgumentType.greedyString())
.executes(context -> {
Optional<Player> playerOptional = proxyServer.getPlayer(context.getArgument("player", String.class));
if (playerOptional.isPresent()) {
Player receiver = playerOptional.get();
proxyServer.getEventManager().fire(new MessageEvent(context.getSource(), receiver, context.getArgument("message", String.class)));
return 1;
} else {
// TODO NOBODY TO REPLY TO
}
return 0;
})
)
.executes(context -> 0)
)
.executes(context -> 0)
.build();
BrigadierCommand brigadierCommand = new BrigadierCommand(command);
CommandMeta.Builder metaBuilder = proxyServer.getCommandManager().metaBuilder(brigadierCommand);
for (String alias : Config.MESSAGECOMMANDALIASES) {
metaBuilder.aliases(alias);
}
CommandMeta meta = metaBuilder.build();
proxyServer.getCommandManager().register(meta, brigadierCommand);
}
}
@@ -0,0 +1,190 @@
package com.alttd.chat.config;
import com.alttd.chat.ChatPlugin;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
import org.yaml.snakeyaml.DumperOptions;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
public final class Config {
private static final Pattern PATH_PATTERN = Pattern.compile("\\.");
private static final String HEADER = "";
private static File CONFIG_FILE;
public static ConfigurationNode config;
public static YAMLConfigurationLoader configLoader;
static int version;
static boolean verbose;
public static void init(File path) {
CONFIG_FILE = new File(path, "config.yml");;
configLoader = YAMLConfigurationLoader.builder()
.setFile(CONFIG_FILE)
.setFlowStyle(DumperOptions.FlowStyle.BLOCK)
.build();
if (!CONFIG_FILE.getParentFile().exists()) {
if(!CONFIG_FILE.getParentFile().mkdirs()) {
ChatPlugin.getPlugin().getLogger().error("Could create config and/or directory");
return;
}
}
if (!CONFIG_FILE.exists()) {
try {
if(!CONFIG_FILE.createNewFile()) {
ChatPlugin.getPlugin().getLogger().error("Could create config and/or directory");
return;
}
} catch (IOException error) {
error.printStackTrace();
}
}
try {
config = configLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
configLoader.getDefaultOptions().setHeader(HEADER);
configLoader.getDefaultOptions().withShouldCopyDefaults(true);
verbose = getBoolean("verbose", true);
version = getInt("config-version", 1);
readConfig(Config.class, null);
try {
configLoader.save(config);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void readConfig(Class<?> clazz, Object instance) {
for (Method method : clazz.getDeclaredMethods()) {
if (Modifier.isPrivate(method.getModifiers())) {
if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) {
try {
method.setAccessible(true);
method.invoke(instance);
} catch (InvocationTargetException | IllegalAccessException ex) {
throw Throwables.propagate(ex.getCause());
}
}
}
}
try {
configLoader.save(config);
} catch (IOException ex) {
throw Throwables.propagate(ex.getCause());
}
}
public static void saveConfig() {
try {
configLoader.save(config);
} catch (IOException ex) {
throw Throwables.propagate(ex.getCause());
}
}
private static Object[] splitPath(String key) {
return PATH_PATTERN.split(key);
}
private static void set(String path, Object def) {
if(config.getNode(splitPath(path)).isVirtual())
config.getNode(splitPath(path)).setValue(def);
}
private static void setString(String path, String def) {
try {
if(config.getNode(splitPath(path)).isVirtual())
config.getNode(splitPath(path)).setValue(TypeToken.of(String.class), def);
} catch(ObjectMappingException ex) {
}
}
private static boolean getBoolean(String path, boolean def) {
set(path, def);
return config.getNode(splitPath(path)).getBoolean(def);
}
private static double getDouble(String path, double def) {
set(path, def);
return config.getNode(splitPath(path)).getDouble(def);
}
private static int getInt(String path, int def) {
set(path, def);
return config.getNode(splitPath(path)).getInt(def);
}
private static String getString(String path, String def) {
setString(path, def);
return config.getNode(splitPath(path)).getString(def);
}
private static Long getLong(String path, Long def) {
set(path, def);
return config.getNode(splitPath(path)).getLong(def);
}
private static <T> List<String> getList(String path, T def) {
try {
set(path, def);
return config.getNode(splitPath(path)).getList(TypeToken.of(String.class));
} catch(ObjectMappingException ex) {
}
return new ArrayList<>();
}
/** ONLY EDIT ANYTHING BELOW THIS LINE **/
public static List<String> PREFIXGROUPS = new ArrayList<>();
private static void settings() {
PREFIXGROUPS = getList("settings.prefix-groups",
Lists.newArrayList("discord", "socialmedia", "eventteam", "eventleader", "youtube", "twitch", "developer"));
}
public static List<String> MESSAGECOMMANDALIASES = new ArrayList<>();
public static List<String> REPLYCOMMANDALIASES = new ArrayList<>();
public static String MESSAGESENDER = "<hover:show_text:Click to reply><click:suggest_command:/msg <receiver> ><light_purple>(Me -> <gray><receiver></gray>) <message></light_purple>";
public static String MESSAGERECIEVER = "<hover:show_text:Click to reply><click:suggest_command:/msg <sender> ><light_purple>(<gray><sender></gray> on <server> -> Me) <message></light_purple>";
private static void messageCommand() {
MESSAGECOMMANDALIASES.clear();
REPLYCOMMANDALIASES.clear();
MESSAGECOMMANDALIASES = getList("commands.message.aliases", Lists.newArrayList("msg", "whisper", "tell"));
REPLYCOMMANDALIASES = getList("commands.reply.aliases", Lists.newArrayList("r"));
MESSAGESENDER = getString("commands.message.sender-message", MESSAGESENDER);
MESSAGERECIEVER = getString("commands.message.reciever-message", MESSAGERECIEVER);
}
public static List<String> GCCOMMANDALIASES = new ArrayList<>();
public static String GCFORMAT = "<white><light_purple><prefix></light_purple> <gray><sender></gray> <hover:show_text:on <server>><yellow>to Global</yellow></hover><gray>: <message></gray></white>";
public static String GCPERMISSION = "proxy.globalchat";
private static void globalChat() {
MESSAGERECIEVER = getString("commands.globalchat.format", MESSAGERECIEVER);
GCPERMISSION = getString("commands.globalchat.view-chat-permission", GCPERMISSION);
GCCOMMANDALIASES = getList("commands.globalchat.aliases", Lists.newArrayList("gc"));
}
public static List<String> GACECOMMANDALIASES = new ArrayList<>();
public static String GACFORMAT = "<hover:show_text:Click to reply><click:suggest_command:/msg <sender> ><yellow>(<sender> on <server> -> Team) <message></yellow>";
private static void globalAdminChat() {
GACECOMMANDALIASES = getList("commands.globaladminchat.aliases", Lists.newArrayList("acg"));
GACFORMAT = getString("commands.globaladminchat.format", GACFORMAT);
}
}
@@ -0,0 +1,71 @@
package com.alttd.chat.config;
import com.google.common.reflect.TypeToken;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import java.util.regex.Pattern;
public final class ServerConfig {
private static final Pattern PATH_PATTERN = Pattern.compile("\\.");
private final String serverName;
private final String configPath;
private final String defaultPath;
public ServerConfig(String serverName) {
this.serverName = serverName;
this.configPath = "server-settings." + this.serverName + ".";
this.defaultPath = "server-settings.default.";
init();
}
public void init() {
Config.readConfig(ServerConfig.class, this);
Config.saveConfig();
}
public static Object[] splitPath(String key) {
return PATH_PATTERN.split(key);
}
private static void set(String path, Object def) {
if(Config.config.getNode(splitPath(path)).isVirtual()) {
Config.config.getNode(splitPath(path)).setValue(def);
}
}
private static void setString(String path, String def) {
try {
if(Config.config.getNode(splitPath(path)).isVirtual())
Config.config.getNode(splitPath(path)).setValue(TypeToken.of(String.class), def);
} catch(ObjectMappingException ex) {
}
}
private boolean getBoolean(String path, boolean def) {
set(defaultPath +path, def);
return Config.config.getNode(splitPath(configPath+path)).getBoolean(
Config.config.getNode(splitPath(defaultPath +path)).getBoolean(def));
}
private double getDouble(String path, double def) {
set(defaultPath +path, def);
return Config.config.getNode(splitPath(configPath+path)).getDouble(
Config.config.getNode(splitPath(defaultPath +path)).getDouble(def));
}
private int getInt(String path, int def) {
set(defaultPath +path, def);
return Config.config.getNode(splitPath(configPath+path)).getInt(
Config.config.getNode(splitPath(defaultPath +path)).getInt(def));
}
private String getString(String path, String def) {
set(defaultPath +path, def);
return Config.config.getNode(splitPath(configPath+path)).getString(
Config.config.getNode(splitPath(defaultPath +path)).getString(def));
}
/** DO NOT EDIT ANYTHING ABOVE **/
}
@@ -0,0 +1,132 @@
package com.alttd.chat.handlers;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.config.Config;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.model.group.Group;
import net.luckperms.api.model.user.User;
import java.util.*;
public class ChatHandler {
private List<ChatPlayer> chatPlayers;
public ChatHandler() {
chatPlayers = new ArrayList<>();
}
public void addPlayer(ChatPlayer chatPlayer) {
chatPlayers.add(chatPlayer);
}
public void removePlayer(ChatPlayer chatPlayer) {
if(chatPlayer != null)
chatPlayers.remove(chatPlayer);
}
public void removePlayer(UUID uuid) {
removePlayer(getChatPlayer(uuid));
}
public ChatPlayer getChatPlayer(UUID uuid) {
for(ChatPlayer p: chatPlayers) {
if(p.getUuid() == uuid)
return p;
}
return null;
}
public List<ChatPlayer> getChatPlayers() {
return Collections.unmodifiableList(chatPlayers);
}
public void globalChat(CommandSource source, String message) {
String senderName, serverName, prefix;
Map<String, String> map = new HashMap<>();
if (source instanceof Player) {
Player sender = (Player) source;
senderName = sender.getUsername();
serverName = sender.getCurrentServer().isPresent() ? sender.getCurrentServer().get().getServerInfo().getName() : "Altitude";
prefix = getPrefix(sender);
} else {
senderName = "Console"; // TODO console name from config
serverName = "Altitude";
prefix = "";
}
MiniMessage miniMessage = MiniMessage.get();
map.put("sender", senderName);
map.put("message", message);
map.put("server", serverName);
map.put("prefix", prefix);
Component component = miniMessage.parse(Config.GCFORMAT, map);
for(Player p: ChatPlugin.getPlugin().getProxy().getAllPlayers()) {
if(p.hasPermission(Config.GCPERMISSION));
p.sendMessage(component);
//TODO send global chat with format from config
}
}
/**
* returns a component containing all prefixes a player has.
*
* @param player the player
* @return a prefix component
*/
public String getPrefix(Player player) {
return getPrefix(player, false);
}
/**
* returns a component containing all or only the highest prefix a player has.
*
* @param player the player
* @param highest
* @return a prefix component
*/
public String getPrefix(Player player, boolean highest) {
// TODO cache these components on load, and return them here?
StringBuilder prefix = new StringBuilder();
LuckPerms luckPerms = ChatPlugin.getPlugin().API().getLuckPerms();
User user = luckPerms.getUserManager().getUser(player.getUniqueId());
if(user == null) return "";
if(!highest) {
Collection<Group> inheritedGroups = user.getInheritedGroups(user.getQueryOptions());
inheritedGroups.stream()
.sorted(Comparator.comparingInt(o -> o.getWeight().orElse(0)))
.forEach(group -> {
if (Config.PREFIXGROUPS.contains(group.getName())) {
prefix.append("<white>[").append(group.getCachedData().getMetaData().getPrefix()).append("]</white>");
}
});
}
LegacyComponentSerializer.builder().character('&').hexColors();
prefix.append("<white>[").append(user.getCachedData().getMetaData().getPrefix()).append("]</white>");
/*component= MiniMessage.get().parse(prefix.toString());
CompletableFuture<User> userFuture = luckPerms.getUserManager().loadUser(player.getUniqueId());
userFuture.thenAcceptAsync(user -> {
Collection<Group> inheritedGroups = user.getInheritedGroups(user.getQueryOptions());
inheritedGroups.stream()
.sorted((o1, o2) -> Integer.compare(o1.getWeight().orElse(0), o2.getWeight().orElse(0)))
.forEach(group -> {
if(Config.PREFIXGROUPS.contains(group.getName())) {
prefix.append("<white>[").append(group.getCachedData().getMetaData().getPrefix()).append("]</white>");
}
});
return MiniMessage.get().parse(prefix.toString());
});*/
//return MiniMessage.get().parse(prefix.toString());
return prefix.toString();
}
}
@@ -0,0 +1,40 @@
package com.alttd.chat.handlers;
import com.velocitypowered.api.proxy.Player;
import java.util.UUID;
public class ChatPlayer {
private UUID uuid;
private Player player;
private UUID replyTarget;
private boolean globalChatEnabled;
public ChatPlayer(Player p) {
player = p;
uuid = p.getUniqueId();
replyTarget = null;
}
public UUID getUuid() {
return uuid;
}
public Player getPlayer() {
return player;
}
public boolean isGlobalChatEnabled() {
return globalChatEnabled;
}
public UUID getReplyTarget() {
return replyTarget;
}
public void setReplyTarget(UUID uuid) {
if(!replyTarget.equals(uuid))
replyTarget = uuid;
}
}
@@ -0,0 +1,91 @@
package com.alttd.chat.listeners;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.api.GlobalStaffChatEvent;
import com.alttd.chat.api.MessageEvent;
import com.alttd.chat.config.Config;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.player.PlayerChatEvent;
import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import java.util.HashMap;
import java.util.Map;
// TODO code CLEANUP
public class ChatListener {
private ChatPlugin plugin;
public ChatListener() {
plugin = ChatPlugin.getPlugin();
}
@Subscribe(order = PostOrder.FIRST)
public void onMessage(MessageEvent event) {
String senderName;
String receiverName;
CommandSource commandSource = event.getSender();
if (commandSource instanceof Player) {
Player sender = (Player) event.getSender();
senderName = sender.getUsername();
plugin.getChatHandler().getChatPlayer(sender.getUniqueId()).setReplyTarget(event.getRecipient().getUniqueId()); // TODO this needs to be cleaner
} else {
senderName = "Console"; // TODO console name from config
}
receiverName = event.getRecipient().getUsername();
MiniMessage miniMessage = MiniMessage.get();
Map<String, String> map = new HashMap<>();
map.put("sender", senderName);
map.put("receiver", receiverName);
map.put("message", event.getMessage());
map.put("server", event.getRecipient().getCurrentServer().isPresent() ? event.getRecipient().getCurrentServer().get().getServerInfo().getName() : "Altitude");
Component senderMessage = miniMessage.parse(Config.MESSAGESENDER, map);
Component receiverMessage = miniMessage.parse(Config.MESSAGERECIEVER, map);
event.getSender().sendMessage(senderMessage);
event.getRecipient().sendMessage(receiverMessage);
}
@Subscribe(order = PostOrder.FIRST)
public void onGlobalStaffChat(GlobalStaffChatEvent event) {
String senderName;
String serverName;
CommandSource commandSource = event.getSender();
if (commandSource instanceof Player) {
Player sender = (Player) event.getSender();
senderName = sender.getUsername();
serverName = sender.getCurrentServer().isPresent() ? sender.getCurrentServer().get().getServerInfo().getName() : "Altitude";
} else {
senderName = "Console"; // TODO console name from config
serverName = "Proxy";
}
MiniMessage miniMessage = MiniMessage.get();
Map<String, String> map = new HashMap<>();
map.put("sender", senderName);
map.put("message", event.getMessage());
map.put("server", serverName);
Component message = miniMessage.parse(Config.GACFORMAT, map);
plugin.getProxy().getAllPlayers().stream().filter(target -> target.hasPermission("command.proxy.globaladminchat")).forEach(target -> {
target.sendMessage(message);
});
}
@Subscribe(order = PostOrder.FIRST)
public void onPlayerChat(PlayerChatEvent event) {
// do stuff
}
}
@@ -0,0 +1,21 @@
package com.alttd.chat.listeners;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.handlers.ChatPlayer;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.LoginEvent;
public class PlayerListener {
@Subscribe(order = PostOrder.FIRST)
public void onPlayerLogin(LoginEvent event) {
ChatPlugin.getPlugin().getChatHandler().addPlayer(new ChatPlayer(event.getPlayer()));
}
@Subscribe
public void quitEvent(DisconnectEvent event) {
ChatPlugin.getPlugin().getChatHandler().removePlayer(event.getPlayer().getUniqueId());
}
}
@@ -0,0 +1,39 @@
package com.alttd.chat.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex {
private static final HashMap<Pattern, ArrayList<String>> cancelRegex = new HashMap<>();
private static final HashMap<String, String> replaceRegex = new HashMap<>();
// IDEA: Regex object -> RegexPattern, shatteredPattern, replacement, replacements
public static void initRegex() {
//TODO load data from config (a regex string, and it's exceptions if there are any)
cancelRegex.put(Pattern.compile("\\b([R]+[^\\w]?[4A]+[^\\w]?[P]+(([^\\w]?[E3]+[^\\w]?[DT]*)|([^\\w]?[I!1]+[^\\w]?[S5]+[^\\w]?[T7]+)|([^\\w]?[I!1]+[^\\w]?[N]+[^\\w]?[G69]+)))\\b"), new ArrayList<>());
//TODO load data from config (a regex string and what to replace it with)
replaceRegex.put(":pirate:", "pirate");
}
public static boolean violatesFilter(String text) {
for (Map.Entry<Pattern, ArrayList<String>> entry : cancelRegex.entrySet()) {
Matcher matcher = entry.getKey().matcher(text);
while (matcher.find()) {
if (!entry.getValue().contains(matcher.group())) return true;
}
}
return false;
}
public static String replaceText(String text) {
for (Map.Entry<String, String> entry : replaceRegex.entrySet()) {
text = text.replaceAll(entry.getKey(), entry.getValue());
}
return text;
}
}