Add basic plugin, config and message command

This commit is contained in:
len 2021-05-02 19:40:27 +02:00
parent 7a6913b7f4
commit 1b4473d017
8 changed files with 585 additions and 0 deletions

39
.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
# ProxyUtils
.idea
testserver
run
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# IntelliJ
*.iml
*.ipr
*.iws
.idea/
out/
# Maven
target/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

118
pom.xml Normal file
View File

@ -0,0 +1,118 @@
<?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>
<groupId>com.alttd.chat</groupId>
<artifactId>Chat</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>Chat</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<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><!-- we can shade this in if needed -->
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>4.2.0_168</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,72 @@
package com.alttd.chat;
import com.alttd.chat.config.Config;
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.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"}
)
public class ChatPlugin {
private static ChatPlugin plugin;
private final ProxyServer server;
private final Logger logger;
private final Path dataDirectory;
private LuckPerms luckPerms;
@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();
server.getEventManager().register(this, new ChatListener());
//statusTask = new StatusTask();
//statusTask.init();
}
public File getDataDirectory() {
return dataDirectory.toFile();
}
public static ChatPlugin getInstance() {
return plugin;
}
public LuckPerms getLuckPerms() {
if(luckPerms == null)
luckPerms = LuckPermsProvider.get();
return luckPerms;
}
public Logger getLogger() {
return logger;
}
public ProxyServer getProxy() {
return server;
}
public void loadCommands() {
// all commands go here
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,68 @@
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.event.Subscribe;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import java.util.HashMap;
import java.util.Map;
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;
}
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);
}
}

View File

@ -0,0 +1,156 @@
package com.alttd.chat.config;
import com.google.common.base.Throwables;
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()) {
CONFIG_FILE.getParentFile().mkdirs();
}
if (!CONFIG_FILE.exists()) {
try {
CONFIG_FILE.createNewFile();
} 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 ex) {
throw Throwables.propagate(ex.getCause());
} catch (Exception ex) {
}
}
}
}
try {
configLoader.save(config);
} catch (IOException ex) {
}
}
public static boolean saveConfig() {
try {
configLoader.save(config);
return true;
} catch (IOException ex) {
return false;
}
}
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 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) {
set(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 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> MESSAGECOMMANDALIASES = 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 <receiver> '><light_purple>(<gray><receiver></gray> on <server> -> Me) <message></light_purple>";
private static void messageCommand() {
MESSAGECOMMANDALIASES.clear();
getList("commands.message.aliases", new ArrayList<String>(){{
add("msg");
add("whisper");
add("tell");
}}).forEach(key -> {
MESSAGECOMMANDALIASES.add(key.toString());
});
MESSAGESENDER = getString("commands.message.sender-message", MESSAGESENDER);
MESSAGERECIEVER = getString("commands.message.reciever-message", MESSAGERECIEVER);
}
}

View File

@ -0,0 +1,60 @@
package com.alttd.chat.config;
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 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 **/
}

View File

@ -0,0 +1,43 @@
package com.alttd.chat.listeners;
import com.alttd.chat.api.MessageEvent;
import com.alttd.chat.config.Config;
import com.velocitypowered.api.event.Subscribe;
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;
public class ChatListener {
@Subscribe
public void onMessage(MessageEvent event) {
String senderName;
String receiverName;
if (event.getSender() instanceof Player) {
Player sender = (Player) event.getSender();
senderName = sender.getUsername();
} else {
senderName = "UNKNOWN";
}
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);
}
}