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"