mirror of https://github.com/PikaMug/Quests.git
3857 lines
203 KiB
Java
3857 lines
203 KiB
Java
/*******************************************************************************************************
|
|
* Continued by PikaMug (formerly HappyPikachu) with permission from _Blackvein_. All rights reserved.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
|
* NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*******************************************************************************************************/
|
|
|
|
package me.blackvein.quests;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.lang.reflect.Constructor;
|
|
import java.net.URISyntaxException;
|
|
import java.net.URL;
|
|
import java.net.URLClassLoader;
|
|
import java.util.AbstractMap;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Enumeration;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
import java.util.jar.JarEntry;
|
|
import java.util.jar.JarFile;
|
|
import java.util.logging.Level;
|
|
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.ChatColor;
|
|
import org.bukkit.Color;
|
|
import org.bukkit.DyeColor;
|
|
import org.bukkit.Effect;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.World;
|
|
import org.bukkit.block.Biome;
|
|
import org.bukkit.command.CommandExecutor;
|
|
import org.bukkit.configuration.ConfigurationSection;
|
|
import org.bukkit.configuration.InvalidConfigurationException;
|
|
import org.bukkit.configuration.file.FileConfiguration;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.bukkit.conversations.ConversationAbandonedEvent;
|
|
import org.bukkit.conversations.ConversationAbandonedListener;
|
|
import org.bukkit.conversations.ConversationContext;
|
|
import org.bukkit.conversations.ConversationFactory;
|
|
import org.bukkit.conversations.ConversationPrefix;
|
|
import org.bukkit.conversations.Prompt;
|
|
import org.bukkit.conversations.StringPrompt;
|
|
import org.bukkit.enchantments.Enchantment;
|
|
import org.bukkit.entity.EntityType;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.entity.Tameable;
|
|
import org.bukkit.event.HandlerList;
|
|
import org.bukkit.inventory.Inventory;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.permissions.Permission;
|
|
import org.bukkit.plugin.java.JavaPlugin;
|
|
import org.bukkit.potion.PotionEffect;
|
|
import org.bukkit.potion.PotionEffectType;
|
|
|
|
import com.codisimus.plugins.phatloots.PhatLootsAPI;
|
|
import com.gmail.nossr50.datatypes.skills.SkillType;
|
|
import com.herocraftonline.heroes.characters.classes.HeroClass;
|
|
|
|
import me.blackvein.quests.actions.Action;
|
|
import me.blackvein.quests.actions.ActionFactory;
|
|
import me.blackvein.quests.conditions.Condition;
|
|
import me.blackvein.quests.conditions.ConditionFactory;
|
|
import me.blackvein.quests.convo.npcs.NpcOfferQuestPrompt;
|
|
import me.blackvein.quests.exceptions.ActionFormatException;
|
|
import me.blackvein.quests.exceptions.ConditionFormatException;
|
|
import me.blackvein.quests.exceptions.QuestFormatException;
|
|
import me.blackvein.quests.exceptions.StageFormatException;
|
|
import me.blackvein.quests.interfaces.ReloadCallback;
|
|
import me.blackvein.quests.listeners.BlockListener;
|
|
import me.blackvein.quests.listeners.CmdExecutor;
|
|
import me.blackvein.quests.listeners.DungeonsListener;
|
|
import me.blackvein.quests.listeners.ItemListener;
|
|
import me.blackvein.quests.listeners.NpcListener;
|
|
import me.blackvein.quests.listeners.PartiesListener;
|
|
import me.blackvein.quests.listeners.PlayerListener;
|
|
import me.blackvein.quests.tasks.NpcEffectThread;
|
|
import me.blackvein.quests.tasks.PlayerMoveThread;
|
|
import me.blackvein.quests.util.ConfigUtil;
|
|
import me.blackvein.quests.util.ItemUtil;
|
|
import me.blackvein.quests.util.Lang;
|
|
import me.blackvein.quests.util.LocaleQuery;
|
|
import me.blackvein.quests.util.MiscUtil;
|
|
import me.clip.placeholderapi.PlaceholderAPI;
|
|
import net.citizensnpcs.api.CitizensAPI;
|
|
import net.citizensnpcs.api.npc.NPC;
|
|
|
|
public class Quests extends JavaPlugin implements ConversationAbandonedListener {
|
|
|
|
private boolean loading = true;
|
|
private String bukkitVersion = "0";
|
|
private Dependencies depends;
|
|
private Settings settings;
|
|
private final List<CustomRequirement> customRequirements = new LinkedList<CustomRequirement>();
|
|
private final List<CustomReward> customRewards = new LinkedList<CustomReward>();
|
|
private final List<CustomObjective> customObjectives = new LinkedList<CustomObjective>();
|
|
private LinkedList<Quester> questers = new LinkedList<Quester>();
|
|
private final LinkedList<Quest> quests = new LinkedList<Quest>();
|
|
private LinkedList<Action> actions = new LinkedList<Action>();
|
|
private LinkedList<Condition> conditions = new LinkedList<Condition>();
|
|
private LinkedList<NPC> questNpcs = new LinkedList<NPC>();
|
|
private CommandExecutor cmdExecutor;
|
|
private ConversationFactory conversationFactory;
|
|
private ConversationFactory npcConversationFactory;
|
|
private QuestFactory questFactory;
|
|
private ActionFactory actionFactory;
|
|
private ConditionFactory conditionFactory;
|
|
private BlockListener blockListener;
|
|
private ItemListener itemListener;
|
|
private NpcListener npcListener;
|
|
private PlayerListener playerListener;
|
|
private NpcEffectThread effThread;
|
|
private PlayerMoveThread moveThread;
|
|
private DungeonsListener dungeonsListener;
|
|
private PartiesListener partiesListener;
|
|
private DenizenTrigger trigger;
|
|
private LocaleQuery localeQuery;
|
|
|
|
@Override
|
|
public void onEnable() {
|
|
/****** WARNING: ORDER OF STEPS MATTERS ******/
|
|
|
|
// 1 - Initialize variables
|
|
bukkitVersion = Bukkit.getServer().getBukkitVersion().split("-")[0];
|
|
settings = new Settings(this);
|
|
localeQuery = new LocaleQuery(this);
|
|
localeQuery.setBukkitVersion(bukkitVersion);
|
|
blockListener = new BlockListener(this);
|
|
itemListener = new ItemListener(this);
|
|
npcListener = new NpcListener(this);
|
|
playerListener = new PlayerListener(this);
|
|
dungeonsListener = new DungeonsListener();
|
|
partiesListener = new PartiesListener();
|
|
effThread = new NpcEffectThread(this);
|
|
moveThread = new PlayerMoveThread(this);
|
|
questFactory = new QuestFactory(this);
|
|
actionFactory = new ActionFactory(this);
|
|
conditionFactory = new ConditionFactory(this);
|
|
depends = new Dependencies(this);
|
|
trigger = new DenizenTrigger(this);
|
|
|
|
// 2 - Load main config
|
|
settings.init();
|
|
|
|
// 3 - Setup language files
|
|
try {
|
|
setupLang();
|
|
} catch (final IOException e) {
|
|
e.printStackTrace();
|
|
} catch (final URISyntaxException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
// 4 - Load command executor
|
|
cmdExecutor = new CmdExecutor(this);
|
|
|
|
// 5 - Load soft-depends
|
|
depends.init();
|
|
|
|
// 6 - Save resources from jar
|
|
saveResourceAs("quests.yml", "quests.yml", false);
|
|
saveResourceAs("actions.yml", "actions.yml", false);
|
|
saveResourceAs("conditions.yml", "conditions.yml", false);
|
|
|
|
// 7 - Save config with any new options
|
|
getConfig().options().copyDefaults(true);
|
|
saveConfig();
|
|
|
|
// 8 - Setup commands
|
|
getCommand("quests").setExecutor(cmdExecutor);
|
|
getCommand("questadmin").setExecutor(cmdExecutor);
|
|
getCommand("quest").setExecutor(cmdExecutor);
|
|
|
|
// 9 - Build conversation factories
|
|
this.conversationFactory = new ConversationFactory(this).withModality(false)
|
|
.withPrefix(new ConversationPrefix() {
|
|
@Override
|
|
public String getPrefix(final ConversationContext context) {
|
|
return ChatColor.GRAY.toString();
|
|
}
|
|
})
|
|
.withFirstPrompt(new QuestAcceptPrompt()).withTimeout(settings.getAcceptTimeout())
|
|
.thatExcludesNonPlayersWithMessage("Console may not perform this conversation!")
|
|
.addConversationAbandonedListener(this);
|
|
this.npcConversationFactory = new ConversationFactory(this).withModality(false)
|
|
.withFirstPrompt(new NpcOfferQuestPrompt()).withTimeout(settings.getAcceptTimeout())
|
|
.withLocalEcho(false).addConversationAbandonedListener(this);
|
|
|
|
// 10 - Register listeners
|
|
getServer().getPluginManager().registerEvents(blockListener, this);
|
|
getServer().getPluginManager().registerEvents(itemListener, this);
|
|
if (depends.getCitizens() != null) {
|
|
getServer().getPluginManager().registerEvents(npcListener, this);
|
|
if (settings.canNpcEffects()) {
|
|
getServer().getScheduler().scheduleSyncRepeatingTask(this, effThread, 20, 20);
|
|
}
|
|
}
|
|
getServer().getPluginManager().registerEvents(playerListener, this);
|
|
if (settings.getStrictPlayerMovement() > 0) {
|
|
final long ticks = settings.getStrictPlayerMovement() * 20;
|
|
getServer().getScheduler().scheduleSyncRepeatingTask(this, moveThread, ticks, ticks);
|
|
}
|
|
if (depends.getDungeonsApi() != null) {
|
|
getServer().getPluginManager().registerEvents(dungeonsListener, this);
|
|
}
|
|
if (depends.getPartiesApi() != null) {
|
|
getServer().getPluginManager().registerEvents(partiesListener, this);
|
|
}
|
|
|
|
// 11 - Delay loading of Quests, Actions and modules
|
|
delayLoadQuestInfo(5L);
|
|
}
|
|
|
|
@Override
|
|
public void onDisable() {
|
|
getLogger().info("Saving Quester data...");
|
|
for (final Player p : getServer().getOnlinePlayers()) {
|
|
final Quester quester = getQuester(p.getUniqueId());
|
|
quester.saveData();
|
|
}
|
|
}
|
|
|
|
public boolean isLoading() {
|
|
return loading;
|
|
}
|
|
|
|
public String getDetectedBukkitVersion() {
|
|
return bukkitVersion;
|
|
}
|
|
|
|
public Dependencies getDependencies() {
|
|
return depends;
|
|
}
|
|
|
|
public Settings getSettings() {
|
|
return settings;
|
|
}
|
|
|
|
public List<CustomRequirement> getCustomRequirements() {
|
|
return customRequirements;
|
|
}
|
|
|
|
public Optional<CustomRequirement> getCustomRequirement(final String className) {
|
|
for (int i = 0; i < customRequirements.size(); i++) {
|
|
final CustomRequirement cr = customRequirements.get(i);
|
|
if (cr.getClass().getName().equals(className)) {
|
|
return Optional.of(cr);
|
|
}
|
|
}
|
|
return Optional.empty();
|
|
}
|
|
|
|
public List<CustomReward> getCustomRewards() {
|
|
return customRewards;
|
|
}
|
|
|
|
public Optional<CustomReward> getCustomReward(final String className) {
|
|
for (int i = 0; i < customRewards.size(); i++) {
|
|
final CustomReward cr = customRewards.get(i);
|
|
if (cr.getClass().getName().equals(className)) {
|
|
return Optional.of(cr);
|
|
}
|
|
}
|
|
return Optional.empty();
|
|
}
|
|
|
|
public List<CustomObjective> getCustomObjectives() {
|
|
return customObjectives;
|
|
}
|
|
|
|
public Optional<CustomObjective> getCustomObjective(final String className) {
|
|
for (int i = 0; i < customObjectives.size(); i++) {
|
|
final CustomObjective co = customObjectives.get(i);
|
|
if (co.getClass().getName().equals(className)) {
|
|
return Optional.of(co);
|
|
}
|
|
}
|
|
return Optional.empty();
|
|
}
|
|
|
|
public LinkedList<Quest> getQuests() {
|
|
return quests;
|
|
}
|
|
|
|
public LinkedList<Action> getActions() {
|
|
return actions;
|
|
}
|
|
|
|
public void setActions(final LinkedList<Action> actions) {
|
|
this.actions = actions;
|
|
}
|
|
|
|
public LinkedList<Condition> getConditions() {
|
|
return conditions;
|
|
}
|
|
|
|
public void setConditions(final LinkedList<Condition> conditions) {
|
|
this.conditions = conditions;
|
|
}
|
|
|
|
public LinkedList<Quester> getQuesters() {
|
|
return questers;
|
|
}
|
|
|
|
public void setQuesters(final LinkedList<Quester> questers) {
|
|
this.questers = questers;
|
|
}
|
|
|
|
public LinkedList<NPC> getQuestNpcs() {
|
|
return questNpcs;
|
|
}
|
|
|
|
public void setQuestNpcs(final LinkedList<NPC> questNpcs) {
|
|
this.questNpcs = questNpcs;
|
|
}
|
|
|
|
public ConversationFactory getConversationFactory() {
|
|
return conversationFactory;
|
|
}
|
|
|
|
public ConversationFactory getNpcConversationFactory() {
|
|
return npcConversationFactory;
|
|
}
|
|
|
|
public QuestFactory getQuestFactory() {
|
|
return questFactory;
|
|
}
|
|
|
|
public ActionFactory getActionFactory() {
|
|
return actionFactory;
|
|
}
|
|
|
|
public ConditionFactory getConditionFactory() {
|
|
return conditionFactory;
|
|
}
|
|
|
|
public BlockListener getBlockListener() {
|
|
return blockListener;
|
|
}
|
|
|
|
public ItemListener getItemListener() {
|
|
return itemListener;
|
|
}
|
|
|
|
public NpcListener getNpcListener() {
|
|
return npcListener;
|
|
}
|
|
|
|
public PlayerListener getPlayerListener() {
|
|
return playerListener;
|
|
}
|
|
|
|
public DungeonsListener getDungeonsListener() {
|
|
return dungeonsListener;
|
|
}
|
|
|
|
public PartiesListener getPartiesListener() {
|
|
return partiesListener;
|
|
}
|
|
|
|
public DenizenTrigger getDenizenTrigger() {
|
|
return trigger;
|
|
}
|
|
|
|
public LocaleQuery getLocaleQuery() {
|
|
return localeQuery;
|
|
}
|
|
|
|
@Override
|
|
public void conversationAbandoned(final ConversationAbandonedEvent abandonedEvent) {
|
|
if (abandonedEvent.gracefulExit() == false) {
|
|
if (abandonedEvent.getContext().getForWhom() != null) {
|
|
try {
|
|
abandonedEvent.getContext().getForWhom().sendRawMessage(ChatColor.YELLOW
|
|
+ Lang.get((Player) abandonedEvent.getContext().getForWhom(), "questTimeout"));
|
|
} catch (final Exception e) {
|
|
// Do nothing
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private class QuestAcceptPrompt extends StringPrompt {
|
|
|
|
@Override
|
|
public String getPromptText(final ConversationContext context) {
|
|
return ChatColor.YELLOW + Lang.get((Player) context.getForWhom(), "acceptQuest") + " " + ChatColor.GREEN
|
|
+ Lang.get("yesWord") + " / " + Lang.get("noWord");
|
|
}
|
|
|
|
@Override
|
|
public Prompt acceptInput(final ConversationContext context, final String s) {
|
|
final Player player = (Player) context.getForWhom();
|
|
if (s.equalsIgnoreCase(Lang.get(player, "yesWord"))) {
|
|
Quester quester = getQuester(player.getUniqueId());
|
|
if (quester == null) {
|
|
// Must be new player
|
|
quester = new Quester(Quests.this);
|
|
quester.setUUID(player.getUniqueId());
|
|
if (quester.saveData()) {
|
|
getLogger().info("Created new data for player " + player.getName());
|
|
} else {
|
|
player.sendMessage(ChatColor.RED + Lang.get(player, "questSaveError"));
|
|
}
|
|
}
|
|
final String questToTake = quester.questToTake;
|
|
try {
|
|
if (getQuest(questToTake) == null) {
|
|
getLogger().info(player.getName() + " attempted to take quest \"" + questToTake
|
|
+ "\" but something went wrong");
|
|
player.sendMessage(ChatColor.RED
|
|
+ "Something went wrong! Please report issue to an administrator.");
|
|
} else {
|
|
getQuester(player.getUniqueId()).takeQuest(getQuest(questToTake), false);
|
|
}
|
|
} catch (final Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return Prompt.END_OF_CONVERSATION;
|
|
} else if (s.equalsIgnoreCase(Lang.get("noWord"))) {
|
|
player.sendMessage(ChatColor.YELLOW + Lang.get("cancelled"));
|
|
return Prompt.END_OF_CONVERSATION;
|
|
} else {
|
|
final String msg = Lang.get(player, "questInvalidChoice")
|
|
.replace("<yes>", Lang.get(player, "yesWord"))
|
|
.replace("<no>", Lang.get(player, "noWord"));
|
|
player.sendMessage(ChatColor.RED + msg);
|
|
return new QuestAcceptPrompt();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transfer language files from jar to disk
|
|
*/
|
|
private void setupLang() throws IOException, URISyntaxException {
|
|
final String path = "lang";
|
|
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
|
|
if(jarFile.isFile()) {
|
|
final JarFile jar = new JarFile(jarFile);
|
|
final Enumeration<JarEntry> entries = jar.entries();
|
|
final Set<String> results = new HashSet<String>();
|
|
while(entries.hasMoreElements()) {
|
|
final String name = entries.nextElement().getName();
|
|
if (name.startsWith(path + "/") && name.contains("strings.yml")) {
|
|
results.add(name);
|
|
}
|
|
}
|
|
for (final String resourcePath : results) {
|
|
saveResourceAs(resourcePath, resourcePath, false);
|
|
saveResourceAs(resourcePath, resourcePath.replace(".yml", "_new.yml"), true);
|
|
}
|
|
jar.close();
|
|
}
|
|
try {
|
|
Lang.init(this);
|
|
} catch (final InvalidConfigurationException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save a Quests plugin resource to a specific path in the filesystem
|
|
*
|
|
* @param resourcePath jar file location starting from resource folder, i.e. "lang/el-GR/strings.yml"
|
|
* @param outputPath file destination starting from Quests folder, i.e. "lang/el-GR/strings.yml"
|
|
* @param replace whether or not to replace the destination file
|
|
*/
|
|
public void saveResourceAs(String resourcePath, final String outputPath, final boolean replace) {
|
|
if (resourcePath == null || resourcePath.equals("")) {
|
|
throw new IllegalArgumentException("ResourcePath cannot be null or empty");
|
|
}
|
|
|
|
resourcePath = resourcePath.replace('\\', '/');
|
|
final InputStream in = getResource(resourcePath);
|
|
if (in == null) {
|
|
throw new IllegalArgumentException("The embedded resource '" + resourcePath
|
|
+ "' cannot be found in Quests jar");
|
|
}
|
|
|
|
final String outPath = outputPath.replace('/', File.separatorChar).replace('\\', File.separatorChar);
|
|
final File outFile = new File(getDataFolder(), outPath);
|
|
final File outDir = new File(outFile.getPath().replace(outFile.getName(), ""));
|
|
|
|
if (!outDir.exists()) {
|
|
if (!outDir.mkdirs()) {
|
|
getLogger().log(Level.SEVERE, "Failed to make directories for " + outFile.getName() + " (canWrite= "
|
|
+ outDir.canWrite() + ")");
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (!outFile.exists() || replace) {
|
|
final OutputStream out = new FileOutputStream(outFile);
|
|
final byte[] buf = new byte[1024];
|
|
int len;
|
|
while ((len = in.read(buf)) > 0) {
|
|
out.write(buf, 0, len);
|
|
}
|
|
out.close();
|
|
in.close();
|
|
if (!outFile.exists()) {
|
|
getLogger().severe("Unable to copy " + outFile.getName() + " (canWrite= " + outFile.canWrite()
|
|
+ ")");
|
|
}
|
|
}
|
|
} catch (final IOException ex) {
|
|
getLogger().log(Level.SEVERE, "Could not save " + outFile.getName() + " to " + outFile, ex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load quests, actions, and modules after specified delay<p>
|
|
*
|
|
* At startup, this lets soft-depends (namely Citizens) fully load first
|
|
*/
|
|
private void delayLoadQuestInfo(final long ticks) {
|
|
getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
loadQuests();
|
|
loadActions();
|
|
loadConditions();
|
|
getLogger().log(Level.INFO, "Loaded " + quests.size() + " Quest(s), " + actions.size() + " Action(s), "
|
|
+ conditions.size() + " Condition(s) and " + Lang.size() + " Phrase(s)");
|
|
for (final Player p : getServer().getOnlinePlayers()) {
|
|
final Quester quester = new Quester(Quests.this);
|
|
quester.setUUID(p.getUniqueId());
|
|
if (quester.loadData() == false) {
|
|
quester.saveData();
|
|
}
|
|
// Workaround for issues with the compass on fast join
|
|
quester.findCompassTarget();
|
|
questers.add(quester);
|
|
}
|
|
if (depends.getCitizens() != null) {
|
|
if (depends.getCitizens().getNPCRegistry() == null) {
|
|
getLogger().log(Level.SEVERE,
|
|
"Citizens was enabled but NPCRegistry was null. Disabling linkage.");
|
|
depends.disableCitizens();
|
|
}
|
|
}
|
|
loadModules();
|
|
loading = false;
|
|
}
|
|
}, ticks);
|
|
}
|
|
|
|
/**
|
|
* Load modules from file
|
|
*/
|
|
public void loadModules() {
|
|
final File f = new File(this.getDataFolder(), "modules");
|
|
if (f.exists() && f.isDirectory()) {
|
|
final File[] modules = f.listFiles();
|
|
if (modules != null) {
|
|
for (final File module : modules) {
|
|
if (module.isDirectory() == false && module.getName().endsWith(".jar")) {
|
|
loadModule(module);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
f.mkdir();
|
|
}
|
|
boolean failedToLoad;
|
|
FileConfiguration config = null;
|
|
final File file = new File(this.getDataFolder(), "quests.yml");
|
|
try {
|
|
config = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(file), "UTF-8"));
|
|
} catch (final IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
if (config != null) {
|
|
ConfigurationSection questsSection;
|
|
if (config.contains("quests")) {
|
|
questsSection = config.getConfigurationSection("quests");
|
|
for (final String questKey : questsSection.getKeys(false)) {
|
|
try {
|
|
failedToLoad = false;
|
|
if (config.contains("quests." + questKey)) {
|
|
loadCustomSections(getQuestById(questKey), config, questKey);
|
|
} else {
|
|
throw new QuestFormatException("Quest block is missing", questKey);
|
|
}
|
|
if (failedToLoad) {
|
|
getLogger().log(Level.SEVERE, "Failed to load Quest \"" + questKey + "\". Skipping.");
|
|
}
|
|
} catch (final QuestFormatException ex) {
|
|
continue;
|
|
} catch (final StageFormatException ex) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
getLogger().severe("Unable to load module data from quests.yml");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load the specified jar as a module
|
|
*
|
|
* @param jar A custom reward/requirement/objective jar
|
|
*/
|
|
public void loadModule(final File jar) {
|
|
try {
|
|
@SuppressWarnings("resource")
|
|
final
|
|
JarFile jarFile = new JarFile(jar);
|
|
final Enumeration<JarEntry> e = jarFile.entries();
|
|
final URL[] urls = { new URL("jar:file:" + jar.getPath() + "!/") };
|
|
final ClassLoader cl = URLClassLoader.newInstance(urls, getClassLoader());
|
|
int count = 0;
|
|
while (e.hasMoreElements()) {
|
|
final JarEntry je = e.nextElement();
|
|
if (je.isDirectory() || !je.getName().endsWith(".class")) {
|
|
continue;
|
|
}
|
|
String className = je.getName().substring(0, je.getName().length() - 6);
|
|
className = className.replace('/', '.');
|
|
final Class<?> c = Class.forName(className, true, cl);
|
|
if (CustomRequirement.class.isAssignableFrom(c)) {
|
|
final Class<? extends CustomRequirement> requirementClass = c.asSubclass(CustomRequirement.class);
|
|
final Constructor<? extends CustomRequirement> cstrctr = requirementClass.getConstructor();
|
|
final CustomRequirement requirement = cstrctr.newInstance();
|
|
final Optional<CustomRequirement>oo=getCustomRequirement(requirement.getClass().getName());
|
|
if (oo.isPresent()) customRequirements.remove(oo.get());
|
|
customRequirements.add(requirement);
|
|
final String name = requirement.getName() == null ? "[" + jar.getName() + "]" : requirement.getName();
|
|
final String author = requirement.getAuthor() == null ? "[Unknown]" : requirement.getAuthor();
|
|
count++;
|
|
getLogger().info("Loaded Module: " + name + " by " + author);
|
|
} else if (CustomReward.class.isAssignableFrom(c)) {
|
|
final Class<? extends CustomReward> rewardClass = c.asSubclass(CustomReward.class);
|
|
final Constructor<? extends CustomReward> cstrctr = rewardClass.getConstructor();
|
|
final CustomReward reward = cstrctr.newInstance();
|
|
final Optional<CustomReward>oo=getCustomReward(reward.getClass().getName());
|
|
if (oo.isPresent()) customRewards.remove(oo.get());
|
|
customRewards.add(reward);
|
|
final String name = reward.getName() == null ? "[" + jar.getName() + "]" : reward.getName();
|
|
final String author = reward.getAuthor() == null ? "[Unknown]" : reward.getAuthor();
|
|
count++;
|
|
getLogger().info("Loaded Module: " + name + " by " + author);
|
|
} else if (CustomObjective.class.isAssignableFrom(c)) {
|
|
final Class<? extends CustomObjective> objectiveClass = c.asSubclass(CustomObjective.class);
|
|
final Constructor<? extends CustomObjective> cstrctr = objectiveClass.getConstructor();
|
|
final CustomObjective objective = cstrctr.newInstance();
|
|
final Optional<CustomObjective>oo=getCustomObjective(objective.getClass().getName());
|
|
if (oo.isPresent()) {
|
|
HandlerList.unregisterAll(oo.get());
|
|
customObjectives.remove(oo.get());
|
|
}
|
|
customObjectives.add(objective);
|
|
final String name = objective.getName() == null ? "[" + jar.getName() + "]" : objective.getName();
|
|
final String author = objective.getAuthor() == null ? "[Unknown]" : objective.getAuthor();
|
|
count++;
|
|
getLogger().info("Loaded Module: " + name + " by " + author);
|
|
try {
|
|
getServer().getPluginManager().registerEvents(objective, this);
|
|
getLogger().info("Registered events for custom objective \"" + name + "\"");
|
|
} catch (final Exception ex) {
|
|
getLogger().warning("Failed to register events for custom objective \"" + name
|
|
+ "\". Does the objective class listen for events?");
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
if (count == 0) {
|
|
getLogger().severe("Unable to load module from file: " + jar.getName()
|
|
+ ", jar file is not a valid module!");
|
|
}
|
|
} catch (final Exception e) {
|
|
getLogger().severe("Unable to load module from file: " + jar.getName());
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show all of a player's objectives for the current stage of a quest.<p>
|
|
*
|
|
* Respects PlaceholderAPI and translations, when enabled.
|
|
*
|
|
* @param quest The quest to get current stage objectives of
|
|
* @param quester The player to show current stage objectives to
|
|
* @param ignoreOverrides Whether to ignore objective-overrides
|
|
*/
|
|
@SuppressWarnings("deprecation")
|
|
public void showObjectives(final Quest quest, final Quester quester, final boolean ignoreOverrides) {
|
|
if (quester.getQuestData(quest) == null) {
|
|
getLogger().warning("Quest data was null when showing objectives for " + quest.getName());
|
|
return;
|
|
}
|
|
if (quester.getCurrentStage(quest) == null) {
|
|
getLogger().warning("Current stage was null when showing objectives for " + quest.getName());
|
|
return;
|
|
}
|
|
if (!ignoreOverrides && !quester.getCurrentStage(quest).objectiveOverrides.isEmpty()) {
|
|
for (final String s: quester.getCurrentStage(quest).objectiveOverrides) {
|
|
String message = ChatColor.GREEN + ConfigUtil.parseString(
|
|
ChatColor.translateAlternateColorCodes('&', s), quest, quester.getPlayer());
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
return;
|
|
}
|
|
final QuestData data = quester.getQuestData(quest);
|
|
final Stage stage = quester.getCurrentStage(quest);
|
|
for (final ItemStack e : stage.blocksToBreak) {
|
|
for (final ItemStack e2 : data.blocksBroken) {
|
|
if (e2.getType().equals(e.getType()) && e2.getDurability() == e.getDurability()) {
|
|
final ChatColor color = e2.getAmount() < e.getAmount() ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "break") + " <item>"
|
|
+ color + ": " + e2.getAmount() + "/" + e.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !e.hasItemMeta() && !e.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, e.getType(), e.getDurability(), null);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(e)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final ItemStack e : stage.blocksToDamage) {
|
|
for (final ItemStack e2 : data.blocksDamaged) {
|
|
if (e2.getType().equals(e.getType()) && e2.getDurability() == e.getDurability()) {
|
|
final ChatColor color = e2.getAmount() < e.getAmount() ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "damage") + " <item>"
|
|
+ color + ": " + e2.getAmount() + "/" + e.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !e.hasItemMeta() && !e.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, e.getType(), e.getDurability(), null);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(e)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final ItemStack e : stage.blocksToPlace) {
|
|
for (final ItemStack e2 : data.blocksPlaced) {
|
|
if (e2.getType().equals(e.getType()) && e2.getDurability() == e.getDurability()) {
|
|
final ChatColor color = e2.getAmount() < e.getAmount() ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "place") + " <item>"
|
|
+ color + ": " + e2.getAmount() + "/" + e.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !e.hasItemMeta() && !e.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, e.getType(), e.getDurability(), null);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(e)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final ItemStack e : stage.blocksToUse) {
|
|
for (final ItemStack e2 : data.blocksUsed) {
|
|
if (e2.getType().equals(e.getType()) && e2.getDurability() == e.getDurability()) {
|
|
final ChatColor color = e2.getAmount() < e.getAmount() ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "use") + " <item>"
|
|
+ color + ": " + e2.getAmount() + "/" + e.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !e.hasItemMeta() && !e.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, e.getType(), e.getDurability(), null);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(e)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final ItemStack e : stage.blocksToCut) {
|
|
for (final ItemStack e2 : data.blocksCut) {
|
|
if (e2.getType().equals(e.getType()) && e2.getDurability() == e.getDurability()) {
|
|
final ChatColor color = e2.getAmount() < e.getAmount() ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "cut") + " <item>"
|
|
+ color + ": " + e2.getAmount() + "/" + e.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !e.hasItemMeta() && !e.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, e.getType(), e.getDurability(), null);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(e)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final ItemStack is : stage.itemsToCraft) {
|
|
int crafted = 0;
|
|
if (data.itemsCrafted.containsKey(is)) {
|
|
crafted = data.itemsCrafted.get(is);
|
|
}
|
|
final int amt = is.getAmount();
|
|
final ChatColor color = crafted < amt ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "craft") + " <item>"
|
|
+ color + ": " + crafted + "/" + is.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !is.hasItemMeta() && !is.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
|
|
is.getEnchantments());
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(is)));
|
|
}
|
|
}
|
|
for (final ItemStack is : stage.itemsToSmelt) {
|
|
int smelted = 0;
|
|
if (data.itemsSmelted.containsKey(is)) {
|
|
smelted = data.itemsSmelted.get(is);
|
|
}
|
|
final int amt = is.getAmount();
|
|
final ChatColor color = smelted < amt ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "smelt") + " <item>"
|
|
+ color + ": " + smelted + "/" + is.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !is.hasItemMeta() && !is.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
|
|
is.getEnchantments());
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(is)));
|
|
}
|
|
}
|
|
Map<Enchantment, Material> set;
|
|
Map<Enchantment, Material> set2;
|
|
Set<Enchantment> enchantSet;
|
|
Set<Enchantment> enchantSet2;
|
|
Collection<Material> matSet;
|
|
Enchantment enchantment = null;
|
|
Enchantment enchantment2 = null;
|
|
Material mat = null;
|
|
int num1;
|
|
int num2;
|
|
for (final Entry<Map<Enchantment, Material>, Integer> e : stage.itemsToEnchant.entrySet()) {
|
|
for (final Entry<Map<Enchantment, Material>, Integer> e2 : data.itemsEnchanted.entrySet()) {
|
|
set = e2.getKey();
|
|
set2 = e.getKey();
|
|
enchantSet = set.keySet();
|
|
enchantSet2 = set2.keySet();
|
|
for (final Object o : enchantSet.toArray()) {
|
|
enchantment = (Enchantment) o;
|
|
}
|
|
for (final Object o : enchantSet2.toArray()) {
|
|
enchantment2 = (Enchantment) o;
|
|
}
|
|
num1 = e2.getValue();
|
|
num2 = e.getValue();
|
|
matSet = set.values();
|
|
for (final Object o : matSet.toArray()) {
|
|
mat = (Material) o;
|
|
}
|
|
if (enchantment2 == enchantment) {
|
|
final ChatColor color = num1 < num2 ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "enchantItem")
|
|
+ color + ": " + num1 + "/" + num2;
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
final Map<Enchantment, Integer> enchs = new HashMap<Enchantment, Integer>();
|
|
enchs.put(enchantment, 1);
|
|
if (getSettings().canTranslateNames()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, mat, (short) 0, enchs);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message
|
|
.replace("<item>", ItemUtil.getName(new ItemStack(mat)))
|
|
.replace("<enchantment>", enchantment.getName()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final ItemStack is : stage.itemsToBrew) {
|
|
int brewed = 0;
|
|
if (data.itemsBrewed.containsKey(is)) {
|
|
brewed = data.itemsBrewed.get(is);
|
|
}
|
|
final int amt = is.getAmount();
|
|
final ChatColor color = brewed < amt ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "brew") + " <item>"
|
|
+ color + ": " + brewed + "/" + is.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames()) {
|
|
if (is.hasItemMeta() && !is.getItemMeta().hasDisplayName()) {
|
|
// Bukkit version is 1.9+
|
|
localeQuery.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
|
|
is.getEnchantments(), is.getItemMeta());
|
|
} else if (Material.getMaterial("LINGERING_POTION") == null && !is.hasItemMeta() ) {
|
|
// Bukkit version is below 1.9
|
|
localeQuery.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
|
|
is.getEnchantments());
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(is)));
|
|
}
|
|
}
|
|
}
|
|
for (final ItemStack is : stage.itemsToConsume) {
|
|
int consumed = 0;
|
|
if (data.itemsConsumed.containsKey(is)) {
|
|
consumed = data.itemsConsumed.get(is);
|
|
}
|
|
final int amt = is.getAmount();
|
|
final ChatColor color = consumed < amt ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "consume") + " <item>"
|
|
+ color + ": " + consumed + "/" + is.getAmount();
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !is.hasItemMeta() && !is.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
|
|
is.getEnchantments());
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(is)));
|
|
}
|
|
}
|
|
if (stage.cowsToMilk != null) {
|
|
final ChatColor color = data.getCowsMilked() < stage.cowsToMilk ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "milkCow")
|
|
+ color + ": " + data.getCowsMilked() + "/" + stage.cowsToMilk;
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
if (stage.fishToCatch != null) {
|
|
final ChatColor color = data.getFishCaught() < stage.fishToCatch ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "catchFish")
|
|
+ color + ": " + data.getFishCaught() + "/" + stage.fishToCatch;
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
for (final EntityType e : stage.mobsToKill) {
|
|
for (final EntityType e2 : data.mobsKilled) {
|
|
if (e == e2) {
|
|
if (data.mobNumKilled.size() > data.mobsKilled.indexOf(e2)
|
|
&& stage.mobNumToKill.size() > stage.mobsToKill.indexOf(e)) {
|
|
final ChatColor color = data.mobNumKilled.get(data.mobsKilled.indexOf(e2))
|
|
< stage.mobNumToKill.get(stage.mobsToKill.indexOf(e))
|
|
? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = "";
|
|
if (stage.locationsToKillWithin.isEmpty()) {
|
|
message = color + Lang.get(quester.getPlayer(), "kill") + " "
|
|
+ ChatColor.AQUA + "<mob>" + color + ": "
|
|
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2)))
|
|
+ "/" + (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e)));
|
|
} else {
|
|
message = color + Lang.get(quester.getPlayer(), "killAtLocation") + color + ": "
|
|
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
|
|
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e)));
|
|
message = message.replace("<location>",
|
|
stage.killNames.get(stage.mobsToKill.indexOf(e)));
|
|
}
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, e, null);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<mob>", MiscUtil.getProperMobName(e)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (stage.playersToKill != null) {
|
|
final ChatColor color = data.getPlayersKilled() < stage.playersToKill ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "killPlayer")
|
|
+ color + ": " + data.getPlayersKilled() + "/" + stage.playersToKill;
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
int index = 0;
|
|
for (final ItemStack is : stage.itemsToDeliver) {
|
|
int delivered = 0;
|
|
if (data.itemsDelivered.size() > index) {
|
|
delivered = data.itemsDelivered.get(index).getAmount();
|
|
}
|
|
final int toDeliver = is.getAmount();
|
|
final Integer npc = stage.itemDeliveryTargets.get(index);
|
|
index++;
|
|
final ChatColor color = delivered < toDeliver ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "deliver")
|
|
+ color + ": " + delivered + "/" + toDeliver;
|
|
message = message.replace("<npc>", depends.getNPCName(npc));
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
if (getSettings().canTranslateNames() && !is.hasItemMeta() && !is.getItemMeta().hasDisplayName()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
|
|
is.getEnchantments());
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<item>", ItemUtil.getName(is)));
|
|
}
|
|
}
|
|
for (final Integer n : stage.citizensToInteract) {
|
|
for (final Entry<Integer, Boolean> e : data.citizensInteracted.entrySet()) {
|
|
if (e.getKey().equals(n)) {
|
|
final ChatColor color = e.getValue() == false ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "talkTo");
|
|
message = message.replace("<npc>", depends.getNPCName(n));
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
}
|
|
}
|
|
for (final Integer n : stage.citizensToKill) {
|
|
for (final Integer n2 : data.citizensKilled) {
|
|
if (n.equals(n2)) {
|
|
if (data.citizenNumKilled.size() > data.citizensKilled.indexOf(n2)
|
|
&& stage.citizenNumToKill.size() > stage.citizensToKill.indexOf(n)) {
|
|
final ChatColor color = data.citizenNumKilled.get(data.citizensKilled.indexOf(n2))
|
|
< stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n)) == false
|
|
? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "kill") + " " + depends.getNPCName(n)
|
|
+ color + " " + data.citizenNumKilled.get(stage.citizensToKill.indexOf(n)) + "/"
|
|
+ stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n));
|
|
if (depends.getPlaceholderApi() != null) {
|
|
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
|
|
}
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final Entry<EntityType, Integer> e : stage.mobsToTame.entrySet()) {
|
|
for (final Entry<EntityType, Integer> e2 : data.mobsTamed.entrySet()) {
|
|
if (e.getKey().equals(e2.getKey())) {
|
|
final ChatColor color = e2.getValue() < e.getValue() == false ? ChatColor.GREEN : ChatColor.GRAY;
|
|
final String message = color + Lang.get(quester.getPlayer(), "tame") + " " + "<mob>"
|
|
+ color + ": " + e2.getValue() + "/" + e.getValue();
|
|
if (getSettings().canTranslateNames()) {
|
|
localeQuery.sendMessage(quester.getPlayer(), message, e.getKey(), null);
|
|
} else {
|
|
quester.getPlayer().sendMessage(message.replace("<mob>",
|
|
MiscUtil.getProperMobName(e.getKey())));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final Entry<DyeColor, Integer> e : stage.sheepToShear.entrySet()) {
|
|
for (final Entry<DyeColor, Integer> e2 : data.sheepSheared.entrySet()) {
|
|
if (e.getKey().equals(e2.getKey())) {
|
|
final ChatColor color = e2.getValue() < e.getValue() == false ? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "shearSheep")
|
|
+ color + ": " + e2.getValue() + "/" + e.getValue();
|
|
message = message.replace("<color>",
|
|
MiscUtil.getPrettyDyeColorName(MiscUtil.getProperDyeColor(e.getKey().name())));
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
}
|
|
}
|
|
for (final Location l : stage.locationsToReach) {
|
|
for (final Location l2 : data.locationsReached) {
|
|
if (l.equals(l2)) {
|
|
if (!data.hasReached.isEmpty()) {
|
|
final ChatColor color = data.hasReached.get(data.locationsReached.indexOf(l2)) == false
|
|
? ChatColor.GREEN : ChatColor.GRAY;
|
|
String message = color + Lang.get(quester.getPlayer(), "goTo");
|
|
message = message.replace("<location>",
|
|
stage.locationNames.get(stage.locationsToReach.indexOf(l)));
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (final String s : stage.passwordDisplays) {
|
|
if (data.passwordsSaid.containsKey(s)) {
|
|
final Boolean b = data.passwordsSaid.get(s);
|
|
final ChatColor color = b != null && !b == false ? ChatColor.GREEN : ChatColor.GRAY;
|
|
final String message = color + s;
|
|
quester.getPlayer().sendMessage(message);
|
|
}
|
|
}
|
|
for (final CustomObjective co : stage.customObjectives) {
|
|
int countsIndex = 0;
|
|
String display = co.getDisplay();
|
|
final List<String> unfinished = new LinkedList<String>();
|
|
final List<String> finished = new LinkedList<String>();
|
|
for (final Entry<String, Integer> entry : data.customObjectiveCounts.entrySet()) {
|
|
if (co.getName().equals(entry.getKey())) {
|
|
for (final Entry<String,Object> prompt : co.getData()) {
|
|
final String replacement = "%" + prompt.getKey() + "%";
|
|
try {
|
|
for (final Entry<String, Object> e : stage.customObjectiveData) {
|
|
if (e.getKey().equals(prompt.getKey())) {
|
|
if (display.contains(replacement)) {
|
|
display = display.replace(replacement, ((String) e.getValue()));
|
|
}
|
|
}
|
|
}
|
|
} catch (final NullPointerException ne) {
|
|
getLogger().severe("Unable to fetch display for " + co.getName() + " on "
|
|
+ quest.getName());
|
|
ne.printStackTrace();
|
|
}
|
|
}
|
|
if (entry.getValue() < stage.customObjectiveCounts.get(countsIndex)) {
|
|
if (co.canShowCount()) {
|
|
display = display.replace("%count%", entry.getValue() + "/"
|
|
+ stage.customObjectiveCounts.get(countsIndex));
|
|
}
|
|
unfinished.add(display);
|
|
} else {
|
|
if (co.canShowCount()) {
|
|
display = display.replace("%count%", stage.customObjectiveCounts.get(countsIndex)
|
|
+ "/" + stage.customObjectiveCounts.get(countsIndex));
|
|
}
|
|
finished.add(display);
|
|
}
|
|
}
|
|
countsIndex++;
|
|
}
|
|
for (final String s : unfinished) {
|
|
quester.getPlayer().sendMessage(ChatColor.GREEN + s);
|
|
}
|
|
for (final String s : finished) {
|
|
quester.getPlayer().sendMessage(ChatColor.GRAY + s);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show the player a list of their quests
|
|
*
|
|
* @param quester Quester to show the list
|
|
* @param page Page to display, with 7 quests per page
|
|
*/
|
|
public void listQuests(final Quester quester, final int page) {
|
|
// Although we could copy the quests list to a new object, we instead opt to
|
|
// duplicate code to improve efficiency if ignore-locked-quests is set to 'false'
|
|
final int rows = 7;
|
|
final Player player = quester.getPlayer();
|
|
if (getSettings().canIgnoreLockedQuests()) {
|
|
final LinkedList<Quest> available = new LinkedList<Quest>();
|
|
for (final Quest q : quests) {
|
|
if (quester.getCompletedQuests().contains(q.getName()) == false) {
|
|
if (q.testRequirements(player)) {
|
|
available.add(q);
|
|
}
|
|
} else if (q.getPlanner().hasCooldown() && quester.getRemainingCooldown(q) < 0) {
|
|
if (q.testRequirements(player)) {
|
|
available.add(q);
|
|
}
|
|
}
|
|
}
|
|
if ((available.size() + rows) <= (page * rows) || available.size() == 0) {
|
|
player.sendMessage(ChatColor.YELLOW + Lang.get(player, "pageNotExist"));
|
|
} else {
|
|
player.sendMessage(ChatColor.GOLD + Lang.get(player, "questListTitle"));
|
|
int fromOrder = (page - 1) * rows;
|
|
List<Quest> subQuests;
|
|
if (available.size() >= (fromOrder + rows)) {
|
|
subQuests = available.subList((fromOrder), (fromOrder + rows));
|
|
} else {
|
|
subQuests = available.subList((fromOrder), available.size());
|
|
}
|
|
fromOrder++;
|
|
for (final Quest q : subQuests) {
|
|
player.sendMessage(ChatColor.YELLOW + Integer.toString(fromOrder) + ". " + q.getName());
|
|
fromOrder++;
|
|
}
|
|
final int numPages = (int) Math.ceil(((double) available.size()) / ((double) rows));
|
|
String msg = Lang.get(player, "pageFooter");
|
|
msg = msg.replace("<current>", String.valueOf(page));
|
|
msg = msg.replace("<all>", String.valueOf(numPages));
|
|
player.sendMessage(ChatColor.GOLD + msg);
|
|
}
|
|
} else {
|
|
if ((quests.size() + rows) <= (page * rows) || quests.size() == 0) {
|
|
player.sendMessage(ChatColor.YELLOW + Lang.get(player, "pageNotExist"));
|
|
} else {
|
|
player.sendMessage(ChatColor.GOLD + Lang.get(player, "questListTitle"));
|
|
int fromOrder = (page - 1) * rows;
|
|
List<Quest> subQuests;
|
|
if (quests.size() >= (fromOrder + rows)) {
|
|
subQuests = quests.subList((fromOrder), (fromOrder + rows));
|
|
} else {
|
|
subQuests = quests.subList((fromOrder), quests.size());
|
|
}
|
|
fromOrder++;
|
|
for (final Quest q : subQuests) {
|
|
player.sendMessage(ChatColor.YELLOW + Integer.toString(fromOrder) + ". " + q.getName());
|
|
fromOrder++;
|
|
}
|
|
final int numPages = (int) Math.ceil(((double) quests.size()) / ((double) rows));
|
|
String msg = Lang.get(player, "pageFooter");
|
|
msg = msg.replace("<current>", String.valueOf(page));
|
|
msg = msg.replace("<all>", String.valueOf(numPages));
|
|
player.sendMessage(ChatColor.GOLD + msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use {@link #reload(ReloadCallback)}
|
|
*/
|
|
@Deprecated
|
|
public void reloadQuests() {
|
|
reload(null);
|
|
}
|
|
|
|
/**
|
|
* Reload quests, actions, config settings, lang and modules, and player data
|
|
*/
|
|
public void reload(final ReloadCallback<Boolean> callback) {
|
|
reloadConfig();
|
|
Bukkit.getScheduler().runTaskAsynchronously(this, new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
loading = true;
|
|
try {
|
|
for (final Quester quester : questers) {
|
|
quester.saveData();
|
|
}
|
|
quests.clear();
|
|
actions.clear();
|
|
conditions.clear();
|
|
Lang.clear();
|
|
settings.init();
|
|
Lang.init(Quests.this);
|
|
loadQuests();
|
|
loadActions();
|
|
loadConditions();
|
|
for (final Quester quester : questers) {
|
|
quester.loadData();
|
|
for (final Quest q : quester.currentQuests.keySet()) {
|
|
quester.checkQuest(q);
|
|
}
|
|
}
|
|
loadModules();
|
|
|
|
if (callback != null) {
|
|
Bukkit.getScheduler().runTask(Quests.this, new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
callback.execute(true);
|
|
}
|
|
});
|
|
}
|
|
} catch (final Exception e) {
|
|
e.printStackTrace();
|
|
if (callback != null) {
|
|
Bukkit.getScheduler().runTask(Quests.this, new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
callback.execute(false);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
loading = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get Quester from player UUID
|
|
*
|
|
* @param id Player UUID
|
|
* @return Quester, or null if not found
|
|
*/
|
|
public Quester getQuester(final UUID id) {
|
|
Quester quester = null;
|
|
for (final Quester q: questers) {
|
|
if (q.getUUID().equals(id)) {
|
|
quester = q;
|
|
}
|
|
}
|
|
if (quester == null) {
|
|
quester = new Quester(this);
|
|
quester.setUUID(id);
|
|
if (depends.getCitizens() != null) {
|
|
if (depends.getCitizens().getNPCRegistry().getByUniqueId(id) != null) {
|
|
return quester;
|
|
}
|
|
}
|
|
questers.add(quester);
|
|
if (!quester.loadData()) {
|
|
questers.remove(quester);
|
|
}
|
|
}
|
|
return quester;
|
|
}
|
|
|
|
/**
|
|
* Get a list of all online Questers
|
|
*
|
|
* @deprecated Use {@link Bukkit#getOnlinePlayers()} and then {@link #getQuester(UUID)}
|
|
* @return list of online Questers
|
|
*/
|
|
@Deprecated
|
|
public LinkedList<Quester> getOnlineQuesters() {
|
|
final LinkedList<Quester> qs = new LinkedList<Quester>();
|
|
for (final Player p : getServer().getOnlinePlayers()) {
|
|
final Quester quester = new Quester(this);
|
|
quester.setUUID(p.getUniqueId());
|
|
if (quester.loadData() == false) {
|
|
quester.saveData();
|
|
}
|
|
qs.add(quester);
|
|
// Workaround for issues with the compass on fast join
|
|
quester.findCompassTarget();
|
|
}
|
|
return qs;
|
|
}
|
|
|
|
/**
|
|
* Load quests from file
|
|
*/
|
|
public void loadQuests() {
|
|
boolean failedToLoad;
|
|
boolean needsSaving = false;
|
|
FileConfiguration config = null;
|
|
final File file = new File(this.getDataFolder(), "quests.yml");
|
|
try {
|
|
config = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(file), "UTF-8"));
|
|
} catch (final IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
if (config != null) {
|
|
ConfigurationSection questsSection;
|
|
if (config.contains("quests")) {
|
|
questsSection = config.getConfigurationSection("quests");
|
|
} else {
|
|
questsSection = config.createSection("quests");
|
|
needsSaving = true;
|
|
}
|
|
if (questsSection == null) {
|
|
getLogger().severe("Missing \'quests\' section marker within quests.yml, canceled loading");
|
|
return;
|
|
}
|
|
for (final String questKey : questsSection.getKeys(false)) {
|
|
try {
|
|
final Quest quest = new Quest();
|
|
failedToLoad = false;
|
|
quest.id = questKey;
|
|
if (config.contains("quests." + questKey + ".name")) {
|
|
quest.setName(ConfigUtil.parseString(config.getString("quests." + questKey + ".name"), quest));
|
|
} else {
|
|
throw new QuestFormatException("name is missing", questKey);
|
|
}
|
|
if (config.contains("quests." + questKey + ".ask-message")) {
|
|
quest.description = ConfigUtil.parseString(config.getString("quests." + questKey
|
|
+ ".ask-message"), quest);
|
|
} else {
|
|
throw new QuestFormatException("ask-message is missing", questKey);
|
|
}
|
|
if (config.contains("quests." + questKey + ".finish-message")) {
|
|
quest.finished = ConfigUtil.parseString(config.getString("quests." + questKey
|
|
+ ".finish-message"), quest);
|
|
} else {
|
|
throw new QuestFormatException("finish-message is missing", questKey);
|
|
}
|
|
if (depends.getCitizens() != null && config.contains("quests." + questKey + ".npc-giver-id")) {
|
|
if (CitizensAPI.getNPCRegistry().getById(config.getInt("quests." + questKey + ".npc-giver-id"))
|
|
!= null) {
|
|
quest.npcStart = CitizensAPI.getNPCRegistry().getById(config.getInt("quests." + questKey
|
|
+ ".npc-giver-id"));
|
|
questNpcs.add(CitizensAPI.getNPCRegistry().getById(config.getInt("quests." + questKey
|
|
+ ".npc-giver-id")));
|
|
} else {
|
|
throw new QuestFormatException("npc-giver-id has invalid NPC ID", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".block-start")) {
|
|
final Location location = ConfigUtil.getLocation(config.getString("quests." + questKey
|
|
+ ".block-start"));
|
|
if (location != null) {
|
|
quest.blockStart = location;
|
|
} else {
|
|
throw new QuestFormatException("block-start has invalid location format", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".region")
|
|
&& getDependencies().getWorldGuardApi() != null) {
|
|
final String region = config.getString("quests." + questKey + ".region");
|
|
boolean exists = false;
|
|
for (final World world : getServer().getWorlds()) {
|
|
if (getDependencies().getWorldGuardApi().getRegionManager(world) != null) {
|
|
if (getDependencies().getWorldGuardApi().getRegionManager(world).hasRegion(region)) {
|
|
quest.regionStart = region;
|
|
exists = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!exists) {
|
|
throw new QuestFormatException("region has invalid WorldGuard region name", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".gui-display")) {
|
|
ItemStack stack = config.getItemStack("quests." + questKey + ".gui-display");
|
|
if (stack == null) {
|
|
// Legacy
|
|
final String item = config.getString("quests." + questKey + ".gui-display");
|
|
try {
|
|
stack = ItemUtil.readItemStack(item);
|
|
} catch (final Exception e) {
|
|
throw new QuestFormatException("items has invalid formatting for " + item, questKey);
|
|
}
|
|
}
|
|
if (stack != null) {
|
|
quest.guiDisplay = stack;
|
|
} else {
|
|
throw new QuestFormatException("gui-display has invalid item format", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".redo-delay")) {
|
|
// Legacy
|
|
if (config.getInt("quests." + questKey + ".redo-delay", -999) != -999) {
|
|
quest.getPlanner().setCooldown(config.getInt("quests." + questKey + ".redo-delay") * 1000);
|
|
} else {
|
|
throw new QuestFormatException("redo-delay is not a number", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".action")) {
|
|
final Action act = loadAction(config.getString("quests." + questKey + ".action"));
|
|
if (act != null) {
|
|
quest.initialAction = act;
|
|
} else {
|
|
throw new QuestFormatException("action failed to load", questKey);
|
|
}
|
|
} else if (config.contains("quests." + questKey + ".event")) {
|
|
Action action = null;
|
|
|
|
action = loadAction(config.getString("quests." + questKey + ".event"));
|
|
if (action != null) {
|
|
quest.initialAction = action;
|
|
} else {
|
|
throw new QuestFormatException("action failed to load", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements")) {
|
|
loadQuestRequirements(config, questsSection, quest, questKey);
|
|
}
|
|
if (config.contains("quests." + questKey + ".planner")) {
|
|
loadQuestPlanner(config, questsSection, quest, questKey);
|
|
}
|
|
if (config.contains("quests." + questKey + ".options")) {
|
|
loadQuestOptions(config, questsSection, quest, questKey);
|
|
}
|
|
quest.plugin = this;
|
|
loadQuestStages(quest, config, questKey);
|
|
loadQuestRewards(config, quest, questKey);
|
|
quests.add(quest);
|
|
if (needsSaving) {
|
|
try {
|
|
config.save(file);
|
|
} catch (final IOException e) {
|
|
getLogger().log(Level.SEVERE, "Failed to save Quest \"" + questKey + "\"");
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
if (failedToLoad == true) {
|
|
getLogger().log(Level.SEVERE, "Failed to load Quest \"" + questKey + "\". Skipping.");
|
|
}
|
|
} catch (final QuestFormatException e) {
|
|
e.printStackTrace();
|
|
continue;
|
|
} catch (final StageFormatException e) {
|
|
e.printStackTrace();
|
|
continue;
|
|
} catch (final ActionFormatException e) {
|
|
e.printStackTrace();
|
|
continue;
|
|
} catch (final ConditionFormatException e) {
|
|
e.printStackTrace();
|
|
continue;
|
|
}
|
|
}
|
|
} else {
|
|
getLogger().severe("Unable to load quests.yml");
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private void loadQuestRewards(final FileConfiguration config, final Quest quest, final String questKey) throws QuestFormatException {
|
|
final Rewards rews = quest.getRewards();
|
|
if (config.contains("quests." + questKey + ".rewards.items")) {
|
|
final LinkedList<ItemStack> temp = new LinkedList<ItemStack>();
|
|
final List<ItemStack> stackList = (List<ItemStack>) config.get("quests." + questKey + ".rewards.items");
|
|
if (ConfigUtil.checkList(stackList, ItemStack.class)) {
|
|
for (final ItemStack stack : stackList) {
|
|
if (stack != null) {
|
|
temp.add(stack);
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy
|
|
if (ConfigUtil.checkList(stackList, String.class)) {
|
|
final List<String> items = config.getStringList("quests." + questKey + ".rewards.items");
|
|
for (final String item : items) {
|
|
try {
|
|
final ItemStack stack = ItemUtil.readItemStack(item);
|
|
if (stack != null) {
|
|
temp.add(stack);
|
|
}
|
|
} catch (final Exception e) {
|
|
throw new QuestFormatException("Reward items has invalid formatting for " + item, questKey);
|
|
}
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Reward items has invalid formatting", questKey);
|
|
}
|
|
}
|
|
rews.setItems(temp);
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.money")) {
|
|
if (config.getInt("quests." + questKey + ".rewards.money", -999) != -999) {
|
|
rews.setMoney(config.getInt("quests." + questKey + ".rewards.money"));
|
|
} else {
|
|
throw new QuestFormatException("Reward money is not a number", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.exp")) {
|
|
if (config.getInt("quests." + questKey + ".rewards.exp", -999) != -999) {
|
|
rews.setExp(config.getInt("quests." + questKey + ".rewards.exp"));
|
|
} else {
|
|
throw new QuestFormatException("Reward exp is not a number", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.commands")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.commands"), String.class)) {
|
|
rews.setCommands(config.getStringList("quests." + questKey + ".rewards.commands"));
|
|
} else {
|
|
throw new QuestFormatException("Reward commands is not a list of commands", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.commands-override-display")) {
|
|
// Legacy
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.commands-override-display"),
|
|
String.class)) {
|
|
rews.setCommandsOverrideDisplay(config.getStringList("quests." + questKey
|
|
+ ".rewards.commands-override-display"));
|
|
} else {
|
|
throw new QuestFormatException("Reward commands-override-display is not a list of strings", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.permissions")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.permissions"), String.class)) {
|
|
rews.setPermissions(config.getStringList("quests." + questKey + ".rewards.permissions"));
|
|
} else {
|
|
throw new QuestFormatException("Reward permissions is not a list of permissions", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.permission-worlds")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey
|
|
+ ".rewards.permission-worlds"), String.class)) {
|
|
rews.setPermissionWorlds(config.getStringList("quests." + questKey + ".rewards.permission-worlds"));
|
|
} else {
|
|
throw new QuestFormatException("Reward permissions is not a list of worlds", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.quest-points")) {
|
|
if (config.getInt("quests." + questKey + ".rewards.quest-points", -999) != -999) {
|
|
rews.setQuestPoints(config.getInt("quests." + questKey + ".rewards.quest-points"));
|
|
} else {
|
|
throw new QuestFormatException("Reward quest-points is not a number", questKey);
|
|
}
|
|
}
|
|
if (depends.isPluginAvailable("mcMMO")) {
|
|
if (config.contains("quests." + questKey + ".rewards.mcmmo-skills")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.mcmmo-skills"),
|
|
String.class)) {
|
|
if (config.contains("quests." + questKey + ".rewards.mcmmo-levels")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.mcmmo-levels"),
|
|
Integer.class)) {
|
|
for (final String skill : config.getStringList("quests." + questKey + ".rewards.mcmmo-skills")) {
|
|
if (depends.getMcmmoClassic() == null) {
|
|
throw new QuestFormatException("Reward mcMMO not found for mcmmo-skills", questKey);
|
|
} else if (Quests.getMcMMOSkill(skill) == null) {
|
|
throw new QuestFormatException("Reward mcmmo-skills has invalid skill name " + skill, questKey);
|
|
}
|
|
}
|
|
rews.setMcmmoSkills(config.getStringList("quests." + questKey + ".rewards.mcmmo-skills"));
|
|
rews.setMcmmoAmounts(config.getIntegerList("quests." + questKey + ".rewards.mcmmo-levels"));
|
|
} else {
|
|
throw new QuestFormatException("Reward mcmmo-levels is not a list of numbers", questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Reward mcmmo-levels is missing!", questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Reward mcmmo-skills is not a list of mcMMO skill names", questKey);
|
|
}
|
|
}
|
|
}
|
|
if (depends.isPluginAvailable("Heroes")) {
|
|
if (config.contains("quests." + questKey + ".rewards.heroes-exp-classes")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.heroes-exp-classes"),
|
|
String.class)) {
|
|
if (config.contains("quests." + questKey + ".rewards.heroes-exp-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.heroes-exp-amounts"),
|
|
Double.class)) {
|
|
for (final String heroClass : config.getStringList("quests." + questKey
|
|
+ ".rewards.heroes-exp-classes")) {
|
|
if (depends.getHeroes() == null) {
|
|
throw new QuestFormatException("Heroes not found for heroes-exp-classes", questKey);
|
|
} else if (depends.getHeroes().getClassManager().getClass(heroClass) == null) {
|
|
throw new QuestFormatException("Reward heroes-exp-classes has invalid class name "
|
|
+ heroClass, questKey);
|
|
}
|
|
}
|
|
rews.setHeroesClasses(config.getStringList("quests." + questKey
|
|
+ ".rewards.heroes-exp-classes"));
|
|
rews.setHeroesAmounts(config.getDoubleList("quests." + questKey
|
|
+ ".rewards.heroes-exp-amounts"));
|
|
} else {
|
|
throw new QuestFormatException("Reward heroes-exp-amounts is not a list of decimal numbers", questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Reward heroes-exp-amounts is missing", questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Reward heroes-exp-classes is not a list of Heroes classes", questKey);
|
|
}
|
|
}
|
|
}
|
|
if (depends.isPluginAvailable("PhatLoots")) {
|
|
if (config.contains("quests." + questKey + ".rewards.phat-loots")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".rewards.phat-loots"), String.class)) {
|
|
for (final String loot : config.getStringList("quests." + questKey + ".rewards.phat-loots")) {
|
|
if (depends.getPhatLoots() == null) {
|
|
throw new QuestFormatException("PhatLoots not found for phat-loots", questKey);
|
|
} else if (PhatLootsAPI.getPhatLoot(loot) == null) {
|
|
throw new QuestFormatException("Reward phat-loots has invalid PhatLoot name " + loot, questKey);
|
|
}
|
|
}
|
|
rews.setPhatLoots(config.getStringList("quests." + questKey + ".rewards.phat-loots"));
|
|
} else {
|
|
throw new QuestFormatException("Reward phat-loots is not a list of PhatLoots", questKey);
|
|
}
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".rewards.details-override")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey
|
|
+ ".rewards.details-override"), String.class)) {
|
|
rews.setDetailsOverride(config.getStringList("quests." + questKey + ".rewards.details-override"));
|
|
} else {
|
|
throw new QuestFormatException("Reward details-override is not a list of strings", questKey);
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private void loadQuestRequirements(final FileConfiguration config, final ConfigurationSection questsSection, final Quest quest,
|
|
final String questKey) throws QuestFormatException {
|
|
final Requirements reqs = quest.getRequirements();
|
|
if (config.contains("quests." + questKey + ".requirements.fail-requirement-message")) {
|
|
final Object o = config.get("quests." + questKey + ".requirements.fail-requirement-message");
|
|
if (o instanceof List) {
|
|
reqs.setDetailsOverride(config.getStringList("quests." + questKey
|
|
+ ".requirements.fail-requirement-message"));
|
|
} else {
|
|
// Legacy
|
|
final List<String> override = new LinkedList<String>();
|
|
override.add((String) o);
|
|
reqs.setDetailsOverride(override);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.items")) {
|
|
final List<ItemStack> temp = new LinkedList<ItemStack>();
|
|
final List<ItemStack> stackList = (List<ItemStack>) config.get("quests." + questKey + ".requirements.items");
|
|
if (ConfigUtil.checkList(stackList, ItemStack.class)) {
|
|
for (final ItemStack stack : stackList) {
|
|
if (stack != null) {
|
|
temp.add(stack);
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy
|
|
final List<String> items = config.getStringList("quests." + questKey + ".requirements.items");
|
|
if (ConfigUtil.checkList(items, String.class)) {
|
|
for (final String item : items) {
|
|
try {
|
|
final ItemStack stack = ItemUtil.readItemStack(item);
|
|
if (stack != null) {
|
|
temp.add(stack);
|
|
}
|
|
} catch (final Exception e) {
|
|
throw new QuestFormatException("Requirement items has invalid formatting for " + item, questKey);
|
|
}
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Requirement items has invalid formatting", questKey);
|
|
}
|
|
}
|
|
reqs.setItems(temp);
|
|
if (config.contains("quests." + questKey + ".requirements.remove-items")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".requirements.remove-items"),
|
|
Boolean.class)) {
|
|
reqs.setRemoveItems(config.getBooleanList("quests." + questKey + ".requirements.remove-items"));
|
|
} else {
|
|
throw new QuestFormatException("Requirement remove-items is not a list of true/false values", questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Requirement remove-items is missing", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.money")) {
|
|
if (config.getInt("quests." + questKey + ".requirements.money", -999) != -999) {
|
|
reqs.setMoney(config.getInt("quests." + questKey + ".requirements.money"));
|
|
} else {
|
|
throw new QuestFormatException("Requirement money is not a number", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.quest-points")) {
|
|
if (config.getInt("quests." + questKey + ".requirements.quest-points", -999) != -999) {
|
|
reqs.setQuestPoints(config.getInt("quests." + questKey + ".requirements.quest-points"));
|
|
} else {
|
|
throw new QuestFormatException("Requirement quest-points is not a number", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.quest-blocks")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".requirements.quest-blocks"),
|
|
String.class)) {
|
|
final List<String> names = config.getStringList("quests." + questKey + ".requirements.quest-blocks");
|
|
boolean failed = false;
|
|
String failedQuest = "NULL";
|
|
final List<String> temp = new LinkedList<String>();
|
|
for (final String name : names) {
|
|
boolean done = false;
|
|
for (final String id : questsSection.getKeys(false)) {
|
|
final String name2 = config.getString("quests." + id + ".name");
|
|
if (name2.equalsIgnoreCase(name)
|
|
|| ChatColor.stripColor(name2).equalsIgnoreCase(ChatColor.stripColor(name))) {
|
|
temp.add(name);
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!done) {
|
|
failed = true;
|
|
failedQuest = name;
|
|
break;
|
|
}
|
|
}
|
|
reqs.setBlockQuests(temp);
|
|
if (failed) {
|
|
throw new QuestFormatException("Requirement quest-blocks has invalid quest name " + failedQuest, questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Requirement quest-blocks is not a list of quest names", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.quests")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".requirements.quests"), String.class)) {
|
|
final List<String> names = config.getStringList("quests." + questKey + ".requirements.quests");
|
|
boolean failed = false;
|
|
String failedQuest = "NULL";
|
|
final List<String> temp = new LinkedList<String>();
|
|
for (final String name : names) {
|
|
boolean done = false;
|
|
for (final String id : questsSection.getKeys(false)) {
|
|
final String name2 = config.getString("quests." + id + ".name");
|
|
if (name2.equalsIgnoreCase(name)
|
|
|| ChatColor.stripColor(name2).equalsIgnoreCase(ChatColor.stripColor(name))) {
|
|
temp.add(name);
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!done) {
|
|
failed = true;
|
|
failedQuest = name;
|
|
break;
|
|
}
|
|
}
|
|
reqs.setNeededQuests(temp);
|
|
if (failed) {
|
|
throw new QuestFormatException("Requirement quests has invalid quest name " + failedQuest, questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Requirement quests is not a list of quest names", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.permissions")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".requirements.permissions"),
|
|
String.class)) {
|
|
reqs.setPermissions(config.getStringList("quests." + questKey + ".requirements.permissions"));
|
|
} else {
|
|
throw new QuestFormatException("Requirement permissions is not a list of permissions", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.mcmmo-skills")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".requirements.mcmmo-skills"),
|
|
String.class)) {
|
|
if (config.contains("quests." + questKey + ".requirements.mcmmo-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".requirements.mcmmo-amounts"),
|
|
Integer.class)) {
|
|
final List<String> skills = config.getStringList("quests." + questKey + ".requirements.mcmmo-skills");
|
|
final List<Integer> amounts = config.getIntegerList("quests." + questKey
|
|
+ ".requirements.mcmmo-amounts");
|
|
if (skills.size() != amounts.size()) {
|
|
throw new QuestFormatException("Requirement mcmmo-skills: and mcmmo-amounts are not the same size",
|
|
questKey);
|
|
}
|
|
reqs.setMcmmoSkills(skills);
|
|
reqs.setMcmmoAmounts(amounts);
|
|
} else {
|
|
throw new QuestFormatException("Requirement mcmmo-amounts is not a list of numbers", questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Requirement mcmmo-amounts is missing", questKey);
|
|
}
|
|
} else {
|
|
throw new QuestFormatException("Requirement mcmmo-skills is not a list of skills", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.heroes-primary-class")) {
|
|
final String className = config.getString("quests." + questKey + ".requirements.heroes-primary-class");
|
|
final HeroClass hc = depends.getHeroes().getClassManager().getClass(className);
|
|
if (hc != null && hc.isPrimary()) {
|
|
reqs.setHeroesPrimaryClass(hc.getName());
|
|
} else if (hc != null) {
|
|
throw new QuestFormatException("Requirement heroes-primary-class is not a primary Heroes class", questKey);
|
|
} else {
|
|
throw new QuestFormatException("Requirement heroes-primary-class has invalid Heroes class", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.heroes-secondary-class")) {
|
|
final String className = config.getString("quests." + questKey + ".requirements.heroes-secondary-class");
|
|
final HeroClass hc = depends.getHeroes().getClassManager().getClass(className);
|
|
if (hc != null && hc.isSecondary()) {
|
|
reqs.setHeroesSecondaryClass(hc.getName());
|
|
} else if (hc != null) {
|
|
throw new QuestFormatException("Requirement heroes-secondary-class is not a secondary Heroes class", questKey);
|
|
} else {
|
|
throw new QuestFormatException("Requirement heroes-secondary-class has invalid Heroes class", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".requirements.details-override")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey
|
|
+ ".requirements.details-override"), String.class)) {
|
|
reqs.setDetailsOverride(config.getStringList("quests." + questKey + ".requirements.details-override"));
|
|
} else {
|
|
throw new QuestFormatException("Requirement details-override is not a list of strings", questKey);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void loadQuestPlanner(final FileConfiguration config, final ConfigurationSection questsSection, final Quest quest,
|
|
final String questKey) throws QuestFormatException {
|
|
final Planner pln = quest.getPlanner();
|
|
if (config.contains("quests." + questKey + ".planner.start")) {
|
|
pln.setStart(config.getString("quests." + questKey + ".planner.start"));
|
|
}
|
|
if (config.contains("quests." + questKey + ".planner.end")) {
|
|
pln.setEnd(config.getString("quests." + questKey + ".planner.end"));
|
|
}
|
|
if (config.contains("quests." + questKey + ".planner.repeat")) {
|
|
if (config.getInt("quests." + questKey + ".planner.repeat", -999) != -999) {
|
|
pln.setRepeat(config.getInt("quests." + questKey + ".planner.repeat") * 1000);
|
|
} else {
|
|
throw new QuestFormatException("Requirement repeat is not a number", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".planner.cooldown")) {
|
|
if (config.getInt("quests." + questKey + ".planner.cooldown", -999) != -999) {
|
|
pln.setCooldown(config.getInt("quests." + questKey + ".planner.cooldown") * 1000);
|
|
} else {
|
|
throw new QuestFormatException("Requirement cooldown is not a number", questKey);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".planner.override")) {
|
|
pln.setOverride(config.getBoolean("quests." + questKey + ".planner.override"));
|
|
}
|
|
}
|
|
|
|
private void loadQuestOptions(final FileConfiguration config, final ConfigurationSection questsSection, final Quest quest,
|
|
final String questKey) throws QuestFormatException {
|
|
final Options opts = quest.getOptions();
|
|
if (config.contains("quests." + questKey + ".options.allow-commands")) {
|
|
opts.setAllowCommands(config.getBoolean("quests." + questKey + ".options.allow-commands"));
|
|
}
|
|
if (config.contains("quests." + questKey + ".options.allow-quitting")) {
|
|
opts.setAllowQuitting(config.getBoolean("quests." + questKey + ".options.allow-quitting"));
|
|
} else if (getConfig().contains("allow-quitting")) {
|
|
// Legacy
|
|
opts.setAllowQuitting(getConfig().getBoolean("allow-quitting"));
|
|
}
|
|
if (config.contains("quests." + questKey + ".options.use-dungeonsxl-plugin")) {
|
|
opts.setUseDungeonsXLPlugin(config.getBoolean("quests." + questKey + ".options.use-dungeonsxl-plugin"));
|
|
}
|
|
if (config.contains("quests." + questKey + ".options.use-parties-plugin")) {
|
|
opts.setUsePartiesPlugin(config.getBoolean("quests." + questKey + ".options.use-parties-plugin"));
|
|
}
|
|
if (config.contains("quests." + questKey + ".options.share-progress-level")) {
|
|
opts.setShareProgressLevel(config.getInt("quests." + questKey + ".options.share-progress-level"));
|
|
}
|
|
if (config.contains("quests." + questKey + ".options.require-same-quest")) {
|
|
opts.setRequireSameQuest(config.getBoolean("quests." + questKey + ".options.require-same-quest"));
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings({ "unchecked", "unused" })
|
|
private void loadQuestStages(final Quest quest, final FileConfiguration config, final String questKey)
|
|
throws StageFormatException, ActionFormatException, ConditionFormatException {
|
|
final ConfigurationSection questStages = config.getConfigurationSection("quests." + questKey + ".stages.ordered");
|
|
if (questStages == null) {
|
|
getLogger().severe(ChatColor.RED + questKey + " must have at least one stage!");
|
|
return;
|
|
}
|
|
for (final String stage : questStages.getKeys(false)) {
|
|
int stageNum = 0;
|
|
try {
|
|
stageNum = Integer.valueOf(stage);
|
|
} catch (final NumberFormatException e) {
|
|
getLogger().severe("Stage key " + stage + "must be a number!");
|
|
continue;
|
|
}
|
|
final Stage oStage = new Stage();
|
|
List<String> breakNames = new LinkedList<String>();
|
|
List<Integer> breakAmounts = new LinkedList<Integer>();
|
|
List<Short> breakDurability = new LinkedList<Short>();
|
|
List<String> damageNames = new LinkedList<String>();
|
|
List<Integer> damageAmounts = new LinkedList<Integer>();
|
|
List<Short> damageDurability = new LinkedList<Short>();
|
|
List<String> placeNames = new LinkedList<String>();
|
|
List<Integer> placeAmounts = new LinkedList<Integer>();
|
|
List<Short> placeDurability = new LinkedList<Short>();
|
|
List<String> useNames = new LinkedList<String>();
|
|
List<Integer> useAmounts = new LinkedList<Integer>();
|
|
List<Short> useDurability = new LinkedList<Short>();
|
|
List<String> cutNames = new LinkedList<String>();
|
|
List<Integer> cutAmounts = new LinkedList<Integer>();
|
|
List<Short> cutDurability = new LinkedList<Short>();
|
|
final List<EntityType> mobsToKill = new LinkedList<EntityType>();
|
|
final List<Integer> mobNumToKill = new LinkedList<Integer>();
|
|
final List<Location> locationsToKillWithin = new LinkedList<Location>();
|
|
final List<Integer> radiiToKillWithin = new LinkedList<Integer>();
|
|
final List<String> areaNames = new LinkedList<String>();
|
|
List<ItemStack> itemsToCraft = new LinkedList<ItemStack>();
|
|
List<ItemStack> itemsToSmelt = new LinkedList<ItemStack>();
|
|
final List<Enchantment> enchantments = new LinkedList<Enchantment>();
|
|
final List<Material> itemsToEnchant = new LinkedList<Material>();
|
|
List<Integer> amountsToEnchant = new LinkedList<Integer>();
|
|
List<ItemStack> itemsToBrew = new LinkedList<ItemStack>();
|
|
List<ItemStack> itemsToConsume = new LinkedList<ItemStack>();
|
|
List<Integer> npcIdsToTalkTo = new LinkedList<Integer>();
|
|
List<ItemStack> itemsToDeliver= new LinkedList<ItemStack>();
|
|
List<Integer> itemDeliveryTargetIds = new LinkedList<Integer>();
|
|
final List<String> deliveryMessages = new LinkedList<String>();
|
|
List<Integer> npcIdsToKill = new LinkedList<Integer>();
|
|
List<Integer> npcAmountsToKill = new LinkedList<Integer>();
|
|
// Legacy Denizen script load
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".script-to-run")) {
|
|
if (getDependencies().getDenizenApi().containsScript(config.getString("quests." + questKey
|
|
+ ".stages.ordered." + stageNum + ".script-to-run"))) {
|
|
oStage.script = config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".script-to-run");
|
|
} else {
|
|
throw new StageFormatException("script-to-run is not a valid Denizen script", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".break-block-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".break-block-names"), String.class)) {
|
|
breakNames = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".break-block-names");
|
|
} else {
|
|
throw new StageFormatException("break-block-names is not a list of strings", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".break-block-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".break-block-amounts"), Integer.class)) {
|
|
breakAmounts = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".break-block-amounts");
|
|
} else {
|
|
throw new StageFormatException("break-block-amounts is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("break-block-amounts is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".break-block-durability")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".break-block-durability"), Integer.class)) {
|
|
breakDurability = config.getShortList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".break-block-durability");
|
|
} else {
|
|
throw new StageFormatException("break-block-durability is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("break-block-durability is missing", quest, stageNum);
|
|
}
|
|
}
|
|
int breakIndex = 0;
|
|
for (final String s : breakNames) {
|
|
ItemStack is;
|
|
if (breakDurability.get(breakIndex) != -1) {
|
|
is = ItemUtil.processItemStack(s, breakAmounts.get(breakIndex), breakDurability.get(breakIndex));
|
|
} else {
|
|
// Legacy
|
|
is = ItemUtil.processItemStack(s, breakAmounts.get(breakIndex), (short) 0);
|
|
}
|
|
if (Material.matchMaterial(s) != null) {
|
|
oStage.blocksToBreak.add(is);
|
|
} else {
|
|
throw new StageFormatException("break-block-names has invalid item name " + s, quest, stageNum);
|
|
}
|
|
breakIndex++;
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".damage-block-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".damage-block-names"), String.class)) {
|
|
damageNames = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".damage-block-names");
|
|
} else {
|
|
throw new StageFormatException("damage-block-names is not a list of strings", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".damage-block-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".damage-block-amounts"), Integer.class)) {
|
|
damageAmounts = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".damage-block-amounts");
|
|
} else {
|
|
throw new StageFormatException("damage-block-amounts is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("damage-block-amounts is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".damage-block-durability")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".damage-block-durability"), Integer.class)) {
|
|
damageDurability = config.getShortList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".damage-block-durability");
|
|
} else {
|
|
throw new StageFormatException("damage-block-durability is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("damage-block-durability is missing", quest, stageNum);
|
|
}
|
|
}
|
|
int damageIndex = 0;
|
|
for (final String s : damageNames) {
|
|
ItemStack is;
|
|
if (damageDurability.get(damageIndex) != -1) {
|
|
is = ItemUtil.processItemStack(s, damageAmounts.get(damageIndex),
|
|
damageDurability.get(damageIndex));
|
|
} else {
|
|
// Legacy
|
|
is = ItemUtil.processItemStack(s, damageAmounts.get(damageIndex), (short) 0);
|
|
}
|
|
if (Material.matchMaterial(s) != null) {
|
|
oStage.blocksToDamage.add(is);
|
|
} else {
|
|
throw new StageFormatException("damage-block-names has invalid item name " + s, quest, stageNum);
|
|
}
|
|
damageIndex++;
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".place-block-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".place-block-names"), String.class)) {
|
|
placeNames = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".place-block-names");
|
|
} else {
|
|
throw new StageFormatException("place-block-names is not a list of strings", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".place-block-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".place-block-amounts"), Integer.class)) {
|
|
placeAmounts = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".place-block-amounts");
|
|
} else {
|
|
throw new StageFormatException("place-block-amounts is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("place-block-amounts is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".place-block-durability")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".place-block-durability"), Integer.class)) {
|
|
placeDurability = config.getShortList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".place-block-durability");
|
|
} else {
|
|
throw new StageFormatException("place-block-durability is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("place-block-durability is missing", quest, stageNum);
|
|
}
|
|
}
|
|
int placeIndex = 0;
|
|
for (final String s : placeNames) {
|
|
ItemStack is;
|
|
if (placeDurability.get(placeIndex) != -1) {
|
|
is = ItemUtil.processItemStack(s, placeAmounts.get(placeIndex), placeDurability.get(placeIndex));
|
|
} else {
|
|
// Legacy
|
|
is = ItemUtil.processItemStack(s, placeAmounts.get(placeIndex), (short) 0);
|
|
}
|
|
if (Material.matchMaterial(s) != null) {
|
|
oStage.blocksToPlace.add(is);
|
|
} else {
|
|
throw new StageFormatException("place-block-names has invalid item name " + s, quest, stageNum);
|
|
}
|
|
placeIndex++;
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".use-block-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".use-block-names"), String.class)) {
|
|
useNames = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".use-block-names");
|
|
} else {
|
|
throw new StageFormatException("use-block-names is not a list of strings", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".use-block-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".use-block-amounts"),Integer.class)) {
|
|
useAmounts = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".use-block-amounts");
|
|
} else {
|
|
throw new StageFormatException("use-block-amounts is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("use-block-amounts is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".use-block-durability")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".use-block-durability"), Integer.class)) {
|
|
useDurability = config.getShortList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".use-block-durability");
|
|
} else {
|
|
throw new StageFormatException("use-block-durability is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("use-block-durability is missing", quest, stageNum);
|
|
}
|
|
}
|
|
int useIndex = 0;
|
|
for (final String s : useNames) {
|
|
ItemStack is;
|
|
if (useDurability.get(useIndex) != -1) {
|
|
is = ItemUtil.processItemStack(s, useAmounts.get(useIndex), useDurability.get(useIndex));
|
|
} else {
|
|
// Legacy
|
|
is = ItemUtil.processItemStack(s, useAmounts.get(useIndex), (short) 0);
|
|
}
|
|
if (Material.matchMaterial(s) != null) {
|
|
oStage.blocksToUse.add(is);
|
|
} else {
|
|
throw new StageFormatException("use-block-names has invalid item name " + s, quest, stageNum);
|
|
}
|
|
useIndex++;
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".cut-block-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".cut-block-names"), String.class)) {
|
|
cutNames = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".cut-block-names");
|
|
} else {
|
|
throw new StageFormatException("cut-block-names is not a list of strings", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".cut-block-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".cut-block-amounts"), Integer.class)) {
|
|
cutAmounts = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".cut-block-amounts");
|
|
} else {
|
|
throw new StageFormatException("cut-block-amounts is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("cut-block-amounts is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".cut-block-durability")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".cut-block-durability"), Integer.class)) {
|
|
cutDurability = config.getShortList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".cut-block-durability");
|
|
} else {
|
|
throw new StageFormatException("cut-block-durability is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("cut-block-durability is missing", quest, stageNum);
|
|
}
|
|
}
|
|
int cutIndex = 0;
|
|
for (final String s : cutNames) {
|
|
ItemStack is;
|
|
if (cutDurability.get(cutIndex) != -1) {
|
|
is = ItemUtil.processItemStack(s, cutAmounts.get(cutIndex), cutDurability.get(cutIndex));
|
|
} else {
|
|
// Legacy
|
|
is = ItemUtil.processItemStack(s, cutAmounts.get(cutIndex), (short) 0);
|
|
}
|
|
if (Material.matchMaterial(s) != null) {
|
|
oStage.blocksToCut.add(is);
|
|
} else {
|
|
throw new StageFormatException("cut-block-names has invalid item name " + s, quest, stageNum);
|
|
}
|
|
cutIndex++;
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".items-to-craft")) {
|
|
itemsToCraft = (List<ItemStack>) config.get("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".items-to-craft");
|
|
if (ConfigUtil.checkList(itemsToCraft, ItemStack.class)) {
|
|
for (final ItemStack stack : itemsToCraft) {
|
|
if (stack != null) {
|
|
oStage.itemsToCraft.add(stack);
|
|
} else {
|
|
throw new StageFormatException("items-to-craft has invalid formatting "
|
|
+ stack, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy
|
|
final List<String> items = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".items-to-craft");
|
|
if (ConfigUtil.checkList(items, String.class)) {
|
|
for (final String item : items) {
|
|
final ItemStack is = ItemUtil.readItemStack("" + item);
|
|
if (is != null) {
|
|
oStage.itemsToCraft.add(is);
|
|
} else {
|
|
throw new StageFormatException("Legacy items-to-craft has invalid formatting "
|
|
+ item, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("items-to-craft is not formatted properly", quest, stageNum);
|
|
}
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".items-to-smelt")) {
|
|
itemsToSmelt = (List<ItemStack>) config.get("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".items-to-smelt");
|
|
if (ConfigUtil.checkList(itemsToSmelt, ItemStack.class)) {
|
|
for (final ItemStack stack : itemsToSmelt) {
|
|
if (stack != null) {
|
|
oStage.itemsToSmelt.add(stack);
|
|
} else {
|
|
throw new StageFormatException("items-to-smelt has invalid formatting "
|
|
+ stack, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy
|
|
final List<String> items = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".items-to-smelt");
|
|
if (ConfigUtil.checkList(items, String.class)) {
|
|
for (final String item : items) {
|
|
final ItemStack is = ItemUtil.readItemStack("" + item);
|
|
if (is != null) {
|
|
oStage.itemsToSmelt.add(is);
|
|
} else {
|
|
throw new StageFormatException("Legacy items-to-smelt has invalid formatting "
|
|
+ item, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("items-to-smelt is not formatted properly", quest, stageNum);
|
|
}
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".enchantments")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".enchantments"), String.class)) {
|
|
for (final String enchant : config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".enchantments")) {
|
|
final Enchantment e = ItemUtil.getEnchantmentFromProperName(enchant);
|
|
if (e != null) {
|
|
enchantments.add(e);
|
|
} else {
|
|
throw new StageFormatException("enchantments has invalid enchantment "
|
|
+ enchant, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("enchantments is not a list of enchantment names", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".enchantment-item-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".enchantment-item-names"), String.class)) {
|
|
for (final String item : config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".enchantment-item-names")) {
|
|
if (Material.matchMaterial(item) != null) {
|
|
itemsToEnchant.add(Material.matchMaterial(item));
|
|
} else {
|
|
throw new StageFormatException("enchantment-item-names has invalid item name "
|
|
+ item, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("enchantment-item-names has invalid item name", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("enchantment-item-names is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".enchantment-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".enchantment-amounts"), Integer.class)) {
|
|
amountsToEnchant = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".enchantment-amounts");
|
|
} else {
|
|
throw new StageFormatException("enchantment-amounts is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("enchantment-amounts is missing", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".items-to-brew")) {
|
|
itemsToBrew = (List<ItemStack>) config.get("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".items-to-brew");
|
|
if (ConfigUtil.checkList(itemsToBrew, ItemStack.class)) {
|
|
for (final ItemStack stack : itemsToBrew) {
|
|
if (stack != null) {
|
|
oStage.itemsToBrew.add(stack);
|
|
} else {
|
|
throw new StageFormatException("items-to-brew has invalid formatting "
|
|
+ stack, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy
|
|
final List<String> items = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".items-to-brew");
|
|
if (ConfigUtil.checkList(items, String.class)) {
|
|
for (final String item : items) {
|
|
final ItemStack is = ItemUtil.readItemStack("" + item);
|
|
if (is != null) {
|
|
oStage.itemsToBrew.add(is);
|
|
} else {
|
|
throw new StageFormatException("Legacy items-to-brew has invalid formatting "
|
|
+ item, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("items-to-brew has invalid formatting", quest, stageNum);
|
|
}
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".items-to-consume")) {
|
|
itemsToConsume = (List<ItemStack>) config.get("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".items-to-consume");
|
|
if (ConfigUtil.checkList(itemsToConsume, ItemStack.class)) {
|
|
for (final ItemStack stack : itemsToConsume) {
|
|
if (stack != null) {
|
|
oStage.itemsToConsume.add(stack);
|
|
} else {
|
|
throw new StageFormatException("items-to-consume has invalid formatting "
|
|
+ stack, quest, stageNum);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".cows-to-milk")) {
|
|
if (config.getInt("quests." + questKey + ".stages.ordered." + stageNum + ".cows-to-milk", -999)
|
|
!= -999) {
|
|
oStage.cowsToMilk = config.getInt("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".cows-to-milk");
|
|
} else {
|
|
throw new StageFormatException("cows-to-milk is not a number", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".fish-to-catch")) {
|
|
if (config.getInt("quests." + questKey + ".stages.ordered." + stageNum + ".fish-to-catch", -999)
|
|
!= -999) {
|
|
oStage.fishToCatch = config.getInt("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".fish-to-catch");
|
|
} else {
|
|
throw new StageFormatException("fish-to-catch is not a number", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".players-to-kill")) {
|
|
if (config.getInt("quests." + questKey + ".stages.ordered." + stageNum + ".players-to-kill", -999)
|
|
!= -999) {
|
|
oStage.playersToKill = config.getInt("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".players-to-kill");
|
|
} else {
|
|
throw new StageFormatException("players-to-kill is not a number", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".npc-ids-to-talk-to")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".npc-ids-to-talk-to"), Integer.class)) {
|
|
npcIdsToTalkTo = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".npc-ids-to-talk-to");
|
|
for (final int i : npcIdsToTalkTo) {
|
|
if (getDependencies().getCitizens() != null) {
|
|
if (CitizensAPI.getNPCRegistry().getById(i) != null) {
|
|
questNpcs.add(CitizensAPI.getNPCRegistry().getById(i));
|
|
} else {
|
|
throw new StageFormatException("npc-ids-to-talk-to has invalid NPC ID of " + i, quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("Citizens not found for npc-ids-to-talk-to", quest,
|
|
stageNum);
|
|
}
|
|
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-ids-to-talk-to is not a list of numbers", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".items-to-deliver")) {
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".npc-delivery-ids")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".npc-delivery-ids"), Integer.class)) {
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".delivery-messages")) {
|
|
itemsToDeliver = (List<ItemStack>) config.get("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".items-to-deliver");
|
|
itemDeliveryTargetIds = config.getIntegerList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".npc-delivery-ids");
|
|
deliveryMessages.addAll(config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".delivery-messages"));
|
|
int index = 0;
|
|
if (ConfigUtil.checkList(itemsToDeliver, ItemStack.class)) {
|
|
for (final ItemStack stack : itemsToDeliver) {
|
|
if (stack != null) {
|
|
final int npcId = itemDeliveryTargetIds.get(index);
|
|
index++;
|
|
if (stack != null) {
|
|
if (getDependencies().getCitizens() != null) {
|
|
final NPC npc = CitizensAPI.getNPCRegistry().getById(npcId);
|
|
if (npc != null) {
|
|
oStage.itemsToDeliver.add(stack);
|
|
oStage.itemDeliveryTargets.add(npcId);
|
|
oStage.deliverMessages.addAll(deliveryMessages);
|
|
} else {
|
|
throw new StageFormatException(
|
|
"Citizens not found for npc-delivery-ids", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-delivery-ids has invalid NPC ID of "
|
|
+ npcId, quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("items-to-deliver has invalid formatting "
|
|
+ stack, quest, stageNum);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
final List<String> items = config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".items-to-deliver");
|
|
if (ConfigUtil.checkList(items, String.class)) {
|
|
// Legacy
|
|
for (final String item : items) {
|
|
final ItemStack is = ItemUtil.readItemStack("" + item);
|
|
if (index <= itemDeliveryTargetIds.size()) {
|
|
final int npcId = itemDeliveryTargetIds.get(index);
|
|
index++;
|
|
if (is != null) {
|
|
if (getDependencies().getCitizens() != null) {
|
|
final NPC npc = CitizensAPI.getNPCRegistry().getById(npcId);
|
|
if (npc != null) {
|
|
oStage.itemsToDeliver.add(is);
|
|
oStage.itemDeliveryTargets.add(npcId);
|
|
oStage.deliverMessages.addAll(deliveryMessages);
|
|
} else {
|
|
throw new StageFormatException(
|
|
"npc-delivery-ids has invalid NPC ID of " + npcId, quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException(
|
|
"Citizens was not found installed for npc-delivery-ids", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("items-to-deliver has invalid formatting "
|
|
+ item, quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("items-to-deliver is missing target IDs"
|
|
, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("items-to-deliver has invalid formatting", quest,
|
|
stageNum);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-delivery-ids is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-delivery-id is missing", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".npc-ids-to-kill")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".npc-ids-to-kill"), Integer.class)) {
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".npc-kill-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".npc-kill-amounts"), Integer.class)) {
|
|
npcIdsToKill = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".npc-ids-to-kill");
|
|
npcAmountsToKill = config.getIntegerList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".npc-kill-amounts");
|
|
for (final int i : npcIdsToKill) {
|
|
if (CitizensAPI.getNPCRegistry().getById(i) != null) {
|
|
if (npcAmountsToKill.get(npcIdsToKill.indexOf(i)) > 0) {
|
|
oStage.citizensToKill.add(i);
|
|
oStage.citizenNumToKill.add(npcAmountsToKill.get(npcIdsToKill.indexOf(i)));
|
|
questNpcs.add(CitizensAPI.getNPCRegistry().getById(i));
|
|
} else {
|
|
throw new StageFormatException("npc-kill-amounts is not a positive number",
|
|
quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-ids-to-kill has invalid NPC ID of " + i, quest,
|
|
stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-kill-amounts is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-kill-amounts is missing", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("npc-ids-to-kill is not a list of numbers", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".mobs-to-kill")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".mobs-to-kill"), String.class)) {
|
|
final List<String> mobNames = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".mobs-to-kill");
|
|
for (final String mob : mobNames) {
|
|
final EntityType type = MiscUtil.getProperMobType(mob);
|
|
if (type != null) {
|
|
mobsToKill.add(type);
|
|
} else {
|
|
throw new StageFormatException("mobs-to-kill has invalid mob name " + mob, quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("mobs-to-kill is not a list of mob names", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".mob-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".mob-amounts"), Integer.class)) {
|
|
for (final int i : config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".mob-amounts")) {
|
|
mobNumToKill.add(i);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("mob-amounts is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("mob-amounts is missing", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".locations-to-kill")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".locations-to-kill"), String.class)) {
|
|
final List<String> locations = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".locations-to-kill");
|
|
for (final String loc : locations) {
|
|
if (ConfigUtil.getLocation(loc) != null) {
|
|
locationsToKillWithin.add(ConfigUtil.getLocation(loc));
|
|
} else {
|
|
throw new StageFormatException("locations-to-kill has invalid formatting " + loc, quest,
|
|
stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("locations-to-kill is not a list of locations", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".kill-location-radii")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".kill-location-radii"), Integer.class)) {
|
|
final List<Integer> radii = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".kill-location-radii");
|
|
for (final int i : radii) {
|
|
radiiToKillWithin.add(i);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("kill-location-radii is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("kill-location-radii is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".kill-location-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".kill-location-names"), String.class)) {
|
|
final List<String> locationNames = config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".kill-location-names");
|
|
for (final String name : locationNames) {
|
|
areaNames.add(name);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("kill-location-names is not a list of names", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("kill-location-names is missing", quest, stageNum);
|
|
}
|
|
}
|
|
oStage.mobsToKill.addAll(mobsToKill);
|
|
oStage.mobNumToKill.addAll(mobNumToKill);
|
|
oStage.locationsToKillWithin.addAll(locationsToKillWithin);
|
|
oStage.radiiToKillWithin.addAll(radiiToKillWithin);
|
|
oStage.killNames.addAll(areaNames);
|
|
final Map<Map<Enchantment, Material>, Integer> enchants = new HashMap<Map<Enchantment, Material>, Integer>();
|
|
for (final Enchantment e : enchantments) {
|
|
final Map<Enchantment, Material> map = new HashMap<Enchantment, Material>();
|
|
map.put(e, itemsToEnchant.get(enchantments.indexOf(e)));
|
|
enchants.put(map, amountsToEnchant.get(enchantments.indexOf(e)));
|
|
}
|
|
oStage.itemsToEnchant = enchants;
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".locations-to-reach")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".locations-to-reach"), String.class)) {
|
|
final List<String> locations = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".locations-to-reach");
|
|
for (final String loc : locations) {
|
|
if (ConfigUtil.getLocation(loc) != null) {
|
|
oStage.locationsToReach.add(ConfigUtil.getLocation(loc));
|
|
} else {
|
|
throw new StageFormatException("locations-to-reach has invalid formatting" + loc, quest,
|
|
stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("locations-to-reach is not a list of locations", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".reach-location-radii")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".reach-location-radii"), Integer.class)) {
|
|
final List<Integer> radii = config.getIntegerList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".reach-location-radii");
|
|
for (final int i : radii) {
|
|
oStage.radiiToReachWithin.add(i);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("reach-location-radii is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("reach-location-radii is missing", quest, stageNum);
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".reach-location-names")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".reach-location-names"), String.class)) {
|
|
final List<String> locationNames = config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".reach-location-names");
|
|
for (final String name : locationNames) {
|
|
oStage.locationNames.add(name);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("reach-location-names is not a list of names", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("reach-location-names is missing", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".mobs-to-tame")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".mobs-to-tame"), String.class)) {
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".mob-tame-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".mob-tame-amounts"), Integer.class)) {
|
|
final List<String> mobs = config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".mobs-to-tame");
|
|
final List<Integer> mobAmounts = config.getIntegerList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".mob-tame-amounts");
|
|
for (final String mob : mobs) {
|
|
if (Tameable.class.isAssignableFrom(EntityType.valueOf(mob.toUpperCase())
|
|
.getEntityClass())) {
|
|
oStage.mobsToTame.put(EntityType.valueOf(mob.toUpperCase()),
|
|
mobAmounts.get(mobs.indexOf(mob)));
|
|
} else {
|
|
throw new StageFormatException("mobs-to-tame has invalid tameable mob " + mob,
|
|
quest, stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("mob-tame-amounts is not a list of numbers", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("mob-tame-amounts is missing", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("mobs-to-tame is not a list of mob names", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".sheep-to-shear")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".sheep-to-shear"), String.class)) {
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".sheep-amounts")) {
|
|
if (ConfigUtil.checkList(config.getList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".sheep-amounts"), Integer.class)) {
|
|
final List<String> sheep = config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".sheep-to-shear");
|
|
final List<Integer> shearAmounts = config.getIntegerList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".sheep-amounts");
|
|
for (final String color : sheep) {
|
|
DyeColor dc = null;
|
|
if (color.equalsIgnoreCase("NULL")) {
|
|
dc = DyeColor.WHITE;
|
|
}
|
|
try {
|
|
if (dc == null) {
|
|
dc = DyeColor.valueOf(color.toUpperCase());
|
|
}
|
|
} catch (final IllegalArgumentException e) {
|
|
// Fail silently
|
|
}
|
|
if (dc != null) {
|
|
oStage.sheepToShear.put(dc, shearAmounts.get(sheep.indexOf(color)));
|
|
// Legacy start -->
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_BLACK"))) {
|
|
oStage.sheepToShear.put(DyeColor.BLACK, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_BLUE"))) {
|
|
oStage.sheepToShear.put(DyeColor.BLUE, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_BROWN"))) {
|
|
oStage.sheepToShear.put(DyeColor.BROWN, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_CYAN"))) {
|
|
oStage.sheepToShear.put(DyeColor.CYAN, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_GRAY"))) {
|
|
oStage.sheepToShear.put(DyeColor.GRAY, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_GREEN"))) {
|
|
oStage.sheepToShear.put(DyeColor.GREEN, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_LIGHT_BLUE"))) {
|
|
oStage.sheepToShear.put(DyeColor.LIGHT_BLUE,
|
|
shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_LIME"))) {
|
|
oStage.sheepToShear.put(DyeColor.LIME, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_MAGENTA"))) {
|
|
oStage.sheepToShear.put(DyeColor.MAGENTA, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_ORANGE"))) {
|
|
oStage.sheepToShear.put(DyeColor.ORANGE, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_PINK"))) {
|
|
oStage.sheepToShear.put(DyeColor.PINK, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_PURPLE"))) {
|
|
oStage.sheepToShear.put(DyeColor.PURPLE, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_RED"))) {
|
|
oStage.sheepToShear.put(DyeColor.RED, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_SILVER"))) {
|
|
// 1.13 changed DyeColor.SILVER -> DyeColor.LIGHT_GRAY
|
|
oStage.sheepToShear.put(DyeColor.getByColor(Color.SILVER),
|
|
shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_WHITE"))) {
|
|
oStage.sheepToShear.put(DyeColor.WHITE, shearAmounts.get(sheep.indexOf(color)));
|
|
} else if (color.equalsIgnoreCase(Lang.get("COLOR_YELLOW"))) {
|
|
oStage.sheepToShear.put(DyeColor.YELLOW, shearAmounts.get(sheep.indexOf(color)));
|
|
// <-- Legacy end
|
|
} else {
|
|
throw new StageFormatException("sheep-to-shear has invalid color " + color, quest,
|
|
stageNum);
|
|
}
|
|
}
|
|
} else {
|
|
throw new StageFormatException("sheep-amounts is not a list of numbers", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("sheep-amounts is missing", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("sheep-to-shear is not a list of colors", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".password-displays")) {
|
|
final List<String> displays = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".password-displays");
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".password-phrases")) {
|
|
final List<String> phrases = config.getStringList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".password-phrases");
|
|
if (displays.size() == phrases.size()) {
|
|
for (int passIndex = 0; passIndex < displays.size(); passIndex++) {
|
|
oStage.passwordDisplays.add(displays.get(passIndex));
|
|
final LinkedList<String> answers = new LinkedList<String>();
|
|
answers.addAll(Arrays.asList(phrases.get(passIndex).split("\\|")));
|
|
oStage.passwordPhrases.add(answers);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("password-displays and password-phrases are not the same size",
|
|
quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("password-phrases is missing", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".objective-override")) {
|
|
final Object o = config.get("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".objective-override");
|
|
if (o instanceof List) {
|
|
oStage.objectiveOverrides.addAll(config.getStringList("quests." + questKey
|
|
+ ".stages.ordered." + stageNum + ".objective-override"));
|
|
} else {
|
|
// Legacy
|
|
final String s = config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".objective-override");
|
|
oStage.objectiveOverrides.add(s);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".start-event")) {
|
|
final Action action = loadAction(config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".start-event"));
|
|
if (action != null) {
|
|
oStage.startAction = action;
|
|
} else {
|
|
throw new StageFormatException("start-event failed to load", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".finish-event")) {
|
|
final Action action = loadAction(config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".finish-event"));
|
|
if (action != null) {
|
|
oStage.finishAction = action;
|
|
} else {
|
|
throw new StageFormatException("finish-event failed to load", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".death-event")) {
|
|
final Action action = loadAction(config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".death-event"));
|
|
if (action != null) {
|
|
oStage.deathAction = action;
|
|
} else {
|
|
throw new StageFormatException("death-event failed to load", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".disconnect-event")) {
|
|
final Action action = loadAction(config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".disconnect-event"));
|
|
if (action != null) {
|
|
oStage.disconnectAction = action;
|
|
} else {
|
|
throw new StageFormatException("disconnect-event failed to load", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".chat-events")) {
|
|
if (config.isList("quests." + questKey + ".stages.ordered." + stageNum + ".chat-events")) {
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".chat-event-triggers")) {
|
|
if (config.isList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".chat-event-triggers")) {
|
|
final List<String> chatEvents = config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".chat-events");
|
|
final List<String> chatEventTriggers = config.getStringList("quests." + questKey
|
|
+ ".stages.ordered." + stageNum + ".chat-event-triggers");
|
|
boolean loadEventFailed = false;
|
|
for (int i = 0; i < chatEvents.size(); i++) {
|
|
final Action action = loadAction(chatEvents.get(i));
|
|
if (action != null) {
|
|
if (i < chatEventTriggers.size()) {
|
|
oStage.chatActions.put(chatEventTriggers.get(i), action);
|
|
} else {
|
|
throw new StageFormatException("chat-event-triggers list is too small",
|
|
quest, stageNum);
|
|
}
|
|
} else {
|
|
loadEventFailed = true;
|
|
throw new StageFormatException("chat-events failed to load " + chatEvents.get(i),
|
|
quest, stageNum);
|
|
}
|
|
}
|
|
if (loadEventFailed) {
|
|
break;
|
|
}
|
|
} else {
|
|
throw new StageFormatException("chat-event-triggers is not in list format", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("chat-event-triggers is missing", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("chat-events is not in list format", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".command-events")) {
|
|
if (config.isList("quests." + questKey + ".stages.ordered." + stageNum + ".command-events")) {
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".command-event-triggers")) {
|
|
if (config.isList("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".command-event-triggers")) {
|
|
final List<String> commandEvents = config.getStringList("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".command-events");
|
|
final List<String> commandEventTriggers = config.getStringList("quests." + questKey
|
|
+ ".stages.ordered." + stageNum + ".command-event-triggers");
|
|
boolean loadEventFailed = false;
|
|
for (int i = 0; i < commandEvents.size(); i++) {
|
|
final Action action = loadAction(commandEvents.get(i));
|
|
if (action != null) {
|
|
if (i < commandEventTriggers.size()) {
|
|
oStage.commandActions.put(commandEventTriggers.get(i), action);
|
|
} else {
|
|
throw new StageFormatException("command-event-triggers list is too small",
|
|
quest, stageNum);
|
|
}
|
|
} else {
|
|
loadEventFailed = true;
|
|
throw new StageFormatException("command-events failed to load "
|
|
+ commandEvents.get(i), quest, stageNum);
|
|
}
|
|
}
|
|
if (loadEventFailed) {
|
|
break;
|
|
}
|
|
} else {
|
|
throw new StageFormatException("command-event-triggers is not in list format", quest,
|
|
stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("command-event-triggers is missing", quest, stageNum);
|
|
}
|
|
} else {
|
|
throw new StageFormatException("command-events is not in list format", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".condition")) {
|
|
final Condition condition = loadCondition(config.getString("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".condition"));
|
|
if (condition != null) {
|
|
oStage.condition = condition;
|
|
} else {
|
|
throw new StageFormatException("condition failed to load", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".delay")) {
|
|
if (config.getLong("quests." + questKey + ".stages.ordered." + stageNum + ".delay", -999) != -999) {
|
|
oStage.delay = config.getInt("quests." + questKey + ".stages.ordered." + stageNum + ".delay")
|
|
* 1000;
|
|
} else {
|
|
throw new StageFormatException("delay is not a number", quest, stageNum);
|
|
}
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".delay-message")) {
|
|
oStage.delayMessage = config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".delay-message");
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".start-message")) {
|
|
oStage.startMessage = config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".start-message");
|
|
}
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".complete-message")) {
|
|
oStage.completeMessage = config.getString("quests." + questKey + ".stages.ordered." + stageNum
|
|
+ ".complete-message");
|
|
}
|
|
final LinkedList<Integer> ids = new LinkedList<Integer>();
|
|
if (npcIdsToTalkTo != null) {
|
|
ids.addAll(npcIdsToTalkTo);
|
|
}
|
|
oStage.citizensToInteract = ids;
|
|
quest.getStages().add(oStage);
|
|
}
|
|
}
|
|
|
|
protected Action loadAction(final String name) throws ActionFormatException {
|
|
if (name == null) {
|
|
return null;
|
|
}
|
|
final File legacy = new File(getDataFolder(), "events.yml");
|
|
final File actions = new File(getDataFolder(), "actions.yml");
|
|
final FileConfiguration data = new YamlConfiguration();
|
|
try {
|
|
if (actions.isFile()) {
|
|
data.load(actions);
|
|
} else {
|
|
data.load(legacy);
|
|
}
|
|
} catch (final IOException e) {
|
|
e.printStackTrace();
|
|
} catch (final InvalidConfigurationException e) {
|
|
e.printStackTrace();
|
|
}
|
|
final String legacyName = "events." + name;
|
|
String actionKey = "actions." + name + ".";
|
|
if (data.contains(legacyName)) {
|
|
actionKey = legacyName + ".";
|
|
}
|
|
final Action action = new Action(this);
|
|
action.setName(name);
|
|
if (data.contains(actionKey + "message")) {
|
|
action.setMessage(ConfigUtil.parseString(data.getString(actionKey + "message")));
|
|
}
|
|
if (data.contains(actionKey + "open-book")) {
|
|
action.setBook(data.getString(actionKey + "open-book"));
|
|
}
|
|
if (data.contains(actionKey + "clear-inventory")) {
|
|
if (data.isBoolean(actionKey + "clear-inventory")) {
|
|
action.setClearInv(data.getBoolean(actionKey + "clear-inventory"));
|
|
} else {
|
|
throw new ActionFormatException("clear-inventory is not a true/false value", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "fail-quest")) {
|
|
if (data.isBoolean(actionKey + "fail-quest")) {
|
|
action.setFailQuest(data.getBoolean(actionKey + "fail-quest"));
|
|
} else {
|
|
throw new ActionFormatException("fail-quest is not a true/false value", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "explosions")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "explosions"), String.class)) {
|
|
final LinkedList<Location> explosions = new LinkedList<Location>();
|
|
for (final String s : data.getStringList(actionKey + "explosions")) {
|
|
final Location loc = ConfigUtil.getLocation(s);
|
|
if (loc == null) {
|
|
throw new ActionFormatException("explosions is not in proper \"WorldName x y z\" format",
|
|
actionKey);
|
|
}
|
|
explosions.add(loc);
|
|
}
|
|
action.setExplosions(explosions);
|
|
} else {
|
|
throw new ActionFormatException("explosions is not a list of locations", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "effects")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "effects"), String.class)) {
|
|
if (data.contains(actionKey + "effect-locations")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "effect-locations"), String.class)) {
|
|
final List<String> effectList = data.getStringList(actionKey + "effects");
|
|
final List<String> effectLocs = data.getStringList(actionKey + "effect-locations");
|
|
final Map<Location, Effect> effects = new HashMap<Location, Effect>();
|
|
for (final String s : effectList) {
|
|
Effect effect = null;
|
|
try {
|
|
effect = Effect.valueOf(s.toUpperCase());
|
|
} catch (final IllegalArgumentException e) {
|
|
throw new ActionFormatException("effect-locations is not a valid effect name",
|
|
actionKey);
|
|
}
|
|
final Location l = ConfigUtil.getLocation(effectLocs.get(effectList.indexOf(s)));
|
|
if (l == null) {
|
|
throw new ActionFormatException("effect-locations is not in proper \"WorldName x y z\""
|
|
+ "format", actionKey);
|
|
}
|
|
effects.put(l, effect);
|
|
}
|
|
action.setEffects(effects);
|
|
} else {
|
|
throw new ActionFormatException("effect-locations is not a list of locations", actionKey);
|
|
}
|
|
} else {
|
|
throw new ActionFormatException("effect-locations is missing", actionKey);
|
|
}
|
|
} else {
|
|
throw new ActionFormatException("effects is not a list of effects", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "items")) {
|
|
final LinkedList<ItemStack> temp = new LinkedList<ItemStack>();
|
|
@SuppressWarnings("unchecked")
|
|
final
|
|
List<ItemStack> stackList = (List<ItemStack>) data.get(actionKey + "items");
|
|
if (ConfigUtil.checkList(stackList, ItemStack.class)) {
|
|
for (final ItemStack stack : stackList) {
|
|
if (stack != null) {
|
|
temp.add(stack);
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy
|
|
if (ConfigUtil.checkList(stackList, String.class)) {
|
|
final List<String> items = data.getStringList(actionKey + "items");
|
|
for (final String item : items) {
|
|
try {
|
|
final ItemStack stack = ItemUtil.readItemStack(item);
|
|
if (stack != null) {
|
|
temp.add(stack);
|
|
}
|
|
} catch (final Exception e) {
|
|
throw new ActionFormatException("items is not formatted properly", actionKey);
|
|
}
|
|
}
|
|
} else {
|
|
throw new ActionFormatException("items is not a list of items", actionKey);
|
|
}
|
|
}
|
|
action.setItems(temp);
|
|
}
|
|
if (data.contains(actionKey + "storm-world")) {
|
|
final World stormWorld = getServer().getWorld(data.getString(actionKey + "storm-world"));
|
|
if (stormWorld == null) {
|
|
throw new ActionFormatException("storm-world is not a valid world name", actionKey);
|
|
}
|
|
if (data.contains(actionKey + "storm-duration")) {
|
|
if (data.getInt(actionKey + "storm-duration", -999) != -999) {
|
|
action.setStormDuration(data.getInt(actionKey + "storm-duration") * 1000);
|
|
} else {
|
|
throw new ActionFormatException("storm-duration is not a number", actionKey);
|
|
}
|
|
action.setStormWorld(stormWorld);
|
|
} else {
|
|
throw new ActionFormatException("storm-duration is missing", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "thunder-world")) {
|
|
final World thunderWorld = getServer().getWorld(data.getString(actionKey + "thunder-world"));
|
|
if (thunderWorld == null) {
|
|
throw new ActionFormatException("thunder-world is not a valid world name", actionKey);
|
|
}
|
|
if (data.contains(actionKey + "thunder-duration")) {
|
|
if (data.getInt(actionKey + "thunder-duration", -999) != -999) {
|
|
action.setThunderDuration(data.getInt(actionKey + "thunder-duration"));
|
|
} else {
|
|
throw new ActionFormatException("thunder-duration is not a number", actionKey);
|
|
}
|
|
action.setThunderWorld(thunderWorld);
|
|
} else {
|
|
throw new ActionFormatException("thunder-duration is missing", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "mob-spawns")) {
|
|
final ConfigurationSection section = data.getConfigurationSection(actionKey + "mob-spawns");
|
|
final LinkedList<QuestMob> mobSpawns = new LinkedList<QuestMob>();
|
|
for (final String s : section.getKeys(false)) {
|
|
final String mobName = section.getString(s + ".name");
|
|
final Location spawnLocation = ConfigUtil.getLocation(section.getString(s + ".spawn-location"));
|
|
final EntityType type = MiscUtil.getProperMobType(section.getString(s + ".mob-type"));
|
|
final Integer mobAmount = section.getInt(s + ".spawn-amounts");
|
|
if (spawnLocation == null) {
|
|
throw new ActionFormatException("mob-spawn-locations is not in proper \"WorldName x y z\" format",
|
|
actionKey);
|
|
}
|
|
if (type == null) {
|
|
throw new ActionFormatException("mob-spawn-types is not a list of mob types", actionKey);
|
|
}
|
|
final ItemStack[] inventory = new ItemStack[5];
|
|
final Float[] dropChances = new Float[5];
|
|
inventory[0] = ItemUtil.readItemStack(section.getString(s + ".held-item"));
|
|
dropChances[0] = (float) section.getDouble(s + ".held-item-drop-chance");
|
|
inventory[1] = ItemUtil.readItemStack(section.getString(s + ".boots"));
|
|
dropChances[1] = (float) section.getDouble(s + ".boots-drop-chance");
|
|
inventory[2] = ItemUtil.readItemStack(section.getString(s + ".leggings"));
|
|
dropChances[2] = (float) section.getDouble(s + ".leggings-drop-chance");
|
|
inventory[3] = ItemUtil.readItemStack(section.getString(s + ".chest-plate"));
|
|
dropChances[3] = (float) section.getDouble(s + ".chest-plate-drop-chance");
|
|
inventory[4] = ItemUtil.readItemStack(section.getString(s + ".helmet"));
|
|
dropChances[4] = (float) section.getDouble(s + ".helmet-drop-chance");
|
|
final QuestMob questMob = new QuestMob(type, spawnLocation, mobAmount);
|
|
questMob.setInventory(inventory);
|
|
questMob.setDropChances(dropChances);
|
|
questMob.setName(mobName);
|
|
mobSpawns.add(questMob);
|
|
}
|
|
action.setMobSpawns(mobSpawns);
|
|
}
|
|
if (data.contains(actionKey + "lightning-strikes")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "lightning-strikes"), String.class)) {
|
|
final LinkedList<Location> lightningStrikes = new LinkedList<Location>();
|
|
for (final String s : data.getStringList(actionKey + "lightning-strikes")) {
|
|
final Location loc = ConfigUtil.getLocation(s);
|
|
if (loc == null) {
|
|
throw new ActionFormatException("lightning-strikes is not in proper \"WorldName x y z\" format",
|
|
actionKey);
|
|
}
|
|
lightningStrikes.add(loc);
|
|
}
|
|
action.setLightningStrikes(lightningStrikes);
|
|
} else {
|
|
throw new ActionFormatException("lightning-strikes is not a list of locations", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "commands")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "commands"), String.class)) {
|
|
final LinkedList<String> commands = new LinkedList<String>();
|
|
for (String s : data.getStringList(actionKey + "commands")) {
|
|
if (s.startsWith("/")) {
|
|
s = s.replaceFirst("/", "");
|
|
}
|
|
commands.add(s);
|
|
}
|
|
action.setCommands(commands);
|
|
} else {
|
|
throw new ActionFormatException("commands is not a list of commands", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "potion-effect-types")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "potion-effect-types"), String.class)) {
|
|
if (data.contains(actionKey + "potion-effect-durations")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "potion-effect-durations"), Integer.class)) {
|
|
if (data.contains(actionKey + "potion-effect-amplifiers")) {
|
|
if (ConfigUtil.checkList(data.getList(actionKey + "potion-effect-amplifiers"),
|
|
Integer.class)) {
|
|
final List<String> types = data.getStringList(actionKey + "potion-effect-types");
|
|
final List<Integer> durations = data.getIntegerList(actionKey + "potion-effect-durations");
|
|
final List<Integer> amplifiers = data.getIntegerList(actionKey + "potion-effect-amplifiers");
|
|
final LinkedList<PotionEffect> potionEffects = new LinkedList<PotionEffect>();
|
|
for (final String s : types) {
|
|
final PotionEffectType type = PotionEffectType.getByName(s);
|
|
if (type == null) {
|
|
throw new ActionFormatException("potion-effect-types is not a list of potion "
|
|
+ "effect types", actionKey);
|
|
}
|
|
final PotionEffect effect = new PotionEffect(type, durations
|
|
.get(types.indexOf(s)), amplifiers.get(types.indexOf(s)));
|
|
potionEffects.add(effect);
|
|
}
|
|
action.setPotionEffects(potionEffects);
|
|
} else {
|
|
throw new ActionFormatException("potion-effect-amplifiers is not a list of numbers",
|
|
actionKey);
|
|
}
|
|
} else {
|
|
throw new ActionFormatException("potion-effect-amplifiers is missing", actionKey);
|
|
}
|
|
} else {
|
|
throw new ActionFormatException("potion-effect-durations is not a list of numbers", actionKey);
|
|
}
|
|
} else {
|
|
throw new ActionFormatException("potion-effect-durations is missing", actionKey);
|
|
}
|
|
} else {
|
|
throw new ActionFormatException("potion-effect-types is not a list of potion effects", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "hunger")) {
|
|
if (data.getInt(actionKey + "hunger", -999) != -999) {
|
|
action.setHunger(data.getInt(actionKey + "hunger"));
|
|
} else {
|
|
throw new ActionFormatException("hunger is not a number", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "saturation")) {
|
|
if (data.getInt(actionKey + "saturation", -999) != -999) {
|
|
action.setSaturation(data.getInt(actionKey + "saturation"));
|
|
} else {
|
|
throw new ActionFormatException("saturation is not a number", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "health")) {
|
|
if (data.getInt(actionKey + "health", -999) != -999) {
|
|
action.setHealth(data.getInt(actionKey + "health"));
|
|
} else {
|
|
throw new ActionFormatException("health is not a number", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "teleport-location")) {
|
|
if (data.isString(actionKey + "teleport-location")) {
|
|
final Location teleport = ConfigUtil.getLocation(data.getString(actionKey + "teleport-location"));
|
|
if (teleport == null) {
|
|
throw new ActionFormatException("teleport-location is not in proper \"WorldName x y z\" format",
|
|
actionKey);
|
|
}
|
|
action.setTeleport(teleport);
|
|
} else {
|
|
throw new ActionFormatException("teleport-location is not a location", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "timer")) {
|
|
if (data.isInt(actionKey + "timer")) {
|
|
action.setTimer(data.getInt(actionKey + "timer"));
|
|
} else {
|
|
throw new ActionFormatException("timer is not a number", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "cancel-timer")) {
|
|
if (data.isBoolean(actionKey + "cancel-timer")) {
|
|
action.setCancelTimer(data.getBoolean(actionKey + "cancel-timer"));
|
|
} else {
|
|
throw new ActionFormatException("cancel-timer is not a true/false value", actionKey);
|
|
}
|
|
}
|
|
if (data.contains(actionKey + "denizen-script")) {
|
|
action.setDenizenScript(data.getString(actionKey + "denizen-script"));
|
|
}
|
|
return action;
|
|
}
|
|
|
|
protected Condition loadCondition(final String name) throws ConditionFormatException {
|
|
if (name == null) {
|
|
return null;
|
|
}
|
|
final File conditions = new File(getDataFolder(), "conditions.yml");
|
|
final FileConfiguration data = new YamlConfiguration();
|
|
try {
|
|
if (conditions.isFile()) {
|
|
data.load(conditions);
|
|
}
|
|
} catch (final IOException e) {
|
|
e.printStackTrace();
|
|
} catch (final InvalidConfigurationException e) {
|
|
e.printStackTrace();
|
|
}
|
|
final String conditionKey = "conditions." + name + ".";
|
|
final Condition condition = new Condition(this);
|
|
condition.setName(name);
|
|
if (data.contains(conditionKey + "fail-quest")) {
|
|
if (data.isBoolean(conditionKey + "fail-quest")) {
|
|
condition.setFailQuest(data.getBoolean(conditionKey + "fail-quest"));
|
|
} else {
|
|
throw new ConditionFormatException("fail-quest is not a true/false value", conditionKey);
|
|
}
|
|
}
|
|
if (data.contains(conditionKey + "hold-main-hand")) {
|
|
final LinkedList<ItemStack> temp = new LinkedList<ItemStack>();
|
|
@SuppressWarnings("unchecked")
|
|
final
|
|
List<ItemStack> stackList = (List<ItemStack>) data.get(conditionKey + "hold-main-hand");
|
|
if (ConfigUtil.checkList(stackList, ItemStack.class)) {
|
|
for (final ItemStack stack : stackList) {
|
|
if (stack != null) {
|
|
temp.add(stack);
|
|
}
|
|
}
|
|
}
|
|
condition.setItemsWhileHoldingMainHand(temp);
|
|
}
|
|
if (data.contains(conditionKey + "stay-within-world")) {
|
|
if (ConfigUtil.checkList(data.getList(conditionKey + "stay-within-world"), String.class)) {
|
|
final LinkedList<String> worlds = new LinkedList<String>();
|
|
for (final String s : data.getStringList(conditionKey + "stay-within-world")) {
|
|
final World w = getServer().getWorld(s);
|
|
if (w == null) {
|
|
throw new ConditionFormatException("stay-within-world is not a valid world",
|
|
conditionKey);
|
|
}
|
|
worlds.add(s);
|
|
}
|
|
condition.setWorldsWhileStayingWithin(worlds);
|
|
} else {
|
|
throw new ConditionFormatException("stay-within-world is not a list of worlds", conditionKey);
|
|
}
|
|
}
|
|
if (data.contains(conditionKey + "stay-within-biome")) {
|
|
if (ConfigUtil.checkList(data.getList(conditionKey + "stay-within-biome"), String.class)) {
|
|
final LinkedList<String> biomes = new LinkedList<String>();
|
|
for (final String s : data.getStringList(conditionKey + "stay-within-biome")) {
|
|
final Biome b = MiscUtil.getProperBiome(s);
|
|
if (b == null) {
|
|
throw new ConditionFormatException("stay-within-biome is not a valid biome",
|
|
conditionKey);
|
|
}
|
|
biomes.add(s);
|
|
}
|
|
condition.setBiomesWhileStayingWithin(biomes);
|
|
} else {
|
|
throw new ConditionFormatException("stay-within-biome is not a list of biomes", conditionKey);
|
|
}
|
|
}
|
|
return condition;
|
|
}
|
|
|
|
private void loadCustomSections(final Quest quest, final FileConfiguration config, final String questKey)
|
|
throws StageFormatException, QuestFormatException {
|
|
final ConfigurationSection questStages = config.getConfigurationSection("quests." + questKey + ".stages.ordered");
|
|
for (final String stageNum : questStages.getKeys(false)) {
|
|
if (quest == null) {
|
|
getLogger().warning("Unable to load custom objectives because quest for " + questKey + " was null");
|
|
return;
|
|
}
|
|
if (quest.getStage(Integer.valueOf(stageNum) - 1) == null) {
|
|
getLogger().severe("Unable to load custom objectives because stage" + (Integer.valueOf(stageNum) - 1)
|
|
+ " for " + quest.getName() + " was null");
|
|
return;
|
|
}
|
|
final Stage oStage = quest.getStage(Integer.valueOf(stageNum) - 1);
|
|
oStage.customObjectives = new LinkedList<>();
|
|
oStage.customObjectiveCounts = new LinkedList<>();
|
|
oStage.customObjectiveData = new LinkedList<>();
|
|
oStage.customObjectiveDisplays = new LinkedList<>();
|
|
if (config.contains("quests." + questKey + ".stages.ordered." + stageNum + ".custom-objectives")) {
|
|
final ConfigurationSection sec = config.getConfigurationSection("quests." + questKey + ".stages.ordered."
|
|
+ stageNum + ".custom-objectives");
|
|
for (final String path : sec.getKeys(false)) {
|
|
final String name = sec.getString(path + ".name");
|
|
final int count = sec.getInt(path + ".count");
|
|
Optional<CustomObjective> found = Optional.empty();
|
|
for (final CustomObjective cr : customObjectives) {
|
|
if (cr.getName().equalsIgnoreCase(name)) {
|
|
found = Optional.of(cr);
|
|
break;
|
|
}
|
|
}
|
|
if (!found.isPresent()) {
|
|
getLogger().warning("Custom objective \"" + name + "\" for Stage " + stageNum + " of Quest \""
|
|
+ quest.getName() + "\" could not be found!");
|
|
continue;
|
|
} else {
|
|
final ConfigurationSection sec2 = sec.getConfigurationSection(path + ".data");
|
|
oStage.customObjectives.add(found.get());
|
|
if (count <= 0) {
|
|
oStage.customObjectiveCounts.add(0);
|
|
} else {
|
|
oStage.customObjectiveCounts.add(count);
|
|
}
|
|
for (final Entry<String,Object> prompt : found.get().getData()) {
|
|
final Entry<String, Object> data = populateCustoms(sec2, prompt);
|
|
oStage.customObjectiveData.add(data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
final Rewards rews = quest.getRewards();
|
|
if (config.contains("quests." + questKey + ".rewards.custom-rewards")) {
|
|
final ConfigurationSection sec = config.getConfigurationSection("quests." + questKey + ".rewards.custom-rewards");
|
|
final Map<String, Map<String, Object>> temp = new HashMap<String, Map<String, Object>>();
|
|
for (final String path : sec.getKeys(false)) {
|
|
final String name = sec.getString(path + ".name");
|
|
Optional<CustomReward>found = Optional.empty();
|
|
for (final CustomReward cr : customRewards) {
|
|
if (cr.getName().equalsIgnoreCase(name)) {
|
|
found=Optional.of(cr);
|
|
break;
|
|
}
|
|
}
|
|
if (!found.isPresent()) {
|
|
getLogger().warning("Custom reward \"" + name + "\" for Quest \"" + quest.getName()
|
|
+ "\" could not be found!");
|
|
continue;
|
|
} else {
|
|
final ConfigurationSection sec2 = sec.getConfigurationSection(path + ".data");
|
|
final Map<String, Object> data = populateCustoms(sec2, found.get().getData());
|
|
temp.put(name, data);
|
|
}
|
|
}
|
|
rews.setCustomRewards(temp);
|
|
}
|
|
final Requirements reqs = quest.getRequirements();
|
|
if (config.contains("quests." + questKey + ".requirements.custom-requirements")) {
|
|
final ConfigurationSection sec = config.getConfigurationSection("quests." + questKey
|
|
+ ".requirements.custom-requirements");
|
|
final Map<String, Map<String, Object>> temp = new HashMap<String, Map<String, Object>>();
|
|
for (final String path : sec.getKeys(false)) {
|
|
final String name = sec.getString(path + ".name");
|
|
Optional<CustomRequirement>found=Optional.empty();
|
|
for (final CustomRequirement cr : customRequirements) {
|
|
if (cr.getName().equalsIgnoreCase(name)) {
|
|
found=Optional.of(cr);
|
|
break;
|
|
}
|
|
}
|
|
if (!found.isPresent()) {
|
|
throw new QuestFormatException(name + " custom requirement not found", questKey);
|
|
} else {
|
|
final ConfigurationSection sec2 = sec.getConfigurationSection(path + ".data");
|
|
final Map<String, Object> data = populateCustoms(sec2,found.get().getData());
|
|
temp.put(name, data);
|
|
}
|
|
}
|
|
reqs.setCustomRequirements(temp);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Permits use of fallbacks for customs maps<p>
|
|
*
|
|
* Avoid null objects in datamap by initializing the entry value with empty string if no fallback present.
|
|
*
|
|
* @param section The section of configuration to check
|
|
* @param datamap The map to process
|
|
* @return Populated map
|
|
*/
|
|
private static Map<String, Object> populateCustoms(final ConfigurationSection section, final Map<String, Object> datamap) {
|
|
final Map<String,Object> data = new HashMap<String,Object>();
|
|
if (section != null) {
|
|
for (final String key : datamap.keySet()) {
|
|
data.put(key, section.contains(key) ? section.get(key) : datamap.get(key) != null
|
|
? datamap.get(key) : new String());
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Permits use of fallbacks for customs entries<p>
|
|
*
|
|
* Avoid null objects in datamap by initializing the entry value with empty string if no fallback present.
|
|
*
|
|
* @param section The section of configuration to check
|
|
* @param datamap The entry to process
|
|
* @return Populated entry
|
|
*/
|
|
private static Entry<String, Object> populateCustoms(final ConfigurationSection section, final Entry<String, Object> datamap) {
|
|
String key = null;;
|
|
Object value = null;;
|
|
if (section != null) {
|
|
key = datamap.getKey();
|
|
value = datamap.getValue();
|
|
}
|
|
return new AbstractMap.SimpleEntry<String, Object>(key, section.contains(key) ? section.get(key) : value != null
|
|
? value : new String());
|
|
}
|
|
|
|
/**
|
|
* Load actions from file
|
|
*/
|
|
public void loadActions() {
|
|
final YamlConfiguration config = new YamlConfiguration();
|
|
final File legacyFile = new File(this.getDataFolder(), "events.yml");
|
|
final File actionsFile = new File(this.getDataFolder(), "actions.yml");
|
|
// Using isFile() because exists() and renameTo() can return false positives
|
|
if (legacyFile.isFile()) {
|
|
getLogger().log(Level.INFO, "Renaming legacy events.yml to actions.yml ...");
|
|
try {
|
|
legacyFile.renameTo(actionsFile);
|
|
if (actionsFile.isFile()) {
|
|
getLogger().log(Level.INFO, "Success! Deleting legacy events.yml ...");
|
|
legacyFile.delete();
|
|
getLogger().log(Level.INFO, "Done!");
|
|
}
|
|
} catch (final Exception e) {
|
|
getLogger().log(Level.WARNING, "Unable to rename events.yml to actions.yml");
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
if (actionsFile.length() != 0) {
|
|
try {
|
|
if (actionsFile.isFile()) {
|
|
config.load(actionsFile);
|
|
} else {
|
|
config.load(legacyFile);
|
|
}
|
|
} catch (final IOException e) {
|
|
e.printStackTrace();
|
|
} catch (final InvalidConfigurationException e) {
|
|
e.printStackTrace();
|
|
}
|
|
ConfigurationSection sec = config.getConfigurationSection("actions");
|
|
if (sec == null) {
|
|
getLogger().log(Level.INFO,
|
|
"Could not find section \"actions\" from actions.yml. Trying legacy \"events\"...");
|
|
sec = config.getConfigurationSection("events");
|
|
}
|
|
if (sec != null) {
|
|
for (final String s : sec.getKeys(false)) {
|
|
Action action = null;
|
|
try {
|
|
action = loadAction(s);
|
|
} catch (final ActionFormatException e) {
|
|
e.printStackTrace();
|
|
}
|
|
if (action != null) {
|
|
actions.add(action);
|
|
} else {
|
|
getLogger().log(Level.SEVERE, "Failed to load Action \"" + s + "\". Skipping.");
|
|
}
|
|
}
|
|
} else {
|
|
getLogger().log(Level.SEVERE, "Could not find beginning section from actions.yml. Skipping.");
|
|
}
|
|
} else {
|
|
getLogger().log(Level.WARNING, "Empty file actions.yml was not loaded.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load conditions from file
|
|
*/
|
|
public void loadConditions() {
|
|
final YamlConfiguration config = new YamlConfiguration();
|
|
final File conditionsFile = new File(this.getDataFolder(), "conditions.yml");
|
|
// Using isFile() because exists() and renameTo() can return false positives
|
|
if (conditionsFile.length() != 0) {
|
|
try {
|
|
if (conditionsFile.isFile()) {
|
|
config.load(conditionsFile);
|
|
}
|
|
} catch (final IOException e) {
|
|
e.printStackTrace();
|
|
} catch (final InvalidConfigurationException e) {
|
|
e.printStackTrace();
|
|
}
|
|
final ConfigurationSection sec = config.getConfigurationSection("conditions");
|
|
if (sec != null) {
|
|
for (final String s : sec.getKeys(false)) {
|
|
Condition condition = null;
|
|
try {
|
|
condition = loadCondition(s);
|
|
} catch (final ConditionFormatException e) {
|
|
e.printStackTrace();
|
|
}
|
|
if (condition != null) {
|
|
conditions.add(condition);
|
|
} else {
|
|
getLogger().log(Level.SEVERE, "Failed to load Condition \"" + s + "\". Skipping.");
|
|
}
|
|
}
|
|
} else {
|
|
getLogger().log(Level.SEVERE, "Could not find beginning section from conditions.yml. Skipping.");
|
|
}
|
|
} else {
|
|
getLogger().log(Level.WARNING, "Empty file conditions.yml was not loaded.");
|
|
}
|
|
}
|
|
|
|
public static SkillType getMcMMOSkill(final String s) {
|
|
return SkillType.getSkill(s);
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use InventoryUtil.removeItem(Inventory, ItemStack)
|
|
*/
|
|
@Deprecated
|
|
public static boolean removeItem(final Inventory inventory, final ItemStack is) {
|
|
final int amount = is.getAmount();
|
|
final HashMap<Integer, ? extends ItemStack> allItems = inventory.all(is.getType());
|
|
final HashMap<Integer, Integer> removeFrom = new HashMap<Integer, Integer>();
|
|
int foundAmount = 0;
|
|
for (final Map.Entry<Integer, ? extends ItemStack> item : allItems.entrySet()) {
|
|
if (ItemUtil.compareItems(is, item.getValue(), true) == 0) {
|
|
if (item.getValue().getAmount() >= amount - foundAmount) {
|
|
removeFrom.put(item.getKey(), amount - foundAmount);
|
|
foundAmount = amount;
|
|
} else {
|
|
foundAmount += item.getValue().getAmount();
|
|
removeFrom.put(item.getKey(), item.getValue().getAmount());
|
|
}
|
|
if (foundAmount >= amount) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (foundAmount == amount) {
|
|
for (final Map.Entry<Integer, Integer> toRemove : removeFrom.entrySet()) {
|
|
final ItemStack item = inventory.getItem(toRemove.getKey());
|
|
if (item.getAmount() - toRemove.getValue() <= 0) {
|
|
inventory.clear(toRemove.getKey());
|
|
} else {
|
|
item.setAmount(item.getAmount() - toRemove.getValue());
|
|
inventory.setItem(toRemove.getKey(), item);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks if player can use Quests
|
|
*
|
|
* @param uuid the entity UUID to be checked
|
|
* @return {@code true} if entity is a Player that has permission
|
|
*/
|
|
public boolean canUseQuests(final UUID uuid) {
|
|
final Player p = Bukkit.getPlayer(uuid);
|
|
if (p != null) {
|
|
for (final Permission perm : getDescription().getPermissions()) {
|
|
if (p.hasPermission(perm.getName())) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get a Quest by ID
|
|
*
|
|
* @param id ID of the quest
|
|
* @return Exact match or null if not found
|
|
* @since 3.8.6
|
|
*/
|
|
public Quest getQuestById(final String id) {
|
|
if (id == null) {
|
|
return null;
|
|
}
|
|
for (final Quest q : quests) {
|
|
if (q.getId().equals(id)) {
|
|
return q;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get a Quest by name
|
|
*
|
|
* @param name Name of the quest
|
|
* @return Closest match or null if not found
|
|
*/
|
|
public Quest getQuest(final String name) {
|
|
if (name == null) {
|
|
return null;
|
|
}
|
|
for (final Quest q : quests) {
|
|
if (q.getName().equalsIgnoreCase(ChatColor.translateAlternateColorCodes('&', name))) {
|
|
return q;
|
|
}
|
|
}
|
|
for (final Quest q : quests) {
|
|
if (q.getName().toLowerCase().startsWith(ChatColor.translateAlternateColorCodes('&', name).toLowerCase())) {
|
|
return q;
|
|
}
|
|
}
|
|
for (final Quest q : quests) {
|
|
if (q.getName().toLowerCase().contains(ChatColor.translateAlternateColorCodes('&', name).toLowerCase())) {
|
|
return q;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get an Action by name
|
|
*
|
|
* @param name Name of the action
|
|
* @return Closest match or null if not found
|
|
*/
|
|
public Action getAction(final String name) {
|
|
if (name == null) {
|
|
return null;
|
|
}
|
|
for (final Action a : actions) {
|
|
if (a.getName().equalsIgnoreCase(ChatColor.translateAlternateColorCodes('&', name))) {
|
|
return a;
|
|
}
|
|
}
|
|
for (final Action a : actions) {
|
|
if (a.getName().toLowerCase().startsWith(ChatColor.translateAlternateColorCodes('&', name).toLowerCase())) {
|
|
return a;
|
|
}
|
|
}
|
|
for (final Action a : actions) {
|
|
if (a.getName().toLowerCase().contains(ChatColor.translateAlternateColorCodes('&', name).toLowerCase())) {
|
|
return a;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get a Condition by name
|
|
*
|
|
* @param name Name of the condition
|
|
* @return Closest match or null if not found
|
|
*/
|
|
public Condition getCondition(final String name) {
|
|
if (name == null) {
|
|
return null;
|
|
}
|
|
for (final Condition c : conditions) {
|
|
if (c.getName().equalsIgnoreCase(ChatColor.translateAlternateColorCodes('&', name))) {
|
|
return c;
|
|
}
|
|
}
|
|
for (final Condition c : conditions) {
|
|
if (c.getName().toLowerCase().startsWith(ChatColor.translateAlternateColorCodes('&', name).toLowerCase())) {
|
|
return c;
|
|
}
|
|
}
|
|
for (final Condition c : conditions) {
|
|
if (c.getName().toLowerCase().contains(ChatColor.translateAlternateColorCodes('&', name).toLowerCase())) {
|
|
return c;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Checks whether a NPC has a quest that the player may accept
|
|
*
|
|
* @param npc The giver NPC to check
|
|
* @param quester The player to check
|
|
* @return true if at least one available quest has not yet been completed
|
|
*/
|
|
public boolean hasQuest(final NPC npc, final Quester quester) {
|
|
for (final Quest q : quests) {
|
|
if (q.npcStart != null && quester.completedQuests.contains(q.getName()) == false) {
|
|
if (q.npcStart.getId() == npc.getId()) {
|
|
final boolean ignoreLockedQuests = settings.canIgnoreLockedQuests();
|
|
if (ignoreLockedQuests == false || ignoreLockedQuests == true
|
|
&& q.testRequirements(quester) == true) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Unused internally, left for external use
|
|
/**
|
|
* Checks whether a NPC has a quest that the player has already completed
|
|
*
|
|
* @param npc The giver NPC to check
|
|
* @param quester The player to check
|
|
* @return true if at least one available quest has been completed
|
|
*/
|
|
public boolean hasCompletedQuest(final NPC npc, final Quester quester) {
|
|
for (final Quest q : quests) {
|
|
if (q.npcStart != null && quester.completedQuests.contains(q.getName()) == true) {
|
|
if (q.npcStart.getId() == npc.getId()) {
|
|
final boolean ignoreLockedQuests = settings.canIgnoreLockedQuests();
|
|
if (ignoreLockedQuests == false || ignoreLockedQuests == true
|
|
&& q.testRequirements(quester) == true) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks whether a NPC has a repeatable quest that the player has already completed
|
|
*
|
|
* @param npc The giver NPC to check
|
|
* @param quester The player to check
|
|
* @return true if at least one available, redoable quest has been completed
|
|
*/
|
|
public boolean hasCompletedRedoableQuest(final NPC npc, final Quester quester) {
|
|
for (final Quest q : quests) {
|
|
if (q.npcStart != null && quester.completedQuests.contains(q.getName()) == true
|
|
&& q.getPlanner().getCooldown() > -1) {
|
|
if (q.npcStart.getId() == npc.getId()) {
|
|
final boolean ignoreLockedQuests = settings.canIgnoreLockedQuests();
|
|
if (ignoreLockedQuests == false || ignoreLockedQuests == true
|
|
&& q.testRequirements(quester) == true) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|