package net.aufdemrand.denizen.scripts.requirements;
import net.aufdemrand.denizen.Denizen;
import net.aufdemrand.denizen.exceptions.RequirementCheckException;
import net.aufdemrand.denizen.objects.aH;
import net.aufdemrand.denizen.objects.dScript;
import net.aufdemrand.denizen.tags.BukkitTagContext;
import net.aufdemrand.denizen.utilities.debugging.dB;
import org.bukkit.ChatColor;
import java.util.List;
import net.aufdemrand.denizen.tags.TagManager;
/**
* This class implements requirement checking for scripts.
*
* @author aufdemrand
*/
public class RequirementChecker {
private Denizen plugin;
public RequirementChecker(Denizen denizen) {
plugin = denizen;
}
/**
* Checks a RequirementsContext with Requirements from the RequirementsRegistry.
*
* @param context the context to check against
* @return true if the list meets the requirements and context set
*
*/
public boolean check(RequirementsContext context) {
//
// Requirement node "NONE"? No requirements in the LIST? No need to
// continue, return true.
//
if (context.mode.getMode() == RequirementsMode.Mode.NONE || context.list.isEmpty())
return true;
//
// Actual requirements that need checking, alert the debugger
//
dB.echoDebug(context.getScriptContainer(), ChatColor.YELLOW + "CHECK! Now checking '" + context.container.getName() + "'");
dB.echoDebug(context.getScriptContainer(), "Requirement mode: '" + context.mode.getMode().toString() + "'");
// Set up checks for requirement mode 'FIRST AND ANY #'
boolean firstReqMet = false;
boolean firstReqChecked = false;
// Counter for keeping track of met requirements
int numberMet = 0;
// Check all requirements
for (String reqEntry : context.list) {
boolean negativeRequirement = false;
//
// Check if this is a Negative Requirement. Negative requirements start
// with a... negative sign :)
//
if (reqEntry.startsWith("-")) {
negativeRequirement = true;
reqEntry = reqEntry.substring(1);
}
//
// Replace tags and build arguments
//
List<String> argumentList = TagManager.fillArguments(aH.buildArgs(reqEntry),
new BukkitTagContext(context.player, context.npc, false, null, dB.shouldDebug(context.getScriptContainer()), new dScript(context.getScriptContainer())));
String reqString = argumentList.get(0).toUpperCase();
//
// Evaluate the requirement
//
// <--[requirement]
// @Name ValueOf
// @Syntax valueof [<tag>]
// @Required 1
// @Stable stable
// @Short Checks if the tag is true.
//
// @Description
// Checks if a specified tag or value returns 'true'.
//
// @Usage
// Check if a simple tag is true.
// - valueof <player.is_player>
//
// @Usage
// Check a comparable (See <@link language comparable> for more information.)
// - valueof <player.health.is[LESS].than[10]>
// -->
if (reqString.equalsIgnoreCase("valueof")) {
String arg = argumentList.get(1);
if (arg.equalsIgnoreCase("true")) {
if (!negativeRequirement) {
dB.echoApproval("Checking 'VALUEOF " + arg + "... requirement met!");
numberMet++;
} else
dB.echoApproval("Checking '-VALUEOF " + arg + "...requirement not met!");
} else {
if (!negativeRequirement)
dB.echoApproval("Checking 'VALUEOF " + arg + "...requirement not met!");
else {
dB.echoApproval("Checking '-VALUEOF " + arg + "...requirement met!");// Not met!
numberMet++;
}
}
} else
// Check requirement with RequirementRegistry
if (plugin.getRequirementRegistry().list().containsKey(reqString)) {
AbstractRequirement requirement = plugin.getRequirementRegistry().get(reqString);
// Remove command name from arguments
argumentList.remove(0);
try {
// Check if # of required args are met
int numArguments = argumentList.isEmpty() ? 0 : argumentList.size();
int neededArguments = requirement.requirementOptions.REQUIRED_ARGS;
if ((numArguments == 0 && neededArguments > 0) ||
numArguments < neededArguments) {
throw new RequirementCheckException("Not enough arguments (" + numArguments + " / " + neededArguments + ")");
}
// Check the Requirement
if (requirement.check(context, argumentList) != negativeRequirement) {
// Check first requirement for mode 'FIRST AND ANY #'
if (!firstReqChecked) {
firstReqMet = true;
firstReqChecked = true;
}
numberMet++;
dB.echoApproval("Checked '" + requirement.getName() + "'" + " ...requirement met!");
} else {
if (!firstReqChecked) {
firstReqMet = false;
firstReqChecked = true;
}
dB.echoApproval("Checked '" + requirement.getName() + "'" + " ...requirement not met!");
}
} catch (Throwable e) {
if (e instanceof RequirementCheckException) {
String msg = e.getMessage().isEmpty() || e == null ? "No Error message defined!" : e.getMessage();
dB.echoError("Woah! Invalid arguments were specified: " + msg);
dB.echoError("Usage: " + requirement.getUsageHint());
} else {
dB.echoError("Woah! An exception has been called " + (requirement != null ? "for Requirement '" + requirement.getName() + "'" : "") + "!");
dB.echoError(e);
}
}
}
// If the requirement is not registered with the Requirement Registry
else {
dB.echoError("Requirement '" + reqEntry.split(" ")[0] + "' not found! Check that the requirement is installed!");
}
}
// Check numberMet with mode-type
// ALL mode
if (context.mode.getMode() == RequirementsMode.Mode.ALL && numberMet == context.list.size()) return true;
// ANY # mode
else if (context.mode.getMode() == RequirementsMode.Mode.ANY_NUM) {
return (numberMet >= context.mode.modeInt);
}
// FIRST AND ANY # mode
else if (context.mode.getMode() == RequirementsMode.Mode.FIRST_AND_ANY_NUM) {
return firstReqMet && (numberMet <= context.mode.modeInt);
}
// Nothing met, return FALSE
return false;
}
}