From 4f1f9523e89c88efb9a56b0733c91dee6f94e0b5 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Thu, 12 Dec 2024 20:14:00 -0500 Subject: [PATCH 01/26] Honestly overkill, allows addons to check for updates though --- .../java/com/dre/brewery/BreweryPlugin.java | 13 +-- .../commands/subcommands/VersionCommand.java | 6 +- .../brewery/configuration/files/Config.java | 4 +- .../dre/brewery/listeners/PlayerListener.java | 3 +- .../dre/brewery/utility/UpdateChecker.java | 102 ---------------- .../utility/releases/ReleaseChecker.java | 109 ++++++++++++++++++ .../releases/impl/GitHubReleaseChecker.java | 79 +++++++++++++ .../releases/impl/NoImplReleaseChecker.java | 49 ++++++++ .../releases/impl/SpigotReleaseChecker.java | 62 ++++++++++ src/main/resources/config-langs/de.yml | 4 +- src/main/resources/config-langs/en.yml | 4 +- src/main/resources/config-langs/es.yml | 4 +- src/main/resources/config-langs/fr.yml | 4 +- src/main/resources/config-langs/it.yml | 4 +- src/main/resources/config-langs/ru.yml | 4 +- src/main/resources/config-langs/zh.yml | 4 +- 16 files changed, 327 insertions(+), 128 deletions(-) delete mode 100644 src/main/java/com/dre/brewery/utility/UpdateChecker.java create mode 100644 src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java create mode 100644 src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java create mode 100644 src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java create mode 100644 src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java diff --git a/src/main/java/com/dre/brewery/BreweryPlugin.java b/src/main/java/com/dre/brewery/BreweryPlugin.java index 02cd3462..48b2fbb5 100644 --- a/src/main/java/com/dre/brewery/BreweryPlugin.java +++ b/src/main/java/com/dre/brewery/BreweryPlugin.java @@ -50,7 +50,7 @@ import com.dre.brewery.storage.StorageInitException; import com.dre.brewery.utility.Logging; import com.dre.brewery.utility.MinecraftVersion; -import com.dre.brewery.utility.UpdateChecker; +import com.dre.brewery.utility.releases.ReleaseChecker; import com.github.Anon8281.universalScheduler.UniversalScheduler; import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler; import io.papermc.lib.PaperLib; @@ -76,8 +76,6 @@ @Getter public class BreweryPlugin extends JavaPlugin { - private static final int RESOURCE_ID = 114777; - private @Getter static AddonManager addonManager; private @Getter static TaskScheduler scheduler; private @Getter static BreweryPlugin instance; @@ -202,16 +200,17 @@ public void onEnable() { placeholderAPIHook.getInstance().register(); } - if (config.isUpdateCheck()) { - UpdateChecker.run(RESOURCE_ID); - } - Logging.log("Using scheduler&7: &a" + scheduler.getClass().getSimpleName()); Logging.log("Environment&7: &a" + Logging.getEnvironmentAsString()); if (!PaperLib.isPaper()) { Logging.log("&aBreweryX performs best on Paper-based servers. Please consider switching to Paper for the best experience. &7https://papermc.io"); } Logging.log("BreweryX enabled!"); + + ReleaseChecker releaseChecker = ReleaseChecker.getInstance(); + releaseChecker.checkForUpdate().thenAccept(updateAvailable -> { + releaseChecker.notify(Bukkit.getConsoleSender()); + }); } @Override diff --git a/src/main/java/com/dre/brewery/commands/subcommands/VersionCommand.java b/src/main/java/com/dre/brewery/commands/subcommands/VersionCommand.java index 9502cb8a..685d2d96 100644 --- a/src/main/java/com/dre/brewery/commands/subcommands/VersionCommand.java +++ b/src/main/java/com/dre/brewery/commands/subcommands/VersionCommand.java @@ -26,7 +26,7 @@ import com.dre.brewery.commands.SubCommand; import com.dre.brewery.configuration.files.Lang; import com.dre.brewery.utility.Logging; -import com.dre.brewery.utility.UpdateChecker; +import com.dre.brewery.utility.releases.ReleaseChecker; import org.bukkit.command.CommandSender; import java.util.List; @@ -45,7 +45,9 @@ public void execute(BreweryPlugin breweryPlugin, Lang lang, CommandSender sender } } - Logging.msg(sender, "&2BreweryX version&7: &av" + breweryPlugin.getDescription().getVersion() + " &7(Latest: v" + UpdateChecker.getLatestVersion() + ")"); + ReleaseChecker rc = ReleaseChecker.getInstance(); + + Logging.msg(sender, "&2BreweryX version&7: &av" + rc.localVersion() + " &7(Latest: v" + rc.getResolvedLatestVersion() + ")"); Logging.msg(sender, "&2Original authors&7: &aGrafe, TTTheKing, Sn0wStorm"); Logging.msg(sender, "&dBreweryX authors&7: &aJsinco, Mitality, Nadwey, Szarkans, Vutka1"); Logging.msg(sender, "&2Loaded addons&7: &a" + addonString); diff --git a/src/main/java/com/dre/brewery/configuration/files/Config.java b/src/main/java/com/dre/brewery/configuration/files/Config.java index 03c1aa9f..e638badc 100644 --- a/src/main/java/com/dre/brewery/configuration/files/Config.java +++ b/src/main/java/com/dre/brewery/configuration/files/Config.java @@ -20,7 +20,6 @@ package com.dre.brewery.configuration.files; -import com.dre.brewery.BreweryPlugin; import com.dre.brewery.configuration.AbstractOkaeriConfigFile; import com.dre.brewery.configuration.annotation.DefaultCommentSpace; import com.dre.brewery.configuration.annotation.Footer; @@ -34,6 +33,7 @@ import com.dre.brewery.configuration.sector.capsule.ConfiguredDataManager; import com.dre.brewery.storage.DataManagerType; import com.dre.brewery.utility.Logging; +import com.dre.brewery.utility.releases.ReleaseChecker; import eu.okaeri.configs.annotation.Header; import lombok.Getter; import lombok.Setter; @@ -64,7 +64,7 @@ public void onFirstCreation() { private String language = "en"; @LocalizedComment("config.updateCheck") - private boolean updateCheck = true; + private ReleaseChecker.ReleaseCheckerType resolveUpdatesFrom = ReleaseChecker.ReleaseCheckerType.GITHUB; @LocalizedComment("config.autosave") private int autosave = 10; diff --git a/src/main/java/com/dre/brewery/listeners/PlayerListener.java b/src/main/java/com/dre/brewery/listeners/PlayerListener.java index 37565b37..625d23f6 100644 --- a/src/main/java/com/dre/brewery/listeners/PlayerListener.java +++ b/src/main/java/com/dre/brewery/listeners/PlayerListener.java @@ -26,6 +26,7 @@ import com.dre.brewery.configuration.files.Lang; import com.dre.brewery.utility.*; import com.dre.brewery.utility.MaterialUtil; +import com.dre.brewery.utility.releases.ReleaseChecker; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.Sound; @@ -299,11 +300,11 @@ public void onPlayerLogin(PlayerLoginEvent event) { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { - UpdateChecker.notify(event.getPlayer()); BPlayer bplayer = BPlayer.get(event.getPlayer()); if (bplayer != null) { bplayer.join(event.getPlayer()); } + ReleaseChecker.getInstance().notify(event.getPlayer()); } @EventHandler diff --git a/src/main/java/com/dre/brewery/utility/UpdateChecker.java b/src/main/java/com/dre/brewery/utility/UpdateChecker.java deleted file mode 100644 index 731731f6..00000000 --- a/src/main/java/com/dre/brewery/utility/UpdateChecker.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * BreweryX Bukkit-Plugin for an alternate brewing process - * Copyright (C) 2024 The Brewery Team - * - * This file is part of BreweryX. - * - * BreweryX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BreweryX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with BreweryX. If not, see . - */ - -package com.dre.brewery.utility; - -import com.dre.brewery.BreweryPlugin; -import com.dre.brewery.configuration.ConfigManager; -import com.dre.brewery.configuration.files.Lang; -import lombok.Getter; -import lombok.Setter; -import org.bukkit.entity.Player; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Scanner; -import java.util.function.Consumer; -import java.util.logging.Level; - - -/** - * Update Checker modified for BreweryX - */ - -public class UpdateChecker { - - private static final BreweryPlugin plugin = BreweryPlugin.getInstance(); - private static final Lang lang = ConfigManager.getConfig(Lang.class); - - @Getter @Setter - private static String latestVersion = "Unknown"; - @Getter @Setter - private static boolean updateAvailable = false; - - private final int resourceID; - - public UpdateChecker(int resourceID) { - this.resourceID = resourceID; - } - - public static void notify(final Player player) { - if (!updateAvailable || !player.hasPermission("brewery.update")) { - return; - } - - lang.sendEntry(player, "Etc_UpdateAvailable", "v" + plugin.getDescription().getVersion(), "v" + latestVersion); - } - - /** - * Query the API to find the latest approved file's details. - */ - public void query(final Consumer consumer) { - BreweryPlugin.getScheduler().runTaskAsynchronously(() -> { - try (InputStream is = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + resourceID + "/~").openStream(); Scanner scann = new Scanner(is)) { - if (scann.hasNext()) { - consumer.accept(scann.next()); - } - } catch (IOException e) { - plugin.getLogger().log(Level.WARNING, "Cannot look for updates: " + e); - } - }); - } - - public static int parseVersion(String version) { - StringBuilder sb = new StringBuilder(); - for (char c : version.toCharArray()) { - if (Character.isDigit(c)) { - sb.append(c); - } - } - return Integer.parseInt(sb.toString()); - } - - public static void run(int resourceID) { - new UpdateChecker(resourceID).query(latestVersion -> { - String currentVersion = plugin.getDescription().getVersion(); - - if (UpdateChecker.parseVersion(latestVersion) > UpdateChecker.parseVersion(currentVersion)) { - UpdateChecker.setUpdateAvailable(true); - Logging.log(lang.getEntry("Etc_UpdateAvailable", "v" + currentVersion, "v" + latestVersion)); - } - UpdateChecker.setLatestVersion(latestVersion); - }); - } -} diff --git a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java new file mode 100644 index 00000000..1af85313 --- /dev/null +++ b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java @@ -0,0 +1,109 @@ +/* + * BreweryX Bukkit-Plugin for an alternate brewing process + * Copyright (C) 2024 The Brewery Team + * + * This file is part of BreweryX. + * + * BreweryX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BreweryX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with BreweryX. If not, see . + */ + +package com.dre.brewery.utility.releases; + +import com.dre.brewery.BreweryPlugin; +import com.dre.brewery.configuration.ConfigManager; +import com.dre.brewery.configuration.files.Config; +import com.dre.brewery.configuration.files.Lang; +import com.dre.brewery.utility.releases.impl.GitHubReleaseChecker; +import com.dre.brewery.utility.releases.impl.NoImplReleaseChecker; +import com.dre.brewery.utility.releases.impl.SpigotReleaseChecker; +import lombok.Getter; +import org.bukkit.command.CommandSender; + +import java.util.concurrent.CompletableFuture; + +@Getter +public abstract class ReleaseChecker { + + protected static final String CONST_UNRESOLVED = "Unresolved"; + private static ReleaseChecker instance; + + protected String resolvedLatestVersion = CONST_UNRESOLVED; // Latest version of BX resolved from the source + + + public abstract CompletableFuture resolveLatest(); + + public abstract CompletableFuture checkForUpdate(); + + + public void notify(CommandSender receiver) { + if (receiver.hasPermission("brewery.update") && isUpdateAvailable()) { + ConfigManager.getConfig(Lang.class) + .sendEntry(receiver, "Etc_UpdateAvailable", "v" + localVersion(), "v" + resolvedLatestVersion); + } + } + + + public boolean isUpdateAvailable() { + if (resolvedLatestVersion.equals(CONST_UNRESOLVED)) { + return false; + } + int local = parseVersion(localVersion()); + int resolved = parseVersion(resolvedLatestVersion); + return resolved > local; + } + + + // Singleton + + public static ReleaseChecker getInstance() { + if (instance != null) { + return instance; + } + Config config = ConfigManager.getConfig(Config.class); + switch (config.getResolveUpdatesFrom()) { + case GITHUB -> instance = new GitHubReleaseChecker("BreweryTeam", "BreweryX"); + case SPIGOT -> instance = new SpigotReleaseChecker(114777); + case NONE -> instance = new NoImplReleaseChecker(); + } + return instance; + } + + + // Util + public String localVersion() { + String versionString = BreweryPlugin.getInstance().getDescription().getVersion(); + if (versionString.contains(";")) { + // I don't care about the branch + return versionString.split(";")[0]; + } + return versionString; + } + + public int parseVersion(String version) { + StringBuilder sb = new StringBuilder(); + for (char c : version.toCharArray()) { + if (Character.isDigit(c)) { + sb.append(c); + } + } + return Integer.parseInt(sb.toString()); + } + + + public enum ReleaseCheckerType { + GITHUB, + SPIGOT, + NONE + } +} diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java new file mode 100644 index 00000000..20e5bd5c --- /dev/null +++ b/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java @@ -0,0 +1,79 @@ +/* + * BreweryX Bukkit-Plugin for an alternate brewing process + * Copyright (C) 2024 The Brewery Team + * + * This file is part of BreweryX. + * + * BreweryX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BreweryX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with BreweryX. If not, see . + */ + +package com.dre.brewery.utility.releases.impl; + +import com.dre.brewery.utility.Logging; +import com.dre.brewery.utility.releases.ReleaseChecker; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.concurrent.CompletableFuture; + +public class GitHubReleaseChecker extends ReleaseChecker { + + private static final String CONST_URL = "https://api.github.com/repos/%s/%s/releases/latest"; + private static final String CONST_JSON_FIELD = "tag_name"; + + private final String link; + + public GitHubReleaseChecker(String owner, String repo) { + this.link = String.format(CONST_URL, owner, repo); + } + + @Override + public CompletableFuture resolveLatest() { + if (resolvedLatestVersion != null) { + return CompletableFuture.completedFuture(resolvedLatestVersion); + } + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(link)) + .GET() + .build(); + + return CompletableFuture.supplyAsync(() -> { + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + JsonObject jsonResponse = JsonParser.parseString(response.body()).getAsJsonObject(); + this.resolvedLatestVersion = jsonResponse.get(CONST_JSON_FIELD).getAsString(); + return this.resolvedLatestVersion; + } catch (IOException | InterruptedException e) { + Logging.warningLog("Failed to resolve latest BreweryX version from GitHub. (No connection?)"); + return CONST_UNRESOLVED; + } + }); + } + + @Override + public CompletableFuture checkForUpdate() { + return resolveLatest().thenApply(v -> { + if (v.equals(CONST_UNRESOLVED)) { + return false; + } + return isUpdateAvailable(); + }); + } +} diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java new file mode 100644 index 00000000..8c03c64c --- /dev/null +++ b/src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java @@ -0,0 +1,49 @@ +/* + * BreweryX Bukkit-Plugin for an alternate brewing process + * Copyright (C) 2024 The Brewery Team + * + * This file is part of BreweryX. + * + * BreweryX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BreweryX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with BreweryX. If not, see . + */ + +package com.dre.brewery.utility.releases.impl; + +import com.dre.brewery.utility.releases.ReleaseChecker; +import org.bukkit.command.CommandSender; + +import java.util.concurrent.CompletableFuture; + +public class NoImplReleaseChecker extends ReleaseChecker { + + @Override + public CompletableFuture resolveLatest() { + return CompletableFuture.completedFuture(CONST_UNRESOLVED); + } + + @Override + public boolean isUpdateAvailable() { + return false; + } + + @Override + public CompletableFuture checkForUpdate() { + return CompletableFuture.completedFuture(false); + } + + @Override + public void notify(CommandSender receiver) { + // No implementation + } +} diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java new file mode 100644 index 00000000..e9d84dd2 --- /dev/null +++ b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java @@ -0,0 +1,62 @@ +/* + * BreweryX Bukkit-Plugin for an alternate brewing process + * Copyright (C) 2024 The Brewery Team + * + * This file is part of BreweryX. + * + * BreweryX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BreweryX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with BreweryX. If not, see . + */ + +package com.dre.brewery.utility.releases.impl; + +import com.dre.brewery.utility.releases.ReleaseChecker; + +import java.io.IOException; +import java.net.URL; +import java.util.Scanner; +import java.util.concurrent.CompletableFuture; + +public class SpigotReleaseChecker extends ReleaseChecker { + + private static final String CONST_URL = "https://api.spigotmc.org/legacy/update.php?resource=%s/~"; + + private final String link; + + public SpigotReleaseChecker(int resourceId) { + this.link = String.format(CONST_URL, resourceId); + } + + @Override + public CompletableFuture resolveLatest() { + if (resolvedLatestVersion != null) { + return CompletableFuture.completedFuture(resolvedLatestVersion); + } + return CompletableFuture.supplyAsync(() -> { + try (Scanner scanner = new Scanner(new URL(link).openStream())) { + if (scanner.hasNext()) { + this.resolvedLatestVersion = scanner.next(); + return this.resolvedLatestVersion; + } + return CONST_UNRESOLVED; + } catch (IOException e) { + return CONST_UNRESOLVED; + } + }); + } + + @Override + public CompletableFuture checkForUpdate() { + return resolveLatest().thenApply(ignored -> isUpdateAvailable()); + } +} diff --git a/src/main/resources/config-langs/de.yml b/src/main/resources/config-langs/de.yml index f63fd224..89860011 100644 --- a/src/main/resources/config-langs/de.yml +++ b/src/main/resources/config-langs/de.yml @@ -6,8 +6,8 @@ config: Sprachedatei die genutzt werden sollte [en] Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | - Aktiviert das Suchen nach Updates für Brewery mit der spigot api [true] - Wenn ein Update gefunden wurde, wird dies bei Serverstart im log angezeigt, sowie OPs benachrichtigt + Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. + Options available: GitHub, Spigot, None [GitHub] autosave: "Autosave Intervall in Minuten [10]" pluginPrefix: "Prefix used on messages" debug: "Debug Nachrichten im Log anzeigen [false]" diff --git a/src/main/resources/config-langs/en.yml b/src/main/resources/config-langs/en.yml index 7d251126..0a2b50a0 100644 --- a/src/main/resources/config-langs/en.yml +++ b/src/main/resources/config-langs/en.yml @@ -6,8 +6,8 @@ config: The translation to be used [en] Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | - Enable checking for Updates, Checks the Spigot api for updates to BreweryX [true] - If an Update is found a Message is logged on Server-start and displayed to OPs joining the game + Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. + Options available: GitHub, Spigot, None [GitHub] autosave: "Autosave interval in minutes [10]" pluginPrefix: "Prefix used on messages" debug: "Show debug messages in logs [false]" diff --git a/src/main/resources/config-langs/es.yml b/src/main/resources/config-langs/es.yml index 233270e2..821946d3 100644 --- a/src/main/resources/config-langs/es.yml +++ b/src/main/resources/config-langs/es.yml @@ -6,8 +6,8 @@ config: La traducción a utilizar Tipos disponibles: en (Inglés), de (Alemán), es (Español), fr (Francés), it (Italiano), ru (Ruso), zh (Chino) updateCheck: | - Activa la comprobación de actualizaciones, pregunta a la API de Spigot por actualizaciones de BreweryX [true] - Si se encuentra una nueva versión, se registra un mensaje en el inicio del servidor y se muestra a OPs al unirse + Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. + Options available: GitHub, Spigot, None [GitHub] autosave: "Intervalo de autoguardado en minutos [10]" pluginPrefix: "Prefijo usado en los mensajes" debug: "Mostrar mensajes de depuración en los registros [false]" diff --git a/src/main/resources/config-langs/fr.yml b/src/main/resources/config-langs/fr.yml index dde480c2..d77cb0e9 100644 --- a/src/main/resources/config-langs/fr.yml +++ b/src/main/resources/config-langs/fr.yml @@ -10,8 +10,8 @@ config: Fichier de langage à utiliser [en] Valeurs disponibles: en (Anglais), de (Allemande), es (Espagnol), fr (Français), it (Italien), ru (Russe), zh (Chinois) updateCheck: | - Activer la cherche de mises à jour. Cherche l’API CurseForge pour les mises à jour. [true] - Si une mise à jour est trouvé, un message sera enregistré lors du démarage du serveur. Il sera également affiché aux joueurs OP quand ils se connectent. + Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. + Options available: GitHub, Spigot, None [GitHub] autosave: "Intervale de la sauvegarde automatique en minutes [10]" pluginPrefix: "Préfixe utilisé avec les messages BreweryX" debug: "Afficher les messages de débogue dans le journal du serveur (log) [false]" diff --git a/src/main/resources/config-langs/it.yml b/src/main/resources/config-langs/it.yml index b454c456..8635280f 100644 --- a/src/main/resources/config-langs/it.yml +++ b/src/main/resources/config-langs/it.yml @@ -6,8 +6,8 @@ config: Lingua da usare [en] Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | - Abilita il controllo degli aggiornamenti, controlla l'API di Spigot per eventuali aggiornamenti di Brewery [true] - Se quando un aggiornamento viene trovato un messaggio è loggato e mostrato agli OPs quando entrano in gioco. + Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. + Options available: GitHub, Spigot, None [GitHub] autosave: "Intervallo di autosalvataggio in minuti [10]" pluginPrefix: "Prefix used on messages" debug: "Show debug messages in logs [false]" diff --git a/src/main/resources/config-langs/ru.yml b/src/main/resources/config-langs/ru.yml index 1e5d0a53..9048f115 100644 --- a/src/main/resources/config-langs/ru.yml +++ b/src/main/resources/config-langs/ru.yml @@ -6,8 +6,8 @@ config: Какой файл локализации использовать [en] Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | - Включить ли проверку обновлений. Проверяет API Spigot на предмет обновлений для BreweryX [true] - Если обнаружено новое обновление, администраторы получат об этом сообщение при входе в игру + Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. + Options available: GitHub, Spigot, None [GitHub] autosave: "Период автосохранения данных (в минутах) [10]" pluginPrefix: | Префикс плагина, используемый в сообщениях. diff --git a/src/main/resources/config-langs/zh.yml b/src/main/resources/config-langs/zh.yml index d17736e3..07c889d7 100644 --- a/src/main/resources/config-langs/zh.yml +++ b/src/main/resources/config-langs/zh.yml @@ -6,8 +6,8 @@ config: 语言文件 [en] Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | - 是否检查更新 [true] - 若有更新, 服务端后台与上线时的管理员会收到通知 + Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. + Options available: GitHub, Spigot, None [GitHub] autosave: "自动保存时间间隔, 单位:分钟 [10]" pluginPrefix: "用于此插件的消息前缀[Brewery]" debug: "是否在日志中显示调试信息 [false]" From cfa866324c0c0cdf03e005569b5869db159acf54 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Fri, 13 Dec 2024 19:56:18 -0500 Subject: [PATCH 02/26] fix BreweryPluginItem --- .../integration/item/BreweryPluginItem.java | 14 +++++++------- .../releases/impl/SpigotReleaseChecker.java | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/dre/brewery/integration/item/BreweryPluginItem.java b/src/main/java/com/dre/brewery/integration/item/BreweryPluginItem.java index dfd5f024..661aa1b6 100644 --- a/src/main/java/com/dre/brewery/integration/item/BreweryPluginItem.java +++ b/src/main/java/com/dre/brewery/integration/item/BreweryPluginItem.java @@ -23,7 +23,6 @@ import com.dre.brewery.Brew; import com.dre.brewery.recipe.BRecipe; import com.dre.brewery.recipe.PluginItem; -import org.bukkit.ChatColor; import org.bukkit.inventory.ItemStack; /** @@ -38,12 +37,13 @@ public class BreweryPluginItem extends PluginItem { @Override public boolean matches(ItemStack item) { Brew brew = Brew.get(item); - if (brew != null) { - BRecipe recipe = brew.getCurrentRecipe(); - if (recipe != null) { - return recipe.getRecipeName().equalsIgnoreCase(getItemId()) || recipe.getName(10).equalsIgnoreCase(getItemId()); - } - return ChatColor.stripColor(item.getItemMeta().getDisplayName()).equalsIgnoreCase(getItemId()); + if (brew == null) { + return false; + } + + BRecipe recipe = brew.getCurrentRecipe(); + if (recipe != null) { + return this.getItemId().equalsIgnoreCase(recipe.getId()); } return false; } diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java index e9d84dd2..5acd687e 100644 --- a/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java @@ -20,6 +20,7 @@ package com.dre.brewery.utility.releases.impl; +import com.dre.brewery.utility.Logging; import com.dre.brewery.utility.releases.ReleaseChecker; import java.io.IOException; @@ -50,6 +51,7 @@ public CompletableFuture resolveLatest() { } return CONST_UNRESOLVED; } catch (IOException e) { + Logging.warningLog("Failed to resolve latest BreweryX version from SpigotMC. (No connection?)"); return CONST_UNRESOLVED; } }); From e7cbc858eba1a81bd545c92a7054d270c602e7ec Mon Sep 17 00:00:00 2001 From: Jsinco Date: Sat, 14 Dec 2024 18:37:46 -0500 Subject: [PATCH 03/26] need to expose more addon api --- build.gradle.kts | 4 +- .../dre/brewery/api/addons/AddonManager.java | 2 + .../dre/brewery/api/addons/BreweryAddon.java | 37 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7350b9bd..23d1bcdc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,9 @@ dependencies { compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.7") compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.3.0-SNAPSHOT") // https://dev.bukkit.org/projects/worldedit/files compileOnly("com.sk89q.worldedit:worldedit-core:7.3.0-SNAPSHOT") // https://dev.bukkit.org/projects/worldguard/files - compileOnly("com.griefcraft.lwc:LWCX:2.2.9-dev")// https://www.spigotmc.org/resources/lwc-extended.69551/history + compileOnly("com.griefcraft.lwc:LWCX:2.4.0") { // https://www.spigotmc.org/resources/lwc-extended.69551/history + exclude("com.google") + } compileOnly("com.github.TechFortress:GriefPrevention:16.18") // https://www.spigotmc.org/resources/griefprevention.1884/history compileOnly("de.diddiz:logblock:1.16.5.1") // https://www.spigotmc.org/resources/logblock.67333/history compileOnly("com.github.Slimefun:Slimefun4:RC-35") // https://github.com/Slimefun/Slimefun4/releases diff --git a/src/main/java/com/dre/brewery/api/addons/AddonManager.java b/src/main/java/com/dre/brewery/api/addons/AddonManager.java index e501acb2..83888a0b 100644 --- a/src/main/java/com/dre/brewery/api/addons/AddonManager.java +++ b/src/main/java/com/dre/brewery/api/addons/AddonManager.java @@ -167,10 +167,12 @@ public void loadAddon(File file) { Field loggerField = BreweryAddon.class.getDeclaredField("logger"); loggerField.setAccessible(true); Field fileManagerField = BreweryAddon.class.getDeclaredField("addonFileManager"); fileManagerField.setAccessible(true); Field addonConfigManagerField = BreweryAddon.class.getDeclaredField("addonConfigManager"); addonConfigManagerField.setAccessible(true); + Field addonFile = BreweryAddon.class.getDeclaredField("addonFile"); addonFile.setAccessible(true); loggerField.set(addon, new AddonLogger(addon.getAddonInfo())); fileManagerField.set(addon, new AddonFileManager(addon, file)); addonConfigManagerField.set(addon, new AddonConfigManager(addon)); + addonFile.set(addon, file); addon.getAddonLogger().info("Loading &a" + addon.getAddonInfo().name() + " &f-&a v" + addon.getAddonInfo().version() + " &fby &a" + addon.getAddonInfo().author()); diff --git a/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java b/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java index 732359ff..6ed9efa8 100644 --- a/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java +++ b/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java @@ -24,14 +24,21 @@ import com.dre.brewery.commands.CommandManager; import com.dre.brewery.utility.MinecraftVersion; import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler; +import com.google.common.reflect.ClassPath; import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; /** * Entry and exit point for a BreweryX addon. Addon classes should be annotated with {@link AddonInfo}. @@ -81,6 +88,7 @@ public abstract class BreweryAddon { private AddonLogger logger; private AddonFileManager addonFileManager; private AddonConfigManager addonConfigManager; + private File addonFile; public void onAddonPreEnable() { @@ -133,6 +141,13 @@ public AddonLogger getAddonLogger() { return logger; } + + @NotNull + public File getAddonFile() { + return addonFile; + } + + /** * Register a listener with the server. * @param listener The listener to register @@ -246,4 +261,26 @@ public boolean isFolia() { public boolean isPaper() { return PaperLib.isPaper(); } + + + // Exposed Reflection API for addons. + + /** + * For addons to reflectively discover their own classes, they must reference their own Jar. + * @param packageName Package to search + * @return Set of classes in the package + */ + public Set> findClasses(String packageName) throws IOException { + URLClassLoader classLoader = new URLClassLoader( + new URL[] { getAddonFile().toURI().toURL() }, + this.getClass().getClassLoader() + ); + return ClassPath.from(classLoader) + .getAllClasses() + .stream() + .filter(clazz -> clazz.getPackageName() + .equalsIgnoreCase(packageName)) // should just be equals instead of equalsIgnoreCase probs + .map(ClassPath.ClassInfo::load) + .collect(Collectors.toSet()); + } } From 5a665fdcbe489dd8422bc60d8218bcbd1006eeb3 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Sat, 14 Dec 2024 18:38:59 -0500 Subject: [PATCH 04/26] bump vers before i publish --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 23d1bcdc..fa2f6fd7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ val langVersion = 17 val encoding = "UTF-8" group = "com.dre.brewery" -version = "3.4.4" +version = "3.4.5-SNAPSHOT" repositories { mavenCentral() From 54d137a5882ad5282984dc86f010a7198b2750d4 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Sat, 14 Dec 2024 18:43:58 -0500 Subject: [PATCH 05/26] lwc dependency being annoying --- build.gradle.kts | 2 +- src/main/java/com/dre/brewery/integration/barrel/LWCBarrel.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index fa2f6fd7..e99c37d1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ dependencies { compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.7") compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.3.0-SNAPSHOT") // https://dev.bukkit.org/projects/worldedit/files compileOnly("com.sk89q.worldedit:worldedit-core:7.3.0-SNAPSHOT") // https://dev.bukkit.org/projects/worldguard/files - compileOnly("com.griefcraft.lwc:LWCX:2.4.0") { // https://www.spigotmc.org/resources/lwc-extended.69551/history + compileOnly("com.griefcraft:lwc:2.3.2") { // https://www.spigotmc.org/resources/lwc-extended.69551/history exclude("com.google") } compileOnly("com.github.TechFortress:GriefPrevention:16.18") // https://www.spigotmc.org/resources/griefprevention.1884/history diff --git a/src/main/java/com/dre/brewery/integration/barrel/LWCBarrel.java b/src/main/java/com/dre/brewery/integration/barrel/LWCBarrel.java index 7510c4f9..1377231e 100644 --- a/src/main/java/com/dre/brewery/integration/barrel/LWCBarrel.java +++ b/src/main/java/com/dre/brewery/integration/barrel/LWCBarrel.java @@ -21,7 +21,6 @@ package com.dre.brewery.integration.barrel; import com.dre.brewery.Barrel; -import com.dre.brewery.BreweryPlugin; import com.dre.brewery.utility.Logging; import com.griefcraft.listeners.LWCPlayerListener; import com.griefcraft.lwc.LWC; From 641b581d4c82d71f540ae21d6e02415b15f274d5 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Sat, 14 Dec 2024 19:08:06 -0500 Subject: [PATCH 06/26] give the previous event on BrewDrinkEvent --- build.gradle.kts | 2 +- src/main/java/com/dre/brewery/BPlayer.java | 5 +- .../api/events/brew/BrewDrinkEvent.java | 38 +++++------- .../commands/subcommands/DrinkCommand.java | 2 +- .../dre/brewery/listeners/PlayerListener.java | 62 +++++++++---------- 5 files changed, 49 insertions(+), 60 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e99c37d1..d394be88 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -120,7 +120,7 @@ tasks { build { dependsOn(shadowJar) - finalizedBy("kotlinReducedJar") + //finalizedBy("kotlinReducedJar") } jar { diff --git a/src/main/java/com/dre/brewery/BPlayer.java b/src/main/java/com/dre/brewery/BPlayer.java index 9ec6a95d..037a0173 100644 --- a/src/main/java/com/dre/brewery/BPlayer.java +++ b/src/main/java/com/dre/brewery/BPlayer.java @@ -48,6 +48,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Item; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -189,13 +190,13 @@ public static void clear() { } // Drink a brew and apply effects, etc. - public static boolean drink(Brew brew, ItemMeta meta, Player player) { + public static boolean drink(Brew brew, Player player, @Nullable ItemMeta meta, @Nullable PlayerItemConsumeEvent event) { BPlayer bPlayer = get(player); if (bPlayer == null) { bPlayer = addPlayer(player); } // In this event the added alcohol amount is calculated, based on the sensitivity permission - BrewDrinkEvent drinkEvent = new BrewDrinkEvent(brew, meta, player, bPlayer); + BrewDrinkEvent drinkEvent = new BrewDrinkEvent(brew, meta, player, bPlayer, event); if (meta != null) { BreweryPlugin.getInstance().getServer().getPluginManager().callEvent(drinkEvent); if (brew != drinkEvent.getBrew()) brew = drinkEvent.getBrew(); diff --git a/src/main/java/com/dre/brewery/api/events/brew/BrewDrinkEvent.java b/src/main/java/com/dre/brewery/api/events/brew/BrewDrinkEvent.java index 1d0692d1..00436c8a 100644 --- a/src/main/java/com/dre/brewery/api/events/brew/BrewDrinkEvent.java +++ b/src/main/java/com/dre/brewery/api/events/brew/BrewDrinkEvent.java @@ -23,32 +23,42 @@ import com.dre.brewery.BPlayer; import com.dre.brewery.Brew; import com.dre.brewery.utility.PermissionUtil; +import lombok.Getter; +import lombok.Setter; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * A Player Drinks a Brew. *

The amount of alcohol and quality that will be added to the player can be get/set here *

If cancelled the drinking will fail silently */ +@Getter +@Setter public class BrewDrinkEvent extends BrewEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); private final Player player; private final BPlayer bPlayer; - private int alc; + private int addedAlcohol; private int quality; private boolean cancelled; - public BrewDrinkEvent(Brew brew, ItemMeta meta, Player player, BPlayer bPlayer) { + @Nullable // Null if drinking from command + private PlayerItemConsumeEvent predecessorEvent; + + public BrewDrinkEvent(Brew brew, ItemMeta meta, Player player, BPlayer bPlayer, @Nullable PlayerItemConsumeEvent predecessor) { super(brew, meta); this.player = player; this.bPlayer = bPlayer; - alc = calcAlcWSensitivity(brew.getOrCalcAlc()); + addedAlcohol = calcAlcWSensitivity(brew.getOrCalcAlc()); quality = brew.getQuality(); + predecessorEvent = predecessor; } /** @@ -66,31 +76,11 @@ public int calcAlcWSensitivity(int alc) { if (sensitive == 0) { alc = 0; } else if (sensitive > 0) { - alc *= ((float) sensitive) / 100f; + alc *= (int) (((float) sensitive) / 100f); } return alc; } - public Player getPlayer() { - return player; - } - - public BPlayer getbPlayer() { - return bPlayer; - } - - public int getAddedAlcohol() { - return alc; - } - - public void setAddedAlcohol(int alc) { - this.alc = alc; - } - - public int getQuality() { - return quality; - } - public void setQuality(int quality) { if (quality > 10 || quality < 0) { throw new IllegalArgumentException("Quality must be in range from 0 to 10"); diff --git a/src/main/java/com/dre/brewery/commands/subcommands/DrinkCommand.java b/src/main/java/com/dre/brewery/commands/subcommands/DrinkCommand.java index 3945a3ed..e50a9c7f 100644 --- a/src/main/java/com/dre/brewery/commands/subcommands/DrinkCommand.java +++ b/src/main/java/com/dre/brewery/commands/subcommands/DrinkCommand.java @@ -46,7 +46,7 @@ public void execute(BreweryPlugin breweryPlugin, Lang lang, CommandSender sender Player player = brewForPlayer.b(); Brew brew = brewForPlayer.a(); String brewName = brew.getCurrentRecipe().getName(brew.getQuality()); - BPlayer.drink(brew, null, player); + BPlayer.drink(brew, player, null, null); lang.sendEntry(sender, "CMD_Drink", brewName); if (!sender.equals(player)) { diff --git a/src/main/java/com/dre/brewery/listeners/PlayerListener.java b/src/main/java/com/dre/brewery/listeners/PlayerListener.java index 625d23f6..4a3abfa9 100644 --- a/src/main/java/com/dre/brewery/listeners/PlayerListener.java +++ b/src/main/java/com/dre/brewery/listeners/PlayerListener.java @@ -207,38 +207,36 @@ public void onClickAir(PlayerInteractEvent event) { public void onPlayerItemConsume(PlayerItemConsumeEvent event) { Player player = event.getPlayer(); ItemStack item = event.getItem(); - if (item != null) { - if (item.getType() == Material.POTION) { - Brew brew = Brew.get(item); - if (brew != null) { - if (!BPlayer.drink(brew, item.getItemMeta(), player)) { - event.setCancelled(true); - return; - } - /*if (player.getGameMode() != org.bukkit.GameMode.CREATIVE) { - brew.remove(item); - }*/ - if (VERSION.isOrLater(MinecraftVersion.V1_9)) { - if (player.getGameMode() != GameMode.CREATIVE) { - // replace the potion with an empty potion to avoid effects - event.setItem(new ItemStack(Material.POTION)); - } else { - // Don't replace the item when keeping the potion, just cancel the event - event.setCancelled(true); - } - } - } - } else if (BUtil.getMaterialMap(config.getDrainItems()).containsKey(item.getType())) { - BPlayer bplayer = BPlayer.get(player); - if (bplayer != null) { - bplayer.drainByItem(player, item.getType()); - if (config.isShowStatusOnDrink()) { - bplayer.showDrunkeness(player); - } - } - } - } - } + if (item.getType() == Material.POTION) { + Brew brew = Brew.get(item); + if (brew != null) { + if (!BPlayer.drink(brew, player, item.getItemMeta(), event)) { + event.setCancelled(true); + return; + } + /*if (player.getGameMode() != org.bukkit.GameMode.CREATIVE) { + brew.remove(item); + }*/ + if (VERSION.isOrLater(MinecraftVersion.V1_9)) { + if (player.getGameMode() != GameMode.CREATIVE) { +// replace the potion with an empty potion to avoid effects + event.setItem(new ItemStack(Material.POTION)); + } else { +// Don't replace the item when keeping the potion, just cancel the event + event.setCancelled(true); + } + } + } + } else if (BUtil.getMaterialMap(config.getDrainItems()).containsKey(item.getType())) { + BPlayer bplayer = BPlayer.get(player); + if (bplayer != null) { + bplayer.drainByItem(player, item.getType()); + if (config.isShowStatusOnDrink()) { + bplayer.showDrunkeness(player); + } + } + } + } // Player has died! Decrease Drunkeness by 20 @EventHandler From 4fbe83f17fd70ac924238cf4159d484b30ec55b6 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Sun, 15 Dec 2024 23:06:39 -0500 Subject: [PATCH 07/26] relocate google stuff properly --- build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d394be88..70bb2b3a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -143,7 +143,8 @@ tasks { } shadowJar { - relocate("com.google", "com.dre.brewery.depend.google") + relocate("com.google.gson", "com.dre.brewery.depend.google.gson") + relocate("com.google.errorprone", "com.dre.brewery.depend.google.errorprone") relocate("com.github.Anon8281.universalScheduler", "com.dre.brewery.depend.universalScheduler") relocate("eu.okaeri", "com.dre.brewery.depend.okaeri") relocate("com.mongodb", "com.dre.brewery.depend.mongodb") From 7eb9daf3ab205ae7336350d186175fb3ee3fd0b2 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Mon, 16 Dec 2024 01:18:18 -0500 Subject: [PATCH 08/26] fix update checker --- .../brewery/commands/subcommands/ReloadCommand.java | 11 ++++++++++- .../brewery/utility/releases/ReleaseChecker.java | 6 +++++- .../utility/releases/impl/GitHubReleaseChecker.java | 1 + .../utility/releases/impl/SpigotReleaseChecker.java | 13 +++++++++---- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java index 81902276..7def5a16 100644 --- a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java +++ b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java @@ -31,9 +31,11 @@ import com.dre.brewery.configuration.configurer.TranslationManager; import com.dre.brewery.configuration.files.Lang; import com.dre.brewery.utility.Logging; +import com.dre.brewery.utility.releases.ReleaseChecker; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; import java.util.List; @@ -94,7 +96,14 @@ public void execute(BreweryPlugin breweryPlugin, Lang lang, CommandSender sender lang.sendEntry(sender, "CMD_Reload"); } - + ReleaseChecker releaseChecker = ReleaseChecker.getInstance(); + releaseChecker.checkForUpdate(true).thenAccept(updateAvailable -> { + if (!(sender instanceof ConsoleCommandSender consoleSender)) { + releaseChecker.notify(sender); + } else { + releaseChecker.notify(consoleSender); + } + }); } catch (Throwable e) { Logging.errorLog("Something went wrong trying to reload Brewery!", e); } diff --git a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java index 1af85313..c410313a 100644 --- a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java @@ -38,12 +38,16 @@ public abstract class ReleaseChecker { protected static final String CONST_UNRESOLVED = "Unresolved"; private static ReleaseChecker instance; - protected String resolvedLatestVersion = CONST_UNRESOLVED; // Latest version of BX resolved from the source + protected String resolvedLatestVersion = null; // Latest version of BX resolved from the source public abstract CompletableFuture resolveLatest(); public abstract CompletableFuture checkForUpdate(); + public CompletableFuture checkForUpdate(boolean overwriteCache) { + this.resolvedLatestVersion = null; + return checkForUpdate(); + } public void notify(CommandSender receiver) { diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java index 20e5bd5c..353931d6 100644 --- a/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java @@ -62,6 +62,7 @@ public CompletableFuture resolveLatest() { return this.resolvedLatestVersion; } catch (IOException | InterruptedException e) { Logging.warningLog("Failed to resolve latest BreweryX version from GitHub. (No connection?)"); + this.resolvedLatestVersion = CONST_UNRESOLVED; return CONST_UNRESOLVED; } }); diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java index 5acd687e..8f61d7e7 100644 --- a/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java @@ -49,11 +49,10 @@ public CompletableFuture resolveLatest() { this.resolvedLatestVersion = scanner.next(); return this.resolvedLatestVersion; } - return CONST_UNRESOLVED; - } catch (IOException e) { - Logging.warningLog("Failed to resolve latest BreweryX version from SpigotMC. (No connection?)"); - return CONST_UNRESOLVED; + } catch (IOException ignored) { + } + return this.failedToResolve(); }); } @@ -61,4 +60,10 @@ public CompletableFuture resolveLatest() { public CompletableFuture checkForUpdate() { return resolveLatest().thenApply(ignored -> isUpdateAvailable()); } + + public String failedToResolve() { + Logging.warningLog("Failed to resolve latest BreweryX version from SpigotMC. (No connection?)"); + this.resolvedLatestVersion = CONST_UNRESOLVED; + return CONST_UNRESOLVED; + } } From 713675db0fc7463fb8bcdb78561d3128372bc34f Mon Sep 17 00:00:00 2001 From: Jsinco Date: Mon, 16 Dec 2024 01:20:21 -0500 Subject: [PATCH 09/26] fix update checker --- .../java/com/dre/brewery/utility/releases/ReleaseChecker.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java index c410313a..bfcc716c 100644 --- a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java @@ -45,7 +45,9 @@ public abstract class ReleaseChecker { public abstract CompletableFuture checkForUpdate(); public CompletableFuture checkForUpdate(boolean overwriteCache) { - this.resolvedLatestVersion = null; + if (overwriteCache) { + this.resolvedLatestVersion = null; + } return checkForUpdate(); } From bff6b8fa285ceab51062033bbad336b291769937 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Mon, 16 Dec 2024 01:36:22 -0500 Subject: [PATCH 10/26] fix it for real this time --- .../commands/subcommands/ReloadCommand.java | 4 ++-- .../utility/releases/ReleaseChecker.java | 18 ++++++++---------- .../releases/impl/GitHubReleaseChecker.java | 3 --- .../releases/impl/NoImplReleaseChecker.java | 1 + .../releases/impl/SpigotReleaseChecker.java | 3 --- 5 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java index 7def5a16..45321473 100644 --- a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java +++ b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java @@ -96,8 +96,8 @@ public void execute(BreweryPlugin breweryPlugin, Lang lang, CommandSender sender lang.sendEntry(sender, "CMD_Reload"); } - ReleaseChecker releaseChecker = ReleaseChecker.getInstance(); - releaseChecker.checkForUpdate(true).thenAccept(updateAvailable -> { + ReleaseChecker releaseChecker = ReleaseChecker.getInstance(true); + releaseChecker.checkForUpdate().thenAccept(updateAvailable -> { if (!(sender instanceof ConsoleCommandSender consoleSender)) { releaseChecker.notify(sender); } else { diff --git a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java index bfcc716c..f3242751 100644 --- a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java @@ -35,21 +35,15 @@ @Getter public abstract class ReleaseChecker { - protected static final String CONST_UNRESOLVED = "Unresolved"; + protected static final String CONST_UNRESOLVED = "UNRESOLVED"; private static ReleaseChecker instance; - protected String resolvedLatestVersion = null; // Latest version of BX resolved from the source + protected String resolvedLatestVersion = CONST_UNRESOLVED; // Latest version of BX resolved from the source public abstract CompletableFuture resolveLatest(); public abstract CompletableFuture checkForUpdate(); - public CompletableFuture checkForUpdate(boolean overwriteCache) { - if (overwriteCache) { - this.resolvedLatestVersion = null; - } - return checkForUpdate(); - } public void notify(CommandSender receiver) { @@ -72,8 +66,8 @@ public boolean isUpdateAvailable() { // Singleton - public static ReleaseChecker getInstance() { - if (instance != null) { + public static ReleaseChecker getInstance(boolean newInstance) { + if (instance != null && !newInstance) { return instance; } Config config = ConfigManager.getConfig(Config.class); @@ -85,6 +79,10 @@ public static ReleaseChecker getInstance() { return instance; } + public static ReleaseChecker getInstance() { + return getInstance(false); + } + // Util public String localVersion() { diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java index 353931d6..1ec586bf 100644 --- a/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/impl/GitHubReleaseChecker.java @@ -45,9 +45,6 @@ public GitHubReleaseChecker(String owner, String repo) { @Override public CompletableFuture resolveLatest() { - if (resolvedLatestVersion != null) { - return CompletableFuture.completedFuture(resolvedLatestVersion); - } HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(link)) diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java index 8c03c64c..b41fa082 100644 --- a/src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/impl/NoImplReleaseChecker.java @@ -29,6 +29,7 @@ public class NoImplReleaseChecker extends ReleaseChecker { @Override public CompletableFuture resolveLatest() { + this.resolvedLatestVersion = CONST_UNRESOLVED; return CompletableFuture.completedFuture(CONST_UNRESOLVED); } diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java index 8f61d7e7..894fec46 100644 --- a/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/impl/SpigotReleaseChecker.java @@ -40,9 +40,6 @@ public SpigotReleaseChecker(int resourceId) { @Override public CompletableFuture resolveLatest() { - if (resolvedLatestVersion != null) { - return CompletableFuture.completedFuture(resolvedLatestVersion); - } return CompletableFuture.supplyAsync(() -> { try (Scanner scanner = new Scanner(new URL(link).openStream())) { if (scanner.hasNext()) { From 7efe944383305e82302573ed3d0c1891254209e7 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Mon, 16 Dec 2024 16:17:59 -0500 Subject: [PATCH 11/26] improve PotionColor --- .../java/com/dre/brewery/BreweryPlugin.java | 2 +- .../com/dre/brewery/recipe/PotionColor.java | 70 +++++++++---------- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/dre/brewery/BreweryPlugin.java b/src/main/java/com/dre/brewery/BreweryPlugin.java index 48b2fbb5..82d64aa2 100644 --- a/src/main/java/com/dre/brewery/BreweryPlugin.java +++ b/src/main/java/com/dre/brewery/BreweryPlugin.java @@ -74,7 +74,7 @@ import java.util.stream.Collectors; @Getter -public class BreweryPlugin extends JavaPlugin { +public final class BreweryPlugin extends JavaPlugin { private @Getter static AddonManager addonManager; private @Getter static TaskScheduler scheduler; diff --git a/src/main/java/com/dre/brewery/recipe/PotionColor.java b/src/main/java/com/dre/brewery/recipe/PotionColor.java index ee8ccf54..f8b875b1 100644 --- a/src/main/java/com/dre/brewery/recipe/PotionColor.java +++ b/src/main/java/com/dre/brewery/recipe/PotionColor.java @@ -22,6 +22,7 @@ import com.dre.brewery.BreweryPlugin; import com.dre.brewery.utility.MinecraftVersion; +import lombok.Getter; import org.bukkit.Color; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -29,9 +30,10 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionType; - +@Getter public class PotionColor { + private static final String HEX_STRING = "#%02x%02x%02x"; private static final MinecraftVersion VERSION = BreweryPlugin.getMCVersion(); public static final PotionColor PINK = new PotionColor(1, PotionType.REGEN, Color.FUCHSIA); @@ -79,14 +81,6 @@ public short getColorId(boolean destillable) { return (short) (colorId + 32); } - public PotionType getType() { - return type; - } - - public Color getColor() { - return color; - } - @SuppressWarnings("deprecation") public void colorBrew(PotionMeta meta, ItemStack potion, boolean destillable) { if (VERSION.isOrLater(MinecraftVersion.V1_9)) { @@ -106,39 +100,41 @@ public void colorBrew(PotionMeta meta, ItemStack potion, boolean destillable) { } public static PotionColor fromString(String string) { - switch (string) { - case "PINK": return PINK; - case "CYAN": return CYAN; - case "ORANGE": return ORANGE; - case "GREEN": return GREEN; - case "BRIGHT_RED": return BRIGHT_RED; - case "BLUE": return BLUE; - case "BLACK": return BLACK; - case "RED": return RED; - case "GREY": return GREY; - case "WATER": return WATER; - case "DARK_RED": return DARK_RED; - case "BRIGHT_GREY": return BRIGHT_GREY; - case "WHITE": return WHITE; - case "LIME": return LIME; - case "OLIVE": return OLIVE; - case "PURPLE": return PURPLE; - case "TEAL": return TEAL; - case "YELLOW": return YELLOW; - default: + return switch (string.toUpperCase()) { + case "PINK" -> PINK; + case "CYAN" -> CYAN; + case "ORANGE" -> ORANGE; + case "GREEN" -> GREEN; + case "BRIGHT_RED" -> BRIGHT_RED; + case "BLUE" -> BLUE; + case "BLACK" -> BLACK; + case "RED" -> RED; + case "GREY" -> GREY; + case "WATER" -> WATER; + case "DARK_RED" -> DARK_RED; + case "BRIGHT_GREY" -> BRIGHT_GREY; + case "WHITE" -> WHITE; + case "LIME" -> LIME; + case "OLIVE" -> OLIVE; + case "PURPLE" -> PURPLE; + case "TEAL" -> TEAL; + case "YELLOW" -> YELLOW; + default -> { try{ if (string.length() >= 7) { string = string.substring(1); } - return new PotionColor(Color.fromRGB( - Integer.parseInt(string.substring( 0, 2 ), 16 ), - Integer.parseInt(string.substring( 2, 4 ), 16 ), - Integer.parseInt(string.substring( 4, 6 ), 16 ) + yield new PotionColor(Color.fromRGB( + Integer.parseInt(string.substring( 0, 2 ), 16 ), + Integer.parseInt(string.substring( 2, 4 ), 16 ), + Integer.parseInt(string.substring( 4, 6 ), 16 ) )); - } catch (Exception e) { - return WATER; + } catch (NumberFormatException e) { + yield WATER; } - } + } + + }; } public static PotionColor fromColor(Color color) { @@ -147,6 +143,6 @@ public static PotionColor fromColor(Color color) { @Override public String toString() { - return super.toString(); + return String.format(HEX_STRING, color.getRed(), color.getGreen(), color.getBlue()); } } From af07b4456d5fd43e1a435c50a3909f126da49071 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Mon, 16 Dec 2024 19:37:48 -0500 Subject: [PATCH 12/26] add dynamic serdespacks to confighead and addonconfigmanager --- .../api/addons/AddonConfigManager.java | 21 +++++-- .../dre/brewery/configuration/ConfigHead.java | 55 +++++++++++++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/dre/brewery/api/addons/AddonConfigManager.java b/src/main/java/com/dre/brewery/api/addons/AddonConfigManager.java index dcb45b69..18a7a582 100644 --- a/src/main/java/com/dre/brewery/api/addons/AddonConfigManager.java +++ b/src/main/java/com/dre/brewery/api/addons/AddonConfigManager.java @@ -24,6 +24,7 @@ import com.dre.brewery.configuration.ConfigHead; import com.dre.brewery.configuration.annotation.OkaeriConfigFileOptions; import eu.okaeri.configs.configurer.Configurer; +import eu.okaeri.configs.serdes.BidirectionalTransformer; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import org.jetbrains.annotations.Nullable; @@ -40,8 +41,6 @@ public class AddonConfigManager { private final ConfigHead INSTANCE; - - public AddonConfigManager(BreweryAddon addon) { this.INSTANCE = new ConfigHead(BreweryPlugin.getInstance().getDataFolder().toPath().resolve("addons").resolve(addon.getAddonInfo().name())); } @@ -106,16 +105,28 @@ private T createConfig(Class configClass, Path fi * @return The new config instance * @param The type of the config */ - private T createConfig(Class configClass) { + public T createConfig(Class configClass) { return INSTANCE.createConfig(configClass); } @Nullable - private T createBlankConfigInstance(Class configClass) { + public T createBlankConfigInstance(Class configClass) { return INSTANCE.createBlankConfigInstance(configClass); } + public void addSerdesPacks(OkaeriSerdesPack... serdesPacks) { + INSTANCE.addSerdesPacks(serdesPacks); + } + + public void addBiDirectionalTransformers(BidirectionalTransformer... transformers) { + INSTANCE.addBidirectionalTransformers(transformers); + } + + public void addConfigurer(Configurer configurer) { + INSTANCE.addConfigurer(configurer); + } + // Util public void createFileFromResources(String resourcesPath, Path destination) { @@ -123,7 +134,7 @@ public void createFileFromResources(String resourcesPath, Path destination) { } - private OkaeriConfigFileOptions getOkaeriConfigFileOptions(Class configClass) { + public OkaeriConfigFileOptions getOkaeriConfigFileOptions(Class configClass) { return INSTANCE.getOkaeriConfigFileOptions(configClass); } public Path getDataFolder() { diff --git a/src/main/java/com/dre/brewery/configuration/ConfigHead.java b/src/main/java/com/dre/brewery/configuration/ConfigHead.java index eb9bf21b..3bd4d121 100644 --- a/src/main/java/com/dre/brewery/configuration/ConfigHead.java +++ b/src/main/java/com/dre/brewery/configuration/ConfigHead.java @@ -26,6 +26,7 @@ import com.dre.brewery.configuration.configurer.TranslationManager; import com.dre.brewery.utility.Logging; import eu.okaeri.configs.configurer.Configurer; +import eu.okaeri.configs.serdes.BidirectionalTransformer; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import eu.okaeri.configs.serdes.standard.StandardSerdes; import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer; @@ -46,10 +47,10 @@ */ public class ConfigHead { - public static final Map, Supplier> CONFIGURERS = Map.of( - BreweryXConfigurer.class, BreweryXConfigurer::new, - YamlSnakeYamlConfigurer.class, YamlSnakeYamlConfigurer::new - ); + public final Map, Configurer> CONFIGURERS = new HashMap<>(Map.of( + BreweryXConfigurer.class, new BreweryXConfigurer(), + YamlSnakeYamlConfigurer.class, new YamlSnakeYamlConfigurer() + )); public final Map, AbstractOkaeriConfigFile> LOADED_CONFIGS = new HashMap<>(); public Path DATA_FOLDER = BreweryPlugin.getInstance().getDataFolder().toPath(); @@ -151,7 +152,13 @@ public T createConfig(Class configClass, public T createConfig(Class configClass) { OkaeriConfigFileOptions options = getOkaeriConfigFileOptions(configClass); - return createConfig(configClass, getFilePath(configClass), CONFIGURERS.get(options.configurer()).get(), new StandardSerdes(), options.update(), options.removeOrphans()); + Configurer configurer = CONFIGURERS.get(options.configurer()); + if (configurer == null) { + Logging.errorLog("Configurer cannot be null. Make sure you've registered the configurer before trying to use it!"); + configurer = CONFIGURERS.get(BreweryXConfigurer.class); + } + + return createConfig(configClass, getFilePath(configClass), configurer, new StandardSerdes(), options.update(), options.removeOrphans()); } @Nullable @@ -168,6 +175,44 @@ public T createBlankConfigInstance(Class } + /** + * Adds the provided OkaeriSerdesPack instances to all registered configurers. + * Each serdes pack is registered to every configurer in the CONFIGURERS map. + * + * @param packs The array of OkaeriSerdesPack instances to be added to the configurers. + */ + public void addSerdesPacks(OkaeriSerdesPack... packs) { + CONFIGURERS.values().forEach(configurer -> { + for (OkaeriSerdesPack pack : packs) { + configurer.register(pack); + } + }); + } + + /** + * Adds the provided BidirectionalTransformer instances to all registered configurers. + * Each transformer is registered to every configurer in the CONFIGURERS map. + * + * @param transformers The array of BidirectionalTransformer instances to be added to the configurers. + */ + public void addBidirectionalTransformers(BidirectionalTransformer... transformers) { + CONFIGURERS.values().forEach(configurer -> { + for (BidirectionalTransformer transformer : transformers) { + configurer.register(registry -> registry.register(transformer)); + } + }); + } + + /** + * Adds the provided configurer instance to the CONFIGURERS map. + * The configurer is stored with its class as the key. + * + * @param configurer The Configurer instance to be added. + */ + public void addConfigurer(Configurer configurer) { + CONFIGURERS.put(configurer.getClass(), configurer); + } + // Util public void createFileFromResources(String resourcesPath, Path destination) { From 6566065a59f8f5692cd2fba0aab0ce5e4b747b5b Mon Sep 17 00:00:00 2001 From: Jsinco Date: Tue, 17 Dec 2024 01:49:40 -0500 Subject: [PATCH 13/26] ignore casing on PluginItems --- .../dre/brewery/integration/item/ItemsAdderPluginItem.java | 4 ++-- .../java/com/dre/brewery/integration/item/NexoPluginItem.java | 2 +- .../com/dre/brewery/integration/item/OraxenPluginItem.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/dre/brewery/integration/item/ItemsAdderPluginItem.java b/src/main/java/com/dre/brewery/integration/item/ItemsAdderPluginItem.java index 5f97470d..8bcd8355 100644 --- a/src/main/java/com/dre/brewery/integration/item/ItemsAdderPluginItem.java +++ b/src/main/java/com/dre/brewery/integration/item/ItemsAdderPluginItem.java @@ -38,9 +38,9 @@ public boolean matches(ItemStack itemStack) { } if (!this.getItemId().contains(":")) { - return cs.getId().equals(this.getItemId()); + return cs.getId().equalsIgnoreCase(this.getItemId()); } else { - return cs.getNamespacedID().equals(this.getItemId()); + return cs.getNamespacedID().equalsIgnoreCase(this.getItemId()); } } } diff --git a/src/main/java/com/dre/brewery/integration/item/NexoPluginItem.java b/src/main/java/com/dre/brewery/integration/item/NexoPluginItem.java index 2a62438a..ca7002b7 100644 --- a/src/main/java/com/dre/brewery/integration/item/NexoPluginItem.java +++ b/src/main/java/com/dre/brewery/integration/item/NexoPluginItem.java @@ -44,7 +44,7 @@ public boolean matches(ItemStack itemStack) { if (itemId == null) { return false; } - return itemId.equals(this.getItemId()); + return itemId.equalsIgnoreCase(this.getItemId()); } // Nexo's internal API code for getting an item's ID: diff --git a/src/main/java/com/dre/brewery/integration/item/OraxenPluginItem.java b/src/main/java/com/dre/brewery/integration/item/OraxenPluginItem.java index 5b89a7c0..582e45fa 100644 --- a/src/main/java/com/dre/brewery/integration/item/OraxenPluginItem.java +++ b/src/main/java/com/dre/brewery/integration/item/OraxenPluginItem.java @@ -36,6 +36,6 @@ public boolean matches(ItemStack itemStack) { if (itemId == null) { return false; } - return itemId.equals(this.getItemId()); + return itemId.equalsIgnoreCase(this.getItemId()); } } \ No newline at end of file From b20a9c5c863d6c6b862684bf22fb65a946bbf6e7 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Wed, 18 Dec 2024 17:51:46 -0500 Subject: [PATCH 14/26] #68* --- src/main/java/com/dre/brewery/BreweryPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dre/brewery/BreweryPlugin.java b/src/main/java/com/dre/brewery/BreweryPlugin.java index ab81d2db..4778f1ec 100644 --- a/src/main/java/com/dre/brewery/BreweryPlugin.java +++ b/src/main/java/com/dre/brewery/BreweryPlugin.java @@ -157,7 +157,7 @@ public void onEnable() { .filter(Objects::nonNull) .collect(Collectors.toMap( BCauldron::getBlock, Function.identity(), - (existing, replacement) -> replacement // Issues#69 + (existing, replacement) -> replacement // Issues#68 ))); BPlayer.getPlayers().putAll(dataManager.getAllPlayers() .stream() From f7c1fc9fb4b836f234b2686f80bf3cc672f44cb8 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Thu, 19 Dec 2024 03:04:11 -0500 Subject: [PATCH 15/26] fail gracefully when creating new file instances, create new file when reloading if it doesn't exist --- .../commands/subcommands/ReloadCommand.java | 3 +- .../AbstractOkaeriConfigFile.java | 37 +++++++++++++------ .../dre/brewery/configuration/ConfigHead.java | 11 +++++- .../dre/brewery/configuration/files/Lang.java | 15 +++++++- 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java index 45321473..f14e6053 100644 --- a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java +++ b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java @@ -56,8 +56,7 @@ public void execute(BreweryPlugin breweryPlugin, Lang lang, CommandSender sender TranslationManager.newInstance(breweryPlugin.getDataFolder()); // Reload each config - for (var entry : ConfigManager.LOADED_CONFIGS.entrySet()) { - AbstractOkaeriConfigFile file = entry.getValue(); + for (var file : ConfigManager.LOADED_CONFIGS.values()) { try { file.reload(); } catch (Throwable e) { diff --git a/src/main/java/com/dre/brewery/configuration/AbstractOkaeriConfigFile.java b/src/main/java/com/dre/brewery/configuration/AbstractOkaeriConfigFile.java index e6757556..5241f1bb 100644 --- a/src/main/java/com/dre/brewery/configuration/AbstractOkaeriConfigFile.java +++ b/src/main/java/com/dre/brewery/configuration/AbstractOkaeriConfigFile.java @@ -20,7 +20,6 @@ package com.dre.brewery.configuration; -import com.dre.brewery.BreweryPlugin; import com.dre.brewery.utility.Logging; import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Exclude; @@ -29,29 +28,45 @@ import lombok.Setter; import lombok.SneakyThrows; +import java.io.IOException; import java.util.concurrent.CompletableFuture; @Getter @Setter public abstract class AbstractOkaeriConfigFile extends OkaeriConfig { - protected @Exclude transient boolean update = false; - protected @Exclude transient boolean firstCreation = false; - private @Exclude transient boolean blankInstance = false; + @Exclude + protected transient boolean update = false; + @Exclude + protected transient boolean firstCreation = false; + @Exclude + protected transient boolean blankInstance = false; - // Util methods - public void saveAsync() throws OkaeriException { - CompletableFuture.runAsync(this::save); - } @SneakyThrows public void reload() { if (this.blankInstance) { ConfigManager.newInstance(this.getClass(), true); - this.blankInstance = false; - } else { - this.load(update); + return; + } + + this.bindFileExists(true); + this.load(update); + } + + public boolean bindFileExists(boolean createIfNotExist) throws IOException { + if (this.blankInstance) { // Don't create if this is a placeholder instance + return false; + } + boolean b = this.getBindFile().toFile().exists(); + if (!b && createIfNotExist){ + return this.getBindFile().toFile().createNewFile(); } + return b; + } + + public void saveAsync() throws OkaeriException { + CompletableFuture.runAsync(this::save); // swap with normal scheduler? } public void onFirstCreation() { diff --git a/src/main/java/com/dre/brewery/configuration/ConfigHead.java b/src/main/java/com/dre/brewery/configuration/ConfigHead.java index 3bd4d121..fa6a97c3 100644 --- a/src/main/java/com/dre/brewery/configuration/ConfigHead.java +++ b/src/main/java/com/dre/brewery/configuration/ConfigHead.java @@ -79,7 +79,7 @@ public T getConfig(Class configClass) { } return createConfig(configClass); } catch (Throwable e) { - Logging.errorLog("Something went wrong trying to load a config file! &e(" + configClass.getSimpleName() + ".yml)", e); + Logging.errorLog("Something went wrong trying to load a config file! &e(Class: " + configClass.getSimpleName() + ")", e); Logging.warningLog("Resolve the issue in the file and run &6/brewery reload"); return createBlankConfigInstance(configClass); } @@ -94,7 +94,14 @@ public void newInstance(Class configClas if (!overwrite && LOADED_CONFIGS.containsKey(configClass)) { return; } - LOADED_CONFIGS.put(configClass, createConfig(configClass)); + + try { + createConfig(configClass); + } catch (Throwable e) { + Logging.errorLog("Something went wrong trying to load a config file! &e(Class: " + configClass.getSimpleName() + ")", e); + Logging.warningLog("Resolve the issue in the file and run &6/brewery reload"); + createBlankConfigInstance(configClass); + } } diff --git a/src/main/java/com/dre/brewery/configuration/files/Lang.java b/src/main/java/com/dre/brewery/configuration/files/Lang.java index db8613b4..464c1910 100644 --- a/src/main/java/com/dre/brewery/configuration/files/Lang.java +++ b/src/main/java/com/dre/brewery/configuration/files/Lang.java @@ -31,9 +31,12 @@ import eu.okaeri.configs.annotation.CustomKey; import eu.okaeri.configs.annotation.Exclude; import eu.okaeri.configs.annotation.Header; +import lombok.SneakyThrows; import org.bukkit.command.CommandSender; +import java.io.File; import java.lang.reflect.Field; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -50,9 +53,19 @@ public class Lang extends AbstractOkaeriConfigFile { @Exclude private transient Map mappedEntries; + @SneakyThrows @Override // Should override because we need to remap our strings after a reload of this file. public void reload() { - this.setBindFile(ConfigManager.getFilePath(Lang.class)); + if (this.blankInstance) { + super.reload(); + return; + } + Path bind = ConfigManager.getFilePath(Lang.class); + File file = bind.toFile(); + if (!file.exists()) { + file.createNewFile(); + } + this.setBindFile(bind); this.load(this.update); this.mapStrings(); } From ca89dc11a9dfa3a89370b22e13d0d759a2dfa67d Mon Sep 17 00:00:00 2001 From: Jsinco Date: Thu, 19 Dec 2024 03:40:15 -0500 Subject: [PATCH 16/26] moved universalscheduler to different repo --- build.gradle.kts | 3 ++- src/main/java/com/dre/brewery/configuration/ConfigHead.java | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 70bb2b3a..f35a3f99 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,6 +36,7 @@ version = "3.4.5-SNAPSHOT" repositories { mavenCentral() + maven("https://repo.jsinco.dev/releases") // UniversalScheduler maven("https://jitpack.io") // GriefPrevention, SlimeFun, PlaceholderAPI maven("https://repo.md-5.net/content/groups/public/") // Bungee maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // Spigot @@ -65,7 +66,7 @@ dependencies { // Which don't support records. implementation("com.google.code.gson:gson:2.11.0") // For proper scheduling between Bukkit-Folia like servers, https://github.com/Anon8281/UniversalScheduler - implementation("com.github.Anon8281:UniversalScheduler:0.1.3") + implementation("com.github.Anon8281:UniversalScheduler:0.1.3-dev") // Nice annotations, I prefer these to Lombok's, https://www.jetbrains.com/help/idea/annotating-source-code.html implementation("org.jetbrains:annotations:16.0.2") // MongoDB & log4j to suppress MongoDB's logger diff --git a/src/main/java/com/dre/brewery/configuration/ConfigHead.java b/src/main/java/com/dre/brewery/configuration/ConfigHead.java index fa6a97c3..f07deff5 100644 --- a/src/main/java/com/dre/brewery/configuration/ConfigHead.java +++ b/src/main/java/com/dre/brewery/configuration/ConfigHead.java @@ -39,7 +39,6 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import java.util.function.Supplier; /** * A class which manages the creation and retrieval of config files. This class From 0c019c6c1ae3322787497a0bc5d9af6a0fc4b4b1 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Thu, 19 Dec 2024 16:12:42 -0500 Subject: [PATCH 17/26] storage changes --- .../java/com/dre/brewery/BreweryPlugin.java | 9 ++- .../dre/brewery/api/addons/BreweryAddon.java | 11 +++ .../commands/subcommands/ReloadCommand.java | 1 - .../java/com/dre/brewery/recipe/BRecipe.java | 2 +- .../com/dre/brewery/storage/DataManager.java | 13 +++- .../storage/impls/FlatFileStorage.java | 77 ++++++++++++++++++- .../brewery/storage/impls/MongoDBStorage.java | 65 +++++++++++----- .../brewery/storage/impls/MySQLStorage.java | 62 +++++++++++---- .../brewery/storage/impls/SQLiteStorage.java | 58 ++++++++++---- 9 files changed, 244 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/dre/brewery/BreweryPlugin.java b/src/main/java/com/dre/brewery/BreweryPlugin.java index 4778f1ec..6ded8cdf 100644 --- a/src/main/java/com/dre/brewery/BreweryPlugin.java +++ b/src/main/java/com/dre/brewery/BreweryPlugin.java @@ -121,14 +121,17 @@ public void onEnable() { BSealer.registerRecipe(); // Sealing table recipe ConfigManager.registerDefaultPluginItems(); // Register plugin items + + // Load Addons + addonManager = new AddonManager(this); + addonManager.loadAddons(); + ConfigManager.loadCauldronIngredients(); ConfigManager.loadRecipes(); ConfigManager.loadDistortWords(); this.breweryStats = new BreweryStats(); // Load metrics - // Load Addons - addonManager = new AddonManager(this); - addonManager.loadAddons(); + diff --git a/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java b/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java index 6ed9efa8..4afd06c5 100644 --- a/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java +++ b/src/main/java/com/dre/brewery/api/addons/BreweryAddon.java @@ -22,6 +22,7 @@ import com.dre.brewery.BreweryPlugin; import com.dre.brewery.commands.CommandManager; +import com.dre.brewery.storage.DataManager; import com.dre.brewery.utility.MinecraftVersion; import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler; import com.google.common.reflect.ClassPath; @@ -228,6 +229,16 @@ public TaskScheduler getScheduler() { return BreweryPlugin.getScheduler(); } + /** + * Retrieves the DataManager associated with the BreweryX plugin. + * + * @return The DataManager instance + */ + @NotNull + public DataManager getDataManager() { + return BreweryPlugin.getDataManager(); + } + /** * Get the addon manager for BreweryX. * @return The addon manager diff --git a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java index f14e6053..befbdf8f 100644 --- a/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java +++ b/src/main/java/com/dre/brewery/commands/subcommands/ReloadCommand.java @@ -26,7 +26,6 @@ import com.dre.brewery.BreweryPlugin; import com.dre.brewery.commands.CommandUtil; import com.dre.brewery.commands.SubCommand; -import com.dre.brewery.configuration.AbstractOkaeriConfigFile; import com.dre.brewery.configuration.ConfigManager; import com.dre.brewery.configuration.configurer.TranslationManager; import com.dre.brewery.configuration.files.Lang; diff --git a/src/main/java/com/dre/brewery/recipe/BRecipe.java b/src/main/java/com/dre/brewery/recipe/BRecipe.java index b25efc0c..54099095 100644 --- a/src/main/java/com/dre/brewery/recipe/BRecipe.java +++ b/src/main/java/com/dre/brewery/recipe/BRecipe.java @@ -254,7 +254,7 @@ public static List loadIngredients(List stringList, String r continue; } else { // TODO Maybe load later ie on first use of recipe? - Logging.errorLog(recipeId + ": Could not Find Plugin: " + ingredParts[1]); + Logging.errorLog(recipeId + ": Could not Find Plugin: " + Arrays.toString(ingredParts)); return null; } } diff --git a/src/main/java/com/dre/brewery/storage/DataManager.java b/src/main/java/com/dre/brewery/storage/DataManager.java index fac51978..cfdcf333 100644 --- a/src/main/java/com/dre/brewery/storage/DataManager.java +++ b/src/main/java/com/dre/brewery/storage/DataManager.java @@ -36,18 +36,21 @@ import com.dre.brewery.storage.impls.MySQLStorage; import com.dre.brewery.storage.impls.SQLiteStorage; import com.dre.brewery.storage.records.BreweryMiscData; +import com.dre.brewery.storage.records.SerializableThing; import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.Logging; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.UUID; +@Getter public abstract class DataManager { // TODO: Instead of using UUIDs for Barrels, Cauldrons, and Wakeups. We should figure out some hashing algorithm to generate a unique ID for each of them. @@ -55,13 +58,21 @@ public abstract class DataManager { protected static BreweryPlugin plugin = BreweryPlugin.getInstance(); protected static long lastAutoSave = System.currentTimeMillis(); - @Getter private final DataManagerType type; protected DataManager(DataManagerType type) throws StorageInitException { this.type = type; } + public abstract boolean createTable(String name); + public abstract boolean dropTable(String name); + + public abstract T getGeneric(String id, String table, Class type); + public abstract List getAllGeneric(String table, Class type); + public abstract void saveAllGeneric(List serializableThings, String table, boolean overwrite, @Nullable Class type); + public abstract void saveGeneric(T serializableThing, String table); + public abstract void deleteGeneric(String id, String table); + public abstract Barrel getBarrel(UUID id); public abstract Collection getAllBarrels(); public abstract void saveAllBarrels(Collection barrels, boolean overwrite); diff --git a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java index 6ecd9a1b..199cc3f5 100644 --- a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java @@ -29,7 +29,9 @@ import com.dre.brewery.storage.DataManager; import com.dre.brewery.storage.StorageInitException; import com.dre.brewery.storage.records.BreweryMiscData; +import com.dre.brewery.storage.records.SerializableThing; import com.dre.brewery.storage.serialization.BukkitSerialization; +import com.dre.brewery.storage.serialization.SQLDataSerializer; import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.BoundingBox; import com.dre.brewery.utility.Logging; @@ -37,6 +39,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -51,6 +54,7 @@ public class FlatFileStorage extends DataManager { private final File rawFile; private final YamlConfiguration dataFile; + private SQLDataSerializer serializer; public FlatFileStorage(ConfiguredDataManager record) throws StorageInitException { super(record.getType()); @@ -73,9 +77,80 @@ private void save() { try { dataFile.save(rawFile); } catch (IOException e) { - Logging.errorLog("Failed to save to Flatfile!", e); + Logging.errorLog("Failed to save to FlatFile!", e); } } + private SQLDataSerializer getLazySerializerInstance() { + if (serializer == null) { + serializer = new SQLDataSerializer(); + } + return serializer; + } + + @Override + public boolean createTable(String name) { + dataFile.createSection(name); + save(); + return true; + } + + @Override + public boolean dropTable(String name) { + dataFile.set(name, null); + save(); + return true; + } + + @Override + public T getGeneric(String id, String table, Class type) { + String path = table + "." + id; + return getLazySerializerInstance().deserialize(dataFile.getString(path), type); + } + + @Override + public List getAllGeneric(String table, Class type) { + ConfigurationSection section = dataFile.getConfigurationSection(table); + if (section == null) { + return Collections.emptyList(); + } + List things = new ArrayList<>(); + for (String key : section.getKeys(false)) { + T thing = section.get(key) != null ? getLazySerializerInstance().deserialize(section.getString(key), type) : null; + if (thing != null) { + things.add(thing); + } + } + return things; + } + + @Override + public void saveAllGeneric(List serializableThings, String table, boolean overwrite, @Nullable Class type) { + ConfigurationSection section = dataFile.getConfigurationSection(table); + if (overwrite && section != null) { + dataFile.set(table, null); + } + + if (section == null) { + dataFile.createSection(table); + } + + for (T thing : serializableThings) { + section.set(thing.getId(), getLazySerializerInstance().serialize(thing)); + } + save(); + } + + @Override + public void saveGeneric(T serializableThing, String table) { + dataFile.set(table + "." + serializableThing.getId(), getLazySerializerInstance().serialize(serializableThing)); + save(); + } + + @Override + public void deleteGeneric(String id, String table) { + dataFile.set(table + "." + id, null); + save(); + } @Override public Barrel getBarrel(UUID id) { diff --git a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java index d592c286..373a2d58 100644 --- a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java @@ -43,6 +43,7 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; @@ -92,40 +93,64 @@ protected void closeConnection() { mongoClient.close(); } - private T getGeneric(UUID id, String collection, Class type) { - MongoCollection mongoCollection = mongoDatabase.getCollection(collectionPrefix + collection, type); - return mongoCollection.find(Filters.eq(MONGO_ID, id)).first(); + @Override + public boolean createTable(String name) { + mongoDatabase.createCollection(collectionPrefix + name); + return true; } - private T getGeneric(String id, String collection, Class type) { + @Override + public boolean dropTable(String name) { + mongoDatabase.getCollection(collectionPrefix + name).drop(); + return true; + } + + @Override + public T getGeneric(String id, String collection, Class type) { MongoCollection mongoCollection = mongoDatabase.getCollection(collectionPrefix + collection, type); return mongoCollection.find(Filters.eq(MONGO_ID, id)).first(); } + private T getGeneric(UUID id, String collection, Class type) { + return getGeneric(id.toString(), collection, type); + } - private List getAllGeneric(String collection, Class type) { + @Override + public List getAllGeneric(String collection, Class type) { MongoCollection mongoCollection = mongoDatabase.getCollection(collectionPrefix + collection, type); return mongoCollection.find().into(new ArrayList<>()); } - - private void saveGeneric(T thing, String collection) { + @Override + public void saveGeneric(T thing, String collection) { MongoCollection mongoCollection = (MongoCollection) mongoDatabase.getCollection(collectionPrefix + collection, thing.getClass()); mongoCollection.replaceOne(Filters.eq(MONGO_ID, thing.getId()), thing, new ReplaceOptions().upsert(true)); } - private void saveAllGeneric(List things, String collection, Class type) { + @Override + public void saveAllGeneric(List things, String collection, boolean overwrite, Class type) { + if (type == null) { + try { + throw new NullPointerException("type must not be null!"); + } catch (NullPointerException e) { + Logging.errorLog("'type' was null.", e); + return; + } + } MongoCollection mongoCollection = mongoDatabase.getCollection(collectionPrefix + collection, type); - Set thingsIds = things.stream().map(T::getId).collect(Collectors.toSet()); - // Delete objects from the collection that are no longer in the list - mongoCollection.deleteMany(Filters.not(Filters.in(MONGO_ID, thingsIds))); + if (overwrite) { + Set thingsIds = things.stream().map(T::getId).collect(Collectors.toSet()); + // Delete objects from the collection that are no longer in the list + mongoCollection.deleteMany(Filters.not(Filters.in(MONGO_ID, thingsIds))); + } for (T thing : things) { mongoCollection.replaceOne(Filters.eq(MONGO_ID, thing.getId()), thing, new ReplaceOptions().upsert(true)); // Upsert to handle both insert and update } } - private void deleteGeneric(UUID id, String collection) { + @Override + public void deleteGeneric(String id, String collection) { MongoCollection mongoCollection = mongoDatabase.getCollection(collectionPrefix + collection, SerializableThing.class); mongoCollection.deleteOne(Filters.eq(MONGO_ID, id)); } @@ -152,7 +177,7 @@ public void saveAllBarrels(Collection barrels, boolean overwrite) { List serializableBarrels = barrels.stream() .map(SerializableBarrel::new) .toList(); - saveAllGeneric(serializableBarrels, "barrels", SerializableBarrel.class); + saveAllGeneric(serializableBarrels, "barrels", overwrite, SerializableBarrel.class); } @Override @@ -162,7 +187,7 @@ public void saveBarrel(Barrel barrel) { @Override public void deleteBarrel(UUID id) { - deleteGeneric(id, "barrels"); + deleteGeneric(id.toString(), "barrels"); } @Override @@ -186,7 +211,7 @@ public void saveAllCauldrons(Collection cauldrons, boolean overwrite) List serializableCauldrons = cauldrons.stream() .map(SerializableCauldron::new) .toList(); - saveAllGeneric(serializableCauldrons, "cauldrons", SerializableCauldron.class); + saveAllGeneric(serializableCauldrons, "cauldrons", overwrite, SerializableCauldron.class); } @Override @@ -196,7 +221,7 @@ public void saveCauldron(BCauldron cauldron) { @Override public void deleteCauldron(UUID id) { - deleteGeneric(id, "cauldrons"); + deleteGeneric(id.toString(), "cauldrons"); } @Override @@ -220,7 +245,7 @@ public void saveAllPlayers(Collection players, boolean overwrite) { List serializableBPlayers = players.stream() .map(SerializableBPlayer::new) .toList(); - saveAllGeneric(serializableBPlayers, "players", SerializableBPlayer.class); + saveAllGeneric(serializableBPlayers, "players", overwrite, SerializableBPlayer.class); } @Override @@ -230,7 +255,7 @@ public void savePlayer(BPlayer player) { @Override public void deletePlayer(UUID playerUUID) { - deleteGeneric(playerUUID, "players"); + deleteGeneric(playerUUID.toString(), "players"); } @Override @@ -254,7 +279,7 @@ public void saveAllWakeups(Collection wakeups, boolean overwrite) { List serializableWakeups = wakeups.stream() .map(SerializableWakeup::new) .toList(); - saveAllGeneric(serializableWakeups, "wakeups", SerializableWakeup.class); + saveAllGeneric(serializableWakeups, "wakeups", overwrite, SerializableWakeup.class); } @Override @@ -264,7 +289,7 @@ public void saveWakeup(Wakeup wakeup) { @Override public void deleteWakeup(UUID id) { - deleteGeneric(id, "wakeups"); + deleteGeneric(id.toString(), "wakeups"); } @Override diff --git a/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java b/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java index 9d417d43..a1cc56cb 100644 --- a/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java @@ -35,6 +35,7 @@ import com.dre.brewery.storage.records.SerializableWakeup; import com.dre.brewery.storage.serialization.SQLDataSerializer; import com.dre.brewery.utility.Logging; +import org.jetbrains.annotations.Nullable; import java.sql.Connection; import java.sql.DriverManager; @@ -97,7 +98,33 @@ protected void closeConnection() { } } - private T getGeneric(UUID id, String table, Class type) { + + @Override + public boolean createTable(String name) { + String sql = "CREATE TABLE IF NOT EXISTS " + tablePrefix + name + " (id VARCHAR(36) PRIMARY KEY, data LONGTEXT);"; + try (PreparedStatement statement = connection.prepareStatement(sql)) { + statement.execute(); + return true; + } catch (SQLException e) { + Logging.errorLog("Failed to create table: " + name + " due to MySQL exception!", e); + return false; + } + } + + @Override + public boolean dropTable(String name) { + String sql = "DROP TABLE IF EXISTS " + tablePrefix + name; + try (PreparedStatement statement = connection.prepareStatement(sql)) { + statement.execute(); + return true; + } catch (SQLException e) { + Logging.errorLog("Failed to drop table: " + name + " due to MySQL exception!", e); + return false; + } + } + + @Override + public T getGeneric(String id, String table, Class type) { String sql = "SELECT data FROM " + tablePrefix + table + " WHERE id = ?"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.setString(1, id.toString()); @@ -112,7 +139,8 @@ private T getGeneric(UUID id, String table, Class type) { return null; } - private List getAllGeneric(String table, Class type) { + @Override + public List getAllGeneric(String table, Class type) { String sql = "SELECT id, data FROM " + tablePrefix + table; List objects = new ArrayList<>(); @@ -130,7 +158,8 @@ private List getAllGeneric(String table, Class< } - private void saveAllGeneric(List serializableThings, String table, boolean overwrite) { + @Override + public void saveAllGeneric(List serializableThings, String table, boolean overwrite, @Nullable Class type) { if (!overwrite) { String insertSql = "INSERT INTO " + tablePrefix + table + " (id, data) VALUES (?, ?) ON DUPLICATE KEY UPDATE data = VALUES(data)"; try (PreparedStatement insertStatement = connection.prepareStatement(insertSql)) { @@ -184,8 +213,12 @@ private void saveAllGeneric(List serializableThings Logging.errorLog("Failed to manage transaction for saving objects to: " + table + " due to MySQL exception!", e); } } + private void saveAllGeneric(List serializableThings, String table, boolean overwrite) { + saveAllGeneric(serializableThings, table, overwrite, null); + } - private void saveGeneric(T serializableThing, String table) { + @Override + public void saveGeneric(T serializableThing, String table) { String sql = "INSERT INTO " + tablePrefix + table + " (id, data) VALUES (?, ?) ON DUPLICATE KEY UPDATE data = VALUES(data)"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.setString(1, serializableThing.getId()); @@ -196,10 +229,11 @@ private void saveGeneric(T serializableThing, Stri } } - private void deleteGeneric(UUID id, String table) { + @Override + public void deleteGeneric(String id, String table) { String sql = "DELETE FROM " + tablePrefix + table + " WHERE id = ?"; try (PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, id.toString()); + statement.setString(1, id); statement.execute(); } catch (SQLException e) { Logging.errorLog("Failed to delete object from: " + table + ", from: MySQL!", e); @@ -208,7 +242,7 @@ private void deleteGeneric(UUID id, String table) { @Override public Barrel getBarrel(UUID id) { - SerializableBarrel serializableBarrel = getGeneric(id, "barrels", SerializableBarrel.class); + SerializableBarrel serializableBarrel = getGeneric(id.toString(), "barrels", SerializableBarrel.class); if (serializableBarrel != null) { return serializableBarrel.toBarrel(); } @@ -237,12 +271,12 @@ public void saveBarrel(Barrel barrel) { @Override public void deleteBarrel(UUID id) { - deleteGeneric(id, "barrels"); + deleteGeneric(id.toString(), "barrels"); } @Override public BCauldron getCauldron(UUID id) { - SerializableCauldron serializableCauldron = getGeneric(id, "cauldrons", SerializableCauldron.class); + SerializableCauldron serializableCauldron = getGeneric(id.toString(), "cauldrons", SerializableCauldron.class); if (serializableCauldron != null) { return serializableCauldron.toCauldron(); } @@ -271,12 +305,12 @@ public void saveCauldron(BCauldron cauldron) { @Override public void deleteCauldron(UUID id) { - deleteGeneric(id, "cauldrons"); + deleteGeneric(id.toString(), "cauldrons"); } @Override public BPlayer getPlayer(UUID playerUUID) { - SerializableBPlayer serializableBPlayer = getGeneric(playerUUID, "players", SerializableBPlayer.class); + SerializableBPlayer serializableBPlayer = getGeneric(playerUUID.toString(), "players", SerializableBPlayer.class); if (serializableBPlayer != null) { return serializableBPlayer.toBPlayer(); } @@ -305,12 +339,12 @@ public void savePlayer(BPlayer player) { @Override public void deletePlayer(UUID playerUUID) { - deleteGeneric(playerUUID, "players"); + deleteGeneric(playerUUID.toString(), "players"); } @Override public Wakeup getWakeup(UUID id) { - SerializableWakeup serializableWakeup = getGeneric(id, "wakeups", SerializableWakeup.class); + SerializableWakeup serializableWakeup = getGeneric(id.toString(), "wakeups", SerializableWakeup.class); if (serializableWakeup != null) { return serializableWakeup.toWakeup(); } @@ -339,7 +373,7 @@ public void saveWakeup(Wakeup wakeup) { @Override public void deleteWakeup(UUID id) { - deleteGeneric(id, "wakeups"); + deleteGeneric(id.toString(), "wakeups"); } @Override diff --git a/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java b/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java index 4b624ac5..1877add3 100644 --- a/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java @@ -101,7 +101,32 @@ protected void closeConnection() { } } - private T getGeneric(UUID id, String table, Class type) { + @Override + public boolean createTable(String name) { + String sql = "CREATE TABLE IF NOT EXISTS " + tablePrefix + name + " (id VARCHAR(36) PRIMARY KEY, data LONGTEXT);"; + try (PreparedStatement statement = connection.prepareStatement(sql)) { + statement.execute(); + return true; + } catch (SQLException e) { + Logging.errorLog("Failed to create table: " + name + " due to MySQL exception!", e); + } + return false; + } + + @Override + public boolean dropTable(String name) { + String sql = "DROP TABLE IF EXISTS " + tablePrefix + name; + try (PreparedStatement statement = connection.prepareStatement(sql)) { + statement.execute(); + return true; + } catch (SQLException e) { + Logging.errorLog("Failed to drop table: " + name + " due to MySQL exception!", e); + } + return false; + } + + @Override + public T getGeneric(String id, String table, Class type) { String sql = "SELECT data FROM " + tablePrefix + table + " WHERE id = ?"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.setString(1, id.toString()); @@ -116,7 +141,8 @@ private T getGeneric(UUID id, String table, Class type) { return null; } - private List getAllGeneric(String table, Class type) { + @Override + public List getAllGeneric(String table, Class type) { String sql = "SELECT id, data FROM " + tablePrefix + table; List objects = new ArrayList<>(); @@ -133,7 +159,8 @@ private List getAllGeneric(String table, Class type) { return objects; } - private void saveAllGeneric(List serializableThings, String table, boolean overwrite) { + @Override + public void saveAllGeneric(List serializableThings, String table, boolean overwrite, Class type) { String sql; if (overwrite) { sql = "INSERT INTO " + tablePrefix + table + " (id, data) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data"; @@ -152,9 +179,13 @@ private void saveAllGeneric(List serializableThings Logging.errorLog("Failed to save objects to SQLite!", e); } } + private void saveAllGeneric(List serializableThings, String table, boolean overwrite) { + saveAllGeneric(serializableThings, table, overwrite, null); + } - private void saveGeneric(T serializableThing, String table) { + @Override + public void saveGeneric(T serializableThing, String table) { String sql = "INSERT INTO " + tablePrefix + table + " (id, data) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.setString(1, serializableThing.getId()); @@ -165,7 +196,8 @@ private void saveGeneric(T serializableThing, Stri } } - private void deleteGeneric(UUID id, String table) { + @Override + public void deleteGeneric(String id, String table) { String sql = "DELETE FROM " + tablePrefix + table + " WHERE id = ?"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.setString(1, id.toString()); @@ -177,7 +209,7 @@ private void deleteGeneric(UUID id, String table) { @Override public Barrel getBarrel(UUID id) { - SerializableBarrel serializableBarrel = getGeneric(id, "barrels", SerializableBarrel.class); + SerializableBarrel serializableBarrel = getGeneric(id.toString(), "barrels", SerializableBarrel.class); if (serializableBarrel != null) { return serializableBarrel.toBarrel(); } @@ -206,12 +238,12 @@ public void saveBarrel(Barrel barrel) { @Override public void deleteBarrel(UUID id) { - deleteGeneric(id, "barrels"); + deleteGeneric(id.toString(), "barrels"); } @Override public BCauldron getCauldron(UUID id) { - SerializableCauldron serializableCauldron = getGeneric(id, "cauldrons", SerializableCauldron.class); + SerializableCauldron serializableCauldron = getGeneric(id.toString(), "cauldrons", SerializableCauldron.class); if (serializableCauldron != null) { return serializableCauldron.toCauldron(); } @@ -240,12 +272,12 @@ public void saveCauldron(BCauldron cauldron) { @Override public void deleteCauldron(UUID id) { - deleteGeneric(id, "cauldrons"); + deleteGeneric(id.toString(), "cauldrons"); } @Override public BPlayer getPlayer(UUID playerUUID) { - SerializableBPlayer serializableBPlayer = getGeneric(playerUUID, "players", SerializableBPlayer.class); + SerializableBPlayer serializableBPlayer = getGeneric(playerUUID.toString(), "players", SerializableBPlayer.class); if (serializableBPlayer != null) { return serializableBPlayer.toBPlayer(); } @@ -274,12 +306,12 @@ public void savePlayer(BPlayer player) { @Override public void deletePlayer(UUID playerUUID) { - deleteGeneric(playerUUID, "players"); + deleteGeneric(playerUUID.toString(), "players"); } @Override public Wakeup getWakeup(UUID id) { - SerializableWakeup serializableWakeup = getGeneric(id, "wakeups", SerializableWakeup.class); + SerializableWakeup serializableWakeup = getGeneric(id.toString(), "wakeups", SerializableWakeup.class); if (serializableWakeup != null) { return serializableWakeup.toWakeup(); } @@ -308,7 +340,7 @@ public void saveWakeup(Wakeup wakeup) { @Override public void deleteWakeup(UUID id) { - deleteGeneric(id, "wakeups"); + deleteGeneric(id.toString(), "wakeups"); } @Override From c040d29da88d9e1b04cc3af58c099f3a1a420707 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Thu, 19 Dec 2024 17:01:38 -0500 Subject: [PATCH 18/26] fix flatfile generic storage --- .../java/com/dre/brewery/BreweryPlugin.java | 2 +- .../dre/brewery/api/addons/AddonManager.java | 7 +++-- .../subcommands/ReloadAddonsCommand.java | 1 + .../com/dre/brewery/storage/DataManager.java | 16 +++++++++-- .../storage/impls/FlatFileStorage.java | 7 ++--- .../brewery/storage/impls/MongoDBStorage.java | 14 +++------- .../brewery/storage/impls/MySQLStorage.java | 6 ++--- .../brewery/storage/impls/SQLiteStorage.java | 6 ++--- .../interfaces/ExternallyAutoSavable.java | 27 +++++++++++++++++++ .../SerializableThing.java | 2 +- .../storage/records/BreweryMiscData.java | 2 ++ .../storage/records/SerializableBPlayer.java | 1 + .../storage/records/SerializableBarrel.java | 1 + .../storage/records/SerializableCauldron.java | 1 + .../storage/records/SerializableWakeup.java | 1 + 15 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java rename src/main/java/com/dre/brewery/storage/{records => interfaces}/SerializableThing.java (95%) diff --git a/src/main/java/com/dre/brewery/BreweryPlugin.java b/src/main/java/com/dre/brewery/BreweryPlugin.java index 6ded8cdf..68340275 100644 --- a/src/main/java/com/dre/brewery/BreweryPlugin.java +++ b/src/main/java/com/dre/brewery/BreweryPlugin.java @@ -174,7 +174,7 @@ public void onEnable() { .filter(Objects::nonNull) .toList()); - + addonManager.enableAddons(); // Setup Metrics this.breweryStats.setupBStats(); new BreweryXStats().setupBStats(); diff --git a/src/main/java/com/dre/brewery/api/addons/AddonManager.java b/src/main/java/com/dre/brewery/api/addons/AddonManager.java index 83888a0b..c5527bbc 100644 --- a/src/main/java/com/dre/brewery/api/addons/AddonManager.java +++ b/src/main/java/com/dre/brewery/api/addons/AddonManager.java @@ -118,6 +118,11 @@ public void loadAddons() { loadAddon(file); // Go read the documentation below to understand what this does. } + int loaded = LOADED_ADDONS.size(); + if (loaded > 0) Logging.log("Loaded " + loaded + " addon(s)"); + } + + public void enableAddons() { for (BreweryAddon addon : LOADED_ADDONS) { try { addon.onAddonEnable(); // All done, let the addon know it's been enabled. @@ -126,8 +131,6 @@ public void loadAddons() { unloadAddon(addon); } } - int loaded = LOADED_ADDONS.size(); - if (loaded > 0) Logging.log("Loaded " + loaded + " addon(s)"); } diff --git a/src/main/java/com/dre/brewery/commands/subcommands/ReloadAddonsCommand.java b/src/main/java/com/dre/brewery/commands/subcommands/ReloadAddonsCommand.java index 49a8b493..a281c2fe 100644 --- a/src/main/java/com/dre/brewery/commands/subcommands/ReloadAddonsCommand.java +++ b/src/main/java/com/dre/brewery/commands/subcommands/ReloadAddonsCommand.java @@ -36,6 +36,7 @@ public void execute(BreweryPlugin breweryPlugin, Lang lang, CommandSender sender AddonManager addonManager = BreweryPlugin.getAddonManager(); addonManager.unloadAddons(); addonManager.loadAddons(); + addonManager.enableAddons(); Logging.msg(sender, "Finished loading " + addonManager.getAddons().size() + " addon(s)"); Logging.msg(sender, "&eUsing this command should be avoided as it can cause unpredictable behavior within addons!"); } else { diff --git a/src/main/java/com/dre/brewery/storage/DataManager.java b/src/main/java/com/dre/brewery/storage/DataManager.java index cfdcf333..731d35f5 100644 --- a/src/main/java/com/dre/brewery/storage/DataManager.java +++ b/src/main/java/com/dre/brewery/storage/DataManager.java @@ -31,12 +31,13 @@ import com.dre.brewery.configuration.files.Config; import com.dre.brewery.configuration.sector.capsule.ConfiguredDataManager; import com.dre.brewery.integration.bstats.BreweryStats; +import com.dre.brewery.storage.interfaces.ExternallyAutoSavable; import com.dre.brewery.storage.impls.FlatFileStorage; import com.dre.brewery.storage.impls.MongoDBStorage; import com.dre.brewery.storage.impls.MySQLStorage; import com.dre.brewery.storage.impls.SQLiteStorage; import com.dre.brewery.storage.records.BreweryMiscData; -import com.dre.brewery.storage.records.SerializableThing; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.Logging; import lombok.Getter; @@ -57,6 +58,8 @@ public abstract class DataManager { protected static BreweryPlugin plugin = BreweryPlugin.getInstance(); protected static long lastAutoSave = System.currentTimeMillis(); + @Getter + protected static List autoSavables = new ArrayList<>(); private final DataManagerType type; @@ -64,7 +67,8 @@ protected DataManager(DataManagerType type) throws StorageInitException { this.type = type; } - public abstract boolean createTable(String name); + public abstract boolean createTable(String name, int maxIdLength); + public boolean createTable(String name) { return createTable(name, 36);} public abstract boolean dropTable(String name); public abstract T getGeneric(String id, String table, Class type); @@ -168,6 +172,14 @@ private void doSave(Collection barrels, Collection cauldrons, saveAllCauldrons(cauldrons, true); saveAllPlayers(players, true); saveAllWakeups(wakeups, true); + + for (ExternallyAutoSavable autoSaveAble : autoSavables) { + try { + autoSaveAble.onAutoSave(this); + } catch (Throwable e) { + Logging.errorLog("An external auto-savable class threw an exception. This is most likely an addon not saving properly.", e); + } + } Logging.debugLog("Saved all data!"); } diff --git a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java index 199cc3f5..52537da4 100644 --- a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java @@ -29,7 +29,7 @@ import com.dre.brewery.storage.DataManager; import com.dre.brewery.storage.StorageInitException; import com.dre.brewery.storage.records.BreweryMiscData; -import com.dre.brewery.storage.records.SerializableThing; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.storage.serialization.BukkitSerialization; import com.dre.brewery.storage.serialization.SQLDataSerializer; import com.dre.brewery.utility.BUtil; @@ -88,7 +88,7 @@ private SQLDataSerializer getLazySerializerInstance() { } @Override - public boolean createTable(String name) { + public boolean createTable(String name, int maxIdLength) { dataFile.createSection(name); save(); return true; @@ -130,8 +130,9 @@ public void saveAllGeneric(List serializableThi dataFile.set(table, null); } - if (section == null) { + if (section == null) { // Sloppy, but whatever dataFile.createSection(table); + section = dataFile.getConfigurationSection(table); } for (T thing : serializableThings) { diff --git a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java index 373a2d58..a8e49df9 100644 --- a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java @@ -31,7 +31,7 @@ import com.dre.brewery.storage.records.SerializableBPlayer; import com.dre.brewery.storage.records.SerializableBarrel; import com.dre.brewery.storage.records.SerializableCauldron; -import com.dre.brewery.storage.records.SerializableThing; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.storage.records.SerializableWakeup; import com.dre.brewery.utility.Logging; import com.mongodb.client.MongoClient; @@ -43,7 +43,6 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; @@ -94,7 +93,7 @@ protected void closeConnection() { } @Override - public boolean createTable(String name) { + public boolean createTable(String name, int maxIdLength) { mongoDatabase.createCollection(collectionPrefix + name); return true; } @@ -128,14 +127,7 @@ public void saveGeneric(T thing, String collection @Override public void saveAllGeneric(List things, String collection, boolean overwrite, Class type) { - if (type == null) { - try { - throw new NullPointerException("type must not be null!"); - } catch (NullPointerException e) { - Logging.errorLog("'type' was null.", e); - return; - } - } + assert type != null : "'type' cannot be null!"; MongoCollection mongoCollection = mongoDatabase.getCollection(collectionPrefix + collection, type); if (overwrite) { diff --git a/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java b/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java index a1cc56cb..a4ad1804 100644 --- a/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/MySQLStorage.java @@ -31,7 +31,7 @@ import com.dre.brewery.storage.records.SerializableBPlayer; import com.dre.brewery.storage.records.SerializableBarrel; import com.dre.brewery.storage.records.SerializableCauldron; -import com.dre.brewery.storage.records.SerializableThing; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.storage.records.SerializableWakeup; import com.dre.brewery.storage.serialization.SQLDataSerializer; import com.dre.brewery.utility.Logging; @@ -100,8 +100,8 @@ protected void closeConnection() { @Override - public boolean createTable(String name) { - String sql = "CREATE TABLE IF NOT EXISTS " + tablePrefix + name + " (id VARCHAR(36) PRIMARY KEY, data LONGTEXT);"; + public boolean createTable(String name, int maxIdLength) { + String sql = "CREATE TABLE IF NOT EXISTS " + tablePrefix + name + " (id VARCHAR(" + maxIdLength + ") PRIMARY KEY, data LONGTEXT);"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.execute(); return true; diff --git a/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java b/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java index 1877add3..20bf5648 100644 --- a/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/SQLiteStorage.java @@ -31,7 +31,7 @@ import com.dre.brewery.storage.records.SerializableBPlayer; import com.dre.brewery.storage.records.SerializableBarrel; import com.dre.brewery.storage.records.SerializableCauldron; -import com.dre.brewery.storage.records.SerializableThing; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.storage.records.SerializableWakeup; import com.dre.brewery.storage.serialization.SQLDataSerializer; import com.dre.brewery.utility.Logging; @@ -102,8 +102,8 @@ protected void closeConnection() { } @Override - public boolean createTable(String name) { - String sql = "CREATE TABLE IF NOT EXISTS " + tablePrefix + name + " (id VARCHAR(36) PRIMARY KEY, data LONGTEXT);"; + public boolean createTable(String name, int maxIdLength) { + String sql = "CREATE TABLE IF NOT EXISTS " + tablePrefix + name + " (id VARCHAR(" + maxIdLength + ") PRIMARY KEY, data LONGTEXT);"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.execute(); return true; diff --git a/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java b/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java new file mode 100644 index 00000000..a5d41262 --- /dev/null +++ b/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java @@ -0,0 +1,27 @@ +/* + * BreweryX Bukkit-Plugin for an alternate brewing process + * Copyright (C) 2024 The Brewery Team + * + * This file is part of BreweryX. + * + * BreweryX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BreweryX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with BreweryX. If not, see . + */ + +package com.dre.brewery.storage.interfaces; + +import com.dre.brewery.storage.DataManager; + +public interface ExternallyAutoSavable { + void onAutoSave(DataManager dataManager); +} diff --git a/src/main/java/com/dre/brewery/storage/records/SerializableThing.java b/src/main/java/com/dre/brewery/storage/interfaces/SerializableThing.java similarity index 95% rename from src/main/java/com/dre/brewery/storage/records/SerializableThing.java rename to src/main/java/com/dre/brewery/storage/interfaces/SerializableThing.java index a3d9bb86..f0212d2d 100644 --- a/src/main/java/com/dre/brewery/storage/records/SerializableThing.java +++ b/src/main/java/com/dre/brewery/storage/interfaces/SerializableThing.java @@ -18,7 +18,7 @@ * along with BreweryX. If not, see . */ -package com.dre.brewery.storage.records; +package com.dre.brewery.storage.interfaces; public interface SerializableThing { String getId(); diff --git a/src/main/java/com/dre/brewery/storage/records/BreweryMiscData.java b/src/main/java/com/dre/brewery/storage/records/BreweryMiscData.java index 9a8595ac..8f543360 100644 --- a/src/main/java/com/dre/brewery/storage/records/BreweryMiscData.java +++ b/src/main/java/com/dre/brewery/storage/records/BreweryMiscData.java @@ -20,6 +20,8 @@ package com.dre.brewery.storage.records; +import com.dre.brewery.storage.interfaces.SerializableThing; + import java.util.List; /** diff --git a/src/main/java/com/dre/brewery/storage/records/SerializableBPlayer.java b/src/main/java/com/dre/brewery/storage/records/SerializableBPlayer.java index be31cef1..adb3b3ca 100644 --- a/src/main/java/com/dre/brewery/storage/records/SerializableBPlayer.java +++ b/src/main/java/com/dre/brewery/storage/records/SerializableBPlayer.java @@ -21,6 +21,7 @@ package com.dre.brewery.storage.records; import com.dre.brewery.BPlayer; +import com.dre.brewery.storage.interfaces.SerializableThing; /** * Represents a player that can be serialized. diff --git a/src/main/java/com/dre/brewery/storage/records/SerializableBarrel.java b/src/main/java/com/dre/brewery/storage/records/SerializableBarrel.java index 98c0b675..015876f9 100644 --- a/src/main/java/com/dre/brewery/storage/records/SerializableBarrel.java +++ b/src/main/java/com/dre/brewery/storage/records/SerializableBarrel.java @@ -22,6 +22,7 @@ import com.dre.brewery.Barrel; import com.dre.brewery.storage.DataManager; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.storage.serialization.BukkitSerialization; import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.BoundingBox; diff --git a/src/main/java/com/dre/brewery/storage/records/SerializableCauldron.java b/src/main/java/com/dre/brewery/storage/records/SerializableCauldron.java index 3908bce7..e17a1076 100644 --- a/src/main/java/com/dre/brewery/storage/records/SerializableCauldron.java +++ b/src/main/java/com/dre/brewery/storage/records/SerializableCauldron.java @@ -23,6 +23,7 @@ import com.dre.brewery.BCauldron; import com.dre.brewery.BIngredients; import com.dre.brewery.storage.DataManager; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.utility.BUtil; import org.bukkit.Location; diff --git a/src/main/java/com/dre/brewery/storage/records/SerializableWakeup.java b/src/main/java/com/dre/brewery/storage/records/SerializableWakeup.java index a685f12b..6fd51166 100644 --- a/src/main/java/com/dre/brewery/storage/records/SerializableWakeup.java +++ b/src/main/java/com/dre/brewery/storage/records/SerializableWakeup.java @@ -22,6 +22,7 @@ import com.dre.brewery.Wakeup; import com.dre.brewery.storage.DataManager; +import com.dre.brewery.storage.interfaces.SerializableThing; import com.dre.brewery.utility.BUtil; import org.bukkit.Location; From ff5fba982bcb69941b83c06675cd383a7d71ff16 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Thu, 19 Dec 2024 21:38:44 -0500 Subject: [PATCH 19/26] modify flatfile generics impl --- .../dre/brewery/api/addons/AddonManager.java | 1 + .../com/dre/brewery/storage/DataManager.java | 20 ++++++-- .../storage/impls/FlatFileStorage.java | 46 +++++++++++++------ .../interfaces/ExternallyAutoSavable.java | 15 ++++++ .../storage/interfaces/SerializableThing.java | 10 ++++ .../serialization/SQLDataSerializer.java | 2 + 6 files changed, 77 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/dre/brewery/api/addons/AddonManager.java b/src/main/java/com/dre/brewery/api/addons/AddonManager.java index c5527bbc..9ef0722c 100644 --- a/src/main/java/com/dre/brewery/api/addons/AddonManager.java +++ b/src/main/java/com/dre/brewery/api/addons/AddonManager.java @@ -239,6 +239,7 @@ private Tuple, List>> getClassesFromJar(F // It's important that we don't initialize any other classes before our main class. clazz = Class.forName(className, false, classLoader); } catch (ClassNotFoundException | NoClassDefFoundError e) { + Logging.errorLog("An exception occurred while trying to load a class from an addon", e); continue; } if (BreweryAddon.class.isAssignableFrom(clazz)) { diff --git a/src/main/java/com/dre/brewery/storage/DataManager.java b/src/main/java/com/dre/brewery/storage/DataManager.java index 731d35f5..28409ffd 100644 --- a/src/main/java/com/dre/brewery/storage/DataManager.java +++ b/src/main/java/com/dre/brewery/storage/DataManager.java @@ -48,7 +48,9 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.UUID; @Getter @@ -58,8 +60,7 @@ public abstract class DataManager { protected static BreweryPlugin plugin = BreweryPlugin.getInstance(); protected static long lastAutoSave = System.currentTimeMillis(); - @Getter - protected static List autoSavables = new ArrayList<>(); + protected static Set autoSavabales = new HashSet<>(); private final DataManagerType type; @@ -68,7 +69,9 @@ protected DataManager(DataManagerType type) throws StorageInitException { } public abstract boolean createTable(String name, int maxIdLength); - public boolean createTable(String name) { return createTable(name, 36);} + public boolean createTable(String name) { + return createTable(name, 36); // Standard UUID length is 36 + } public abstract boolean dropTable(String name); public abstract T getGeneric(String id, String table, Class type); @@ -173,7 +176,7 @@ private void doSave(Collection barrels, Collection cauldrons, saveAllPlayers(players, true); saveAllWakeups(wakeups, true); - for (ExternallyAutoSavable autoSaveAble : autoSavables) { + for (ExternallyAutoSavable autoSaveAble : autoSavabales) { try { autoSaveAble.onAutoSave(this); } catch (Throwable e) { @@ -218,6 +221,15 @@ public static DataManager createDataManager(ConfiguredDataManager record) throws // Utility + public static void registerAutoSavable(ExternallyAutoSavable autoSavable) { + autoSavabales.add(autoSavable); + } + + public static void unregisterAutoSavable(ExternallyAutoSavable autoSavable) { + autoSavabales.remove(autoSavable); + } + + public static void loadMiscData(BreweryMiscData miscData) { Brew.installTime = miscData.installTime(); MCBarrel.mcBarrelTime = miscData.mcBarrelTime(); diff --git a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java index 52537da4..3b2bcef5 100644 --- a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java @@ -35,6 +35,9 @@ import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.BoundingBox; import com.dre.brewery.utility.Logging; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; @@ -43,13 +46,15 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.UUID; -// TODO: Should we use Okaeri here? +// TODO: Simplify methods public class FlatFileStorage extends DataManager { private final File rawFile; @@ -101,10 +106,23 @@ public boolean dropTable(String name) { return true; } + @Override public T getGeneric(String id, String table, Class type) { String path = table + "." + id; - return getLazySerializerInstance().deserialize(dataFile.getString(path), type); + + ConfigurationSection section = dataFile.getConfigurationSection(path); + if (section == null) { + return null; + } + + // Get all values at the path as a Map + Map map = section.getValues(false); + Gson gson = getLazySerializerInstance().getGson(); + + // Gson writes ints as doubles sometimes, but they seem to serialize back to ints just fine. + String json = gson.toJson(map); + return gson.fromJson(json, type); } @Override @@ -115,10 +133,7 @@ public List getAllGeneric(String table, Class things = new ArrayList<>(); for (String key : section.getKeys(false)) { - T thing = section.get(key) != null ? getLazySerializerInstance().deserialize(section.getString(key), type) : null; - if (thing != null) { - things.add(thing); - } + things.add(getGeneric(key, table, type)); } return things; } @@ -127,23 +142,28 @@ public List getAllGeneric(String table, Class void saveAllGeneric(List serializableThings, String table, boolean overwrite, @Nullable Class type) { ConfigurationSection section = dataFile.getConfigurationSection(table); if (overwrite && section != null) { - dataFile.set(table, null); - } - - if (section == null) { // Sloppy, but whatever + section.getKeys(false).forEach(key -> dataFile.set(table + "." + key, null)); + } else if (section == null) { dataFile.createSection(table); - section = dataFile.getConfigurationSection(table); } for (T thing : serializableThings) { - section.set(thing.getId(), getLazySerializerInstance().serialize(thing)); + saveGeneric(thing, table); } save(); } @Override public void saveGeneric(T serializableThing, String table) { - dataFile.set(table + "." + serializableThing.getId(), getLazySerializerInstance().serialize(serializableThing)); + String path = table + "." + serializableThing.getId(); + + Gson gson = getLazySerializerInstance().getGson(); + JsonObject jsonObject = gson.toJsonTree(serializableThing).getAsJsonObject(); + Type mapType = new TypeToken>() {}.getType(); + Map map = gson.fromJson(jsonObject, mapType); + for (Map.Entry entry : map.entrySet()) { + dataFile.set(path + "." + entry.getKey(), entry.getValue()); + } save(); } diff --git a/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java b/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java index a5d41262..0995b229 100644 --- a/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java +++ b/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java @@ -22,6 +22,21 @@ import com.dre.brewery.storage.DataManager; +/** + * Allows an external class (a class outside or inside) of this Plugin to be auto-saved by Brewery. + * Auto saving will occur every X number of minutes and will also occur when this Plugin is disabled. + *

+ * A class + * implementing this interface must be registered with BreweryX auto-savable system. {@link DataManager#registerAutoSavable(ExternallyAutoSavable)} + * + * @see DataManager#registerAutoSavable(ExternallyAutoSavable) + * @see DataManager#unregisterAutoSavable(ExternallyAutoSavable) + */ public interface ExternallyAutoSavable { + + /** + * Fired when Brewery is handling its auto-save task. + * @param dataManager Instance of the DataManager + */ void onAutoSave(DataManager dataManager); } diff --git a/src/main/java/com/dre/brewery/storage/interfaces/SerializableThing.java b/src/main/java/com/dre/brewery/storage/interfaces/SerializableThing.java index f0212d2d..ca8dd04c 100644 --- a/src/main/java/com/dre/brewery/storage/interfaces/SerializableThing.java +++ b/src/main/java/com/dre/brewery/storage/interfaces/SerializableThing.java @@ -20,6 +20,16 @@ package com.dre.brewery.storage.interfaces; +/** + * Represents an object that can be serialized and uniquely identified. + * Implementations of this interface should serialize their respective data into + * a format that enables persistent storage and retrieval. + */ public interface SerializableThing { + + /** + * The identifier of this serializable object. Usually a UUID or similar. + * @return The identifier as a String + */ String getId(); } diff --git a/src/main/java/com/dre/brewery/storage/serialization/SQLDataSerializer.java b/src/main/java/com/dre/brewery/storage/serialization/SQLDataSerializer.java index a02c8999..3dbb2c69 100644 --- a/src/main/java/com/dre/brewery/storage/serialization/SQLDataSerializer.java +++ b/src/main/java/com/dre/brewery/storage/serialization/SQLDataSerializer.java @@ -22,6 +22,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import lombok.Getter; import java.lang.reflect.Modifier; import java.util.Base64; @@ -29,6 +30,7 @@ /** * Serializes the given object to JSON and then to a Base64 encoded string. */ +@Getter public class SQLDataSerializer { private final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithModifiers(Modifier.STATIC).create(); From c852e84b23b75596d19ff9855041b8a8b125d28d Mon Sep 17 00:00:00 2001 From: Jsinco Date: Thu, 19 Dec 2024 23:00:36 -0500 Subject: [PATCH 20/26] idk why this was written like this --- src/main/java/com/dre/brewery/BCauldron.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dre/brewery/BCauldron.java b/src/main/java/com/dre/brewery/BCauldron.java index 94ef9c3d..120555ef 100644 --- a/src/main/java/com/dre/brewery/BCauldron.java +++ b/src/main/java/com/dre/brewery/BCauldron.java @@ -516,7 +516,7 @@ public static void clickCauldron(PlayerInteractEvent event) { } else if (isBottle) { BUtil.setItemInHand(event, Material.GLASS_BOTTLE, handSwap); } else { - BUtil.setItemInHand(event, Material.AIR, handSwap); + item.setAmount(0); } } } From 8a051db3ad11b00d48f51fa786f4d09199b90e09 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Fri, 20 Dec 2024 14:52:06 -0500 Subject: [PATCH 21/26] check if section already exists in FlatFileStorage --- src/main/java/com/dre/brewery/api/addons/AddonManager.java | 2 +- .../java/com/dre/brewery/storage/impls/FlatFileStorage.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dre/brewery/api/addons/AddonManager.java b/src/main/java/com/dre/brewery/api/addons/AddonManager.java index 9ef0722c..51e57de1 100644 --- a/src/main/java/com/dre/brewery/api/addons/AddonManager.java +++ b/src/main/java/com/dre/brewery/api/addons/AddonManager.java @@ -127,7 +127,7 @@ public void enableAddons() { try { addon.onAddonEnable(); // All done, let the addon know it's been enabled. } catch (Throwable t) { - Logging.errorLog("Failed to enable addon " + addon.getClass().getSimpleName(), t); + Logging.errorLog("Failed to enable addon " + addon.getAddonInfo().name(), t); unloadAddon(addon); } } diff --git a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java index 3b2bcef5..420803d6 100644 --- a/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/FlatFileStorage.java @@ -94,6 +94,9 @@ private SQLDataSerializer getLazySerializerInstance() { @Override public boolean createTable(String name, int maxIdLength) { + if (dataFile.contains(name)) { + return false; + } dataFile.createSection(name); save(); return true; From d9f6529b693c08437851bdc16b9458dfa6f5ffa2 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Fri, 20 Dec 2024 15:18:47 -0500 Subject: [PATCH 22/26] check if tables already exist/re-create when hotswapping datamanagers --- .../com/dre/brewery/storage/DataManager.java | 21 ++++++++++++------- .../brewery/storage/impls/MongoDBStorage.java | 10 +++++++++ .../interfaces/ExternallyAutoSavable.java | 15 +++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/dre/brewery/storage/DataManager.java b/src/main/java/com/dre/brewery/storage/DataManager.java index 28409ffd..3e451a22 100644 --- a/src/main/java/com/dre/brewery/storage/DataManager.java +++ b/src/main/java/com/dre/brewery/storage/DataManager.java @@ -69,9 +69,6 @@ protected DataManager(DataManagerType type) throws StorageInitException { } public abstract boolean createTable(String name, int maxIdLength); - public boolean createTable(String name) { - return createTable(name, 36); // Standard UUID length is 36 - } public abstract boolean dropTable(String name); public abstract T getGeneric(String id, String table, Class type); @@ -111,6 +108,10 @@ public boolean createTable(String name) { public abstract BreweryMiscData getBreweryMiscData(); public abstract void saveBreweryMiscData(BreweryMiscData data); + protected void closeConnection() { + // Implemented in subclasses that use database connections + } + public void tryAutoSave() { long interval = ConfigManager.getConfig(Config.class).getAutosave() * 60000L; @@ -186,9 +187,6 @@ private void doSave(Collection barrels, Collection cauldrons, Logging.debugLog("Saved all data!"); } - protected void closeConnection() { - // Implemented in subclasses that use database connections - } public static DataManager createDataManager(ConfiguredDataManager record) throws StorageInitException { DataManager dataManager = switch (record.getType()) { @@ -212,6 +210,12 @@ public static DataManager createDataManager(ConfiguredDataManager record) throws Logging.warningLog("BreweryX can only load legacy data from worlds that exist. If you're trying to migrate old cauldrons, barrels, etc. And the worlds they're in don't exist, you'll need to migrate manually."); } + // DataManager has been reloaded and may have swapped to a new implementation. + // We have to ensure all our tables that were externally + // created are re-created on the new DataManager or already exist! + for (ExternallyAutoSavable autoSavable : autoSavabales) { // Should be empty on the first startup of the DataManager + dataManager.createTable(autoSavable.table(), autoSavable.tableMaxIdLength()); + } Logging.log("DataManager created&7:&a " + record.getType().getFormattedName()); return dataManager; @@ -221,11 +225,12 @@ public static DataManager createDataManager(ConfiguredDataManager record) throws // Utility - public static void registerAutoSavable(ExternallyAutoSavable autoSavable) { + public void registerAutoSavable(ExternallyAutoSavable autoSavable) { autoSavabales.add(autoSavable); + this.createTable(autoSavable.table(), autoSavable.tableMaxIdLength()); } - public static void unregisterAutoSavable(ExternallyAutoSavable autoSavable) { + public void unregisterAutoSavable(ExternallyAutoSavable autoSavable) { autoSavabales.remove(autoSavable); } diff --git a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java index a8e49df9..7acc7791 100644 --- a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java @@ -92,14 +92,24 @@ protected void closeConnection() { mongoClient.close(); } + private boolean collectionExists(String name) { + return mongoDatabase.listCollectionNames().into(new ArrayList<>()).contains(collectionPrefix + name); + } + @Override public boolean createTable(String name, int maxIdLength) { + if (collectionExists(name)) { + return false; + } mongoDatabase.createCollection(collectionPrefix + name); return true; } @Override public boolean dropTable(String name) { + if (collectionExists(name)) { + return false; + } mongoDatabase.getCollection(collectionPrefix + name).drop(); return true; } diff --git a/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java b/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java index 0995b229..fb8b1c45 100644 --- a/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java +++ b/src/main/java/com/dre/brewery/storage/interfaces/ExternallyAutoSavable.java @@ -34,6 +34,21 @@ */ public interface ExternallyAutoSavable { + /** + * @return The identifier of the table. Should be unique. + */ + String table(); + + /** + * The max length of the identifier for the PRIMARY KEY of the table. + * This only matters if the user is using an SQL-relational database. + * This specifies what {@code VARCHAR(size)} should be. + * @return The max length of the table specified by the child class. Max length is 255. + */ + default int tableMaxIdLength() { + return 36; // Standard UUID length is 36 + } + /** * Fired when Brewery is handling its auto-save task. * @param dataManager Instance of the DataManager From bd96e389a5f4455715f03bc163d6527dc8281f0c Mon Sep 17 00:00:00 2001 From: Jsinco Date: Fri, 20 Dec 2024 15:31:42 -0500 Subject: [PATCH 23/26] minor changes --- src/main/java/com/dre/brewery/storage/DataManager.java | 2 ++ src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dre/brewery/storage/DataManager.java b/src/main/java/com/dre/brewery/storage/DataManager.java index 3e451a22..fa314343 100644 --- a/src/main/java/com/dre/brewery/storage/DataManager.java +++ b/src/main/java/com/dre/brewery/storage/DataManager.java @@ -68,6 +68,8 @@ protected DataManager(DataManagerType type) throws StorageInitException { this.type = type; } + // Child methods + public abstract boolean createTable(String name, int maxIdLength); public abstract boolean dropTable(String name); diff --git a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java index 7acc7791..4d1d4df9 100644 --- a/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java +++ b/src/main/java/com/dre/brewery/storage/impls/MongoDBStorage.java @@ -63,8 +63,6 @@ public class MongoDBStorage extends DataManager { public MongoDBStorage(ConfiguredDataManager record) throws StorageInitException { super(record.getType()); - Logging.warningLog("Mongo storage option is in an experimental stage. Use at your own discretion."); - try { // suppress mongo client's logs Logger clientLogger = (Logger) LogManager.getLogger("org.mongodb.driver.client"); From 1f52e993672e43c9136fc826af5660796a5df54f Mon Sep 17 00:00:00 2001 From: Jsinco Date: Fri, 20 Dec 2024 17:57:38 -0500 Subject: [PATCH 24/26] add GithubSnapshotsReleaseChecker --- .../dre/brewery/api/addons/AddonManager.java | 2 +- .../com/dre/brewery/utility/MaterialUtil.java | 2 + .../utility/releases/ReleaseChecker.java | 3 + .../impl/GithubSnapshotsReleaseChecker.java | 82 +++++++++++++++++++ src/main/resources/config-langs/de.yml | 2 +- src/main/resources/config-langs/en.yml | 2 +- src/main/resources/config-langs/es.yml | 2 +- src/main/resources/config-langs/fr.yml | 2 +- src/main/resources/config-langs/it.yml | 2 +- src/main/resources/config-langs/ru.yml | 2 +- src/main/resources/config-langs/zh.yml | 2 +- 11 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/dre/brewery/utility/releases/impl/GithubSnapshotsReleaseChecker.java diff --git a/src/main/java/com/dre/brewery/api/addons/AddonManager.java b/src/main/java/com/dre/brewery/api/addons/AddonManager.java index 51e57de1..537c25ae 100644 --- a/src/main/java/com/dre/brewery/api/addons/AddonManager.java +++ b/src/main/java/com/dre/brewery/api/addons/AddonManager.java @@ -50,7 +50,7 @@ */ public class AddonManager { - public final static ConcurrentLinkedQueue LOADED_ADDONS = new ConcurrentLinkedQueue<>(); + public static final ConcurrentLinkedQueue LOADED_ADDONS = new ConcurrentLinkedQueue<>(); private final BreweryPlugin plugin; private final File addonsFolder; diff --git a/src/main/java/com/dre/brewery/utility/MaterialUtil.java b/src/main/java/com/dre/brewery/utility/MaterialUtil.java index 0461eadb..7e85ac8f 100644 --- a/src/main/java/com/dre/brewery/utility/MaterialUtil.java +++ b/src/main/java/com/dre/brewery/utility/MaterialUtil.java @@ -78,6 +78,8 @@ public static Method getMethod(Class clazz, String name, Class... paramete public static Material getMaterialSafely(String name) { try { + // TODO: + // I want to make some interface for including renamed PotionEffectTypes, Enchants, and Materials if (name.equalsIgnoreCase("GRASS")) { // 1.20.6 -> renamed to short_grass return Material.GRASS; } diff --git a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java index f3242751..06f9eed0 100644 --- a/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java +++ b/src/main/java/com/dre/brewery/utility/releases/ReleaseChecker.java @@ -25,6 +25,7 @@ import com.dre.brewery.configuration.files.Config; import com.dre.brewery.configuration.files.Lang; import com.dre.brewery.utility.releases.impl.GitHubReleaseChecker; +import com.dre.brewery.utility.releases.impl.GithubSnapshotsReleaseChecker; import com.dre.brewery.utility.releases.impl.NoImplReleaseChecker; import com.dre.brewery.utility.releases.impl.SpigotReleaseChecker; import lombok.Getter; @@ -73,6 +74,7 @@ public static ReleaseChecker getInstance(boolean newInstance) { Config config = ConfigManager.getConfig(Config.class); switch (config.getResolveUpdatesFrom()) { case GITHUB -> instance = new GitHubReleaseChecker("BreweryTeam", "BreweryX"); + case SNAPSHOTS -> instance = new GithubSnapshotsReleaseChecker("BreweryTeam", "BreweryX"); case SPIGOT -> instance = new SpigotReleaseChecker(114777); case NONE -> instance = new NoImplReleaseChecker(); } @@ -107,6 +109,7 @@ public int parseVersion(String version) { public enum ReleaseCheckerType { GITHUB, + SNAPSHOTS, SPIGOT, NONE } diff --git a/src/main/java/com/dre/brewery/utility/releases/impl/GithubSnapshotsReleaseChecker.java b/src/main/java/com/dre/brewery/utility/releases/impl/GithubSnapshotsReleaseChecker.java new file mode 100644 index 00000000..77fefe43 --- /dev/null +++ b/src/main/java/com/dre/brewery/utility/releases/impl/GithubSnapshotsReleaseChecker.java @@ -0,0 +1,82 @@ +/* + * BreweryX Bukkit-Plugin for an alternate brewing process + * Copyright (C) 2024 The Brewery Team + * + * This file is part of BreweryX. + * + * BreweryX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BreweryX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with BreweryX. If not, see . + */ + +package com.dre.brewery.utility.releases.impl; + +import com.dre.brewery.utility.Logging; +import com.dre.brewery.utility.releases.ReleaseChecker; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.concurrent.CompletableFuture; + +public class GithubSnapshotsReleaseChecker extends ReleaseChecker { + + private static final String CONST_URL = "https://api.github.com/repos/%s/%s/releases"; + private static final String CONST_JSON_FIELD = "tag_name"; + + private final String link; + + public GithubSnapshotsReleaseChecker(String owner, String repo) { + this.link = String.format(CONST_URL, owner, repo); + } + + @Override + public CompletableFuture resolveLatest() { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(link)) + .GET() + .build(); + + return CompletableFuture.supplyAsync(() -> { + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + JsonObject jsonResponse = JsonParser.parseString(response.body()) + .getAsJsonArray().asList().stream() + .filter(JsonElement::isJsonObject) + .map(JsonElement::getAsJsonObject) + .toList().get(0); + this.resolvedLatestVersion = jsonResponse.get(CONST_JSON_FIELD).getAsString(); + return this.resolvedLatestVersion; + } catch (IOException | InterruptedException e) { + Logging.warningLog("Failed to resolve latest BreweryX version from GitHub. (No connection?)"); + this.resolvedLatestVersion = CONST_UNRESOLVED; + return CONST_UNRESOLVED; + } + }); + } + + @Override + public CompletableFuture checkForUpdate() { + return resolveLatest().thenApply(v -> { + if (v.equals(CONST_UNRESOLVED)) { + return false; + } + return isUpdateAvailable(); + }); + } +} diff --git a/src/main/resources/config-langs/de.yml b/src/main/resources/config-langs/de.yml index 89860011..14d5b24b 100644 --- a/src/main/resources/config-langs/de.yml +++ b/src/main/resources/config-langs/de.yml @@ -7,7 +7,7 @@ config: Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. - Options available: GitHub, Spigot, None [GitHub] + Options available: GitHub, Snapshots, Spigot, None [GitHub] autosave: "Autosave Intervall in Minuten [10]" pluginPrefix: "Prefix used on messages" debug: "Debug Nachrichten im Log anzeigen [false]" diff --git a/src/main/resources/config-langs/en.yml b/src/main/resources/config-langs/en.yml index 0a2b50a0..3c7971c7 100644 --- a/src/main/resources/config-langs/en.yml +++ b/src/main/resources/config-langs/en.yml @@ -7,7 +7,7 @@ config: Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. - Options available: GitHub, Spigot, None [GitHub] + Options available: GitHub, Snapshots, Spigot, None [GitHub] autosave: "Autosave interval in minutes [10]" pluginPrefix: "Prefix used on messages" debug: "Show debug messages in logs [false]" diff --git a/src/main/resources/config-langs/es.yml b/src/main/resources/config-langs/es.yml index 821946d3..2b6f202c 100644 --- a/src/main/resources/config-langs/es.yml +++ b/src/main/resources/config-langs/es.yml @@ -7,7 +7,7 @@ config: Tipos disponibles: en (Inglés), de (Alemán), es (Español), fr (Francés), it (Italiano), ru (Ruso), zh (Chino) updateCheck: | Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. - Options available: GitHub, Spigot, None [GitHub] + Options available: GitHub, Snapshots, Spigot, None [GitHub] autosave: "Intervalo de autoguardado en minutos [10]" pluginPrefix: "Prefijo usado en los mensajes" debug: "Mostrar mensajes de depuración en los registros [false]" diff --git a/src/main/resources/config-langs/fr.yml b/src/main/resources/config-langs/fr.yml index d77cb0e9..cc5b8c56 100644 --- a/src/main/resources/config-langs/fr.yml +++ b/src/main/resources/config-langs/fr.yml @@ -11,7 +11,7 @@ config: Valeurs disponibles: en (Anglais), de (Allemande), es (Espagnol), fr (Français), it (Italien), ru (Russe), zh (Chinois) updateCheck: | Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. - Options available: GitHub, Spigot, None [GitHub] + Options available: GitHub, Snapshots, Spigot, None [GitHub] autosave: "Intervale de la sauvegarde automatique en minutes [10]" pluginPrefix: "Préfixe utilisé avec les messages BreweryX" debug: "Afficher les messages de débogue dans le journal du serveur (log) [false]" diff --git a/src/main/resources/config-langs/it.yml b/src/main/resources/config-langs/it.yml index 8635280f..e9a5f489 100644 --- a/src/main/resources/config-langs/it.yml +++ b/src/main/resources/config-langs/it.yml @@ -7,7 +7,7 @@ config: Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. - Options available: GitHub, Spigot, None [GitHub] + Options available: GitHub, Snapshots, Spigot, None [GitHub] autosave: "Intervallo di autosalvataggio in minuti [10]" pluginPrefix: "Prefix used on messages" debug: "Show debug messages in logs [false]" diff --git a/src/main/resources/config-langs/ru.yml b/src/main/resources/config-langs/ru.yml index 9048f115..65f3371a 100644 --- a/src/main/resources/config-langs/ru.yml +++ b/src/main/resources/config-langs/ru.yml @@ -7,7 +7,7 @@ config: Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. - Options available: GitHub, Spigot, None [GitHub] + Options available: GitHub, Snapshots, Spigot, None [GitHub] autosave: "Период автосохранения данных (в минутах) [10]" pluginPrefix: | Префикс плагина, используемый в сообщениях. diff --git a/src/main/resources/config-langs/zh.yml b/src/main/resources/config-langs/zh.yml index 07c889d7..705ea229 100644 --- a/src/main/resources/config-langs/zh.yml +++ b/src/main/resources/config-langs/zh.yml @@ -7,7 +7,7 @@ config: Available types: en (English), de (German), es (Spanish), fr (French), it (Italian), ru (Russian), zh (Chinese) updateCheck: | Should BreweryX check for updates? Specify which service you'd like to use for update checking or disable it. - Options available: GitHub, Spigot, None [GitHub] + Options available: GitHub, Snapshots, Spigot, None [GitHub] autosave: "自动保存时间间隔, 单位:分钟 [10]" pluginPrefix: "用于此插件的消息前缀[Brewery]" debug: "是否在日志中显示调试信息 [false]" From d61f30e044b490d1a20513acaf27976349cbe5cd Mon Sep 17 00:00:00 2001 From: Jsinco Date: Fri, 20 Dec 2024 19:59:22 -0500 Subject: [PATCH 25/26] add hangar-publish.yml --- .github/workflows/hangar-publish.yml | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/hangar-publish.yml diff --git a/.github/workflows/hangar-publish.yml b/.github/workflows/hangar-publish.yml new file mode 100644 index 00000000..3809084a --- /dev/null +++ b/.github/workflows/hangar-publish.yml @@ -0,0 +1,29 @@ +name: 'Upload to Hangar' + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + if: ${{ github.event.release.prerelease }} == false + steps: + - uses: benwoo1110/hangar-upload-action@v1 + with: + api_token: ${{ secrets.HANGAR_TOKEN }} + slug: 'BreweryX' + version: ${{ github.event.release.tag_name }} + channel: release + description: ${{ github.event.release.body }} + files: | + [ + { + "path": "build/libs/BreweryX-*.jar", + "platforms": ["PAPER", "FOLIA"] + } + ] +# platform_dependencies: | +# { +# "PAPER": ["1.12","1.16-1.18.2","1.20.x"] +# } \ No newline at end of file From 8af9384f803bb25534515ec7a63555abaf7bbbe4 Mon Sep 17 00:00:00 2001 From: Jsinco Date: Fri, 20 Dec 2024 20:00:30 -0500 Subject: [PATCH 26/26] specify branch for this --- .github/workflows/hangar-publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/hangar-publish.yml b/.github/workflows/hangar-publish.yml index 3809084a..6c8b2fef 100644 --- a/.github/workflows/hangar-publish.yml +++ b/.github/workflows/hangar-publish.yml @@ -2,6 +2,7 @@ name: 'Upload to Hangar' on: release: + branches: [master] types: [published] jobs: