From 9a2cb349385a4a6646d35b5dda3d529b3454f1ec Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sun, 24 Nov 2024 14:32:00 +0000 Subject: [PATCH 01/20] setup new features --- .../configuration/JsonQuestHistory.java | 31 ---- .../configuration/JsonQuestSave.java | 38 +++-- .../configuration/QuestHistoryManager.java | 151 ++++++++++++++++++ .../configuration/QuestLibrary.java | 7 +- .../configuration/QuestModel.java | 2 +- .../ServerQuests/objectives/Objective.java | 10 +- .../rewards/RankedRewards.java | 1 + .../questcomponents/rewards/RewardEntry.java | 1 + .../rewards/RewardJoinListener.java | 35 ++++ .../rewards/RewardMessage.java | 2 + .../rewards/{ => types}/CommandReward.java | 2 +- .../rewards/{ => types}/ExperienceReward.java | 0 .../rewards/{ => types}/ItemReward.java | 2 +- .../rewards/{ => types}/MoneyReward.java | 0 .../rewards/{ => types}/Reward.java | 2 +- 15 files changed, 231 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestHistory.java create mode 100644 src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java create mode 100644 src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardJoinListener.java rename src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/{ => types}/CommandReward.java (93%) rename src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/{ => types}/ExperienceReward.java (100%) rename src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/{ => types}/ItemReward.java (98%) rename src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/{ => types}/MoneyReward.java (100%) rename src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/{ => types}/Reward.java (77%) diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestHistory.java b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestHistory.java deleted file mode 100644 index 696b7c4..0000000 --- a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestHistory.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.wonka01.ServerQuests.configuration; - -import java.io.File; -import java.io.IOException; - -import org.bukkit.Bukkit; - -import me.wonka01.ServerQuests.ServerQuests; - -public class JsonQuestHistory { - private final ServerQuests plugin; - private final File path; - - public JsonQuestHistory(ServerQuests plugin, File path) { - this.plugin = plugin; - this.path = new File(path + "/questSave.json"); - } - - public boolean getOrCreateQuestFile() { - if (path.exists()) { - return true; - } else { - try { - path.createNewFile(); - } catch (IOException e) { - Bukkit.getServer().getConsoleSender().sendMessage(e.getMessage()); - } - } - return false; - } -} diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java index aed542e..83f81a1 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java @@ -22,12 +22,14 @@ import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.UUID; +import java.util.stream.Collectors; public class JsonQuestSave { @@ -85,10 +87,14 @@ public void saveQuestsInProgress() { } } - private List convertJsonArrayToList(JSONArray arr) { - List list = new ArrayList<>(); + // public List fromArrayToList(T[] a) { + // return Arrays.stream(a).collect(Collectors.toList()); + // } + + private List convertJsonArrayToList(JSONArray arr, Class clazz) { + List list = new ArrayList<>(); for (Object o : arr) { - list.add((String) o); + list.add(clazz.cast(o)); } return list; } @@ -122,19 +128,23 @@ public void readAndInitializeQuests() { JSONArray mobNames = (JSONArray) obj.get("mobNames"); JSONArray materials = (JSONArray) obj.get("materials"); JSONArray customNames = (JSONArray) obj.get("customMobNames"); - List materialList = convertJsonArrayToList(materials).stream().map(materialName -> { - String capitalizedMaterialName = materialName.toUpperCase().replaceAll(" ", "_"); - Material material = Material.getMaterial(capitalizedMaterialName); - if (material == null) { - return Material.AIR; - } - return material; - }).collect(java.util.stream.Collectors.toList()); + JSONArray customModelIds = (JSONArray) obj.get("customModelIds"); + List materialList = convertJsonArrayToList(materials, String.class).stream() + .map(materialName -> { + String capitalizedMaterialName = materialName.toUpperCase().replaceAll(" ", "_"); + Material material = Material.getMaterial(capitalizedMaterialName); + if (material == null) { + return Material.AIR; + } + return material; + }).collect(java.util.stream.Collectors.toList()); ObjectiveType objectiveType = ObjectiveType.match(type); - Objective objective = new Objective(objectiveType, goal, amount, convertJsonArrayToList(mobNames), - materialList, (String) obj.get("description"), convertJsonArrayToList(customNames), - dynamicGoal); + Objective objective = new Objective(objectiveType, goal, amount, + convertJsonArrayToList(mobNames, String.class), + materialList, (String) obj.get("description"), + convertJsonArrayToList(customNames, String.class), + dynamicGoal, convertJsonArrayToList(customModelIds, Integer.class)); objectives.add(objective); } long questDuration = (Long) questObject.getOrDefault("timeLeft", 0); diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java new file mode 100644 index 0000000..422155d --- /dev/null +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java @@ -0,0 +1,151 @@ +package me.wonka01.ServerQuests.configuration; + +import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.questcomponents.players.PlayerData; +import org.bukkit.Bukkit; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; +import java.util.logging.Logger; + +public class QuestHistoryManager { + private final File historyFile; + private final Logger logger; + private static final int MAX_HISTORY_ENTRIES = 50; // Limit how many completed quests to store + + public QuestHistoryManager(ServerQuests plugin, File dataFolder) { + this.historyFile = new File(dataFolder, "questHistory.json"); + this.logger = plugin.getLogger(); + createHistoryFileIfNotExists(); + } + + private void createHistoryFileIfNotExists() { + if (!historyFile.exists()) { + try { + historyFile.createNewFile(); + // Initialize with empty array + saveToFile(new JSONArray()); + } catch (IOException e) { + logger.warning("Failed to create quest history file: " + e.getMessage()); + } + } + } + + public void saveCompletedQuest(String questId, String questName, Map playerData, + boolean wasCompetitive) { + JSONArray historyArray = loadHistoryArray(); + + // Create new entry for this quest + JSONObject questEntry = new JSONObject(); + questEntry.put("questId", questId); + questEntry.put("questName", questName); + questEntry.put("completionTime", System.currentTimeMillis()); + questEntry.put("wasCompetitive", wasCompetitive); + + // Save top contributors + JSONArray topPlayers = new JSONArray(); + playerData.entrySet().stream() + .sorted((e1, e2) -> { + double total1 = e1.getValue().getAmountContributed(); + double total2 = e2.getValue().getAmountContributed(); + return Double.compare(total2, total1); // Sort descending + }) + .limit(10) // Store only top 10 players + .forEach(entry -> { + JSONObject playerInfo = new JSONObject(); + playerInfo.put("uuid", entry.getKey().toString()); + playerInfo.put("name", entry.getValue().getName()); + playerInfo.put("contribution", entry.getValue().getAmountContributed()); + topPlayers.add(playerInfo); + }); + + questEntry.put("topContributors", topPlayers); + + // Add to history and maintain size limit + historyArray.add(0, questEntry); // Add to start of array + while (historyArray.size() > MAX_HISTORY_ENTRIES) { + historyArray.remove(historyArray.size() - 1); + } + + saveToFile(historyArray); + } + + public List> getPlayerQuestHistory(UUID playerId) { + List> playerHistory = new ArrayList<>(); + JSONArray historyArray = loadHistoryArray(); + + for (Object entry : historyArray) { + JSONObject questEntry = (JSONObject) entry; + JSONArray topContributors = (JSONArray) questEntry.get("topContributors"); + + // Check if player was in top contributors + for (Object contributor : topContributors) { + JSONObject playerInfo = (JSONObject) contributor; + if (playerInfo.get("uuid").equals(playerId.toString())) { + Map historyEntry = new HashMap<>(); + historyEntry.put("questId", questEntry.get("questId")); + historyEntry.put("questName", questEntry.get("questName")); + historyEntry.put("completionTime", questEntry.get("completionTime")); + historyEntry.put("contribution", playerInfo.get("contribution")); + historyEntry.put("wasCompetitive", questEntry.get("wasCompetitive")); + playerHistory.add(historyEntry); + break; + } + } + } + + return playerHistory; + } + + public List> getRecentQuests(int limit) { + List> recentQuests = new ArrayList<>(); + JSONArray historyArray = loadHistoryArray(); + + int count = 0; + for (Object entry : historyArray) { + if (count >= limit) + break; + + JSONObject questEntry = (JSONObject) entry; + Map questInfo = new HashMap<>(); + questInfo.put("questId", questEntry.get("questId")); + questInfo.put("questName", questEntry.get("questName")); + questInfo.put("completionTime", questEntry.get("completionTime")); + questInfo.put("wasCompetitive", questEntry.get("wasCompetitive")); + questInfo.put("topContributors", questEntry.get("topContributors")); + + recentQuests.add(questInfo); + count++; + } + + return recentQuests; + } + + private JSONArray loadHistoryArray() { + if (!historyFile.exists()) { + return new JSONArray(); + } + + try (FileReader reader = new FileReader(historyFile)) { + JSONParser parser = new JSONParser(); + return (JSONArray) parser.parse(reader); + } catch (Exception e) { + logger.warning("Failed to load quest history: " + e.getMessage()); + return new JSONArray(); + } + } + + private void saveToFile(JSONArray historyArray) { + try (FileWriter writer = new FileWriter(historyFile)) { + writer.write(historyArray.toJSONString()); + } catch (IOException e) { + logger.warning("Failed to save quest history: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index afc9f72..3e8900f 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -99,6 +99,8 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { List objectiveMobs = (List) obj.get("entities"); List objectiveMaterials = (List) obj.get("materials"); List objectiveCustomNames = (List) obj.get("customMobNames"); + List objectiveModelIds = (List) obj.get("modelIds"); + ObjectiveType objectiveTypeEnum = ObjectiveType.match(objectiveType); List mats = new ArrayList<>(); if (objectiveMaterials != null) { @@ -120,9 +122,12 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { if (objectiveCustomNames == null) { objectiveCustomNames = new ArrayList<>(); } + if (objectiveModelIds == null) { + objectiveModelIds = new ArrayList<>(); + } Objective objective = new Objective(objectiveTypeEnum, objectiveGoal, 0.0, objectiveMobs, - mats, objDescription, objectiveCustomNames, dynamicGoal); + mats, objDescription, objectiveCustomNames, dynamicGoal, objectiveModelIds); objectives.add(objective); } } diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java index 2da11ba..eb6848d 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java @@ -71,7 +71,7 @@ public QuestModel(String questId, String displayName, String eventDescription, } else { this.objectives = Arrays .asList(new Objective(objective, questGoal * 1.0, 0, mobNames, materials, objective.getString(), - customNames, "")); + customNames, "", new ArrayList<>())); } this.mobNames = mobNames; this.rewards = rewards; diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java b/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java index 9084abb..4086e27 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java @@ -3,7 +3,6 @@ import java.util.List; import org.bukkit.Material; -import org.checkerframework.checker.units.qual.t; import org.json.simple.JSONObject; import com.google.gson.Gson; @@ -22,11 +21,13 @@ public class Objective implements Cloneable { private List mobNames; private List materials; private List customNames; + private List customModelIds; private String description; private String dynamicGoal; public Objective(ObjectiveType type, double goal, double amountComplete, List mobNames, - List materials, String description, List customNames, String dynamicGoal) { + List materials, String description, List customNames, String dynamicGoal, + List customModelIds) { this.type = type; this.goal = goal; this.amountComplete = amountComplete; @@ -35,6 +36,7 @@ public Objective(ObjectiveType type, double goal, double amountComplete, List Date: Sun, 24 Nov 2024 14:34:23 +0000 Subject: [PATCH 02/20] cleanup --- .../configuration/QuestHistoryManager.java | 11 ++--------- .../questcomponents/rewards/RewardManager.java | 6 ++++++ .../rewards/types/ExperienceReward.java | 5 ++--- .../questcomponents/rewards/types/MoneyReward.java | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java index 422155d..9d1490b 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java @@ -2,7 +2,6 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.players.PlayerData; -import org.bukkit.Bukkit; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -17,7 +16,7 @@ public class QuestHistoryManager { private final File historyFile; private final Logger logger; - private static final int MAX_HISTORY_ENTRIES = 50; // Limit how many completed quests to store + private static final int MAX_HISTORY_ENTRIES = 50; public QuestHistoryManager(ServerQuests plugin, File dataFolder) { this.historyFile = new File(dataFolder, "questHistory.json"); @@ -29,7 +28,6 @@ private void createHistoryFileIfNotExists() { if (!historyFile.exists()) { try { historyFile.createNewFile(); - // Initialize with empty array saveToFile(new JSONArray()); } catch (IOException e) { logger.warning("Failed to create quest history file: " + e.getMessage()); @@ -37,8 +35,7 @@ private void createHistoryFileIfNotExists() { } } - public void saveCompletedQuest(String questId, String questName, Map playerData, - boolean wasCompetitive) { + public void saveCompletedQuest(String questId, String questName, Map playerData) { JSONArray historyArray = loadHistoryArray(); // Create new entry for this quest @@ -46,7 +43,6 @@ public void saveCompletedQuest(String questId, String questName, Map> getPlayerQuestHistory(UUID playerId) { JSONObject questEntry = (JSONObject) entry; JSONArray topContributors = (JSONArray) questEntry.get("topContributors"); - // Check if player was in top contributors for (Object contributor : topContributors) { JSONObject playerInfo = (JSONObject) contributor; if (playerInfo.get("uuid").equals(playerId.toString())) { @@ -93,7 +88,6 @@ public List> getPlayerQuestHistory(UUID playerId) { historyEntry.put("questName", questEntry.get("questName")); historyEntry.put("completionTime", questEntry.get("completionTime")); historyEntry.put("contribution", playerInfo.get("contribution")); - historyEntry.put("wasCompetitive", questEntry.get("wasCompetitive")); playerHistory.add(historyEntry); break; } @@ -117,7 +111,6 @@ public List> getRecentQuests(int limit) { questInfo.put("questId", questEntry.get("questId")); questInfo.put("questName", questEntry.get("questName")); questInfo.put("completionTime", questEntry.get("completionTime")); - questInfo.put("wasCompetitive", questEntry.get("wasCompetitive")); questInfo.put("topContributors", questEntry.get("topContributors")); recentQuests.add(questInfo); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardManager.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardManager.java index dca7e43..8d862ef 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardManager.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardManager.java @@ -17,6 +17,12 @@ import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import me.wonka01.ServerQuests.questcomponents.rewards.types.CommandReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.ExperienceReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.ItemReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.MoneyReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; + public class RewardManager { private static RewardManager instance; private HashMap> playerRewards = new HashMap<>(); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java index 7fba2d9..dd5a0ae 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java @@ -1,15 +1,14 @@ -package me.wonka01.ServerQuests.questcomponents.rewards; +package me.wonka01.ServerQuests.questcomponents.rewards.types; import lombok.Getter; import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; + import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.json.simple.JSONObject; -import java.text.MessageFormat; - public class ExperienceReward implements Reward, Colorization { @Getter diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java index dbb2565..92bcd07 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java @@ -1,4 +1,4 @@ -package me.wonka01.ServerQuests.questcomponents.rewards; +package me.wonka01.ServerQuests.questcomponents.rewards.types; import lombok.Getter; import me.knighthat.apis.utils.Colorization; From a086a149601bf28194ee83afd87b6d5ad32c9c57 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sun, 24 Nov 2024 14:34:47 +0000 Subject: [PATCH 03/20] imports --- .../me/wonka01/ServerQuests/configuration/QuestLibrary.java | 5 +++++ .../me/wonka01/ServerQuests/configuration/QuestModel.java | 2 +- .../questcomponents/players/BasePlayerComponent.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index 3e8900f..90c735f 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -4,6 +4,11 @@ import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; import me.wonka01.ServerQuests.questcomponents.rewards.*; +import me.wonka01.ServerQuests.questcomponents.rewards.types.CommandReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.ExperienceReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.ItemReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.MoneyReward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; import org.bukkit.Bukkit; import org.bukkit.Material; diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java index eb6848d..da858c4 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java @@ -4,7 +4,7 @@ import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; -import me.wonka01.ServerQuests.questcomponents.rewards.Reward; +import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; import me.wonka01.ServerQuests.questcomponents.schedulers.ParseDurationString; import org.bukkit.Material; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java index f624fdc..9fed98a 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java @@ -3,8 +3,8 @@ import me.knighthat.apis.utils.Colorization; import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; -import me.wonka01.ServerQuests.questcomponents.rewards.Reward; import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; +import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; From c79ffcda0dafb8f049da45264cb55519b0842be2 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Thu, 28 Nov 2024 16:19:59 +0000 Subject: [PATCH 04/20] ad history menu, new quests and stuff --- README.md | 10 ++- pom.xml | 2 +- .../java/me/knighthat/apis/menus/Menu.java | 13 ++-- .../me/wonka01/ServerQuests/ServerQuests.java | 5 ++ .../ServerQuests/commands/CommandManager.java | 19 +++++- .../ServerQuests/commands/HistoryCommand.java | 33 ++++++++++ .../ServerQuests/commands/PluginCommand.java | 6 +- .../ServerQuests/commands/QuestScheduler.java | 12 +++- .../configuration/JsonQuestSave.java | 4 ++ .../configuration/QuestHistoryManager.java | 7 +- .../configuration/QuestLibrary.java | 6 ++ .../ServerQuests/enums/ObjectiveType.java | 2 + .../events/InventoryClickEvents.java | 64 +++++++++++++++++++ .../ServerQuests/gui/ViewHistoryMenu.java | 63 ++++++++++++++++++ .../questcomponents/QuestController.java | 2 + .../questcomponents/bossbar/QuestBar.java | 1 - .../players/BasePlayerComponent.java | 1 + 17 files changed, 234 insertions(+), 16 deletions(-) create mode 100644 src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java create mode 100644 src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java create mode 100644 src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java diff --git a/README.md b/README.md index d5afb65..20f9df1 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,10 @@ Claims rewards for a specific player. Rewards are directly given to the user Clear all rewards for a specific player. Do not specify a player name if you want to clear rewards for all players. +### /cq history + +Opens a UI with historical quest information and data + ## Configuration The config.yml is used to configure quests in the plugin. Once the quests have been created you can start them using the /cq start command. @@ -320,7 +324,6 @@ Fishing: experience: 100 ``` -- **playerkill**: kill other players - **blockbreak**: break a block specified in the materials list in the configuration - **blockplace**: place a block specified in the materials list in the configuration - **projectilekill**: kill entities with a projectile specify entities in the configuration @@ -332,9 +335,12 @@ Fishing: - **enchantitem**: enchant something - **money**: players can contribute money with /cq deposit - **experience**: players must gather Minecraft experience +- **distance**: travel a certain distance in blocks +- **smeltitem**: use furnace to smelt or cook an item +- **brewpotion**: brew potions +- **playerkill**: kill other players - **carvepumpkin**: use shears on a pumpkin - **mythicmob**: Kill mobs from the mythicmob plugin (requires MythicMobs to be installed) -- **distance**: travel a certain distance in blocks ### MythicMobs Example diff --git a/pom.xml b/pom.xml index 6745ba9..8335666 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.wonka01 CommunityQuests - 2.11.3 + 2.12.0 diff --git a/src/main/java/me/knighthat/apis/menus/Menu.java b/src/main/java/me/knighthat/apis/menus/Menu.java index a1a9e26..32b62c5 100644 --- a/src/main/java/me/knighthat/apis/menus/Menu.java +++ b/src/main/java/me/knighthat/apis/menus/Menu.java @@ -65,10 +65,15 @@ protected void onClose(@NonNull final InventoryCloseEvent event) { } public void open() { - setBorder(); - setButtons(); - setContents(); - owner.openInventory(inventory); + try { + setBorder(); + setButtons(); + setContents(); + owner.openInventory(inventory); + } catch (Exception exception) { + Bukkit.getLogger().warning("Error opening menu: " + exception.getMessage()); + exception.printStackTrace(); + } } protected @NonNull ItemStack createItemStack(@NonNull Material m, @NonNull String n) { diff --git a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java index 188457c..b7e2826 100644 --- a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java +++ b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java @@ -7,6 +7,7 @@ import me.knighthat.apis.menus.MenuEvents; import me.wonka01.ServerQuests.commands.CommandManager; import me.wonka01.ServerQuests.configuration.JsonQuestSave; +import me.wonka01.ServerQuests.configuration.QuestHistoryManager; import me.wonka01.ServerQuests.events.*; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.bossbar.BarManager; @@ -36,6 +37,8 @@ public class ServerQuests extends JavaPlugin { private boolean isPlaceholderApiEnabled; @Getter private CommandManager commandManager; + @Getter + private QuestHistoryManager questHistoryManager; @Override public void onEnable() { @@ -71,6 +74,7 @@ public void onEnable() { registerQuestEvents(); RewardManager.getInstance().populateFromJsonFile(getDataFolder(), getLogger()); BossbarPlayerInfo.getInstance().loadFromJsonFile(getDataFolder()); + questHistoryManager = new QuestHistoryManager(this, getDataFolder()); getLogger().info("Plugin is enabled"); } @@ -140,6 +144,7 @@ private void registerQuestEvents() { getServer().getPluginManager().registerEvents(new ConsumeItemQuestEvent(activeQuests), this); getServer().getPluginManager().registerEvents(new EnchantItemQuestEvent(activeQuests), this); getServer().getPluginManager().registerEvents(new DistanceTraveled(activeQuests), this); + getServer().getPluginManager().registerEvents(new InventoryClickEvents(activeQuests), this); try { getServer().getPluginManager().registerEvents(new ExperienceEvent(activeQuests), this); getServer().getPluginManager().registerEvents(new HarvestEvent(activeQuests), this); diff --git a/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java b/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java index de96d50..95b3054 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java @@ -40,6 +40,7 @@ public CommandManager(ServerQuests plugin) { commands.add(new EndAllCommand(plugin)); commands.add(new ClaimRewards(plugin)); commands.add(new ClearRewardsCommand(plugin)); + commands.add(new HistoryCommand(plugin)); this.questScheduler = new QuestScheduler(plugin); commands.add(this.questScheduler); } @@ -57,11 +58,27 @@ public boolean onCommand(CommandSender sender, Command command, String label, St return true; } + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + List completions = new ArrayList<>(); + if (args.length == 1) { + for (PluginCommand cmd : commands) { + if (cmd.getName().startsWith(args[0].toLowerCase())) { + if (cmd.isPlayerCommand() && !(sender instanceof Player)) + break; + + if (cmd.getPermission().isEmpty() || sender.hasPermission(cmd.getPermission())) + completions.add(cmd.getName()); + } + } + } + return completions; + } + private @Nullable PluginCommand getCommand(@NonNull CommandSender sender, @NonNull String arg) { for (PluginCommand cmd : commands) if (cmd.getName().equalsIgnoreCase(arg)) { - if (cmd.isRequiresPlayer() && !(sender instanceof Player)) + if (cmd.isPlayerCommand() && !(sender instanceof Player)) break; if (cmd.getPermission().isEmpty() || sender.hasPermission(cmd.getPermission())) diff --git a/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java new file mode 100644 index 0000000..38f083e --- /dev/null +++ b/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java @@ -0,0 +1,33 @@ +package me.wonka01.ServerQuests.commands; + +import lombok.NonNull; +import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.gui.ViewHistoryMenu; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class HistoryCommand extends PluginCommand { + public HistoryCommand(ServerQuests plugin) { + super(plugin, true); + } + + @Override + public @NonNull String getName() { + return "history"; + } + + @Override + public @NonNull String getPermission() { + return "communityquests.view"; + } + + @Override + public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { + Player player = (Player) sender; + Bukkit.getLogger().info("History command executed by " + player.getName()); + new ViewHistoryMenu(getPlugin(), player).open(); + } +} diff --git a/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java index db18e52..bec4acd 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java @@ -10,11 +10,11 @@ public abstract class PluginCommand implements Colorization { private final ServerQuests plugin; - private final boolean requiresPlayer; + private final boolean playerCommand; - protected PluginCommand(ServerQuests plugin, boolean requiresPlayer) { + protected PluginCommand(ServerQuests plugin, boolean playerCommand) { this.plugin = plugin; - this.requiresPlayer = requiresPlayer; + this.playerCommand = playerCommand; } public abstract @NonNull String getName(); diff --git a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java index 3dbddc0..8a95dc4 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java @@ -95,7 +95,7 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar String action = args[5].toLowerCase(); // check quest library to see if id exists - if (!plugin.config().getQuestLibrary().containsQuest(questId) || questId.equalsIgnoreCase("random")) { + if (!plugin.config().getQuestLibrary().containsQuest(questId) && !questId.equalsIgnoreCase("random")) { sender.sendMessage("§cQuest with ID " + questId + " does not exist!"); return; } @@ -260,8 +260,14 @@ private void scheduleQuest(String scheduleId, String questId, String mode, Strin BukkitRunnable task = new BukkitRunnable() { @Override public void run() { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "cq start " + questId + " " + mode); - plugin.getLogger().info("Scheduled quest " + questId + " executed in " + mode + " mode"); + if (questId.equalsIgnoreCase("random")) { + String random = plugin.config().getQuestLibrary().getRandomQuest(); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "cq start " + random + " " + mode); + plugin.getLogger().info("Scheduled random quest executed in " + mode + " mode"); + } else { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "cq start " + questId + " " + mode); + plugin.getLogger().info("Scheduled quest " + questId + " executed in " + mode + " mode"); + } } }; diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java index 83f81a1..6fa6101 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java @@ -93,6 +93,9 @@ public void saveQuestsInProgress() { private List convertJsonArrayToList(JSONArray arr, Class clazz) { List list = new ArrayList<>(); + if (arr == null) { + return list; + } for (Object o : arr) { list.add(clazz.cast(o)); } @@ -129,6 +132,7 @@ public void readAndInitializeQuests() { JSONArray materials = (JSONArray) obj.get("materials"); JSONArray customNames = (JSONArray) obj.get("customMobNames"); JSONArray customModelIds = (JSONArray) obj.get("customModelIds"); + List materialList = convertJsonArrayToList(materials, String.class).stream() .map(materialName -> { String capitalizedMaterialName = materialName.toUpperCase().replaceAll(" ", "_"); diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java index 9d1490b..957adc9 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java @@ -2,6 +2,8 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.players.PlayerData; + +import org.bukkit.Material; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -35,7 +37,8 @@ private void createHistoryFileIfNotExists() { } } - public void saveCompletedQuest(String questId, String questName, Map playerData) { + public void saveCompletedQuest(String questId, String questName, Map playerData, + Material displayItem) { JSONArray historyArray = loadHistoryArray(); // Create new entry for this quest @@ -43,6 +46,7 @@ public void saveCompletedQuest(String questId, String questName, Map> getRecentQuests(int limit) { questInfo.put("questName", questEntry.get("questName")); questInfo.put("completionTime", questEntry.get("completionTime")); questInfo.put("topContributors", questEntry.get("topContributors")); + questInfo.put("displayItem", questEntry.get("displayItem")); recentQuests.add(questInfo); count++; diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index 21b563a..b46b2fb 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -56,6 +56,12 @@ public void loadQuestConfiguration(ConfigurationSection serverQuestConfig) { questList = map; } + public String getRandomQuest() { + List keys = new ArrayList<>(questList.keySet()); + Random random = new Random(); + return keys.get(random.nextInt(keys.size())); + } + private QuestModel loadQuestFromConfig(ConfigurationSection section) { String questId = section.getName(); String displayName = section.getString("displayName"); diff --git a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java index 14351ee..4f56e59 100644 --- a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java +++ b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java @@ -25,6 +25,8 @@ public enum ObjectiveType { MYTHIC_MOB("mythicmob", Material.DRAGON_HEAD), CARVE_PUMPKIN("carvepumpkin", Material.CARVED_PUMPKIN), MOVEMENT("movement", Material.DIAMOND_BOOTS), + BREW_POTION("brewpotion", Material.BREWING_STAND), + SMELT_ITEM("smeltitem", Material.FURNACE), UNKNOWN("unknown", Material.AIR); @Getter diff --git a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java new file mode 100644 index 0000000..737207f --- /dev/null +++ b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java @@ -0,0 +1,64 @@ +package me.wonka01.ServerQuests.events; + +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.BrewEvent; +import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.inventory.InventoryType.SlotType; +import org.bukkit.inventory.ItemStack; + +import me.wonka01.ServerQuests.enums.ObjectiveType; +import me.wonka01.ServerQuests.questcomponents.ActiveQuests; +import me.wonka01.ServerQuests.questcomponents.QuestController; + +public class InventoryClickEvents extends QuestListener implements Listener { + + private final ObjectiveType BREW_TYPE = ObjectiveType.BREW_POTION; + + public InventoryClickEvents(ActiveQuests activeQuests) { + super(activeQuests); + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + if (event.isCancelled() || !(event.getWhoClicked() instanceof Player)) { + return; + } + Player player = (Player) event.getWhoClicked(); + ItemStack item = event.getCurrentItem(); + InventoryType inventoryType = event.getInventory().getType(); + + if (inventoryType == InventoryType.BREWING) { + Bukkit.getLogger().info("Brewing event " + event.getSlotType().toString()); + Bukkit.getLogger().info("Brewing action " + event.getAction().toString()); + if (event.getSlotType() == SlotType.CRAFTING + || event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) { + List controllers = tryGetControllersOfObjectiveType(BREW_TYPE); + + Bukkit.getLogger().info("Brewing event " + item.getType().toString()); + for (QuestController controller : controllers) { + updateQuest(controller, player, 1, ObjectiveType.BREW_POTION, item.getType().toString(), + item.getItemMeta().getDisplayName()); + } + } + } else if (inventoryType == InventoryType.FURNACE + || inventoryType.name().equals("BLAST_FURNACE") + || inventoryType.name().equals("SMOKER")) { + if (event.getSlotType() == SlotType.RESULT) { + Bukkit.getLogger().info("Furnace inv type " + inventoryType.name()); + Bukkit.getLogger().info("Furnace item " + item.getType().toString()); + List controllers = tryGetControllersOfObjectiveType(ObjectiveType.SMELT_ITEM); + for (QuestController controller : controllers) { + updateQuest(controller, player, 1, ObjectiveType.SMELT_ITEM, item.getType().toString(), + item.getItemMeta().getDisplayName()); + } + } + } + } +} diff --git a/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java new file mode 100644 index 0000000..912fbae --- /dev/null +++ b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java @@ -0,0 +1,63 @@ +package me.wonka01.ServerQuests.gui; + +import me.knighthat.apis.menus.Menu; +import me.knighthat.apis.utils.Utils; +import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.configuration.QuestHistoryManager; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class ViewHistoryMenu extends Menu { + private final QuestHistoryManager historyManager; + + public ViewHistoryMenu(ServerQuests plugin, Player owner) { + super(plugin, owner, "questHistory", 54); // Use full chest inventory + this.historyManager = plugin.getQuestHistoryManager(); + Bukkit.getLogger().info("ViewHistoryMenu created"); + } + + @Override + protected void setContents() { + List> recentQuests = historyManager.getRecentQuests(45); // Get up to 45 recent quests + Bukkit.getLogger().info("Recent quests: " + recentQuests.size()); + for (int i = 0; i < recentQuests.size() && i < 45; i++) { + Map questData = recentQuests.get(i); + + // Choose material based on quest type + String displayItem = (String) questData.get("displayItem"); + Bukkit.getLogger().info("Material: " + displayItem); + Material material = Material.valueOf((String) questData.get("displayItem")); + ItemStack questItem = createQuestHistoryItem(material, questData); + getInventory().setItem(i, questItem); + } + } + + private ItemStack createQuestHistoryItem(Material material, Map questData) { + String questName = (String) questData.get("questName"); + + List lore = new ArrayList<>(); + + long completionTime = (Long) questData.get("completionTime"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + lore.add(color("&7Completed: &f" + sdf.format(new Date(completionTime)))); + + lore.add(color("&eTop Contributors:")); + List topContributors = (List) questData.get("topContributors"); + for (int i = 0; i < Math.min(topContributors.size(), 5); i++) { + Map contributor = (Map) topContributors.get(i); + String contributorName = (String) contributor.get("name"); + String contribution = Utils.decimalToString((Double) contributor.get("contribution")); + lore.add(color("&7" + (i + 1) + ") &f" + contributorName + " &7- &6" + contribution)); + } + return super.createItemStack(material, color("&6" + questName), lore); + } +} \ No newline at end of file diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java index d0a50d2..9bcf92b 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java @@ -105,6 +105,8 @@ public void endQuest() { plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), questData.getAfterQuestCommand()); } + getPlugin().getQuestHistoryManager().saveCompletedQuest(questId.toString(), questData.getDisplayName(), + playerComponent.getPlayerMap(), questData.getDisplayItem()); } ActiveQuests.getActiveQuestsInstance().endQuest(questId); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java index 9cfcba1..4d7b5f2 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java @@ -15,7 +15,6 @@ public class QuestBar implements Colorization { public QuestBar(@NonNull String name, @NonNull String color, @NonNull BarStyle style) { this.barColor = getBarColor(color); - Bukkit.broadcastMessage("Actually adding with color " + this.barColor.toString()); bar = Bukkit.createBossBar(color(name), this.barColor, style); bar.setVisible(true); bar.setProgress(0.0); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java index 3e0a46e..da972a8 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java @@ -29,6 +29,7 @@ public class BasePlayerComponent implements Colorization { @Getter private static int leaderBoardSize = 5; + @Getter private final Map playerMap; private final Map> rankedRewards; private final int rewardsLimit; From 84e2ed7ea20db75fe8ff24dded09e2899da6dcb4 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Fri, 29 Nov 2024 11:16:08 +0000 Subject: [PATCH 05/20] add tab completions, improve filtering logic for event constraints --- README.md | 11 + .../java/me/knighthat/apis/utils/Utils.java | 15 ++ .../me/wonka01/ServerQuests/ServerQuests.java | 6 + .../ServerQuests/commands/CommandManager.java | 4 +- .../configuration/QuestLibrary.java | 16 +- .../ServerQuests/events/BreakEvent.java | 3 +- .../ServerQuests/events/CatchFishEvent.java | 8 +- .../events/ConsumeItemQuestEvent.java | 2 +- .../events/CraftItemQuestEvent.java | 3 +- .../events/EnchantItemQuestEvent.java | 2 +- .../ServerQuests/events/HarvestEvent.java | 3 +- .../events/InventoryClickEvents.java | 28 ++- .../ServerQuests/events/MilkCowEvent.java | 3 - .../ServerQuests/events/MobKillEvent.java | 2 +- .../events/MythicMobKillEvent.java | 2 +- .../ServerQuests/events/PlaceEvent.java | 1 + .../events/ProjectileKillEvent.java | 3 +- .../ServerQuests/events/QuestListener.java | 92 ++++++-- .../ServerQuests/events/ShearEvent.java | 2 +- .../ServerQuests/events/TameEvent.java | 3 +- .../wonka01/ServerQuests/gui/DonateMenu.java | 9 +- .../objectives/ObjectiveFilters.java | 201 ++++++++++++++++++ .../questcomponents/QuestController.java | 2 +- .../players/BasePlayerComponent.java | 3 + .../questcomponents/players/PlayerData.java | 4 +- .../rewards/RewardJoinListener.java | 1 - src/main/resources/plugin.yml | 1 + 27 files changed, 368 insertions(+), 62 deletions(-) create mode 100644 src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java diff --git a/README.md b/README.md index 47266b3..8bca7d1 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,17 @@ objectives: description: Oak Saplings ``` +### Objective filters + +The quest above uses the materials filter so that the first objective looks for `ACACIA_SAPLINGS` on a blockplace event and then second objective looks for `OAK_SAPLING`. Both objectives run concurrently. For block related events, materials is the only filter that works but there are four more filters you can use. + +- **materials** - use to specify the material type of blocks or items +- **entities** - use to specify the entity type of mobs for quests like mobKill, projectileKill and tameevent. It's also used in the catchfish event and the mythicmob event. +- **customNames** - use to specify the custom name of both mobs and items. This can be used for custom mobs or renamed items. +- **modelIds** - use to specify the model id of items. This can be used for custom items with a specific model id in custom model plugins like oraxen. +- **potions** - use to specify the potion type for the brewpotion event. For example, `AWKWARD` or `FIRE_RESISTANCE`. +- **enchants** - use to specify the enchantment type for the enchantitem event. For example, `DAMAGE_ALL` or `PROTECTION_ENVIRONMENTAL`. + The quest below requires you to kill 15 zombified piglins and 10 zombie pigmen. For mob related quests you can use the customNames field to specify the name of the mob you want to kill. If you want to kill a specific mob type you can use the entities field and specify the mob type from the [entity list](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html). ```yaml diff --git a/src/main/java/me/knighthat/apis/utils/Utils.java b/src/main/java/me/knighthat/apis/utils/Utils.java index f2a3d91..71ef0f4 100644 --- a/src/main/java/me/knighthat/apis/utils/Utils.java +++ b/src/main/java/me/knighthat/apis/utils/Utils.java @@ -1,6 +1,9 @@ package me.knighthat.apis.utils; import lombok.NonNull; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.Nullable; import java.text.DecimalFormat; @@ -32,4 +35,16 @@ static boolean contains(@Nullable F[] from, @Nullable V value) { DecimalFormat format = new DecimalFormat("0.#"); return format.format(a); } + + static int getCustomModelData(ItemStack item) { + if (item == null || !item.hasItemMeta()) { + return -1; + } + + ItemMeta meta = item.getItemMeta(); + if (meta != null && meta.hasCustomModelData()) { + return meta.getCustomModelData(); + } + return -1; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java index b7e2826..094ecd9 100644 --- a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java +++ b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java @@ -13,11 +13,13 @@ import me.wonka01.ServerQuests.questcomponents.bossbar.BarManager; import me.wonka01.ServerQuests.questcomponents.bossbar.BossbarPlayerInfo; import me.wonka01.ServerQuests.questcomponents.hologram.DecentHologramsDisplay; +import me.wonka01.ServerQuests.questcomponents.rewards.RewardJoinListener; import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; import me.wonka01.placeholders.CommunityQuestsPlaceholders; import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; +import org.bukkit.command.PluginCommand; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; @@ -43,6 +45,9 @@ public class ServerQuests extends JavaPlugin { @Override public void onEnable() { this.commandManager = new CommandManager(this); + PluginCommand pluginCommand = getCommand("communityquests"); + pluginCommand.setExecutor(commandManager); + pluginCommand.setTabCompleter(commandManager); loadSaveData(); @@ -145,6 +150,7 @@ private void registerQuestEvents() { getServer().getPluginManager().registerEvents(new EnchantItemQuestEvent(activeQuests), this); getServer().getPluginManager().registerEvents(new DistanceTraveled(activeQuests), this); getServer().getPluginManager().registerEvents(new InventoryClickEvents(activeQuests), this); + getServer().getPluginManager().registerEvents(new RewardJoinListener(true), this); try { getServer().getPluginManager().registerEvents(new ExperienceEvent(activeQuests), this); getServer().getPluginManager().registerEvents(new HarvestEvent(activeQuests), this); diff --git a/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java b/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java index 95b3054..f07c003 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java @@ -6,13 +6,14 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -public class CommandManager implements CommandExecutor { +public class CommandManager implements CommandExecutor, TabCompleter { private final ServerQuests plugin; @@ -58,6 +59,7 @@ public boolean onCommand(CommandSender sender, Command command, String label, St return true; } + @Override public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { List completions = new ArrayList<>(); if (args.length == 1) { diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index ca1243d..d5cb63e 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -80,8 +80,10 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { BarStyle style = BarStyle.valueOf(barStyle.toUpperCase()); List objectives = null; - List mobNames = null; - List customMobNames = null; + List entityNames = null; + List customNames = null; + List customModelIds = null; + int goal = 0; ObjectiveType type = null; List materials = null; @@ -93,9 +95,9 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { Bukkit.getServer().getConsoleSender().sendMessage( "[Community Quests] Using the legacy questing system for ID " + questId + ". Please check the docs and follow the new format for creating quests with the objectives option. This enables you to set multiple objectives per quest."); - mobNames = section.getStringList("entities"); + entityNames = section.getStringList("entities"); materials = section.getStringList("materials"); - customMobNames = section.getStringList("customMobNames"); + customNames = section.getStringList("customNames"); type = ObjectiveType.match(section.getString("type")); goal = section.getInt("goal", -1); } else { @@ -112,7 +114,7 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { String objDescription = (String) obj.get("description"); List objectiveMobs = (List) obj.get("entities"); List objectiveMaterials = (List) obj.get("materials"); - List objectiveCustomNames = (List) obj.get("customMobNames"); + List objectiveCustomNames = (List) obj.get("customNames"); List objectiveModelIds = (List) obj.get("modelIds"); ObjectiveType objectiveTypeEnum = ObjectiveType.match(objectiveType); @@ -170,8 +172,8 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { } return new QuestModel(questId, displayName, description, goal, - type, mobNames, materials, displayItem, worlds, questDuration, rewardsLimit, afterQuestCommand, - beforeQuestCommand, objectives, questFailedCommand, customMobNames, barColor.toUpperCase(), + type, entityNames, materials, displayItem, worlds, questDuration, rewardsLimit, afterQuestCommand, + beforeQuestCommand, objectives, questFailedCommand, customNames, barColor.toUpperCase(), rankedRewardsMap, rankedRewardMessages, style); } diff --git a/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java b/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java index a4c9a6c..4ba0303 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java @@ -50,9 +50,10 @@ public void onBlockBreakEvent(BlockBreakEvent event) { } List controllers = tryGetControllersOfObjectiveType(ObjectiveType.BLOCK_BREAK); + for (QuestController controller : controllers) { block.setMetadata(BROKEN, meta); - updateQuest(controller, event.getPlayer(), 1., ObjectiveType.BLOCK_BREAK, block.getType()); + updateQuest(controller, event.getPlayer(), 1, ObjectiveType.BLOCK_BREAK, block.getType()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/CatchFishEvent.java b/src/main/java/me/wonka01/ServerQuests/events/CatchFishEvent.java index 0082fba..a1fb068 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/CatchFishEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/CatchFishEvent.java @@ -23,12 +23,16 @@ public CatchFishEvent(ActiveQuests activeQuests) { @EventHandler public void onCatchFish(PlayerFishEvent event) { if (event.getState() == PlayerFishEvent.State.CAUGHT_FISH) { - List controllers = tryGetControllersOfObjectiveType(TYPE); Item item = (Item) event.getCaught(); String fishName = item.getItemStack().getType().toString(); + // log fish name and type + Bukkit.getLogger().info("Caught fish: " + fishName); + Bukkit.getLogger().info("Fish type: " + item.getName()); + + List controllers = tryGetControllersOfObjectiveType(TYPE); for (QuestController controller : controllers) { - updateQuest(controller, event.getPlayer(), 1, ObjectiveType.CATCH_FISH, fishName, item.getName()); + updateQuest(controller, event.getPlayer(), 1, ObjectiveType.CATCH_FISH, fishName); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/ConsumeItemQuestEvent.java b/src/main/java/me/wonka01/ServerQuests/events/ConsumeItemQuestEvent.java index da3dabe..5577059 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/ConsumeItemQuestEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/ConsumeItemQuestEvent.java @@ -23,7 +23,7 @@ public void onConsumeItem(PlayerItemConsumeEvent event) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.CONSUME_ITEM); for (QuestController controller : controllers) { - updateQuest(controller, player, 1, ObjectiveType.CONSUME_ITEM, event.getItem().getType()); + updateQuest(controller, player, 1, ObjectiveType.CONSUME_ITEM, event.getItem()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/CraftItemQuestEvent.java b/src/main/java/me/wonka01/ServerQuests/events/CraftItemQuestEvent.java index 8c42d2c..21b060f 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/CraftItemQuestEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/CraftItemQuestEvent.java @@ -4,7 +4,6 @@ import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -58,7 +57,7 @@ public void onCraftItem(CraftItemEvent event) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.CRAFT_ITEM); for (QuestController controller : controllers) { - updateQuest(controller, (Player) event.getWhoClicked(), realAmount, ObjectiveType.CRAFT_ITEM, material); + updateQuest(controller, (Player) event.getWhoClicked(), realAmount, ObjectiveType.CRAFT_ITEM, craftedItem); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java b/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java index 70361eb..ea573fe 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java @@ -23,7 +23,7 @@ public void onEnchantItem(EnchantItemEvent event) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.ENCHANT_ITEM); for (QuestController controller : controllers) { - updateQuest(controller, player, 1, ObjectiveType.ENCHANT_ITEM, event.getItem().getType()); + updateQuest(controller, player, 1, ObjectiveType.ENCHANT_ITEM, event.getItem()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java b/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java index ae1e15a..36900a5 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java @@ -8,6 +8,7 @@ import org.bukkit.event.player.PlayerHarvestBlockEvent; import org.bukkit.inventory.ItemStack; +import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; @@ -24,7 +25,7 @@ public void onHarvestEvent(PlayerHarvestBlockEvent event) { for (QuestController controller : controllers) { List harvestedItems = event.getItemsHarvested(); for (ItemStack item : harvestedItems) { - updateQuest(controller, event.getPlayer(), item.getAmount(), ObjectiveType.HARVEST, item.getType()); + updateQuest(controller, event.getPlayer(), item.getAmount(), ObjectiveType.HARVEST, item); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java index 737207f..42db814 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java +++ b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java @@ -6,13 +6,16 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.inventory.BrewEvent; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.Potion; +import org.bukkit.potion.PotionType; +import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; @@ -35,28 +38,33 @@ public void onInventoryClick(InventoryClickEvent event) { InventoryType inventoryType = event.getInventory().getType(); if (inventoryType == InventoryType.BREWING) { - Bukkit.getLogger().info("Brewing event " + event.getSlotType().toString()); - Bukkit.getLogger().info("Brewing action " + event.getAction().toString()); if (event.getSlotType() == SlotType.CRAFTING || event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) { List controllers = tryGetControllersOfObjectiveType(BREW_TYPE); - Bukkit.getLogger().info("Brewing event " + item.getType().toString()); + Bukkit.getLogger().info("Brewing item " + item.getType().toString()); + PotionMeta potionMeta = (PotionMeta) item.getItemMeta(); + + if (potionMeta == null) { + Bukkit.getLogger().info("PotionMeta is null for item " + item.getType().toString()); + return; + } + + Bukkit.getLogger() + .info("PotionMeta is not null for item " + potionMeta.getBasePotionData().getType().toString()); + for (QuestController controller : controllers) { - updateQuest(controller, player, 1, ObjectiveType.BREW_POTION, item.getType().toString(), - item.getItemMeta().getDisplayName()); + updateQuest(controller, player, 1, ObjectiveType.BREW_POTION, item); } } } else if (inventoryType == InventoryType.FURNACE || inventoryType.name().equals("BLAST_FURNACE") || inventoryType.name().equals("SMOKER")) { if (event.getSlotType() == SlotType.RESULT) { - Bukkit.getLogger().info("Furnace inv type " + inventoryType.name()); - Bukkit.getLogger().info("Furnace item " + item.getType().toString()); List controllers = tryGetControllersOfObjectiveType(ObjectiveType.SMELT_ITEM); for (QuestController controller : controllers) { - updateQuest(controller, player, 1, ObjectiveType.SMELT_ITEM, item.getType().toString(), - item.getItemMeta().getDisplayName()); + updateQuest(controller, player, item.getAmount(), ObjectiveType.SMELT_ITEM, + item); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/MilkCowEvent.java b/src/main/java/me/wonka01/ServerQuests/events/MilkCowEvent.java index 544d13b..9c5b1f2 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/MilkCowEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/MilkCowEvent.java @@ -4,14 +4,11 @@ import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; import org.bukkit.Material; -import org.bukkit.entity.Cow; -import org.bukkit.entity.Entity; 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.PlayerBucketFillEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; import java.util.List; diff --git a/src/main/java/me/wonka01/ServerQuests/events/MobKillEvent.java b/src/main/java/me/wonka01/ServerQuests/events/MobKillEvent.java index 6615343..0d4a70b 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/MobKillEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/MobKillEvent.java @@ -30,7 +30,7 @@ public void OnPlayerKillMob(EntityDeathEvent event) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.MOB_KILL); for (QuestController controller : controllers) { - updateQuest(controller, killer, 1, ObjectiveType.MOB_KILL, entity.getType().toString(), entity.getName()); + updateQuest(controller, killer, 1, ObjectiveType.MOB_KILL, entity); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/MythicMobKillEvent.java b/src/main/java/me/wonka01/ServerQuests/events/MythicMobKillEvent.java index 1297daf..51a347a 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/MythicMobKillEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/MythicMobKillEvent.java @@ -28,7 +28,7 @@ public void onKillMythicMobEvent(MythicMobDeathEvent event) { for (QuestController controller : controllers) { updateQuest(controller, (Player) event.getKiller(), 1, ObjectiveType.MYTHIC_MOB, - event.getMobType().getInternalName(), event.getMobType().getInternalName()); + event.getMobType().getInternalName()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java b/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java index e25d2cf..078bb86 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java @@ -40,6 +40,7 @@ public void onBlockPlace(BlockPlaceEvent event) { } List controllers = tryGetControllersOfObjectiveType(ObjectiveType.BLOCK_PLACE); + for (QuestController controller : controllers) { updateQuest(controller, event.getPlayer(), 1, ObjectiveType.BLOCK_PLACE, block.getType()); block.setMetadata(PLACED, meta); diff --git a/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java b/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java index 7d39f51..c3f9d87 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java @@ -37,8 +37,7 @@ public void onProjectileKill(EntityDeathEvent event) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.PROJ_KILL); for (QuestController controller : controllers) { - updateQuest(controller, player, 1, ObjectiveType.PROJ_KILL, event.getEntity().getType().toString(), - event.getEntity().getName()); + updateQuest(controller, player, 1, ObjectiveType.PROJ_KILL, event.getEntity()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java index 10c3162..d30f039 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java +++ b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java @@ -1,14 +1,16 @@ package me.wonka01.ServerQuests.events; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; +import me.wonka01.ServerQuests.objectives.ObjectiveFilters; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; import me.wonka01.ServerQuests.questcomponents.QuestData; import org.bukkit.Material; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.List; @@ -20,6 +22,15 @@ public QuestListener(ActiveQuests activeQuests) { this.activeQuests = activeQuests; } + protected boolean updateQuest(QuestController controller, Player player, double amount, Objective obj, + int objectiveId) { + if (!isEnabledInWorld(controller.getEventConstraints().getWorlds(), player.getWorld().getName())) { + return false; + } + return controller.updateQuest(amount, player, obj, objectiveId); + } + + // General quests without filters protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type) { QuestData questData = controller.getQuestData(); List objectives = questData.getObjectives(); @@ -31,42 +42,85 @@ protected void updateQuest(QuestController controller, Player player, double amo } } - protected boolean updateQuest(QuestController controller, Player player, double amount, Objective obj, - int objectiveId) { - if (!isEnabledInWorld(controller.getEventConstraints().getWorlds(), player.getWorld().getName())) { - return false; + // Mob quests + protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, + Entity entity) { + QuestData questData = controller.getQuestData(); + List objectives = questData.getObjectives(); + for (int i = 0; i < objectives.size(); i++) { + Objective objective = objectives.get(i); + boolean matches = ObjectiveFilters.filter() + .withEntity(entity) + .withType(type) + .matches(objective); + + if (matches) { + updateQuest(controller, player, amount, objective, i); + } + + // if (objective.getType().equals(type)) { + // if (objective.getMobNames().isEmpty()) { + // if (objective.getCustomNames().isEmpty()) { + // updateQuest(controller, player, amount, objective, i); + // } else if (Utils.contains(objective.getCustomNames(), customName)) { + // updateQuest(controller, player, amount, objective, i); + // } + // } else if (Utils.contains(objective.getMobNames(), mobName)) { + // updateQuest(controller, player, amount, objective, i); + // } + // } } - return controller.updateQuest(amount, player, obj, objectiveId); } + // Mob quests with entity as a string protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, - String mobName, String customName) { + String entity) { QuestData questData = controller.getQuestData(); List objectives = questData.getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); - if (objective.getType().equals(type)) { - if (objective.getMobNames().isEmpty()) { - if (objective.getCustomNames().isEmpty()) { - updateQuest(controller, player, amount, objective, i); - } else if (Utils.contains(objective.getCustomNames(), customName)) { - updateQuest(controller, player, amount, objective, i); - } - } else if (Utils.contains(objective.getMobNames(), mobName)) { - updateQuest(controller, player, amount, objective, i); - } + boolean matches = ObjectiveFilters.filter() + .withEntity(entity) + .withType(type) + .matches(objective); + + if (matches) { + updateQuest(controller, player, amount, objective, i); } } } + // Block quests protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, Material material) { QuestData questData = controller.getQuestData(); List objectives = questData.getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); - if (objective.getType().equals(type) - && (objective.getMaterials().isEmpty() || objective.getMaterials().contains(material))) { + boolean matches = ObjectiveFilters.filter() + .withMaterial(material) + .withType(type) + .matches(objective); + + if (matches) { + updateQuest(controller, player, amount, objective, i); + } + } + } + + // Item quests + protected void updateQuest(QuestController controller, Player player, int amount, ObjectiveType type, + ItemStack item) { + QuestData questData = controller.getQuestData(); + List objectives = questData.getObjectives(); + for (int i = 0; i < objectives.size(); i++) { + Objective objective = objectives.get(i); + boolean matches = ObjectiveFilters.filter() + .withItem(item) + .withType(type) + .matches(objective); + + if (matches) { updateQuest(controller, player, amount, objective, i); } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/ShearEvent.java b/src/main/java/me/wonka01/ServerQuests/events/ShearEvent.java index d34a462..ce79f90 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/ShearEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/ShearEvent.java @@ -27,7 +27,7 @@ public void onSheer(PlayerShearEntityEvent shearEvent) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.SHEAR); for (QuestController controller : controllers) { updateQuest(controller, shearEvent.getPlayer(), 1, ObjectiveType.SHEAR, - shearEvent.getEntity().getType().toString(), shearEvent.getEntity().getName()); + shearEvent.getEntity()); } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/TameEvent.java b/src/main/java/me/wonka01/ServerQuests/events/TameEvent.java index c3918a6..eaf6110 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/TameEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/TameEvent.java @@ -21,8 +21,7 @@ public void onTameEvent(EntityTameEvent tameEvent) { if (tameEvent.getOwner() instanceof Player) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.TAME); for (QuestController controller : controllers) { - updateQuest(controller, (Player) tameEvent.getOwner(), 1, ObjectiveType.TAME, - tameEvent.getEntity().getType().toString(), tameEvent.getEntity().getName()); + updateQuest(controller, (Player) tameEvent.getOwner(), 1, ObjectiveType.TAME, tameEvent.getEntity()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java index 7682164..2ea38ce 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java @@ -8,11 +8,11 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; +import me.wonka01.ServerQuests.objectives.ObjectiveFilters; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.CompetitiveQuestData; import me.wonka01.ServerQuests.questcomponents.QuestController; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.entity.Player; @@ -97,8 +97,11 @@ protected void onItemClick(@NonNull InventoryClickEvent event) { total = data.getPlayers().getAmountContributedByObjectiveId(getOwner(), i) + inputItem.getAmount(); } - List requirements = objective.getMaterials(); - if (requirements.isEmpty() || requirements.contains(inputItem.getType())) { + boolean matches = ObjectiveFilters.filter() + .withItem(inputItem) + .matches(objective); + + if (matches) { boolean updateResult = updateQuest(ctrl, inputItem, objective, counter); if (updateResult) { if (total > goal && goal > 0) { diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java new file mode 100644 index 0000000..5d55d75 --- /dev/null +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -0,0 +1,201 @@ +package me.wonka01.ServerQuests.objectives; + +import me.knighthat.apis.utils.Utils; +import me.wonka01.ServerQuests.enums.ObjectiveType; + +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.inventory.ItemStack; + +import java.util.function.Predicate; + +public class ObjectiveFilters { + + /** + * Creates a filter for objectives based on various criteria + */ + public static class Builder { + private Material material; + private String entity; + private String customName; + private Integer customModelId; + private ObjectiveType type; + + public Builder withMaterial(Material material) { + this.material = material; + return this; + } + + public Builder withType(ObjectiveType type) { + this.type = type; + return this; + } + + public Builder withItem(ItemStack item) { + if (item != null) { + this.material = item.getType(); + this.customModelId = Utils.getCustomModelData(item); + } + return this; + } + + public Builder withEntity(Entity entity) { + if (entity != null) { + this.entity = entity.getType().name(); + if (entity.getCustomName() != null) { + this.customName = entity.getCustomName(); + } else { + this.customName = entity.getName(); + } + } + return this; + } + + // option to define with string for fishing/mythic mobs where entity is not + // needed + public Builder withEntity(String entity) { + this.entity = entity; + return this; + } + + public Builder withCustomName(String customName) { + this.customName = customName; + return this; + } + + public Builder withCustomModelId(Integer customModelId) { + this.customModelId = customModelId; + return this; + } + + /** + * Build a predicate to filter objectives + * + * @param objective The objective to filter + * @return true if the objective matches all specified criteria + */ + public boolean matches(Objective objective) { + // Material filter + if (material != null) { + if (objective.getMaterials().isEmpty()) { + return false; + } + if (!objective.getMaterials().contains(material)) { + return false; + } + } + + if (type != null) { + if (!objective.getType().equals(type)) { + return false; + } + } + + // Mob name filter + if (entity != null) { + if (objective.getMobNames().isEmpty()) { + return false; + } + if (!Utils.contains(objective.getMobNames(), entity)) { + return false; + } + } + + // Custom name filter + if (customName != null) { + if (objective.getCustomNames().isEmpty()) { + return false; + } + if (!Utils.contains(objective.getCustomNames(), customName)) { + return false; + } + } + + // Custom model ID filter + if (customModelId != null) { + if (!hasCustomModelId(objective, customModelId)) { + return false; + } + } + + return true; + } + + /** + * Check if an objective contains items with a specific custom model ID + * + * @param objective The objective to check + * @param modelId The custom model ID to match + * @return true if the objective contains an item with the specified custom + * model ID + */ + private boolean hasCustomModelId(Objective objective, int modelId) { + // This is a placeholder method. You'll need to implement the actual + // logic to check for custom model ID in your Objective class + return true; + } + } + + /** + * Convenience method to create a new filter builder + * + * @return A new ObjectiveFilters.Builder instance + */ + public static Builder filter() { + return new Builder(); + } + + /** + * Additional utility method to check if an item matches a custom model ID + * + * @param item The ItemStack to check + * @param customModelId The custom model ID to match + * @return true if the item's custom model ID matches + */ + public static boolean matchesCustomModelId(ItemStack item, int customModelId) { + if (item == null || !item.hasItemMeta()) { + return false; + } + + return item.getItemMeta().hasCustomModelData() && + item.getItemMeta().getCustomModelData() == customModelId; + } + + /** + * Create a predicate filter for objectives based on multiple criteria + * + * @return A Predicate that can be used to filter objectives + */ + public static Predicate createObjectivePredicate( + Material material, + String entity, + String customName, + Integer customModelId) { + return objective -> { + // Null checks and filtering logic + if (material != null + && (objective.getMaterials().isEmpty() || !objective.getMaterials().contains(material))) { + return false; + } + + if (entity != null + && (objective.getMobNames().isEmpty() || !Utils.contains(objective.getMobNames(), entity))) { + return false; + } + + if (customName != null && (objective.getCustomNames().isEmpty() + || !Utils.contains(objective.getCustomNames(), customName))) { + return false; + } + + // Custom model ID filter (placeholder - implement based on your Objective class + // structure) + if (customModelId != null) { + // Implement custom model ID checking logic + return false; + } + + return true; + }; + } +} \ No newline at end of file diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java index 9bcf92b..c4d79fe 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java @@ -44,7 +44,7 @@ public QuestController(ServerQuests plugin, QuestData questData, QuestBar questB public boolean updateQuest(double count, Player player, Objective objective, Integer objectiveId) { double amountToAdd = count; - // Check if quest is complete + // Check if quest is complete (not 100% sure if this is needed) if (questData.getEventType().equals(EventType.COMPETITIVE)) { CompetitiveQuestData competitiveQuestData = (CompetitiveQuestData) questData; if (competitiveQuestData.isGoalComplete(objective, player, objectiveId)) { diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java index f5671ed..d53cf84 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java @@ -52,6 +52,9 @@ public void savePlayerAction(Player player, double count, Integer objectiveId) { if (playerMap.containsKey(player.getUniqueId())) { PlayerData playerData = playerMap.get(player.getUniqueId()); playerData.increaseContribution(count, objectiveId); + + // update display name so ranks and such are handled better + playerData.setName(player.getDisplayName()); } else { PlayerData playerData = new PlayerData(player.getDisplayName(), player.getUniqueId()); playerData.increaseContribution(count, objectiveId); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java index f51e5cf..707dc71 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java @@ -4,13 +4,13 @@ import java.util.Map; import java.util.UUID; -import org.bukkit.Bukkit; - import lombok.Getter; +import lombok.Setter; @Getter public class PlayerData { + @Setter private String name; private UUID uuid; Map objectiveContributions; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardJoinListener.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardJoinListener.java index 9a2f085..970c5e8 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardJoinListener.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardJoinListener.java @@ -23,7 +23,6 @@ public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - // Check if player has pending rewards if (rewardManager.hasRewards(player.getUniqueId())) { // Give rewards to the player rewardManager.giveRewardToPlayer(player.getUniqueId()); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3b2310b..d4ce559 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -8,6 +8,7 @@ commands: communityquests: aliases: [cq, quests] description: Commands for Community Quests Plugin + usage: / [start|stop|reload|view|rewards|donate|money|showmessages|togglebar|claim|clearrewards|schedule] softdepend: - Vault From 4148a327cdc7155c72eab93473eeaa6832ead649 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Fri, 29 Nov 2024 11:21:00 +0000 Subject: [PATCH 06/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bca7d1..9d000e7 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ objectives: ### Objective filters -The quest above uses the materials filter so that the first objective looks for `ACACIA_SAPLINGS` on a blockplace event and then second objective looks for `OAK_SAPLING`. Both objectives run concurrently. For block related events, materials is the only filter that works but there are four more filters you can use. +The quest above uses the materials filter so that the first objective looks for `ACACIA_SAPLINGS` on a blockplace event and then second objective looks for `OAK_SAPLING`. Both objectives run concurrently. For block related events, materials is the only filter that works but there are four more filters you can use. If no constraints are provided (or you provide an invalid material name!), then the quest will count all events of that type! - **materials** - use to specify the material type of blocks or items - **entities** - use to specify the entity type of mobs for quests like mobKill, projectileKill and tameevent. It's also used in the catchfish event and the mythicmob event. From 8e7da2013a5408afb44e0253e6df88f00debb872 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Fri, 29 Nov 2024 15:46:58 +0000 Subject: [PATCH 07/20] potion quest updates / levelup event --- README.md | 3 ++- .../configuration/QuestLibrary.java | 14 +++++++++++++- .../ServerQuests/enums/ObjectiveType.java | 1 + .../ServerQuests/events/ExperienceEvent.java | 15 +++++++++++++++ .../events/InventoryClickEvents.java | 8 +++----- .../ServerQuests/events/QuestListener.java | 19 +++++++++++++++++++ .../objectives/ObjectiveFilters.java | 12 +++++++++--- 7 files changed, 62 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9d000e7..4611a41 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ objectives: ### Objective filters -The quest above uses the materials filter so that the first objective looks for `ACACIA_SAPLINGS` on a blockplace event and then second objective looks for `OAK_SAPLING`. Both objectives run concurrently. For block related events, materials is the only filter that works but there are four more filters you can use. If no constraints are provided (or you provide an invalid material name!), then the quest will count all events of that type! +The quest above uses the `materials` filter so the first objective looks for `ACACIA_SAPLINGS` on a blockplace event and then second objective looks for `OAK_SAPLING`. Both objectives run concurrently. For block related events, materials is the only valid filter but there are six more filters you can use. If no constraints are provided (or you provide an invalid material name!), the quest will count all events of that type! - **materials** - use to specify the material type of blocks or items - **entities** - use to specify the entity type of mobs for quests like mobKill, projectileKill and tameevent. It's also used in the catchfish event and the mythicmob event. @@ -346,6 +346,7 @@ Fishing: - **enchantitem**: enchant something - **money**: players can contribute money with /cq deposit - **experience**: players must gather Minecraft experience +- **level**: players must levelup - **distance**: travel a certain distance in blocks - **smeltitem**: use furnace to smelt or cook an item - **brewpotion**: brew potions diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index d5cb63e..383ad95 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -82,7 +82,6 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { List objectives = null; List entityNames = null; List customNames = null; - List customModelIds = null; int goal = 0; ObjectiveType type = null; @@ -98,6 +97,7 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { entityNames = section.getStringList("entities"); materials = section.getStringList("materials"); customNames = section.getStringList("customNames"); + type = ObjectiveType.match(section.getString("type")); goal = section.getInt("goal", -1); } else { @@ -116,6 +116,16 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { List objectiveMaterials = (List) obj.get("materials"); List objectiveCustomNames = (List) obj.get("customNames"); List objectiveModelIds = (List) obj.get("modelIds"); + List potionNames = (List) obj.get("potions"); + List enchantments = (List) obj.get("enchantments"); + + if (potionNames != null) { + objectiveCustomNames = potionNames; + } + + if (enchantments != null) { + objectiveCustomNames = enchantments; + } ObjectiveType objectiveTypeEnum = ObjectiveType.match(objectiveType); List mats = new ArrayList<>(); @@ -124,6 +134,8 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { String capitalizedMaterialName = itemName.toUpperCase().replaceAll(" ", "_"); Material material = Material.getMaterial(capitalizedMaterialName); if (material == null) { + Bukkit.getServer().getConsoleSender().sendMessage( + "[Community Quests] Invalid material name " + itemName + " for quest " + questId); return Material.AIR; } return material; diff --git a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java index 4f56e59..849bfb3 100644 --- a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java +++ b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java @@ -21,6 +21,7 @@ public enum ObjectiveType { GIVE_MONEY("money", Material.GOLDEN_APPLE), ENCHANT_ITEM("enchantitem", Material.EMERALD), EXPERIENCE("experience", Material.EXPERIENCE_BOTTLE), + LEVELUP("level", Material.EXPERIENCE_BOTTLE), HARVEST("harvest", Material.WHEAT), MYTHIC_MOB("mythicmob", Material.DRAGON_HEAD), CARVE_PUMPKIN("carvepumpkin", Material.CARVED_PUMPKIN), diff --git a/src/main/java/me/wonka01/ServerQuests/events/ExperienceEvent.java b/src/main/java/me/wonka01/ServerQuests/events/ExperienceEvent.java index f720a08..654bb68 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/ExperienceEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/ExperienceEvent.java @@ -7,6 +7,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerExpChangeEvent; +import org.bukkit.event.player.PlayerLevelChangeEvent; import java.util.List; @@ -23,4 +24,18 @@ public void onExperienceEvent(PlayerExpChangeEvent event) { updateQuest(controller, event.getPlayer(), event.getAmount(), ObjectiveType.EXPERIENCE); } } + + @EventHandler(priority = EventPriority.MONITOR) + public void onLevelUpEvent(PlayerLevelChangeEvent event) { + int newLevel = event.getNewLevel(); + int oldLevel = event.getOldLevel(); + + if (newLevel <= oldLevel) { + return; + } + List controllers = tryGetControllersOfObjectiveType(ObjectiveType.LEVELUP); + for (QuestController controller : controllers) { + updateQuest(controller, event.getPlayer(), newLevel - oldLevel, ObjectiveType.LEVELUP); + } + } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java index 42db814..4d309c9 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java +++ b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java @@ -12,10 +12,7 @@ import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.Potion; -import org.bukkit.potion.PotionType; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; @@ -51,10 +48,11 @@ public void onInventoryClick(InventoryClickEvent event) { } Bukkit.getLogger() - .info("PotionMeta is not null for item " + potionMeta.getBasePotionData().getType().toString()); + .info("PotionMeta is not null for item " + potionMeta.getBasePotionData().getType().name()); for (QuestController controller : controllers) { - updateQuest(controller, player, 1, ObjectiveType.BREW_POTION, item); + updateQuest(controller, player, 1, ObjectiveType.BREW_POTION, + potionMeta.getBasePotionData().getType()); } } } else if (inventoryType == InventoryType.FURNACE diff --git a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java index d30f039..753061b 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java +++ b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java @@ -11,6 +11,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionType; import java.util.ArrayList; import java.util.List; @@ -90,6 +91,24 @@ protected void updateQuest(QuestController controller, Player player, double amo } } + // Potion quests + protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, + PotionType potion) { + QuestData questData = controller.getQuestData(); + List objectives = questData.getObjectives(); + for (int i = 0; i < objectives.size(); i++) { + Objective objective = objectives.get(i); + boolean matches = ObjectiveFilters.filter() + .withEntity(potion.name()) + .withType(type) + .matches(objective); + + if (matches) { + updateQuest(controller, player, amount, objective, i); + } + } + } + // Block quests protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, Material material) { diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java index 5d55d75..ad972f5 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -6,6 +6,7 @@ import org.bukkit.Material; import org.bukkit.entity.Entity; import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionType; import java.util.function.Predicate; @@ -39,6 +40,13 @@ public Builder withItem(ItemStack item) { return this; } + public Builder withPotion(PotionType potion) { + if (potion != null) { + this.customName = potion.name(); + } + return this; + } + public Builder withEntity(Entity entity) { if (entity != null) { this.entity = entity.getType().name(); @@ -130,9 +138,7 @@ public boolean matches(Objective objective) { * model ID */ private boolean hasCustomModelId(Objective objective, int modelId) { - // This is a placeholder method. You'll need to implement the actual - // logic to check for custom model ID in your Objective class - return true; + return objective.getCustomModelIds().contains(modelId); } } From c8cf83586ce3850e1dc3ac2e73663f226f20f8ee Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sat, 30 Nov 2024 19:04:12 +0000 Subject: [PATCH 08/20] save quest complete message with rewards, give reward, fix reload break/places on quest complete or login --- .../me/wonka01/ServerQuests/ServerQuests.java | 4 +- .../ServerQuests/commands/HistoryCommand.java | 2 - .../ServerQuests/configuration}/Config.java | 9 +++- .../configuration/QuestHistoryManager.java | 11 ++--- .../configuration/QuestLibrary.java | 5 +- .../ServerQuests/events/BreakEvent.java | 8 +++- .../events/EnchantItemQuestEvent.java | 2 +- .../events/InventoryClickEvents.java | 36 ++++++++++++-- .../ServerQuests/events/PlaceEvent.java | 9 ++-- .../events/ProjectileKillEvent.java | 1 - .../ServerQuests/events/QuestListener.java | 43 +++++++++++------ .../ServerQuests/gui/ViewHistoryMenu.java | 9 ++-- .../objectives/ObjectiveFilters.java | 48 +++++++++++++------ .../questcomponents/QuestController.java | 3 +- .../players/BasePlayerComponent.java | 24 ++++++---- src/main/resources/config.yml | 5 +- src/main/resources/messages.yml | 2 + 17 files changed, 148 insertions(+), 73 deletions(-) rename src/main/java/me/{knighthat/apis/files => wonka01/ServerQuests/configuration}/Config.java (81%) diff --git a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java index 094ecd9..52aecfa 100644 --- a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java +++ b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java @@ -70,7 +70,7 @@ public void onEnable() { registerPlaceholders(); if (!setupDecentHologram() && getConfig().getBoolean("hologram.enabled")) { getLogger().info("Warning! DecentHolograms not found, holograms will not work."); - } else { + } else if (getConfig().getBoolean("hologram.enabled")) { hologram = new DecentHologramsDisplay(this); hologram.displayHologram(); } @@ -149,7 +149,7 @@ private void registerQuestEvents() { getServer().getPluginManager().registerEvents(new ConsumeItemQuestEvent(activeQuests), this); getServer().getPluginManager().registerEvents(new EnchantItemQuestEvent(activeQuests), this); getServer().getPluginManager().registerEvents(new DistanceTraveled(activeQuests), this); - getServer().getPluginManager().registerEvents(new InventoryClickEvents(activeQuests), this); + getServer().getPluginManager().registerEvents(new InventoryClickEvents(activeQuests, this), this); getServer().getPluginManager().registerEvents(new RewardJoinListener(true), this); try { getServer().getPluginManager().registerEvents(new ExperienceEvent(activeQuests), this); diff --git a/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java index 38f083e..de3cb26 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java @@ -4,7 +4,6 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.gui.ViewHistoryMenu; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -27,7 +26,6 @@ public HistoryCommand(ServerQuests plugin) { @Override public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { Player player = (Player) sender; - Bukkit.getLogger().info("History command executed by " + player.getName()); new ViewHistoryMenu(getPlugin(), player).open(); } } diff --git a/src/main/java/me/knighthat/apis/files/Config.java b/src/main/java/me/wonka01/ServerQuests/configuration/Config.java similarity index 81% rename from src/main/java/me/knighthat/apis/files/Config.java rename to src/main/java/me/wonka01/ServerQuests/configuration/Config.java index bcfe5e5..c1f3239 100644 --- a/src/main/java/me/knighthat/apis/files/Config.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/Config.java @@ -1,9 +1,11 @@ -package me.knighthat.apis.files; +package me.wonka01.ServerQuests.configuration; import lombok.Getter; import lombok.NonNull; +import me.knighthat.apis.files.Getters; import me.wonka01.ServerQuests.ServerQuests; -import me.wonka01.ServerQuests.configuration.QuestLibrary; +import me.wonka01.ServerQuests.events.BreakEvent; +import me.wonka01.ServerQuests.events.PlaceEvent; import me.wonka01.ServerQuests.gui.DonateMenu; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.bossbar.BarManager; @@ -40,6 +42,9 @@ public void initializeVariables() { borderMaterial = Material.BLACK_STAINED_GLASS_PANE; } DonateMenu.setBorderItem(new ItemStack(borderMaterial)); + + PlaceEvent.setDisableDuplicatePlaces(get().getBoolean("disableDuplicatePlaces", false)); + BreakEvent.setDisableDuplicateBreaks(get().getBoolean("disableDuplicateBreaks", false)); } public void initializeQuests() { diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java index 957adc9..ddb7164 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestHistoryManager.java @@ -18,6 +18,8 @@ public class QuestHistoryManager { private final File historyFile; private final Logger logger; + + // TODO: move to config private static final int MAX_HISTORY_ENTRIES = 50; public QuestHistoryManager(ServerQuests plugin, File dataFolder) { @@ -41,22 +43,20 @@ public void saveCompletedQuest(String questId, String questName, Map { double total1 = e1.getValue().getAmountContributed(); double total2 = e2.getValue().getAmountContributed(); - return Double.compare(total2, total1); // Sort descending + return Double.compare(total2, total1); }) - .limit(10) // Store only top 10 players + .limit(10) // TODO - read from leaderboard size config .forEach(entry -> { JSONObject playerInfo = new JSONObject(); playerInfo.put("uuid", entry.getKey().toString()); @@ -67,8 +67,7 @@ public void saveCompletedQuest(String questId, String questName, Map MAX_HISTORY_ENTRIES) { historyArray.remove(historyArray.size() - 1); } diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index 383ad95..f0a06b6 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -14,7 +14,6 @@ import org.bukkit.Material; import org.bukkit.boss.BarStyle; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.plugin.java.JavaPlugin; import java.util.*; import java.util.stream.Collectors; @@ -232,9 +231,9 @@ private ArrayList getRewardsFromConfig(ConfigurationSection section) { reward = new ItemReward(amount, material, itemName); rewards.add(reward); } catch (Exception ex) { - JavaPlugin.getPlugin(ServerQuests.class).getLogger() + Bukkit.getLogger() .info("Item reward failed to load due to invalid configuration"); - JavaPlugin.getPlugin(ServerQuests.class).getLogger() + Bukkit.getLogger() .info(ex.getMessage()); } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java b/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java index 4ba0303..560d0bf 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/BreakEvent.java @@ -16,13 +16,17 @@ import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.java.JavaPlugin; +import lombok.Setter; + import java.util.List; public class BreakEvent extends QuestListener implements Listener { + @Setter + private static boolean disableDuplicateBreaks = true; + private final String BROKEN = "BROKEN"; private final MetadataValue meta = new FixedMetadataValue(JavaPlugin.getPlugin(ServerQuests.class), true); - private boolean disableDuplicateBreaks = true; public BreakEvent(ActiveQuests activeQuests) { super(activeQuests); @@ -51,8 +55,8 @@ public void onBlockBreakEvent(BlockBreakEvent event) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.BLOCK_BREAK); + block.setMetadata(BROKEN, meta); for (QuestController controller : controllers) { - block.setMetadata(BROKEN, meta); updateQuest(controller, event.getPlayer(), 1, ObjectiveType.BLOCK_BREAK, block.getType()); } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java b/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java index ea573fe..7db38c5 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/EnchantItemQuestEvent.java @@ -23,7 +23,7 @@ public void onEnchantItem(EnchantItemEvent event) { List controllers = tryGetControllersOfObjectiveType(ObjectiveType.ENCHANT_ITEM); for (QuestController controller : controllers) { - updateQuest(controller, player, 1, ObjectiveType.ENCHANT_ITEM, event.getItem()); + updateQuest(controller, player, 1, ObjectiveType.ENCHANT_ITEM, event.getItem(), event.getEnchantsToAdd()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java index 4d309c9..7c0b131 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java +++ b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java @@ -1,8 +1,10 @@ package me.wonka01.ServerQuests.events; import java.util.List; +import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -11,8 +13,12 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; +import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; @@ -20,9 +26,31 @@ public class InventoryClickEvents extends QuestListener implements Listener { private final ObjectiveType BREW_TYPE = ObjectiveType.BREW_POTION; + private ServerQuests plugin; - public InventoryClickEvents(ActiveQuests activeQuests) { + public InventoryClickEvents(ActiveQuests activeQuests, ServerQuests plugin) { super(activeQuests); + this.plugin = plugin; + } + + private void markItemAsUnique(ItemStack item) { + ItemMeta meta = item.getItemMeta(); + PersistentDataContainer container = meta.getPersistentDataContainer(); + NamespacedKey uniqueKey = new NamespacedKey(plugin, "processed"); + container.set(uniqueKey, PersistentDataType.STRING, UUID.randomUUID().toString()); + item.setItemMeta(meta); + } + + private boolean isItemProcessed(ItemStack item) { + if (item == null || !item.hasItemMeta()) + return false; + + ItemMeta meta = item.getItemMeta(); + PersistentDataContainer container = meta.getPersistentDataContainer(); + + NamespacedKey uniqueKey = new NamespacedKey(plugin, "processed"); + + return container.has(uniqueKey, PersistentDataType.STRING); } @EventHandler @@ -47,9 +75,11 @@ public void onInventoryClick(InventoryClickEvent event) { return; } - Bukkit.getLogger() - .info("PotionMeta is not null for item " + potionMeta.getBasePotionData().getType().name()); + if (isItemProcessed(item)) { + return; + } + markItemAsUnique(item); for (QuestController controller : controllers) { updateQuest(controller, player, 1, ObjectiveType.BREW_POTION, potionMeta.getBasePotionData().getType()); diff --git a/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java b/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java index 078bb86..815d5d2 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/PlaceEvent.java @@ -14,13 +14,17 @@ import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.java.JavaPlugin; +import lombok.Setter; + import java.util.List; public class PlaceEvent extends QuestListener implements Listener { + @Setter + private static boolean disableDuplicatePlaces; + private final String PLACED = "PLACED"; private final MetadataValue meta = new FixedMetadataValue(JavaPlugin.getPlugin(ServerQuests.class), true); - private boolean disableDuplicatePlaces; public PlaceEvent(ActiveQuests activeQuests) { super(activeQuests); @@ -40,10 +44,9 @@ public void onBlockPlace(BlockPlaceEvent event) { } List controllers = tryGetControllersOfObjectiveType(ObjectiveType.BLOCK_PLACE); - + block.setMetadata(PLACED, meta); for (QuestController controller : controllers) { updateQuest(controller, event.getPlayer(), 1, ObjectiveType.BLOCK_PLACE, block.getType()); - block.setMetadata(PLACED, meta); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java b/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java index c3f9d87..fac0f3b 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/ProjectileKillEvent.java @@ -1,6 +1,5 @@ package me.wonka01.ServerQuests.events; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; diff --git a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java index 753061b..2677263 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java +++ b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java @@ -5,9 +5,9 @@ import me.wonka01.ServerQuests.objectives.ObjectiveFilters; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; -import me.wonka01.ServerQuests.questcomponents.QuestData; import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -15,7 +15,9 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +// TODO - rename updateQuest functions to be specific to their type public abstract class QuestListener { protected ActiveQuests activeQuests; @@ -33,8 +35,7 @@ protected boolean updateQuest(QuestController controller, Player player, double // General quests without filters protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type) { - QuestData questData = controller.getQuestData(); - List objectives = questData.getObjectives(); + List objectives = controller.getQuestData().getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); if (objective.getType().equals(type)) { @@ -46,8 +47,7 @@ protected void updateQuest(QuestController controller, Player player, double amo // Mob quests protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, Entity entity) { - QuestData questData = controller.getQuestData(); - List objectives = questData.getObjectives(); + List objectives = controller.getQuestData().getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); boolean matches = ObjectiveFilters.filter() @@ -76,8 +76,7 @@ protected void updateQuest(QuestController controller, Player player, double amo // Mob quests with entity as a string protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, String entity) { - QuestData questData = controller.getQuestData(); - List objectives = questData.getObjectives(); + List objectives = controller.getQuestData().getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); boolean matches = ObjectiveFilters.filter() @@ -94,12 +93,30 @@ protected void updateQuest(QuestController controller, Player player, double amo // Potion quests protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, PotionType potion) { - QuestData questData = controller.getQuestData(); - List objectives = questData.getObjectives(); + List objectives = controller.getQuestData().getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); boolean matches = ObjectiveFilters.filter() - .withEntity(potion.name()) + .withPotion(potion) + .withType(type) + .matches(objective); + + if (matches) { + updateQuest(controller, player, amount, objective, i); + } + } + } + + // enchantment quests + protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, + ItemStack item, + Map enchantments) { + List objectives = controller.getQuestData().getObjectives(); + for (int i = 0; i < objectives.size(); i++) { + Objective objective = objectives.get(i); + boolean matches = ObjectiveFilters.filter() + .withMaterial(item.getType()) // only check material bc of how we're using customItem names atm + .withEnchantments(enchantments) .withType(type) .matches(objective); @@ -112,8 +129,7 @@ protected void updateQuest(QuestController controller, Player player, double amo // Block quests protected void updateQuest(QuestController controller, Player player, double amount, ObjectiveType type, Material material) { - QuestData questData = controller.getQuestData(); - List objectives = questData.getObjectives(); + List objectives = controller.getQuestData().getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); boolean matches = ObjectiveFilters.filter() @@ -130,8 +146,7 @@ protected void updateQuest(QuestController controller, Player player, double amo // Item quests protected void updateQuest(QuestController controller, Player player, int amount, ObjectiveType type, ItemStack item) { - QuestData questData = controller.getQuestData(); - List objectives = questData.getObjectives(); + List objectives = controller.getQuestData().getObjectives(); for (int i = 0; i < objectives.size(); i++) { Objective objective = objectives.get(i); boolean matches = ObjectiveFilters.filter() diff --git a/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java index 912fbae..006ae1c 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java @@ -20,9 +20,8 @@ public class ViewHistoryMenu extends Menu { private final QuestHistoryManager historyManager; public ViewHistoryMenu(ServerQuests plugin, Player owner) { - super(plugin, owner, "questHistory", 54); // Use full chest inventory + super(plugin, owner, "historyMenu", 54); // Use full chest inventory this.historyManager = plugin.getQuestHistoryManager(); - Bukkit.getLogger().info("ViewHistoryMenu created"); } @Override @@ -33,8 +32,6 @@ protected void setContents() { Map questData = recentQuests.get(i); // Choose material based on quest type - String displayItem = (String) questData.get("displayItem"); - Bukkit.getLogger().info("Material: " + displayItem); Material material = Material.valueOf((String) questData.get("displayItem")); ItemStack questItem = createQuestHistoryItem(material, questData); getInventory().setItem(i, questItem); @@ -48,9 +45,9 @@ private ItemStack createQuestHistoryItem(Material material, Map long completionTime = (Long) questData.get("completionTime"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); - lore.add(color("&7Completed: &f" + sdf.format(new Date(completionTime)))); + lore.add(color(getPlugin().messages().string("completed") + "&f" + sdf.format(new Date(completionTime)))); - lore.add(color("&eTop Contributors:")); + lore.add(color(getPlugin().messages().string("topContributors"))); List topContributors = (List) questData.get("topContributors"); for (int i = 0; i < Math.min(topContributors.size(), 5); i++) { Map contributor = (Map) topContributors.get(i); diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java index ad972f5..a02c23f 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -3,11 +3,14 @@ import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; +import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionType; +import java.util.Map; import java.util.function.Predicate; public class ObjectiveFilters { @@ -21,6 +24,7 @@ public static class Builder { private String customName; private Integer customModelId; private ObjectiveType type; + private Map enchantments; public Builder withMaterial(Material material) { this.material = material; @@ -47,6 +51,13 @@ public Builder withPotion(PotionType potion) { return this; } + public Builder withEnchantments(Map enchantments) { + if (enchantments != null) { + this.enchantments = enchantments; + } + return this; + } + public Builder withEntity(Entity entity) { if (entity != null) { this.entity = entity.getType().name(); @@ -59,8 +70,7 @@ public Builder withEntity(Entity entity) { return this; } - // option to define with string for fishing/mythic mobs where entity is not - // needed + // option to define with string for fishing/mythic mobs public Builder withEntity(String entity) { this.entity = entity; return this; @@ -85,10 +95,7 @@ public Builder withCustomModelId(Integer customModelId) { public boolean matches(Objective objective) { // Material filter if (material != null) { - if (objective.getMaterials().isEmpty()) { - return false; - } - if (!objective.getMaterials().contains(material)) { + if (!objective.getMaterials().contains(material) && !objective.getMaterials().isEmpty()) { return false; } } @@ -101,20 +108,14 @@ public boolean matches(Objective objective) { // Mob name filter if (entity != null) { - if (objective.getMobNames().isEmpty()) { - return false; - } - if (!Utils.contains(objective.getMobNames(), entity)) { + if (!Utils.contains(objective.getMobNames(), entity) && !objective.getMobNames().isEmpty()) { return false; } } // Custom name filter if (customName != null) { - if (objective.getCustomNames().isEmpty()) { - return false; - } - if (!Utils.contains(objective.getCustomNames(), customName)) { + if (!Utils.contains(objective.getCustomNames(), customName) && !objective.getCustomNames().isEmpty()) { return false; } } @@ -126,6 +127,25 @@ public boolean matches(Objective objective) { } } + // Enchantment filter + if (enchantments != null) { + // enchantments stored in customNames for now + boolean containsOne = false; + Bukkit.getLogger().info("Checking enchantments of size " + enchantments.size()); + for (Map.Entry entry : enchantments.entrySet()) { + String enchantmentName = entry.getKey().getKey().toString(); + Bukkit.getLogger().info("Checking enchantment named " + enchantmentName); + if (Utils.contains(objective.getCustomNames(), enchantmentName)) { + containsOne = true; + break; + } + } + + if (!containsOne && !objective.getCustomNames().isEmpty()) { + return false; + } + } + return true; } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java index c4d79fe..bf15caa 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java @@ -100,7 +100,8 @@ public void endQuest() { } else { broadcast("questCompleteMessage"); playerComponent.sendLeaderString(); - playerComponent.giveOutRewards(questData.getQuestGoal()); + String completeMessage = color(plugin.messages().message("questCompleteMessage", questData)); + playerComponent.giveOutRewards(questData.getQuestGoal(), completeMessage); if (questData.getAfterQuestCommand() != null && !questData.getAfterQuestCommand().isEmpty()) { plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), questData.getAfterQuestCommand()); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java index d53cf84..9e31e87 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java @@ -4,6 +4,7 @@ import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; +import me.wonka01.ServerQuests.questcomponents.rewards.RewardMessage; import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; import org.bukkit.Bukkit; @@ -160,7 +161,7 @@ public JSONArray toJSONArray() { return jArray; } - public void giveOutRewards(double questGoal) { + public void giveOutRewards(double questGoal, String completeMessage) { List players; if (rewardsLimit > 0) { players = getTopPlayers(rewardsLimit); @@ -191,19 +192,24 @@ public void giveOutRewards(double questGoal) { } OfflinePlayer player = Bukkit.getServer().getOfflinePlayer(playerData.getUuid()); + RewardManager rewardManager = RewardManager.getInstance(); if (player.isOnline()) { Player onlinePlayer = (Player) player; if (rankedReward.size() > 0) { - ServerQuests plugin = JavaPlugin.getPlugin(ServerQuests.class); - String rewardsMessage = plugin.messages().message("rewardsMessage"); - onlinePlayer.sendMessage(rewardsMessage); + // ServerQuests plugin = JavaPlugin.getPlugin(ServerQuests.class); + // String rewardsMessage = plugin.messages().message("rewardsMessage"); + onlinePlayer.sendMessage("rewards size " + rankedReward.size()); + for (Reward reward : rankedReward) { + reward.giveRewardToPlayer(onlinePlayer, playerContributionRatio); + } + } + } else { + RewardMessage rewardMessage = new RewardMessage(completeMessage); + rewardManager.addReward(player.getUniqueId(), rewardMessage, playerContributionRatio); + for (Reward reward : rankedReward) { + rewardManager.addReward(player.getUniqueId(), reward, playerContributionRatio); } - } - - RewardManager rewardManager = RewardManager.getInstance(); - for (Reward reward : rankedReward) { - rewardManager.addReward(player.getUniqueId(), reward, playerContributionRatio); } } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index db61800..488fd3b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -8,14 +8,11 @@ leaderBoardSize: 5 disableBossBar: false # Material used in the donate quest menu. -donateMenuItem: EMERALD +donateMenuItem: BLACK_STAINED_GLASS_PANE # If true, blockbreak quests will not be able to break the same item multiple # times in a row. disableDuplicateBreaks: false - -barColor: "GREEN" - # If true, blockplace quests will not be able to place the same item multiple # times in a row. disableDuplicatePlaces: false diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index e6342a4..5bada2d 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -43,6 +43,7 @@ you: "&fYou" leader: "&n&7Leader" progress: "&bProgress" topContributors: "&6Top Contributors" +completed: "&7Completed:" # GUI titles viewQuests: "Active Quests" @@ -50,6 +51,7 @@ startQuest: "Begin Quest Menu" stopQuest: "End Quest Menu" typeMenu: "Select an Event Type" donateMenu: "Place item in the center slot!" +historyMenu: "&7Quest History" endQuestText: "&eClick to end the quest" goBack: "&cGo Back" From 4d1a2aeabddc8baedebc177dfb7b3f16857743a1 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sat, 30 Nov 2024 19:05:40 +0000 Subject: [PATCH 09/20] Update ServerQuests.java --- src/main/java/me/wonka01/ServerQuests/ServerQuests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java index 52aecfa..2bcd8c6 100644 --- a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java +++ b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java @@ -2,10 +2,10 @@ import lombok.Getter; import lombok.NonNull; -import me.knighthat.apis.files.Config; import me.knighthat.apis.files.Messages; import me.knighthat.apis.menus.MenuEvents; import me.wonka01.ServerQuests.commands.CommandManager; +import me.wonka01.ServerQuests.configuration.Config; import me.wonka01.ServerQuests.configuration.JsonQuestSave; import me.wonka01.ServerQuests.configuration.QuestHistoryManager; import me.wonka01.ServerQuests.events.*; From 1d1fed1439e4e743d9928aebb72653b13fe52ccb Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sat, 30 Nov 2024 19:46:56 +0000 Subject: [PATCH 10/20] cut enchantments string --- .../me/wonka01/ServerQuests/configuration/QuestLibrary.java | 1 - .../me/wonka01/ServerQuests/objectives/ObjectiveFilters.java | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index f0a06b6..a6cdfab 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -1,6 +1,5 @@ package me.wonka01.ServerQuests.configuration; -import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; import me.wonka01.ServerQuests.questcomponents.rewards.*; diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java index a02c23f..c7441b1 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -131,11 +131,10 @@ public boolean matches(Objective objective) { if (enchantments != null) { // enchantments stored in customNames for now boolean containsOne = false; - Bukkit.getLogger().info("Checking enchantments of size " + enchantments.size()); for (Map.Entry entry : enchantments.entrySet()) { String enchantmentName = entry.getKey().getKey().toString(); Bukkit.getLogger().info("Checking enchantment named " + enchantmentName); - if (Utils.contains(objective.getCustomNames(), enchantmentName)) { + if (Utils.contains(objective.getCustomNames(), enchantmentName.replace("minecraft:", ""))) { containsOne = true; break; } From 5e371fd542e55dd904d27a90f0fddd81ccae5cb8 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sun, 1 Dec 2024 09:55:05 +0000 Subject: [PATCH 11/20] fix double schedule, code cleanup and finalize quest filter testing --- .../ServerQuests/commands/QuestScheduler.java | 6 +++++- .../wonka01/ServerQuests/events/QuestListener.java | 2 +- .../me/wonka01/ServerQuests/gui/DonateMenu.java | 2 +- .../ServerQuests/objectives/ObjectiveFilters.java | 6 ++---- .../questcomponents/EventConstraints.java | 14 -------------- .../questcomponents/QuestController.java | 6 +++--- .../questcomponents/QuestTypeHandler.java | 3 +-- 7 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 src/main/java/me/wonka01/ServerQuests/questcomponents/EventConstraints.java diff --git a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java index 8a95dc4..ff5f1a3 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java @@ -271,7 +271,11 @@ public void run() { } }; - // Schedule the task + // reset if exists + if (activeSchedules.containsKey(scheduleId)) { + activeSchedules.get(scheduleId).cancel(); + } + task.runTaskTimer(plugin, initialDelayTicks, intervalTicks); activeSchedules.put(scheduleId.toString(), task); } diff --git a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java index 2677263..89ac5fe 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java +++ b/src/main/java/me/wonka01/ServerQuests/events/QuestListener.java @@ -27,7 +27,7 @@ public QuestListener(ActiveQuests activeQuests) { protected boolean updateQuest(QuestController controller, Player player, double amount, Objective obj, int objectiveId) { - if (!isEnabledInWorld(controller.getEventConstraints().getWorlds(), player.getWorld().getName())) { + if (!isEnabledInWorld(controller.getWorlds(), player.getWorld().getName())) { return false; } return controller.updateQuest(amount, player, obj, objectiveId); diff --git a/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java index 2ea38ce..d9219f4 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java @@ -168,7 +168,7 @@ private boolean updateQuest(@NonNull QuestController ctrl, @NonNull ItemStack it } private boolean isWorldAllowed(@NonNull QuestController ctrl, @NonNull World world) { - List worlds = ctrl.getEventConstraints().getWorlds(); + List worlds = ctrl.getWorlds(); return worlds.isEmpty() || Utils.contains(worlds, world.getName()); } } diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java index c7441b1..172d61c 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -95,7 +95,7 @@ public Builder withCustomModelId(Integer customModelId) { public boolean matches(Objective objective) { // Material filter if (material != null) { - if (!objective.getMaterials().contains(material) && !objective.getMaterials().isEmpty()) { + if (!Utils.contains(objective.getMaterials(), material) && !objective.getMaterials().isEmpty()) { return false; } } @@ -122,18 +122,16 @@ public boolean matches(Objective objective) { // Custom model ID filter if (customModelId != null) { - if (!hasCustomModelId(objective, customModelId)) { + if (!hasCustomModelId(objective, customModelId) && !objective.getCustomModelIds().isEmpty()) { return false; } } // Enchantment filter if (enchantments != null) { - // enchantments stored in customNames for now boolean containsOne = false; for (Map.Entry entry : enchantments.entrySet()) { String enchantmentName = entry.getKey().getKey().toString(); - Bukkit.getLogger().info("Checking enchantment named " + enchantmentName); if (Utils.contains(objective.getCustomNames(), enchantmentName.replace("minecraft:", ""))) { containsOne = true; break; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/EventConstraints.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/EventConstraints.java deleted file mode 100644 index 2dabc98..0000000 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/EventConstraints.java +++ /dev/null @@ -1,14 +0,0 @@ -package me.wonka01.ServerQuests.questcomponents; - -import lombok.Getter; - -import java.util.List; - -@Getter -public class EventConstraints { - private final List worlds; - - public EventConstraints(List worlds) { - this.worlds = worlds; - } -} diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java index bf15caa..9503bf6 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java @@ -23,18 +23,18 @@ public class QuestController implements Colorization { private final QuestBar questBar; private final QuestData questData; private final BasePlayerComponent playerComponent; - private final EventConstraints eventConstraints; + private final List worlds; private final UUID questId; private final ServerQuests plugin; public QuestController(ServerQuests plugin, QuestData questData, QuestBar questBar, - BasePlayerComponent playerComponent, EventConstraints eventConstraints) { + BasePlayerComponent playerComponent, List worlds) { this.plugin = plugin; this.questData = questData; this.questBar = questBar; this.playerComponent = playerComponent; questId = UUID.randomUUID(); - this.eventConstraints = eventConstraints; + this.worlds = worlds; if (questData.getQuestDuration() > 0) { new QuestTimer(this); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java index d8e718d..5e5e4f9 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java @@ -62,13 +62,12 @@ public QuestController createControllerFromSave(@NonNull QuestModel model, @NonN } QuestData data = getQuestData(model, pComponent, timeLeft, objs); - EventConstraints event = new EventConstraints(model.getWorlds()); if (data.getAmountCompleted() > 0) { bar.updateBarProgress(data.getAmountCompleted() / data.getQuestGoal()); } - return new QuestController(plugin, data, bar, pComponent, event); + return new QuestController(plugin, data, bar, pComponent, model.getWorlds()); } private QuestData getQuestData(QuestModel questModel, BasePlayerComponent playerComponent, From 70c054cb3c28fc3eda8104bb22b74a3de7a36aeb Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sun, 1 Dec 2024 19:25:55 +0000 Subject: [PATCH 12/20] add more tab completes --- .../ServerQuests/commands/ClaimRewards.java | 9 ++ .../commands/ClearRewardsCommand.java | 8 ++ .../ServerQuests/commands/CommandManager.java | 13 ++- .../ServerQuests/commands/DonateCommand.java | 7 ++ .../ServerQuests/commands/EndAllCommand.java | 9 ++ .../ServerQuests/commands/HelpCommand.java | 10 +++ .../ServerQuests/commands/HistoryCommand.java | 9 ++ .../ServerQuests/commands/MoneyCommand.java | 9 ++ .../ServerQuests/commands/PluginCommand.java | 7 ++ .../ServerQuests/commands/QuestCommand.java | 47 +++++++++++ .../ServerQuests/commands/QuestScheduler.java | 84 +++++++++++++++++++ .../ServerQuests/commands/ReloadCommand.java | 10 +++ .../ServerQuests/commands/RewardsCommand.java | 9 ++ .../ServerQuests/commands/StartCommand.java | 30 +++++++ .../ServerQuests/commands/StopCommand.java | 9 ++ .../commands/ToggleBarCommand.java | 9 ++ .../commands/ToggleMessageCommand.java | 44 ---------- .../ServerQuests/commands/ViewCommand.java | 9 ++ .../configuration/QuestLibrary.java | 4 + .../ServerQuests/enums/ObjectiveType.java | 1 + 20 files changed, 292 insertions(+), 45 deletions(-) create mode 100644 src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java delete mode 100644 src/main/java/me/wonka01/ServerQuests/commands/ToggleMessageCommand.java diff --git a/src/main/java/me/wonka01/ServerQuests/commands/ClaimRewards.java b/src/main/java/me/wonka01/ServerQuests/commands/ClaimRewards.java index c5657f8..397f5ff 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/ClaimRewards.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/ClaimRewards.java @@ -5,7 +5,10 @@ import me.wonka01.ServerQuests.questcomponents.rewards.RewardEntry; import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; +import java.util.List; + import org.bukkit.Bukkit; +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -75,4 +78,10 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar rewards.removeRewards(player.getUniqueId()); } } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/ClearRewardsCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/ClearRewardsCommand.java index 580bd4e..144385b 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/ClearRewardsCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/ClearRewardsCommand.java @@ -1,6 +1,9 @@ package me.wonka01.ServerQuests.commands; +import java.util.List; + import org.bukkit.Bukkit; +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -57,4 +60,9 @@ public void execute(CommandSender sender, String[] args) { } } + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java b/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java index f07c003..f03499a 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/CommandManager.java @@ -36,7 +36,6 @@ public CommandManager(ServerQuests plugin) { commands.add(new DonateCommand(plugin)); commands.add(new MoneyCommand(plugin)); commands.add(new ToggleBarCommand(plugin)); - commands.add(new ToggleMessageCommand(plugin)); commands.add(new RewardsCommand(plugin)); commands.add(new EndAllCommand(plugin)); commands.add(new ClaimRewards(plugin)); @@ -73,6 +72,18 @@ public List onTabComplete(CommandSender sender, Command command, String } } } + + if (args.length > 1) { + for (PluginCommand cmd : commands) { + if (cmd.getName().equalsIgnoreCase(args[0])) { + // Check if the command implements a tab complete method + List comps = cmd.onTabComplete(sender, command, alias, args); + if (comps != null) + return comps; + break; + } + } + } return completions; } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/DonateCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/DonateCommand.java index 16260df..1504146 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/DonateCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/DonateCommand.java @@ -8,6 +8,7 @@ import me.wonka01.ServerQuests.questcomponents.QuestController; import org.bukkit.Bukkit; +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -71,4 +72,10 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar player.sendMessage(noActiveQuest); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/EndAllCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/EndAllCommand.java index ac0e144..b877f5a 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/EndAllCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/EndAllCommand.java @@ -4,6 +4,9 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -28,4 +31,10 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar ActiveQuests.getActiveQuestsInstance().endAllQuests(); sender.sendMessage(getPlugin().messages().message("endAllQuestsMessage")); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/HelpCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/HelpCommand.java index 7a1e483..be49b96 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/HelpCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/HelpCommand.java @@ -2,6 +2,10 @@ import lombok.NonNull; import me.wonka01.ServerQuests.ServerQuests; + +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -25,4 +29,10 @@ public HelpCommand(ServerQuests plugin) { public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { sender.sendMessage(getPlugin().messages().message("helpMessage")); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java index de3cb26..cc6cec7 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/HistoryCommand.java @@ -4,6 +4,9 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.gui.ViewHistoryMenu; +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -28,4 +31,10 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar Player player = (Player) sender; new ViewHistoryMenu(getPlugin(), player).open(); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/MoneyCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/MoneyCommand.java index 9f1f75a..8f8ecd6 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/MoneyCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/MoneyCommand.java @@ -4,6 +4,10 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.events.MoneyQuest; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; + +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -47,4 +51,9 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar player.sendMessage(message); } } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java index bec4acd..1b2dd14 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java @@ -4,6 +4,10 @@ import lombok.NonNull; import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; + +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @Getter @@ -22,4 +26,7 @@ protected PluginCommand(ServerQuests plugin, boolean playerCommand) { public abstract @NonNull String getPermission(); public abstract void execute(@NonNull CommandSender sender, @NonNull String[] args); + + public abstract List onTabComplete(CommandSender sender, Command command, String alias, String[] args); + } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java new file mode 100644 index 0000000..778ea92 --- /dev/null +++ b/src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java @@ -0,0 +1,47 @@ +package me.wonka01.ServerQuests.commands; + +import lombok.NonNull; +import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.gui.ViewMenu; +import me.wonka01.ServerQuests.questcomponents.ActiveQuests; + +import java.util.List; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class QuestCommand extends PluginCommand { + public QuestCommand(ServerQuests plugin) { + super(plugin, true); + } + + @Override + public @NonNull String getName() { + return "quest"; + } + + @Override + public @NonNull String getPermission() { + return "communityquests.start"; + } + + @Override + public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { + Player player = (Player) sender; + + if (ActiveQuests.getActiveQuestsInstance().getActiveQuestsList().isEmpty()) { + String noActiveQuestMessage = getPlugin().messages().message("noActiveQuests"); + player.sendMessage(noActiveQuestMessage); + return; + } + new ViewMenu(getPlugin(), player).open(); + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java index ff5f1a3..3eb53a7 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java @@ -1,6 +1,7 @@ package me.wonka01.ServerQuests.commands; import org.bukkit.Bukkit; +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -9,6 +10,7 @@ import lombok.NonNull; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.configuration.QuestModel; import java.io.File; import java.io.IOException; @@ -17,9 +19,13 @@ import java.time.temporal.ChronoUnit; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; public class QuestScheduler extends PluginCommand { private final ServerQuests plugin; @@ -292,4 +298,82 @@ public void shutdown() { public @NonNull String getPermission() { return "communityquests.schedule"; } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + List completions = new ArrayList<>(); + + // Argument count determines the type of completions + switch (args.length) { + case 2: + // Quest ID completions + List questIds = new ArrayList<>(plugin.config().getQuestLibrary().getAllQuestModels() + .stream() + .map(QuestModel::getQuestId) + .collect(Collectors.toList())); + questIds.add("random"); // Add 'random' as a special option + completions = questIds.stream() + .filter(id -> id.toLowerCase().startsWith(args[1].toLowerCase())) + .collect(Collectors.toList()); + break; + + case 3: + // Mode completions + List modes = Arrays.asList("coop", "comp"); + completions = modes.stream() + .filter(mode -> mode.startsWith(args[2].toLowerCase())) + .collect(Collectors.toList()); + break; + + case 4: + // Time format suggestions + completions = Arrays.asList("00:00", "12:00", "14:30", "18:00", "20:00"); + completions = completions.stream() + .filter(time -> time.startsWith(args[3])) + .collect(Collectors.toList()); + break; + + case 5: + // Schedule type completions + List scheduleTypes = Arrays.stream(ScheduleType.values()) + .map(Enum::name) + .collect(Collectors.toList()); + completions = scheduleTypes.stream() + .filter(type -> type.toLowerCase().startsWith(args[4].toLowerCase())) + .collect(Collectors.toList()); + break; + + case 6: + // Action completions + List actions = Arrays.asList("add", "remove"); + completions = actions.stream() + .filter(action -> action.startsWith(args[5].toLowerCase())) + .collect(Collectors.toList()); + break; + + case 7: + // Conditional completions based on previous arguments + if (args[4].toUpperCase().equals("WEEKLY")) { + // Day of week suggestions + completions = Arrays.stream(DayOfWeek.values()) + .map(Enum::name) + .filter(day -> day.toLowerCase().startsWith(args[6].toLowerCase())) + .collect(Collectors.toList()); + } else if (args[4].toUpperCase().equals("CUSTOM_DAYS")) { + // Interval suggestions + completions = Arrays.asList("1", "2", "3", "7", "14", "30"); + completions = completions.stream() + .filter(interval -> interval.startsWith(args[6])) + .collect(Collectors.toList()); + } else if (args[5].toLowerCase().equals("remove")) { + // If removing, suggest existing schedule IDs + completions = new ArrayList<>(activeSchedules.keySet()).stream() + .filter(id -> id.toLowerCase().startsWith(args[6].toLowerCase())) + .collect(Collectors.toList()); + } + break; + } + + return completions; + } } \ No newline at end of file diff --git a/src/main/java/me/wonka01/ServerQuests/commands/ReloadCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/ReloadCommand.java index 562641c..b9b8a83 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/ReloadCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/ReloadCommand.java @@ -2,6 +2,10 @@ import lombok.NonNull; import me.wonka01.ServerQuests.ServerQuests; + +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -42,4 +46,10 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar String reloadMessage = getPlugin().messages().message("reloadCommand"); sender.sendMessage(reloadMessage); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/RewardsCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/RewardsCommand.java index 3354c56..3e6e123 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/RewardsCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/RewardsCommand.java @@ -5,6 +5,9 @@ import me.wonka01.ServerQuests.gui.RewardsMenu; import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -35,4 +38,10 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar } new RewardsMenu(getPlugin(), player).open(); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java index bb24181..d415ec0 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java @@ -7,6 +7,12 @@ import me.wonka01.ServerQuests.gui.StartMenu; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -62,4 +68,28 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar new StartMenu(getPlugin(), (Player) sender).open(); } } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + List completions = new ArrayList<>(); + + if (args.length == 2) { + // Fetch all available quest models and filter based on partial input + List questModels = getPlugin().config().getQuestLibrary().getAllQuestModels(); + completions = questModels.stream() + .map(QuestModel::getQuestId) + .filter(id -> id.toLowerCase().startsWith(args[1].toLowerCase())) + .collect(Collectors.toList()); + } + + // Handle quest type completions (third argument) + if (args.length == 3) { + List questTypes = Arrays.asList("coop", "comp"); + completions = questTypes.stream() + .filter(type -> type.startsWith(args[2].toLowerCase())) + .collect(Collectors.toList()); + } + + return completions; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/StopCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/StopCommand.java index 697c743..fdfc73d 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/StopCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/StopCommand.java @@ -3,6 +3,10 @@ import lombok.NonNull; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.gui.StopMenu; + +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -26,4 +30,9 @@ public StopCommand(ServerQuests plugin) { public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { new StopMenu(getPlugin(), (Player) sender).open(); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/ToggleBarCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/ToggleBarCommand.java index f5f8a52..6cc4c34 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/ToggleBarCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/ToggleBarCommand.java @@ -3,6 +3,10 @@ import lombok.NonNull; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.bossbar.BarManager; + +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -27,4 +31,9 @@ public ToggleBarCommand(ServerQuests plugin) { public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { BarManager.toggleShowPlayerBar((Player) sender); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/commands/ToggleMessageCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/ToggleMessageCommand.java deleted file mode 100644 index 7d980ad..0000000 --- a/src/main/java/me/wonka01/ServerQuests/commands/ToggleMessageCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package me.wonka01.ServerQuests.commands; - -import lombok.NonNull; -import me.wonka01.ServerQuests.ServerQuests; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -public class ToggleMessageCommand extends PluginCommand { - - // public HashMap map = new HashMap(); - - public ToggleMessageCommand(ServerQuests plugin) { - super(plugin, true); - } - - @Override - public @NonNull String getName() { - return "togglemessage"; - } - - @Override - public @NonNull String getPermission() { - return "communityquests.showmessages"; - } - - @Override - public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { - - // PermissionAttachment attachment = - // player.addAttachment(JavaPlugin.getPlugin(ServerQuests.class)); - // if (player.hasPermission("serverquests.showmessages")) { - // attachment.setPermission("serverquests.showmessages", false); - // player.sendMessage(ChatColor.YELLOW + "You will no longer see server quest - // messages"); - // } else { - // attachment.setPermission("serverquests.showmessages", true); - // player.sendMessage(ChatColor.YELLOW + "You will now see server quest - // messages"); - // } - // - // map.put(player.getUniqueId(), attachment); - } -} diff --git a/src/main/java/me/wonka01/ServerQuests/commands/ViewCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/ViewCommand.java index deebbed..06329b6 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/ViewCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/ViewCommand.java @@ -4,6 +4,10 @@ import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.gui.ViewMenu; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; + +import java.util.List; + +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -34,4 +38,9 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar } new ViewMenu(getPlugin(), player).open(); } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + return null; + } } diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index a6cdfab..5333735 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -245,4 +245,8 @@ private ArrayList getRewardsFromConfig(ConfigurationSection section) { public Set getAllQuestKeys() { return questList.keySet(); } + + public List getAllQuestModels() { + return new ArrayList<>(questList.values()); + } } diff --git a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java index 849bfb3..d126f2e 100644 --- a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java +++ b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java @@ -28,6 +28,7 @@ public enum ObjectiveType { MOVEMENT("movement", Material.DIAMOND_BOOTS), BREW_POTION("brewpotion", Material.BREWING_STAND), SMELT_ITEM("smeltitem", Material.FURNACE), + COMMAND("command", Material.COMMAND_BLOCK), UNKNOWN("unknown", Material.AIR); @Getter From 8268380362864b207ae470697d4dd3b67d563f70 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Mon, 2 Dec 2024 21:56:05 +0000 Subject: [PATCH 13/20] add bStats --- .../me/wonka01/ServerQuests/ServerQuests.java | 25 + src/main/java/me/wonka01/bStats/Metrics.java | 915 ++++++++++++++++++ 2 files changed, 940 insertions(+) create mode 100644 src/main/java/me/wonka01/bStats/Metrics.java diff --git a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java index 2bcd8c6..ad3b870 100644 --- a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java +++ b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java @@ -15,9 +15,12 @@ import me.wonka01.ServerQuests.questcomponents.hologram.DecentHologramsDisplay; import me.wonka01.ServerQuests.questcomponents.rewards.RewardJoinListener; import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; +import me.wonka01.bStats.Metrics; import me.wonka01.placeholders.CommunityQuestsPlaceholders; import net.milkbowl.vault.economy.Economy; +import java.util.concurrent.Callable; + import org.bukkit.Bukkit; import org.bukkit.command.PluginCommand; import org.bukkit.plugin.RegisteredServiceProvider; @@ -80,6 +83,28 @@ public void onEnable() { RewardManager.getInstance().populateFromJsonFile(getDataFolder(), getLogger()); BossbarPlayerInfo.getInstance().loadFromJsonFile(getDataFolder()); questHistoryManager = new QuestHistoryManager(this, getDataFolder()); + + int pluginId = 24062; + + try { + Metrics metrics = new Metrics(this, pluginId); + metrics.addCustomChart(new Metrics.SingleLineChart("players", new Callable() { + @Override + public Integer call() throws Exception { + // (This is useless as there is already a player chart by default.) + return Bukkit.getOnlinePlayers().size(); + } + })); + metrics.addCustomChart(new Metrics.SingleLineChart("active_quests", new Callable() { + @Override + public Integer call() throws Exception { + // (This is useless as there is already a player chart by default.) + return ActiveQuests.getActiveQuestsInstance().getActiveQuestsList().size(); + } + })); + } catch (Exception e) { + getLogger().info("[Community Quests] Failed to submit metrics data for bstats"); + } getLogger().info("Plugin is enabled"); } diff --git a/src/main/java/me/wonka01/bStats/Metrics.java b/src/main/java/me/wonka01/bStats/Metrics.java new file mode 100644 index 0000000..5c8dba0 --- /dev/null +++ b/src/main/java/me/wonka01/bStats/Metrics.java @@ -0,0 +1,915 @@ + +/* + * This Metrics class was auto-generated and can be copied into your project if you are + * not using a build tool like Gradle or Maven for dependency management. + * + * IMPORTANT: You are not allowed to modify this class, except changing the package. + * + * Disallowed modifications include but are not limited to: + * - Remove the option for users to opt-out + * - Change the frequency for data submission + * - Obfuscate the code (every obfuscator should allow you to make an exception for specific files) + * - Reformat the code (if you use a linter, add an exception) + * + * Violations will result in a ban of your plugin and account from bStats. + */ +package me.wonka01.bStats; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.zip.GZIPOutputStream; +import javax.net.ssl.HttpsURLConnection; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public class Metrics { + + private final Plugin plugin; + + private final MetricsBase metricsBase; + + /** + * Creates a new Metrics instance. + * + * @param plugin Your plugin instance. + * @param serviceId The id of the service. It can be found at What is my + * plugin id? + */ + public Metrics(Plugin plugin, int serviceId) { + this.plugin = plugin; + // Get the config file + File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); + File configFile = new File(bStatsFolder, "config.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + if (!config.isSet("serverUuid")) { + config.addDefault("enabled", true); + config.addDefault("serverUuid", UUID.randomUUID().toString()); + config.addDefault("logFailedRequests", false); + config.addDefault("logSentData", false); + config.addDefault("logResponseStatusText", false); + // Inform the server owners about bStats + config + .options() + .header( + "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" + + "many people use their plugin and their total player count. It's recommended to keep bStats\n" + + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" + + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" + + "anonymous.") + .copyDefaults(true); + try { + config.save(configFile); + } catch (IOException ignored) { + } + } + // Load the data + boolean enabled = config.getBoolean("enabled", true); + String serverUUID = config.getString("serverUuid"); + boolean logErrors = config.getBoolean("logFailedRequests", false); + boolean logSentData = config.getBoolean("logSentData", false); + boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); + boolean isFolia = false; + try { + isFolia = Class.forName("io.papermc.paper.threadedregions.RegionizedServer") != null; + } catch (Exception e) { + } + metricsBase = new // See https://github.com/Bastian/bstats-metrics/pull/126 + // See https://github.com/Bastian/bstats-metrics/pull/126 + // See https://github.com/Bastian/bstats-metrics/pull/126 + // See https://github.com/Bastian/bstats-metrics/pull/126 + // See https://github.com/Bastian/bstats-metrics/pull/126 + // See https://github.com/Bastian/bstats-metrics/pull/126 + // See https://github.com/Bastian/bstats-metrics/pull/126 + MetricsBase( + "bukkit", + serverUUID, + serviceId, + enabled, + this::appendPlatformData, + this::appendServiceData, + isFolia + ? null + : submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask), + plugin::isEnabled, + (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), + (message) -> this.plugin.getLogger().log(Level.INFO, message), + logErrors, + logSentData, + logResponseStatusText, + false); + } + + /** Shuts down the underlying scheduler service. */ + public void shutdown() { + metricsBase.shutdown(); + } + + /** + * Adds a custom chart. + * + * @param chart The chart to add. + */ + public void addCustomChart(CustomChart chart) { + metricsBase.addCustomChart(chart); + } + + private void appendPlatformData(JsonObjectBuilder builder) { + builder.appendField("playerAmount", getPlayerAmount()); + builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); + builder.appendField("bukkitVersion", Bukkit.getVersion()); + builder.appendField("bukkitName", Bukkit.getName()); + builder.appendField("javaVersion", System.getProperty("java.version")); + builder.appendField("osName", System.getProperty("os.name")); + builder.appendField("osArch", System.getProperty("os.arch")); + builder.appendField("osVersion", System.getProperty("os.version")); + builder.appendField("coreCount", Runtime.getRuntime().availableProcessors()); + } + + private void appendServiceData(JsonObjectBuilder builder) { + builder.appendField("pluginVersion", plugin.getDescription().getVersion()); + } + + private int getPlayerAmount() { + try { + // Around MC 1.8 the return type was changed from an array to a collection, + // This fixes java.lang.NoSuchMethodError: + // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; + Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); + return onlinePlayersMethod.getReturnType().equals(Collection.class) + ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() + : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; + } catch (Exception e) { + // Just use the new method if the reflection failed + return Bukkit.getOnlinePlayers().size(); + } + } + + public static class MetricsBase { + + /** The version of the Metrics class. */ + public static final String METRICS_VERSION = "3.1.0"; + + private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s"; + + private final ScheduledExecutorService scheduler; + + private final String platform; + + private final String serverUuid; + + private final int serviceId; + + private final Consumer appendPlatformDataConsumer; + + private final Consumer appendServiceDataConsumer; + + private final Consumer submitTaskConsumer; + + private final Supplier checkServiceEnabledSupplier; + + private final BiConsumer errorLogger; + + private final Consumer infoLogger; + + private final boolean logErrors; + + private final boolean logSentData; + + private final boolean logResponseStatusText; + + private final Set customCharts = new HashSet<>(); + + private final boolean enabled; + + /** + * Creates a new MetricsBase class instance. + * + * @param platform The platform of the service. + * @param serviceId The id of the service. + * @param serverUuid The server uuid. + * @param enabled Whether or not data sending is enabled. + * @param appendPlatformDataConsumer A consumer that receives a + * {@code JsonObjectBuilder} and + * appends all platform-specific data. + * @param appendServiceDataConsumer A consumer that receives a + * {@code JsonObjectBuilder} and + * appends all service-specific data. + * @param submitTaskConsumer A consumer that takes a runnable with the + * submit task. This can be + * used to delegate the data collection to a + * another thread to prevent errors caused by + * concurrency. Can be {@code null}. + * @param checkServiceEnabledSupplier A supplier to check if the service is + * still enabled. + * @param errorLogger A consumer that accepts log message and an + * error. + * @param infoLogger A consumer that accepts info log messages. + * @param logErrors Whether or not errors should be logged. + * @param logSentData Whether or not the sent data should be + * logged. + * @param logResponseStatusText Whether or not the response status text + * should be logged. + * @param skipRelocateCheck Whether or not the relocate check should + * be skipped. + */ + public MetricsBase( + String platform, + String serverUuid, + int serviceId, + boolean enabled, + Consumer appendPlatformDataConsumer, + Consumer appendServiceDataConsumer, + Consumer submitTaskConsumer, + Supplier checkServiceEnabledSupplier, + BiConsumer errorLogger, + Consumer infoLogger, + boolean logErrors, + boolean logSentData, + boolean logResponseStatusText, + boolean skipRelocateCheck) { + ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor( + 1, + task -> { + Thread thread = new Thread(task, "bStats-Metrics"); + thread.setDaemon(true); + return thread; + }); + // We want delayed tasks (non-periodic) that will execute in the future to be + // cancelled when the scheduler is shutdown. + // Otherwise, we risk preventing the server from shutting down even when + // MetricsBase#shutdown() is called + scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); + this.scheduler = scheduler; + this.platform = platform; + this.serverUuid = serverUuid; + this.serviceId = serviceId; + this.enabled = enabled; + this.appendPlatformDataConsumer = appendPlatformDataConsumer; + this.appendServiceDataConsumer = appendServiceDataConsumer; + this.submitTaskConsumer = submitTaskConsumer; + this.checkServiceEnabledSupplier = checkServiceEnabledSupplier; + this.errorLogger = errorLogger; + this.infoLogger = infoLogger; + this.logErrors = logErrors; + this.logSentData = logSentData; + this.logResponseStatusText = logResponseStatusText; + if (!skipRelocateCheck) { + checkRelocation(); + } + if (enabled) { + // WARNING: Removing the option to opt-out will get your plugin banned from + // bStats + startSubmitting(); + } + } + + public void addCustomChart(CustomChart chart) { + this.customCharts.add(chart); + } + + public void shutdown() { + scheduler.shutdown(); + } + + private void startSubmitting() { + final Runnable submitTask = () -> { + if (!enabled || !checkServiceEnabledSupplier.get()) { + // Submitting data or service is disabled + scheduler.shutdown(); + return; + } + if (submitTaskConsumer != null) { + submitTaskConsumer.accept(this::submitData); + } else { + this.submitData(); + } + }; + // Many servers tend to restart at a fixed time at xx:00 which causes an uneven + // distribution of requests on the + // bStats backend. To circumvent this problem, we introduce some randomness into + // the initial and second delay. + // WARNING: You must not modify and part of this Metrics class, including the + // submit delay or frequency! + // WARNING: Modifying this code will get your plugin banned on bStats. Just + // don't do it! + long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); + long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); + scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate( + submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); + } + + private void submitData() { + final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder(); + appendPlatformDataConsumer.accept(baseJsonBuilder); + final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder(); + appendServiceDataConsumer.accept(serviceJsonBuilder); + JsonObjectBuilder.JsonObject[] chartData = customCharts.stream() + .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors)) + .filter(Objects::nonNull) + .toArray(JsonObjectBuilder.JsonObject[]::new); + serviceJsonBuilder.appendField("id", serviceId); + serviceJsonBuilder.appendField("customCharts", chartData); + baseJsonBuilder.appendField("service", serviceJsonBuilder.build()); + baseJsonBuilder.appendField("serverUUID", serverUuid); + baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION); + JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); + scheduler.execute( + () -> { + try { + // Send the data + sendData(data); + } catch (Exception e) { + // Something went wrong! :( + if (logErrors) { + errorLogger.accept("Could not submit bStats metrics data", e); + } + } + }); + } + + private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { + if (logSentData) { + infoLogger.accept("Sent bStats metrics data: " + data.toString()); + } + String url = String.format(REPORT_URL, platform); + HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); + // Compress the data to save bandwidth + byte[] compressedData = compress(data.toString()); + connection.setRequestMethod("POST"); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.addRequestProperty("Content-Encoding", "gzip"); + connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("User-Agent", "Metrics-Service/1"); + connection.setDoOutput(true); + try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { + outputStream.write(compressedData); + } + StringBuilder builder = new StringBuilder(); + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + builder.append(line); + } + } + if (logResponseStatusText) { + infoLogger.accept("Sent data to bStats and received response: " + builder); + } + } + + /** Checks that the class was properly relocated. */ + private void checkRelocation() { + // You can use the property to disable the check in your test environment + if (System.getProperty("bstats.relocatecheck") == null + || !System.getProperty("bstats.relocatecheck").equals("false")) { + // Maven's Relocate is clever and changes strings, too. So we have to use this + // little "trick" ... :D + final String defaultPackage = new String(new byte[] { 'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's' }); + final String examplePackage = new String( + new byte[] { 'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e' }); + // We want to make sure no one just copy & pastes the example and uses the wrong + // package names + if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) + || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) { + throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); + } + } + } + + /** + * Gzips the given string. + * + * @param str The string to gzip. + * @return The gzipped string. + */ + private static byte[] compress(final String str) throws IOException { + if (str == null) { + return null; + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) { + gzip.write(str.getBytes(StandardCharsets.UTF_8)); + } + return outputStream.toByteArray(); + } + } + + public static class AdvancedBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue().length == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class SimplePie extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimplePie(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + String value = callable.call(); + if (value == null || value.isEmpty()) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("value", value).build(); + } + } + + public static class DrilldownPie extends CustomChart { + + private final Callable>> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public DrilldownPie(String chartId, Callable>> callable) { + super(chartId); + this.callable = callable; + } + + @Override + public JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map> map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean reallyAllSkipped = true; + for (Map.Entry> entryValues : map.entrySet()) { + JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); + boolean allSkipped = true; + for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { + valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue()); + allSkipped = false; + } + if (!allSkipped) { + reallyAllSkipped = false; + valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build()); + } + } + if (reallyAllSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class SingleLineChart extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SingleLineChart(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + int value = callable.call(); + if (value == 0) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("value", value).build(); + } + } + + public static class MultiLineChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public MultiLineChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class AdvancedPie extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedPie(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public abstract static class CustomChart { + + private final String chartId; + + protected CustomChart(String chartId) { + if (chartId == null) { + throw new IllegalArgumentException("chartId must not be null"); + } + this.chartId = chartId; + } + + public JsonObjectBuilder.JsonObject getRequestJsonObject( + BiConsumer errorLogger, boolean logErrors) { + JsonObjectBuilder builder = new JsonObjectBuilder(); + builder.appendField("chartId", chartId); + try { + JsonObjectBuilder.JsonObject data = getChartData(); + if (data == null) { + // If the data is null we don't send the chart. + return null; + } + builder.appendField("data", data); + } catch (Throwable t) { + if (logErrors) { + errorLogger.accept("Failed to get data for custom chart with id " + chartId, t); + } + return null; + } + return builder.build(); + } + + protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception; + } + + public static class SimpleBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimpleBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + for (Map.Entry entry : map.entrySet()) { + valuesBuilder.appendField(entry.getKey(), new int[] { entry.getValue() }); + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + /** + * An extremely simple JSON builder. + * + *

+ * While this class is neither feature-rich nor the most performant one, it's + * sufficient enough + * for its use-case. + */ + public static class JsonObjectBuilder { + + private StringBuilder builder = new StringBuilder(); + + private boolean hasAtLeastOneField = false; + + public JsonObjectBuilder() { + builder.append("{"); + } + + /** + * Appends a null field to the JSON. + * + * @param key The key of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendNull(String key) { + appendFieldUnescaped(key, "null"); + return this; + } + + /** + * Appends a string field to the JSON. + * + * @param key The key of the field. + * @param value The value of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, String value) { + if (value == null) { + throw new IllegalArgumentException("JSON value must not be null"); + } + appendFieldUnescaped(key, "\"" + escape(value) + "\""); + return this; + } + + /** + * Appends an integer field to the JSON. + * + * @param key The key of the field. + * @param value The value of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, int value) { + appendFieldUnescaped(key, String.valueOf(value)); + return this; + } + + /** + * Appends an object to the JSON. + * + * @param key The key of the field. + * @param object The object. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, JsonObject object) { + if (object == null) { + throw new IllegalArgumentException("JSON object must not be null"); + } + appendFieldUnescaped(key, object.toString()); + return this; + } + + /** + * Appends a string array to the JSON. + * + * @param key The key of the field. + * @param values The string array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, String[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = Arrays.stream(values) + .map(value -> "\"" + escape(value) + "\"") + .collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends an integer array to the JSON. + * + * @param key The key of the field. + * @param values The integer array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, int[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends an object array to the JSON. + * + * @param key The key of the field. + * @param values The integer array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, JsonObject[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends a field to the object. + * + * @param key The key of the field. + * @param escapedValue The escaped value of the field. + */ + private void appendFieldUnescaped(String key, String escapedValue) { + if (builder == null) { + throw new IllegalStateException("JSON has already been built"); + } + if (key == null) { + throw new IllegalArgumentException("JSON key must not be null"); + } + if (hasAtLeastOneField) { + builder.append(","); + } + builder.append("\"").append(escape(key)).append("\":").append(escapedValue); + hasAtLeastOneField = true; + } + + /** + * Builds the JSON string and invalidates this builder. + * + * @return The built JSON string. + */ + public JsonObject build() { + if (builder == null) { + throw new IllegalStateException("JSON has already been built"); + } + JsonObject object = new JsonObject(builder.append("}").toString()); + builder = null; + return object; + } + + /** + * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt. + * + *

+ * This method escapes only the necessary characters '"', '\'. and '\u0000' - + * '\u001F'. + * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as + * "\n"). + * + * @param value The value to escape. + * @return The escaped value. + */ + private static String escape(String value) { + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (c == '"') { + builder.append("\\\""); + } else if (c == '\\') { + builder.append("\\\\"); + } else if (c <= '\u000F') { + builder.append("\\u000").append(Integer.toHexString(c)); + } else if (c <= '\u001F') { + builder.append("\\u00").append(Integer.toHexString(c)); + } else { + builder.append(c); + } + } + return builder.toString(); + } + + /** + * A super simple representation of a JSON object. + * + *

+ * This class only exists to make methods of the {@link JsonObjectBuilder} + * type-safe and not + * allow a raw string inputs for methods like + * {@link JsonObjectBuilder#appendField(String, + * JsonObject)}. + */ + public static class JsonObject { + + private final String value; + + private JsonObject(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + } + } +} From b02f338986c73232124f1d959fa126a872553ee7 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Tue, 3 Dec 2024 15:22:39 +0000 Subject: [PATCH 14/20] begin adding logic for collective quest type --- README.md | 26 ++++--- .../configuration/JsonQuestSave.java | 4 +- .../configuration/QuestLibrary.java | 5 +- .../configuration/QuestModel.java | 4 +- .../wonka01/ServerQuests/enums/EventType.java | 3 +- .../me/wonka01/ServerQuests/gui/ViewMenu.java | 16 +++++ .../questcomponents/CompetitiveQuestData.java | 4 +- .../questcomponents/GoalQuestData.java | 71 +++++++++++++++++++ .../questcomponents/QuestController.java | 11 ++- .../questcomponents/QuestData.java | 7 +- .../questcomponents/QuestTypeHandler.java | 20 ++++-- .../players/BasePlayerComponent.java | 1 + .../questcomponents/players/PlayerData.java | 6 +- .../players/SortByContributions.java | 3 +- 14 files changed, 153 insertions(+), 28 deletions(-) create mode 100644 src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java diff --git a/README.md b/README.md index 6ddf5bb..d838b79 100644 --- a/README.md +++ b/README.md @@ -242,6 +242,10 @@ Rewards example ```yaml rewards: rewardsLimit: 5 # only top 5 contributors get the rewards, if not set or 0 then everyone gets rewards + rewardDisplay: # If this is set it will show the rewards in the quest view + - "REWARDS!" + - "1 Iron Sword" + - "50 Experience" rankedRewards: "1": # The key is the rank of the player experience: 100 @@ -290,26 +294,26 @@ rewards: displayName: "&capples" ``` -## Competitive vs. Cooperative +## Quest Types -There are two quest types to chose from: competitive and cooperative. If you're using the GUI which is opened from the /sp start command, after choosing the quest you'd like to run you're presented with a -GUI to pick the type. You can also do /cq start [QuestId] [coop/comp]. +There are three quest types to chose from: competitive, cooperative and collective. If you're using the GUI which is opened from the /sp start command, after choosing the quest you'd like to run you're presented with a +GUI to pick the type. You can also do /cq start [QuestId] [coop/comp/coll]. ### Cooperative -Cooperative quests involve everyone on the server working together to complete the goal. For example in the quest created in the configuration section, the quest will be complete once 100 zombies, pigs, and zombie pigmen have been killed. Note: This means 100 total of -any combination of zombies/pigs/zombie pigman kills that add to 100. If questDuration is set then the player's must complete the quest in the given time limit. -If the quest is not completed no rewards will be given out. +In cooperative quests player's work together to reach a goal. For example, if the quest has 3 objectives: kill 100 zombies, kill 100 pigmen and kill 200 skeletons. Players will need to reach all 3 of those objectives together to win the rewards. If questDuration is set, the player's must complete the quest before the time limit is reached to get the rewards. -Player's are rewarded based on how much they contribute to the quest. If the reward is 1000 -money and PlayerX kills 50 of the 100 zombies, PlayerX will receive 500. Item and command rewards are given to every player who contributes to the quest. You can use the **_rewardsLimit_** field in the rewards section of the config if you only want the top x number of players to get a reward. +Player's are rewarded based on how much they contribute to the quest. If the reward is 1000 money and PlayerX kills 50 of the 100 zombies, PlayerX will receive 500. Item and command rewards are given to every player who contributes to the quest. You can use the **_rewardsLimit_** field in the rewards section of the config if you only want the top x number of players to get a reward. You can also set rewards for specific ranks using the **_rankedRewards_** field. ### Competitive -Competitive quests put the players against each other to see who can complete a goal first. Using our zombie/pig example -from above, the quest will end once a single player gets 100 kills for the correct mob types. If a time limit is set and the quest ends before the goal is reached the top players will still get rewards based on their contributions. +In competitive quests, players compete to see who can reach the objective first. If goals are set on the objectives then the quest ends when the first player completes them. If a time limit is set then a goal is no required, and once the timer runs out players will be rewarded based on their ranking. -Money/experience awards work the same way as cooperative quests. If the money reward is 1000 the winner of the competition will get 1000. If Player1 came in second with 70 kills, he or she will get 700. The winner is the only person who will get items and commands in a competitive quest. Think of it as more of a challenge than a quest. +Money/experience rewards work the same way as cooperative quests. If the money reward is 1000 the winner of the competition will get 1000. If Player1 came in second with 70 kills, he or she will get 700. The winner is the only person who will get items and commands in a competitive quest, unless rewards are specified for specific rankings. + +### Collective + +In a collective quest, all player's are working toward the same goal. Like competitive quests, the goal is tracked individually for each player, but when a player reaches the goal the quest doesn't end. The quest must have a duration and will end when the timer runs out. All player's who reach the goal will be eligible for rewards, you can use ranked rewards to reward player's based on who finishes the quest first. ## Objectives diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java index 6a7529c..5c997ad 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java @@ -163,6 +163,7 @@ public void readAndInitializeQuests() { UUID uuidKey = null; String playerName = (String) obj.get("name"); + long lastUpdated = (Long) obj.get("lastUpdated"); while (keys.hasNext()) { String key = keys.next(); @@ -178,7 +179,8 @@ public void readAndInitializeQuests() { Type type = new com.google.gson.reflect.TypeToken>() { }.getType(); String jsonContributions = (String) obj.get(uuidKey.toString()); - playerMap.put(uuidKey, new PlayerData(playerName, uuidKey, gson.fromJson(jsonContributions, type))); + playerMap.put(uuidKey, + new PlayerData(playerName, uuidKey, gson.fromJson(jsonContributions, type), lastUpdated)); } QuestTypeHandler handler = new QuestTypeHandler(questType); diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java index 5333735..2358d42 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestLibrary.java @@ -160,10 +160,12 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { ConfigurationSection rewardsSection = section.getConfigurationSection("rewards"); ConfigurationSection rankedRewards = null; + List rewardUiView = null; int rewardsLimit = 0; if (rewardsSection != null) { rewardsLimit = rewardsSection.getInt("rewardsLimit", 0); rankedRewards = rewardsSection.getConfigurationSection("rankedRewards"); + rewardUiView = rewardsSection.getStringList("rewardDisplay"); } Map> rankedRewardsMap = new HashMap<>(); @@ -184,8 +186,7 @@ private QuestModel loadQuestFromConfig(ConfigurationSection section) { return new QuestModel(questId, displayName, description, goal, type, entityNames, materials, displayItem, worlds, questDuration, rewardsLimit, afterQuestCommand, beforeQuestCommand, objectives, questFailedCommand, customNames, barColor.toUpperCase(), - rankedRewardsMap, - rankedRewardMessages, style); + rankedRewardsMap, rankedRewardMessages, style, rewardUiView); } private ArrayList getRewardsFromConfig(ConfigurationSection section) { diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java index 48ac017..6c87707 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java @@ -36,6 +36,7 @@ public class QuestModel { private final Map> rankedRewards; private final Map rankedRewardMessages; private final BarStyle barStyle; + private final List rewardDisplay; public QuestModel(String questId, String displayName, String eventDescription, int questGoal, ObjectiveType objective, @@ -43,7 +44,7 @@ public QuestModel(String questId, String displayName, String eventDescription, List worlds, String questDuration, int rewardLimit, String afterQuestCommand, String beforeQuestCommand, List objectives, String questFailedCommand, List customNames, String barColor, Map> rankedRewards, - Map rankedRewardMessages, BarStyle barStyle) { + Map rankedRewardMessages, BarStyle barStyle, List rewardDisplay) { this.questId = questId; this.displayName = displayName; this.eventDescription = eventDescription; @@ -52,6 +53,7 @@ public QuestModel(String questId, String displayName, String eventDescription, this.questFailedCommand = questFailedCommand; this.barColor = barColor; this.barStyle = barStyle; + this.rewardDisplay = rewardDisplay; List materials = new ArrayList<>(); if (itemNames != null) { diff --git a/src/main/java/me/wonka01/ServerQuests/enums/EventType.java b/src/main/java/me/wonka01/ServerQuests/enums/EventType.java index b64e2f1..97e63b8 100644 --- a/src/main/java/me/wonka01/ServerQuests/enums/EventType.java +++ b/src/main/java/me/wonka01/ServerQuests/enums/EventType.java @@ -2,5 +2,6 @@ public enum EventType { COLLAB, - COMPETITIVE + COMPETITIVE, + GOAL } diff --git a/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java index 94b5d15..b252b2a 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java @@ -4,6 +4,7 @@ import me.knighthat.apis.menus.Menu; import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.configuration.QuestModel; import me.wonka01.ServerQuests.objectives.Objective; import me.wonka01.ServerQuests.questcomponents.CompetitiveQuestData; import me.wonka01.ServerQuests.questcomponents.QuestController; @@ -57,9 +58,21 @@ protected void setContents() { } lore.add(getPlayerProgress(controller)); + addRewardDisplay(lore, controller.getQuestData()); + return super.createItemStack(data.getDisplayItem(), data.getDisplayName(), lore); } + private void addRewardDisplay(List lore, QuestData data) { + if (data.getRewardDisplay() == null || data.getRewardDisplay().isEmpty()) { + return; + } + lore.add(""); + for (String reward : data.getRewardDisplay()) { + lore.add(color(reward)); + } + } + private @NonNull ItemStack compItem(QuestController ctrl) { QuestData data = ctrl.getQuestData(); List lore = super.getLoreFromData(data); @@ -72,6 +85,9 @@ protected void setContents() { lore.add(""); getObjectivePlayerProgress(data.getObjectives(), lore, getOwner(), (CompetitiveQuestData) data); } + + addRewardDisplay(lore, data); + return super.createItemStack(data.getDisplayItem(), data.getDisplayName(), lore); } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java index 26c591d..c404920 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java @@ -20,9 +20,9 @@ public class CompetitiveQuestData extends QuestData { public CompetitiveQuestData(String displayName, String description, BasePlayerComponent players, String questType, int durationLeft, Material displayItem, String questId, String afterQuestCommand, String beforeQuestCommand, List objectives, - String questFailedCommand) { + String questFailedCommand, List rewardDisplay) { super(displayName, description, questType, durationLeft, displayItem, questId, - afterQuestCommand, beforeQuestCommand, objectives, questFailedCommand); + afterQuestCommand, beforeQuestCommand, objectives, questFailedCommand, rewardDisplay); this.players = players; } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java new file mode 100644 index 0000000..bbaa917 --- /dev/null +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java @@ -0,0 +1,71 @@ +package me.wonka01.ServerQuests.questcomponents; + +import me.wonka01.ServerQuests.enums.EventType; +import me.wonka01.ServerQuests.objectives.Objective; +import me.wonka01.ServerQuests.questcomponents.players.BasePlayerComponent; +import me.wonka01.ServerQuests.questcomponents.players.PlayerData; + +import java.util.List; + +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import lombok.Getter; + +public class GoalQuestData extends QuestData { + + @Getter + private BasePlayerComponent players; + + public GoalQuestData(String displayName, String description, + BasePlayerComponent players, String questType, int durationLeft, Material displayItem, + String questId, String afterQuestCommand, String beforeQuestCommand, List objectives, + String questFailedCommand, List rewardDisplay) { + super(displayName, description, questType, durationLeft, displayItem, questId, + afterQuestCommand, beforeQuestCommand, objectives, questFailedCommand, rewardDisplay); + this.players = players; + } + + @Override + public double getAmountCompleted() { + PlayerData playerData = players.getTopPlayer(); + if (playerData != null) { + return playerData.getAmountContributed(); + } + return 0; + } + + @Override + public double getPercentageComplete() { + PlayerData playerData = players.getTopPlayer(); + if (playerData != null) { + return playerData.getAmountContributed() / this.getQuestGoal(); + } + return 0; + } + + @Override + public boolean isGoalComplete() { + return false; + } + + // This really means is goal complete for the top player + @Override + public boolean isGoalComplete(Objective objective) { + PlayerData playerData = players.getTopPlayer(); + if (playerData == null) { + return false; + } + return (getQuestGoal() > 0 && playerData.getAmountContributed() >= getQuestGoal()); + } + + public boolean isGoalComplete(Objective objective, Player player, Integer objectiveId) { + double amountContributed = players.getAmountContributedByObjectiveId(player, objectiveId); + return (objective.getGoal() > 0 && amountContributed >= objective.getGoal()); + } + + @Override + public EventType getEventType() { + return EventType.COMPETITIVE; + } +} diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java index 9503bf6..d54481a 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java @@ -44,12 +44,17 @@ public QuestController(ServerQuests plugin, QuestData questData, QuestBar questB public boolean updateQuest(double count, Player player, Objective objective, Integer objectiveId) { double amountToAdd = count; - // Check if quest is complete (not 100% sure if this is needed) + // Make sure individuals can't exceed the goal of an objective if (questData.getEventType().equals(EventType.COMPETITIVE)) { CompetitiveQuestData competitiveQuestData = (CompetitiveQuestData) questData; if (competitiveQuestData.isGoalComplete(objective, player, objectiveId)) { return false; } + } else if (questData.getEventType().equals(objectiveId)) { + GoalQuestData goalQuest = (GoalQuestData) questData; + if (goalQuest.isGoalComplete(objective, player, objectiveId)) { + return false; + } } else { if (questData.isGoalComplete()) { return false; @@ -121,6 +126,10 @@ public boolean isCompetitive() { return (questData.getEventType().equals(EventType.COMPETITIVE)); } + public boolean isGoalQuest() { + return (questData.getEventType().equals(EventType.GOAL)); + } + private void updateBossBar() { double barProgress = questData.getPercentageComplete(); questBar.updateBarProgress(barProgress); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java index 2993336..473ae41 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java @@ -15,8 +15,6 @@ import org.bukkit.ChatColor; import org.bukkit.Material; -import eu.decentsoftware.holograms.api.utils.scheduler.S; - @Getter public class QuestData implements Colorization { @@ -31,10 +29,12 @@ public class QuestData implements Colorization { private String beforeQuestCommand; private List objectives; private String questFailedCommand; + private List rewardDisplay; public QuestData(String displayName, String description, String questType, int questDuration, Material displayItem, @NonNull String questId, String afterQuestCommand, - String beforeQuestCommand, List objectives, String questFailedCommand) { + String beforeQuestCommand, List objectives, String questFailedCommand, + List rewardDisplay) { this.questDuration = questDuration; this.displayName = displayName; this.description = description == null ? "" : description; @@ -45,6 +45,7 @@ public QuestData(String displayName, String description, String questType, this.beforeQuestCommand = beforeQuestCommand; this.objectives = objectives; this.questFailedCommand = questFailedCommand; + this.rewardDisplay = rewardDisplay; } public double getAmountCompleted() { diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java index 5e5e4f9..5306cfd 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java @@ -25,7 +25,11 @@ public QuestTypeHandler(EventType eventType) { } public QuestTypeHandler(String type) { - eventType = type.equalsIgnoreCase("comp") ? EventType.COMPETITIVE : EventType.COLLAB; + if (type.equalsIgnoreCase("goal")) { + eventType = EventType.GOAL; + } else { + eventType = type.equalsIgnoreCase("comp") ? EventType.COMPETITIVE : EventType.COLLAB; + } } public QuestController createQuestController(@NonNull QuestModel model) { @@ -76,12 +80,20 @@ private QuestData getQuestData(QuestModel questModel, BasePlayerComponent player return new CompetitiveQuestData(questModel.getDisplayName(), questModel.getEventDescription(), playerComponent, questModel.getQuestId(), timeLeft, questModel.getDisplayItem(), questModel.getQuestId(), questModel.getAfterQuestCommand(), - questModel.getBeforeQuestCommand(), objectives, questModel.getQuestFailedCommand()); - } else { + questModel.getBeforeQuestCommand(), objectives, questModel.getQuestFailedCommand(), + questModel.getRewardDisplay()); + } else if (eventType == EventType.COLLAB) { return new QuestData(questModel.getDisplayName(), questModel.getEventDescription(), questModel.getQuestId(), timeLeft, questModel.getDisplayItem(), questModel.getQuestId(), questModel.getAfterQuestCommand(), - questModel.getBeforeQuestCommand(), objectives, questModel.getQuestFailedCommand()); + questModel.getBeforeQuestCommand(), objectives, questModel.getQuestFailedCommand(), + questModel.getRewardDisplay()); + } else { + return new GoalQuestData(questModel.getDisplayName(), + questModel.getEventDescription(), playerComponent, questModel.getQuestId(), + timeLeft, questModel.getDisplayItem(), questModel.getQuestId(), questModel.getAfterQuestCommand(), + questModel.getBeforeQuestCommand(), objectives, questModel.getQuestFailedCommand(), + questModel.getRewardDisplay()); } } } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java index 9e31e87..1f80376 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java @@ -156,6 +156,7 @@ public JSONArray toJSONArray() { String jsonString = gson.toJson(playerMap.get(key).getObjectiveContributions()); jsonObject.put(key.toString(), jsonString); jsonObject.put("name", playerMap.get(key).getName()); + jsonObject.put("lastUpdated", playerMap.get(key).getLastUpdated()); jArray.add(jsonObject); } return jArray; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java index 707dc71..767769b 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerData.java @@ -14,17 +14,20 @@ public class PlayerData { private String name; private UUID uuid; Map objectiveContributions; + long lastUpdated; public PlayerData(String name, UUID uuid) { objectiveContributions = new HashMap<>(); this.name = name; this.uuid = uuid; + this.lastUpdated = System.currentTimeMillis(); } - public PlayerData(String name, UUID uuid, Map objectives) { + public PlayerData(String name, UUID uuid, Map objectives, long lastUpdated) { this.objectiveContributions = objectives; this.name = name; this.uuid = uuid; + this.lastUpdated = lastUpdated; } public double getAmountContributed() { @@ -47,5 +50,6 @@ public void increaseContribution(double count, int objectiveId) { objectiveContributions.put(objectiveId, 0.0); } objectiveContributions.put(objectiveId, objectiveContributions.get(objectiveId) + count); + lastUpdated = System.currentTimeMillis(); } } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/SortByContributions.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/SortByContributions.java index d262e5f..2ce4854 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/SortByContributions.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/SortByContributions.java @@ -16,7 +16,8 @@ public int compare(UUID p1Id, UUID p2Id) { map.get(p1Id).getAmountContributed()); if (contributionComparison == 0) { - return p1Id.compareTo(p2Id); + // if same amount whoever updated first would be higher + return Long.compare(map.get(p1Id).getLastUpdated(), map.get(p2Id).getLastUpdated()); } return contributionComparison; } From 52fc1e9f2c4c6ed28d3288a8116e90989bd43f6e Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sat, 7 Dec 2024 21:05:21 +0000 Subject: [PATCH 15/20] new quest type / rename for clarity --- .../ServerQuests/configuration/Config.java | 4 ++-- .../me/wonka01/ServerQuests/gui/TypeMenu.java | 23 ++++++++++++++++++- .../me/wonka01/ServerQuests/gui/ViewMenu.java | 4 ++-- .../questcomponents/CompetitiveQuestData.java | 6 ++--- .../questcomponents/GoalQuestData.java | 8 +++---- .../questcomponents/QuestController.java | 8 +++---- .../questcomponents/QuestTypeHandler.java | 8 +++---- .../bossbar/BossbarPlayerInfo.java | 5 +--- ...ponent.java => PlayerContributionMap.java} | 18 +++++++++++---- 9 files changed, 56 insertions(+), 28 deletions(-) rename src/main/java/me/wonka01/ServerQuests/questcomponents/players/{BasePlayerComponent.java => PlayerContributionMap.java} (93%) diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/Config.java b/src/main/java/me/wonka01/ServerQuests/configuration/Config.java index c1f3239..5b6e64b 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/Config.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/Config.java @@ -9,7 +9,7 @@ import me.wonka01.ServerQuests.gui.DonateMenu; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.bossbar.BarManager; -import me.wonka01.ServerQuests.questcomponents.players.BasePlayerComponent; +import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -32,7 +32,7 @@ public void initializeVariables() { ActiveQuests.setQuestLimit(limit); int leaderBoardSize = get().getInt("leaderBoardSize", 5); - BasePlayerComponent.setLeaderBoardSize(leaderBoardSize); + PlayerContributionMap.setLeaderBoardSize(leaderBoardSize); boolean disableBar = get().getBoolean("disableBossBar", false); BarManager.setDisableBossBar(disableBar); diff --git a/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java index b9bcb57..55d9182 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java @@ -13,11 +13,12 @@ import org.bukkit.inventory.ItemStack; import java.util.Collections; +import java.util.List; import java.util.stream.Collectors; public class TypeMenu extends Menu { - private final int COMP = 12, COOP = 14, BACK = 18; + private final int COMP = 11, COLL = 13, COOP = 15, BACK = 18; private final @NonNull QuestModel model; @@ -38,6 +39,7 @@ protected void setButtons() { @Override protected void setContents() { getInventory().setItem(COMP, getCompItem()); + getInventory().setItem(COLL, getCollItem()); getInventory().setItem(COOP, getCoopItem()); } @@ -47,6 +49,22 @@ protected void setContents() { return createItemStack(material, title); } + private @NonNull ItemStack getCollItem() { + double goal = model.getObjectives().stream().mapToDouble(Objective::getGoal).sum(); + String dynamicGoal = model.getObjectives().stream().map(Objective::getDynamicGoal) + .collect(Collectors.joining("")); + boolean isValid = (goal > 0 || !dynamicGoal.isEmpty()) && model.getCompleteTime() > 0; + List lore = Collections + .singletonList(isValid ? "&fPlayers who reach the objective before time runs out will receive a reward!" + : "&2Quest can not be collective, collective quests must have a time limit and a goal."); + + String title = getPlugin().messages().string("collective"); + if (title == null || title.isEmpty()) { + title = "Collective"; + } + return createItemStack(Material.ENCHANTED_BOOK, title, lore); + } + private @NonNull ItemStack getCoopItem() { double goal = model.getObjectives().stream().mapToDouble(Objective::getGoal).sum(); String dynamicGoal = model.getObjectives().stream().map(Objective::getDynamicGoal) @@ -67,6 +85,9 @@ protected void onItemClick(@NonNull InventoryClickEvent event) { case COOP: startQuest(EventType.COLLAB); break; + case COLL: + startQuest(EventType.GOAL); + break; case BACK: new StartMenu(getPlugin(), getOwner()).open(); default: diff --git a/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java index b252b2a..2fd9c6f 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java @@ -9,7 +9,7 @@ import me.wonka01.ServerQuests.questcomponents.CompetitiveQuestData; import me.wonka01.ServerQuests.questcomponents.QuestController; import me.wonka01.ServerQuests.questcomponents.QuestData; -import me.wonka01.ServerQuests.questcomponents.players.BasePlayerComponent; +import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import me.wonka01.ServerQuests.questcomponents.players.PlayerData; import org.bukkit.Bukkit; @@ -108,7 +108,7 @@ protected void onClose(InventoryCloseEvent event) { private void getTopPlayerString(QuestController controller, List lore) { String noData = "&7n/a"; - int size = BasePlayerComponent.getLeaderBoardSize(); + int size = PlayerContributionMap.getLeaderBoardSize(); ArrayList topPlayers = controller.getPlayerComponent().getTopPlayers(size); if (topPlayers.size() < 1) { diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java index c404920..f2fee68 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/CompetitiveQuestData.java @@ -2,7 +2,7 @@ import me.wonka01.ServerQuests.enums.EventType; import me.wonka01.ServerQuests.objectives.Objective; -import me.wonka01.ServerQuests.questcomponents.players.BasePlayerComponent; +import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import me.wonka01.ServerQuests.questcomponents.players.PlayerData; import java.util.List; @@ -15,10 +15,10 @@ public class CompetitiveQuestData extends QuestData { @Getter - private BasePlayerComponent players; + private PlayerContributionMap players; public CompetitiveQuestData(String displayName, String description, - BasePlayerComponent players, String questType, int durationLeft, Material displayItem, + PlayerContributionMap players, String questType, int durationLeft, Material displayItem, String questId, String afterQuestCommand, String beforeQuestCommand, List objectives, String questFailedCommand, List rewardDisplay) { super(displayName, description, questType, durationLeft, displayItem, questId, diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java index bbaa917..fadc3a5 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java @@ -2,7 +2,7 @@ import me.wonka01.ServerQuests.enums.EventType; import me.wonka01.ServerQuests.objectives.Objective; -import me.wonka01.ServerQuests.questcomponents.players.BasePlayerComponent; +import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import me.wonka01.ServerQuests.questcomponents.players.PlayerData; import java.util.List; @@ -15,10 +15,10 @@ public class GoalQuestData extends QuestData { @Getter - private BasePlayerComponent players; + private PlayerContributionMap players; public GoalQuestData(String displayName, String description, - BasePlayerComponent players, String questType, int durationLeft, Material displayItem, + PlayerContributionMap players, String questType, int durationLeft, Material displayItem, String questId, String afterQuestCommand, String beforeQuestCommand, List objectives, String questFailedCommand, List rewardDisplay) { super(displayName, description, questType, durationLeft, displayItem, questId, @@ -66,6 +66,6 @@ public boolean isGoalComplete(Objective objective, Player player, Integer object @Override public EventType getEventType() { - return EventType.COMPETITIVE; + return EventType.GOAL; } } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java index d54481a..57dc132 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java @@ -8,7 +8,7 @@ import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; import me.wonka01.ServerQuests.questcomponents.bossbar.QuestBar; -import me.wonka01.ServerQuests.questcomponents.players.BasePlayerComponent; +import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import me.wonka01.ServerQuests.questcomponents.schedulers.QuestTimer; import org.bukkit.entity.Player; @@ -22,13 +22,13 @@ public class QuestController implements Colorization { private final QuestBar questBar; private final QuestData questData; - private final BasePlayerComponent playerComponent; + private final PlayerContributionMap playerComponent; private final List worlds; private final UUID questId; private final ServerQuests plugin; public QuestController(ServerQuests plugin, QuestData questData, QuestBar questBar, - BasePlayerComponent playerComponent, List worlds) { + PlayerContributionMap playerComponent, List worlds) { this.plugin = plugin; this.questData = questData; this.questBar = questBar; @@ -106,7 +106,7 @@ public void endQuest() { broadcast("questCompleteMessage"); playerComponent.sendLeaderString(); String completeMessage = color(plugin.messages().message("questCompleteMessage", questData)); - playerComponent.giveOutRewards(questData.getQuestGoal(), completeMessage); + playerComponent.giveOutRewards(questData.getQuestGoal(), completeMessage, questData.getEventType()); if (questData.getAfterQuestCommand() != null && !questData.getAfterQuestCommand().isEmpty()) { plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), questData.getAfterQuestCommand()); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java index 5306cfd..9281218 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java @@ -6,7 +6,7 @@ import me.wonka01.ServerQuests.enums.EventType; import me.wonka01.ServerQuests.objectives.Objective; import me.wonka01.ServerQuests.questcomponents.bossbar.QuestBar; -import me.wonka01.ServerQuests.questcomponents.players.BasePlayerComponent; +import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import me.wonka01.ServerQuests.questcomponents.players.PlayerData; import org.bukkit.plugin.java.JavaPlugin; @@ -52,11 +52,11 @@ public QuestController createControllerFromSave(@NonNull QuestModel model, @NonN QuestBar bar = new QuestBar(model.getDisplayName(), barColor, model.getBarStyle()); - BasePlayerComponent pComponent = new BasePlayerComponent(model.getRewardLimit(), + PlayerContributionMap pComponent = new PlayerContributionMap(model.getRewardLimit(), model.getRankedRewards()); if (players != null) { - pComponent = new BasePlayerComponent(players, model.getRewardLimit(), + pComponent = new PlayerContributionMap(players, model.getRewardLimit(), model.getRankedRewards()); } @@ -74,7 +74,7 @@ public QuestController createControllerFromSave(@NonNull QuestModel model, @NonN return new QuestController(plugin, data, bar, pComponent, model.getWorlds()); } - private QuestData getQuestData(QuestModel questModel, BasePlayerComponent playerComponent, + private QuestData getQuestData(QuestModel questModel, PlayerContributionMap playerComponent, int timeLeft, List objectives) { if (eventType == EventType.COMPETITIVE) { return new CompetitiveQuestData(questModel.getDisplayName(), diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/BossbarPlayerInfo.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/BossbarPlayerInfo.java index e27d284..4af859b 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/BossbarPlayerInfo.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/BossbarPlayerInfo.java @@ -11,8 +11,8 @@ import org.json.simple.JSONArray; import org.json.simple.parser.JSONParser; +// Class that manages the players that have hidden the bossbar public class BossbarPlayerInfo { - // make singleton class with a list of playerId who have the bossbar enabled private static BossbarPlayerInfo instance; private List playersToHideBossbar; @@ -65,9 +65,6 @@ public void saveToJsonFile(File path) { } public void loadFromJsonFile(File path) { - // load the list of players from a json file - // if the file does not exist, do nothing - // if the file exists, load the list of players JSONParser parser = new JSONParser(); File fullPath = new File(path + "/togglebar.json"); try { diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java similarity index 93% rename from src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java rename to src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java index 1f80376..61a2bbf 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/BasePlayerComponent.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java @@ -6,6 +6,7 @@ import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; import me.wonka01.ServerQuests.questcomponents.rewards.RewardMessage; import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; +import me.wonka01.ServerQuests.enums.EventType; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; @@ -25,7 +26,7 @@ import java.util.TreeMap; import java.util.UUID; -public class BasePlayerComponent implements Colorization { +public class PlayerContributionMap implements Colorization { @Setter @Getter private static int leaderBoardSize = 5; @@ -35,14 +36,14 @@ public class BasePlayerComponent implements Colorization { private final Map> rankedRewards; private final int rewardsLimit; - public BasePlayerComponent(int rewardLimit, + public PlayerContributionMap(int rewardLimit, Map> rankedRewards) { this.playerMap = new TreeMap<>(); this.rewardsLimit = rewardLimit; this.rankedRewards = rankedRewards; } - public BasePlayerComponent(Map map, int rewardLimit, + public PlayerContributionMap(Map map, int rewardLimit, Map> rankedRewards) { this.playerMap = map; this.rewardsLimit = rewardLimit; @@ -162,13 +163,14 @@ public JSONArray toJSONArray() { return jArray; } - public void giveOutRewards(double questGoal, String completeMessage) { + public void giveOutRewards(double questGoal, String completeMessage, EventType eventType) { List players; if (rewardsLimit > 0) { players = getTopPlayers(rewardsLimit); } else { players = getTopPlayers(playerMap.size()); } + for (PlayerData playerData : players) { double playerContributionRatio; double playerContribution = playerData.getAmountContributed(); @@ -195,6 +197,14 @@ public void giveOutRewards(double questGoal, String completeMessage) { OfflinePlayer player = Bukkit.getServer().getOfflinePlayer(playerData.getUuid()); RewardManager rewardManager = RewardManager.getInstance(); + if (eventType == EventType.GOAL) { + if (playerContribution >= questGoal) { + playerContributionRatio = 1.0; + } else { + continue; + } + } + if (player.isOnline()) { Player onlinePlayer = (Player) player; if (rankedReward.size() > 0) { From c900b4386210399e6fb39105b792a452f6b3ddb6 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sun, 8 Dec 2024 20:37:18 +0000 Subject: [PATCH 16/20] cleanup code, test modelIds and new quest type --- README.md | 4 +- .../ServerQuests/commands/QuestScheduler.java | 6 +- .../ServerQuests/commands/StartCommand.java | 5 +- .../configuration/JsonQuestSave.java | 9 +- .../wonka01/ServerQuests/enums/EventType.java | 2 +- .../ServerQuests/enums/ObjectiveType.java | 2 +- .../events/InventoryClickEvents.java | 13 +- .../me/wonka01/ServerQuests/gui/TypeMenu.java | 4 +- .../ServerQuests/objectives/Objective.java | 4 +- .../objectives/ObjectiveFilters.java | 11 +- ...uestData.java => CollectiveQuestData.java} | 6 +- .../questcomponents/QuestController.java | 29 ++-- .../questcomponents/QuestTypeHandler.java | 6 +- .../players/PlayerContributionMap.java | 3 +- .../ServerQuests}/utils/Colorization.java | 0 .../ServerQuests}/utils/Utils.java | 2 +- src/main/resources/config.yml | 161 ++++++++++++++++-- src/main/resources/messages.yml | 2 +- 18 files changed, 206 insertions(+), 63 deletions(-) rename src/main/java/me/wonka01/ServerQuests/questcomponents/{GoalQuestData.java => CollectiveQuestData.java} (93%) rename src/main/java/me/{knighthat/apis => wonka01/ServerQuests}/utils/Colorization.java (100%) rename src/main/java/me/{knighthat/apis => wonka01/ServerQuests}/utils/Utils.java (97%) diff --git a/README.md b/README.md index d838b79..afb724c 100644 --- a/README.md +++ b/README.md @@ -352,7 +352,7 @@ Fishing: - **experience**: players must gather Minecraft experience - **level**: players must levelup - **distance**: travel a certain distance in blocks -- **smeltitem**: use furnace to smelt or cook an item +- **furnace**: use furnace to smelt or cook an item - **brewpotion**: brew potions - **playerkill**: kill other players - **carvepumpkin**: use shears on a pumpkin @@ -508,7 +508,7 @@ You can directly configure schedules in `schedules.yml`: ```yaml 12345678-example: questId: "mining" # Quest identifier - mode: "coop" # Mode: "coop" or "comp" + mode: "coop" # Mode: "coop", "comp" or "coll" time: "14:30" # 24-hour format (HH:mm) scheduleType: "DAILY" # DAILY, WEEKLY, or CUSTOM_DAYS interval: 1 # Days between runs (for CUSTOM_DAYS only) diff --git a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java index 3eb53a7..49ff52e 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/QuestScheduler.java @@ -106,8 +106,8 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar return; } - if (!mode.equals("coop") && !mode.equals("comp")) { - sender.sendMessage("§cMode must be either 'coop' or 'comp'!"); + if (!mode.equalsIgnoreCase("coop") && !mode.equalsIgnoreCase("comp") && !mode.equalsIgnoreCase("coll")) { + sender.sendMessage("§cMode must be either 'coop', 'comp' or 'coll'!"); return; } @@ -319,7 +319,7 @@ public List onTabComplete(CommandSender sender, Command command, String case 3: // Mode completions - List modes = Arrays.asList("coop", "comp"); + List modes = Arrays.asList("coop", "comp", "coll"); completions = modes.stream() .filter(mode -> mode.startsWith(args[2].toLowerCase())) .collect(Collectors.toList()); diff --git a/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java index d415ec0..1e3f2cb 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/StartCommand.java @@ -51,6 +51,9 @@ public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] ar case "comp": type = EventType.COMPETITIVE; break; + case "coll": + type = EventType.COLLECTIVE; + break; default: String invalidQuestType = getPlugin().messages().message("invalidQuestType"); sender.sendMessage(invalidQuestType); @@ -84,7 +87,7 @@ public List onTabComplete(CommandSender sender, Command command, String // Handle quest type completions (third argument) if (args.length == 3) { - List questTypes = Arrays.asList("coop", "comp"); + List questTypes = Arrays.asList("coop", "comp", "coll"); completions = questTypes.stream() .filter(type -> type.startsWith(args[2].toLowerCase())) .collect(Collectors.toList()); diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java index 5c997ad..b0e36d0 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java @@ -1,6 +1,7 @@ package me.wonka01.ServerQuests.configuration; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.enums.EventType; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; @@ -69,8 +70,10 @@ public void saveQuestsInProgress() { } jObject.put("objectives", objectives); jObject.put("timeLeft", questController.getQuestData().getQuestDuration()); - if (questController.getQuestData() instanceof CompetitiveQuestData) { + if (questController.getQuestData().getEventType().equals(EventType.COMPETITIVE)) { jObject.put("type", "comp"); + } else if (questController.getQuestData().getEventType().equals(EventType.COLLECTIVE)) { + jObject.put("type", "coll"); } else { jObject.put("type", "coop"); } @@ -130,8 +133,8 @@ public void readAndInitializeQuests() { double amount = (double) obj.get("amountComplete"); JSONArray mobNames = (JSONArray) obj.get("mobNames"); JSONArray materials = (JSONArray) obj.get("materials"); - JSONArray customNames = (JSONArray) obj.get("customMobNames"); - JSONArray customModelIds = (JSONArray) obj.get("customModelIds"); + JSONArray customNames = (JSONArray) obj.get("customNames"); + JSONArray customModelIds = (JSONArray) obj.get("modelIds"); List materialList = convertJsonArrayToList(materials, String.class).stream() .map(materialName -> { diff --git a/src/main/java/me/wonka01/ServerQuests/enums/EventType.java b/src/main/java/me/wonka01/ServerQuests/enums/EventType.java index 97e63b8..3ebd578 100644 --- a/src/main/java/me/wonka01/ServerQuests/enums/EventType.java +++ b/src/main/java/me/wonka01/ServerQuests/enums/EventType.java @@ -3,5 +3,5 @@ public enum EventType { COLLAB, COMPETITIVE, - GOAL + COLLECTIVE } diff --git a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java index d126f2e..9e04db0 100644 --- a/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java +++ b/src/main/java/me/wonka01/ServerQuests/enums/ObjectiveType.java @@ -27,7 +27,7 @@ public enum ObjectiveType { CARVE_PUMPKIN("carvepumpkin", Material.CARVED_PUMPKIN), MOVEMENT("movement", Material.DIAMOND_BOOTS), BREW_POTION("brewpotion", Material.BREWING_STAND), - SMELT_ITEM("smeltitem", Material.FURNACE), + SMELT_ITEM("furnace", Material.FURNACE), COMMAND("command", Material.COMMAND_BLOCK), UNKNOWN("unknown", Material.AIR); diff --git a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java index 7c0b131..6b16703 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java +++ b/src/main/java/me/wonka01/ServerQuests/events/InventoryClickEvents.java @@ -3,7 +3,6 @@ import java.util.List; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -33,7 +32,7 @@ public InventoryClickEvents(ActiveQuests activeQuests, ServerQuests plugin) { this.plugin = plugin; } - private void markItemAsUnique(ItemStack item) { + private void markItemAsProcessed(ItemStack item) { ItemMeta meta = item.getItemMeta(); PersistentDataContainer container = meta.getPersistentDataContainer(); NamespacedKey uniqueKey = new NamespacedKey(plugin, "processed"); @@ -47,7 +46,6 @@ private boolean isItemProcessed(ItemStack item) { ItemMeta meta = item.getItemMeta(); PersistentDataContainer container = meta.getPersistentDataContainer(); - NamespacedKey uniqueKey = new NamespacedKey(plugin, "processed"); return container.has(uniqueKey, PersistentDataType.STRING); @@ -67,19 +65,14 @@ public void onInventoryClick(InventoryClickEvent event) { || event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) { List controllers = tryGetControllersOfObjectiveType(BREW_TYPE); - Bukkit.getLogger().info("Brewing item " + item.getType().toString()); PotionMeta potionMeta = (PotionMeta) item.getItemMeta(); - if (potionMeta == null) { - Bukkit.getLogger().info("PotionMeta is null for item " + item.getType().toString()); - return; - } - + // Make sure potion hasn't already been used for a community quest if (isItemProcessed(item)) { return; } - markItemAsUnique(item); + markItemAsProcessed(item); for (QuestController controller : controllers) { updateQuest(controller, player, 1, ObjectiveType.BREW_POTION, potionMeta.getBasePotionData().getType()); diff --git a/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java index 55d9182..038f597 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java @@ -55,7 +55,7 @@ protected void setContents() { .collect(Collectors.joining("")); boolean isValid = (goal > 0 || !dynamicGoal.isEmpty()) && model.getCompleteTime() > 0; List lore = Collections - .singletonList(isValid ? "&fPlayers who reach the objective before time runs out will receive a reward!" + .singletonList(isValid ? "&fComplete the objective before time runs out to receive a reward!" : "&2Quest can not be collective, collective quests must have a time limit and a goal."); String title = getPlugin().messages().string("collective"); @@ -86,7 +86,7 @@ protected void onItemClick(@NonNull InventoryClickEvent event) { startQuest(EventType.COLLAB); break; case COLL: - startQuest(EventType.GOAL); + startQuest(EventType.COLLECTIVE); break; case BACK: new StartMenu(getPlugin(), getOwner()).open(); diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java b/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java index 4086e27..21317f6 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/Objective.java @@ -58,8 +58,8 @@ public JSONObject toJsonObject() { objectiveJson.put("amountComplete", amountComplete); Gson gson = new Gson(); objectiveJson.put("mobNames", gson.toJsonTree(mobNames).getAsJsonArray()); - objectiveJson.put("customMobNames", gson.toJsonTree(customNames).getAsJsonArray()); - objectiveJson.put("customModelIds", gson.toJsonTree(customModelIds).getAsJsonArray()); + objectiveJson.put("customNames", gson.toJsonTree(customNames).getAsJsonArray()); + objectiveJson.put("modelIds", gson.toJsonTree(customModelIds).getAsJsonArray()); objectiveJson.put("materials", gson.toJsonTree(materials).getAsJsonArray()); objectiveJson.put("description", description); return objectiveJson; diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java index 172d61c..b74d814 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -1,7 +1,7 @@ package me.wonka01.ServerQuests.objectives; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; +import me.wonka01.ServerQuests.utils.Utils; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -39,7 +39,12 @@ public Builder withType(ObjectiveType type) { public Builder withItem(ItemStack item) { if (item != null) { this.material = item.getType(); + this.customName = item.getItemMeta().getDisplayName(); this.customModelId = Utils.getCustomModelData(item); + + if (this.customName == null || this.customName.isEmpty()) { + this.customName = item.getType().name().replace("_", " ").toLowerCase(); + } } return this; } @@ -122,6 +127,10 @@ public boolean matches(Objective objective) { // Custom model ID filter if (customModelId != null) { + Bukkit.getLogger().info("Custom model id: " + customModelId); + if (!objective.getCustomModelIds().isEmpty()) { + Bukkit.getLogger().info("Objective custom names: " + objective.getCustomModelIds().get(0)); + } if (!hasCustomModelId(objective, customModelId) && !objective.getCustomModelIds().isEmpty()) { return false; } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/CollectiveQuestData.java similarity index 93% rename from src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java rename to src/main/java/me/wonka01/ServerQuests/questcomponents/CollectiveQuestData.java index fadc3a5..4b259c6 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/GoalQuestData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/CollectiveQuestData.java @@ -12,12 +12,12 @@ import lombok.Getter; -public class GoalQuestData extends QuestData { +public class CollectiveQuestData extends QuestData { @Getter private PlayerContributionMap players; - public GoalQuestData(String displayName, String description, + public CollectiveQuestData(String displayName, String description, PlayerContributionMap players, String questType, int durationLeft, Material displayItem, String questId, String afterQuestCommand, String beforeQuestCommand, List objectives, String questFailedCommand, List rewardDisplay) { @@ -66,6 +66,6 @@ public boolean isGoalComplete(Objective objective, Player player, Integer object @Override public EventType getEventType() { - return EventType.GOAL; + return EventType.COLLECTIVE; } } diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java index 57dc132..22393e0 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestController.java @@ -2,7 +2,6 @@ import lombok.Getter; import lombok.NonNull; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.enums.EventType; import me.wonka01.ServerQuests.enums.ObjectiveType; @@ -10,7 +9,9 @@ import me.wonka01.ServerQuests.questcomponents.bossbar.QuestBar; import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import me.wonka01.ServerQuests.questcomponents.schedulers.QuestTimer; +import me.wonka01.ServerQuests.utils.Colorization; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import java.text.DecimalFormat; @@ -50,8 +51,8 @@ public boolean updateQuest(double count, Player player, Objective objective, Int if (competitiveQuestData.isGoalComplete(objective, player, objectiveId)) { return false; } - } else if (questData.getEventType().equals(objectiveId)) { - GoalQuestData goalQuest = (GoalQuestData) questData; + } else if (questData.getEventType().equals(EventType.COLLECTIVE)) { + CollectiveQuestData goalQuest = (CollectiveQuestData) questData; if (goalQuest.isGoalComplete(objective, player, objectiveId)) { return false; } @@ -61,14 +62,18 @@ public boolean updateQuest(double count, Player player, Objective objective, Int } } - if (questData.hasGoal() && questData.getEventType().equals(EventType.COLLAB)) { - if (amountToAdd > objective.getGoal() - objective.getAmountComplete()) { - amountToAdd = objective.getGoal() - objective.getAmountComplete(); + if (questData.hasGoal()) { + double amountComplete = objective.getAmountComplete(); + + if (questData.getEventType().equals(EventType.COMPETITIVE)) { + CompetitiveQuestData competitiveQuestData = (CompetitiveQuestData) questData; + amountComplete = competitiveQuestData.getPlayers().getAmountContributedByObjectiveId(player, + objectiveId); + } else if (questData.getEventType().equals(EventType.COLLECTIVE)) { + CollectiveQuestData goalQuest = (CollectiveQuestData) questData; + amountComplete = goalQuest.getPlayers().getAmountContributedByObjectiveId(player, objectiveId); } - } else if (questData.hasGoal() && questData.getEventType().equals(EventType.COMPETITIVE)) { - CompetitiveQuestData competitiveQuestData = (CompetitiveQuestData) questData; - double amountComplete = competitiveQuestData.getPlayers().getAmountContributedByObjectiveId(player, - objectiveId); + if (amountToAdd > objective.getGoal() - amountComplete) { amountToAdd = objective.getGoal() - amountComplete; } @@ -84,11 +89,13 @@ public boolean updateQuest(double count, Player player, Objective objective, Int updateBossBar(); sendPlayerMessage(player, amountToAdd); + // save to file every 100 actions if (questData.getAmountCompleted() % 100 == 0) { plugin.getJsonSave().saveQuestsInProgress(); } if (getQuestData().isGoalComplete()) { + Bukkit.getLogger().info("Quest complete"); endQuest(); } return getQuestData().isGoalComplete(); @@ -127,7 +134,7 @@ public boolean isCompetitive() { } public boolean isGoalQuest() { - return (questData.getEventType().equals(EventType.GOAL)); + return (questData.getEventType().equals(EventType.COLLECTIVE)); } private void updateBossBar() { diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java index 9281218..89c102b 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java @@ -25,8 +25,8 @@ public QuestTypeHandler(EventType eventType) { } public QuestTypeHandler(String type) { - if (type.equalsIgnoreCase("goal")) { - eventType = EventType.GOAL; + if (type.equalsIgnoreCase("coll")) { + eventType = EventType.COLLECTIVE; } else { eventType = type.equalsIgnoreCase("comp") ? EventType.COMPETITIVE : EventType.COLLAB; } @@ -89,7 +89,7 @@ private QuestData getQuestData(QuestModel questModel, PlayerContributionMap play questModel.getBeforeQuestCommand(), objectives, questModel.getQuestFailedCommand(), questModel.getRewardDisplay()); } else { - return new GoalQuestData(questModel.getDisplayName(), + return new CollectiveQuestData(questModel.getDisplayName(), questModel.getEventDescription(), playerComponent, questModel.getQuestId(), timeLeft, questModel.getDisplayItem(), questModel.getQuestId(), questModel.getAfterQuestCommand(), questModel.getBeforeQuestCommand(), objectives, questModel.getQuestFailedCommand(), diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java index 61a2bbf..0c5e76c 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java @@ -197,7 +197,7 @@ public void giveOutRewards(double questGoal, String completeMessage, EventType e OfflinePlayer player = Bukkit.getServer().getOfflinePlayer(playerData.getUuid()); RewardManager rewardManager = RewardManager.getInstance(); - if (eventType == EventType.GOAL) { + if (eventType == EventType.COLLECTIVE) { if (playerContribution >= questGoal) { playerContributionRatio = 1.0; } else { @@ -210,7 +210,6 @@ public void giveOutRewards(double questGoal, String completeMessage, EventType e if (rankedReward.size() > 0) { // ServerQuests plugin = JavaPlugin.getPlugin(ServerQuests.class); // String rewardsMessage = plugin.messages().message("rewardsMessage"); - onlinePlayer.sendMessage("rewards size " + rankedReward.size()); for (Reward reward : rankedReward) { reward.giveRewardToPlayer(onlinePlayer, playerContributionRatio); } diff --git a/src/main/java/me/knighthat/apis/utils/Colorization.java b/src/main/java/me/wonka01/ServerQuests/utils/Colorization.java similarity index 100% rename from src/main/java/me/knighthat/apis/utils/Colorization.java rename to src/main/java/me/wonka01/ServerQuests/utils/Colorization.java diff --git a/src/main/java/me/knighthat/apis/utils/Utils.java b/src/main/java/me/wonka01/ServerQuests/utils/Utils.java similarity index 97% rename from src/main/java/me/knighthat/apis/utils/Utils.java rename to src/main/java/me/wonka01/ServerQuests/utils/Utils.java index 71ef0f4..2a3658f 100644 --- a/src/main/java/me/knighthat/apis/utils/Utils.java +++ b/src/main/java/me/wonka01/ServerQuests/utils/Utils.java @@ -1,4 +1,4 @@ -package me.knighthat.apis.utils; +package me.wonka01.ServerQuests.utils; import lombok.NonNull; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 488fd3b..6cc58c8 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -13,9 +13,12 @@ donateMenuItem: BLACK_STAINED_GLASS_PANE # If true, blockbreak quests will not be able to break the same item multiple # times in a row. disableDuplicateBreaks: false + +barColor: "GREEN" + # If true, blockplace quests will not be able to place the same item multiple # times in a row. -disableDuplicatePlaces: false +disableDuplicatePlaces: true ## configure the location and text of a hologram that displays quest information hologram: @@ -36,6 +39,37 @@ hologram: Quests: TestQuest: # Quest identifier can be whatever you'd like as long as it's unique + displayName: "&cBasalt Zerstörer" + displayItem: BASALT # optional parameter to set the item used in GUIs for a given quest + # See color options here: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarColor.html + barColor: "GREEN" + barStyle: "SEGMENTED_20" + worlds: # this parameter is optional, if included the quest will only occur in the specified worlds + - WL + - world + - WL_nether + objectives: # at least one objective is required, each quest can have infinite objectives + - type: donate + goal: 10000000 + materials: + - BASALT + description: "Liefert insgesamt 10.000.000 Basalt" + questDuration: 21d # The quest will last for 1 day or until the goal is reached, whichever comes first + rewards: + rankedRewards: + "1": # The key is the rank of the player + experience: 10000 + commands: + - "gems add %player% 10000" + "2": + experience: 5000 + commands: + - "gems add %player% 5000" + "*": # This is a wildcard, this reward will apply to all other players who participated in the quest and didn't get a ranked reward + experience: 2500 + commands: + - "eco add %player% 10000" + ZombieQuest: # Quest identifier can be whatever you'd like as long as it's unique displayName: "&cZombie and Pig Slayer" displayItem: ZOMBIE_HEAD # optional parameter to set the item used in GUIs for a given quest # See color options here: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarColor.html @@ -45,17 +79,12 @@ Quests: - world objectives: # at least one objective is required, each quest can have infinite objectives - type: mobkill ## required, see type list for available types - dynamicGoal: "%server_online%" + dynamicGoal: "%math_{server_online}*1000%" entities: # This is an optional parameter, if it doesn't exist the quest will count ALL mob kills. entity reference: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html - Zombie - Pig - ZOMBIFIED_PIGLIN description: "Zombies & Pigs" # A short description of the objective used in the GUI - - type: mobkill - goal: 5 - customMobNames: - - Skeleton - description: Skeletons description: "Kill 100 zombies and pigs! \nKill 50 skeletons!" questDuration: 1d # The quest will last for 1 day or until the goal is reached, whichever comes first rewards: @@ -78,21 +107,120 @@ Quests: - material: stone_sword amount: 1 displayName: "&8Stone Sword" + brewPotion: + displayName: "&6&lPotion Master" + displayItem: BREWING_STAND + objectives: + - type: brewpotion + goal: 5 + description: "&cHealth Potions" + # https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionType.html + potions: + - INSTANT_HEAL + - STRONG_HEALING + - type: brewpotion + goal: 5 + description: "&6Regen Potions" + potions: + - LONG_REGENERATION + - REGENERATION + - STRONG_REGENERATION + description: "&fBrew 5 healing and 5 regen potions!" + rewards: + rewardDisplay: + - "&a&lRewards" + - "&f- &b15 Diamonds" + - "&f- &b100 Experience" + rankedRewards: + "1": + experience: 100 + items: + - material: DIAMOND + amount: 15 + displayName: "&bDiamond!" + rewardMessage: "&6You have been rewarded with a diamond and 100 experience for completing the quest!" + enchantItem: + displayName: "&6Enchant Item" + displayItem: ENCHANTING_TABLE + objectives: + - type: enchantitem + goal: 5 + description: "&6Enchantments" + materials: + - DIAMOND_SWORD + enchantments: + - SHARPNESS + - KNOCKBACK + description: "&fEnchant 5 diamond swords with sharpness or knockback" + rewards: + rankedRewards: + "1": + experience: 100 + items: + - material: DIAMOND + amount: 1 + displayName: "&bDiamond!" + rewardMessage: "&6You have been rewarded with a diamond!" + smeltIron: + displayName: "&6Smelt Iron" + displayItem: IRON_INGOT + description: "&6Smelt 10 iron ore into iron ingots" + questDuration: 1h + objectives: + - type: furnace + goal: 10 + materials: + - IRON_INGOT + description: "&6Iron Ingots" + - type: smeltitem + goal: 10 + customNames: + - "Cooked Cod" + description: "&6Cod" + rewards: + experience: 100 + items: + - material: DIAMOND + amount: 1 + displayName: "&bDiamond" + logs: + displayName: "&2Im a lumberjack" + description: "&2chop 500 logs of each type of wood" + displayItem: OAK_WOOD + objectives: + - type: blockbreak + goal: 5 + materials: + - OAK_LOG + description: "&2oak wood" Egg: displayName: "&6Eggcellent" displayItem: EGG questDuration: 7d - barColor: "WHITE" + barColor: "RED" barStyle: "SEGMENTED_20" objectives: - - type: donate - materials: - - EGG + - type: milkcow + goal: 20 description: H1 needs some cake, you can get some eggs! rewards: items: - material: CHICKEN_SPAWN_EGG amount: 1 + ShearSheep: + displayName: "&6Shear Sheep" + displayItem: SHEARS + questDuration: 7d + barColor: "YELLOW" + barStyle: "SEGMENTED_20" + objectives: + - type: shear + goal: 20 + description: "Shear 20 sheep!" + rewards: + items: + - material: CHICKEN_SPAWN_EGG + amount: 1 MoveIt: displayName: "&6Movement Quest" displayItem: DIAMOND_BOOTS @@ -180,19 +308,19 @@ Quests: amount: 1 displayName: "&8Stone Sword" GuiQuest: - displayName: "&a&lPotato Diamond Quest" + displayName: "&l&bDiamond Miner" objectives: - type: donate goal: 60 materials: - - POTATO + - DIAMOND description: "&l&aPotatoes" - type: donate goal: 20 materials: - - DIAMOND + - POTATO description: "&l&aDiamonds" - description: "&fDonate 60 potatoes and 20 diamonds with /cq donate!" + description: '&fThe royal family is in dire need of diamonds. Bring us 60 diamonds and we will reward you handsomely! \n&fAlso throw in 20 potatoes for the next royal feast!' rewards: rankedRewards: "1": # The key is the rank of the player @@ -287,7 +415,8 @@ Quests: displayName: "&bPowerful Diamond Sword" MythicQuest: displayName: "&c&lKill mythic mobs" - objective: + # displayItem: DRAGON_HEAD + objectives: - type: mythicmob goal: 4 description: "Spiderz" diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 5bada2d..4b96baf 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -4,7 +4,7 @@ reloadCommand: "&AThe Community Quests configuration has reloaded successfully." helpMessage: "&eThe Community Quests plugin allows servers to run quests that the entire server either works together or competes against one another to complete an objective. To view active quests use /cq view, to begin a new quests use /cq start. For donation quests, use the /cq donate command to open up the donation GUI." noActiveDonateQuests: "&cThere are no active quests that require you to donate items." invalidQuestName: "&cThe quest name you entered does not exist" -invalidQuestType: "&cYou must enter a quest type; coop or comp" +invalidQuestType: "&cYou must enter a quest type; coop, comp or coll" noActiveQuests: "&cThere are currently no active quests running on the server." questLimitReached: "&cThe quest could not be created, the number of active quests has reached its limit" endAllQuestsMessage: "&cAll active quests have been ended" From dd7f8fc4fed12333d9abe01472813c11907a84bf Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sun, 8 Dec 2024 20:54:20 +0000 Subject: [PATCH 17/20] cleanup --- src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java | 2 +- .../me/wonka01/ServerQuests/objectives/ObjectiveFilters.java | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java index 038f597..0393b6c 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/TypeMenu.java @@ -56,7 +56,7 @@ protected void setContents() { boolean isValid = (goal > 0 || !dynamicGoal.isEmpty()) && model.getCompleteTime() > 0; List lore = Collections .singletonList(isValid ? "&fComplete the objective before time runs out to receive a reward!" - : "&2Quest can not be collective, collective quests must have a time limit and a goal."); + : "&cCollective quests need a time limit and a goal."); String title = getPlugin().messages().string("collective"); if (title == null || title.isEmpty()) { diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java index b74d814..3ce38dd 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -3,7 +3,6 @@ import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.utils.Utils; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; @@ -127,10 +126,6 @@ public boolean matches(Objective objective) { // Custom model ID filter if (customModelId != null) { - Bukkit.getLogger().info("Custom model id: " + customModelId); - if (!objective.getCustomModelIds().isEmpty()) { - Bukkit.getLogger().info("Objective custom names: " + objective.getCustomModelIds().get(0)); - } if (!hasCustomModelId(objective, customModelId) && !objective.getCustomModelIds().isEmpty()) { return false; } From 2b4d7cbb60d23bca2be48e43d804a125b4edcdb9 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sat, 1 Feb 2025 15:00:22 +0000 Subject: [PATCH 18/20] fix issue with placeholder/holograms, better # formatting --- .../java/me/knighthat/apis/files/Getters.java | 2 +- .../java/me/knighthat/apis/menus/Menu.java | 3 +- .../me/wonka01/ServerQuests/ServerQuests.java | 17 +++---- .../ServerQuests/commands/PluginCommand.java | 2 +- .../ServerQuests/commands/QuestCommand.java | 47 ------------------- .../configuration/JsonQuestSave.java | 19 +++++--- .../configuration/QuestModel.java | 2 +- .../ServerQuests/events/HarvestEvent.java | 1 - .../wonka01/ServerQuests/gui/DonateMenu.java | 2 +- .../me/wonka01/ServerQuests/gui/StopMenu.java | 3 +- .../ServerQuests/gui/ViewHistoryMenu.java | 2 +- .../me/wonka01/ServerQuests/gui/ViewMenu.java | 2 +- .../questcomponents/QuestData.java | 2 +- .../questcomponents/bossbar/QuestBar.java | 3 +- .../players/PlayerContributionMap.java | 4 +- .../rewards/RewardMessage.java | 2 +- .../rewards/types/ExperienceReward.java | 2 +- .../rewards/types/ItemReward.java | 2 +- .../rewards/types/MoneyReward.java | 2 +- .../ServerQuests/utils/Colorization.java | 2 +- .../me/wonka01/ServerQuests/utils/Utils.java | 2 +- .../CommunityQuestsPlaceholders.java | 18 ++++--- src/main/resources/config.yml | 2 +- 23 files changed, 52 insertions(+), 91 deletions(-) delete mode 100644 src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java diff --git a/src/main/java/me/knighthat/apis/files/Getters.java b/src/main/java/me/knighthat/apis/files/Getters.java index 5b5de82..04f5f16 100644 --- a/src/main/java/me/knighthat/apis/files/Getters.java +++ b/src/main/java/me/knighthat/apis/files/Getters.java @@ -1,8 +1,8 @@ package me.knighthat.apis.files; import lombok.NonNull; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.utils.Colorization; public abstract class Getters extends PluginFiles implements Colorization { diff --git a/src/main/java/me/knighthat/apis/menus/Menu.java b/src/main/java/me/knighthat/apis/menus/Menu.java index b429ca0..2cb81dd 100644 --- a/src/main/java/me/knighthat/apis/menus/Menu.java +++ b/src/main/java/me/knighthat/apis/menus/Menu.java @@ -8,7 +8,8 @@ import me.wonka01.ServerQuests.questcomponents.QuestController; import me.wonka01.ServerQuests.questcomponents.QuestData; import me.wonka01.ServerQuests.questcomponents.schedulers.ParseDurationString; -import me.knighthat.apis.utils.Colorization; +import me.wonka01.ServerQuests.utils.Colorization; + import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; diff --git a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java index ad3b870..7b2b822 100644 --- a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java +++ b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java @@ -71,8 +71,9 @@ public void onEnable() { } registerPlaceholders(); - if (!setupDecentHologram() && getConfig().getBoolean("hologram.enabled")) { - getLogger().info("Warning! DecentHolograms not found, holograms will not work."); + if (!setupDecentHologram()) { + getLogger() + .info("Warning! DecentHolograms not found or no placeholder api found, holograms will not work."); } else if (getConfig().getBoolean("hologram.enabled")) { hologram = new DecentHologramsDisplay(this); hologram.displayHologram(); @@ -88,17 +89,9 @@ public void onEnable() { try { Metrics metrics = new Metrics(this, pluginId); - metrics.addCustomChart(new Metrics.SingleLineChart("players", new Callable() { - @Override - public Integer call() throws Exception { - // (This is useless as there is already a player chart by default.) - return Bukkit.getOnlinePlayers().size(); - } - })); metrics.addCustomChart(new Metrics.SingleLineChart("active_quests", new Callable() { @Override public Integer call() throws Exception { - // (This is useless as there is already a player chart by default.) return ActiveQuests.getActiveQuestsInstance().getActiveQuestsList().size(); } })); @@ -155,7 +148,9 @@ private boolean setupMythicMobs() { } private boolean setupDecentHologram() { - return Bukkit.getPluginManager().getPlugin("DecentHolograms") != null; + boolean isEnabled = Bukkit.getPluginManager().getPlugin("DecentHolograms") != null && isPlaceholderApiEnabled; + getLogger().info("DecentHolograms is enabled: " + isEnabled); + return isEnabled; } private void registerQuestEvents() { diff --git a/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java index 1b2dd14..a39be05 100644 --- a/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java +++ b/src/main/java/me/wonka01/ServerQuests/commands/PluginCommand.java @@ -2,8 +2,8 @@ import lombok.Getter; import lombok.NonNull; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.utils.Colorization; import java.util.List; diff --git a/src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java b/src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java deleted file mode 100644 index 778ea92..0000000 --- a/src/main/java/me/wonka01/ServerQuests/commands/QuestCommand.java +++ /dev/null @@ -1,47 +0,0 @@ -package me.wonka01.ServerQuests.commands; - -import lombok.NonNull; -import me.wonka01.ServerQuests.ServerQuests; -import me.wonka01.ServerQuests.gui.ViewMenu; -import me.wonka01.ServerQuests.questcomponents.ActiveQuests; - -import java.util.List; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public class QuestCommand extends PluginCommand { - public QuestCommand(ServerQuests plugin) { - super(plugin, true); - } - - @Override - public @NonNull String getName() { - return "quest"; - } - - @Override - public @NonNull String getPermission() { - return "communityquests.start"; - } - - @Override - public void execute(@NonNull CommandSender sender, @NotNull @NonNull String[] args) { - Player player = (Player) sender; - - if (ActiveQuests.getActiveQuestsInstance().getActiveQuestsList().isEmpty()) { - String noActiveQuestMessage = getPlugin().messages().message("noActiveQuests"); - player.sendMessage(noActiveQuestMessage); - return; - } - new ViewMenu(getPlugin(), player).open(); - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - // TODO Auto-generated method stub - return null; - } -} diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java index b0e36d0..065e37d 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/JsonQuestSave.java @@ -90,17 +90,20 @@ public void saveQuestsInProgress() { } } - // public List fromArrayToList(T[] a) { - // return Arrays.stream(a).collect(Collectors.toList()); - // } - private List convertJsonArrayToList(JSONArray arr, Class clazz) { List list = new ArrayList<>(); if (arr == null) { return list; } for (Object o : arr) { - list.add(clazz.cast(o)); + if (clazz == Integer.class && o instanceof Long) { + list.add(clazz.cast(((Long) o).intValue())); // Convert Long to Integer + } else if (clazz.isInstance(o)) { + list.add(clazz.cast(o)); // Safe cast for other types + } else { + throw new IllegalArgumentException( + "Cannot convert " + o.getClass().getName() + " to " + clazz.getName()); + } } return list; } @@ -166,7 +169,11 @@ public void readAndInitializeQuests() { UUID uuidKey = null; String playerName = (String) obj.get("name"); - long lastUpdated = (Long) obj.get("lastUpdated"); + Object lastUpdatedObj = obj.get("lastUpdated"); + long lastUpdated = System.currentTimeMillis(); + if (lastUpdatedObj != null) { + lastUpdated = (Long) lastUpdatedObj; + } while (keys.hasNext()) { String key = keys.next(); diff --git a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java index 6c87707..e705ac1 100644 --- a/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java +++ b/src/main/java/me/wonka01/ServerQuests/configuration/QuestModel.java @@ -1,11 +1,11 @@ package me.wonka01.ServerQuests.configuration; import lombok.Getter; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; import me.wonka01.ServerQuests.questcomponents.schedulers.ParseDurationString; +import me.wonka01.ServerQuests.utils.Utils; import org.bukkit.Material; import org.bukkit.boss.BarStyle; diff --git a/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java b/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java index 36900a5..5c2babe 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java +++ b/src/main/java/me/wonka01/ServerQuests/events/HarvestEvent.java @@ -8,7 +8,6 @@ import org.bukkit.event.player.PlayerHarvestBlockEvent; import org.bukkit.inventory.ItemStack; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; diff --git a/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java index d9219f4..972e8c1 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/DonateMenu.java @@ -4,7 +4,6 @@ import lombok.NonNull; import lombok.Setter; import me.knighthat.apis.menus.Menu; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; @@ -12,6 +11,7 @@ import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.CompetitiveQuestData; import me.wonka01.ServerQuests.questcomponents.QuestController; +import me.wonka01.ServerQuests.utils.Utils; import org.bukkit.Material; import org.bukkit.World; diff --git a/src/main/java/me/wonka01/ServerQuests/gui/StopMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/StopMenu.java index 1d041a7..293b906 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/StopMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/StopMenu.java @@ -2,11 +2,12 @@ import lombok.NonNull; import me.knighthat.apis.menus.Menu; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; import me.wonka01.ServerQuests.questcomponents.QuestData; +import me.wonka01.ServerQuests.utils.Utils; + import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.ItemStack; diff --git a/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java index 006ae1c..0e0f608 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java @@ -1,9 +1,9 @@ package me.wonka01.ServerQuests.gui; import me.knighthat.apis.menus.Menu; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.configuration.QuestHistoryManager; +import me.wonka01.ServerQuests.utils.Utils; import org.bukkit.Bukkit; import org.bukkit.Material; diff --git a/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java index 2fd9c6f..f616fc1 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/ViewMenu.java @@ -2,7 +2,6 @@ import lombok.NonNull; import me.knighthat.apis.menus.Menu; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.configuration.QuestModel; import me.wonka01.ServerQuests.objectives.Objective; @@ -11,6 +10,7 @@ import me.wonka01.ServerQuests.questcomponents.QuestData; import me.wonka01.ServerQuests.questcomponents.players.PlayerContributionMap; import me.wonka01.ServerQuests.questcomponents.players.PlayerData; +import me.wonka01.ServerQuests.utils.Utils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java index 473ae41..337bec4 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestData.java @@ -3,11 +3,11 @@ import lombok.Getter; import lombok.NonNull; import me.clip.placeholderapi.PlaceholderAPI; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.enums.EventType; import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.objectives.Objective; +import me.wonka01.ServerQuests.utils.Colorization; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java index 4d7b5f2..a6ed39d 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/bossbar/QuestBar.java @@ -2,7 +2,8 @@ import lombok.NonNull; import lombok.Setter; -import me.knighthat.apis.utils.Colorization; +import me.wonka01.ServerQuests.utils.Colorization; + import org.bukkit.Bukkit; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java index 0c5e76c..b251bab 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/players/PlayerContributionMap.java @@ -1,11 +1,11 @@ package me.wonka01.ServerQuests.questcomponents.players; -import me.knighthat.apis.utils.Colorization; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.rewards.RewardManager; import me.wonka01.ServerQuests.questcomponents.rewards.RewardMessage; import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; +import me.wonka01.ServerQuests.utils.Colorization; +import me.wonka01.ServerQuests.utils.Utils; import me.wonka01.ServerQuests.enums.EventType; import org.bukkit.Bukkit; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardMessage.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardMessage.java index fb2dc15..e4e2d3c 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardMessage.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/RewardMessage.java @@ -1,8 +1,8 @@ package me.wonka01.ServerQuests.questcomponents.rewards; import lombok.Getter; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.questcomponents.rewards.types.Reward; +import me.wonka01.ServerQuests.utils.Colorization; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java index dd5a0ae..ba65695 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ExperienceReward.java @@ -1,8 +1,8 @@ package me.wonka01.ServerQuests.questcomponents.rewards.types; import lombok.Getter; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.utils.Colorization; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ItemReward.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ItemReward.java index b24b058..3b1217c 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ItemReward.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/ItemReward.java @@ -2,8 +2,8 @@ import lombok.Getter; import lombok.NonNull; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.utils.Colorization; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java index 92bcd07..aa9d1f1 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/rewards/types/MoneyReward.java @@ -1,8 +1,8 @@ package me.wonka01.ServerQuests.questcomponents.rewards.types; import lombok.Getter; -import me.knighthat.apis.utils.Colorization; import me.wonka01.ServerQuests.ServerQuests; +import me.wonka01.ServerQuests.utils.Colorization; import net.milkbowl.vault.economy.Economy; import org.bukkit.OfflinePlayer; import org.bukkit.plugin.java.JavaPlugin; diff --git a/src/main/java/me/wonka01/ServerQuests/utils/Colorization.java b/src/main/java/me/wonka01/ServerQuests/utils/Colorization.java index 54ceb8b..2d28c92 100644 --- a/src/main/java/me/wonka01/ServerQuests/utils/Colorization.java +++ b/src/main/java/me/wonka01/ServerQuests/utils/Colorization.java @@ -1,4 +1,4 @@ -package me.knighthat.apis.utils; +package me.wonka01.ServerQuests.utils; import lombok.NonNull; import org.bukkit.ChatColor; diff --git a/src/main/java/me/wonka01/ServerQuests/utils/Utils.java b/src/main/java/me/wonka01/ServerQuests/utils/Utils.java index 2a3658f..1f11364 100644 --- a/src/main/java/me/wonka01/ServerQuests/utils/Utils.java +++ b/src/main/java/me/wonka01/ServerQuests/utils/Utils.java @@ -32,7 +32,7 @@ static boolean contains(@Nullable F[] from, @Nullable V value) { } static @NonNull String decimalToString(double a) { - DecimalFormat format = new DecimalFormat("0.#"); + DecimalFormat format = new DecimalFormat("#,###.#"); return format.format(a); } diff --git a/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java b/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java index be551a9..6a29294 100644 --- a/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java +++ b/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java @@ -1,13 +1,13 @@ package me.wonka01.placeholders; import me.clip.placeholderapi.expansion.PlaceholderExpansion; -import me.knighthat.apis.utils.Colorization; -import me.knighthat.apis.utils.Utils; import me.wonka01.ServerQuests.ServerQuests; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; import me.wonka01.ServerQuests.questcomponents.QuestData; import me.wonka01.ServerQuests.questcomponents.schedulers.ParseDurationString; +import me.wonka01.ServerQuests.utils.Colorization; +import me.wonka01.ServerQuests.utils.Utils; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -77,7 +77,7 @@ public String onRequest(OfflinePlayer player, String identifier) { // %communityquests_goal_% if (identifier.startsWith("goal")) { - return String.valueOf(questData.getQuestGoal()); + return formatNumber(questData.getQuestGoal()); } // %communityquests_complete_questId% @@ -120,8 +120,8 @@ public String onRequest(OfflinePlayer player, String identifier) { // %communityquests_you_questId% if (identifier.startsWith("you")) { if (player.isOnline()) { - int playerContribution = (int) controller.getPlayerComponent().getAmountContributed((Player) player); - return "" + playerContribution; + double playerContribution = controller.getPlayerComponent().getAmountContributed((Player) player); + return formatNumber(playerContribution); } return "0"; } @@ -129,14 +129,14 @@ public String onRequest(OfflinePlayer player, String identifier) { // %communityquests_objective_goal_objId_questId% if (identifier.startsWith("objective_goal")) { int index = extractIndex(identifier.replace(questId, "")); - return "" + questData.getObjectives().get(index).getGoal(); + return formatNumber(questData.getObjectives().get(index).getGoal()); } // %communityquests_objective_completed_objId_questId% if (identifier.startsWith("objective_completed")) { // get value of index from identifier and covert it to an integer int index = extractIndex(identifier.replace(questId, "")); - return "" + questData.getObjectives().get(index).getAmountComplete(); + return formatNumber(questData.getObjectives().get(index).getAmountComplete()); } // %communityquests_objective_objId_questId% @@ -175,6 +175,10 @@ public String onRequest(OfflinePlayer player, String identifier) { return null; } + private String formatNumber(Double number) { + return String.format("%,d", number); + } + public static int extractIndex(String input) { Pattern pattern = Pattern.compile("\\d+"); // Match one or more digits Matcher matcher = pattern.matcher(input); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6cc58c8..1d36e07 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -24,7 +24,7 @@ disableDuplicatePlaces: true hologram: # set to 0 or omit refresh-interval if you don't want it to refresh. Refresh is needed for dynamic placeholders refresh-interval: 60 - enabled: true + enabled: false location: world: world x: -78 From db226761674858d9a3a57a514078081657383705 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sat, 8 Feb 2025 14:58:37 +0000 Subject: [PATCH 19/20] bug fixes --- .../me/wonka01/ServerQuests/objectives/ObjectiveFilters.java | 4 +++- .../me/wonka01/placeholders/CommunityQuestsPlaceholders.java | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java index 3ce38dd..acc0f33 100644 --- a/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java +++ b/src/main/java/me/wonka01/ServerQuests/objectives/ObjectiveFilters.java @@ -38,7 +38,9 @@ public Builder withType(ObjectiveType type) { public Builder withItem(ItemStack item) { if (item != null) { this.material = item.getType(); - this.customName = item.getItemMeta().getDisplayName(); + if (item.hasItemMeta()) { + this.customName = item.getItemMeta().getDisplayName(); + } this.customModelId = Utils.getCustomModelData(item); if (this.customName == null || this.customName.isEmpty()) { diff --git a/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java b/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java index 6a29294..a723f4c 100644 --- a/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java +++ b/src/main/java/me/wonka01/placeholders/CommunityQuestsPlaceholders.java @@ -136,7 +136,8 @@ public String onRequest(OfflinePlayer player, String identifier) { if (identifier.startsWith("objective_completed")) { // get value of index from identifier and covert it to an integer int index = extractIndex(identifier.replace(questId, "")); - return formatNumber(questData.getObjectives().get(index).getAmountComplete()); + Double amountComplete = questData.getObjectives().get(index).getAmountComplete(); + return formatNumber(amountComplete); } // %communityquests_objective_objId_questId% @@ -176,7 +177,7 @@ public String onRequest(OfflinePlayer player, String identifier) { } private String formatNumber(Double number) { - return String.format("%,d", number); + return String.format("%,.0f", number); } public static int extractIndex(String input) { From 91ca15ca51c87536ab2eb77e537dc710ff31d2e5 Mon Sep 17 00:00:00 2001 From: wsaada19 Date: Sat, 31 May 2025 18:53:14 +0100 Subject: [PATCH 20/20] cleanup --- src/main/java/me/wonka01/ServerQuests/ServerQuests.java | 2 +- .../me/wonka01/ServerQuests/events/DistanceTraveled.java | 2 ++ .../java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java | 7 +++---- .../ServerQuests/questcomponents/QuestTypeHandler.java | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java index 7b2b822..0832bd8 100644 --- a/src/main/java/me/wonka01/ServerQuests/ServerQuests.java +++ b/src/main/java/me/wonka01/ServerQuests/ServerQuests.java @@ -149,7 +149,7 @@ private boolean setupMythicMobs() { private boolean setupDecentHologram() { boolean isEnabled = Bukkit.getPluginManager().getPlugin("DecentHolograms") != null && isPlaceholderApiEnabled; - getLogger().info("DecentHolograms is enabled: " + isEnabled); + getLogger().info("DecentHolograms enabled: " + isEnabled); return isEnabled; } diff --git a/src/main/java/me/wonka01/ServerQuests/events/DistanceTraveled.java b/src/main/java/me/wonka01/ServerQuests/events/DistanceTraveled.java index 8ae673b..530720a 100644 --- a/src/main/java/me/wonka01/ServerQuests/events/DistanceTraveled.java +++ b/src/main/java/me/wonka01/ServerQuests/events/DistanceTraveled.java @@ -3,6 +3,8 @@ import me.wonka01.ServerQuests.enums.ObjectiveType; import me.wonka01.ServerQuests.questcomponents.ActiveQuests; import me.wonka01.ServerQuests.questcomponents.QuestController; + +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; diff --git a/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java index 0e0f608..78620b9 100644 --- a/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java +++ b/src/main/java/me/wonka01/ServerQuests/gui/ViewHistoryMenu.java @@ -5,7 +5,6 @@ import me.wonka01.ServerQuests.configuration.QuestHistoryManager; import me.wonka01.ServerQuests.utils.Utils; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -27,7 +26,6 @@ public ViewHistoryMenu(ServerQuests plugin, Player owner) { @Override protected void setContents() { List> recentQuests = historyManager.getRecentQuests(45); // Get up to 45 recent quests - Bukkit.getLogger().info("Recent quests: " + recentQuests.size()); for (int i = 0; i < recentQuests.size() && i < 45; i++) { Map questData = recentQuests.get(i); @@ -44,8 +42,9 @@ private ItemStack createQuestHistoryItem(Material material, Map List lore = new ArrayList<>(); long completionTime = (Long) questData.get("completionTime"); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); - lore.add(color(getPlugin().messages().string("completed") + "&f" + sdf.format(new Date(completionTime)))); + // format date in a readable way + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy"); + lore.add(color(getPlugin().messages().string("completed") + "&f " + sdf.format(new Date(completionTime)))); lore.add(color(getPlugin().messages().string("topContributors"))); List topContributors = (List) questData.get("topContributors"); diff --git a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java index 89c102b..a7b0208 100644 --- a/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java +++ b/src/main/java/me/wonka01/ServerQuests/questcomponents/QuestTypeHandler.java @@ -50,8 +50,6 @@ public QuestController createControllerFromSave(@NonNull QuestModel model, @NonN barColor = plugin.getConfig().getString("barColor", "GREEN"); } - QuestBar bar = new QuestBar(model.getDisplayName(), barColor, model.getBarStyle()); - PlayerContributionMap pComponent = new PlayerContributionMap(model.getRewardLimit(), model.getRankedRewards()); @@ -67,6 +65,8 @@ public QuestController createControllerFromSave(@NonNull QuestModel model, @NonN QuestData data = getQuestData(model, pComponent, timeLeft, objs); + QuestBar bar = new QuestBar(data.getDisplayName(), barColor, model.getBarStyle()); + if (data.getAmountCompleted() > 0) { bar.updateBarProgress(data.getAmountCompleted() / data.getQuestGoal()); }