From 847790c5141ef3174da049b32c09a02876eeb119 Mon Sep 17 00:00:00 2001 From: William278 Date: Sat, 10 Sep 2022 19:25:07 +0300 Subject: [PATCH 1/7] Remove `api` module, include it in with the `bukkit` module for simplicity --- api/build.gradle | 34 ------------------- build.gradle | 4 +-- .../william278/husksync/api/HuskSyncAPI.java | 0 plugin/build.gradle | 1 - settings.gradle | 1 - 5 files changed, 2 insertions(+), 38 deletions(-) delete mode 100644 api/build.gradle rename {api => bukkit}/src/main/java/net/william278/husksync/api/HuskSyncAPI.java (100%) diff --git a/api/build.gradle b/api/build.gradle deleted file mode 100644 index 2e9ad263..00000000 --- a/api/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -dependencies { - implementation project(path: ':bukkit') - compileOnly project(path: ':common') - - compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT' - compileOnly 'org.jetbrains:annotations:23.0.0' -} - -shadowJar { - dependencies { - exclude(dependency('com.mojang:brigadier')) - } - - relocate 'org.apache', 'net.william278.husksync.libraries' - relocate 'dev.dejvokep', 'net.william278.husksync.libraries' - relocate 'de.themoep', 'net.william278.husksync.libraries' - relocate 'org.jetbrains', 'net.william278.husksync.libraries' - relocate 'org.intellij', 'net.william278.husksync.libraries' - relocate 'com.zaxxer', 'net.william278.husksync.libraries' - relocate 'com.google', 'net.william278.husksync.libraries' - relocate 'redis.clients', 'net.william278.husksync.libraries' - relocate 'org.json', 'net.william278.husksync.libraries.json' - relocate 'me.lucko.commodore', 'net.william278.husksync.libraries.commodore' - - relocate 'net.byteflux.libby', 'net.william278.husksync.libraries.libby' - relocate 'org.bstats', 'net.william278.husksync.libraries.bstats' - relocate 'net.william278.mpdbconverter', 'net.william278.husksync.libraries.mpdbconverter' - relocate 'net.william278.hslmigrator', 'net.william278.husksync.libraries.hslconverter' -} - -java { - withSourcesJar() - withJavadocJar() -} \ No newline at end of file diff --git a/build.gradle b/build.gradle index ce3b2ea7..275edfa9 100644 --- a/build.gradle +++ b/build.gradle @@ -56,14 +56,14 @@ subprojects { version rootProject.version archivesBaseName = "${rootProject.name}-${project.name.capitalize()}" - if (['bukkit', 'api', 'plugin'].contains(project.name)) { + if (['bukkit', 'plugin'].contains(project.name)) { shadowJar { destinationDirectory.set(file("$rootDir/target")) archiveClassifier.set('') } // API publishing - if ('api'.contains(project.name)) { + if ('bukkit'.contains(project.name)) { java { withSourcesJar() withJavadocJar() diff --git a/api/src/main/java/net/william278/husksync/api/HuskSyncAPI.java b/bukkit/src/main/java/net/william278/husksync/api/HuskSyncAPI.java similarity index 100% rename from api/src/main/java/net/william278/husksync/api/HuskSyncAPI.java rename to bukkit/src/main/java/net/william278/husksync/api/HuskSyncAPI.java diff --git a/plugin/build.gradle b/plugin/build.gradle index e121c5b2..32b9327e 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -1,6 +1,5 @@ dependencies { implementation project(path: ':bukkit', configuration: 'shadow') - implementation project(path: ':api', configuration: 'shadow') } shadowJar { diff --git a/settings.gradle b/settings.gradle index 914df6f3..c0e4840c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,5 +8,4 @@ rootProject.name = 'HuskSync' include 'common' include 'bukkit' -include 'api' include 'plugin' \ No newline at end of file From ff1ace834280c478a4e32955800290250016b98f Mon Sep 17 00:00:00 2001 From: William278 Date: Sat, 10 Sep 2022 19:27:26 +0300 Subject: [PATCH 2/7] Update version format --- build.gradle | 4 ++-- .../src/main/java/net/william278/husksync/util/Version.java | 2 +- gradle.properties | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 275edfa9..d6a0883b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group 'net.william278' -version "$ext.plugin_version+${versionMetadata()}" +version "$ext.plugin_version-${versionMetadata()}" ext { set 'version', version.toString() @@ -102,5 +102,5 @@ def versionMetadata() { if (grgit == null) { return System.getenv("GITHUB_RUN_NUMBER") ? 'build.' + System.getenv("GITHUB_RUN_NUMBER") : 'unknown' } - return 'rev.' + grgit.head().abbreviatedId + (grgit.status().clean ? '' : '-indev') + return grgit.head().abbreviatedId + (grgit.status().clean ? '' : '-indev') } \ No newline at end of file diff --git a/common/src/main/java/net/william278/husksync/util/Version.java b/common/src/main/java/net/william278/husksync/util/Version.java index d93cc8e8..1ed1799f 100644 --- a/common/src/main/java/net/william278/husksync/util/Version.java +++ b/common/src/main/java/net/william278/husksync/util/Version.java @@ -9,7 +9,7 @@ import java.util.regex.Pattern; public class Version implements Comparable { private final static String VERSION_SEPARATOR = "."; private final static String MINECRAFT_META_SEPARATOR = "-"; - private final static String PLUGIN_META_SEPARATOR = "+"; + private final static String PLUGIN_META_SEPARATOR = "-"; private int[] versions = new int[]{}; @NotNull diff --git a/gradle.properties b/gradle.properties index 1928bb97..d2bffd12 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8' org.gradle.daemon=true javaVersion=16 -plugin_version=2.0.2 +plugin_version=2.1 plugin_archive=husksync jedis_version=4.2.3 From 61020e04d9a690e9a5ef028744e340127583db0c Mon Sep 17 00:00:00 2001 From: William278 Date: Sat, 10 Sep 2022 19:40:53 +0300 Subject: [PATCH 3/7] Fix typo in default command description --- .../main/java/net/william278/husksync/command/CommandBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/net/william278/husksync/command/CommandBase.java b/common/src/main/java/net/william278/husksync/command/CommandBase.java index c13038ae..e7aac53c 100644 --- a/common/src/main/java/net/william278/husksync/command/CommandBase.java +++ b/common/src/main/java/net/william278/husksync/command/CommandBase.java @@ -52,7 +52,7 @@ public abstract class CommandBase { */ public String getDescription() { return plugin.getLocales().getRawLocale(command + "_command_description") - .orElse("A HuskHomes command"); + .orElse("A HuskSync command"); } } From 59a0002c160ce4b784ce86b53b55eea70dda82ea Mon Sep 17 00:00:00 2001 From: William278 Date: Sat, 10 Sep 2022 19:52:34 +0300 Subject: [PATCH 4/7] Migrate to DesertWell for about menu, version checking --- bukkit/build.gradle | 2 + .../william278/husksync/BukkitHuskSync.java | 25 ++++-- .../husksync/player/BukkitPlayer.java | 4 +- common/build.gradle | 2 + .../net/william278/husksync/HuskSync.java | 21 ++++- .../husksync/command/HuskSyncCommand.java | 81 ++++++++++++------- .../husksync/command/Permission.java | 2 +- .../william278/husksync/config/Locales.java | 41 ---------- .../husksync/player/OnlineUser.java | 4 +- .../husksync/util/UpdateChecker.java | 57 ------------- .../net/william278/husksync/util/Version.java | 71 ---------------- .../husksync/player/DummyPlayer.java | 4 +- 12 files changed, 101 insertions(+), 213 deletions(-) delete mode 100644 common/src/main/java/net/william278/husksync/util/UpdateChecker.java delete mode 100644 common/src/main/java/net/william278/husksync/util/Version.java diff --git a/bukkit/build.gradle b/bukkit/build.gradle index 0942897a..5af21039 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -10,6 +10,7 @@ dependencies { compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT' compileOnly 'dev.dejvokep:boosted-yaml:1.3' compileOnly 'com.zaxxer:HikariCP:5.0.1' + compileOnly 'net.william278:DesertWell:1.0' testImplementation 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT' } @@ -26,6 +27,7 @@ shadowJar { relocate 'org.intellij', 'net.william278.husksync.libraries' relocate 'com.zaxxer', 'net.william278.husksync.libraries' relocate 'dev.dejvokep', 'net.william278.husksync.libraries' + relocate 'net.william278.desertwell', 'net.william278.huskhomes.libraries.desertwell' relocate 'me.lucko.commodore', 'net.william278.husksync.libraries.commodore' relocate 'net.byteflux.libby', 'net.william278.husksync.libraries.libby' diff --git a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java index 0d62b01b..5f566f5d 100644 --- a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java +++ b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java @@ -6,6 +6,7 @@ import dev.dejvokep.boostedyaml.settings.dumper.DumperSettings; import dev.dejvokep.boostedyaml.settings.general.GeneralSettings; import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings; import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; +import net.william278.desertwell.Version; import net.william278.husksync.command.BukkitCommand; import net.william278.husksync.command.BukkitCommandType; import net.william278.husksync.command.Permission; @@ -28,7 +29,10 @@ import net.william278.husksync.migrator.MpdbMigrator; import net.william278.husksync.player.BukkitPlayer; import net.william278.husksync.player.OnlineUser; import net.william278.husksync.redis.RedisManager; -import net.william278.husksync.util.*; +import net.william278.husksync.util.BukkitLogger; +import net.william278.husksync.util.BukkitResourceReader; +import net.william278.husksync.util.Logger; +import net.william278.husksync.util.ResourceReader; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.command.PluginCommand; @@ -127,7 +131,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync { getLoggingAdapter().log(Level.INFO, "Successfully established a connection to the database"); } else { throw new HuskSyncInitializationException("Failed to establish a connection to the database. " + - "Please check the supplied database credentials in the config file"); + "Please check the supplied database credentials in the config file"); } // Prepare redis connection @@ -138,7 +142,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync { getLoggingAdapter().log(Level.INFO, "Successfully established a connection to the Redis server"); } else { throw new HuskSyncInitializationException("Failed to establish a connection to the Redis server. " + - "Please check the supplied Redis credentials in the config file"); + "Please check the supplied Redis credentials in the config file"); } // Register events @@ -181,7 +185,10 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync { // Check for updates if (settings.getBooleanValue(Settings.ConfigOption.CHECK_FOR_UPDATES)) { getLoggingAdapter().log(Level.INFO, "Checking for updates..."); - CompletableFuture.runAsync(() -> new UpdateChecker(getPluginVersion(), getLoggingAdapter()).logToConsole()); + getLatestVersionIfOutdated().thenAccept(newestVersion -> + newestVersion.ifPresent(newVersion -> getLoggingAdapter().log(Level.WARNING, + "An update is available for HuskSync, v" + newVersion + + " (Currently running v" + getPluginVersion() + ")"))); } } catch (HuskSyncInitializationException exception) { getLoggingAdapter().log(Level.SEVERE, """ @@ -286,14 +293,16 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync { return resourceReader; } + @NotNull @Override - public @NotNull Version getPluginVersion() { - return Version.pluginVersion(getDescription().getVersion()); + public Version getPluginVersion() { + return Version.fromString(getDescription().getVersion(), "-"); } + @NotNull @Override - public @NotNull Version getMinecraftVersion() { - return Version.minecraftVersion(Bukkit.getBukkitVersion()); + public Version getMinecraftVersion() { + return Version.fromMinecraftVersionString(Bukkit.getBukkitVersion()); } @Override diff --git a/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java b/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java index d835d07f..e1503c60 100644 --- a/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java +++ b/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java @@ -6,7 +6,7 @@ import net.md_5.bungee.api.chat.BaseComponent; import net.william278.husksync.BukkitHuskSync; import net.william278.husksync.data.*; import net.william278.husksync.editor.ItemEditorMenu; -import net.william278.husksync.util.Version; +import net.william278.desertwell.Version; import org.bukkit.*; import org.bukkit.advancement.Advancement; import org.bukkit.advancement.AdvancementProgress; @@ -554,7 +554,7 @@ public class BukkitPlayer extends OnlineUser { @NotNull @Override public Version getMinecraftVersion() { - return Version.minecraftVersion(Bukkit.getBukkitVersion()); + return Version.fromMinecraftVersionString(Bukkit.getBukkitVersion()); } @Override diff --git a/common/build.gradle b/common/build.gradle index 9b94a48c..951a3f09 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -3,6 +3,7 @@ dependencies { implementation 'de.themoep:minedown:1.7.1-SNAPSHOT' implementation 'com.google.code.gson:gson:2.9.0' implementation 'dev.dejvokep:boosted-yaml:1.3' + implementation 'net.william278:DesertWell:1.0' implementation ('com.zaxxer:HikariCP:5.0.1') { exclude module: 'slf4j-api' } @@ -26,4 +27,5 @@ shadowJar { relocate 'org.intellij', 'net.william278.husksync.libraries' relocate 'com.zaxxer', 'net.william278.husksync.libraries' relocate 'dev.dejvokep', 'net.william278.husksync.libraries' + relocate 'net.william278.desertwell', 'net.william278.husksync.libraries.desertwell' } \ No newline at end of file diff --git a/common/src/main/java/net/william278/husksync/HuskSync.java b/common/src/main/java/net/william278/husksync/HuskSync.java index 7c20ddea..a3511160 100644 --- a/common/src/main/java/net/william278/husksync/HuskSync.java +++ b/common/src/main/java/net/william278/husksync/HuskSync.java @@ -1,5 +1,6 @@ package net.william278.husksync; +import net.william278.desertwell.UpdateChecker; import net.william278.husksync.config.Locales; import net.william278.husksync.config.Settings; import net.william278.husksync.data.DataAdapter; @@ -11,7 +12,7 @@ import net.william278.husksync.player.OnlineUser; import net.william278.husksync.redis.RedisManager; import net.william278.husksync.util.Logger; import net.william278.husksync.util.ResourceReader; -import net.william278.husksync.util.Version; +import net.william278.desertwell.Version; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -25,6 +26,8 @@ import java.util.concurrent.CompletableFuture; */ public interface HuskSync { + int SPIGOT_RESOURCE_ID = 97144; + /** * Returns a set of online players. * @@ -131,6 +134,22 @@ public interface HuskSync { @NotNull Version getPluginVersion(); + /** + * Returns a future returning the latest plugin {@link Version} if the plugin is out-of-date + * + * @return a {@link CompletableFuture} returning the latest {@link Version} if the current one is out-of-date + */ + default CompletableFuture> getLatestVersionIfOutdated() { + final UpdateChecker updateChecker = UpdateChecker.create(getPluginVersion(), SPIGOT_RESOURCE_ID); + return updateChecker.isUpToDate().thenApply(upToDate -> { + if (upToDate) { + return Optional.empty(); + } else { + return Optional.of(updateChecker.getLatestVersion().join()); + } + }); + } + /** * Returns the Minecraft version implementation * diff --git a/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java b/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java index 02bfd1f5..f6a5fe89 100644 --- a/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java +++ b/common/src/main/java/net/william278/husksync/command/HuskSyncCommand.java @@ -1,11 +1,10 @@ package net.william278.husksync.command; import de.themoep.minedown.MineDown; +import net.william278.desertwell.AboutMenu; import net.william278.husksync.HuskSync; -import net.william278.husksync.config.Locales; import net.william278.husksync.migrator.Migrator; import net.william278.husksync.player.OnlineUser; -import net.william278.husksync.util.UpdateChecker; import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -17,16 +16,41 @@ import java.util.stream.Collectors; public class HuskSyncCommand extends CommandBase implements TabCompletable, ConsoleExecutable { - private final String[] COMMAND_ARGUMENTS = {"update", "about", "reload", "migrate"}; + private final String[] SUB_COMMANDS = {"update", "about", "reload", "migrate"}; + private final AboutMenu aboutMenu; public HuskSyncCommand(@NotNull HuskSync implementor) { super("husksync", Permission.COMMAND_HUSKSYNC, implementor); + this.aboutMenu = AboutMenu.create("HuskSync") + .withDescription("A modern, cross-server player data synchronization system") + .withVersion(implementor.getPluginVersion()) + .addAttribution("Author", + AboutMenu.Credit.of("William278").withDescription("Click to visit website").withUrl("https://william278.net")) + .addAttribution("Contributors", + AboutMenu.Credit.of("HarvelsX").withDescription("Code"), + AboutMenu.Credit.of("HookWoods").withDescription("Code")) + .addAttribution("Translators", + AboutMenu.Credit.of("Namiu").withDescription("Japanese (ja-jp)"), + AboutMenu.Credit.of("anchelthe").withDescription("Spanish (es-es)"), + AboutMenu.Credit.of("Melonzio").withDescription("Spanish (es-es)"), + AboutMenu.Credit.of("Ceddix").withDescription("German (de-de)"), + AboutMenu.Credit.of("Pukejoy_1").withDescription("Bulgarian (bg-bg)"), + AboutMenu.Credit.of("mateusneresrb").withDescription("Brazilian Portuguese (pt-br)"), + AboutMenu.Credit.of("小蔡").withDescription("Traditional Chinese (zh-tw)"), + AboutMenu.Credit.of("Ghost-chu").withDescription("Simplified Chinese (zh-cn)"), + AboutMenu.Credit.of("DJelly4K").withDescription("Simplified Chinese (zh-cn)"), + AboutMenu.Credit.of("Thourgard").withDescription("Ukrainian (uk-ua)"), + AboutMenu.Credit.of("xF3d3").withDescription("Italian (it-it)")) + .addButtons( + AboutMenu.Link.of("https://william278.net/docs/husksync").withText("Documentation").withIcon("⛏"), + AboutMenu.Link.of("https://github.com/WiIIiam278/HuskSync/issues").withText("Issues").withIcon("❌").withColor("#ff9f0f"), + AboutMenu.Link.of("https://discord.gg/tVYhJfyDWG").withText("Discord").withIcon("⭐").withColor("#6773f5")); } @Override public void onExecute(@NotNull OnlineUser player, @NotNull String[] args) { if (args.length < 1) { - displayPluginInformation(player); + sendAboutMenu(player); return; } switch (args[0].toLowerCase()) { @@ -35,18 +59,16 @@ public class HuskSyncCommand extends CommandBase implements TabCompletable, Cons plugin.getLocales().getLocale("error_no_permission").ifPresent(player::sendMessage); return; } - final UpdateChecker updateChecker = new UpdateChecker(plugin.getPluginVersion(), plugin.getLoggingAdapter()); - updateChecker.fetchLatestVersion().thenAccept(latestVersion -> { - if (updateChecker.isUpdateAvailable(latestVersion)) { - player.sendMessage(new MineDown("[HuskSync](#00fb9a bold) [| A new update is available:](#00fb9a) [HuskSync " + latestVersion + "](#00fb9a bold)" + - "[•](white) [Currently running:](#00fb9a) [Version " + updateChecker.getCurrentVersion() + "](gray)" + - "[•](white) [Download links:](#00fb9a) [[⏩ Spigot]](gray open_url=https://www.spigotmc.org/resources/husksync.97144/updates) [•](#262626) [[⏩ Polymart]](gray open_url=https://polymart.org/resource/husksync.1634/updates) [•](#262626) [[⏩ Songoda]](gray open_url=https://songoda.com/marketplace/product/husksync-a-modern-cross-server-player-data-synchronization-system.758)")); - } else { - player.sendMessage(new MineDown("[HuskSync](#00fb9a bold) [| HuskSync is up-to-date, running version " + updateChecker.getCurrentVersion() + "](#00fb9a)")); - } - }); + plugin.getLatestVersionIfOutdated().thenAccept(newestVersion -> + newestVersion.ifPresentOrElse( + newVersion -> player.sendMessage( + new MineDown("[HuskSync](#00fb9a bold) [| A new version of HuskSync is available!" + + " (v" + newVersion + " (Running: v" + plugin.getPluginVersion() + ")](#00fb9a)")), + () -> player.sendMessage( + new MineDown("[HuskSync](#00fb9a bold) [| HuskSync is up-to-date." + + " (Running: v" + plugin.getPluginVersion() + ")](#00fb9a)")))); } - case "info", "about" -> displayPluginInformation(player); + case "about", "info" -> sendAboutMenu(player); case "reload" -> { if (!player.hasPermission(Permission.COMMAND_HUSKSYNC_RELOAD.node)) { plugin.getLocales().getLocale("error_no_permission").ifPresent(player::sendMessage); @@ -70,11 +92,14 @@ public class HuskSyncCommand extends CommandBase implements TabCompletable, Cons return; } switch (args[0].toLowerCase()) { - case "update", "version" -> - new UpdateChecker(plugin.getPluginVersion(), plugin.getLoggingAdapter()).logToConsole(); - case "info", "about" -> - plugin.getLoggingAdapter().log(Level.INFO, new MineDown(plugin.getLocales().stripMineDown( - Locales.PLUGIN_INFORMATION.replace("%version%", plugin.getPluginVersion().toString())))); + case "update", "version" -> plugin.getLatestVersionIfOutdated().thenAccept(newestVersion -> + newestVersion.ifPresentOrElse(newVersion -> plugin.getLoggingAdapter().log(Level.WARNING, + "An update is available for HuskSync, v" + newVersion + + " (Running v" + plugin.getPluginVersion() + ")"), + () -> plugin.getLoggingAdapter().log(Level.INFO, + "HuskSync is up to date" + + " (Running v" + plugin.getPluginVersion() + ")"))); + case "about", "info" -> aboutMenu.toString().lines().forEach(plugin.getLoggingAdapter()::info); case "reload" -> { plugin.reload(); plugin.getLoggingAdapter().log(Level.INFO, "Reloaded config & message files."); @@ -108,7 +133,7 @@ public class HuskSyncCommand extends CommandBase implements TabCompletable, Cons }, () -> { plugin.getLoggingAdapter().log(Level.INFO, "Please specify a valid migrator.\n" + - "If a migrator is not available, please verify that you meet the prerequisites to use it."); + "If a migrator is not available, please verify that you meet the prerequisites to use it."); logMigratorsList(); }); } @@ -120,26 +145,26 @@ public class HuskSyncCommand extends CommandBase implements TabCompletable, Cons private void logMigratorsList() { plugin.getLoggingAdapter().log(Level.INFO, "List of available migrators:\nMigrator ID / Migrator Name:\n" + - plugin.getAvailableMigrators().stream() - .map(migrator -> migrator.getIdentifier() + " - " + migrator.getName()) - .collect(Collectors.joining("\n"))); + plugin.getAvailableMigrators().stream() + .map(migrator -> migrator.getIdentifier() + " - " + migrator.getName()) + .collect(Collectors.joining("\n"))); } @Override public List onTabComplete(@NotNull String[] args) { if (args.length <= 1) { - return Arrays.stream(COMMAND_ARGUMENTS) + return Arrays.stream(SUB_COMMANDS) .filter(argument -> argument.startsWith(args.length >= 1 ? args[0] : "")) .sorted().collect(Collectors.toList()); } return Collections.emptyList(); } - private void displayPluginInformation(@NotNull OnlineUser player) { - if (!player.hasPermission(Permission.COMMAND_HUSKSYNC_INFO.node)) { + private void sendAboutMenu(@NotNull OnlineUser player) { + if (!player.hasPermission(Permission.COMMAND_HUSKSYNC_ABOUT.node)) { plugin.getLocales().getLocale("error_no_permission").ifPresent(player::sendMessage); return; } - player.sendMessage(new MineDown(Locales.PLUGIN_INFORMATION.replace("%version%", plugin.getPluginVersion().toString()))); + player.sendMessage(aboutMenu.toMineDown()); } } diff --git a/common/src/main/java/net/william278/husksync/command/Permission.java b/common/src/main/java/net/william278/husksync/command/Permission.java index 4e7dba78..344b3666 100644 --- a/common/src/main/java/net/william278/husksync/command/Permission.java +++ b/common/src/main/java/net/william278/husksync/command/Permission.java @@ -18,7 +18,7 @@ public enum Permission { /** * Lets the user view plugin info {@code /husksync info} */ - COMMAND_HUSKSYNC_INFO("husksync.command.husksync.info", DefaultAccess.EVERYONE), + COMMAND_HUSKSYNC_ABOUT("husksync.command.husksync.info", DefaultAccess.EVERYONE), /** * Lets the user reload the plugin {@code /husksync reload} */ diff --git a/common/src/main/java/net/william278/husksync/config/Locales.java b/common/src/main/java/net/william278/husksync/config/Locales.java index e2f281e8..cf5c3deb 100644 --- a/common/src/main/java/net/william278/husksync/config/Locales.java +++ b/common/src/main/java/net/william278/husksync/config/Locales.java @@ -6,7 +6,6 @@ import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Optional; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -14,16 +13,6 @@ import java.util.regex.Pattern; */ public class Locales { - public static final String PLUGIN_INFORMATION = """ - [HuskSync](#00fb9a bold) [| Version %version%](#00fb9a) - [A modern, cross-server player data synchronization system](gray) - [• Author:](white) [William278](gray show_text=&7Click to visit website open_url=https://william278.net) - [• Contributors:](white) [HarvelsX](gray show_text=&7Code), [HookWoods](gray show_text=&7Code) - [• Translators:](white) [Namiu](gray show_text=&7\\(うにたろう\\) - Japanese, ja-jp), [anchelthe](gray show_text=&7Spanish, es-es), [Melonzio](gray show_text=&7Spanish, es-es), [Ceddix](gray show_text=&7German, de-de), [Pukejoy_1](gray show_text=&7Bulgarian, bg-bg), [mateusneresrb](gray show_text=&7Brazilian Portuguese, pt-br], [小蔡](gray show_text=&7Traditional Chinese, zh-tw), [Ghost-chu](gray show_text=&7Simplified Chinese, zh-cn), [DJelly4K](gray show_text=&7Simplified Chinese, zh-cn), [Thourgard](gray show_text=&7Ukrainian, uk-ua), [xF3d3](gray show_text=&7Italian, it-it) - [• Documentation:](white) [[Link]](#00fb9a show_text=&7Click to open link open_url=https://william278.net/docs/husksync/Home/) - [• Bug reporting:](white) [[Link]](#00fb9a show_text=&7Click to open link open_url=https://github.com/WiIIiam278/HuskSync/issues) - [• Discord support:](white) [[Link]](#00fb9a show_text=&7Click to join open_url=https://discord.gg/tVYhJfyDWG)"""; - @NotNull private final HashMap rawLocales; @@ -106,34 +95,4 @@ public class Locales { return new Locales(localesConfig); } - /** - * Strips a string of basic MineDown formatting, used for displaying plugin info to console - * - * @param string The string to strip - * @return The MineDown-stripped string - */ - public String stripMineDown(@NotNull String string) { - final String[] in = string.split("\n"); - final StringBuilder out = new StringBuilder(); - String regex = "[^\\[\\]() ]*\\[([^()]+)]\\([^()]+open_url=(\\S+).*\\)"; - - for (int i = 0; i < in.length; i++) { - Pattern pattern = Pattern.compile(regex); - Matcher m = pattern.matcher(in[i]); - - if (m.find()) { - out.append(in[i].replace(m.group(0), "")); - out.append(m.group(2)); - } else { - out.append(in[i]); - } - - if (i + 1 != in.length) { - out.append("\n"); - } - } - - return out.toString(); - } - } diff --git a/common/src/main/java/net/william278/husksync/player/OnlineUser.java b/common/src/main/java/net/william278/husksync/player/OnlineUser.java index d3e08903..a28a35d8 100644 --- a/common/src/main/java/net/william278/husksync/player/OnlineUser.java +++ b/common/src/main/java/net/william278/husksync/player/OnlineUser.java @@ -7,7 +7,7 @@ import net.william278.husksync.editor.ItemEditorMenu; import net.william278.husksync.event.EventCannon; import net.william278.husksync.event.PreSyncEvent; import net.william278.husksync.util.Logger; -import net.william278.husksync.util.Version; +import net.william278.desertwell.Version; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -176,7 +176,7 @@ public abstract class OnlineUser extends User { @NotNull Version serverMinecraftVersion) { return CompletableFuture.supplyAsync(() -> { // Prevent synchronising user data from newer versions of Minecraft - if (Version.minecraftVersion(data.getMinecraftVersion()).compareTo(serverMinecraftVersion) > 0) { + if (Version.fromMinecraftVersionString(data.getMinecraftVersion()).compareTo(serverMinecraftVersion) > 0) { logger.log(Level.SEVERE, "Cannot set data for " + username + " because the Minecraft version of their user data (" + data.getMinecraftVersion() + ") is newer than the server's Minecraft version (" + serverMinecraftVersion + ")."); diff --git a/common/src/main/java/net/william278/husksync/util/UpdateChecker.java b/common/src/main/java/net/william278/husksync/util/UpdateChecker.java deleted file mode 100644 index 4d9f48ad..00000000 --- a/common/src/main/java/net/william278/husksync/util/UpdateChecker.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.william278.husksync.util; - -import org.jetbrains.annotations.NotNull; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.util.concurrent.CompletableFuture; -import java.util.logging.Level; - -public class UpdateChecker { - - private final static int SPIGOT_PROJECT_ID = 97144; - private final Logger logger; - private final Version currentVersion; - - public UpdateChecker(@NotNull Version currentVersion, @NotNull Logger logger) { - this.currentVersion = currentVersion; - this.logger = logger; - } - - public CompletableFuture fetchLatestVersion() { - return CompletableFuture.supplyAsync(() -> { - try { - final URL url = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + SPIGOT_PROJECT_ID); - URLConnection urlConnection = url.openConnection(); - return Version.pluginVersion(new BufferedReader(new InputStreamReader(urlConnection.getInputStream())).readLine()); - } catch (Exception e) { - logger.log(Level.WARNING, "Failed to fetch the latest plugin version", e); - } - return new Version(); - }); - } - - public boolean isUpdateAvailable(@NotNull Version latestVersion) { - return latestVersion.compareTo(currentVersion) > 0; - } - - public Version getCurrentVersion() { - return currentVersion; - } - - public CompletableFuture isUpToDate() { - return fetchLatestVersion().thenApply(this::isUpdateAvailable); - } - - public void logToConsole() { - fetchLatestVersion().thenAccept(latestVersion -> { - if (isUpdateAvailable(latestVersion)) { - logger.log(Level.WARNING, "A new version of HuskSync is available: v" + latestVersion); - } else { - logger.log(Level.INFO, "HuskSync is up-to-date! (Running: v" + getCurrentVersion().toString() + ")"); - } - }); - } -} \ No newline at end of file diff --git a/common/src/main/java/net/william278/husksync/util/Version.java b/common/src/main/java/net/william278/husksync/util/Version.java deleted file mode 100644 index 1ed1799f..00000000 --- a/common/src/main/java/net/william278/husksync/util/Version.java +++ /dev/null @@ -1,71 +0,0 @@ -package net.william278.husksync.util; - -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.StringJoiner; -import java.util.regex.Pattern; - -public class Version implements Comparable { - private final static String VERSION_SEPARATOR = "."; - private final static String MINECRAFT_META_SEPARATOR = "-"; - private final static String PLUGIN_META_SEPARATOR = "-"; - - private int[] versions = new int[]{}; - @NotNull - private String metadata = ""; - @NotNull - private String metaSeparator = ""; - - protected Version() { - } - - private Version(@NotNull String version, @NotNull String metaSeparator) { - this.parse(version, metaSeparator); - this.metaSeparator = metaSeparator; - } - - @NotNull - public static Version pluginVersion(@NotNull String versionString) { - return new Version(versionString, PLUGIN_META_SEPARATOR); - } - - @NotNull - public static Version minecraftVersion(@NotNull String versionString) { - return new Version(versionString, MINECRAFT_META_SEPARATOR); - } - - private void parse(@NotNull String version, @NotNull String metaSeparator) { - int metaIndex = version.indexOf(metaSeparator); - if (metaIndex > 0) { - this.metadata = version.substring(metaIndex + 1); - version = version.substring(0, metaIndex); - } - String[] versions = version.split(Pattern.quote(VERSION_SEPARATOR)); - this.versions = Arrays.stream(versions).mapToInt(Integer::parseInt).toArray(); - } - - @Override - public int compareTo(@NotNull Version other) { - int length = Math.max(this.versions.length, other.versions.length); - for (int i = 0; i < length; i++) { - int a = i < this.versions.length ? this.versions[i] : 0; - int b = i < other.versions.length ? other.versions[i] : 0; - - if (a < b) return -1; - if (a > b) return 1; - } - - return 0; - } - - @Override - public String toString() { - final StringJoiner joiner = new StringJoiner(VERSION_SEPARATOR); - for (int version : this.versions) { - joiner.add(String.valueOf(version)); - } - return joiner + ((!this.metadata.isEmpty()) ? (this.metaSeparator + this.metadata) : ""); - } - -} diff --git a/common/src/test/java/net/william278/husksync/player/DummyPlayer.java b/common/src/test/java/net/william278/husksync/player/DummyPlayer.java index c8cb46c3..06bfdd69 100644 --- a/common/src/test/java/net/william278/husksync/player/DummyPlayer.java +++ b/common/src/test/java/net/william278/husksync/player/DummyPlayer.java @@ -3,7 +3,7 @@ package net.william278.husksync.player; import de.themoep.minedown.MineDown; import net.william278.husksync.data.*; import net.william278.husksync.editor.ItemEditorMenu; -import net.william278.husksync.util.Version; +import net.william278.desertwell.Version; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -132,7 +132,7 @@ public class DummyPlayer extends OnlineUser { @NotNull @Override public Version getMinecraftVersion() { - return Version.minecraftVersion("1.19-beta123456"); + return Version.fromMinecraftVersionString("1.19-beta123456"); } @Override From 31a14b2de77e8463a2b245c43ca2e106e3478750 Mon Sep 17 00:00:00 2001 From: William278 Date: Sat, 10 Sep 2022 19:58:53 +0300 Subject: [PATCH 5/7] [ci skip] Update README with new badges --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f0b1704f..cee4fd03 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # [![HuskSync Banner](images/banner-graphic.png)](https://github.com/WiIIiam278/HuskSync) -![Github Actions](https://github.com/WiIIiam278/HuskSync/workflows/Java%20CI/badge.svg) -[![Discord](https://img.shields.io/discord/818135932103557162?color=7289da&logo=discord)](https://discord.gg/tVYhJfyDWG) +[![GitHub CI](https://img.shields.io/github/workflow/status/WiIIiam278/HuskSync/Java%20CI?logo=github)](https://github.com/WiIIiam278/HuskSync/actions/workflows/java_ci.yml) +[![JitPack API](https://img.shields.io/jitpack/version/net.william278/HuskSync?color=%2300fb9a&label=api&logo=gradle)](https://jitpack.io/#net.william278/HuskSync) +[![Support Discord](https://img.shields.io/discord/818135932103557162.svg?label=&logo=discord&logoColor=fff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/tVYhJfyDWG) [Documentation, Guides & API](https://william278.net/docs/husksync/Home) · [Resource Page](https://www.spigotmc.org/resources/husksync.97144/) · [Bug Reports](https://github.com/WiIIiam278/HuskSync/issues) From abc41a0acaf85fb05d03c2df9247753c2b3c5836 Mon Sep 17 00:00:00 2001 From: William278 Date: Sat, 10 Sep 2022 20:01:00 +0300 Subject: [PATCH 6/7] [ci skip] Add screenshot to README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cee4fd03..14bd856a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ **HuskSync** is a modern, cross-server player data synchronisation system that enables the comprehensive synchronisation of your user's data across multiple proxied servers. It does this by making use of Redis and MySQL to optimally cache data while players change servers. ## Features +![Data snapshot viewer](images/data-snapshot-viewer.png) + - Synchronise inventories, ender chests, advancements, statistics, experience points, health, max health, hunger, saturation, potion effects, persistent data container tags, game mode, location and more across multiple proxied servers. - Create and manage "snapshot" backups of user data and roll back users to previous states on-the-fly. (`/userdata`) - Preview, list, delete, restore & pin user data snapshots in-game with an intuitive menu. @@ -24,7 +26,7 @@ 1. Place the plugin jar file in the `/plugins/` directory of each Spigot server. You do not need to install HuskSync as a proxy plugin. 2. Start, then stop every server to let HuskSync generate the config file. 3. Navigate to the HuskSync config file on each server (`~/plugins/HuskSync/config.yml`) and fill in both the MySQL and Redis database credentials. -4. Start every server again and synchronistaion will begin. +4. Start every server again and synchronization will begin. ## Building To build HuskSync, simply run the following in the root of the repository: From 97a02b7a05a531ae499cc5c2a0f94bc751a71d6c Mon Sep 17 00:00:00 2001 From: William278 Date: Sat, 10 Sep 2022 20:01:41 +0300 Subject: [PATCH 7/7] [ci skip] Tweak docs URL --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 14bd856a..7861698c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![JitPack API](https://img.shields.io/jitpack/version/net.william278/HuskSync?color=%2300fb9a&label=api&logo=gradle)](https://jitpack.io/#net.william278/HuskSync) [![Support Discord](https://img.shields.io/discord/818135932103557162.svg?label=&logo=discord&logoColor=fff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/tVYhJfyDWG) -[Documentation, Guides & API](https://william278.net/docs/husksync/Home) · [Resource Page](https://www.spigotmc.org/resources/husksync.97144/) · [Bug Reports](https://github.com/WiIIiam278/HuskSync/issues) +[Documentation, Guides & API](https://william278.net/docs/husksync) · [Resource Page](https://www.spigotmc.org/resources/husksync.97144/) · [Bug Reports](https://github.com/WiIIiam278/HuskSync/issues) **HuskSync** is a modern, cross-server player data synchronisation system that enables the comprehensive synchronisation of your user's data across multiple proxied servers. It does this by making use of Redis and MySQL to optimally cache data while players change servers. @@ -55,7 +55,7 @@ This plugin uses bStats to provide me with metrics about its usage: You can turn metric collection off by navigating to `~/plugins/bStats/config.yml` and editing the config to disable plugin metrics. ## Links -- [Documentation, Guides & API](https://william278.net/docs/husksync/Home) +- [Documentation, Guides & API](https://william278.net/docs/husksync) - [Resource Page](https://www.spigotmc.org/resources/husksync.97144/) - [Bug Reports](https://github.com/WiIIiam278/HuskSync/issues) - [Discord Support](https://discord.gg/tVYhJfyDWG) (Proof of purchase required)