diff --git a/multichat/dependency-reduced-pom.xml b/multichat/dependency-reduced-pom.xml new file mode 100644 index 00000000..9736f338 --- /dev/null +++ b/multichat/dependency-reduced-pom.xml @@ -0,0 +1,227 @@ + + + 4.0.0 + xyz.olivermartin.multichat + multichat + 1.7.4 + + + + maven-shade-plugin + 3.1.0 + + + package + + shade + + + + + + + org.bstats + xyz.olivermartin.bungee + + + + + + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + + + + CodeMC + https://repo.codemc.org/repository/maven-public + + + sponge + http://repo.spongepowered.org/maven + + + bungeecord-repo + https://oss.sonatype.org/content/repositories/snapshots + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + vault-repo + http://nexus.hc.to/content/repositories/pub_releases + + + placeholderapi + http://repo.extendedclip.com/content/repositories/placeholderapi/ + + + jitpack.io + https://jitpack.io + + + + + org.spongepowered + spongeapi + 7.1.0 + provided + + + error_prone_annotations + com.google.errorprone + + + gson + com.google.code.gson + + + commons-lang3 + org.apache.commons + + + jsr305 + com.google.code.findbugs + + + guice + com.google.inject + + + caffeine + com.github.ben-manes.caffeine + + + guava + com.github.ben-manes.caffeine + + + plugin-meta + org.spongepowered + + + configurate-hocon + org.spongepowered + + + configurate-gson + org.spongepowered + + + configurate-yaml + org.spongepowered + + + flow-math + com.flowpowered + + + flow-noise + com.flowpowered + + + asm + org.ow2.asm + + + + + net.md-5 + bungeecord-api + 1.14-SNAPSHOT + provided + + + bungeecord-chat + net.md-5 + + + bungeecord-config + net.md-5 + + + bungeecord-event + net.md-5 + + + bungeecord-protocol + net.md-5 + + + + + net.md-5 + bungeecord-api + 1.14-SNAPSHOT + javadoc + provided + + + bungeecord-chat + net.md-5 + + + bungeecord-config + net.md-5 + + + bungeecord-event + net.md-5 + + + bungeecord-protocol + net.md-5 + + + + + org.spigotmc + spigot-api + 1.14.2-R0.1-SNAPSHOT + provided + + + commons-lang + commons-lang + + + snakeyaml + org.yaml + + + gson + com.google.code.gson + + + bungeecord-chat + net.md-5 + + + + + net.milkbowl.vault + VaultAPI + 1.6 + provided + + + bukkit + org.bukkit + + + + + me.clip + placeholderapi + 2.9.2 + provided + + + + diff --git a/multichat/pom.xml b/multichat/pom.xml index 0a966d27..a918d343 100644 --- a/multichat/pom.xml +++ b/multichat/pom.xml @@ -5,10 +5,15 @@ xyz.olivermartin.multichat multichat - 1.7.3 + 1.7.4 + + CodeMC + https://repo.codemc.org/repository/maven-public + + sponge http://repo.spongepowered.org/maven @@ -43,6 +48,12 @@ + + org.apache.maven.plugins maven-compiler-plugin @@ -57,6 +68,19 @@ + + + + org.xerial + sqlite-jdbc + 3.27.2.1 + + org.spongepowered spongeapi @@ -67,7 +91,7 @@ net.md-5 bungeecord-api - 1.13-SNAPSHOT + 1.14-SNAPSHOT jar provided @@ -75,7 +99,7 @@ net.md-5 bungeecord-api - 1.13-SNAPSHOT + 1.14-SNAPSHOT javadoc provided @@ -83,7 +107,7 @@ org.spigotmc spigot-api - 1.13.1-R0.1-SNAPSHOT + 1.14.2-R0.1-SNAPSHOT provided diff --git a/multichat/releases/1.7.4/multichat-1.7.4.jar b/multichat/releases/1.7.4/multichat-1.7.4.jar new file mode 100644 index 00000000..40a291fe Binary files /dev/null and b/multichat/releases/1.7.4/multichat-1.7.4.jar differ diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/BungeeComm.java b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/BungeeComm.java index 18000a9e..5ab3ee2c 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/BungeeComm.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/BungeeComm.java @@ -88,7 +88,7 @@ public static void sendCommandMessage(String command, ServerInfo server) { e.printStackTrace(); } - server.sendData("multichat:action", stream.toByteArray()); + server.sendData("multichat:act", stream.toByteArray()); } @@ -107,7 +107,7 @@ public static void sendPlayerCommandMessage(String command, String playerRegex, e.printStackTrace(); } - server.sendData("multichat:paction", stream.toByteArray()); + server.sendData("multichat:pact", stream.toByteArray()); } @@ -173,16 +173,16 @@ public static void sendPlayerChannelMessage(String playerName, String channel, C e.printStackTrace(); } - server.sendData("multichat:channel", stream.toByteArray()); + server.sendData("multichat:ch", stream.toByteArray()); - DebugManager.log("Sent message on multichat:channel channel!"); + DebugManager.log("Sent message on multichat:ch channel!"); } @EventHandler public static void onPluginMessage(PluginMessageEvent ev) { - if (! (ev.getTag().equals("multichat:comm") || ev.getTag().equals("multichat:chat") || ev.getTag().equals("multichat:prefix") || ev.getTag().equals("multichat:suffix") || ev.getTag().equals("multichat:world") || ev.getTag().equals("multichat:nick")) ) { + if (! (ev.getTag().equals("multichat:comm") || ev.getTag().equals("multichat:chat") || ev.getTag().equals("multichat:prefix") || ev.getTag().equals("multichat:suffix") || ev.getTag().equals("multichat:dn") || ev.getTag().equals("multichat:world") || ev.getTag().equals("multichat:nick")) ) { return; } @@ -358,6 +358,46 @@ public static void onPluginMessage(PluginMessageEvent ev) { } + if (ev.getTag().equals("multichat:dn")) { + + DebugManager.log("[multichat:dn] Got an incoming channel message!"); + + ByteArrayInputStream stream = new ByteArrayInputStream(ev.getData()); + DataInputStream in = new DataInputStream(stream); + + try { + + UUID uuid = UUID.fromString(in.readUTF()); + String spigotDisplayName = in.readUTF(); + ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid); + + if (player == null) return; + + synchronized (player) { + + DebugManager.log("[multichat:dn] Player exists!"); + + Optional opm = PlayerMetaManager.getInstance().getPlayer(uuid); + + if (opm.isPresent()) { + + DebugManager.log("[multichat:dn] Player meta exists!"); + + DebugManager.log("[multichat:dn] The displayname received is: " + spigotDisplayName); + + opm.get().spigotDisplayName = spigotDisplayName; + PlayerMetaManager.getInstance().updateDisplayName(uuid); + + } + + } + + } catch (IOException e) { + e.printStackTrace(); + } + + } + if (ev.getTag().equals("multichat:world")) { ByteArrayInputStream stream = new ByteArrayInputStream(ev.getData()); diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/Metrics.java b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/Metrics.java new file mode 100644 index 00000000..61628738 --- /dev/null +++ b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/Metrics.java @@ -0,0 +1,766 @@ +package xyz.olivermartin.multichat.bungee; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.GZIPOutputStream; + +import javax.net.ssl.HttpsURLConnection; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import net.md_5.bungee.api.plugin.Plugin; +import net.md_5.bungee.config.Configuration; +import net.md_5.bungee.config.ConfigurationProvider; +import net.md_5.bungee.config.YamlConfiguration; + +/** + * bStats collects some data for plugin authors. + *

+ * Check out https://bStats.org/ to learn more about bStats! + */ +@SuppressWarnings({}) +public class Metrics { + + static { + // You can use the property to disable the check in your test environment + if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) { + // Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D + final String defaultPackage = new String( + new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'n', 'g', 'e', 'e', 'c', 'o', 'r', 'd'}); + final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); + // We want to make sure nobody just copy & pastes the example and use the wrong package names + if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) { + throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); + } + } + } + + // The version of this bStats class + public static final int B_STATS_VERSION = 1; + + // The url to which the data is sent + private static final String URL = "https://bStats.org/submitData/bungeecord"; + + // The plugin + private final Plugin plugin; + + // Is bStats enabled on this server? + private boolean enabled; + + // The uuid of the server + private String serverUUID; + + // Should failed requests be logged? + private boolean logFailedRequests = false; + + // Should the sent data be logged? + private static boolean logSentData; + + // Should the response text be logged? + private static boolean logResponseStatusText; + + // A list with all known metrics class objects including this one + private static final List knownMetricsInstances = new ArrayList<>(); + + // A list with all custom charts + private final List charts = new ArrayList<>(); + + public Metrics(Plugin plugin) { + this.plugin = plugin; + + try { + loadConfig(); + } catch (IOException e) { + // Failed to load configuration + plugin.getLogger().log(Level.WARNING, "Failed to load bStats config!", e); + return; + } + + // We are not allowed to send data about this server :( + if (!enabled) { + return; + } + + Class usedMetricsClass = getFirstBStatsClass(); + if (usedMetricsClass == null) { + // Failed to get first metrics class + return; + } + if (usedMetricsClass == getClass()) { + // We are the first! :) + linkMetrics(this); + startSubmitting(); + } else { + // We aren't the first so we link to the first metrics class + try { + usedMetricsClass.getMethod("linkMetrics", Object.class).invoke(null, this); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + if (logFailedRequests) { + plugin.getLogger().log(Level.WARNING, "Failed to link to first metrics class " + usedMetricsClass.getName() + "!", e); + } + } + } + } + + /** + * Checks if bStats is enabled. + * + * @return Whether bStats is enabled or not. + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Adds a custom chart. + * + * @param chart The chart to add. + */ + public void addCustomChart(CustomChart chart) { + if (chart == null) { + plugin.getLogger().log(Level.WARNING, "Chart cannot be null"); + } + charts.add(chart); + } + + /** + * Links an other metrics class with this class. + * This method is called using Reflection. + * + * @param metrics An object of the metrics class to link. + */ + public static void linkMetrics(Object metrics) { + knownMetricsInstances.add(metrics); + } + + /** + * Gets the plugin specific data. + * This method is called using Reflection. + * + * @return The plugin specific data. + */ + public JsonObject getPluginData() { + JsonObject data = new JsonObject(); + + String pluginName = plugin.getDescription().getName(); + String pluginVersion = plugin.getDescription().getVersion(); + + data.addProperty("pluginName", pluginName); + data.addProperty("pluginVersion", pluginVersion); + + JsonArray customCharts = new JsonArray(); + for (CustomChart customChart : charts) { + // Add the data of the custom charts + JsonObject chart = customChart.getRequestJsonObject(plugin.getLogger(), logFailedRequests); + if (chart == null) { // If the chart is null, we skip it + continue; + } + customCharts.add(chart); + } + data.add("customCharts", customCharts); + + return data; + } + + private void startSubmitting() { + // The data collection is async, as well as sending the data + // Bungeecord does not have a main thread, everything is async + plugin.getProxy().getScheduler().schedule(plugin, this::submitData, 2, 30, TimeUnit.MINUTES); + // Submit the data every 30 minutes, first time after 2 minutes to give other plugins enough time to start + // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! + // WARNING: Just don't do it! + } + + /** + * Gets the server specific data. + * + * @return The server specific data. + */ + private JsonObject getServerData() { + // Minecraft specific data + int playerAmount = plugin.getProxy().getOnlineCount(); + playerAmount = playerAmount > 500 ? 500 : playerAmount; + @SuppressWarnings("deprecation") + int onlineMode = plugin.getProxy().getConfig().isOnlineMode() ? 1 : 0; + String bungeecordVersion = plugin.getProxy().getVersion(); + int managedServers = plugin.getProxy().getServers().size(); + + // OS/Java specific data + String javaVersion = System.getProperty("java.version"); + String osName = System.getProperty("os.name"); + String osArch = System.getProperty("os.arch"); + String osVersion = System.getProperty("os.version"); + int coreCount = Runtime.getRuntime().availableProcessors(); + + JsonObject data = new JsonObject(); + + data.addProperty("serverUUID", serverUUID); + + data.addProperty("playerAmount", playerAmount); + data.addProperty("managedServers", managedServers); + data.addProperty("onlineMode", onlineMode); + data.addProperty("bungeecordVersion", bungeecordVersion); + + data.addProperty("javaVersion", javaVersion); + data.addProperty("osName", osName); + data.addProperty("osArch", osArch); + data.addProperty("osVersion", osVersion); + data.addProperty("coreCount", coreCount); + + return data; + } + + /** + * Collects the data and sends it afterwards. + */ + private void submitData() { + final JsonObject data = getServerData(); + + final JsonArray pluginData = new JsonArray(); + // Search for all other bStats Metrics classes to get their plugin data + for (Object metrics : knownMetricsInstances) { + try { + Object plugin = metrics.getClass().getMethod("getPluginData").invoke(metrics); + if (plugin instanceof JsonObject) { + pluginData.add((JsonObject) plugin); + } + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { } + } + + data.add("plugins", pluginData); + + try { + // Send the data + sendData(plugin, data); + } catch (Exception e) { + // Something went wrong! :( + if (logFailedRequests) { + plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats!", e); + } + } + } + + /** + * Loads the bStats configuration. + * + * @throws IOException If something did not work :( + */ + private void loadConfig() throws IOException { + Path configPath = plugin.getDataFolder().toPath().getParent().resolve("bStats"); + configPath.toFile().mkdirs(); + File configFile = new File(configPath.toFile(), "config.yml"); + if (!configFile.exists()) { + writeFile(configFile, + "#bStats collects some data for plugin authors like how many servers are using their plugins.", + "#To honor their work, you should not disable it.", + "#This has nearly no effect on the server performance!", + "#Check out https://bStats.org/ to learn more :)", + "enabled: true", + "serverUuid: \"" + UUID.randomUUID().toString() + "\"", + "logFailedRequests: false", + "logSentData: false", + "logResponseStatusText: false"); + } + + Configuration configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); + + // Load configuration + enabled = configuration.getBoolean("enabled", true); + serverUUID = configuration.getString("serverUuid"); + logFailedRequests = configuration.getBoolean("logFailedRequests", false); + logSentData = configuration.getBoolean("logSentData", false); + logResponseStatusText = configuration.getBoolean("logResponseStatusText", false); + } + + /** + * Gets the first bStat Metrics class. + * + * @return The first bStats metrics class. + */ + private Class getFirstBStatsClass() { + Path configPath = plugin.getDataFolder().toPath().getParent().resolve("bStats"); + configPath.toFile().mkdirs(); + File tempFile = new File(configPath.toFile(), "temp.txt"); + + try { + String className = readFile(tempFile); + if (className != null) { + try { + // Let's check if a class with the given name exists. + return Class.forName(className); + } catch (ClassNotFoundException ignored) { } + } + writeFile(tempFile, getClass().getName()); + return getClass(); + } catch (IOException e) { + if (logFailedRequests) { + plugin.getLogger().log(Level.WARNING, "Failed to get first bStats class!", e); + } + return null; + } + } + + /** + * Reads the first line of the file. + * + * @param file The file to read. Cannot be null. + * @return The first line of the file or null if the file does not exist or is empty. + * @throws IOException If something did not work :( + */ + private String readFile(File file) throws IOException { + if (!file.exists()) { + return null; + } + try ( + FileReader fileReader = new FileReader(file); + BufferedReader bufferedReader = new BufferedReader(fileReader); + ) { + return bufferedReader.readLine(); + } + } + + /** + * Writes a String to a file. It also adds a note for the user, + * + * @param file The file to write to. Cannot be null. + * @param lines The lines to write. + * @throws IOException If something did not work :( + */ + private void writeFile(File file, String... lines) throws IOException { + if (!file.exists()) { + file.createNewFile(); + } + try ( + FileWriter fileWriter = new FileWriter(file); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter) + ) { + for (String line : lines) { + bufferedWriter.write(line); + bufferedWriter.newLine(); + } + } + } + + /** + * Sends the data to the bStats server. + * + * @param plugin Any plugin. It's just used to get a logger instance. + * @param data The data to send. + * @throws Exception If the request failed. + */ + private static void sendData(Plugin plugin, JsonObject data) throws Exception { + if (data == null) { + throw new IllegalArgumentException("Data cannot be null"); + } + if (logSentData) { + plugin.getLogger().info("Sending data to bStats: " + data.toString()); + } + + HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); + + // Compress the data to save bandwidth + byte[] compressedData = compress(data.toString()); + + // Add headers + connection.setRequestMethod("POST"); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request + connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); + connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format + connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); + + // Send data + connection.setDoOutput(true); + DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); + outputStream.write(compressedData); + outputStream.flush(); + outputStream.close(); + + InputStream inputStream = connection.getInputStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + + StringBuilder builder = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) { + builder.append(line); + } + bufferedReader.close(); + if (logResponseStatusText) { + plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString()); + } + } + + /** + * Gzips the given String. + * + * @param str The string to gzip. + * @return The gzipped String. + * @throws IOException If the compression failed. + */ + private static byte[] compress(final String str) throws IOException { + if (str == null) { + return null; + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + GZIPOutputStream gzip = new GZIPOutputStream(outputStream); + gzip.write(str.getBytes(StandardCharsets.UTF_8)); + gzip.close(); + return outputStream.toByteArray(); + } + + + /** + * Represents a custom chart. + */ + public static abstract class CustomChart { + + // The id of the chart + private final String chartId; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + */ + CustomChart(String chartId) { + if (chartId == null || chartId.isEmpty()) { + throw new IllegalArgumentException("ChartId cannot be null or empty!"); + } + this.chartId = chartId; + } + + private JsonObject getRequestJsonObject(Logger logger, boolean logFailedRequests) { + JsonObject chart = new JsonObject(); + chart.addProperty("chartId", chartId); + try { + JsonObject data = getChartData(); + if (data == null) { + // If the data is null we don't send the chart. + return null; + } + chart.add("data", data); + } catch (Throwable t) { + if (logFailedRequests) { + logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); + } + return null; + } + return chart; + } + + protected abstract JsonObject getChartData() throws Exception; + + } + + /** + * Represents a custom simple pie. + */ + public static class SimplePie extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimplePie(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObject getChartData() throws Exception { + JsonObject data = new JsonObject(); + String value = callable.call(); + if (value == null || value.isEmpty()) { + // Null = skip the chart + return null; + } + data.addProperty("value", value); + return data; + } + } + + /** + * Represents a custom advanced pie. + */ + public static class AdvancedPie extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedPie(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObject getChartData() throws Exception { + JsonObject data = new JsonObject(); + JsonObject values = new JsonObject(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + continue; // Skip this invalid + } + allSkipped = false; + values.addProperty(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + data.add("values", values); + return data; + } + } + + /** + * Represents a custom drilldown pie. + */ + public static class DrilldownPie extends CustomChart { + + private final Callable>> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public DrilldownPie(String chartId, Callable>> callable) { + super(chartId); + this.callable = callable; + } + + @Override + public JsonObject getChartData() throws Exception { + JsonObject data = new JsonObject(); + JsonObject values = new JsonObject(); + Map> map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean reallyAllSkipped = true; + for (Map.Entry> entryValues : map.entrySet()) { + JsonObject value = new JsonObject(); + boolean allSkipped = true; + for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { + value.addProperty(valueEntry.getKey(), valueEntry.getValue()); + allSkipped = false; + } + if (!allSkipped) { + reallyAllSkipped = false; + values.add(entryValues.getKey(), value); + } + } + if (reallyAllSkipped) { + // Null = skip the chart + return null; + } + data.add("values", values); + return data; + } + } + + /** + * Represents a custom single line chart. + */ + public static class SingleLineChart extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SingleLineChart(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObject getChartData() throws Exception { + JsonObject data = new JsonObject(); + int value = callable.call(); + if (value == 0) { + // Null = skip the chart + return null; + } + data.addProperty("value", value); + return data; + } + + } + + /** + * Represents a custom multi line chart. + */ + public static class MultiLineChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public MultiLineChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObject getChartData() throws Exception { + JsonObject data = new JsonObject(); + JsonObject values = new JsonObject(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + continue; // Skip this invalid + } + allSkipped = false; + values.addProperty(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + data.add("values", values); + return data; + } + + } + + /** + * Represents a custom simple bar chart. + */ + public static class SimpleBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimpleBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObject getChartData() throws Exception { + JsonObject data = new JsonObject(); + JsonObject values = new JsonObject(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + for (Map.Entry entry : map.entrySet()) { + JsonArray categoryValues = new JsonArray(); + categoryValues.add(new JsonPrimitive(entry.getValue())); + values.add(entry.getKey(), categoryValues); + } + data.add("values", values); + return data; + } + + } + + /** + * Represents a custom advanced bar chart. + */ + public static class AdvancedBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObject getChartData() throws Exception { + JsonObject data = new JsonObject(); + JsonObject values = new JsonObject(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue().length == 0) { + continue; // Skip this invalid + } + allSkipped = false; + JsonArray categoryValues = new JsonArray(); + for (int categoryValue : entry.getValue()) { + categoryValues.add(new JsonPrimitive(categoryValue)); + } + values.add(entry.getKey(), categoryValues); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + data.add("values", values); + return data; + } + + } + +} \ No newline at end of file diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/MultiChat.java b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/MultiChat.java index 27f70c29..4b21b8b0 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/MultiChat.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/MultiChat.java @@ -37,11 +37,12 @@ */ public class MultiChat extends Plugin implements Listener { - public static final String LATEST_VERSION = "1.7.3"; + public static final String LATEST_VERSION = "1.7.4"; public static final String[] ALLOWED_VERSIONS = new String[] { LATEST_VERSION, + "1.7.3", "1.7.2", "1.7.1", "1.7", @@ -231,6 +232,9 @@ public void onEnable() { instance = this; + @SuppressWarnings("unused") + Metrics metrics = new Metrics(this); + configDir = getDataFolder(); if (!getDataFolder().exists()) { System.out.println("[MultiChat] Creating plugin directory!"); @@ -277,12 +281,13 @@ public void onEnable() { getProxy().registerChannel("multichat:comm"); getProxy().registerChannel("multichat:prefix"); getProxy().registerChannel("multichat:suffix"); + getProxy().registerChannel("multichat:dn"); getProxy().registerChannel("multichat:nick"); getProxy().registerChannel("multichat:world"); - getProxy().registerChannel("multichat:action"); - getProxy().registerChannel("multichat:paction"); + getProxy().registerChannel("multichat:act"); + getProxy().registerChannel("multichat:pact"); getProxy().registerChannel("multichat:chat"); - getProxy().registerChannel("multichat:channel"); + getProxy().registerChannel("multichat:ch"); getProxy().registerChannel("multichat:ignore"); getProxy().getPluginManager().registerListener(this, new BungeeComm()); @@ -294,7 +299,7 @@ public void onEnable() { // Run start-up routines Startup(); UUIDNameManager.Startup(); - + // Set up chat control stuff if (chatcontrolYML.contains("link_control")) { ChatControl.controlLinks = chatcontrolYML.getBoolean("link_control"); diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMeta.java b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMeta.java index 1662bd05..5b013937 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMeta.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMeta.java @@ -7,6 +7,7 @@ public class PlayerMeta { public UUID uuid; public String name; public String nick; + public String spigotDisplayName; public String prefix; public String suffix; public String world; @@ -15,12 +16,17 @@ public PlayerMeta(UUID uuid, String name) { this.uuid = uuid; this.name = name; nick = name; + spigotDisplayName = nick; prefix = ""; suffix = ""; world = ""; } - public String getDisplayName(String format) { + public String getSpigotDisplayname() { + return this.spigotDisplayName; + } + + /*public String getDisplayName(String format) { String displayName = format; @@ -34,6 +40,6 @@ public String getDisplayName(String format) { return displayName; - } + }*/ } diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMetaManager.java b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMetaManager.java index 512b8145..d21ca316 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMetaManager.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/bungee/PlayerMetaManager.java @@ -43,26 +43,64 @@ public Optional getPlayer(UUID uuid) { public void updateDisplayName(UUID uuid) { + DebugManager.log("[PlayerMetaManager] Updating display name..."); + Optional opm = getPlayer(uuid); if (!opm.isPresent()) return; + DebugManager.log("[PlayerMetaManager] Player is present!"); + ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid); if (ConfigManager.getInstance().getHandler("config.yml").getConfig().getBoolean("fetch_spigot_display_names") == true && player != null) { + + DebugManager.log("[PlayerMetaManager] Fetch Spigot Display Names is true"); + if (ConfigManager.getInstance().getHandler("config.yml").getConfig().contains("set_display_name")) { + if (ConfigManager.getInstance().getHandler("config.yml").getConfig().getBoolean("set_display_name")) { + + DebugManager.log("[PlayerMetaManager] MultiChat is in charge of display names"); + if (ConfigManager.getInstance().getHandler("config.yml").getConfig().contains("display_name_format")) { - player.setDisplayName(opm.get().getDisplayName(ConfigManager.getInstance().getHandler("config.yml").getConfig().getString("display_name_format"))); + //player.setDisplayName(opm.get().getDisplayName(ConfigManager.getInstance().getHandler("config.yml").getConfig().getString("display_name_format"))); + + DebugManager.log("[PlayerMetaManager] Set as: " + opm.get().getSpigotDisplayname()); + + player.setDisplayName(opm.get().getSpigotDisplayname()); } else { - player.setDisplayName(opm.get().getDisplayName("%PREFIX%%NICK%%SUFFIX%")); + //player.setDisplayName(opm.get().getDisplayName("%PREFIX%%NICK%%SUFFIX%")); + + DebugManager.log("[PlayerMetaManager] Set as: " + opm.get().getSpigotDisplayname()); + + player.setDisplayName(opm.get().getSpigotDisplayname()); } + } else { + + DebugManager.log("[PlayerMetaManager] MultiChat is NOT in charge of display names!"); + + DebugManager.log("[PlayerMetaManager] Set as: " + opm.get().getSpigotDisplayname()); + + player.setDisplayName(opm.get().getSpigotDisplayname()); + } + } else { + if (ConfigManager.getInstance().getHandler("config.yml").getConfig().contains("display_name_format")) { - player.setDisplayName(opm.get().getDisplayName(ConfigManager.getInstance().getHandler("config.yml").getConfig().getString("display_name_format"))); + //player.setDisplayName(opm.get().getDisplayName(ConfigManager.getInstance().getHandler("config.yml").getConfig().getString("display_name_format"))); + // TODO Maybe new option for "fetch_spigot_displayname"? + + DebugManager.log("[PlayerMetaManager] Set as: " + opm.get().getSpigotDisplayname()); + + player.setDisplayName(opm.get().getSpigotDisplayname()); } else { - player.setDisplayName(opm.get().getDisplayName("%PREFIX%%NICK%%SUFFIX%")); + //player.setDisplayName(opm.get().getDisplayName("%PREFIX%%NICK%%SUFFIX%")); + + DebugManager.log("[PlayerMetaManager] Set as: " + opm.get().getSpigotDisplayname()); + + player.setDisplayName(opm.get().getSpigotDisplayname()); } } diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MetaManager.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MetaManager.java index 8fc1f0ac..4ecff156 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MetaManager.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MetaManager.java @@ -51,6 +51,9 @@ public void updatePlayerMeta(String playername, boolean setDisplayName, String d Bukkit.getPlayer(playername).setDisplayName(displayNameFormat); Bukkit.getPlayer(playername).setPlayerListName(displayNameFormat); } + + comm.sendPluginChannelMessage("multichat:dn", Bukkit.getPlayer(playername).getUniqueId(), Bukkit.getPlayer(playername).getDisplayName()); + } else { if (setDisplayName) { @@ -63,6 +66,8 @@ public void updatePlayerMeta(String playername, boolean setDisplayName, String d Bukkit.getPlayer(playername).setPlayerListName(displayNameFormat); } + + comm.sendPluginChannelMessage("multichat:dn", Bukkit.getPlayer(playername).getUniqueId(), Bukkit.getPlayer(playername).getDisplayName()); } diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MultiChatSpigot.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MultiChatSpigot.java index c17be521..5a1c2d44 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MultiChatSpigot.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/MultiChatSpigot.java @@ -46,6 +46,8 @@ public class MultiChatSpigot extends JavaPlugin implements Listener { private static boolean vault; private static boolean papi; + public static String serverName = "SERVER_NAME"; + public static Map playerChannels = new HashMap(); public static Map channelObjects = new HashMap(); public static Map> ignoreMap = new HashMap>(); @@ -82,10 +84,12 @@ public static boolean hookedPAPI() { public static String localChatFormat = "&7&lLOCAL &f> &f%DISPLAYNAME%&f: "; public static boolean setLocalFormat = false; public static boolean forceMultiChatFormat = false; - + public static boolean showNicknamePrefix = false; public static String nicknamePrefix = "~"; public static List nicknameBlacklist = new ArrayList(); + public static int nicknameMaxLength = 20; + public static boolean nicknameLengthIncludeFormatting = false; @SuppressWarnings("unchecked") public void onEnable() { @@ -104,6 +108,10 @@ public void onEnable() { SpigotConfigManager.getInstance().registerHandler("spigotconfig.yml", configDir); Configuration config = SpigotConfigManager.getInstance().getHandler("spigotconfig.yml").getConfig(); + if (config.contains("server_name")) { + serverName = config.getString("server_name"); + } + overrideGlobalFormat = config.getBoolean("override_global_format"); overrideGlobalFormatFormat = config.getString("override_global_format_format"); overrideAllMultiChatFormats = config.getBoolean("override_all_multichat_formatting"); @@ -120,11 +128,17 @@ public void onEnable() { } } - + if (config.contains("show_nickname_prefix")) { showNicknamePrefix = config.getBoolean("show_nickname_prefix"); nicknamePrefix = config.getString("nickname_prefix"); nicknameBlacklist = config.getStringList("nickname_blacklist"); + if (config.contains("nickname_length_limit")) { + + nicknameMaxLength = config.getInt("nickname_length_limit"); + nicknameLengthIncludeFormatting = config.getBoolean("nickname_length_limit_formatting"); + + } } File f = new File(configDir, nameDataFile); @@ -222,13 +236,14 @@ public void onEnable() { getServer().getMessenger().registerOutgoingPluginChannel(this, "multichat:chat"); getServer().getMessenger().registerOutgoingPluginChannel(this, "multichat:prefix"); getServer().getMessenger().registerOutgoingPluginChannel(this, "multichat:suffix"); + getServer().getMessenger().registerOutgoingPluginChannel(this, "multichat:dn"); getServer().getMessenger().registerOutgoingPluginChannel(this, "multichat:world"); getServer().getMessenger().registerOutgoingPluginChannel(this, "multichat:nick"); getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:comm", MultiChatPluginMessageListener.getInstance()); getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:chat", MultiChatPluginMessageListener.getInstance()); - getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:action", MultiChatPluginMessageListener.getInstance()); - getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:paction", MultiChatPluginMessageListener.getInstance()); - getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:channel", MultiChatPluginMessageListener.getInstance()); + getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:act", MultiChatPluginMessageListener.getInstance()); + getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:pact", MultiChatPluginMessageListener.getInstance()); + getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:ch", MultiChatPluginMessageListener.getInstance()); getServer().getMessenger().registerIncomingPluginChannel(this, "multichat:ignore", MultiChatPluginMessageListener.getInstance()); // Register listeners diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/SpigotPlaceholderManager.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/SpigotPlaceholderManager.java index 7809257f..e0f37e44 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/SpigotPlaceholderManager.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/SpigotPlaceholderManager.java @@ -1,6 +1,5 @@ package xyz.olivermartin.multichat.spigotbridge; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import net.milkbowl.vault.chat.Chat; @@ -18,14 +17,14 @@ public static String buildChatFormat(Player player, String format) { } format = format.replace("%NICK%", NameManager.getInstance().getCurrentName(player.getUniqueId())); format = format.replace("%WORLD%", player.getWorld().getName()); - format = format.replace("%SERVER%", Bukkit.getServerName()); + format = format.replace("%SERVER%", MultiChatSpigot.serverName); return format + "%2$s"; } - + public static String buildMultiChatPlaceholder(Player player, String format) { - + format = format.replace("%NAME%", player.getName()); format = format.replace("%DISPLAYNAME%", "%1$s"); // This might work? if (MultiChatSpigot.hookedVault()) { @@ -35,10 +34,10 @@ public static String buildMultiChatPlaceholder(Player player, String format) { } format = format.replace("%NICK%", NameManager.getInstance().getCurrentName(player.getUniqueId())); format = format.replace("%WORLD%", player.getWorld().getName()); - format = format.replace("%SERVER%", Bukkit.getServerName()); + format = format.replace("%SERVER%", MultiChatSpigot.serverName); return format; - + } } diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/commands/CommandHandler.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/commands/CommandHandler.java index 30e4591e..9bd33a02 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/commands/CommandHandler.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/commands/CommandHandler.java @@ -56,6 +56,10 @@ public boolean onCommand(CommandSender commandSender, Command cmd, String label, SpigotConfigManager.getInstance().getHandler("spigotconfig.yml").startupConfig(); Configuration config = SpigotConfigManager.getInstance().getHandler("spigotconfig.yml").getConfig(); + if (config.contains("server_name")) { + MultiChatSpigot.serverName = config.getString("server_name"); + } + MultiChatSpigot.overrideGlobalFormat = config.getBoolean("override_global_format"); MultiChatSpigot.overrideGlobalFormatFormat = config.getString("override_global_format_format"); MultiChatSpigot.overrideAllMultiChatFormats = config.getBoolean("override_all_multichat_formatting"); @@ -77,6 +81,12 @@ public boolean onCommand(CommandSender commandSender, Command cmd, String label, MultiChatSpigot.showNicknamePrefix = config.getBoolean("show_nickname_prefix"); MultiChatSpigot.nicknamePrefix = config.getString("nickname_prefix"); MultiChatSpigot.nicknameBlacklist = config.getStringList("nickname_blacklist"); + if (config.contains("nickname_length_limit")) { + + MultiChatSpigot.nicknameMaxLength = config.getInt("nickname_length_limit"); + MultiChatSpigot.nicknameLengthIncludeFormatting = config.getBoolean("nickname_length_limit_formatting"); + + } } commandSender.sendMessage(ChatColor.GREEN + "The plugin has been reloaded!"); @@ -137,11 +147,22 @@ public boolean onCommand(CommandSender commandSender, Command cmd, String label, return true; } - if (NameManager.getInstance().stripAllFormattingCodes(args[0]).length() > 20 && !sender.hasPermission("multichatspigot.nick.anylength")) { + if (MultiChatSpigot.nicknameLengthIncludeFormatting) { + // Include formatting codes in the nickname length + if (args[0].length() > MultiChatSpigot.nicknameMaxLength && !sender.hasPermission("multichatspigot.nick.anylength")) { - sender.sendMessage(ChatColor.DARK_RED + "Sorry your nickname is too long, max 20 characters! (Excluding format codes)"); - return true; + sender.sendMessage(ChatColor.DARK_RED + "Sorry your nickname is too long, max " + MultiChatSpigot.nicknameMaxLength + " characters! (Including format codes)"); + return true; + + } + } else { + // Do not include formatting codes in the nickname length + if (NameManager.getInstance().stripAllFormattingCodes(args[0]).length() > MultiChatSpigot.nicknameMaxLength && !sender.hasPermission("multichatspigot.nick.anylength")) { + + sender.sendMessage(ChatColor.DARK_RED + "Sorry your nickname is too long, max " + MultiChatSpigot.nicknameMaxLength + " characters! (Excluding format codes)"); + return true; + } } String targetNickname = NameManager.getInstance().stripAllFormattingCodes(NameManager.getInstance().getCurrentName(targetUUID)); @@ -221,11 +242,22 @@ public boolean onCommand(CommandSender commandSender, Command cmd, String label, return true; } - if (NameManager.getInstance().stripAllFormattingCodes(args[1]).length() > 20 && !sender.hasPermission("multichatspigot.nick.anylength")) { + if (MultiChatSpigot.nicknameLengthIncludeFormatting) { + // Include formatting codes in the nickname length + if (args[1].length() > MultiChatSpigot.nicknameMaxLength && !sender.hasPermission("multichatspigot.nick.anylength")) { - sender.sendMessage(ChatColor.DARK_RED + "Sorry your nickname is too long, max 20 characters! (Excluding format codes)"); - return true; + sender.sendMessage(ChatColor.DARK_RED + "Sorry your nickname is too long, max " + MultiChatSpigot.nicknameMaxLength + " characters! (Including format codes)"); + return true; + } + } else { + // Do not include formatting codes in the nickname length + if (NameManager.getInstance().stripAllFormattingCodes(args[1]).length() > MultiChatSpigot.nicknameMaxLength && !sender.hasPermission("multichatspigot.nick.anylength")) { + + sender.sendMessage(ChatColor.DARK_RED + "Sorry your nickname is too long, max " + MultiChatSpigot.nicknameMaxLength + " characters! (Excluding format codes)"); + return true; + + } } String targetNickname = NameManager.getInstance().stripAllFormattingCodes(NameManager.getInstance().getCurrentName(targetUUID)); diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/DatabaseManager.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/DatabaseManager.java new file mode 100644 index 00000000..31de05a7 --- /dev/null +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/DatabaseManager.java @@ -0,0 +1,99 @@ +package xyz.olivermartin.multichat.spigotbridge.database; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/* + * DROP TABLE IF EXISTS nicknames; + +CREATE TABLE nicknames(id VARCHAR(128) PRIMARY KEY, u_nick VARCHAR(255), f_nick VARCHAR(255)); + +INSERT INTO nicknames VALUES ('255-444-2221--11-11', 'revilo', '&4Revilo'); + +SELECT * FROM nicknames; + */ + +public class DatabaseManager { + + private static DatabaseManager instance; + + public static DatabaseManager getInstance() { + return instance; + } + + static { + instance = new DatabaseManager(); + } + + /* END STATIC */ + + private File databasePath; + private DatabaseMode databaseMode = DatabaseMode.SQLite; + + private Map databases; + + private DatabaseManager() { + databases = new HashMap(); + } + + //////////// + + public static void main(String args[]) { + DatabaseManager.getInstance().setPath(new File("C:\\multichat\\db\\")); + DatabaseManager.getInstance().createDatabase("testing.db"); + } + + //////////// + + public void setPath(File path) { + this.databasePath = path; + } + + public GenericDatabase createDatabase(String name) { + return createDatabase(name, name); + } + + public boolean isReady() { + return databasePath != null; + } + + /** + * Generic class to create a sqlite database + */ + public GenericDatabase createDatabase(String databaseName, String fileName) { + + if (!isReady()) throw new RuntimeException("MultiChat Database Manager Not Ready!"); + + if (!databasePath.exists()) { + databasePath.mkdirs(); + } + + switch (databaseMode) { + case SQLite: + default: + // TODO check doesnt already exist + databases.put(databaseName.toLowerCase(), new SQLiteDatabase(databasePath, fileName)); + return databases.get(databaseName.toLowerCase()); + } + + } + + public Optional getDatabase(String databaseName) { + if (databases.containsKey(databaseName.toLowerCase())) { + return Optional.of(databases.get(databaseName.toLowerCase())); + } else { + return Optional.empty(); + } + } + + public void removeDatabase(String databaseName) { + if (databases.containsKey(databaseName.toLowerCase())) { + GenericDatabase gdb = databases.get(databaseName.toLowerCase()); + gdb.disconnectFromDatabase(); + databases.remove(databaseName.toLowerCase()); + } + } + +} diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/DatabaseMode.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/DatabaseMode.java new file mode 100644 index 00000000..1696d475 --- /dev/null +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/DatabaseMode.java @@ -0,0 +1,7 @@ +package xyz.olivermartin.multichat.spigotbridge.database; + +public enum DatabaseMode { + + SQLite + +} diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/GenericDatabase.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/GenericDatabase.java new file mode 100644 index 00000000..2d31261d --- /dev/null +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/GenericDatabase.java @@ -0,0 +1,36 @@ +package xyz.olivermartin.multichat.spigotbridge.database; + +public abstract class GenericDatabase { + + protected String url; + private boolean ready; + + public GenericDatabase(String url) { + this.url = url; + ready = setupDatabase(url); + } + + public String getURL() { + return this.url; + } + + public boolean isReady() { + return this.ready; + } + + protected abstract boolean setupDatabase(String url); + + protected abstract void disconnect(); + + protected abstract boolean connect(); + + public void connectToDatabase() { + this.ready = connect(); + } + + public void disconnectFromDatabase() { + disconnect(); + this.ready = false; + } + +} diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/SQLiteDatabase.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/SQLiteDatabase.java new file mode 100644 index 00000000..4eeff0a3 --- /dev/null +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/database/SQLiteDatabase.java @@ -0,0 +1,78 @@ +package xyz.olivermartin.multichat.spigotbridge.database; + +import java.io.File; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.SQLException; + +public class SQLiteDatabase extends GenericDatabase { + + private static final String URL_PREFIX = "jdbc:sqlite:"; + private Connection conn; + + public SQLiteDatabase(File path, String filename) { + super(URL_PREFIX + path + File.separator + filename); + } + + protected boolean setupDatabase(String url) { + + try (Connection conn = DriverManager.getConnection(url)) { + + if (conn != null) { + DatabaseMetaData meta = conn.getMetaData(); + System.out.println("The driver name is " + meta.getDriverName()); + System.out.println("A new database has been created."); + + this.conn = conn; + + // Database successfully created + return true; + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + + // Database not successfully created + return false; + + } + + @Override + protected void disconnect() { + + if (conn != null) { + try { + if (!conn.isClosed()) { + conn.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + } + + @Override + protected boolean connect() { + + if (conn == null) { + + return setupDatabase(url); + + } else { + try { + if (conn.isClosed()) { + return setupDatabase(url); + } + } catch (SQLException e) { + return false; + } + } + + // Already connected + return true; + } + +} diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/listeners/MultiChatPluginMessageListener.java b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/listeners/MultiChatPluginMessageListener.java index 68a3940a..b097b3d2 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/listeners/MultiChatPluginMessageListener.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spigotbridge/listeners/MultiChatPluginMessageListener.java @@ -88,7 +88,7 @@ public void onPluginMessageReceived(String channel, Player player, byte[] bytes) e.printStackTrace(); } - } else if (channel.equals("multichat:action")) { + } else if (channel.equals("multichat:act")) { ByteArrayInputStream stream = new ByteArrayInputStream(bytes); DataInputStream in = new DataInputStream(stream); @@ -104,7 +104,7 @@ public void onPluginMessageReceived(String channel, Player player, byte[] bytes) e.printStackTrace(); } - } else if (channel.equals("multichat:paction")) { + } else if (channel.equals("multichat:pact")) { ByteArrayInputStream stream = new ByteArrayInputStream(bytes); DataInputStream in = new DataInputStream(stream); @@ -147,7 +147,7 @@ public void onPluginMessageReceived(String channel, Player player, byte[] bytes) } - } else if (channel.equals("multichat:channel")) { + } else if (channel.equals("multichat:ch")) { ByteArrayInputStream stream = new ByteArrayInputStream(bytes); //DataInputStream in = new DataInputStream(stream); diff --git a/multichat/src/main/java/xyz/olivermartin/multichat/spongebridge/MultiChatSponge.java b/multichat/src/main/java/xyz/olivermartin/multichat/spongebridge/MultiChatSponge.java index 31f4857c..1fee8a2f 100644 --- a/multichat/src/main/java/xyz/olivermartin/multichat/spongebridge/MultiChatSponge.java +++ b/multichat/src/main/java/xyz/olivermartin/multichat/spongebridge/MultiChatSponge.java @@ -62,7 +62,7 @@ * @author Oliver Martin (Revilo410) * */ -@Plugin(id = "multichat", name = "MultiChatSponge", version = "1.7.3", dependencies = { @Dependency(id = "placeholderapi", optional = true) }) +@Plugin(id = "multichat", name = "MultiChatSponge", version = "1.7.4", dependencies = { @Dependency(id = "placeholderapi", optional = true) }) public final class MultiChatSponge implements CommandExecutor { public static SimpleMutableMessageChannel multichatChannel; @@ -77,6 +77,7 @@ public final class MultiChatSponge implements CommandExecutor { static RawDataChannel prefixChannel; static RawDataChannel suffixChannel; + static RawDataChannel displayNameChannel; static RawDataChannel nickChannel; static RawDataChannel worldChannel; static RawDataChannel channelChannel; @@ -115,7 +116,7 @@ public final class MultiChatSponge implements CommandExecutor { @SuppressWarnings("serial") @Listener public void onServerStart(GameStartedServerEvent event) { - + // DEBUG MODE //DebugManager.setDebug(true); @@ -184,14 +185,15 @@ public void onServerStart(GameStartedServerEvent event) { ChannelBinding.RawDataChannel commChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:comm"); ChannelBinding.RawDataChannel chatChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:chat"); - ChannelBinding.RawDataChannel actionChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:action"); - ChannelBinding.RawDataChannel playerActionChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:paction"); + ChannelBinding.RawDataChannel actionChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:act"); + ChannelBinding.RawDataChannel playerActionChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:pact"); ChannelBinding.RawDataChannel prefixChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:prefix"); ChannelBinding.RawDataChannel suffixChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:suffix"); + ChannelBinding.RawDataChannel displayNameChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:dn"); ChannelBinding.RawDataChannel worldChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:world"); ChannelBinding.RawDataChannel nickChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:nick"); - ChannelBinding.RawDataChannel channelChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:channel"); + ChannelBinding.RawDataChannel channelChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:ch"); ChannelBinding.RawDataChannel ignoreChannel = Sponge.getGame().getChannelRegistrar().createRawChannel(this, "multichat:ignore"); commChannel.addListener(Platform.Type.SERVER, new MetaListener(commChannel)); @@ -210,6 +212,7 @@ public void onServerStart(GameStartedServerEvent event) { MultiChatSponge.prefixChannel = prefixChannel; MultiChatSponge.suffixChannel = suffixChannel; + MultiChatSponge.displayNameChannel = displayNameChannel; MultiChatSponge.nickChannel = nickChannel; MultiChatSponge.worldChannel = worldChannel; MultiChatSponge.channelChannel = channelChannel; @@ -257,6 +260,7 @@ public void onServerStop(GameStoppingServerEvent event) { Sponge.getChannelRegistrar().unbindChannel(actionChannel); Sponge.getChannelRegistrar().unbindChannel(prefixChannel); Sponge.getChannelRegistrar().unbindChannel(suffixChannel); + Sponge.getChannelRegistrar().unbindChannel(displayNameChannel); Sponge.getChannelRegistrar().unbindChannel(nickChannel); Sponge.getChannelRegistrar().unbindChannel(worldChannel); Sponge.getChannelRegistrar().unbindChannel(channelChannel); @@ -336,6 +340,12 @@ public static void updatePlayerMeta(String playername, boolean setDisplayName, S Sponge.getServer().getPlayer(playername).ifPresent(x -> x.offer(Keys.DISPLAY_NAME, Text.of(finalDisplayName))); + displayNameChannel.sendTo(player, buffer -> buffer.writeUTF(player.getUniqueId().toString()).writeUTF(finalDisplayName)); + + } else { + + displayNameChannel.sendTo(player, buffer -> buffer.writeUTF(player.getUniqueId().toString()).writeUTF(playername)); + } } diff --git a/multichat/src/main/resources/bungee.yml b/multichat/src/main/resources/bungee.yml index 75f19063..0c001e04 100644 --- a/multichat/src/main/resources/bungee.yml +++ b/multichat/src/main/resources/bungee.yml @@ -1,5 +1,5 @@ name: MultiChat main: xyz.olivermartin.multichat.bungee.MultiChat -version: 1.7.3 +version: 1.7.4 author: Revilo410 api-version: 1.13 \ No newline at end of file diff --git a/multichat/src/main/resources/chatcontrol.yml b/multichat/src/main/resources/chatcontrol.yml index 9eb7d726..5e7f1d5e 100644 --- a/multichat/src/main/resources/chatcontrol.yml +++ b/multichat/src/main/resources/chatcontrol.yml @@ -8,7 +8,7 @@ ################## # DON'T EDIT # -version: "1.7.3" # +version: "1.7.4" # ################## # 1. Chat Control Rules diff --git a/multichat/src/main/resources/config.yml b/multichat/src/main/resources/config.yml index c8b3de3c..76bdaa8e 100644 --- a/multichat/src/main/resources/config.yml +++ b/multichat/src/main/resources/config.yml @@ -8,7 +8,7 @@ ################## # DON'T EDIT # -version: "1.7.3" # +version: "1.7.4" # ################## # 1. General diff --git a/multichat/src/main/resources/joinmessages.yml b/multichat/src/main/resources/joinmessages.yml index 8fbdfac0..6a6978cc 100644 --- a/multichat/src/main/resources/joinmessages.yml +++ b/multichat/src/main/resources/joinmessages.yml @@ -8,7 +8,7 @@ ################## # DON'T EDIT # -version: "1.7.3" # +version: "1.7.4" # ################## ############################################################ diff --git a/multichat/src/main/resources/joinmessages_fr.yml b/multichat/src/main/resources/joinmessages_fr.yml index 7b49af11..0e79b869 100644 --- a/multichat/src/main/resources/joinmessages_fr.yml +++ b/multichat/src/main/resources/joinmessages_fr.yml @@ -8,7 +8,7 @@ ################## # Ne pas éditer # -version: "1.7.3" # +version: "1.7.4" # ################## # French Translation by Nogapra - Thank you! diff --git a/multichat/src/main/resources/messages.yml b/multichat/src/main/resources/messages.yml index de44d257..cbe496c3 100644 --- a/multichat/src/main/resources/messages.yml +++ b/multichat/src/main/resources/messages.yml @@ -8,7 +8,7 @@ ################## # DON'T EDIT # -version: "1.7.3" # +version: "1.7.4" # ################## ############################################################ diff --git a/multichat/src/main/resources/messages_fr.yml b/multichat/src/main/resources/messages_fr.yml index a2588f2a..5626fe6c 100644 --- a/multichat/src/main/resources/messages_fr.yml +++ b/multichat/src/main/resources/messages_fr.yml @@ -8,7 +8,7 @@ ################## # DON'T EDIT # -version: "1.7.3" # +version: "1.7.4" # ################## # French Translation by Nogapra - Thank you! diff --git a/multichat/src/main/resources/multichatsponge.yml b/multichat/src/main/resources/multichatsponge.yml index 3f6c2f2e..69f6e091 100644 --- a/multichat/src/main/resources/multichatsponge.yml +++ b/multichat/src/main/resources/multichatsponge.yml @@ -8,7 +8,7 @@ ################## # DON'T EDIT # -version: "1.7.3" # +version: "1.7.4" # ################## # Specify the name of this server here for the %SERVER% placeholder diff --git a/multichat/src/main/resources/plugin.yml b/multichat/src/main/resources/plugin.yml index 4b058787..5d914f8e 100644 --- a/multichat/src/main/resources/plugin.yml +++ b/multichat/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: MultiChatSpigot -version: 1.7.3 +version: 1.7.4 author: Revilo410 main: xyz.olivermartin.multichat.spigotbridge.MultiChatSpigot softdepend: [Vault,PlaceholderAPI] diff --git a/multichat/src/main/resources/spigotconfig.yml b/multichat/src/main/resources/spigotconfig.yml index 2f0a1928..46f2500e 100644 --- a/multichat/src/main/resources/spigotconfig.yml +++ b/multichat/src/main/resources/spigotconfig.yml @@ -8,9 +8,12 @@ ################## # DON'T EDIT # -version: "1.7.3" # +version: "1.7.4" # ################## +# Specify the name of this server here for the %SERVER% placeholder +server_name: "SERVER_NAME" + ############################################################ # +------------------------------------------------------+ # # | Global | # @@ -103,3 +106,9 @@ show_nickname_prefix: false # What should the prefix before nicknames be? nickname_prefix: "~" + +# The maximum length for nicknames +nickname_length_limit: 20 + +# Should formatting codes such as "&3" be counted in the length of the nickname? +nickname_length_limit_formatting: false