From c778f03cf0e361cae71ded4e7c1195b63f2ea290 Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 28 May 2018 10:12:37 -0700 Subject: [PATCH] Converted to support multigame Admin command cimport will import ASkyBlock-style challenges.yml file to world. --- challenges.yml | 13 +++- locales/en-US.yml | 11 ++++ .../addon/challenges/ChallengesAddon.java | 18 ++++-- .../addon/challenges/ChallengesManager.java | 48 +++++++++++---- .../challenges/FreshSqueezedChallenges.java | 60 +++++++++++++++---- .../admin/ChallengesAdminCommand.java | 33 ---------- .../admin/ChallengesAdminImportCommand.java | 44 ++++++++++++++ .../database/object/Challenges.java | 31 +++++----- 8 files changed, 179 insertions(+), 79 deletions(-) delete mode 100644 src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java create mode 100644 src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminImportCommand.java diff --git a/challenges.yml b/challenges.yml index ad122bd..c4caf01 100644 --- a/challenges.yml +++ b/challenges.yml @@ -1,8 +1,15 @@ ########################################################################################## -# Challenges +# Example challenges.yml file. This is the same format as ASkyBlock. +# Use the cimport command to import the challenges to your world. +# For example: /bsbadmin cimport +# to overwrite previous challenges, use /bsbadmin cimport overwrite +# Once challenges are imported, you can edit them directly in the database folder. +# BSkyBlock offers more features in the native challenge definition files. +# +########################################################################################## # Rewards and required items have to be described using Bukkit Materials # and be exactly correct -# Do not use Type Id's - they will not work +# Do not use Type Id numbers - they will not work! # Challenges can be one of three types - inventory, island or level. # inventory - means the player must have the items on them # island - means the items have to be on the island and within 10 blocks of the player @@ -68,7 +75,7 @@ challenges: # freelevels: 'Novice Competent' will make all Novice, Competent and Expert challenges available immediately. # freelevels: 'Competent' will open Competent and Expert levels once Novice is complete freelevels: '' - + # This section determines what happens when a player unlocks a new level # The subname should correspond to the levels listed above # Note that there is no section for the first level as it is automatically unlocked diff --git a/locales/en-US.yml b/locales/en-US.yml index 733b648..54502ff 100755 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -58,6 +58,17 @@ challenges: admin: parameters: "" description: "admin command to create challenges" + import: + parameters: "[overwrite]" + description: "import challenges from challenges.yml" + no-file: "&cCould not find challenges.yml file to import!" + no-load: "&cError: Could not load challenges.yml. [message]" + no-levels: "Warning: No levels defined in challenges.yml" + levels: "Importing levels: [levels]" + number: "Imported [number] challenges" + skipping: "'[challenge]' already exists - skipping" + overwriting: "Overwriting '[challenge]'" + imported: "Imported '[challenge]'" create: description: "&6Collect:" description-item-color: "&B" diff --git a/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java b/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java index 17f378d..e0acdd5 100644 --- a/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java +++ b/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java @@ -3,7 +3,7 @@ package bskyblock.addon.challenges; import org.bukkit.Bukkit; import bskyblock.addon.challenges.commands.ChallengesCommand; -import bskyblock.addon.challenges.commands.admin.ChallengesAdminCommand; +import bskyblock.addon.challenges.commands.admin.ChallengesAdminImportCommand; import us.tastybento.bskyblock.api.addons.Addon; import us.tastybento.bskyblock.api.commands.CompositeCommand; @@ -16,6 +16,7 @@ public class ChallengesAddon extends Addon { private ChallengesManager challengesManager; private String permissionPrefix = "addon"; + private FreshSqueezedChallenges importManager; @Override public void onEnable() { @@ -28,8 +29,8 @@ public class ChallengesAddon extends Addon { // Challenges Manager challengesManager = new ChallengesManager(this); - // First time challenges creation - new FreshSqueezedChallenges(this); + // Challenge import setup + importManager = new FreshSqueezedChallenges(this); // Register commands - run one tick later to allow all addons to load // AcidIsland hook in @@ -39,14 +40,14 @@ public class ChallengesAddon extends Addon { CompositeCommand acidIslandCmd = getBSkyBlock().getCommandsManager().getCommand("ai"); new ChallengesCommand(this, acidIslandCmd); CompositeCommand acidCmd = getBSkyBlock().getCommandsManager().getCommand("acid"); - new ChallengesAdminCommand(this, acidCmd); + new ChallengesAdminImportCommand(this, acidCmd); }); }); // BSkyBlock hook in CompositeCommand bsbIslandCmd = getBSkyBlock().getCommandsManager().getCommand("island"); new ChallengesCommand(this, bsbIslandCmd); CompositeCommand bsbAdminCmd = getBSkyBlock().getCommandsManager().getCommand("bsbadmin"); - new ChallengesAdminCommand(this, bsbAdminCmd); + new ChallengesAdminImportCommand(this, bsbAdminCmd); // Done } @@ -65,4 +66,11 @@ public class ChallengesAddon extends Addon { return permissionPrefix ; } + /** + * @return the importManager + */ + public FreshSqueezedChallenges getImportManager() { + return importManager; + } + } diff --git a/src/main/java/bskyblock/addon/challenges/ChallengesManager.java b/src/main/java/bskyblock/addon/challenges/ChallengesManager.java index 75dacce..6711ae1 100644 --- a/src/main/java/bskyblock/addon/challenges/ChallengesManager.java +++ b/src/main/java/bskyblock/addon/challenges/ChallengesManager.java @@ -257,7 +257,7 @@ public class ChallengesManager { Optional lv = challengeMap.keySet().stream().filter(l -> l.getUniqueId().equalsIgnoreCase(level)).findFirst(); // Get the challenges applicable to this world return lv.isPresent() ? challengeMap.get(lv.get()).stream() - .filter(c -> c.getWorlds().contains(worldName) || c.getWorlds().isEmpty()).collect(Collectors.toSet()) + .filter(c -> c.getWorld().equalsIgnoreCase(worldName) || c.getWorld().isEmpty()).collect(Collectors.toSet()) : new HashSet<>(); } @@ -388,11 +388,25 @@ public class ChallengesManager { (oldValue, newValue) -> oldValue, LinkedHashMap::new)); } + /** - * Stores the challenge. If a challenge already exists with the same name, it is overwritten. + * Store challenge silently. Used when loading. * @param challenge + * @return true if successful */ - public void storeChallenge(Challenges challenge) { + private boolean storeChallenge(Challenges challenge) { + return storeChallenge(challenge, true, null, true); + } + + /** + * Stores the challenge. + * @param challenge - challenge + * @param overwrite - true if previous challenge should be overwritten + * @param user - user making the request + * @param silent - if true, no messages are sent to user + * @return - true if imported + */ + public boolean storeChallenge(Challenges challenge, boolean overwrite, User user, boolean silent) { // See if we have this level already ChallengeLevels level; if (lvConfig.configObjectExists(challenge.getLevel())) { @@ -404,18 +418,26 @@ public class ChallengesManager { level.setUniqueId(challenge.getLevel()); lvConfig.saveConfigObject(level); } - if (challengeMap.containsKey(level)) { - // Replace if this challenge uniqueId already exists - if (challengeMap.get(level).contains(challenge)) { - challengeMap.get(level).remove(challenge); + challengeMap.putIfAbsent(level, new HashSet<>()); + if (challengeMap.get(level).contains(challenge)) { + if (!overwrite) { + if (!silent) { + user.sendMessage("challenges.admin.import.skipping", "[challenge]", challenge.getFriendlyName()); + } + return false; + } else { + if (!silent) { + user.sendMessage("challenges.admin.import.overwriting", "[challenge]", challenge.getFriendlyName()); + } + challengeMap.get(level).add(challenge); + return true; } - challengeMap.get(level).add(challenge); - } else { - // First challenge of this level type - Set challenges = new HashSet<>(); - challenges.add(challenge); - challengeMap.put(level, challenges); } + if (!silent) { + user.sendMessage("challenges.admin.import.imported", "[challenge]", challenge.getFriendlyName()); + } + challengeMap.get(level).add(challenge); + return true; } /** diff --git a/src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java b/src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java index 69f00cc..693c14f 100644 --- a/src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java +++ b/src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; @@ -17,33 +18,62 @@ import org.bukkit.inventory.ItemStack; import bskyblock.addon.challenges.database.object.ChallengeLevels; import bskyblock.addon.challenges.database.object.Challenges; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.util.Util; +/** + * Imports challenges + * @author tastybento + * + */ public class FreshSqueezedChallenges { - ChallengesAddon addon; - YamlConfiguration chal; + private ChallengesAddon addon; + private YamlConfiguration chal; + /** + * Import challenges from challenges.yml + * @param challengesAddon + */ public FreshSqueezedChallenges(ChallengesAddon challengesAddon) { this.addon = challengesAddon; File challengeFile = new File(addon.getDataFolder(), "challenges.yml"); if (!challengeFile.exists()) { addon.saveResource("challenges.yml",false); } + } + + /** + * Import challenges + * @param user - user + * @param world - world to import into + * @param overwrite - true if previous ones should be overwritten + * @return true if successful + */ + public boolean importChallenges(User user, World world, boolean overwrite) { + File challengeFile = new File(addon.getDataFolder(), "challenges.yml"); + if (!challengeFile.exists()) { + user.sendMessage("challenges.admin.import.no-file"); + return false; + } chal = new YamlConfiguration(); try { chal.load(challengeFile); } catch (IOException | InvalidConfigurationException e) { - addon.getLogger().severe("Could not set up initial challenges"); + user.sendMessage("challenges.admin.import.no-load","[message]", e.getMessage()); + return false; } - makeLevels(); - makeChallenges(); + makeLevels(user); + makeChallenges(user, world, overwrite); addon.getChallengesManager().save(true); + return true; } - private void makeLevels() { + private void makeLevels(User user) { // Parse the levels String levels = chal.getString("challenges.levels", ""); if (!levels.isEmpty()) { + user.sendMessage("challenges.admin.import.levels", "[levels]", levels); String[] lvs = levels.split(" "); int order = 0; for (String level : lvs) { @@ -64,20 +94,27 @@ public class FreshSqueezedChallenges { } addon.getChallengesManager().storeLevel(challengeLevel); } - } + } else { + user.sendMessage("challenges.admin.import.no-levels"); + } } /** * Imports challenges + * @param overwrite + * @param args */ - private void makeChallenges() { + private void makeChallenges(User user, World world, boolean overwrite) { + int size = 0; // Parse the challenge file ConfigurationSection chals = chal.getConfigurationSection("challenges.challengeList"); for (String challenge : chals.getKeys(false)) { Challenges newChallenge = new Challenges(); - newChallenge.setUniqueId(challenge); + newChallenge.setUniqueId(Util.getWorld(world).getName() + "_" + challenge); + newChallenge.setDeployed(true); ConfigurationSection details = chals.getConfigurationSection(challenge); newChallenge.setFriendlyName(details.getString("friendlyname", challenge)); + newChallenge.setWorld(Util.getWorld(world).getName()); newChallenge.setDescription(addon.getChallengesManager().stringSplit(details.getString("description", ""))); newChallenge.setIcon(new ParseItem(addon, details.getString("icon") + ":1").getItem()); newChallenge.setLevel(details.getString("level", ChallengesManager.FREE)); @@ -107,9 +144,12 @@ public class FreshSqueezedChallenges { newChallenge.setItemReward(parseItems(details.getString("itemReward"))); newChallenge.setRepeatItemReward(parseItems(details.getString("repeatItemReward"))); // Save - addon.getChallengesManager().storeChallenge(newChallenge); + if (addon.getChallengesManager().storeChallenge(newChallenge, overwrite, user, false)) { + size++; + } } addon.getChallengesManager().sortChallenges(); + user.sendMessage("challenges.admin.import.number", "[number]", String.valueOf(size)); } /** diff --git a/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java b/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java deleted file mode 100644 index 8b7b105..0000000 --- a/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java +++ /dev/null @@ -1,33 +0,0 @@ -package bskyblock.addon.challenges.commands.admin; - -import java.util.List; - -import bskyblock.addon.challenges.ChallengesAddon; -import us.tastybento.bskyblock.api.commands.CompositeCommand; -import us.tastybento.bskyblock.api.user.User; - -public class ChallengesAdminCommand extends CompositeCommand { - private static final String CHALLENGE_ADMIN_COMMAND = "cadmin"; - - public ChallengesAdminCommand(ChallengesAddon addon, CompositeCommand cmd) { - super(cmd, CHALLENGE_ADMIN_COMMAND); - // Set up create command - new CreateChallenge(addon, this); - new SetIcon(addon, this); - } - - @Override - public boolean execute(User user, List args) { - return false; - } - - @Override - public void setup() { - this.setOnlyPlayer(true); - this.setPermission(getPermissionPrefix() + "challenges.admin"); - this.setParameters("challaneges.admin.parameters"); - this.setDescription("challenges.admin.description"); - this.setOnlyPlayer(true); - } - -} diff --git a/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminImportCommand.java b/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminImportCommand.java new file mode 100644 index 0000000..aa42a20 --- /dev/null +++ b/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminImportCommand.java @@ -0,0 +1,44 @@ +package bskyblock.addon.challenges.commands.admin; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import bskyblock.addon.challenges.ChallengesAddon; +import us.tastybento.bskyblock.api.commands.CompositeCommand; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.util.Util; + +public class ChallengesAdminImportCommand extends CompositeCommand { + + private ChallengesAddon addon; + + /** + * Import challenges + * @param addon + * @param cmd + */ + public ChallengesAdminImportCommand(ChallengesAddon addon, CompositeCommand cmd) { + super(cmd, "cimport"); + this.addon = addon; + } + + @Override + public boolean execute(User user, List args) { + return addon.getImportManager().importChallenges(user, getWorld(), !args.isEmpty() && args.get(0).equalsIgnoreCase("overwrite")); + } + + @Override + public void setup() { + this.setPermission(getPermissionPrefix() + "challenges.admin"); + this.setParameters("challenges.admin.import.parameters"); + this.setDescription("challenges.admin.import.description"); + } + + @Override + public Optional> tabComplete(User user, String alias, List args) { + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; + return Optional.of(Util.tabLimit(Arrays.asList("overwrite"), lastArg)); + } + +} diff --git a/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java b/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java index ddb5856..d6e5e6f 100644 --- a/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java +++ b/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java @@ -16,6 +16,11 @@ import bskyblock.addon.challenges.ChallengesManager; import us.tastybento.bskyblock.api.configuration.ConfigComment; import us.tastybento.bskyblock.database.objects.DataObject; +/** + * Data object for challenges + * @author tastybento + * + */ public class Challenges implements DataObject { public enum ChallengeType { @@ -40,10 +45,7 @@ public class Challenges implements DataObject { // The order of the fields is the order shown in the YML files @ConfigComment("Whether this challenge is deployed or not") private boolean deployed; - - @ConfigComment("Worlds that this challenge will run in. String list. List only overworld. Nether and end are automatically covered.") - private List worlds = new ArrayList<>(); - + // Description @ConfigComment("Name of the icon and challenge. May include color codes. Single line.") private String friendlyName = ""; @@ -59,9 +61,11 @@ public class Challenges implements DataObject { private String level = ChallengesManager.FREE; @ConfigComment("Challenge type can be ICON, INVENTORY, LEVEL or SURROUNDING.") private ChallengeType challengeType = ChallengeType.INVENTORY; + @ConfigComment("World where this challenge operates. List only overworld. Nether and end are automatically covered.") + private String world = ""; @ConfigComment("List of environments where this challenge will occur: NETHER, NORMAL, THE_END. Leave blank for all.") private List environment = new ArrayList<>(); - @ConfigComment("The required permissions to see this challenge. String Set.") + @ConfigComment("The required permissions to see this challenge. String list.") private Set reqPerms = new HashSet<>(); @ConfigComment("The number of blocks around the player to search for items on an island") private int searchRadius = 10; @@ -115,15 +119,12 @@ public class Challenges implements DataObject { private String repeatRewardText = ""; - - - - - - @ConfigComment("Unique name of the challenge") private String uniqueId = ""; + /* + * END OF SETTINGS + */ /** * @return the challengeType @@ -565,15 +566,15 @@ public class Challenges implements DataObject { /** * @return the worlds */ - public List getWorlds() { - return worlds; + public String getWorld() { + return world; } /** * @param worlds the worlds to set */ - public void setWorlds(List worlds) { - this.worlds = worlds; + public void setWorld(String world) { + this.world = world; } /**