Converted to support multigame

Admin command cimport will import ASkyBlock-style challenges.yml file to
world.
This commit is contained in:
tastybento 2018-05-28 10:12:37 -07:00
parent 983399ec3b
commit c778f03cf0
8 changed files with 179 additions and 79 deletions

View File

@ -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

View File

@ -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"

View File

@ -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;
}
}

View File

@ -257,7 +257,7 @@ public class ChallengesManager {
Optional<ChallengeLevels> 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> 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;
}
/**

View File

@ -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));
}
/**

View File

@ -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<String> 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);
}
}

View File

@ -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<String> 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<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
return Optional.of(Util.tabLimit(Arrays.asList("overwrite"), lastArg));
}
}

View File

@ -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<String> 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<World.Environment> 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<String> 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<String> getWorlds() {
return worlds;
public String getWorld() {
return world;
}
/**
* @param worlds the worlds to set
*/
public void setWorlds(List<String> worlds) {
this.worlds = worlds;
public void setWorld(String world) {
this.world = world;
}
/**