diff --git a/pom.xml b/pom.xml index 9e30680..21a93d5 100644 --- a/pom.xml +++ b/pom.xml @@ -42,12 +42,19 @@ + org.bstats bstats-bukkit 3.0.2 compile + + + eu.m724 + jarupdater + 0.1.2 + @@ -72,15 +79,20 @@ 3.6.0 false - true - full + org.bstats - eu.m724.giants + + + org.bstats:* + eu.m724:jarupdater + + diff --git a/src/main/java/eu/m724/giants/Configuration.java b/src/main/java/eu/m724/giants/Configuration.java index 1b34d40..a754743 100644 --- a/src/main/java/eu/m724/giants/Configuration.java +++ b/src/main/java/eu/m724/giants/Configuration.java @@ -19,6 +19,8 @@ public class Configuration { private final File file; private final Logger logger; + String updater; + boolean ai; double attackDamage; @@ -42,6 +44,13 @@ public class Configuration { public void load() { YamlConfiguration config = YamlConfiguration.loadConfiguration(file); + updater = config.getString("updater", "true"); + if (updater.equalsIgnoreCase("true")) { + updater = "release"; + } else if (updater.equalsIgnoreCase("false")) { + updater = null; + } + ai = config.getBoolean("ai"); chance = config.getDouble("chance"); diff --git a/src/main/java/eu/m724/giants/GiantsCommand.java b/src/main/java/eu/m724/giants/GiantsCommand.java index a8337ef..14366c0 100644 --- a/src/main/java/eu/m724/giants/GiantsCommand.java +++ b/src/main/java/eu/m724/giants/GiantsCommand.java @@ -1,5 +1,6 @@ package eu.m724.giants; +import eu.m724.giants.updater.UpdateCommand; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -20,9 +21,12 @@ public class GiantsCommand implements CommandExecutor { private final GiantsPlugin plugin; private final Configuration configuration; - public GiantsCommand(GiantsPlugin plugin, Configuration configuration) { + private final UpdateCommand updateCommand; + + public GiantsCommand(GiantsPlugin plugin, Configuration configuration, UpdateCommand updateCommand) { this.plugin = plugin; this.configuration = configuration; + this.updateCommand = updateCommand; } @Override @@ -128,6 +132,11 @@ public class GiantsCommand implements CommandExecutor { } else { sender.sendMessage("Jump delay: " + configuration.jumpDelay); } + } else if (action.equals("update")) { + if (updateCommand != null) + updateCommand.onCommand(sender, command, label, args); + else + sender.sendMessage("Updater is disabled"); } return true; diff --git a/src/main/java/eu/m724/giants/GiantsPlugin.java b/src/main/java/eu/m724/giants/GiantsPlugin.java index 438ca14..bfdf89d 100644 --- a/src/main/java/eu/m724/giants/GiantsPlugin.java +++ b/src/main/java/eu/m724/giants/GiantsPlugin.java @@ -1,5 +1,7 @@ package eu.m724.giants; +import eu.m724.giants.updater.PluginUpdater; +import eu.m724.giants.updater.UpdateCommand; import org.bstats.bukkit.Metrics; import org.bukkit.Location; import org.bukkit.command.CommandExecutor; @@ -24,7 +26,14 @@ public class GiantsPlugin extends JavaPlugin implements CommandExecutor { configuration.load(); - getCommand("giants").setExecutor(new GiantsCommand(this, configuration)); + UpdateCommand updateCommand = null; + if (configuration.updater != null) { + PluginUpdater updater = PluginUpdater.build(this, configuration.updater); + updater.initNotifier(); + updateCommand = new UpdateCommand(updater); + } + + getCommand("giants").setExecutor(new GiantsCommand(this, configuration, updateCommand)); giantProcessor.start(); @@ -37,6 +46,7 @@ public class GiantsPlugin extends JavaPlugin implements CommandExecutor { } catch (Exception e) { getLogger().info("Not using bStats (" + e.getClass().getName() + ")"); } + } // TODO api, untested diff --git a/src/main/java/eu/m724/giants/updater/PluginEnvironment.java b/src/main/java/eu/m724/giants/updater/PluginEnvironment.java new file mode 100644 index 0000000..ce22d9d --- /dev/null +++ b/src/main/java/eu/m724/giants/updater/PluginEnvironment.java @@ -0,0 +1,14 @@ +package eu.m724.giants.updater; + +import eu.m724.jarupdater.environment.ConstantEnvironment; +import org.bukkit.plugin.Plugin; + +import java.nio.file.Path; + +public class PluginEnvironment extends ConstantEnvironment { + public PluginEnvironment(Plugin plugin, String channel) { + super(plugin.getDescription().getVersion(), + channel, + Path.of(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().getPath())); + } +} \ No newline at end of file diff --git a/src/main/java/eu/m724/giants/updater/PluginUpdater.java b/src/main/java/eu/m724/giants/updater/PluginUpdater.java new file mode 100644 index 0000000..28aba62 --- /dev/null +++ b/src/main/java/eu/m724/giants/updater/PluginUpdater.java @@ -0,0 +1,33 @@ +package eu.m724.giants.updater; + +import eu.m724.jarupdater.Updater; +import eu.m724.jarupdater.download.Downloader; +import eu.m724.jarupdater.download.SimpleDownloader; +import eu.m724.jarupdater.environment.Environment; +import eu.m724.jarupdater.live.GiteaMetadataDAO; +import eu.m724.jarupdater.live.MetadataDAO; +import eu.m724.jarupdater.live.MetadataFacade; +import org.bukkit.plugin.Plugin; + +public class PluginUpdater extends Updater { + private final Plugin plugin; + + private PluginUpdater(Environment environment, MetadataFacade metadataProvider, Downloader downloader, Plugin plugin) { + super(environment, metadataProvider, downloader); + this.plugin = plugin; + } + + public static PluginUpdater build(Plugin plugin, String channel) { + Environment environment = new PluginEnvironment(plugin, channel); + MetadataDAO metadataDAO = new GiteaMetadataDAO("https://git.m724.eu/Minecon724/giants-metadata", "master"); + MetadataFacade metadataFacade = new MetadataFacade(environment, metadataDAO); + Downloader downloader = new SimpleDownloader("giants"); + + return new PluginUpdater(environment, metadataFacade, downloader, plugin); + } + + public void initNotifier() { + UpdateNotifier updateNotifier = new UpdateNotifier(plugin, this, (version) -> {}); + updateNotifier.register(); + } +} diff --git a/src/main/java/eu/m724/giants/updater/UpdateCommand.java b/src/main/java/eu/m724/giants/updater/UpdateCommand.java new file mode 100644 index 0000000..21cd9e1 --- /dev/null +++ b/src/main/java/eu/m724/giants/updater/UpdateCommand.java @@ -0,0 +1,88 @@ +package eu.m724.giants.updater; + +import eu.m724.jarupdater.Updater; +import eu.m724.jarupdater.object.Version; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.nio.file.NoSuchFileException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.CompletableFuture; + +/** + * not actually a command but deserves a separate file + */ +public class UpdateCommand { + private final Updater updater; + + public UpdateCommand(Updater updater) { + this.updater = updater; + } + + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + sender.sendMessage("Please wait..."); + sender.sendMessage("Channel: " + updater.getEnvironment().getChannel()); + CompletableFuture latestFuture = updater.getLatestVersion(); + + if (args.length == 1) { // remember this function is proxied + latestFuture.thenAccept(metadata -> { + if (metadata != null) { + sender.sendMessage("An update is available!"); + sender.sendMessage("Giants " + metadata.getLabel() + " released " + formatDate(metadata.getTimestamp())); + sender.sendMessage("To download: /giants update download"); + } else { + sender.sendMessage("No new updates"); + updater.getCurrentVersion().thenAccept(metadata2 -> { + sender.sendMessage("You're on Giants " + metadata2.getLabel() + " released " + formatDate(metadata2.getTimestamp())); + }).exceptionally(e -> { + sender.sendMessage("Error retrieving information about current version, see console for details. " + e.getMessage()); + e.printStackTrace(); + return null; + }); + } + }).exceptionally(e -> { + sender.sendMessage("Error checking for update. See console for details."); + e.printStackTrace(); + return null; + }); + } else { + String action = args[1]; // remember this function is proxied + + if (action.equals("download")) { + sender.sendMessage("Started download"); + + updater.downloadLatestVersion().thenAccept(file -> { + sender.sendMessage("Download finished, install with /giants update install"); + }).exceptionally(e -> { + sender.sendMessage("Download failed. See console for details."); + e.printStackTrace(); + return null; + }); + } else if (action.equals("install")) { + try { + updater.installLatestVersion().thenAccept(v -> { + sender.sendMessage("Installation completed, restart server to apply."); + }).exceptionally(e -> { + sender.sendMessage("Install failed, see console for details. " + e.getMessage()); + e.printStackTrace(); + return null; + }); + } catch (NoSuchFileException e) { + sender.sendMessage("First, download the update: /giants update download"); + } + } else { + return false; + } + } + + return true; + } + + private String formatDate(long timestamp) { // TODO move this + return LocalDate.ofEpochDay(timestamp / 86400).format(DateTimeFormatter.ofPattern("dd.MM.yyyy")); + } + +} diff --git a/src/main/java/eu/m724/giants/updater/UpdateNotifier.java b/src/main/java/eu/m724/giants/updater/UpdateNotifier.java new file mode 100644 index 0000000..bfd7c3d --- /dev/null +++ b/src/main/java/eu/m724/giants/updater/UpdateNotifier.java @@ -0,0 +1,66 @@ +package eu.m724.giants.updater; + +import eu.m724.jarupdater.Updater; +import eu.m724.jarupdater.object.Version; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.IOException; +import java.util.concurrent.CompletionException; +import java.util.function.Consumer; + +public class UpdateNotifier extends BukkitRunnable implements Listener { // TODO move this to jarupdater + private final Updater updater; + private final Consumer updateConsumer; + + private final Plugin plugin; + private Version latestVersion; + + public UpdateNotifier(Plugin plugin, Updater updater, Consumer updateConsumer) { + this.plugin = plugin; + this.updater = updater; + this.updateConsumer = updateConsumer; + } + + public void register() { + this.runTaskTimerAsynchronously(plugin, 0, 432000); // 6h + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public void run() { + try { + latestVersion = updater.getLatestVersion().join(); + } catch (CompletionException e) { + Throwable ex = e.getCause(); + + if (ex instanceof IOException) + plugin.getLogger().info("error trying to contact update server: " + ex.getMessage()); + else e.printStackTrace(); + } + + if (latestVersion == null) return; + plugin.getLogger().info("Giants are outdated. /giants update"); + + for (Player player : plugin.getServer().getOnlinePlayers()) { + if (player.hasPermission("giants.update.notify")) { + player.sendMessage("Giants are outdated. /giants update"); + } + } + + updateConsumer.accept(latestVersion); + + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + Player player = e.getPlayer(); + if (latestVersion != null && player.hasPermission("giants.update.notify")) { + player.sendMessage("Giants are outdated. /giants update"); + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 964dab4..baa67bd 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,6 +1,12 @@ # Notes: # To have no values in a list, remove every value below it and change to [] like `effects: []` +# Enable updater +# It still requires an admin to confirm update +updater: true + +### + # If disabled, the giant will not move or attack ai: true diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c7fdeca..35f8527 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -15,4 +15,14 @@ permissions: default: op giants.command.serialize: description: Permits /giants serialize - default: op \ No newline at end of file + default: op + giants.command.update: + description: Permits /giants update. Doesn't permit installing update, giants.update for that + default: op + + giants.update.downloading: + description: Permits DOWNLOADING the latest update of the Giants plugin. + default: op + giants.update.install: + description: Permits INSTALLING the latest update of the Giants plugin. + default: op