From a835e7b48765f3b3fe1bc1c35adff0e867181e91 Mon Sep 17 00:00:00 2001 From: LMBishop <13875753+LMBishop@users.noreply.github.com> Date: Mon, 21 Jun 2021 01:02:06 +0100 Subject: Start BungeeCord synchronisation with plugin messaging channel - See #180 --- bukkit/build.gradle | 1 - .../quests/bukkit/BukkitQuestsPlugin.java | 34 +++- .../quests/bukkit/command/QuestsCommand.java | 2 +- .../quests/bukkit/listener/PlayerJoinListener.java | 41 +++-- .../bukkit/listener/PlayerLeaveListener.java | 4 +- .../bukkit/storage/MySqlStorageProvider.java | 11 +- .../quests/bukkit/storage/YamlStorageProvider.java | 9 +- .../src/main/resources/resources/bukkit/config.yml | 5 +- bungee/build.gradle | 23 +++ .../quests/bungee/BungeeQuestsPlugin.java | 26 +++ .../bungee/listener/PluginMessageListener.java | 69 ++++++++ .../quests/bungee/lock/DataLockManager.java | 67 ++++++++ .../quests/bungee/lock/QueuedServer.java | 21 +++ bungee/src/main/resources/bungee.yml | 8 + .../common/enums/PluginMessagingChannels.java | 7 + .../quests/common/player/QPlayerManager.java | 40 ++++- gradle/wrapper/gradle-wrapper.jar | Bin 58695 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 5 +- gradlew | 4 +- gradlew.bat | 189 ++++++++++----------- 20 files changed, 419 insertions(+), 147 deletions(-) create mode 100644 bungee/src/main/java/com/leonardobishop/quests/bungee/BungeeQuestsPlugin.java create mode 100644 bungee/src/main/java/com/leonardobishop/quests/bungee/listener/PluginMessageListener.java create mode 100644 bungee/src/main/java/com/leonardobishop/quests/bungee/lock/DataLockManager.java create mode 100644 bungee/src/main/java/com/leonardobishop/quests/bungee/lock/QueuedServer.java create mode 100644 bungee/src/main/resources/bungee.yml create mode 100644 common/src/main/java/com/leonardobishop/quests/common/enums/PluginMessagingChannels.java diff --git a/bukkit/build.gradle b/bukkit/build.gradle index f12ab459..9e041ee8 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -1,5 +1,4 @@ plugins { - id 'java' id 'com.github.johnrengelman.shadow' } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java index eeb359bc..5fce8a31 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java @@ -64,6 +64,7 @@ import com.leonardobishop.quests.bukkit.util.Messages; import com.leonardobishop.quests.common.config.ConfigProblem; import com.leonardobishop.quests.common.config.ConfigProblemDescriptions; import com.leonardobishop.quests.common.config.QuestsConfig; +import com.leonardobishop.quests.common.enums.PluginMessagingChannels; import com.leonardobishop.quests.common.logger.QuestsLogger; import com.leonardobishop.quests.common.player.QPlayerManager; import com.leonardobishop.quests.common.plugin.Quests; @@ -82,6 +83,7 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.plugin.messaging.PluginMessageListener; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; @@ -214,7 +216,7 @@ public class BukkitQuestsPlugin extends JavaPlugin implements Quests { MetricsLite metrics = new MetricsLite(this, 3443); if (metrics.isEnabled()) { - this.getQuestsLogger().info("Metrics started. This can be disabled at /plugins/bStats/config.yml."); + this.questsLogger.info("Metrics started. This can be disabled at /plugins/bStats/config.yml."); } if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { @@ -247,6 +249,31 @@ public class BukkitQuestsPlugin extends JavaPlugin implements Quests { super.getServer().getPluginManager().registerEvents(menuController, this); super.getServer().getPluginManager().registerEvents(new PlayerLeaveListener(this), this); + // TODO https://github.com/LMBishop/Quests/issues/180 +// this.getServer().getMessenger().registerOutgoingPluginChannel(this, PluginMessagingChannels.QUESTS_LOCKS_CHANNEL); +// this.getServer().getMessenger().registerIncomingPluginChannel(this, PluginMessagingChannels.QUESTS_LOCKS_CHANNEL, new PluginMessageListener() { +// @Override +// public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) { +// System.out.println("A PLUGIN MESSAGE HAS BEEN RECEIVED"); +// } +// }); +// +// this.questsLogger.warning("#########################################################"); +// this.questsLogger.warning("WARNING WARNING WARNING WARNING WARNING WARNING WARNING"); +// this.questsLogger.warning(""); +// this.questsLogger.warning("You have BungeeCord synchronisation enabled, however"); +// this.questsLogger.warning("Quests does not appear to be present on the proxy server."); +// this.questsLogger.warning(""); +// this.questsLogger.warning("Player data will not be loaded if the BungeeCord plugin"); +// this.questsLogger.warning("is missing!"); +// this.questsLogger.warning(""); +// this.questsLogger.warning("You must install Quests onto your BungeeCord server, in"); +// this.questsLogger.warning("addition to this installation, in order for synchronisation"); +// this.questsLogger.warning("to work!"); +// this.questsLogger.warning(""); +// this.questsLogger.warning("For more info: "); //TODO write wiki page +// this.questsLogger.warning("#########################################################"); + // register task types after the server has fully started Bukkit.getScheduler().runTask(this, () -> { taskTypeManager.registerTaskType(new MiningTaskType(this)); @@ -316,6 +343,11 @@ public class BukkitQuestsPlugin extends JavaPlugin implements Quests { }); } + @Override + public void onDisable() { + this.getServer().getMessenger().unregisterOutgoingPluginChannel(this); + } + @Override public void reloadQuests() { if (this.reloadBaseConfiguration()) { diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/QuestsCommand.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/QuestsCommand.java index 37a388fb..03a13ea1 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/QuestsCommand.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/QuestsCommand.java @@ -6,6 +6,7 @@ import com.leonardobishop.quests.bukkit.util.Messages; import com.leonardobishop.quests.common.config.ConfigProblem; import com.leonardobishop.quests.common.enums.QuestStartResult; import com.leonardobishop.quests.common.player.QPlayer; +import com.leonardobishop.quests.common.player.QPlayerManager; import com.leonardobishop.quests.common.player.questprogressfile.QuestProgressFile; import com.leonardobishop.quests.common.quest.Category; import com.leonardobishop.quests.common.quest.Quest; @@ -41,7 +42,6 @@ public class QuestsCommand implements TabExecutor { this.plugin = plugin; } - @SuppressWarnings("deprecation") @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { if (plugin.getTaskTypeManager().areRegistrationsAccepted()) { diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerJoinListener.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerJoinListener.java index 2fe15860..103c4fcb 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerJoinListener.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerJoinListener.java @@ -1,13 +1,15 @@ package com.leonardobishop.quests.bukkit.listener; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; import com.leonardobishop.quests.bukkit.BukkitQuestsPlugin; import com.leonardobishop.quests.bukkit.util.Messages; +import com.leonardobishop.quests.common.enums.PluginMessagingChannels; import com.leonardobishop.quests.common.player.QPlayer; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerJoinEvent; import java.util.UUID; @@ -20,15 +22,8 @@ public class PlayerJoinListener implements Listener { this.plugin = plugin; } - @EventHandler(priority = EventPriority.MONITOR) - public void onAsyncJoin(AsyncPlayerPreLoginEvent event) { - plugin.getPlayerManager().loadPlayer(event.getUniqueId()); - } - @EventHandler - public void onEvent(PlayerJoinEvent event) { - UUID playerUuid = event.getPlayer().getUniqueId(); - plugin.getPlayerManager().loadPlayer(playerUuid); + public void onJoin(PlayerJoinEvent event) { if (plugin.getDescription().getVersion().contains("beta") && event.getPlayer().hasPermission("quests.admin")) { event.getPlayer().sendMessage(Messages.BETA_REMINDER.getMessage()); } @@ -41,11 +36,29 @@ public class PlayerJoinListener implements Listener { Bukkit.getScheduler().runTaskLater(this.plugin, () -> event.getPlayer().sendMessage(updateMessage), 50L); } - QPlayer qPlayer = plugin.getPlayerManager().getPlayer(playerUuid); - if (qPlayer == null) return; + Player player = event.getPlayer(); + +// Bukkit.getScheduler().runTaskLater(plugin, () -> { +// if (!player.isOnline()) return; +// +// ByteArrayDataOutput out = ByteStreams.newDataOutput(); +// out.writeUTF("acquireLock"); +// out.writeUTF(player.getUniqueId().toString()); +// player.sendPluginMessage(plugin, PluginMessagingChannels.QUESTS_LOCKS_CHANNEL, out.toByteArray()); +// }, 20L); + + + plugin.getScheduler().doAsync(() -> { + plugin.getPlayerManager().loadPlayer(player.getUniqueId()); + + plugin.getScheduler().doSync(() -> { + QPlayer qPlayer = plugin.getPlayerManager().getPlayer(player.getUniqueId()); + if (qPlayer == null) return; - // run a full check to check for any missed quest completions - plugin.getQuestCompleter().queueFullCheck(qPlayer.getQuestProgressFile()); + // run a full check to check for any missed quest completions + plugin.getQuestCompleter().queueFullCheck(qPlayer.getQuestProgressFile()); + }); + }); } } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerLeaveListener.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerLeaveListener.java index 1f41344a..db8bb698 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerLeaveListener.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/listener/PlayerLeaveListener.java @@ -16,9 +16,7 @@ public class PlayerLeaveListener implements Listener { @EventHandler public void onEvent(PlayerQuitEvent event) { - QPlayer qPlayer = plugin.getPlayerManager().getPlayer(event.getPlayer().getUniqueId()); - if (qPlayer == null) return; - plugin.getPlayerManager().removePlayer(qPlayer.getPlayerUUID()); + plugin.getPlayerManager().removePlayer(event.getPlayer().getUniqueId()); } } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/MySqlStorageProvider.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/MySqlStorageProvider.java index fd473af6..5482c63a 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/MySqlStorageProvider.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/MySqlStorageProvider.java @@ -126,7 +126,7 @@ public class MySqlStorageProvider implements StorageProvider { @Override public QuestProgressFile loadProgressFile(UUID uuid) { - if (fault) return null; + if (fault) throw new RuntimeException("storage provider encountered a fault during initialization and cannot be used"); QuestProgressFile questProgressFile = new QuestProgressFile(uuid, plugin); try (Connection connection = hikari.getConnection()) { plugin.getQuestsLogger().debug("Querying player " + uuid); @@ -197,16 +197,14 @@ public class MySqlStorageProvider implements StorageProvider { questProgressFile.addQuestProgress(questProgress); } } catch (SQLException e) { - plugin.getQuestsLogger().severe("Failed to load player: " + uuid + "!"); - e.printStackTrace(); - return null; + throw new RuntimeException(e); } return questProgressFile; } @Override public void saveProgressFile(UUID uuid, QuestProgressFile questProgressFile) { - if (fault) return; + if (fault) throw new RuntimeException("storage provider encountered a fault during initialization and cannot be used"); try (Connection connection = hikari.getConnection()) { try (PreparedStatement writeQuestProgress = connection.prepareStatement(this.statementProcessor.apply(WRITE_PLAYER_QUEST_PROGRESS)); PreparedStatement writeTaskProgress = connection.prepareStatement(this.statementProcessor.apply(WRITE_PLAYER_TASK_PROGRESS))) { @@ -269,8 +267,7 @@ public class MySqlStorageProvider implements StorageProvider { writeTaskProgress.executeBatch(); } } catch (SQLException e) { - plugin.getQuestsLogger().severe("Failed to save player: " + uuid + "!"); - e.printStackTrace(); + throw new RuntimeException(e); } } } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/YamlStorageProvider.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/YamlStorageProvider.java index 75e271f9..0a272abc 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/YamlStorageProvider.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/storage/YamlStorageProvider.java @@ -79,10 +79,6 @@ public class YamlStorageProvider implements StorageProvider { plugin.getQuestsLogger().debug("Player " + uuid + " does not have a quest progress file."); } } - } catch (Exception ex) { - plugin.getQuestsLogger().severe("Failed to load player: " + uuid + "! This WILL cause errors."); - ex.printStackTrace(); - // fuck } finally { lock.unlock(); } @@ -104,7 +100,7 @@ public class YamlStorageProvider implements StorageProvider { try { file.createNewFile(); } catch (IOException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } @@ -128,8 +124,7 @@ public class YamlStorageProvider implements StorageProvider { data.save(file); plugin.getQuestsLogger().debug("Write of player " + uuid + " to disk complete."); } catch (IOException e) { - plugin.getQuestsLogger().debug("Failed to write player: " + uuid + "!."); - e.printStackTrace(); + throw new RuntimeException(e); } } finally { lock.unlock(); diff --git a/bukkit/src/main/resources/resources/bukkit/config.yml b/bukkit/src/main/resources/resources/bukkit/config.yml index f7084505..7e007ba2 100644 --- a/bukkit/src/main/resources/resources/bukkit/config.yml +++ b/bukkit/src/main/resources/resources/bukkit/config.yml @@ -237,8 +237,11 @@ options: # Storage options - please see the following: https://github.com/LMBishop/Quests/wiki/Storage-Providers storage: # Either 'yaml' (flatfile) or 'mysql' (network) - # Please read the following before using MySQL https://github.com/LMBishop/Quests/wiki/Storage-Providers#network + # You must read the following before using MySQL https://github.com/LMBishop/Quests/wiki/Storage-Providers#network provider: "yaml" + # Please see the following wiki page before changing these options: + synchronisation: + bungeecord: false # The following is only applicable for database storage providers (e.g. mysql) database-settings: network: diff --git a/bungee/build.gradle b/bungee/build.gradle index e69de29b..ebad07e7 100644 --- a/bungee/build.gradle +++ b/bungee/build.gradle @@ -0,0 +1,23 @@ +processResources { + duplicatesStrategy = 'include' + from(sourceSets.main.resources.srcDirs) { + include 'bungee.yml' + expand('version': project.version) + } +} + +repositories { + // BungeeCord + maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } + + mavenCentral() +} + +dependencies { + compileOnly project(':common') + + // BungeeCord + compileOnly ('net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT') + + compileOnly fileTree(dir: 'libs', includes: ['*.jar']) +} \ No newline at end of file diff --git a/bungee/src/main/java/com/leonardobishop/quests/bungee/BungeeQuestsPlugin.java b/bungee/src/main/java/com/leonardobishop/quests/bungee/BungeeQuestsPlugin.java new file mode 100644 index 00000000..b6769f2c --- /dev/null +++ b/bungee/src/main/java/com/leonardobishop/quests/bungee/BungeeQuestsPlugin.java @@ -0,0 +1,26 @@ +package com.leonardobishop.quests.bungee; + +import com.leonardobishop.quests.bungee.listener.PluginMessageListener; +import com.leonardobishop.quests.bungee.lock.DataLockManager; +import com.leonardobishop.quests.common.enums.PluginMessagingChannels; +import net.md_5.bungee.api.plugin.Plugin; + +public class BungeeQuestsPlugin extends Plugin { + + private DataLockManager dataLockManager; + + @Override + public void onEnable() { + this.dataLockManager = new DataLockManager(); + + //TODO: https://github.com/LMBishop/Quests/issues/180 + +// super.getProxy().registerChannel(PluginMessagingChannels.QUESTS_LOCKS_CHANNEL); +// super.getProxy().getPluginManager().registerListener(this, new PluginMessageListener(this)); + } + + public DataLockManager getDataLockManager() { + return dataLockManager; + } + +} diff --git a/bungee/src/main/java/com/leonardobishop/quests/bungee/listener/PluginMessageListener.java b/bungee/src/main/java/com/leonardobishop/quests/bungee/listener/PluginMessageListener.java new file mode 100644 index 00000000..e54d094c --- /dev/null +++ b/bungee/src/main/java/com/leonardobishop/quests/bungee/listener/PluginMessageListener.java @@ -0,0 +1,69 @@ +package com.leonardobishop.quests.bungee.listener; + +import com.leonardobishop.quests.bungee.BungeeQuestsPlugin; +import com.leonardobishop.quests.common.enums.PluginMessagingChannels; +import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.connection.Server; +import net.md_5.bungee.api.event.PluginMessageEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.event.EventHandler; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.UUID; + +public class PluginMessageListener implements Listener { + + private final BungeeQuestsPlugin plugin; + + public PluginMessageListener(BungeeQuestsPlugin plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPluginMessage(PluginMessageEvent e) { + if (!e.getTag().equals(PluginMessagingChannels.QUESTS_LOCKS_CHANNEL)) { + return; + } + e.setCancelled(true); + if (!(e.getSender() instanceof Server) || !(e.getReceiver() instanceof ProxiedPlayer)) { + return; + } + Server sender = (Server) e.getSender(); + + ByteArrayInputStream stream = new ByteArrayInputStream(e.getData()); + DataInputStream in = new DataInputStream(stream); + try { + String request = in.readUTF(); + UUID uuid = UUID.fromString(in.readUTF()); + + if (request.equals("acquireLock")) { + plugin.getDataLockManager().acquireLock(sender.getInfo().getName(), uuid, + () -> sendMessage(sender.getInfo().getName(), "lockAcquired", uuid)); + } + } catch (Exception ex) { + plugin.getLogger().warning("Could not parse plugin message:"); + ex.printStackTrace(); + } + } + + public void sendMessage(String server, String request, UUID who) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(stream); + try { + out.writeUTF(request); + out.writeUTF(who.toString()); + } catch (IOException ex) { + plugin.getLogger().warning("Could not write plugin message:"); + ex.printStackTrace(); + } + + ServerInfo serverInfo = plugin.getProxy().getServerInfo(server); + if (serverInfo != null) serverInfo.sendData(PluginMessagingChannels.QUESTS_LOCKS_CHANNEL, stream.toByteArray()); + } + +} diff --git a/bungee/src/main/java/com/leonardobishop/quests/bungee/lock/DataLockManager.java b/bungee/src/main/java/com/leonardobishop/quests/bungee/lock/DataLockManager.java new file mode 100644 index 00000000..ed80fd94 --- /dev/null +++ b/bungee/src/main/java/com/leonardobishop/quests/bungee/lock/DataLockManager.java @@ -0,0 +1,67 @@ +package com.leonardobishop.quests.bungee.lock; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +//TODO https://github.com/LMBishop/Quests/issues/180 +public class DataLockManager { + + private final Map locks = new HashMap<>(); + private final Map> queue = new HashMap<>(); + + public synchronized boolean hasLock(String server, UUID who) { + String lockedServer = locks.get(who); + if (lockedServer == null) { + return false; + } else { + return lockedServer.equals(server); + } + } + + public synchronized void acquireLock(String server, UUID who, Runnable callback) { + String lockedServer = locks.get(who); + if (lockedServer == null) { + locks.put(who, server); + callback.run(); + } else if (lockedServer.equals(server)) { + callback.run(); + } + CompletableFuture future = new CompletableFuture<>(); + QueuedServer queuedServer = new QueuedServer(callback, server); + queue.compute(who, (uuid, list) -> { + if (list == null) { + LinkedList newList = new LinkedList<>(); + newList.add(queuedServer); + return newList; + } else { + list.add(queuedServer); + } + return list; + }); + } + + public synchronized void releaseLock(String server, UUID who) { + String lockedServer = locks.get(who); + if (lockedServer == null || lockedServer.equals(server)) { + LinkedList queuedServers = queue.get(who); + QueuedServer nextServer = queuedServers.poll(); + if (nextServer != null) { + locks.put(who, nextServer.getServer()); + nextServer.getCallback().run(); + } else { + locks.remove(who); + } + } else { + LinkedList queuedServers = queue.get(who); + QueuedServer queuedServer = null; + for (QueuedServer qs : queuedServers) { + if (qs.getServer().equals(server)) queuedServer = qs; + } + if (queuedServer != null) queuedServers.remove(queuedServer); + } + } + +} diff --git a/bungee/src/main/java/com/leonardobishop/quests/bungee/lock/QueuedServer.java b/bungee/src/main/java/com/leonardobishop/quests/bungee/lock/QueuedServer.java new file mode 100644 index 00000000..90a68987 --- /dev/null +++ b/bungee/src/main/java/com/leonardobishop/quests/bungee/lock/QueuedServer.java @@ -0,0 +1,21 @@ +package com.leonardobishop.quests.bungee.lock; + +public class QueuedServer { + + private Runnable callback; + private String server; + + public QueuedServer(Runnable callback, String server) { + this.callback = callback; + this.server = server; + } + + public Runnable getCallback() { + return callback; + } + + public String getServer() { + return server; + } + +} diff --git a/bungee/src/main/resources/bungee.yml b/bungee/src/main/resources/bungee.yml new file mode 100644 index 00000000..02411cc2 --- /dev/null +++ b/bungee/src/main/resources/bungee.yml @@ -0,0 +1,8 @@ +name: Quests + +# This will be replaced with the property "version" in build.gradle +version: ${version} + +main: com.leonardobishop.quests.bungee.BungeeQuestsPlugin +website: https://github.com/LMBishop/Quests +author: "LMBishop & contributors" \ No newline at end of file diff --git a/common/src/main/java/com/leonardobishop/quests/common/enums/PluginMessagingChannels.java b/common/src/main/java/com/leonardobishop/quests/common/enums/PluginMessagingChannels.java new file mode 100644 index 00000000..99622900 --- /dev/null +++ b/common/src/main/java/com/leonardobishop/quests/common/enums/PluginMessagingChannels.java @@ -0,0 +1,7 @@ +package com.leonardobishop.quests.common.enums; + +public class PluginMessagingChannels { + + public static final String QUESTS_LOCKS_CHANNEL = "quests:locks"; + +} diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java index 28a46ae1..43b6fa20 100644 --- a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java +++ b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java @@ -49,7 +49,7 @@ public class QPlayerManager { public void removePlayer(UUID uuid) { plugin.getQuestsLogger().debug("Unloading and saving player " + uuid + "."); qPlayers.computeIfPresent(uuid, (mapUUID, qPlayer) -> { - savePlayer(uuid); + savePlayer(uuid, qPlayer.getQuestProgressFile()); return null; }); } @@ -104,7 +104,12 @@ public class QPlayerManager { private void save(UUID uuid, QuestProgressFile questProgressFile) { plugin.getQuestsLogger().debug("Saving player " + uuid + "."); - storageProvider.saveProgressFile(uuid, questProgressFile); + try { + storageProvider.saveProgressFile(uuid, questProgressFile); + } catch (Exception e) { + plugin.getQuestsLogger().debug("Failed to save player: " + uuid + "!"); + e.printStackTrace(); + } } /** @@ -126,14 +131,22 @@ public class QPlayerManager { * This will have no effect if player is already loaded. Can be invoked asynchronously. * * @param uuid the uuid of the player + * @return {@link LoadResult} - if the player was successfully loaded */ - public void loadPlayer(UUID uuid) { + public LoadResult loadPlayer(UUID uuid) { plugin.getQuestsLogger().debug("Loading player " + uuid + "."); - qPlayers.computeIfAbsent(uuid, s -> { - QuestProgressFile questProgressFile = storageProvider.loadProgressFile(uuid); - if (questProgressFile == null) return null; - return new QPlayer(plugin, uuid, new QPlayerPreferences(null), questProgressFile, activeQuestController); - }); + try { + QPlayer qPlayer = qPlayers.computeIfAbsent(uuid, s -> { + QuestProgressFile questProgressFile = storageProvider.loadProgressFile(uuid); + if (questProgressFile == null) return null; + return new QPlayer(plugin, uuid, new QPlayerPreferences(null), questProgressFile, activeQuestController); + }); + return (qPlayer != null) ? LoadResult.LOADED : LoadResult.UNAVAILABLE; + } catch (Exception e) { + plugin.getQuestsLogger().severe("Failed to load player: " + uuid + "!"); + e.printStackTrace(); + } + return LoadResult.FAILED; } /** @@ -155,4 +168,15 @@ public class QPlayerManager { qPlayer.setQuestController(activeQuestController); } } + + public enum LoadResult { + + /** A successful load into the QPlayerManager */ + LOADED, + /** An unsuccessful load, however not due to an error (e.g deferred) */ + UNAVAILABLE, + /** An unsuccessful load */ + FAILED; + + } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f3d88b1c..7454180f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 42ab3796..69a97150 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sat May 16 22:29:02 CST 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 2fe81a7d..744e882e 100755 --- a/gradlew +++ b/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 9618d8d9..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,100 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega -- cgit v1.2.3-70-g09d2