From 8068d1efc179e60e5b01a1733c392f5b3de21549 Mon Sep 17 00:00:00 2001 From: LMBishop <13875753+LMBishop@users.noreply.github.com> Date: Sun, 1 May 2022 18:48:21 +0100 Subject: Add time-limit option and quest expiry functionality (closes #379) --- .../bukkit/api/event/PlayerExpireQuestEvent.java | 51 +++++++++++++++++++ .../quests/bukkit/config/BukkitQuestsLoader.java | 6 ++- .../questcompleter/BukkitQuestCompleter.java | 57 ++++++++++++++++++---- .../questcontroller/NormalQuestController.java | 42 +++++++++++++--- .../bukkit/storage/MySqlStorageProvider.java | 4 +- .../quests/bukkit/util/Messages.java | 1 + .../src/main/resources/resources/bukkit/config.yml | 1 + 7 files changed, 144 insertions(+), 18 deletions(-) create mode 100644 bukkit/src/main/java/com/leonardobishop/quests/bukkit/api/event/PlayerExpireQuestEvent.java (limited to 'bukkit/src') diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/api/event/PlayerExpireQuestEvent.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/api/event/PlayerExpireQuestEvent.java new file mode 100644 index 00000000..3e7c87a3 --- /dev/null +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/api/event/PlayerExpireQuestEvent.java @@ -0,0 +1,51 @@ +package com.leonardobishop.quests.bukkit.api.event; + +import com.leonardobishop.quests.common.player.QPlayer; +import com.leonardobishop.quests.common.player.questprogressfile.QuestProgress; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class PlayerExpireQuestEvent extends PlayerQuestEvent { + private final static HandlerList handlers = new HandlerList(); + private final QuestProgress questProgress; + private String questExpireMessage; + + public PlayerExpireQuestEvent(@NotNull Player who, @NotNull QPlayer questPlayer, @NotNull QuestProgress questProgress, String questExpireMessage) { + super(who, questPlayer); + this.questProgress = questProgress; + this.questExpireMessage = questExpireMessage; + } + + /** + * @return The quest progress + */ + public QuestProgress getQuestProgress() { + return this.questProgress; + } + + /** + * @return The message sent to the player + */ + public String getQuestExpireMessage() { + return this.questExpireMessage; + } + + /** + * @param questExpireMessage The quest expire message + * @return The quest expire message set + */ + public String setQuestExpireMessage(String questExpireMessage) { + return (this.questExpireMessage = questExpireMessage); + } + + @NotNull + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java index 282b0d61..9291caee 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java @@ -223,11 +223,13 @@ public class BukkitQuestsLoader implements QuestsLoader { List startCommands = config.getStringList("startcommands"); boolean repeatable = config.getBoolean("options.repeatable", false); boolean cooldown = config.getBoolean("options.cooldown.enabled", false); + boolean timeLimit = config.getBoolean("options.time-limit.enabled", false); boolean permissionRequired = config.getBoolean("options.permission-required", false); boolean autostart = config.getBoolean("options.autostart", false); boolean cancellable = config.getBoolean("options.cancellable", true); boolean countsTowardsLimit = config.getBoolean("options.counts-towards-limit", true); int cooldownTime = config.getInt("options.cooldown.time", 10); + int timeLimtTime = config.getInt("options.time-limit.time", 10); int sortOrder = config.getInt("options.sort-order", 1); String category = config.getString("options.category"); Map placeholders = new HashMap<>(); @@ -250,12 +252,14 @@ public class BukkitQuestsLoader implements QuestsLoader { .withStartCommands(startCommands) .withPlaceholders(placeholders) .withCooldown(cooldownTime) + .withTimeLimit(timeLimtTime) .withSortOrder(sortOrder) .withCooldownEnabled(cooldown) + .withTimeLimitEnabled(timeLimit) .withPermissionRequired(permissionRequired) .withRepeatEnabled(repeatable) .withCancellable(cancellable) - .withCancellable(countsTowardsLimit) + .withCountsTowardsLimit(countsTowardsLimit) .withAutoStartEnabled(autostart) .inCategory(category) .build(); diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java index a981dc15..95c20f68 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java @@ -16,13 +16,17 @@ import org.jetbrains.annotations.NotNull; import java.util.LinkedList; import java.util.Objects; import java.util.Queue; +import java.util.UUID; +import java.util.stream.Collectors; //TODO move complete effects here ? public class BukkitQuestCompleter implements QuestCompleter, Runnable { private final Queue completionQueue = new LinkedList<>(); private final Queue fullCheckQueue = new LinkedList<>(); + private final Queue expiredCheckQueue = new LinkedList<>(); private final BukkitQuestsPlugin plugin; + private int expiredQuestsCheckCountdown; public BukkitQuestCompleter(BukkitQuestsPlugin plugin) { this.plugin = plugin; @@ -30,10 +34,47 @@ public class BukkitQuestCompleter implements QuestCompleter, Runnable { @Override public void run() { + this.processExpiredCheckQueue(); this.processCompletionQueue(); this.processFullCheckQueue(); } + private void checkExpiredQuests(QPlayer qPlayer) { + QuestProgressFile questProgressFile = qPlayer.getQuestProgressFile(); + for (QuestProgress questProgress : questProgressFile.getAllQuestProgress()) { + if (!questProgress.isStarted()) { + continue; + } + + Quest quest = plugin.getQuestManager().getQuestById(questProgress.getQuestId()); + if (quest == null) { + continue; + } + + if (questProgressFile.getTimeRemainingFor(quest) == 0) { + qPlayer.expireQuest(quest); + } + } + } + + private void processExpiredCheckQueue() { + UUID who = expiredCheckQueue.poll(); + if (who == null) { + for (Player player : Bukkit.getOnlinePlayers()) { + expiredCheckQueue.add(player.getUniqueId()); + } + return; + } + + Player player = Bukkit.getPlayer(who); + if (player == null || !player.isOnline()) return; + + QPlayer qPlayer = plugin.getPlayerManager().getPlayer(player.getUniqueId()); + if (qPlayer == null) return; + + checkExpiredQuests(qPlayer); + } + private void processCompletionQueue() { QuestProgress questProgress = completionQueue.poll(); if (questProgress == null) return; @@ -44,6 +85,9 @@ public class BukkitQuestCompleter implements QuestCompleter, Runnable { if (qPlayer == null) return; plugin.getQuestsLogger().debug("Processing player (singular: " + questProgress.getQuestId() + ") " + qPlayer.getPlayerUUID()); + + checkExpiredQuests(qPlayer); + Quest quest = plugin.getQuestManager().getQuestById(questProgress.getQuestId()); if (!qPlayer.hasStartedQuest(quest)) return; @@ -63,20 +107,15 @@ public class BukkitQuestCompleter implements QuestCompleter, Runnable { QPlayer qPlayer = plugin.getPlayerManager().getPlayer(player.getUniqueId()); if (qPlayer == null) return; plugin.getQuestsLogger().debug("Processing player (full check) " + qPlayer.getPlayerUUID()); + + checkExpiredQuests(qPlayer); + for (QuestProgress questProgress : questProgressFile.getAllQuestProgress()) { Quest quest = plugin.getQuestManager().getQuestById(questProgress.getQuestId()); if (quest == null) continue; if (!qPlayer.hasStartedQuest(quest)) continue; - boolean complete = true; - for (Task task : quest.getTasks()) { - TaskProgress taskProgress; - if ((taskProgress = questProgress.getTaskProgress(task.getId())) == null || !taskProgress.isCompleted()) { - complete = false; - break; - } - } - if (complete) { + if (checkComplete(quest, questProgress)) { qPlayer.completeQuest(quest); } } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcontroller/NormalQuestController.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcontroller/NormalQuestController.java index 3a8dbb5c..c5f4ef7a 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcontroller/NormalQuestController.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcontroller/NormalQuestController.java @@ -258,6 +258,15 @@ public class NormalQuestController implements QuestController { } } + private void resetQuest(QuestProgress questProgress) { + questProgress.setStarted(false); + questProgress.setStartedDate(System.currentTimeMillis()); + for (TaskProgress taskProgress : questProgress.getTaskProgress()) { + taskProgress.setCompleted(false); + taskProgress.setProgress(null); + } + } + @Override public boolean cancelQuestForPlayer(QPlayer qPlayer, Quest quest) { QuestProgress questProgress = qPlayer.getQuestProgressFile().getQuestProgress(quest); @@ -272,12 +281,7 @@ public class NormalQuestController implements QuestController { Messages.QUEST_CANCEL_NOTCANCELLABLE.send(player); return false; } - questProgress.setStarted(false); - questProgress.setStartedDate(System.currentTimeMillis()); - for (TaskProgress taskProgress : questProgress.getTaskProgress()) { - taskProgress.setCompleted(false); - taskProgress.setProgress(null); - } + resetQuest(questProgress); if (player != null) { QItemStack qItemStack = plugin.getQItemStackRegistry().getQuestItemStack(quest); String displayName = Chat.strip(qItemStack.getName()); @@ -297,6 +301,32 @@ public class NormalQuestController implements QuestController { return true; } + @Override + public boolean expireQuestForPlayer(QPlayer qPlayer, Quest quest) { + QuestProgress questProgress = qPlayer.getQuestProgressFile().getQuestProgress(quest); + Player player = Bukkit.getPlayer(qPlayer.getPlayerUUID()); + if (!questProgress.isStarted()) { + return false; + } + resetQuest(questProgress); + if (player != null) { + QItemStack qItemStack = plugin.getQItemStackRegistry().getQuestItemStack(quest); + String displayName = Chat.strip(qItemStack.getName()); + String questExpireMessage = Messages.QUEST_EXPIRE.getMessage().replace("{quest}", displayName); + // PlayerCancelQuestEvent -- start + PlayerExpireQuestEvent questCancelEvent = new PlayerExpireQuestEvent(player, qPlayer, questProgress, questExpireMessage); + Bukkit.getPluginManager().callEvent(questCancelEvent); + // PlayerCancelQuestEvent -- end + Messages.send(questCancelEvent.getQuestExpireMessage(), player); + } + if (config.getBoolean("options.allow-quest-track") + && config.getBoolean("options.quest-autotrack") + && quest.getId().equals(qPlayer.getPlayerPreferences().getTrackedQuestId())) { + trackNextQuest(qPlayer, null); + } + return true; + } + @Override public void trackQuestForPlayer(QPlayer qPlayer, Quest quest) { Player player = Bukkit.getPlayer(qPlayer.getPlayerUUID()); 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 45244374..640bbd98 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 @@ -44,7 +44,7 @@ public class MySqlStorageProvider implements StorageProvider { " `value` VARCHAR(255) NOT NULL," + " PRIMARY KEY (`key`));"; private static final String SELECT_PLAYER_QUEST_PROGRESS = - "SELECT quest_id, started, completed, completed_before, completion_date FROM `{prefix}quest_progress` WHERE uuid=?;"; + "SELECT quest_id, started, started_date, completed, completed_before, completion_date FROM `{prefix}quest_progress` WHERE uuid=?;"; private static final String SELECT_PLAYER_TASK_PROGRESS = "SELECT quest_id, task_id, completed, progress, data_type FROM `{prefix}task_progress` WHERE uuid=?;"; private static final String SELECT_UUID_LIST = @@ -54,7 +54,7 @@ public class MySqlStorageProvider implements StorageProvider { private static final String SELECT_KNOWN_PLAYER_TASK_PROGRESS = "SELECT quest_id, task_id FROM `{prefix}task_progress` WHERE uuid=?;"; private static final String WRITE_PLAYER_QUEST_PROGRESS = - "INSERT INTO `{prefix}quest_progress` (uuid, quest_id, started, started_date, completed, completed_before, completion_date) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE started=?, started_date=?, completed=?, completed_before=?, completion_date=?"; + "INSERT INTO `{prefix}quest_progress` (uuid, quest_id, started, started_date, completed, completed_before, completion_date) VALUES (?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE started=?, started_date=?, completed=?, completed_before=?, completion_date=?"; private static final String WRITE_PLAYER_TASK_PROGRESS = "INSERT INTO `{prefix}task_progress` (uuid, quest_id, task_id, completed, progress, data_type) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE completed=?, progress=?, data_type=?"; diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/Messages.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/Messages.java index c63a2f05..87dd1087 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/Messages.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/Messages.java @@ -19,6 +19,7 @@ public enum Messages { QUEST_START("messages.quest-start", "&7Quest &c{quest} &7started!"), QUEST_COMPLETE("messages.quest-complete", "&7Quest &c{quest} &completed!"), QUEST_CANCEL("messages.quest-cancel", "&7Quest &c{quest} &7cancelled!"), + QUEST_EXPIRE("messages.quest-expire", "&7Quest &c{quest} &7has expired."), QUEST_TRACK("messages.quest-track", "&7Tracking quest &c{quest}&7."), QUEST_TRACK_STOP("messages.quest-track-stop", "&7No longer tracking quest &c{quest}&7."), QUEST_RANDOM_NONE("messages.quest-random-none", "&cYou have no quests which you can start."), diff --git a/bukkit/src/main/resources/resources/bukkit/config.yml b/bukkit/src/main/resources/resources/bukkit/config.yml index 0e7192c6..472a0da1 100644 --- a/bukkit/src/main/resources/resources/bukkit/config.yml +++ b/bukkit/src/main/resources/resources/bukkit/config.yml @@ -311,6 +311,7 @@ messages: quest-start: "&7Quest &c{quest} &7started!" quest-complete: "&7Quest &c{quest} &7completed!" quest-cancel: "&7Quest &c{quest} &7cancelled!" + quest-expire: "&7Quest &c{quest} &7has expired." quest-track: "&7Tracking quest &c{quest}&7." quest-track-stop: "&7No longer tracking quest &c{quest}&7." quest-random-none: "&cYou have no quests which you can start." -- cgit v1.2.3-70-g09d2