From c14b242cbd75217b1ee04c1dd5d06e91af8cb821 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 6 Oct 2018 08:49:49 -0700 Subject: [PATCH] Added admin complete command Other items are WIP --- pom.xml | 2 +- .../addon/challenges/ChallengesManager.java | 26 ++++ .../commands/ChallengesCommand.java | 7 +- .../challenges/commands/admin/Challenges.java | 4 +- .../commands/admin/CompleteChallenge.java | 77 ++++++++++++ .../addon/challenges/panel/AdminEditGUI.java | 64 ++++++++++ .../challenges/panel/ChallengesPanels2.java | 117 ++++++++++++------ src/main/resources/locales/en-US.yml | 6 +- 8 files changed, 260 insertions(+), 43 deletions(-) create mode 100644 src/main/java/bentobox/addon/challenges/commands/admin/CompleteChallenge.java create mode 100644 src/main/java/bentobox/addon/challenges/panel/AdminEditGUI.java diff --git a/pom.xml b/pom.xml index fce8045..df4732c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ us.tastybento Challenges - 0.0.3-SNAPSHOT + 0.1.0-SNAPSHOT Challenges Challenges is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like ASkyBlock or AcidIsland. diff --git a/src/main/java/bentobox/addon/challenges/ChallengesManager.java b/src/main/java/bentobox/addon/challenges/ChallengesManager.java index 68b1bbc..439bb64 100644 --- a/src/main/java/bentobox/addon/challenges/ChallengesManager.java +++ b/src/main/java/bentobox/addon/challenges/ChallengesManager.java @@ -190,6 +190,17 @@ public class ChallengesManager { return result; } + /** + * Get the list of all challenge unique names for world. + * @param world - the world to check + * @return List of challenge names + */ + public List getAllChallengesList(World world) { + List result = new ArrayList<>(); + challengeMap.values().forEach(ch -> ch.stream().filter(c -> c.getWorld().equals(Util.getWorld(world).getName())).forEach(c -> result.add(c.getUniqueId()))); + return result; + } + /** * Get challenge by name * @param name - unique name of challenge @@ -297,6 +308,21 @@ public class ChallengesManager { return false; } + /** + * Check if a challenge exists in world - case insensitive + * @param world - world to check + * @param name - name of challenge + * @return true if it exists, otherwise false + */ + public boolean isChallenge(World world, String name) { + for (Set ch : challengeMap.values()) { + if (ch.stream().filter(c -> c.getWorld().equals(Util.getWorld(world).getName())).anyMatch(c -> c.getUniqueId().equalsIgnoreCase(name))) { + return true; + } + } + return false; + } + /** * Checks if a challenge is complete or not * @param uniqueId - unique ID - player's UUID diff --git a/src/main/java/bentobox/addon/challenges/commands/ChallengesCommand.java b/src/main/java/bentobox/addon/challenges/commands/ChallengesCommand.java index b4b33f8..d8e9638 100644 --- a/src/main/java/bentobox/addon/challenges/commands/ChallengesCommand.java +++ b/src/main/java/bentobox/addon/challenges/commands/ChallengesCommand.java @@ -4,6 +4,7 @@ import java.util.List; import bentobox.addon.challenges.ChallengesAddon; import bentobox.addon.challenges.panel.ChallengesPanels2; +import bentobox.addon.challenges.panel.ChallengesPanels2.Mode; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; @@ -18,19 +19,19 @@ public class ChallengesCommand extends CompositeCommand { public boolean execute(User user, String label, List args) { // Open up the challenges GUI if (user.isPlayer()) { - new ChallengesPanels2((ChallengesAddon) getAddon(), user, args.isEmpty() ? "" : args.get(0), getWorld(), getPermissionPrefix(), getTopLabel(), false); + new ChallengesPanels2((ChallengesAddon) getAddon(), user, user, args.isEmpty() ? "" : args.get(0), getWorld(), getPermissionPrefix(), getTopLabel(), Mode.PLAYER); return true; } + // Show help + showHelp(this, user); return false; } @Override public void setup() { - this.setOnlyPlayer(true); this.setPermission(CHALLENGE_COMMAND); this.setParametersHelp(CHALLENGE_COMMAND + ".parameters"); this.setDescription(CHALLENGE_COMMAND + ".description"); - this.setOnlyPlayer(true); } diff --git a/src/main/java/bentobox/addon/challenges/commands/admin/Challenges.java b/src/main/java/bentobox/addon/challenges/commands/admin/Challenges.java index e16d2aa..b02ef9f 100644 --- a/src/main/java/bentobox/addon/challenges/commands/admin/Challenges.java +++ b/src/main/java/bentobox/addon/challenges/commands/admin/Challenges.java @@ -4,6 +4,7 @@ import java.util.List; import bentobox.addon.challenges.ChallengesAddon; import bentobox.addon.challenges.panel.ChallengesPanels2; +import bentobox.addon.challenges.panel.ChallengesPanels2.Mode; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; @@ -24,6 +25,7 @@ public class Challenges extends CompositeCommand { this.setDescription("challenges.admin.description"); // Register sub commands new ImportCommand(getAddon(), this); + new CompleteChallenge(getAddon(), this); //new ShowChallenges(getAddon(), this); //new CreateChallenge(getAddon(), this); @@ -33,7 +35,7 @@ public class Challenges extends CompositeCommand { public boolean execute(User user, String label, List args) { // Open up the admin challenges GUI if (user.isPlayer()) { - new ChallengesPanels2((ChallengesAddon) getAddon(), user, args.isEmpty() ? "" : args.get(0), getWorld(), getPermissionPrefix(), getTopLabel(), true); + new ChallengesPanels2((ChallengesAddon) getAddon(), user, user, args.isEmpty() ? "" : args.get(0), getWorld(), getPermissionPrefix(), getTopLabel(), Mode.ADMIN); return true; } return false; diff --git a/src/main/java/bentobox/addon/challenges/commands/admin/CompleteChallenge.java b/src/main/java/bentobox/addon/challenges/commands/admin/CompleteChallenge.java new file mode 100644 index 0000000..4d262d3 --- /dev/null +++ b/src/main/java/bentobox/addon/challenges/commands/admin/CompleteChallenge.java @@ -0,0 +1,77 @@ +package bentobox.addon.challenges.commands.admin; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import bentobox.addon.challenges.ChallengesAddon; +import bentobox.addon.challenges.ChallengesManager; +import world.bentobox.bentobox.api.addons.Addon; +import world.bentobox.bentobox.api.commands.CompositeCommand; +import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; + +public class CompleteChallenge extends CompositeCommand { + + private ChallengesManager manager; + + /** + * Admin command to complete user challenges + * @param parent + */ + public CompleteChallenge(Addon addon, CompositeCommand parent) { + super(addon, parent, "complete"); + } + + @Override + public void setup() { + this.setPermission("admin.challenges"); + this.setParametersHelp("challenges.admin.complete.parameters"); + this.setDescription("challenges.admin.complete.description"); + manager = ((ChallengesAddon)getAddon()).getChallengesManager(); + } + + @Override + public boolean execute(User user, String label, List args) { + if (args.size() != 2) { + // Show help + showHelp(this, user); + return false; + } + // Get target player + UUID targetUUID = getPlayers().getUUID(args.get(0)); + if (targetUUID == null) { + user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); + return false; + } + if (!getPlugin().getIslands().hasIsland(getWorld(), targetUUID)) { + user.sendMessage("general.errors.player-has-no-island"); + return false; + } + // Check for valid challenge name + if (!manager.isChallenge(getWorld(), args.get(1))) { + user.sendMessage("challenges.admin.complete.unknown-challenge"); + return false; + } + // Complete challenge + User target = User.getInstance(targetUUID); + manager.setChallengeComplete(target, args.get(1), getWorld()); + user.sendMessage("general.success"); + return true; + } + + @Override + public Optional> tabComplete(User user, String alias, List args) { + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; + if (args.size() == 3) { + // Online players + return Optional.of(Util.tabLimit(new ArrayList<>(Util.getOnlinePlayerList(user)), lastArg)); + } else if (args.size() == 4) { + // Challenges in this world + return Optional.of(Util.tabLimit(manager.getAllChallengesList(getWorld()), lastArg)); + } + return Optional.empty(); + } +} diff --git a/src/main/java/bentobox/addon/challenges/panel/AdminEditGUI.java b/src/main/java/bentobox/addon/challenges/panel/AdminEditGUI.java new file mode 100644 index 0000000..f594b7a --- /dev/null +++ b/src/main/java/bentobox/addon/challenges/panel/AdminEditGUI.java @@ -0,0 +1,64 @@ +package bentobox.addon.challenges.panel; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import bentobox.addon.challenges.ChallengesAddon; +import bentobox.addon.challenges.database.object.Challenges; +import world.bentobox.bentobox.api.panels.Panel; +import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler; +import world.bentobox.bentobox.api.panels.builders.PanelBuilder; +import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; +import world.bentobox.bentobox.api.user.User; + +public class AdminEditGUI implements ClickHandler { + + private ChallengesAddon addon; + private User requester; + private Challenges challenge; + private World world; + private String permPrefix; + private String label; + private User target; + + /** + * Shows the admin panel for the challenge for a player + * @param addon addon + * @param requester admin user + * @param target target of admin + * @param challenge challenge + * @param world world + * @param permPrefix permission prefix for world + * @param label command label + */ + public AdminEditGUI(ChallengesAddon addon, User requester, User target, Challenges challenge, World world, + String permPrefix, String label) { + super(); + this.addon = addon; + this.requester = requester; + this.target = target; + this.challenge = challenge; + this.world = world; + this.permPrefix = permPrefix; + this.label = label; + + new PanelBuilder().size(27).user(requester).name(requester.getTranslation("challenges.admin.gui-title")) + .item(new PanelItemBuilder().icon(challenge.getIcon()).name("Icon").build()) + .item(9, new PanelItemBuilder().icon(new ItemStack(Material.WHITE_BANNER)).name("Description").description(challenge.getDescription()).build()) + .item(18, new PanelItemBuilder().icon(new ItemStack(Material.GREEN_STAINED_GLASS_PANE)).name("Active").build()) + .item(27, new PanelItemBuilder().icon(new ItemStack(Material.BOOK)).name("Edit required items").clickHandler(this).build()) + .build(); + } + + @Override + public boolean onClick(Panel panel, User user, ClickType clickType, int slot) { + if (slot == 27) { + new RequiredPanel(challenge, user, panel); + } + return true; + } + + +} diff --git a/src/main/java/bentobox/addon/challenges/panel/ChallengesPanels2.java b/src/main/java/bentobox/addon/challenges/panel/ChallengesPanels2.java index f5b5cf7..b2e5829 100644 --- a/src/main/java/bentobox/addon/challenges/panel/ChallengesPanels2.java +++ b/src/main/java/bentobox/addon/challenges/panel/ChallengesPanels2.java @@ -22,40 +22,61 @@ import world.bentobox.bentobox.api.user.User; public class ChallengesPanels2 { + + public enum Mode { + ADMIN, + EDIT, + PLAYER + } private ChallengesAddon addon; private ChallengesManager manager; - private User user; + private User requester; private String level; private World world; private String permPrefix; private String label; - private boolean admin; + private Mode mode; + private User target; - public ChallengesPanels2(ChallengesAddon addon, User user, String level, World world, String permPrefix, String label, boolean admin) { + public ChallengesPanels2(ChallengesAddon addon, User requester, User target, String level, World world, String permPrefix, String label, Mode mode) { this.addon = addon; this.manager = addon.getChallengesManager(); - this.user = user; + this.requester = requester; + this.target = target; this.world = world; this.permPrefix = permPrefix; this.label = label; - this.admin = admin; + this.mode = mode; if (manager.getChallengeList().isEmpty()) { addon.getLogger().severe("There are no challenges set up!"); - user.sendMessage("general.errors.general"); + requester.sendMessage("general.errors.general"); return; } if (level.isEmpty()) { - // TODO: open the furthest challenge panel + // TODO: open the farthest challenge panel level = manager.getChallengeList().keySet().iterator().next().getUniqueId(); } this.level = level; // Check if level is valid - if (!admin && !manager.isLevelUnlocked(user, level, world)) { + if (mode.equals(Mode.PLAYER) && !manager.isLevelUnlocked(requester, level, world)) { return; } - PanelBuilder panelBuilder = new PanelBuilder() - .name(admin ? user.getTranslation("challenges.admin.gui-title") : user.getTranslation("challenges.gui-title")); + PanelBuilder panelBuilder = new PanelBuilder(); + switch (mode) { + case ADMIN: + panelBuilder.name(requester.getTranslation("challenges.admin.gui-title")); + break; + case EDIT: + panelBuilder.name(requester.getTranslation("challenges.admin.edit-gui-title")); + break; + case PLAYER: + panelBuilder.name(requester.getTranslation("challenges.gui-title")); + break; + default: + break; + + } addChallengeItems(panelBuilder); addNavigation(panelBuilder); @@ -63,7 +84,7 @@ public class ChallengesPanels2 { // Create the panel Panel panel = panelBuilder.build(); - panel.open(user); + panel.open(requester); } private void addChallengeItems(PanelBuilder panelBuilder) { @@ -82,13 +103,27 @@ public class ChallengesPanels2 { * Creates a panel item for challenge if appropriate and adds it to panelBuilder * @param panelBuilder * @param challenge - * @param user + * @param requester */ private void createItem(PanelBuilder panelBuilder, Challenges challenge) { // For admin, glow means activated. For user, glow means done - boolean glow = admin ? challenge.isDeployed() : manager.isChallengeComplete(user, challenge.getUniqueId(), world); + boolean glow = false; + switch (mode) { + case ADMIN: + glow = challenge.isDeployed(); + break; + case EDIT: + glow = manager.isChallengeComplete(requester, challenge.getUniqueId(), world); + break; + case PLAYER: + glow = manager.isChallengeComplete(requester, challenge.getUniqueId(), world); + break; + default: + break; + + } // If not admin and challenge is removed after completion, remove it - if (!admin && glow && challenge.isRemoveWhenCompleted()) { + if (mode.equals(Mode.PLAYER) && glow && challenge.isRemoveWhenCompleted()) { return; } PanelItemBuilder itemBuilder = new PanelItemBuilder() @@ -96,7 +131,7 @@ public class ChallengesPanels2 { .name(challenge.getFriendlyName().isEmpty() ? challenge.getUniqueId() : challenge.getFriendlyName()) .description(challengeDescription(challenge)) .glow(glow); - if (admin) { + if (mode.equals(Mode.ADMIN)) { // Admin click itemBuilder.clickHandler((panel, player, c, s) -> { if (!challenge.getChallengeType().equals(ChallengeType.ICON)) { @@ -105,6 +140,14 @@ public class ChallengesPanels2 { return true; }); + } else if (mode.equals(Mode.EDIT)) { + // Admin edit click + itemBuilder.clickHandler((panel, player, c, s) -> { + if (!challenge.getChallengeType().equals(ChallengeType.ICON)) { + new AdminEditGUI(addon, player, target, challenge, world, permPrefix, label); + } + return true; + }); } else { // Player click itemBuilder.clickHandler((panel, player, c, s) -> { @@ -125,7 +168,7 @@ public class ChallengesPanels2 { private void addNavigation(PanelBuilder panelBuilder) { // Add navigation to other levels - for (LevelStatus status: manager.getChallengeLevelStatus(user, world)) { + for (LevelStatus status: manager.getChallengeLevelStatus(requester, world)) { if (status.getLevel().getUniqueId().equalsIgnoreCase(level)) { // Skip if this is the current level continue; @@ -133,12 +176,12 @@ public class ChallengesPanels2 { // Create a nice name for the level String name = status.getLevel().getFriendlyName().isEmpty() ? status.getLevel().getUniqueId() : status.getLevel().getFriendlyName(); - if (admin || status.isUnlocked()) { + if (mode.equals(Mode.ADMIN) || mode.equals(Mode.EDIT) || status.isUnlocked()) { // Clicking on this icon will open up this level's challenges PanelItem item = new PanelItemBuilder() .icon(new ItemStack(Material.ENCHANTED_BOOK)) .name(name) - .description(manager.stringSplit(user.getTranslation("challenges.navigation","[level]",name))) + .description(manager.stringSplit(requester.getTranslation("challenges.navigation","[level]",name))) .clickHandler((p, u, c, s) -> { u.closeInventory(); u.performCommand(label + " " + ChallengesCommand.CHALLENGE_COMMAND + " " + status.getLevel().getUniqueId()); @@ -152,7 +195,7 @@ public class ChallengesPanels2 { PanelItem item = new PanelItemBuilder() .icon(new ItemStack(Material.BOOK)) .name(name) - .description(manager.stringSplit(user.getTranslation("challenges.to-complete", "[challengesToDo]",String.valueOf(status.getNumberOfChallengesStillToDo()), "[thisLevel]", previousLevelName))) + .description(manager.stringSplit(requester.getTranslation("challenges.to-complete", "[challengesToDo]",String.valueOf(status.getNumberOfChallengesStillToDo()), "[thisLevel]", previousLevelName))) .build(); panelBuilder.item(item); } @@ -170,26 +213,26 @@ public class ChallengesPanels2 { List result = new ArrayList(); String level = challenge.getLevel(); if (!level.isEmpty()) { - result.addAll(splitTrans(user, "challenges.level", "[level]", level)); + result.addAll(splitTrans(requester, "challenges.level", "[level]", level)); } - if (admin) { + if (mode.equals(Mode.ADMIN)) { if ((!challenge.getChallengeType().equals(ChallengeType.INVENTORY) || !challenge.isRepeatable())) { - result.addAll(splitTrans(user, "challenges.not-repeatable")); + result.addAll(splitTrans(requester, "challenges.not-repeatable")); } else { - result.addAll(splitTrans(user, "challenges.repeatable", "[maxtimes]", String.valueOf(challenge.getMaxTimes()))); + result.addAll(splitTrans(requester, "challenges.repeatable", "[maxtimes]", String.valueOf(challenge.getMaxTimes()))); } if (challenge.getChallengeType().equals(ChallengeType.INVENTORY) && challenge.isTakeItems()) { - result.addAll(splitTrans(user, "challenges.item-take-warning")); + result.addAll(splitTrans(requester, "challenges.item-take-warning")); } result.addAll(addRewards(challenge, true, true)); } else { // Check if completed or not - boolean complete = addon.getChallengesManager().isChallengeComplete(user, challenge.getUniqueId(), world); + boolean complete = addon.getChallengesManager().isChallengeComplete(requester, challenge.getUniqueId(), world); int maxTimes = challenge.getMaxTimes(); - long doneTimes = addon.getChallengesManager().checkChallengeTimes(user, challenge, world); + long doneTimes = addon.getChallengesManager().checkChallengeTimes(requester, challenge, world); if (complete) { - result.add(user.getTranslation("challenges.complete")); + result.add(requester.getTranslation("challenges.complete")); } if (challenge.isRepeatable()) { @@ -197,9 +240,9 @@ public class ChallengesPanels2 { // Check if the player has maxed out the challenge if (doneTimes < maxTimes) { - result.addAll(splitTrans(user, "challenges.completed-times","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes))); + result.addAll(splitTrans(requester, "challenges.completed-times","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes))); } else { - result.addAll(splitTrans(user, "challenges.maxed-reached","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes))); + result.addAll(splitTrans(requester, "challenges.maxed-reached","[donetimes]", String.valueOf(doneTimes),"[maxtimes]", String.valueOf(maxTimes))); } } } @@ -207,14 +250,14 @@ public class ChallengesPanels2 { result.addAll(challenge.getDescription()); if (challenge.getChallengeType().equals(ChallengeType.INVENTORY)) { if (challenge.isTakeItems()) { - result.addAll(splitTrans(user, "challenges.item-take-warning")); + result.addAll(splitTrans(requester, "challenges.item-take-warning")); } } else if (challenge.getChallengeType().equals(ChallengeType.ISLAND)) { - result.addAll(splitTrans(user, "challenges.items-closeby")); + result.addAll(splitTrans(requester, "challenges.items-closeby")); } } if (complete && (!challenge.getChallengeType().equals(ChallengeType.INVENTORY) || !challenge.isRepeatable())) { - result.addAll(splitTrans(user, "challenges.not-repeatable")); + result.addAll(splitTrans(requester, "challenges.not-repeatable")); result.replaceAll(x -> x.replace("[label]", label)); return result; } @@ -236,7 +279,7 @@ public class ChallengesPanels2 { rewardText = challenge.getRewardText(); expReward = challenge.getRewardExp(); if (!rewardText.isEmpty()) { - result.addAll(splitTrans(user, "challenges.first-time-rewards")); + result.addAll(splitTrans(requester, "challenges.first-time-rewards")); } } if (admin || complete){ @@ -245,18 +288,18 @@ public class ChallengesPanels2 { rewardText = challenge.getRepeatRewardText(); expReward = challenge.getRepeatExpReward(); if (!rewardText.isEmpty()) { - result.addAll(splitTrans(user, "challenges.repeat-rewards")); + result.addAll(splitTrans(requester, "challenges.repeat-rewards")); } } if (!rewardText.isEmpty()) { - result.addAll(splitTrans(user,rewardText)); + result.addAll(splitTrans(requester,rewardText)); } if (expReward > 0) { - result.addAll(splitTrans(user,"challenges.exp-reward", "[reward]", String.valueOf(expReward))); + result.addAll(splitTrans(requester,"challenges.exp-reward", "[reward]", String.valueOf(expReward))); } if (addon.getPlugin().getSettings().isUseEconomy() && moneyReward > 0) { - result.addAll(splitTrans(user,"challenges.money-reward", "[reward]", String.valueOf(moneyReward))); + result.addAll(splitTrans(requester,"challenges.money-reward", "[reward]", String.valueOf(moneyReward))); } return result; } diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 04aa289..129dd01 100755 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -58,7 +58,7 @@ challenges: error-challenge-does-not-exist: "Challenge doesn't exist or isn't yet completed" admin: parameters: "" - description: "admin command to create challenges" + description: "challenges admin" import: parameters: "[overwrite]" description: "import challenges from challenges.yml" @@ -70,6 +70,10 @@ challenges: skipping: "'[challenge]' already exists - skipping" overwriting: "Overwriting '[challenge]'" imported: "Imported '[challenge]'" + complete: + description: "Marks challenge complete" + parameters: " " + unknown-challenge: "&cUnknown challenge" create: description: "&6Collect:" description-item-color: "&B"