diff --git a/src/main/java/net/aufdemrand/denizen/objects/Adjustable.java b/src/main/java/net/aufdemrand/denizen/objects/Adjustable.java deleted file mode 100644 index 3d426e1254..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/Adjustable.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.aufdemrand.denizen.objects; - -public interface Adjustable { - - /** - * Sets a specific attribute using this object to modify the necessary data. - * - * @param mechanism the mechanism to gather change information from - */ - public void adjust(Mechanism mechanism); - - /** - * Applies a property, passing it to 'adjust' or throwing an error, depending on whether - * the mechanism may be used as a property. - * - * @param mechanism the mechanism to gather change information from - */ - public void applyProperty(Mechanism mechanism); -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/Duration.java b/src/main/java/net/aufdemrand/denizen/objects/Duration.java deleted file mode 100644 index 80331b95b6..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/Duration.java +++ /dev/null @@ -1,617 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import net.aufdemrand.denizen.objects.properties.Property; -import net.aufdemrand.denizen.objects.properties.PropertyParser; -import net.aufdemrand.denizen.tags.Attribute; -import net.aufdemrand.denizen.utilities.debugging.dB; - -import net.aufdemrand.denizencore.utilities.CoreUtilities; -import org.bukkit.ChatColor; - -import com.google.common.primitives.Ints; - - -/** - * Durations are a convenient way to get a 'unit of time' within Denizen. - * - * @version 1.0 - * @author Jeremy Schroeder - * - */ -public class Duration implements dObject { - - // <--[language] - // @name Duration - // @group Object System - // @description - // Durations are a unified and convenient way to get a 'unit of time' throughout Denizen. - // Many commands and features that require a duration can be satisfied by specifying a number - // and unit of time, especially command arguments that are prefixed 'duration:', etc. The d@ - // object fetcher notation can also be used, and is encouraged. The unit of time can be specified - // by using one of the following: T=ticks, M=minutes, S=seconds, H=hours, D=days, W = Weeks. - // Not using a unit will imply seconds. Examples: d@10s, d@50m, d@1d, d@20. - // - // Specifying a range of duration will result in a randomly selected duration that is - // in between the range specified. The smaller value should be first. Examples: - // d@10s-25s, d@1m-2m. - // - // See 'd@duration' tags for an explanation of duration attributes. - // --> - - // <--[language] - // @name Tick - // @description - // A 'tick' is usually referred to as 1/20th of a second, the speed at which CraftBukkit updates - // its various server events. - // --> - - - ///////////////////// - // STATIC METHODS AND FIELDS - ///////////////// - - // Use regex pattern matching to easily determine if a string - // value is a valid Duration. - final static Pattern match = - Pattern.compile("(?:d@)?(\\d+.\\d+|.\\d+|\\d+)(t|m|s|h|d|w)?" + - // Optional 'high-range' for random durations. - "(?:(?:-\\d+.\\d+|.\\d+|\\d+)(?:t|m|s|h|d|w)?)?", - Pattern.CASE_INSENSITIVE); - - - // Define a 'ZERO' Duration - final public static Duration ZERO = new Duration(0); - - - ///////////////////// - // OBJECT FETCHER - ///////////////// - - // <--[language] - // @name d@ - // @group Object Fetcher System - // @description - // d@ refers to the 'object identifier' of a 'Duration'. The 'd@' is notation for Denizen's Object - // Fetcher. Durations must be a positive number or range of numbers followed optionally by - // a unit of time, and prefixed by d@. Examples: d@3s, d@1d, d@10s-20s. - // - // See also 'Duration' - // --> - - /** - * Gets a Duration Object from a dScript argument. Durations must be a positive - * number. Can specify the unit of time by using one of the following: T=ticks, M=minutes, - * S=seconds, H=hours, D=days. Not using a unit will imply seconds. Examples: 10s, 50m, 1d, 50. - * - * @param string the Argument value. - * @return a Duration, or null if incorrectly formatted. - */ - @Fetchable("d") - public static Duration valueOf(String string) { - if (string == null) return null; - - string = string.replace("d@", ""); - - // Pick a duration between a high and low number if there is a '-' present. - String[] split = string.split("-", 2); - if (split.length == 2 - && Duration.matches(split[0]) - && Duration.matches(split[1])) { - Duration low = Duration.valueOf(split[0]); - Duration high = Duration.valueOf(split[1]); - - // Make sure 'low' and 'high' returned valid Durations, - // and that 'low' is less time than 'high'. - if (low != null && high != null - && low.getSecondsAsInt() < high.getSecondsAsInt()) { - int seconds = CoreUtilities.getRandom() - .nextInt((high.getSecondsAsInt() - low.getSecondsAsInt() + 1)) - + low.getSecondsAsInt(); - // dB.log("Getting random duration between " + low.identify() - // + " and " + high.identify() + "... " + seconds + "s"); - - return new Duration(seconds); - - } else return null; - } - - // Standard Duration. Check the type and create new Duration object accordingly. - Matcher m = match.matcher(string); - if (m.matches()) { - if (m.group().toLowerCase().endsWith("t")) - // Matches TICKS, so 1 tick = .05 seconds - return new Duration(Double.valueOf(m.group(1)) * 0.05); - - else if (m.group().toLowerCase().endsWith("d")) - // Matches DAYS, so 1 day = 86400 seconds - return new Duration(Double.valueOf(m.group(1)) * 86400); - - else if (m.group().toLowerCase().endsWith("w")) - // Matches WEEKS, so 1 week = 604800 seconds - return new Duration(Double.valueOf(m.group(1)) * 604800); - - else if (m.group().toLowerCase().endsWith("m")) - // Matches MINUTES, so 1 minute = 60 seconds - return new Duration(Double.valueOf(m.group(1)) * 60); - - else if (m.group().toLowerCase().endsWith("h")) - // Matches HOURS, so 1 hour = 3600 seconds - return new Duration(Double.valueOf(m.group(1)) * 3600); - - else // seconds - return new Duration(Double.valueOf(m.group(1))); - } - - return null; - } - - - /** - * Checks to see if the string is a valid Duration. - * - * @param string the String to match. - * @return true if valid. - */ - public static boolean matches(String string) { - Matcher m = match.matcher(string); - return m.matches(); - } - - - ///////////////////// - // CONSTRUCTORS - ///////////////// - - /** - * Creates a duration object when given number of seconds. - * - * @param seconds the number of seconds. - */ - public Duration(double seconds) { - this.seconds = seconds; - if (this.seconds < 0) this.seconds = 0; - } - - /** - * Creates a duration object when given number of seconds. - * - * @param seconds the number of seconds. - */ - public Duration(int seconds) { - this.seconds = seconds; - if (this.seconds < 0) this.seconds = 0; - } - - /** - * Creates a duration object when given number of Bukkit ticks. - * - * @param ticks the number of ticks. - */ - public Duration (long ticks) { - this.seconds = ticks / 20; - if (this.seconds < 0) this.seconds = 0; - } - - - ///////////////////// - // INSTANCE FIELDS/METHODS - ///////////////// - - - // The amount of seconds in the duration. - private double seconds; - - - // Duration's default dObject prefix. - private String prefix = "Duration"; - - - /** - * Gets the number of ticks of this duration. There are 20 ticks - * per second. - * - * @return the number of ticks. - */ - public long getTicks() { - return (long) (seconds * 20); - } - - - /** - * Gets the number of ticks of this duration as an integer. There are - * 20 per second. - * - * @return the number of ticks. - */ - public int getTicksAsInt() { - return Ints.checkedCast((long) (seconds * 20)); - } - - - /** - * Gets the number of milliseconds in this duration. - * - * @return the number of milliseconds. - */ - public long getMillis() { - Double millis = seconds * 1000; - return millis.longValue(); - } - - - /** - * Gets the number of seconds of this duration. - * - * @return number of seconds - */ - public double getSeconds() { - return seconds; - } - - - /** - * Gets the number of seconds as an integer value of the duration. - * - * @return number of seconds rounded to the nearest second - */ - public int getSecondsAsInt() { - // Durations that are a fraction of a second - // will return as 1 when using this method. - if (seconds < 1 && seconds > 0) return 1; - return round(seconds); - } - - private int round(double d){ - double dAbs = Math.abs(d); - int i = (int) dAbs; - double result = dAbs - i; - if(result<0.5){ - return d<0 ? -i : i; - }else{ - return d<0 ? -(i+1) : i+1; - } - } - - - ///////////////////// - // dObject Methods - ///////////////// - - @Override - public String getPrefix() { - return prefix; - } - - @Override - public String debug() { - return ChatColor.DARK_GRAY + prefix + "='" - + ChatColor.YELLOW + identify() - + ChatColor.DARK_GRAY + "' "; - } - - @Override - public boolean isUnique() { - // Durations are not unique, cannot be saved or persisted. - return false; - } - - @Override - public String getObjectType() { - return "duration"; - } - - /** - * Return the value of this Duration. This will also return a - * valid String that can be re-interpreted with Duration.valueOf() - * thus acting as a form of 'serialization/deserialization'. - * - * @return a valid String-form Duration. - */ - @Override - public String identify() { - return "d@" + getTicks() + "t"; - } - - @Override - public String identifySimple() { - return identify(); - } - - /** - * Acts just like identify(). - * - * @return a valid String-form Duration. - */ - @Override - public String toString() { - return identify(); - } - - @Override - public dObject setPrefix(String prefix) { - this.prefix = prefix; - return this; - } - - - @Override - public String getAttribute(Attribute attribute) { - - if (attribute == null) return null; - - - ///////////////////// - // CONVERSION ATTRIBUTES - ///////////////// - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @description - // returns the number of years in the Duration. - // --> - if (attribute.startsWith("in_years") || attribute.startsWith("years")) - return new Element(seconds / (86400 * 365)) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @description - // returns the number of years in the Duration. - // --> - if (attribute.startsWith("in_weeks") || attribute.startsWith("weeks")) - return new Element(seconds / 604800) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @description - // returns the number of days in the Duration. - // --> - if (attribute.startsWith("in_days") || attribute.startsWith("days")) - return new Element(seconds / 86400) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @description - // returns the number of hours in the Duration. - // --> - if (attribute.startsWith("in_hours") || attribute.startsWith("hours")) - return new Element(seconds / 3600) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @description - // returns the number of minutes in the Duration. - // --> - if (attribute.startsWith("in_minutes") || attribute.startsWith("minutes")) - return new Element(seconds / 60) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @description - // returns the number of seconds in the Duration. - // --> - if (attribute.startsWith("in_seconds") || attribute.startsWith("seconds")) - return new Element(getTicks() / 20) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @description - // returns the number of milliseconds in the Duration. - // --> - if (attribute.startsWith("in_milliseconds") || attribute.startsWith("milliseconds")) - return new Element(getTicks() * (1000 / 20)) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // returns the number of ticks in the Duration. (20t/second) - // --> - if (attribute.startsWith("in_ticks") || attribute.startsWith("ticks")) - return new Element(getTicks()) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute ]> - // @returns Element(Number) - // @description - // returns this duration minus another. - // --> - if (attribute.startsWith("sub") && attribute.hasContext(1)) { - return new Duration(getTicks() - Duration.valueOf(attribute.getContext(1)).getTicks()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Number) - // @description - // returns this duration plus another. - // --> - if (attribute.startsWith("add") && attribute.hasContext(1)) { - return new Duration(getTicks() + Duration.valueOf(attribute.getContext(1)).getTicks()) - .getAttribute(attribute.fulfill(1)); - } - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the date-time specified by the duration object. - // --> - if (attribute.startsWith("time")) { - - Date currentDate = new Date(getTicks() * 50); - SimpleDateFormat format = new SimpleDateFormat(); - - attribute = attribute.fulfill(1); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // Returns the current year of the time specified by the duration object. - // --> - if (attribute.startsWith("year")) - return new Element(currentDate.getYear() + 1900 /* ??? */).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // Returns the current month of the time specified by the duration object. - // --> - else if (attribute.startsWith("month")) - return new Element(currentDate.getMonth() + 1).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // Returns the current day of the time specified by the duration object. - // --> - else if (attribute.startsWith("day")) - return new Element(currentDate.getDate()).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // Returns the current hour of the time specified by the duration object. - // --> - else if (attribute.startsWith("hour")) - return new Element(currentDate.getHours()).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // Returns the current minute of the time specified by the duration object. - // --> - else if (attribute.startsWith("minute")) - return new Element(currentDate.getMinutes()).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // Returns the current second of the time specified by the duration object. - // --> - else if (attribute.startsWith("second")) - return new Element(currentDate.getSeconds()).getAttribute(attribute.fulfill(1)); - - // TODO: Custom format option - else { - format.applyPattern("EEE, d MMM yyyy HH:mm:ss"); - return new Element(format.format(currentDate)) - .getAttribute(attribute); - } - } - - ///////////////////// - // DEBUG ATTRIBUTES - ///////////////// - - if (attribute.startsWith("prefix")) - return new Element(prefix) - .getAttribute(attribute.fulfill(1)); - - if (attribute.startsWith("debug.log")) { - dB.log(debug()); - return new Element(Boolean.TRUE.toString()) - .getAttribute(attribute.fulfill(2)); - } - - if (attribute.startsWith("debug.no_color")) { - return new Element(ChatColor.stripColor(debug())) - .getAttribute(attribute.fulfill(2)); - } - - if (attribute.startsWith("debug")) { - return new Element(debug()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Always returns 'Duration' for Duration objects. All objects fetchable by the Object Fetcher will return the - // type of object that is fulfilling this attribute. - // --> - if (attribute.startsWith("type")) { - return new Element("Duration").getAttribute(attribute.fulfill(1)); - } - - ///////////////////// - // FORMAT ATTRIBUTES - ///////////////// - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the value of the duration in an easily readable - // format like 2h 30m, where minutes are only shown if there - // is less than a day left and seconds are only shown if - // there are less than 10 minutes left. - // --> - if (attribute.startsWith("formatted") || attribute.startsWith("value")) { - - return new Element(formatted()) - .getAttribute(attribute.fulfill(1)); - } - - // Iterate through this object's properties' attributes - for (Property property : PropertyParser.getProperties(this)) { - String returned = property.getAttribute(attribute); - if (returned != null) return returned; - } - - return new Element(identify()).getAttribute(attribute); - } - - public String formatted() { - // Make sure you don't change these longs into doubles - // and break the code - - long seconds = (long) this.seconds; - long days = seconds / 86400; - long hours = (seconds - days * 86400) / 3600; - long minutes = (seconds - days * 86400 - hours * 3600) / 60; - seconds = seconds - days * 86400 - hours * 3600 - minutes * 60; - - String timeString = ""; - - if (days > 0) - timeString = String.valueOf(days) + "d "; - if (hours > 0) - timeString = timeString + String.valueOf(hours) + "h "; - if (minutes > 0 && days == 0) - timeString = timeString + String.valueOf(minutes) + "m "; - if (seconds > 0 && minutes < 10 && hours == 0 && days == 0) - timeString = timeString + String.valueOf(seconds) + "s"; - - if (timeString.isEmpty()) - timeString = "forever"; - - return timeString.trim(); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/Element.java b/src/main/java/net/aufdemrand/denizen/objects/Element.java deleted file mode 100644 index 79d97a2e4c..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/Element.java +++ /dev/null @@ -1,1889 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import net.aufdemrand.denizen.BukkitScriptEntryData; -import net.aufdemrand.denizen.objects.properties.Property; -import net.aufdemrand.denizen.objects.properties.PropertyParser; -import net.aufdemrand.denizen.scripts.ScriptRegistry; -import net.aufdemrand.denizen.scripts.commands.core.Comparable; -import net.aufdemrand.denizen.scripts.containers.core.FormatScriptContainer; -import net.aufdemrand.denizen.scripts.containers.core.ItemScriptHelper; -import net.aufdemrand.denizen.scripts.queues.ScriptQueue; -import net.aufdemrand.denizen.tags.Attribute; -import net.aufdemrand.denizen.tags.TagManager; -import net.aufdemrand.denizen.tags.core.EscapeTags; -import net.aufdemrand.denizen.utilities.SQLEscaper; -import net.aufdemrand.denizen.utilities.debugging.dB; - -import net.aufdemrand.denizencore.utilities.CoreUtilities; -import org.bukkit.ChatColor; - -// <--[language] -// @name Element -// @group Object System -// @description -// Elements are simple objects that contain either a boolean (true/false), -// string, or number value. Their main usage is within the replaceable tag -// system, often times returned from the use of another tag that isn't returning -// a specific object type, such as a location or entity. For example, -// or will both return Elements. -// -// Pluses to the Element system is the ability to utilize its attributes that -// can provide a range of functionality that should be familiar from any other -// programming language, such as 'to_uppercase', 'split', 'replace', 'contains', -// as_int, any many more. See 'element' tags for more information. -// -// While information fetched from other tags resulting in an Element is often -// times automatically handled, it may be desirable to utilize element -// attributes from strings/numbers/etc. that aren't already an element object. -// To accomplish this, the object fetcher can be used to create a new element. -// Element has a constructor, el@val[element_value], that will allow the -// creation of a new element. For example: -// will result in the value 'THIS_IS_A_TEST.' Note that while other objects often -// return their object identifier (el@, li@, e@, etc.), elements do not. - -// --> - - -public class Element implements dObject { - - public final static Element TRUE = new Element(Boolean.TRUE); - public final static Element FALSE = new Element(Boolean.FALSE); - public final static Element SERVER = new Element("server"); - public final static Element NULL = new Element("null"); - - final static Pattern VALUE_PATTERN = - Pattern.compile("el@val(?:ue)?\\[([^\\[\\]]+)\\].*", - Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE); - - /** - * - * @param string the string or dScript argument String - * @return a dScript dList - * - */ - @Fetchable("el") - public static Element valueOf(String string) { - if (string == null) return null; - - Matcher m = VALUE_PATTERN.matcher(string); - - // Allow construction of elements with el@val[] - if (m.matches()) { - String value = m.group(1); - return new Element(value); - } - - return new Element(string.toLowerCase().startsWith("el@") ? string.substring(3): string); - } - - public static boolean matches(String string) { - return string != null; - } - - /** - * Handle null dObjects appropriately for potentionally null tags. - * Will show a dB error message and return Element.NULL for null objects. - * - * @param tag The input string that produced a potentially null object, for debugging. - * @param object The potentially null object. - * @param type The type of object expected, for debugging. (EG: 'dNPC') - * @return The object or Element.NULL if the object is null. - */ - public static dObject handleNull(String tag, dObject object, String type, boolean has_fallback) { - if (object == null) { - if (!has_fallback) - dB.echoError("'" + tag + "' is an invalid " + type + "!"); - return null; - } - return object; - } - - private final String element; - - public Element(String string) { - this.prefix = "element"; - if (string == null) - this.element = "null"; - else - this.element = TagManager.cleanOutputFully(string); - } - - public Element(Boolean bool) { - this.prefix = "boolean"; - this.element = String.valueOf(bool); - } - - public Element(Integer integer) { - this.prefix = "integer"; - this.element = String.valueOf(integer); - } - - public Element(Byte byt) { - this.prefix = "byte"; - this.element = String.valueOf(byt); - } - - public Element(Short shrt) { - this.prefix = "short"; - this.element = String.valueOf(shrt); - } - - public Element(Long lng) { - this.prefix = "long"; - this.element = String.valueOf(lng); - } - - public Element(Double dbl) { - this.prefix = "double"; - this.element = String.valueOf(dbl); - } - - public Element(Float flt) { - this.prefix = "float"; - this.element = String.valueOf(flt); - } - - public Element(String prefix, String string) { - if (prefix == null) this.prefix = "element"; - else this.prefix = prefix; - this.element = TagManager.cleanOutputFully(string); - } - - private BigDecimal getBD(String text) { - return new BigDecimal(text); - } - - public BigDecimal asBigDecimal() { - return getBD(element.replaceAll("%", "")); - } - - public double asDouble() { - return Double.valueOf(element.replaceAll("%", "")); - } - - public float asFloat() { - return Float.valueOf(element.replaceAll("%", "")); - } - - public int asInt() { - try { - return Integer.valueOf(element.replaceAll("(%)|(\\.\\d+)", "")); - } - catch (NumberFormatException ex) { - dB.echoError("'" + element + "' is not a valid integer!"); - return 0; - } - } - - public long asLong() { - try { - return Long.valueOf(element.replaceAll("(%)|(\\.\\d+)", "")); - } - catch (NumberFormatException ex) { - dB.echoError("'" + element + "' is not a valid integer!"); - return 0; - } - } - - public boolean asBoolean() { - return Boolean.valueOf(element.replaceAll("el@", "")); - } - - public String asString() { - return element; - } - - public boolean isBoolean() { - return (element != null && (element.equalsIgnoreCase("true") || element.equalsIgnoreCase("false"))); - } - - public boolean isDouble() { - try { - if (Double.valueOf(element) != null) - return true; - } catch (Exception e) {} - return false; - } - - public boolean isFloat() { - try { - if (Float.valueOf(element) != null) - return true; - } catch (Exception e) {} - return false; - } - - public boolean isInt() { - try { - if (Integer.valueOf(element.replaceAll("(%)|(\\.\\d+)", "")) != null) - return true; - } catch (Exception e) {} - return false; - } - - public boolean isString() { - return (element != null && !element.isEmpty()); - } - - public boolean matchesType(Class dClass) { - return ObjectFetcher.checkMatch(dClass, element); - } - - public T asType(Class dClass) { - return ObjectFetcher.getObjectFrom(dClass, element); - } - - public boolean matchesEnum(Enum[] values) { - for (Enum value : values) - if (value.name().equalsIgnoreCase(element)) - return true; - - return false; - } - - private String prefix; - - @Override - public String getObjectType() { - return "Element"; - } - - @Override - public String getPrefix() { - return prefix; - } - - @Override - public dObject setPrefix(String prefix) { - this.prefix = prefix; - return this; - } - - @Override - public String debug() { - return (prefix + "='" + identify() + "' "); - } - - @Override - public String identify() { - return element; - } - - @Override - public String identifySimple() { - return identify(); - } - - @Override - public String toString() { - return identify(); - } - - @Override - public boolean isUnique() { - return false; - } - - @Override - public String getAttribute(Attribute attribute) { - - if (attribute == null) return null; - - - //////////////////// - // COMPARABLE ATTRIBUTES - //////////////// - - // <--[tag] - // @attribute ].to[]> - // @returns Element(Boolean) - // @group comparison - // @description - // Takes an operator, and compares the value of the element to the supplied - // element. Returns the outcome of the comparable, either true or false. For - // information on operators, see <@link language operator>. - // Equivalent to <@link tag el@element.is[].than[]> - // --> - - // <--[tag] - // @attribute ].than[]> - // @returns Element(Boolean) - // @group comparison - // @description - // Takes an operator, and compares the value of the element to the supplied - // element. Returns the outcome of the comparable, either true or false. For - // information on operators, see <@link language operator>. - // Equivalent to <@link tag el@element.is[].to[]> - // --> - if (attribute.startsWith("is") && attribute.hasContext(1) - && (attribute.startsWith("to", 2) || attribute.startsWith("than", 2)) && attribute.hasContext(2)) { - - // Use the Comparable object as implemented for the IF command. First, a new Comparable! - Comparable com = new net.aufdemrand.denizen.scripts.commands.core.Comparable(); - - // Check for negative logic - String operator; - if (attribute.getContext(1).startsWith("!")) { - operator = attribute.getContext(1).substring(1); - com.setNegativeLogic(); - } else operator = attribute.getContext(1); - - // Operator is the value of the .is[] context. Valid are Comparable.Operators, same - // as used by the IF command. - Comparable.Operator comparableOperator = null; - try { - comparableOperator = Comparable.Operator.valueOf(operator.replace("==", "EQUALS") - .replace(">=", "OR_MORE").replace("<=", "OR_LESS").replace("<", "LESS") - .replace(">", "MORE").replace("=", "EQUALS").toUpperCase()); - } - catch (IllegalArgumentException e) { } - - if (comparableOperator != null) { - com.setOperator(comparableOperator); - - // Comparable is the value of this element - com.setComparable(element); - // Compared_to is the value of the .to[] context. - com.setComparedto(attribute.getContext(2)); - - return new Element(com.determineOutcome()).getAttribute(attribute.fulfill(2)); - } - else { - dB.echoError("Unknown operator '" + operator + "'."); - } - } - - - ///////////////////// - // CONVERSION ATTRIBUTES - ///////////////// - - // <--[tag] - // @attribute - // @returns Element(Boolean) - // @group conversion - // @description - // Returns the element as true/false. - // --> - if (attribute.startsWith("asboolean") - || attribute.startsWith("as_boolean")) - return new Element(element.equalsIgnoreCase("true") || - element.equalsIgnoreCase("t") || element.equalsIgnoreCase("1")) - .getAttribute(attribute.fulfill(1)); - - // TODO: Why does this exist? It just throws an error or makes no changes. - if (attribute.startsWith("asdouble") - || attribute.startsWith("as_double")) - try { return new Element(Double.valueOf(element)) - .getAttribute(attribute.fulfill(1)); } - catch (NumberFormatException e) { - if (!attribute.hasAlternative()) - dB.echoError("'" + element + "' is not a valid Double."); - } - - // <--[tag] - // @attribute - // @returns Element(Number) - // @group conversion - // @description - // Returns the element as a number without a decimal. Rounds decimal values. - // --> - if (attribute.startsWith("asint") - || attribute.startsWith("as_int")) - try { - // Round the Double instead of just getting its - // value as an Integer (which would incorrectly - // turn 2.9 into 2) - return new Element(Math.round(Double.valueOf(element))) - .getAttribute(attribute.fulfill(1)); } - catch (NumberFormatException e) { - if (!attribute.hasAlternative()) - dB.echoError("'" + element + "' is not a valid Integer."); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group conversion - // @description - // Returns the element as a number with two decimal places. - // --> - if (attribute.startsWith("asmoney") - || attribute.startsWith("as_money")) { - try { - DecimalFormat d = new DecimalFormat("0.00"); - return new Element(d.format(Double.valueOf(element))) - .getAttribute(attribute.fulfill(1)); } - catch (NumberFormatException e) { - if (!attribute.hasAlternative()) - dB.echoError("'" + element + "' is not a valid number."); - } - } - - // <--[tag] - // @attribute - // @returns dCuboid - // @group conversion - // @description - // Returns the element as a chunk. Note: the value must be a valid chunk. - // --> - if (attribute.startsWith("aschunk") - || attribute.startsWith("as_chunk")) { - dObject object = handleNull(element, dChunk.valueOf(element), "dChunk", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dCuboid - // @group conversion - // @description - // Returns the element as a dColor. Note: the value must be a valid color. - // --> - if (attribute.startsWith("ascolor") - || attribute.startsWith("as_color")) { - dObject object = handleNull(element, dColor.valueOf(element), "dColor", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dCuboid - // @group conversion - // @description - // Returns the element as a cuboid. Note: the value must be a valid cuboid. - // --> - if (attribute.startsWith("ascuboid") - || attribute.startsWith("as_cuboid")) { - dObject object = handleNull(element, dCuboid.valueOf(element), "dCuboid", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dEntity - // @group conversion - // @description - // Returns the element as an entity. Note: the value must be a valid entity. - // --> - if (attribute.startsWith("asentity") - || attribute.startsWith("as_entity")) { - dObject object = handleNull(element, dEntity.valueOf(element), "dEntity", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dInventory - // @group conversion - // @description - // Returns the element as an inventory. Note: the value must be a valid inventory. - // --> - if (attribute.startsWith("asinventory") - || attribute.startsWith("as_inventory")) { - dObject object = handleNull(element, dInventory.valueOf(element), "dInventory", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dItem - // @group conversion - // @description - // Returns the element as an item. Additional attributes can be accessed by dItem. - // Note: the value must be a valid item. - // --> - if (attribute.startsWith("asitem") - || attribute.startsWith("as_item")) { - dObject object = handleNull(element, dItem.valueOf(element), "dItem", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @group conversion - // @description - // Returns the element as a list. - // --> - if (attribute.startsWith("aslist") - || attribute.startsWith("as_list")) { - dObject object = handleNull(element, dList.valueOf(element), "dList", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dLocation - // @group conversion - // @description - // Returns the element as a location. Note: the value must be a valid location. - // --> - if (attribute.startsWith("aslocation") - || attribute.startsWith("as_location")) { - dObject object = handleNull(element, dLocation.valueOf(element), "dLocation", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dMaterial - // @group conversion - // @description - // Returns the element as a material. Note: the value must be a valid material. - // --> - if (attribute.startsWith("asmaterial") - || attribute.startsWith("as_material")) { - dObject object = handleNull(element, dMaterial.valueOf(element), "dMaterial", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dNPC - // @group conversion - // @description - // Returns the element as an NPC. Note: the value must be a valid NPC. - // --> - if (attribute.startsWith("asnpc") - || attribute.startsWith("as_npc")) { - dObject object = handleNull(element, dNPC.valueOf(element), "dNPC", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dPlayer - // @group conversion - // @description - // Returns the element as a player. Note: the value must be a valid player. Can be online or offline. - // --> - if (attribute.startsWith("asplayer") - || attribute.startsWith("as_player")) { - dObject object = handleNull(element, dPlayer.valueOf(element), "dPlayer", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dPlugin - // @group conversion - // @description - // Returns the element as a plugin. Note: the value must be a valid plugin. - // --> - if (attribute.startsWith("asplugin") - || attribute.startsWith("as_plugin")) { - dObject object = handleNull(element, dPlugin.valueOf(element), "dPlugin", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dScript - // @group conversion - // @description - // Returns the element as a script. Note: the value must be a valid script. - // --> - if (attribute.startsWith("asscript") - || attribute.startsWith("as_script")) { - dObject object = handleNull(element, dScript.valueOf(element), "dScript", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Duration - // @group conversion - // @description - // Returns the element as a duration. - // --> - if (attribute.startsWith("asduration") - || attribute.startsWith("as_duration")) { - dObject object = handleNull(element, Duration.valueOf(element), "Duration", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dWorld - // @group conversion - // @description - // Returns the element as a world. - // --> - if (attribute.startsWith("asworld") - || attribute.startsWith("as_world")) { - dObject object = handleNull(element, dWorld.valueOf(element), "dWorld", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dQueue - // @group conversion - // @description - // Returns the element as a queue. - // --> - if (attribute.startsWith("asqueue") - || attribute.startsWith("as_queue")) { - dObject object = handleNull(element, ScriptQueue.valueOf(element), "dQueue", attribute.hasAlternative()); - if (object != null) - return object.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @group conversion - // @description - // Returns the element, escaped for safe reuse. - // Inverts <@link tag el@element.unescaped> - // See <@link language property escaping> - // --> - if (attribute.startsWith("escaped")) - return new Element(EscapeTags.Escape(element)).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @group conversion - // @description - // Returns the element, escaped for safe use in SQL. - // --> - if (attribute.startsWith("sql_escaped")) - return new Element(SQLEscaper.escapeSQL(element)).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @group conversion - // @description - // Returns the element, unescaped. - // Inverts <@link tag el@element.escaped> - // See <@link language property escaping> - // --> - if (attribute.startsWith("unescaped")) - return new Element(EscapeTags.unEscape(element)).getAttribute(attribute.fulfill(1)); - - - ///////////////////// - // DEBUG ATTRIBUTES - ///////////////// - - // <--[tag] - // @attribute - // @returns Element - // @group debug - // @description - // Prints the Element's debug representation in the console and returns true. - // --> - if (attribute.startsWith("debug.log")) { - dB.log(debug()); - return new Element(Boolean.TRUE) - .getAttribute(attribute.fulfill(2)); - } - - // <--[tag] - // @attribute - // @returns Element - // @group debug - // @description - // Returns a standard debug representation of the Element with colors stripped. - // --> - if (attribute.startsWith("debug.no_color")) { - return new Element(ChatColor.stripColor(debug())) - .getAttribute(attribute.fulfill(2)); - } - - // <--[tag] - // @attribute - // @returns Element - // @group debug - // @description - // Returns a standard debug representation of the Element. - // --> - if (attribute.startsWith("debug")) { - return new Element(debug()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @group debug - // @description - // Returns the prefix of the element. - // --> - if (attribute.startsWith("prefix")) - return new Element(prefix) - .getAttribute(attribute.fulfill(1)); - - - ///////////////////// - // STRING CHECKING ATTRIBUTES - ///////////////// - - // <--[tag] - // @attribute |...]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains any of a list of specified strings, case sensitive. - // --> - // <--[tag] - // @attribute |...]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains any of a list of specified strings, case sensitive. - // --> - if (attribute.startsWith("contains_any_case_sensitive")) { - dList list = dList.valueOf(attribute.getContext(1)); - for (String list_element: list) { - if (element.contains(list_element)) { - return Element.TRUE.getAttribute(attribute.fulfill(1)); - } - } - return Element.FALSE.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute |...]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains any of a list of specified strings, case insensitive. - // --> - - // <--[tag] - // @attribute |...]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains any of a list of specified strings, case insensitive. - // --> - if (attribute.startsWith("contains_any")) { - dList list = dList.valueOf(attribute.getContext(1)); - String ellow = element.toLowerCase(); - for (String list_element: list) { - if (ellow.contains(list_element.toLowerCase())) { - return Element.TRUE.getAttribute(attribute.fulfill(1)); - } - } - return Element.FALSE.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains a specified string, case sensitive. - // --> - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains a specified string, case sensitive. - // --> - if (attribute.startsWith("contains_case_sensitive")) { - String contains = attribute.getContext(1); - if (element.contains(contains)) - return new Element("true").getAttribute(attribute.fulfill(1)); - else return new Element("false").getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains a specified string, case insensitive. Can use - // regular expression by prefixing the string with regex: - // --> - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element contains a specified string, case insensitive. Can use - // regular expression by prefixing the string with regex: - // --> - if (attribute.startsWith("contains")) { - String contains = attribute.getContext(1); - - if (contains.toLowerCase().startsWith("regex:")) { - - if (Pattern.compile(contains.substring(("regex:").length()), Pattern.CASE_INSENSITIVE).matcher(element).matches()) - return new Element("true").getAttribute(attribute.fulfill(1)); - else return new Element("false").getAttribute(attribute.fulfill(1)); - } - - else if (element.toLowerCase().contains(contains.toLowerCase())) - return new Element("true").getAttribute(attribute.fulfill(1)); - else return new Element("false").getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element ends with a specified string. - // --> - if (attribute.startsWith("ends_with") || attribute.startsWith("endswith")) - return new Element(element.toLowerCase().endsWith(attribute.getContext(1).toLowerCase())).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element matches another element, case-sensitive. - // --> - if (attribute.startsWith("equals_case_sensitive") - && attribute.hasContext(1)) { - return new Element(element.equals(attribute.getContext(1))).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element matches a regex input. - // --> - if (attribute.startsWith("matches") - && attribute.hasContext(1)) { - return new Element(element.matches(attribute.getContext(1))).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ].group[]> - // @returns Element - // @group string checking - // @description - // Returns the specific group from a regex match. - // Specify group 0 for the whole match. - // For example, returns '5'. - // --> - if (attribute.startsWith("regex") - && attribute.hasContext(1) - && attribute.hasContext(2)) { - String regex = attribute.getContext(1); - Matcher m = Pattern.compile(regex).matcher(element); - if (!m.matches()) { - return null; - } - int group = new Element(attribute.getContext(2)).asInt(); - if (group < 0) - group = 0; - if (group > m.groupCount()) - group = m.groupCount(); - return new Element(m.group(group)).getAttribute(attribute.fulfill(2)); - } - - // <--[tag] - // @attribute - // @returns Element - // @group string checking - // @description - // Returns the ChatColors used at the end of a string. - // --> - if (attribute.startsWith("last_color")) - return new Element(ChatColor.getLastColors(element)).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Number) - // @group string checking - // @description - // Returns the length of the element. - // --> - if (attribute.startsWith("length")) { - return new Element(element.length()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Boolean) - // @group string checking - // @description - // Returns the opposite of the element - // IE, true returns false and false returns true. - // --> - if (attribute.startsWith("not")) { - return new Element(!element.equalsIgnoreCase("true")) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether both the element and the second element are true. - // --> - if (attribute.startsWith("and") - && attribute.hasContext(1)) { - return new Element(element.equalsIgnoreCase("true") && attribute.getContext(1).equalsIgnoreCase("true")) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether either the element or the second element are true. - // --> - if (attribute.startsWith("or") - && attribute.hasContext(1)) { - return new Element(element.equalsIgnoreCase("true") || attribute.getContext(1).equalsIgnoreCase("true")) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element and the second element are true and false (exclusive or). - // --> - if (attribute.startsWith("xor") - && attribute.hasContext(1)) { - return new Element(element.equalsIgnoreCase("true") != attribute.getContext(1).equalsIgnoreCase("true")) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the two elements exactly match, counting casing. - // --> - if (attribute.startsWith("equals_with_case") - && attribute.hasContext(1)) { - return new Element(element.equals(attribute.getContext(1))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @group string checking - // @description - // Returns whether the element starts with a specified string. - // --> - if (attribute.startsWith("starts_with") || attribute.startsWith("startswith")) - return new Element(element.toLowerCase().startsWith(attribute.getContext(1).toLowerCase())).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute ]> - // @returns Element(Number) - // @group string checking - // @description - // Returns the index of the first occurrence of a specified string. - // Returns -1 if the string never occurs within the element. - // --> - if (attribute.startsWith("index_of") - && attribute.hasContext(1)) { - return new Element(element.toLowerCase().indexOf(attribute.getContext(1).toLowerCase()) + 1) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Number) - // @group string checking - // @description - // Returns the index of the last occurrence of a specified string. - // Returns -1 if the string never occurs within the element. - // --> - if (attribute.startsWith("last_index_of") - && attribute.hasContext(1)) { - return new Element(element.toLowerCase().lastIndexOf(attribute.getContext(1).toLowerCase()) + 1) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string checking - // @description - // Returns the character at a specified index. - // Returns null if the index is outside the range of the element. - // --> - if (attribute.startsWith("char_at") - && attribute.hasContext(1)) { - int index = attribute.getIntContext(1) - 1; - if (index < 0 || index >= element.length()) - return null; - else - return new Element(String.valueOf(element.charAt(index))) - .getAttribute(attribute.fulfill(1)); - } - - - ///////////////////// - // STRING MANIPULATION ATTRIBUTES - ///////////////// - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the portion of an element after the last occurrence of a specified string. - // EG, abcabc .after[b] returns c. - // --> - if (attribute.startsWith("after_last") - && attribute.hasContext(1)) { - String delimiter = attribute.getContext(1); - if (element.toLowerCase().contains(delimiter.toLowerCase())) - return new Element(element.substring - (element.toLowerCase().lastIndexOf(delimiter.toLowerCase()) + delimiter.length())) - .getAttribute(attribute.fulfill(1)); - else - return new Element("") - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the portion of an element after the first occurrence of a specified string. - // EG, HelloWorld .after[Hello] returns World. - // --> - if (attribute.startsWith("after") - && attribute.hasContext(1)) { - String delimiter = attribute.getContext(1); - if (element.toLowerCase().contains(delimiter.toLowerCase())) - return new Element(element.substring - (element.toLowerCase().indexOf(delimiter.toLowerCase()) + delimiter.length())) - .getAttribute(attribute.fulfill(1)); - else - return new Element("") - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the portion of an element before the last occurrence of a specified string. - // EG, abcabc .before[b] returns abca. - // --> - if (attribute.startsWith("before_last") - && attribute.hasContext(1)) { - String delimiter = attribute.getContext(1); - if (element.toLowerCase().contains(delimiter.toLowerCase())) - return new Element(element.substring - (0, element.toLowerCase().lastIndexOf(delimiter.toLowerCase()))) - .getAttribute(attribute.fulfill(1)); - else - return new Element(element) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the portion of an element before the first occurrence of specified string. - // EG, abcd .before[c] returns ab. - // --> - if (attribute.startsWith("before") - && attribute.hasContext(1)) { - String delimiter = attribute.getContext(1); - if (element.toLowerCase().contains(delimiter.toLowerCase())) - return new Element(element.substring - (0, element.toLowerCase().indexOf(delimiter.toLowerCase()))) - .getAttribute(attribute.fulfill(1)); - else - return new Element(element) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the element with all instances of a string removed. - // --> - - // <--[tag] - // @attribute ].with[]> - // @returns Element - // @group string manipulation - // @description - // Returns the element with all instances of a string replaced with another. - // Specify regex: at the start of the replace string to use Regex replacement. - // Specify firstregex: at the start of the replace string to Regex 'replaceFirst' - // --> - if (attribute.startsWith("replace") - && attribute.hasContext(1)) { - - String replace = attribute.getContext(1); - String replacement = ""; - attribute.fulfill(1); - if (attribute.startsWith("with")) { - if (attribute.hasContext(1)) { - replacement = attribute.getContext(1); - if (replacement == null) - replacement = ""; - attribute.fulfill(1); - } - } - - if (replace.startsWith("regex:")) - return new Element(element.replaceAll(replace.substring("regex:".length()), replacement)) - .getAttribute(attribute); - if (replace.startsWith("firstregex:")) - return new Element(element.replaceFirst(replace.substring("firstregex:".length()), replacement)) - .getAttribute(attribute); - else - return new Element(element.replaceAll("(?i)" + Pattern.quote(replace), replacement)) - .getAttribute(attribute); - } - - // <--[tag] - // @attribute ].limit[<#>]> - // @returns dList - // @group string manipulation - // @description - // Returns a list of portions of this element, split by the specified string, - // and capped at the specified number of max list items. - // --> - if (attribute.startsWith("split") && attribute.startsWith("limit", 2)) { - String split_string = (attribute.hasContext(1) ? attribute.getContext(1) : " "); - Integer limit = (attribute.hasContext(2) ? attribute.getIntContext(2) : 1); - if (split_string.toLowerCase().startsWith("regex:")) - return new dList(Arrays.asList(element.split(split_string.split(":", 2)[1], limit))) - .getAttribute(attribute.fulfill(2)); - else - return new dList(Arrays.asList(element.split("(?i)" + Pattern.quote(split_string), limit))) - .getAttribute(attribute.fulfill(2)); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @group string manipulation - // @description - // Returns a list of portions of this element, split by the specified string. - // --> - if (attribute.startsWith("split")) { - String split_string = (attribute.hasContext(1) ? attribute.getContext(1) : " "); - if (split_string.toLowerCase().startsWith("regex:")) - return new dList(Arrays.asList(element.split(split_string.split(":", 2)[1]))) - .getAttribute(attribute.fulfill(1)); - else - return new dList(Arrays.asList(element.split("(?i)" + Pattern.quote(split_string)))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @group string manipulation - // @description - // Returns a number reformatted for easier reading. - // EG, 1234567 will become 1,234,567. - // --> - if (attribute.startsWith("format_number")) { - try { - int decimal = element.indexOf('.'); - String shortelement; - String afterdecimal; - if (decimal != -1) { - shortelement = element.substring(0, decimal); - afterdecimal = element.substring(decimal); - } - else { - shortelement = element; - afterdecimal = ""; - } - String intform = Long.valueOf(shortelement.replace("%", "")).toString(); - String negative = ""; - if (intform.startsWith("-")) { - negative = "-"; - intform = intform.substring(1, intform.length()); - } - for (int i = intform.length() - 3; i > 0; i -= 3) { - intform = intform.substring(0, i) + "," + intform.substring(i, intform.length()); - } - return new Element(negative + intform + afterdecimal).getAttribute(attribute.fulfill(1)); - } - catch (Exception ex) { - dB.echoError(ex); - } - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the text re-formatted according to a format script. - // See <@link example using format scripts>. - // --> - if (attribute.startsWith("format") - && attribute.hasContext(1)) { - FormatScriptContainer format = ScriptRegistry.getScriptContainer(attribute.getContext(1)); - if (format == null) { - dB.echoError("Could not find format script matching '" + attribute.getContext(1) + "'"); - return null; - } - else { - return new Element(format.getFormattedText(element, - attribute.getScriptEntry() != null ? ((BukkitScriptEntryData)attribute.getScriptEntry().entryData).getNPC(): null, - attribute.getScriptEntry() != null ? ((BukkitScriptEntryData)attribute.getScriptEntry().entryData).getPlayer(): null)) - .getAttribute(attribute.fulfill(1)); - } - } - - // <--[tag] - // @attribute - // @returns dList - // @group string manipulation - // @description - // Returns a dList of each letter in the element. - // --> - if (attribute.startsWith("to_list")) { - dList list = new dList(); - for (int i = 0; i < element.length(); i++) { - list.add(String.valueOf(element.charAt(i))); - } - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @group string manipulation - // @description - // Returns the element with all color encoding stripped. - // --> - if (attribute.startsWith("strip_color")) - return new Element(ChatColor.stripColor(element)).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @group string manipulation - // @description - // Returns the value of an element minus any leading or trailing whitespace. - // --> - if (attribute.startsWith("trim")) - return new Element(element.trim()).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @group string manipulation - // @description - // Returns the value of an element in all uppercase letters. - // --> - if (attribute.startsWith("to_uppercase") || attribute.startsWith("upper")) - return new Element(element.toUpperCase()).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @group string manipulation - // @description - // Returns the value of an element in all lowercase letters. - // --> - if (attribute.startsWith("to_lowercase") || attribute.startsWith("lower")) - return new Element(CoreUtilities.toLowerCase(element)).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @group string manipulation - // @description - // Returns The Value Of An Element In Title Case. - // --> - if (attribute.startsWith("to_titlecase") || attribute.startsWith("totitlecase")) { - if (element.length() == 0) { - return new Element("").getAttribute(attribute.fulfill(1)); - } - StringBuilder TitleCase = new StringBuilder(element.length()); - String Upper = element.toUpperCase(); - String Lower = element.toLowerCase(); - TitleCase.append(Upper.charAt(0)); - for (int i = 1; i < element.length(); i++) { - if (element.charAt(i - 1) == ' ') - TitleCase.append(Upper.charAt(i)); - else - TitleCase.append(Lower.charAt(i)); - } - return new Element(TitleCase.toString()).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute (,<#>)]> - // @returns Element - // @group string manipulation - // @description - // Returns the portion of an element between two string indices. - // If no second index is specified, it will return the portion of an - // element after the specified index. - // --> - if (attribute.startsWith("substring")||attribute.startsWith("substr")) { // substring[2,8] - int beginning_index = new Element(attribute.getContext(1).split(",")[0]).asInt() - 1; - int ending_index; - if (attribute.getContext(1).split(",").length > 1) - ending_index = new Element(attribute.getContext(1).split(",")[1]).asInt(); - else - ending_index = element.length(); - if (beginning_index < 0) beginning_index = 0; - if (beginning_index > element.length()) beginning_index = element.length(); - if (ending_index > element.length()) ending_index = element.length(); - if (ending_index < beginning_index) ending_index = beginning_index; - return new Element(element.substring(beginning_index, ending_index)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the value of an element extended to reach a minimum specified length - // by adding spaces to the left side. - // --> - if (attribute.startsWith("pad_left") - && attribute.hasContext(1)) { - String with = String.valueOf((char)0x00A0); - int length = attribute.getIntContext(1); - attribute = attribute.fulfill(1); - // <--[tag] - // @attribute ].with[]> - // @returns Element - // @group string manipulation - // @description - // Returns the value of an element extended to reach a minimum specified length - // by adding a specific symbol to the left side. - // --> - if (attribute.startsWith("with") - && attribute.hasContext(1)) { - with = String.valueOf(attribute.getContext(1).charAt(0)); - attribute = attribute.fulfill(1); - } - String padded = element; - while (padded.length() < length) { - padded = with + padded; - } - return new Element(padded).getAttribute(attribute); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @group string manipulation - // @description - // Returns the value of an element extended to reach a minimum specified length - // by adding spaces to the right side. - // --> - if (attribute.startsWith("pad_right") - && attribute.hasContext(1)) { - String with = String.valueOf((char)0x00A0); - int length = attribute.getIntContext(1); - attribute = attribute.fulfill(1); - // <--[tag] - // @attribute ].with[]> - // @returns Element - // @group string manipulation - // @description - // Returns the value of an element extended to reach a minimum specified length - // by adding a specific symbol to the right side. - // --> - if (attribute.startsWith("with") - && attribute.hasContext(1)) { - with = String.valueOf(attribute.getContext(1).charAt(0)); - attribute = attribute.fulfill(1); - } - StringBuilder padded = new StringBuilder(element); - while (padded.length() < length) { - padded.append(with); - } - return new Element(padded.toString()).getAttribute(attribute); - } - - - ///////////////////// - // MATH ATTRIBUTES - ///////////////// - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the absolute value of the element. - // --> - if (attribute.startsWith("abs")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.abs(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element plus a number, using integer math. - // --> - if (attribute.startsWith("add_int") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid number!"); - return null; - } - return new Element(asLong() + aH.getLongFrom(attribute.getContext(1))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element divided by a number. - // --> - if (attribute.startsWith("div_int") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(asLong() / aH.getLongFrom(attribute.getContext(1))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element multiplied by a number. - // --> - if (attribute.startsWith("mul_int") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(asLong() * aH.getLongFrom(attribute.getContext(1))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element minus a number. - // --> - if (attribute.startsWith("sub_int") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(asLong() - aH.getLongFrom(attribute.getContext(1))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element plus a number. - // --> - if (attribute.startsWith("add") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(asBigDecimal().add(getBD(attribute.getContext(1))).toString()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element divided by a number. - // --> - if (attribute.startsWith("div") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - try { - return new Element(asBigDecimal().divide(getBD(attribute.getContext(1))).toString()) - .getAttribute(attribute.fulfill(1)); - } - catch (Exception e) { - return new Element(asDouble() / (aH.getDoubleFrom(attribute.getContext(1)))) - .getAttribute(attribute.fulfill(1)); - } - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the remainder of the element divided by a number. - // --> - if (attribute.startsWith("mod") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(asDouble() % aH.getDoubleFrom(attribute.getContext(1))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element multiplied by a number. - // --> - if (attribute.startsWith("mul") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - try { - return new Element(asBigDecimal().multiply(getBD(attribute.getContext(1))).toString()) - .getAttribute(attribute.fulfill(1)); - } - catch (Exception e) { - return new Element(asDouble() * (aH.getDoubleFrom(attribute.getContext(1)))) - .getAttribute(attribute.fulfill(1)); - } - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element minus a number. - // --> - if (attribute.startsWith("sub") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(asBigDecimal().subtract(getBD(attribute.getContext(1))).toString()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the square root of the element. - // --> - if (attribute.startsWith("sqrt")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.sqrt(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // Iterate through this object's properties' attributes - for (Property property : PropertyParser.getProperties(this)) { - String returned = property.getAttribute(attribute); - if (returned != null) return returned; - } - - // <--[tag] - // @attribute ]> - // @returns Element(Decimal) - // @group math - // @description - // Returns the element to the power of a number. - // --> - if (attribute.startsWith("power") - && attribute.hasContext(1)) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.pow(asDouble(), aH.getDoubleFrom(attribute.getContext(1)))) - .getAttribute(attribute.fulfill(1)); - } - - // Iterate through this object's properties' attributes - for (Property property : PropertyParser.getProperties(this)) { - String returned = property.getAttribute(attribute); - if (returned != null) return returned; - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the arc-sine of the element. - // --> - if (attribute.startsWith("asin")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.asin(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the arc-cosine of the element. - // --> - if (attribute.startsWith("acos")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.acos(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the arc-tangent of the element. - // --> - if (attribute.startsWith("atan")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.atan(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the cosine of the element. - // --> - if (attribute.startsWith("cos")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.cos(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the sine of the element. - // --> - if (attribute.startsWith("sin")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.sin(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Returns the tangent of the element. - // --> - if (attribute.startsWith("tan")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.tan(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Converts the element from radians to degrees. - // --> - if (attribute.startsWith("to_degrees")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.toDegrees(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Decimal) - // @group math - // @description - // Converts the element from degrees to radians. - // --> - if (attribute.startsWith("to_radians")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element(Math.toRadians(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Number) - // @group math - // @description - // Rounds a decimal upward. - // --> - if (attribute.startsWith("round_up")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element((int)Math.ceil(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Number) - // @group math - // @description - // Rounds a decimal downward. - // --> - if (attribute.startsWith("round_down")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element((int)Math.floor(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Number) - // @group math - // @description - // Rounds a decimal. - // --> - if (attribute.startsWith("round")) { - if (!isDouble()) { - dB.echoError("Element '" + element + "' is not a valid decimal number!"); - return null; - } - return new Element((int)Math.round(asDouble())) - .getAttribute(attribute.fulfill(1)); - } - - - // <--[tag] - // @attribute - // @returns Element(Number) - // @group conversion - // @description - // Shortens the element down to an itemscript hash ID, made of invisible color codes. - // --> - if (attribute.startsWith("to_itemscript_hash")) { - return new Element(ItemScriptHelper.createItemScriptID(element)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Always returns 'Element' for Element objects. All objects fetchable by the Object Fetcher will return the - // type of object that is fulfilling this attribute. - // --> - if (attribute.startsWith("type")) { - return new Element("Element").getAttribute(attribute.fulfill(1)); - } - // Unfilled attributes past this point probably means the tag is spelled - // incorrectly. So instead of just passing through what's been resolved - // so far, 'null' shall be returned with a debug message. - - if (attribute.attributes.size() > 0) { - if (!attribute.hasAlternative()) - dB.echoDebug(attribute.getScriptEntry(), "Unfilled attributes '" + attribute.attributes.toString() + - "' for tag <" + attribute.getOrigin() + ">!"); - return null; - - } else { - return element; - } - } -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/Fetchable.java b/src/main/java/net/aufdemrand/denizen/objects/Fetchable.java deleted file mode 100644 index c6c7c76402..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/Fetchable.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) - -public @interface Fetchable { - String value(); -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/Mechanism.java b/src/main/java/net/aufdemrand/denizen/objects/Mechanism.java deleted file mode 100644 index 44f22095e1..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/Mechanism.java +++ /dev/null @@ -1,136 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import net.aufdemrand.denizen.utilities.debugging.dB; - -public class Mechanism { - - private boolean fulfilled; - private String raw_mechanism; - private Element value; - private String outcome = null; - - public Mechanism(Element mechanism, Element value) { - fulfilled = false; - raw_mechanism = mechanism.asString(); - this.value = value; - } - - public void fulfill(String _outcome) { - fulfilled = true; - outcome = _outcome; // TODO: Return outcome somewhere? - } - - public boolean fulfilled() { - return fulfilled; - } - - public String getName() { - return raw_mechanism; - } - - public Element getValue() { - return value; - } - - public boolean hasValue() { - return value != null && value.asString().length() > 0; - } - - public boolean matches(String string) { - if (string.equalsIgnoreCase(raw_mechanism)) { - fulfill(""); - return true; - } - return false; - } - - public boolean requireBoolean() { - return requireBoolean("Invalid boolean. Must specify TRUE or FALSE."); - } - - public boolean requireDouble() { - return requireDouble("Invalid double specified."); - } - - public boolean requireEnum(boolean allowInt, Enum... values) { - return requireEnum(null, allowInt, values); - } - - public boolean requireFloat() { - return requireFloat("Invalid float specified."); - } - - public boolean requireInteger() { - return requireInteger("Invalid integer specified."); - } - - public boolean requireObject(Class type) { - return requireObject(null, type); - } - - public boolean requireBoolean(String error) { - if (value.isBoolean()) - return true; - dB.echoError(error); - return false; - } - - public boolean requireDouble(String error) { - if (value.isDouble()) - return true; - dB.echoError(error); - return false; - } - - public boolean requireEnum(String error, boolean allowInt, Enum... values) { - if (allowInt && value.isInt() && value.asInt() < values.length) - return true; - if (value.isString()) { - String raw_value = value.asString().toUpperCase(); - for (Enum check_value : values) { - if (raw_value.equals(check_value.name())) - return true; - } - } - if (error == null) { - // TODO: Remove getSimpleName(), or simplify somehow. - dB.echoError("Invalid " + values[0].getDeclaringClass().getSimpleName() + "." - + " Must specify a valid name" + (allowInt ? " or number" : "") + "."); - } - else { - dB.echoError(error); - } - return false; - } - - public boolean requireFloat(String error) { - if (value.isFloat()) - return true; - dB.echoError(error); - return false; - } - - public boolean requireInteger(String error) { - if (value.isInt()) - return true; - dB.echoError(error); - return false; - } - - public boolean requireObject(String error, Class type) { - if (value.matchesType(type)) - return true; - if (error == null) { - // TODO: Remove getSimpleName(), or simplify somehow. - dB.echoError("Invalid " + type.getSimpleName() + " specified."); - } - else { - dB.echoError(error); - } - return false; - } - - public void reportInvalid() { - dB.echoError("Invalid mechanism specified: " + raw_mechanism); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/ObjectFetcher.java b/src/main/java/net/aufdemrand/denizen/objects/ObjectFetcher.java deleted file mode 100644 index e001b3a1fc..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/ObjectFetcher.java +++ /dev/null @@ -1,208 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import net.aufdemrand.denizen.scripts.queues.ScriptQueue; -import net.aufdemrand.denizen.utilities.debugging.dB; -import net.aufdemrand.denizen.utilities.depends.Depends; -import org.apache.commons.lang3.StringUtils; - -/** - * - * @author Jeremy Schroeder - * - */ - -public class ObjectFetcher { - - // Keep track of each Class keyed by its 'object identifier' --> i@, e@, etc. - private static Map objects = new HashMap(); - - // Keep track of the static 'matches' and 'valueOf' methods for each dObject - static Map matches = new WeakHashMap(); - static Map valueof = new WeakHashMap(); - - public static void _initialize() throws IOException, ClassNotFoundException { - - if (fetchable_objects.isEmpty()) - return; - - Map adding = new HashMap(); - for (Class dClass : fetchable_objects) { - try { - Method method = dClass.getMethod("valueOf", String.class); - if (method.isAnnotationPresent(Fetchable.class)) { - String[] identifiers = method.getAnnotation(Fetchable.class).value().split(","); - for (String identifier : identifiers) - adding.put(identifier.trim().toLowerCase(), dClass); - } - } - catch (Throwable e) { - dB.echoError("Failed to initialize an object type(" + dClass.getSimpleName() + "): "); - dB.echoError(e); - } - } - - objects.putAll(adding); - dB.echoApproval("Added objects to the ObjectFetcher " + adding.keySet().toString()); - fetchable_objects.clear(); - } - - public static void _registerCoreObjects() throws NoSuchMethodException, ClassNotFoundException, IOException { - - // Initialize the ObjectFetcher - registerWithObjectFetcher(dItem.class); // i@ - registerWithObjectFetcher(dCuboid.class); // cu@ - registerWithObjectFetcher(dEntity.class); // e@ - registerWithObjectFetcher(dInventory.class); // in@ - registerWithObjectFetcher(dColor.class); // co@ - registerWithObjectFetcher(dList.class); // li@/fl@ - registerWithObjectFetcher(dLocation.class); // l@ - registerWithObjectFetcher(dMaterial.class); // m@ - if (Depends.citizens != null) - registerWithObjectFetcher(dNPC.class); // n@ - registerWithObjectFetcher(dPlayer.class); // p@ - registerWithObjectFetcher(dScript.class); // s@ - registerWithObjectFetcher(dWorld.class); // w@ - registerWithObjectFetcher(Element.class); // el@ - registerWithObjectFetcher(Duration.class); // d@ - registerWithObjectFetcher(dChunk.class); // ch@ - registerWithObjectFetcher(dPlugin.class); // pl@ - registerWithObjectFetcher(ScriptQueue.class);// q@ - registerWithObjectFetcher(dEllipsoid.class); // ellipsoid@ - - _initialize(); - - } - - private static ArrayList fetchable_objects = new ArrayList(); - - public static void registerWithObjectFetcher(Class dObject) { - try { - fetchable_objects.add(dObject); - matches.put(dObject, dObject.getMethod("matches", String.class)); - valueof.put(dObject, dObject.getMethod("valueOf", String.class)); - } - catch (Throwable e) { - dB.echoError("Failed to register an object type (" + dObject.getSimpleName() + "): "); - dB.echoError(e); - } - } - - public static boolean canFetch(String id) { - return objects.containsKey(id.toLowerCase()); - } - - public static Class getObjectClass(String id) { - if (canFetch(id)) - return objects.get(id.toLowerCase()); - else - return null; - } - - final static Pattern PROPERTIES_PATTERN = Pattern.compile("([^\\[]+)\\[(.+=.+)\\]", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE); - - public final static Pattern DESCRIBED_PATTERN = - Pattern.compile("[^\\[]+\\[.+=.+\\]", Pattern.DOTALL | Pattern.MULTILINE); - - public static boolean checkMatch(Class dClass, String value) { - if (value == null || dClass == null) - return false; - Matcher m = PROPERTIES_PATTERN.matcher(value); - try { - return (Boolean) matches.get(dClass).invoke(null, m.matches() ? m.group(1): value); - } catch (Exception e) { - dB.echoError(e); - } - - return false; - - } - - public static T getObjectFrom(Class dClass, String value) { - return getObjectFrom(dClass, value, null, null); - } - - public static List separateProperties(String input) { - if (input.indexOf('[') == -1 || input.lastIndexOf(']') != input.length() - 1) - return null; - ArrayList output = new ArrayList(); - int start = 0; - boolean needObject = true; - int brackets = 0; - for (int i = 0; i < input.length(); i++) { - if (input.charAt(i) == '[' && needObject) { - needObject = false; - output.add(input.substring(start, i)); - start = i + 1; - } - else if (input.charAt(i) == '[') { - brackets++; - } - else if (input.charAt(i) == ']' && brackets > 0) { - brackets--; - } - else if ((input.charAt(i) == ';' || input.charAt(i) == ']') && brackets == 0) { - output.add((input.substring(start, i))); - start = i + 1; - } - } - return output; - } - - public static T getObjectFrom(Class dClass, String value, dPlayer player, dNPC npc) { - try { - List matches = separateProperties(value); - boolean matched = matches != null && Adjustable.class.isAssignableFrom(dClass); - T gotten = (T) ((dClass.equals(dItem.class)) ? dItem.valueOf(matched ? matches.get(0): value, player, npc): - valueof.get(dClass).invoke(null, matched ? matches.get(0): value)); - if (gotten != null && matched) { - for (int i = 1; i < matches.size(); i++) { - String[] data = StringUtils.split(matches.get(i), "=", 2); - if (data.length != 2) { - dB.echoError("Invalid property string '" + matches.get(i) + "'!"); - continue; - } - ((Adjustable) gotten).applyProperty(new Mechanism(new Element(data[0]), - new Element(data[1].replace((char)0x2011, ';')))); - } - } - return gotten; - } catch (Exception e) { - dB.echoError(e); - } - - return null; - } - - /** - * This function will return the most-valid dObject for the input string. - * If the input lacks @ notation or is not a valid object, an Element will be returned. - * - * @param value the input string. - * @return the most-valid dObject available. - */ - public static dObject pickObjectFor(String value) { - // While many inputs are valid as various object types - // (EG, 'bob' could be a player or NPC's name) - // Only use specific objects for input with @ notation - if (value.contains("@")) { - String type = value.split("@", 2)[0]; - // Of course, ensure the @ notation is valid first - if (canFetch(type)) { - Class toFetch = getObjectClass(type); - dObject fetched = getObjectFrom(toFetch, value); - // Only return if a valid object is born... otherwise, use an element. - if (fetched != null) { - return fetched; - } - } - } - // If all else fails, just use a simple Element! - return new Element(value); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/aH.java b/src/main/java/net/aufdemrand/denizen/objects/aH.java deleted file mode 100644 index 782520cc82..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/aH.java +++ /dev/null @@ -1,721 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import net.aufdemrand.denizen.scripts.ScriptRegistry; -import net.aufdemrand.denizen.utilities.debugging.dB; - -import net.aufdemrand.denizencore.utilities.CoreUtilities; -import org.apache.commons.lang.StringUtils; -import org.bukkit.ChatColor; -import org.bukkit.entity.EntityType; - - -/** - * The dScript Argument Helper will aid you in parsing and formatting arguments from a - * dScript argument string (such as those found in a ScriptEntry.getArguments() method). - * - * @author aufdemrand - * - */ -public class aH { - - - //////////////////// - // Patterns and Enumerations - ///////////////// - - public enum PrimitiveType { Float, Double, Integer, Boolean, String, Word, Percentage } - - final static Pattern floatPrimitive = - Pattern.compile("^[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?$"); - - // <--[language] - // @name number - // @description - // Many arguments in Denizen require the use of a 'number', or 'double'. Sometimes referred to as #.# or , - // this kind of hint can generally be filled with any reasonable positive or negative number with or without a - // decimal point. Numbers can be verified with the 'if' commands' 'matches' functionality. - // For example: - if matches double ... will return true if is a valid number. - // - // Denizen uses the regular expression pattern -?(?:\d+)?(\.\d+)? for number matching. - // --> - final static Pattern doublePrimitive = - Pattern.compile("-?(?:\\d+)?(\\.\\d+)?"); - - // <--[language] - // @name percentage - // @description - // Promotes the usage of a 'percentage' format to be used in applicable arguments. The 'percentage' in Denizen is - // much like the 'number', except arguments which utilize percentages instead of numbers can also include a %. - // Percentage arguments can generally be filled with any reasonable positive or negative number with or without a - // decimal point and/or percentage sign. Argument hints and other usages will typically refer to a percentage as - // #.#% or . Percentages can be verified with the 'if' commands' 'matches' functionality. - // For example: - if matches percentage ... will return true if is a valid percentage. - // - // Denizen uses the regular expression pattern -?(?:\d+)?(\.\d+)?(%)? for percentage matching. - // --> - final static Pattern percentagePrimitive = - Pattern.compile("-?(?:\\d+)?(\\.\\d+)?(%)?"); - - final static Pattern integerPrimitive = - Pattern.compile("(-)?\\d+"); - - final static Pattern booleanPrimitive = - Pattern.compile("true|false", Pattern.CASE_INSENSITIVE); - - final static Pattern wordPrimitive = - Pattern.compile("\\w+"); - - - //////////////////// - // Argument Object - ////////////////// - - public static class Argument { - - public String raw_value; - String prefix = null; - String lower_prefix = null; - String value; - String lower_value; - boolean has_prefix = false; - - // Construction - public Argument(String string) { - raw_value = string; - string = string.trim(); - - int first_colon = string.indexOf(':'); - int first_space = string.indexOf(' '); - - if ((first_space > -1 && first_space < first_colon) || first_colon == -1) { - value = string; - lower_value = CoreUtilities.toLowerCase(string); - } - else { - has_prefix = true; - String[] split = StringUtils.split(string, ":", 2); - prefix = split[0]; - lower_prefix = CoreUtilities.toLowerCase(prefix); - if (split.length == 2) - value = split[1]; - else - value = ""; - lower_value = CoreUtilities.toLowerCase(value); - } - - } - - - public static Argument valueOf(String string) { - return new Argument(string); - } - - - public boolean startsWith(String string) { - return lower_value.startsWith(CoreUtilities.toLowerCase(string)); - } - - - public boolean hasPrefix() { - return has_prefix; - } - - - public Argument getPrefix() { - if (prefix == null) - return null; - return valueOf(prefix); - } - - - // TODO: REMOVE IN 1.0 - public boolean matches(String values) { - for (String value : StringUtils.split(values, ',')) { - if (CoreUtilities.toLowerCase(value.trim()).equals(lower_value)) - return true; - } - return false; - } - - public boolean matches(String... values) { - for (String value : values) { - if (CoreUtilities.toLowerCase(value).equals(lower_value)) - return true; - } - return false; - } - - - public void replaceValue(String string) { - value = string; - lower_value = CoreUtilities.toLowerCase(value); - } - - - public String getValue() { - return value; - } - - - public boolean matchesEnum(Enum[] values) { - for (Enum value : values) - if (value.name().replace("_", "").equalsIgnoreCase(this.value.replace("_", ""))) - return true; - - return false; - } - - - // Check if this argument matches a dList of Enum values - public boolean matchesEnumList(Enum[] values) { - dList list = dList.valueOf(this.value); - - for (String string : list) { - for (Enum value : values) - if (value.name().replace("_", "").equalsIgnoreCase(string.replace("_", ""))) - return true; - } - - return false; - } - - - // TODO: REMOVE IN 1.0 - public boolean matchesPrefix(String values) { - if (!hasPrefix()) return false; - for (String value : StringUtils.split(values, ',')) { - if (CoreUtilities.toLowerCase(value.trim()).equals(lower_prefix)) - return true; - } - return false; - } - - public boolean matchesPrefix(String... values) { - if (!hasPrefix()) return false; - for (String value : values) { - if (CoreUtilities.toLowerCase(value).equals(lower_prefix)) - return true; - } - return false; - } - - - public boolean matchesPrimitive(PrimitiveType argumentType) { - if (value == null) return false; - - switch (argumentType) { - case Word: - return wordPrimitive.matcher(value).matches(); - - case Integer: - return integerPrimitive.matcher(value).matches(); - - case Double: - return doublePrimitive.matcher(value).matches(); - - case Float: - return floatPrimitive.matcher(value).matches(); - - case Boolean: - return booleanPrimitive.matcher(value).matches(); - - case Percentage: - return percentagePrimitive.matcher(value).matches(); - - case String: - return true; - } - - return false; - } - - - // Check if this argument matches a certain dObject type - public boolean matchesArgumentType(Class dClass) { - return ObjectFetcher.checkMatch(dClass, value); - } - - - // Check if this argument matches any of multiple dObject types - public boolean matchesArgumentTypes(Class... dClasses) { - - for (Class c : dClasses) { - if (matchesArgumentType(c)) { - return true; - } - } - - return false; - } - - - // Check if this argument matches a dList of a certain dObject - public boolean matchesArgumentList(Class dClass) { - - dList list = dList.valueOf(this.value); - - return list.isEmpty() || list.containsObjectsFrom(dClass); - } - - - public Element asElement() { - return new Element(prefix, value); - } - - - public T asType(Class clazz) { - dObject arg = ObjectFetcher.getObjectFrom(clazz, value); - if (arg != null) { - arg.setPrefix(prefix); - return clazz.cast(arg); - } - return null; - } - - - public void reportUnhandled() { - dB.echoError('\'' + raw_value + "' is an unknown argument!"); - } - - - @Override - public String toString() { - return raw_value; - } - } - - ///////////////// - // Static Methods - /////////////// - - - /** - * Turns a list of string arguments (separated by buildArgs) into Argument - * Objects for easy matching and dObject creation throughout Denizen. - * - * @param args a list of string arguments - * @return a list of Arguments - */ - public static List interpret(List args) { - List arg_list = new ArrayList(); - for (String string : args) { - arg_list.add(new Argument(string.trim())); - } - return arg_list; - } - - private static final Pattern argsRegex = Pattern.compile("[^\\s\"'¨]+|\"([^\"]*)\"|'([^']*)'|¨([^¨]*)¨"); - - - /** - * Builds an arguments array, recognizing items in quotes as a single item, but - * otherwise splitting on a space. - * - * @param stringArgs the line of arguments that need split - * @return an array of arguments - * - */ - public static String[] buildArgs(String stringArgs) { - if (stringArgs == null) return null; - java.util.List matchList = new ArrayList(); - Matcher regexMatcher = argsRegex.matcher(stringArgs); - while (regexMatcher.find()) { - if (regexMatcher.group(1) != null) { - matchList.add(regexMatcher.group(1)); - } else if (regexMatcher.group(2) != null) { - matchList.add(regexMatcher.group(2)); - } else { - matchList.add(regexMatcher.group()); - } - } - - if (dB.showScriptBuilder) - dB.log(ChatColor.GRAY + "Constructed args: " + Arrays.toString(matchList.toArray())); - - return matchList.toArray(new String[matchList.size()]); - } - - /** - * To be used with the dBuggers' .report to provide debug output for - * objects that don't extend dObject. - * - * @param prefix name/type/simple description of the object being reported - * @param value object being reported will report the value of toString() - * - * @return color coded debug report - */ - public static String debugObj(String prefix, Object value) { - return "" + prefix + "='" + (value != null ? value.toString() : "null") + "' "; - } - - public static String debugList(String prefix, Collection objects) { - if (objects == null) - return debugObj(prefix, null); - StringBuilder sb = new StringBuilder(); - for (dObject obj: objects) { - String output = obj.debug(); - sb.append(output.substring((obj.getPrefix() + "='").length(), output.length() - 6)).append(", "); - } - if (sb.length() == 0) - return debugObj(prefix, sb); - else - return debugObj(prefix, "[" + sb.substring(0, sb.length() - 2) + "]"); - } - - /** - * To be used with the dBuggers' .report to provide debug output for - * objects that may have some kind of id or type also associated with - * the object. - * - * @param prefix name/type/simple description of the object being reported - * @param id additional id/type of the object - * @param value object being reported will report the value of toString() - * - * @return color coded debug report - */ - public static String debugUniqueObj(String prefix, String id, Object value) { - return "" + prefix + "='" + id + "(" + (value != null ? value.toString() : "null") + ")' "; - } - - - public enum ArgumentType { - LivingEntity, Item, Boolean, Custom, Double, Float, - Integer, String, Word, Location, Script, Duration - } - - - /** - *

Used to determine if a argument string matches a non-valued custom argument. - * If a dScript valued argument (such as TARGET:NAME) is passed, this method - * will always return false. Also supports multiple argument names, separated by a - * comma (,) character. This method will trim() each name specified.

- * - * Example use of 'aH.matchesArg("NOW, LATER", arg)': - *
    - * arg = "NOW" will return true.
    - * arg = "NEVER" will return false.
    - * arg = "LATER:8PM" will return false.
    - * arg = "LATER" will return true. - *
- * - * @param names the valid argument names to match - * @param string_arg the dScript argument string - * @return true if matched, false if not - * - */ - public static boolean matchesArg(String names, String string_arg) { - String[] parts = names.split(","); - if (parts.length == 1) { - if (string_arg.toUpperCase().equals(names.toUpperCase())) return true; - } else { - for (String string : parts) - if (string_arg.split(":")[0].equalsIgnoreCase(string.trim())) return true; - } - return false; - } - - - /** - *

Used to match a custom argument with a value. In practice, the standard - * arguments should be used whenever possible to keep things consistent across - * the entire 'dScript experience'. Should you need to use custom arguments, - * however, this method provides some support. After all, while using standard - * arguments is nice, you should never reach. Arguments should make as much - * sense to the user/script writer as possible.

- * - * Small code example: - *
    - * 0 if (aH.matchesValueArg("HARDNESS", arg, ArgumentType.Word))
    - * 1 try {
    - * 2 hardness = Hardness.valueOf(aH.getStringFrom(arg).toUpperCase());
    - * 3 } catch (Exception e) {
    - * 4 dB.echoError("Invalid HARDNESS!")
    - * 5 }
    - *
- * - *

Note: Like {@link #matchesArg(String, String)}, matchesValueArg(String) - * supports multiple argument names, separated by a comma (,) character. This method - * will trim() each name specified.

- * - *

Also requires a specified ArgumentType, which will filter the type of value - * to match to. If anything should be excepted as the value, or you plan - * on parsing the value yourself, use ArgumentType.Custom, otherwise use an - * an appropriate ArgumentType. See: {@link ArgumentType}.

- * - * Example use of 'aH.matchesValueArg("TIME", arg, ArgumentType.Integer)': - *
    - * arg = "TIME:60" will return true.
    - * arg = "90" will return false.
    - * arg = "TIME:8 o'clock" will return false.
    - * arg = "TIME:0" will return true. - *
- * - * @param names the desired name variations of the argument - * @param string_arg the dScript argument string - * @param type a valid ArgumentType, used for matching values - * @return true if matched, false otherwise - * - */ - @Deprecated - public static boolean matchesValueArg(String names, String string_arg, ArgumentType type) { - if (string_arg == null) return false; - - int firstColonIndex = string_arg.indexOf(':'); - if (firstColonIndex == -1) return false; - - String[] commaParts = names.split(","); - - if (commaParts.length == 1) { - if (!string_arg.substring(0,firstColonIndex).equalsIgnoreCase(names)) - return false; - } - - else { - boolean matched = false; - for (String string : commaParts) - if (string_arg.substring(0,firstColonIndex).equalsIgnoreCase(string.trim())) - matched = true; - if (!matched) return false; - } - - string_arg = string_arg.split(":", 2)[1]; - - switch (type) { - case Word: - return wordPrimitive.matcher(string_arg).matches(); - - case Integer: - return integerPrimitive.matcher(string_arg).matches(); - - case Double: - return doublePrimitive.matcher(string_arg).matches(); - - case Float: - return floatPrimitive.matcher(string_arg).matches(); - - case Boolean: - return booleanPrimitive.matcher(string_arg).matches(); - - case Location: - return dLocation.matches(string_arg); - - case Script: - // return dScript.matches(string_arg); - return true; - - case Item: - return dItem.matches(string_arg); - - case LivingEntity: - return dEntity.matches(string_arg); - - case Duration: - return Duration.matches(string_arg); - - case String: - return true; - - case Custom: - return true; - - } - - dB.echoError("While parsing '" + string_arg + "', Denizen has run into a problem. While the " + - "prefix is correct, the value is not valid. Check documentation for valid value." + - "Perhaps a replaceable tag has failed to fill in a value?"); - - return false; - } - - public static boolean getBooleanFrom(String arg) { - return Boolean.valueOf(getStringFrom(arg)); - } - - public static double getDoubleFrom(String arg) { - try { - return Double.valueOf(getStringFrom(arg)); - } catch (NumberFormatException e) { - return 0D; - } - } - - @Deprecated - public static EntityType getEntityTypeFrom(String arg) { - for (EntityType validEntity : EntityType.values()) - if (getStringFrom(arg).equalsIgnoreCase(validEntity.name())) - return validEntity; - - // No match - return null; - } - - @Deprecated - public static dEntity getEntityFrom(String arg) { - arg = arg.toLowerCase().replace("entity:", ""); - return dEntity.valueOf(arg); - } - - public static float getFloatFrom(String arg) { - try { - return Float.valueOf(getStringFrom(arg)); - } catch (NumberFormatException e) { - return 0f; - } - } - - public static int getIntegerFrom(String arg) { - try { - return Integer.valueOf(getStringFrom(arg)); - } catch (NumberFormatException e) { - return 0; - } - } - - @Deprecated - public static dItem getItemFrom(String arg) { - arg = arg.toLowerCase().replace("item:", ""); - return dItem.valueOf(arg); - } - - @Deprecated - public static dList getListFrom(String arg) { - return dList.valueOf(aH.getStringFrom(arg)); - } - - @Deprecated - public static dLocation getLocationFrom(String arg) { - arg = arg.toLowerCase().replace("location:", ""); - return dLocation.valueOf(arg); - } - - public static long getLongFrom(String arg) { - try { - return Long.valueOf(getStringFrom(arg)); - } catch (NumberFormatException e) { - return 0; - } - } - - @Deprecated - public static dScript getScriptFrom(String arg) { - arg = arg.toLowerCase().replace("script:", ""); - return dScript.valueOf(arg); - } - - @Deprecated - public static dPlayer getPlayerFrom(String arg) { - return dPlayer.valueOf(aH.getStringFrom(arg)); - } - - @Deprecated - public static dNPC getNPCFrom(String arg) { - return dNPC.valueOf(aH.getStringFrom(arg)); - } - - public static String getStringFrom(String arg) { - String[] parts = arg.split(":", 2); - return parts.length >=2 ? parts[1] : arg; - } - - @Deprecated - public static Duration getDurationFrom(String arg) { - arg = arg.toLowerCase().replace("duration:", "").replace("delay:", ""); - return Duration.valueOf(arg); - } - - public static boolean matchesDouble(String arg) { - return doublePrimitive.matcher(arg).matches(); - } - - @Deprecated - public static boolean matchesDuration(String arg) { - arg = arg.toLowerCase().replace("duration:", "").replace("delay:", ""); - return Duration.matches(arg); - } - - public static boolean matchesEntityType(String arg) { - arg = arg.toLowerCase().replace("entity:", ""); - - // Check against valid EntityTypes using Bukkit's EntityType enum - for (EntityType validEntity : EntityType.values()) - if (arg.equalsIgnoreCase(validEntity.name())) - return true; - return false; - } - - public static boolean matchesInteger(String arg) { - return integerPrimitive.matcher(arg).matches(); - } - - @Deprecated - public static boolean matchesItem(String arg) { - if (arg.length() > 5 && arg.toUpperCase().startsWith("ITEM:")) - return true; - return false; - } - - @Deprecated - public static boolean matchesContext(String arg) { - if (arg.toUpperCase().startsWith("CONTEXT:") || - arg.toUpperCase().startsWith("DEFINE:")) return true; - return false; - } - - @Deprecated - public static Map getContextFrom(String arg) { - Map context = new HashMap(); - int x = 1; - for (String ctxt : aH.getListFrom(arg)) { - context.put(String.valueOf(x), ctxt.trim()); - x++; - } - return context; - } - - @Deprecated - public static boolean matchesLocation(String arg) { - return arg.toUpperCase().startsWith("LOCATION:"); - } - - @Deprecated - public static boolean matchesQuantity(String arg) { - return arg.toUpperCase().startsWith("QTY:"); - } - - @Deprecated - public static boolean matchesQueue(String arg) { - return arg.toUpperCase().startsWith("QUEUE:"); - } - - @Deprecated - public static boolean matchesScript(String arg) { - Matcher m = matchesScriptPtrn.matcher(arg); - if (m.matches()) { - if (ScriptRegistry.containsScript(m.group(1))) - return true; - else { - dB.echoError("While parsing '" + arg + "', Denizen has run into a problem. This " + - "argument's format is correct, but Denizen couldn't locate a script " + - "named '" + m.group(1) + "'. Is it spelled correctly?"); - } - } - return false; - } - - @Deprecated - public static boolean matchesState(String arg) { - final Pattern m = Pattern.compile("(state|toggle):(true|false|toggle)"); - if (m.matcher(arg).matches()) return true; - else if (arg.toUpperCase().startsWith("(state|toggle):")) - dB.echoError("While parsing '" + arg + "', Denizen has run into a problem. While the prefix is " + - "correct, the value is not valid. 'STATE' requires a value of TRUE, FALSE, or TOGGLE. "); - - return false; - } - - final static Pattern matchesScriptPtrn = Pattern.compile("script:(.+)", Pattern.CASE_INSENSITIVE); -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/dList.java b/src/main/java/net/aufdemrand/denizen/objects/dList.java deleted file mode 100644 index 80c3e8a283..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/dList.java +++ /dev/null @@ -1,1363 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import net.aufdemrand.denizen.BukkitScriptEntryData; -import net.aufdemrand.denizen.flags.FlagManager; -import net.aufdemrand.denizen.objects.properties.Property; -import net.aufdemrand.denizen.objects.properties.PropertyParser; -import net.aufdemrand.denizen.scripts.ScriptBuilder; -import net.aufdemrand.denizen.scripts.ScriptEntry; -import net.aufdemrand.denizen.scripts.ScriptRegistry; -import net.aufdemrand.denizen.scripts.commands.core.DetermineCommand; -import net.aufdemrand.denizen.scripts.containers.core.ProcedureScriptContainer; -import net.aufdemrand.denizen.scripts.queues.ScriptQueue; -import net.aufdemrand.denizen.scripts.queues.core.InstantQueue; -import net.aufdemrand.denizen.tags.Attribute; -import net.aufdemrand.denizen.tags.core.EscapeTags; -import net.aufdemrand.denizen.utilities.DenizenAPI; -import net.aufdemrand.denizen.utilities.NaturalOrderComparator; -import net.aufdemrand.denizen.utilities.debugging.dB; -import net.aufdemrand.denizen.utilities.depends.Depends; -import net.aufdemrand.denizencore.utilities.CoreUtilities; -import org.bukkit.ChatColor; - -import java.util.*; -import java.util.regex.Pattern; - -public class dList extends ArrayList implements dObject { - - public final static char internal_escape_char = (char)0x05; - public final static String internal_escape = String.valueOf(internal_escape_char); - - @Fetchable("li, fl") - public static dList valueOf(String string) { - if (string == null) return null; - - /////// - // Match @object format - - if (string.startsWith("fl")) { - FlagManager flag_manager = DenizenAPI.getCurrentInstance().flagManager(); - if (string.indexOf('[') == 2) { - int cb = string.indexOf(']'); - if (cb > 4 && string.indexOf('@') == (cb + 1)) { - String owner = string.substring(3, cb); - String flag = string.substring(cb + 2); - if (dPlayer.matches(owner)) { - dPlayer player = dPlayer.valueOf(owner); - if (FlagManager.playerHasFlag(player, flag)) - return new dList(flag_manager.getPlayerFlag(player, flag)); - else - dB.echoError("Player '" + owner + "' flag '" + flag + "' not found."); - } - else if (Depends.citizens != null && dNPC.matches(owner)) { - dNPC npc = dNPC.valueOf(owner); - if (FlagManager.npcHasFlag(npc, flag)) - return new dList(flag_manager.getNPCFlag(npc.getId(), flag)); - else - dB.echoError("NPC '" + owner + "' flag '" + flag + "' not found."); - } - } - else - dB.echoError("Invalid dFlag format: " + string); - } - else if (string.indexOf('@') == 2) { - String flag = string.substring(3); - if (FlagManager.serverHasFlag(flag)) - return new dList(flag_manager.getGlobalFlag(flag)); - else - dB.echoError("Global flag '" + flag + "' not found."); - } - else { - return new dList(string); - } - } - - // Use value of string, which will separate values by the use of a pipe '|' - return new dList(string.startsWith("li@") ? string.substring(3) : string); - } - - - public static boolean matches(String arg) { - - boolean flag = false; - - if (arg.startsWith("fl")) { - if (arg.indexOf('[') == 2) { - int cb = arg.indexOf(']'); - if (cb > 4 && arg.indexOf('@') == (cb + 1)) { - String owner = arg.substring(3, cb); - flag = arg.substring(cb + 2).length() > 0 && (dPlayer.matches(owner) - || (Depends.citizens != null && dNPC.matches(owner))); - } - } - else if (arg.indexOf('@') == 2) { - flag = arg.substring(3).length() > 0; - } - } - - return flag || arg.contains("|") || arg.contains(internal_escape) || arg.startsWith("li@"); - } - - - ///////////// - // Constructors - ////////// - - // A list of dObjects - public dList(Collection dObjectList) { - for (dObject obj : dObjectList) - add(obj.identify()); - } - - // Empty dList - public dList() { } - - // A string of items, split by '|' - public dList(String items) { - if (items != null && items.length() > 0) { - // Count brackets - int brackets = 0; - // Record start position - int start = 0; - // Loop through characters - for (int i = 0; i < items.length(); i++) { - char chr = items.charAt(i); - // Count brackets - if (chr == '[') { - brackets++; - } - else if (chr == ']') { - if (brackets > 0) brackets--; - } - // Separate if an un-bracketed pipe is found - else if ((brackets == 0) && (chr == '|' || chr == internal_escape_char)) { - add(items.substring(start, i)); - start = i + 1; - } - } - // If there is an item waiting, add it too - if (start < items.length()) { - add(items.substring(start, items.length())); - } - } - } - - // A List of items - public dList(List items) { - if (items != null) addAll(items); - } - - // A Set of items - public dList(Set items) { - if (items != null) addAll(items); - } - - // A List of items, with a prefix - public dList(List items, String prefix) { - for (String element : items) { - add(prefix + element); - } - } - - // A Flag - public dList(FlagManager.Flag flag) { - this.flag = flag; - addAll(flag.values()); - } - - - ///////////// - // Instance Fields/Methods - ////////// - - private FlagManager.Flag flag = null; - - - /** - * Adds a list of dObjects to a dList by forcing each to 'identify()'. - * - * @param dObjects the List of dObjects - * @return a dList - */ - public dList addObjects(List dObjects) { - for (dObject obj : dObjects) { - add(obj.identify()); - } - - return this; - } - - /** - * Fetches a String Array copy of the dList, - * with the same size as the dList. - * - * @return the array copy - */ - public String[] toArray() { - return toArray(size()); - } - - /** - * Fetches a String Array copy of the dList. - * - * @param arraySize the size of the new array - * @return the array copy - */ - public String[] toArray(int arraySize) { // TODO: Why does this exist? - List list = new ArrayList(); - - for (String string : this) { - list.add(string); // TODO: Why is this a manual copy? - } - - return list.toArray(new String[arraySize]); - } - - - // Returns if the list contains objects from the specified dClass - // by using the matches() method. - public boolean containsObjectsFrom(Class dClass) { - - // Iterate through elements until one matches() the dClass - for (String element : this) - if (ObjectFetcher.checkMatch(dClass, element)) - return true; - - return false; - } - - - /** - * Return a new list that includes only strings that match the values of an Enum array - * - * @param values the Enum's value - * @return a filtered list - */ - public List filter(Enum[] values) { - List list = new ArrayList(); - - for (String string : this) { - for (Enum value : values) - if (value.name().equalsIgnoreCase(string)) - list.add(string); - } - - if (!list.isEmpty()) - return list; - else return null; - } - - - // Return a list that includes only elements belonging to a certain class - public List filter(Class dClass) { - return filter(dClass, null); - } - - - public List filter(Class dClass, ScriptEntry entry) { - List results = new ArrayList(); - - for (String element : this) { - - try { - if (ObjectFetcher.checkMatch(dClass, element)) { - - T object = ObjectFetcher.getObjectFrom(dClass, element, - (entry != null ? ((BukkitScriptEntryData)entry.entryData).getPlayer(): null), - (entry != null ? ((BukkitScriptEntryData)entry.entryData).getNPC(): null)); - - // Only add the object if it is not null, thus filtering useless - // list items - - if (object != null) { - results.add(object); - } - } - } catch (Exception e) { - dB.echoError(e); - } - } - - return results; - } - - - @Override - public String toString() { - return identify(); - } - - - ////////////////////////////// - // DSCRIPT ARGUMENT METHODS - ///////////////////////// - - - private String prefix = "List"; - - @Override - public String getPrefix() { - return prefix; - } - - @Override - public dList setPrefix(String prefix) { - this.prefix = prefix; - return this; - } - - @Override - public String debug() { - return "" + prefix + "='" + identify() + "' "; - } - - @Override - public boolean isUnique() { - return flag != null; - } - - @Override - public String getObjectType() { - return "List"; - } - - @Override - public String identify() { - if (flag != null) - return flag.toString(); - - if (isEmpty()) return "li@"; - - StringBuilder dScriptArg = new StringBuilder(); - dScriptArg.append("li@"); - for (String item : this) { - dScriptArg.append(item); - // Items are separated by the | character in dLists - dScriptArg.append('|'); - } - - return dScriptArg.toString().substring(0, dScriptArg.length() - 1); - } - - - @Override - public String identifySimple() { - return identify(); - } - - - @Override - public String getAttribute(Attribute attribute) { - - if (attribute == null) return null; - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // returns a list of the specified sub items in the list, as split by the - // forward-slash character (/). - // EG, .get_sub_items[1] on a list of "one/alpha|two/beta" will return "one|two". - // --> - - if (attribute.startsWith("get_sub_items")) { - int index = -1; - if (aH.matchesInteger(attribute.getContext(1))) - index = attribute.getIntContext(1) - 1; - attribute.fulfill(1); - - - // <--[tag] - // @attribute ].split_by[]> - // @returns dList - // @description - // returns a list of the specified sub item in the list, allowing you to specify a - // character in which to split the sub items by. WARNING: When setting your own split - // character, make note that it is CASE SENSITIVE. - // EG, .get_sub_items[1].split_by[-] on a list of "one-alpha|two-beta" will return "one|two". - // --> - - String split = "/"; - if (attribute.startsWith("split_by")) { - if (attribute.hasContext(1) && attribute.getContext(1).length() > 0) - split = attribute.getContext(1); - attribute.fulfill(1); - } - - if (index < 0) - return null; - - dList sub_list = new dList(); - - for (String item : this) { - String[] strings = item.split(Pattern.quote(split)); - if (strings.length > index) - sub_list.add(strings[index]); - else sub_list.add("null"); - } - - return sub_list.getAttribute(attribute); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // Returns the sub-list split by the / symbol's - // value for the matching input element. - // TODO: Clarify - // EG: li@one/a|two/b.map_get[one] returns a. - // --> - - if (attribute.startsWith("map_get") - && attribute.hasContext(1)) { - String input = attribute.getContext(1); - attribute.fulfill(1); - - - // <--[tag] - // @attribute ].split_by[]> - // @returns dList - // @description - // Returns the sub-list split by the given symbol's - // value for the matching input element. - // TODO: Clarify - // EG: li@one/a|two/b.map_get[one] returns a. - // --> - - String split = "/"; - if (attribute.startsWith("split_by")) { - if (attribute.hasContext(1) && attribute.getContext(1).length() > 0) - split = attribute.getContext(1); - attribute.fulfill(1); - } - - for (String item : this) { - String[] strings = item.split(Pattern.quote(split), 2); - if (strings.length > 1 && strings[0].equalsIgnoreCase(input)) { - return new Element(strings[1]).getAttribute(attribute); - } - } - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the list in a cleaner format, separated by commas. - // EG, a list of "one|two|three" will return "one, two, three". - // --> - if (attribute.startsWith("comma_separated") - || attribute.startsWith("ascslist") - || attribute.startsWith("as_cslist")) { - if (isEmpty()) return new Element("").getAttribute(attribute.fulfill(1)); - StringBuilder dScriptArg = new StringBuilder(); - for (String item : this) { - dScriptArg.append(item); - // Insert a comma and space after each item - dScriptArg.append(", "); - } - return new Element(dScriptArg.toString().substring(0, dScriptArg.length() - 2)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the list in a cleaner format, separated by spaces. - // EG, a list of "one|two|three" will return "one two three". - // --> - if (attribute.startsWith("space_separated")) { - if (isEmpty()) return new Element("").getAttribute(attribute.fulfill(1)); - StringBuilder dScriptArg = new StringBuilder(); - for (String item : this) { - dScriptArg.append(item); - // Insert a space after each item - dScriptArg.append(" "); - } - return new Element(dScriptArg.toString().substring(0, dScriptArg.length() - 1)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the list in a less clean format, separated by nothing. - // EG, a list of "one|two|three" will return "onetwothree". - // --> - if (attribute.startsWith("unseparated")) { - if (isEmpty()) return new Element("").getAttribute(attribute.fulfill(1)); - StringBuilder dScriptArg = new StringBuilder(); - for (String item : this) { - dScriptArg.append(item); - } - return new Element(dScriptArg.toString()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the list in a human-readable format. - // EG, a list of "n@3|p@bob|potato" will return "GuardNPC, bob, and potato". - // --> - if (attribute.startsWith("formatted")) { - if (isEmpty()) return new Element("").getAttribute(attribute.fulfill(1)); - StringBuilder dScriptArg = new StringBuilder(); - - for (int n = 0; n < this.size(); n++) { - if (get(n).startsWith("p@")) { - dPlayer gotten = dPlayer.valueOf(get(n)); - if (gotten != null) { - dScriptArg.append(gotten.getName()); - } - else { - dScriptArg.append(get(n).replaceAll("\\w+@", "")); - } - } - else if (get(n).startsWith("e@") || get(n).startsWith("n@")) { - dEntity gotten = dEntity.valueOf(get(n)); - if (gotten != null) { - dScriptArg.append(gotten.getName()); - } - else { - dScriptArg.append(get(n).replaceAll("\\w+@", "")); - } - } - else { - dScriptArg.append(get(n).replaceAll("\\w+@", "")); - } - - if (n == this.size() - 2) { - dScriptArg.append(n == 0 ? " and ": ", and "); - } - else { - dScriptArg.append(", "); - } - } - - return new Element(dScriptArg.toString().substring(0, dScriptArg.length() - 2)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element(Number) - // @description - // returns the size of the list. - // EG, a list of "one|two|three" will return "3". - // --> - if (attribute.startsWith("size")) - return new Element(size()).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element(Boolean) - // @description - // returns whether the list is empty. - // --> - if (attribute.startsWith("is_empty")) - return new Element(isEmpty()).getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns each item in the list as a single 'String'. - // EG, a list of "one|two|three" will return "one two three". - // --> - if (attribute.startsWith("asstring") - || attribute.startsWith("as_string")) { - if (isEmpty()) return new Element("").getAttribute(attribute.fulfill(1)); - StringBuilder dScriptArg = new StringBuilder(); - for (String item : this) { - dScriptArg.append(item); - // Insert space between items. - dScriptArg.append(' '); - } - return new Element(dScriptArg.toString().substring(0, dScriptArg.length() - 1)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // returns a new dList with the items specified inserted to the specified location. - // EG, .insert[two|three].at[2] on a list of "one|four" will return "one|two|three|four". - // --> - if (attribute.startsWith("insert") && - attribute.hasContext(1)) { - dList items = dList.valueOf(attribute.getContext(1)); - attribute = attribute.fulfill(1); - if (attribute.startsWith("at") - && attribute.hasContext(1)) { - dList result = new dList(this); - int index = new Element(attribute.getContext(1)).asInt() - 1; - if (index < 0) - index = 0; - if (index > result.size()) - index = result.size(); - for (int i = 0; i < items.size(); i++) { - result.add(index + i, items.get(i)); - } - return result.getAttribute(attribute.fulfill(1)); - } - else { - dB.echoError("The tag li@list.insert[...] must be followed by .at[#]!"); - return null; - } - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // returns a new dList with the items specified inserted to the specified location, replacing the element - // already at that location. - // EG, .set[potato].at[2] on a list of "one|two|three" will return "one|potato|three". - // --> - if (attribute.startsWith("set") && - attribute.hasContext(1)) { - if (this.size() == 0) - return null; - dList items = dList.valueOf(attribute.getContext(1)); - attribute = attribute.fulfill(1); - if (attribute.startsWith("at") - && attribute.hasContext(1)) { - dList result = new dList(this); - int index = new Element(attribute.getContext(1)).asInt() - 1; - if (index < 0) - index = 0; - if (index > result.size() - 1) - index = result.size() - 1; - result.remove(index); - for (int i = 0; i < items.size(); i++) { - result.add(index + i, items.get(i)); - } - return result.getAttribute(attribute.fulfill(1)); - } - else { - dB.echoError("The tag li@list.set[...] must be followed by .at[#]!"); - return null; - } - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // returns a new dList including the items specified. - // EG, .include[three|four] on a list of "one|two" will return "one|two|three|four". - // --> - if (attribute.startsWith("include") && - attribute.hasContext(1)) { - dList list = new dList(this); - list.addAll(dList.valueOf(attribute.getContext(1))); - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // returns a new dList excluding the items specified. - // EG, .exclude[two|four] on a list of "one|two|three|four" will return "one|three". - // --> - if (attribute.startsWith("exclude") && - attribute.hasContext(1)) { - dList exclusions = dList.valueOf(attribute.getContext(1)); - // Create a new dList that will contain the exclusions - dList list = new dList(this); - // Iterate through - for (String exclusion : exclusions) { - for (int i = 0;i < list.size();i++) { - if (list.get(i).equalsIgnoreCase(exclusion)) { - list.remove(i--); - } - } - } - - // Return the modified list - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute |...]> - // @returns dList - // @description - // returns a new dList excluding the items at the specified index. - // EG, .remove[2] on a list of "one|two|three|four" will return "one|three|four". - // --> - if (attribute.startsWith("remove") && - attribute.hasContext(1)) { - dList indices = dList.valueOf(attribute.getContext(1)); - dList list = new dList(this); - for (String index: indices) { - int remove = new Element(index).asInt() - 1; - if (remove >= 0 && remove < list.size()) { - list.set(remove, "\0"); - } - } - for (int i = 0; i < list.size(); i++) { - if (list.get(i).equals("\0")) - list.remove(i--); - } - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // returns a copy of the list, with all items placed in opposite order. - // EG, a list of "one|two|three" will become "three|two|one". - // --> - if (attribute.startsWith("reverse")) { - dList list = new dList(this); - Collections.reverse(list); - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // returns a copy of the list with any duplicate items removed. - // EG, a list of "one|one|two|three" will become "one|two|three". - // --> - if (attribute.startsWith("deduplicate")) { - dList list = new dList(); - int listSize = 0; - int size = this.size(); - for (int i = 0; i < size; i++) { - String entry = get(i); - boolean duplicate = false; - for (int x = 0; x < listSize; x++) { - if (get(x).equalsIgnoreCase(entry)) { - duplicate = true; - break; - } - } - if (!duplicate) { - list.add(entry); - listSize++; - } - } - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute |...]> - // @returns dObject - // @description - // returns an element of the value specified by the supplied context. - // EG, .get[1] on a list of "one|two" will return "one", and .get[2] will return "two" - // Specify more than one index to get a list of results. - // --> - if (attribute.startsWith("get") && - attribute.hasContext(1)) { - if (isEmpty()) return null; - dList indices = dList.valueOf(attribute.getContext(1)); - if (indices.size() > 1) { - dList results = new dList(); - for (String index: indices) { - int ind = aH.getIntegerFrom(index); - if (ind > 0 && ind <= size()) - results.add(get(ind - 1)); - } - return results.getAttribute(attribute.fulfill(1)); - } - if (indices.size() > 0) { - int index = aH.getIntegerFrom(indices.get(0)); - if (index > size()) return null; - if (index < 1) index = 1; - attribute = attribute.fulfill(1); - - // <--[tag] - // @attribute ].to[<#>]> - // @returns dList - // @description - // returns all elements in the range from the first index to the second. - // EG, .get[1].to[3] on a list of "one|two|three|four" will return "one|two|three" - // --> - if (attribute.startsWith("to") && - attribute.hasContext(1)) { - int index2 = attribute.getIntContext(1); - if (index2 > size()) index2 = size(); - if (index2 < 1) index2 = 1; - String item = ""; - for (int i = index; i <= index2; i++) { - item += get(i - 1) + (i < index2 ? "|": ""); - } - return new dList(item).getAttribute(attribute.fulfill(1)); - } - else { - String item; - item = get(index - 1); - return ObjectFetcher.pickObjectFor(item).getAttribute(attribute); - } - } - } - - // <--[tag] - // @attribute ]> - // @returns dList(Element(Number)) - // @description - // returns all the numbered locations of elements that contain the text within a list, - // or an empty list if the list does not contain that item. - // EG, .find_all_partial[tw] on a list of "one|two|three|two" will return "2|4". - // TODO: Take multiple inputs? Or a regex? - // --> - if (attribute.startsWith("find_all_partial") && - attribute.hasContext(1)) { - dList positions = new dList(); - for (int i = 0; i < size(); i++) { - if (get(i).toUpperCase().contains(attribute.getContext(1).toUpperCase())) - positions.add(String.valueOf(i + 1)); - } - return positions.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns dList(Element(Number)) - // @description - // returns all the numbered locations of elements that match the text within a list, - // or an empty list if the list does not contain that item. - // EG, .find[two] on a list of "one|two|three|two" will return "2|4". - // TODO: Take multiple inputs? Or a regex? - // --> - if (attribute.startsWith("find_all") && - attribute.hasContext(1)) { - dList positions = new dList(); - for (int i = 0; i < size(); i++) { - if (get(i).equalsIgnoreCase(attribute.getContext(1))) - positions.add(String.valueOf(i + 1)); - } - return positions.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Number) - // @description - // returns the numbered location of the first partially matching element within a list, - // or -1 if the list does not contain that item. - // EG, .find[two] on a list of "one|two|three" will return "2". - // TODO: Take multiple inputs? Or a regex? - // --> - if (attribute.startsWith("find_partial") && - attribute.hasContext(1)) { - for (int i = 0; i < size(); i++) { - if (get(i).toUpperCase().contains(attribute.getContext(1).toUpperCase())) - return new Element(i + 1).getAttribute(attribute.fulfill(1)); - } - return new Element(-1).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Number) - // @description - // returns the numbered location of an element within a list, - // or -1 if the list does not contain that item. - // EG, .find[two] on a list of "one|two|three" will return "2". - // TODO: Take multiple inputs? Or a regex? - // --> - if (attribute.startsWith("find") && - attribute.hasContext(1)) { - for (int i = 0; i < size(); i++) { - if (get(i).equalsIgnoreCase(attribute.getContext(1))) - return new Element(i + 1).getAttribute(attribute.fulfill(1)); - } - // TODO: This should be find_partial or something - /* - for (int i = 0; i < size(); i++) { - if (get(i).toUpperCase().contains(attribute.getContext(1).toUpperCase())) - return new Element(i + 1).getAttribute(attribute.fulfill(1)); - } - */ - return new Element(-1).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element(Number) - // @description - // returns how many times in the sub-list occurs. - // EG, a list of "one|two|two|three" .count[two] returns 2. - // --> - if (attribute.startsWith("count") && - attribute.hasContext(1)) { - String element = attribute.getContext(1); - int count = 0; - for (int i = 0; i < size(); i++) { - if (get(i).equalsIgnoreCase(element)) - count++; - } - return new Element(count).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the first element in the list. - // If the list is empty, returns null instead. - // EG, a list of "one|two|three" will return "one". - // Effectively equivalent to .get[1] - // --> - if (attribute.startsWith("first")) { - if (size() == 0) - return null; - else - return new Element(get(0)).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the last element in the list. - // If the list is empty, returns null instead. - // EG, a list of "one|two|three" will return "three". - // Effectively equivalent to .get[999999] - // --> - if (attribute.startsWith("last")) { - if (size() == 0) - return null; - else - return new Element(get(size() - 1)).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the list sorted to be in numerical order. - // EG, a list of "3|2|1|10" will return "1|2|3|10". - // --> - if (attribute.startsWith("numerical")) { - dList list = new dList(this); - Collections.sort(list, new Comparator() { - @Override - public int compare(String o1, String o2) { - double value = new Element(o1).asDouble() - new Element(o2).asDouble(); - if (value == 0) - return 0; - else if (value > 0) - return 1; - else - return -1; - } - }); - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the list sorted to be in alphabetical/numerical order. - // EG, a list of "b|c|a10|a1" will return "a1|a10|b|c". - // --> - if (attribute.startsWith("alphanumeric")) { - dList list = new dList(this); - Collections.sort(list, new NaturalOrderComparator()); - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // returns the list sorted to be in alphabetical order. - // EG, a list of "c|d|q|a|g" will return "a|c|d|g|q". - // --> - if (attribute.startsWith("alphabetical")) { - dList list = new dList(this); - Collections.sort(list, new Comparator() { - @Override - public int compare(String o1, String o2) { - return o1.compareToIgnoreCase(o2); - } - }); - return list.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @description - // returns a list sorted according to the return values of a procedure. - // The should link a procedure script that takes two definitions - // each of which will be an item in the list, and returns -1, 0, or 1 based on - // whether the second item should be added. EG, if a procedure with definitions - // "one" and "two" returned 1, it would place "two" after "one". Note that this - // uses some complex internal sorting code that could potentially throw errors - // if the procedure does not return consistently - EG, if "one" and "two" returned - // 1, but "two" and "one" returned 1 as well - obviously, "two" can not be both - // before AND after "one"! - // Note that the script should ALWAYS return -1, 0, or 1, or glitches will happen! - // Note that if two inputs are exactly equal, the procedure should always return 0. - // --> - if (attribute.startsWith("sort") - && attribute.hasContext(1)) { - final ProcedureScriptContainer script = ScriptRegistry.getScriptContainer(attribute.getContext(1)); - if (script == null) { - dB.echoError("'" + attribute.getContext(1) + "' is not a valid procedure script!"); - return getAttribute(attribute.fulfill(1)); - } - final ScriptEntry entry = attribute.getScriptEntry(); - List list = new ArrayList(this); - try { - Collections.sort(list, new Comparator() { - @Override - public int compare(String o1, String o2) { - List entries = script.getBaseEntries(entry.entryData.clone()); - if (entries.isEmpty()) { - return 0; - } - long id = DetermineCommand.getNewId(); - ScriptBuilder.addObjectToEntries(entries, "ReqId", id); - InstantQueue queue = InstantQueue.getQueue(ScriptQueue.getNextId("DLIST_SORT")); - queue.addEntries(entries); - queue.setReqId(id); - int x = 1; - dList definitions = new dList(); - definitions.add(o1); - definitions.add(o2); - String[] definition_names = null; - try { definition_names = script.getString("definitions").split("\\|"); } catch (Exception e) { /* IGNORE */ } - for (String definition : definitions) { - String name = definition_names != null && definition_names.length >= x ? - definition_names[x - 1].trim() : String.valueOf(x); - queue.addDefinition(name, definition); - dB.echoDebug(entry, "Adding definition %" + name + "% as " + definition); - x++; - } - queue.start(); - int res = 0; - if (DetermineCommand.hasOutcome(id)) - res = new Element(DetermineCommand.getOutcome(id).get(0)).asInt(); - if (res < 0) - return -1; - else if (res > 0) - return 1; - else - return 0; - } - }); - } - catch (Exception e) { - dB.echoError("list.sort[...] tag failed - procedure returned unreasonable valid - internal error: " + e.getMessage()); - } - return new dList(list).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // returns a copy of the list with all its contents parsed through the given tag and only including ones that returned 'true'. - // For example, a list of '1|2|3|4|5' .filter[is[or_more].than[3]] returns a list of '3|4|5'. - // --> - if (attribute.startsWith("filter") - && attribute.hasContext(1)) { - dList newlist = new dList(); - try { - for (String str: this) { - if (str == null) { - dB.echoError("Null string in dList! (From .filter tag)"); - } - String result = ObjectFetcher.pickObjectFor(str).getAttribute(new Attribute(attribute.getContext(1), - attribute.getScriptEntry())); - if (result != null && result.equalsIgnoreCase("true")) { - newlist.add(str); - } - } - } - catch (Exception ex) { - dB.echoError(ex); - } - return newlist.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // returns a copy of the list with all its contents parsed through the given tag. - // For example, a list of 'one|two' .parse[to_uppercase] returns a list of 'ONE|TWO'. - // --> - if (attribute.startsWith("parse") - && attribute.hasContext(1)) { - dList newlist = new dList(); - try { - for (String str: this) { - newlist.add(ObjectFetcher.pickObjectFor(str).getAttribute(new Attribute(attribute.getContext(1), - attribute.getScriptEntry()))); - } - } - catch (Exception ex) { - dB.echoError(ex); - } - return newlist.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // returns a copy of the list with all its contents escaped. - // Inverts <@link tag li@list.unescape_contents> - // See <@link language property escaping> - // --> - if (attribute.startsWith("escape_contents")) { - dList escaped = new dList(); - for (String entry: this) { - escaped.add(EscapeTags.Escape(entry)); - } - return escaped.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // returns a copy of the list with all its contents unescaped. - // Inverts <@link tag li@list.escape_contents> - // See <@link language property escaping> - // --> - if (attribute.startsWith("unescape_contents")) { - dList escaped = new dList(); - for (String entry: this) { - escaped.add(EscapeTags.unEscape(entry)); - } - return escaped.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute |...]> - // @returns Element(Boolean) - // @description - // returns whether the list contains any of a list of given elements, case-sensitive. - // --> - if (attribute.matches("contains_any_case_sensitive")) { - if (attribute.hasContext(1)) { - dList list = dList.valueOf(attribute.getContext(1)); - boolean state = false; - - full_set: - for (String element : this) { - for (String sub_element: list) { - if (element.equals(sub_element)) { - state = true; - break full_set; - } - } - } - - return new Element(state).getAttribute(attribute.fulfill(1)); - } - } - - // <--[tag] - // @attribute |...]> - // @returns Element(Boolean) - // @description - // returns whether the list contains any of a list of given elements. - // --> - if (attribute.matches("contains_any")) { - if (attribute.hasContext(1)) { - dList list = dList.valueOf(attribute.getContext(1)); - boolean state = false; - - full_set: - for (String element : this) { - for (String sub_element: list) { - if (element.equalsIgnoreCase(sub_element)) { - state = true; - break full_set; - } - } - } - - return new Element(state).getAttribute(attribute.fulfill(1)); - } - } - - // <--[tag] - // @attribute ]> - // @returns Element(Boolean) - // @description - // returns whether the list contains a given element, case-sensitive. - // --> - if (attribute.matches("contains_case_sensitive")) { - if (attribute.hasContext(1)) { - boolean state = false; - - for (String element : this) { - if (element.equals(attribute.getContext(1))) { - state = true; - break; - } - } - - return new Element(state).getAttribute(attribute.fulfill(1)); - } - } - - // <--[tag] - // @attribute |...]> - // @returns Element(Boolean) - // @description - // returns whether the list contains all of the given elements. - // --> - if (attribute.matches("contains") - && attribute.hasContext(1)) { - dList needed = dList.valueOf(attribute.getContext(1)); - int gotten = 0; - - for (String check: needed) { - for (String element : this) { - if (element.equalsIgnoreCase(check)) { - gotten++; - break; - } - } - } - - return new Element(gotten == needed.size()).getAttribute(attribute.fulfill(1)); - } - - if (attribute.startsWith("prefix")) - return new Element(prefix) - .getAttribute(attribute.fulfill(1)); - - if (attribute.startsWith("debug.log")) { - dB.log(debug()); - return new Element(Boolean.TRUE.toString()) - .getAttribute(attribute.fulfill(2)); - } - - if (attribute.startsWith("debug.no_color")) { - return new Element(ChatColor.stripColor(debug())) - .getAttribute(attribute.fulfill(2)); - } - - if (attribute.startsWith("debug")) { - return new Element(debug()) - .getAttribute(attribute.fulfill(1)); - } - - if (attribute.startsWith("identify")) { // TODO: ??? - return new Element(identify()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Always returns 'List' for dList objects. All objects fetchable by the Object Fetcher will return the - // type of object that is fulfilling this attribute. - // --> - if (attribute.startsWith("type")) { - return new Element("List").getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element - // @description - // Gets a random item in the list and returns it as an Element. - // Optionally, add [<#>] to get a list of multiple randomly chosen elements. - // EG, .random on a list of "one|two" could return EITHER "one" or "two" - different each time! - // EG, .random[2] on a list of "one|two|three" could return "one|two", "two|three", OR "one|three" - different each time! - // EG, .random[9999] on a list of "one|two|three" could return "one|two|three", "one|three|two", "two|one|three", - // "two|three|one", "three|two|one", OR "three|one|two" - different each time! - // --> - if (attribute.startsWith("random")) { - if (!this.isEmpty()) { - if (attribute.hasContext(1)) { - int count = Integer.valueOf(attribute.getContext(1)); - int times = 0; - ArrayList available = new ArrayList(); - available.addAll(this); - dList toReturn = new dList(); - while (!available.isEmpty() && times < count) { - int random = CoreUtilities.getRandom().nextInt(available.size()); - toReturn.add(available.get(random)); - available.remove(random); - times++; - } - return toReturn.getAttribute(attribute.fulfill(1)); - } - else { - return ObjectFetcher.pickObjectFor(this.get(CoreUtilities.getRandom().nextInt(this.size()))) - .getAttribute(attribute.fulfill(1)); - } - } - } - - // FLAG Specific Attributes - - // Note: is_expired attribute is handled in player/npc/server - // since expired flags return 'null' - - // <--[tag] - // @attribute - // @returns Element(Boolean) - // @description - // returns true of the flag is expired or does not exist, false if it - // is not yet expired, or has no expiration. - // --> - // NOTE: Defined in UtilTags.java - - // <--[tag] - // @attribute - // @returns Duration - // @description - // returns a Duration of the time remaining on the flag, if it - // has an expiration. - // --> - if (flag != null && attribute.startsWith("expiration")) { - return flag.expiration() - .getAttribute(attribute.fulfill(1)); - } - - // Need this attribute (for flags) since they return the last - // element of the list, unless '.as_list' is specified. - - // <--[tag] - // @attribute - // @returns dList - // @description - // returns a dList containing the items in the flag. - // --> - if (flag != null && (attribute.startsWith("as_list") - || attribute.startsWith("aslist"))) - return new dList(this).getAttribute(attribute.fulfill(1)); - - - // If this is a flag, return the last element (this is how it has always worked...) - // Use as_list to return a list representation of the flag. - // If this is NOT a flag, but instead a normal dList, return an element - // with dList's identify() value. - - // Iterate through this object's properties' attributes - for (Property property : PropertyParser.getProperties(this)) { - String returned = property.getAttribute(attribute); - if (returned != null) return returned; - } - - return (flag != null - ? new Element(flag.getLast().asString()).getAttribute(attribute) - : new Element(identify()).getAttribute(attribute)); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/dObject.java b/src/main/java/net/aufdemrand/denizen/objects/dObject.java deleted file mode 100644 index 878fde1b74..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/dObject.java +++ /dev/null @@ -1,279 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import net.aufdemrand.denizen.tags.Attribute; - -// <--[language] -// @name dObjects -// @group Object System -// @description -// dObjects are a system put into place by Denizen that make working with things, or 'objects', -// in Minecraft and Denizen easier. Many parts of scripts will require some kind of object as an -// argument, identifier/type, or such as in world events, part of an event name. The dObjects notation -// system helps both you and Denizen know what type of objects are being referenced and worked with. -// -// So when should you use dObjects? In arguments, event names, replaceable tags, configs, flags, and -// more! If you're just a beginner, you've probably been using them without even realizing it! -// -// dObject is a broader term for a 'type' of object that more specifically represents something, -// such as a dLocation or dScript, often times just referred to as a 'location' or 'script'. Denizen -// employs many object types that you should be familiar with. You'll notice that many times objects -// are reference with their 'dObject notation' which is in the format of 'x@', the x being the specific -// notation of an object type. Example: player objects use the p@ notation, and locations use l@. -// The use of this notation is encouraged, but not always required. -// -// Let's take the tag system, for example. It uses the dObjects system pretty heavily. For instance, -// every time you use or , you're using a dObject, which brings us to a simple -// clarification: Why and not ? That's because Denizen allows Players, -// NPCs and other 'in-context objects' to be linked to certain scripts. In short, already -// contains a reference to a specific player, such as the player that died in a world event 'on player dies'. -// would incorrectly reference the player named 'player', however this format is often -// used to help with usage of a tag, simply indicating 'any player object'. -// -// dObjects can be used to CREATE new instances of objects, too! Though not all types allow 'new' -// objects to be created, many do, such as dItems. With the use of tags, it's easy to reference a specific -// item, say -- an item in the Player's hand -- items are also able to use a constructor to make a new item, -// and say, drop it in the world. Take the case of the command/usage '- drop i@diamond_ore'. The item object -// used is a brand new diamond_ore, which is then dropped by the command to a location of your choice -- just -// specify an additional location argument. -// -// There's a great deal more to learn about dObjects, so be sure to check out each object type for more -// specific information. While all dObjects share some features, many contain goodies on top of that! -// -// Here's an overview of each object type that is implemented by the Denizen core: -// -// + ----- dPlayer ----- + -// | object notation: p@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | p@ - fetches an online or offline player with the specified UUID -// | p@ - Outdated constructor for back-support, fetches by name instead of UUID -// -// + ----- dNPC ---------+ -// | object notation: n@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | n@ - fetches the NPC with the specified ID -// | n@ - fetches the first NPC found with the specified name -// -// + ----- dLocation ----+ -// | object notation: l@ can reference unique objects: no can be notable: yes -// | constructors: ( <>'s represent non-static information and are not literal) -// | l@,,, - fetches a specific location -// | l@,,,,, - fetches a specific location and direction -// | l@ - fetches the location that has been 'noted' with the specified ID -// -// + ----- dEntity ------+ -// | object notation: e@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | e@ - fetches a new entity with the specified type as implemented by Bukkit's entity type enumeration -// | e@, - fetches a new entity of the specified type with a custom setting unique to the type -// | e@ - fetches a new custom entity as specified by the referenced entity script (soon) -// | e@ - fetches the entity that has the (temporary) entity ID set by Bukkit -// | e@random - fetches a new, random entity -// -// + ----- dItem --------+ -// | object notation: i@ can reference unique objects: no can be notable: yes -// | constructors: ( <>'s represent non-static information and are not literal) -// | i@ - fetches a new item of the specified material -// | i@, - fetches a new item with the specified data -// | i@ - fetches a new custom item as specified by the referenced item script -// | i@ - fetches the item that has been noted with the specified ID -// -// + ----- dWorld -------+ -// | object notation: w@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | w@ - fetches the world with the specified name -// -// + ----- dColor -------+ -// | object notation: co@ can reference unique objects: no can be notable: soon -// | constructors: ( <>'s represent non-static information and are not literal) -// | co@ - fetches a named color, as implemented by Bukkit's color enumeration -// | co@,, - fetches a color made of the specified Red,Green,Blue value -// | co@random - fetches a random color -// -// + ----- dCuboid ------+ -// | object notation: cu@ can reference unique objects: no can be notable: yes -// | constructors: ( <>'s represent non-static information and are not literal) -// | cu@||... - fetches a new cuboid encompassing a region from position 1 to 2, from 2 to 3, ... -// | cu@ - fetches the cuboid that has been noted with the specified ID -// -// + ----- dEllipsoid ------+ -// | object notation: ellipsoid@ can reference unique objects: no can be notable: yes -// | constructors: ( <>'s represent non-static information and are not literal) -// | ellipsoid@,,,,,,... - fetches a new ellispoid at the position with the given radius -// | cu@ - fetches the ellipsoid that has been noted with the specified ID -// -// + ----- dChunk ------+ -// | object notation: ch@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | ch@,, - fetches a chunk at the given chunk location -// -// + ----- dInventory ---+ -// | object notation: in@ can reference unique objects: yes can be notable: yes -// | constructors: ( <>'s represent non-static information and are not literal) -// | in@player[holder=] - fetches the specified Player's inventory (Works for offline players) -// | in@enderchest[holder=] - fetches the specified Player's enderchest inventory (Works for offline players) -// | in@npc[holder=] - fetches the specified NPC's inventory -// | in@entity[holder=] - fetches the specified object's inventory, such as a Player, NPC, or Mule -// | in@location[holder=] - fetches the contents of a chest or other 'inventory' block -// | in@ - fetches the inventory that has been 'noted' with the specified ID -// | in@ - fetches a new custom inventory as specified by the referenced inventory script -// | in@generic - represents a generic, customizable virtual inventory to be used with inventory properties (See <@link language Virtual Inventories>) -// -// + ----- dMaterial ----+ -// | object notation: m@ can reference unique objects: no can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | m@ - fetches the material as specified by Bukkit's material enumeration -// | m@, - fetches the material as specified by Bukkit's material enumeration with specified data -// | m@ - fetches the material specified by Denizen's 'data variety' dMaterials -// | m@random - fetches a random material -// -// + ----- dList -------+ -// | object notation: li@,fl@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | li@ - fetches a new list with the elements specified, separated by a pipe (|) character -// | li@val[] - slightly more verbose, but tag friendly way to fetch a new list (allows periods) -// | fl@ - fetches the flag list value of the specified server flag, as a dList -// | fl[ - fetches the flag list value of the specified player/NPC's flag, as a dList -// -// + ----- dScript -------+ -// | object notation: s@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | s@ - fetches the script container with the specified name -// -// + ----- Duration ------+ -// | object notation: d@ can reference unique objects: no can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | d@ - fetches a duration object with the specified amount of time -// | d@| - fetches a duration that is randomly selected between the specified 'low' and 'high' -// -// + ----- dPlugin -------+ -// | object notation: pl@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | pl@ - fetches the plugin with the specified name -// -// + ----- Element ------+ -// | object notation: el@ can reference unique objects: no can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | el@ - fetches an element with the specified value -// | el@val[] - slightly more verbose, but tag friendly way to fetch a new element (allows periods) -// -// + ----- Queue ------+ -// | object notation: q@ can reference unique objects: yes can be notable: no -// | constructors: ( <>'s represent non-static information and are not literal) -// | q@ - fetches the queue with the given ID -// -// --> - -public interface dObject { - - /** - * dObjects should contain these two static methods, of which valueOf contains a valid - * annotation for ObjectFetcher - * - * public static dObject valueOf(String string); - * - * valueOf() should take a string representation of the object, preferably with a valid object - * notation (x@), and turn it into a new instance of the dObject. Care has to be taken to - * ensure that it is compatible with the tag system (ie. no periods (.) outside of square brackets), - * and other parts of Denizen. - * - * Since your object may be using the dObject Attributes System, valueOf should take that into - * account as well. - * - * - * public static boolean matches() - * - * matches() should use some logic to determine if a string is in the proper format to possibly - * return a non-null valueOf() call. - * - */ - - - /** - * Retrieves the dScript argument prefix. dObjects should provide a default - * prefix if nothing else has been specified. - * - * @return the prefix - */ - public String getPrefix(); - - - /** - *

Gets a standard dB representation of this argument. All dObjects should follow - * suit.

- * - * Example:
- * - * Location='x,y,z,world' - * Location='unique_location(x,y,z,world)' - * - * - * - * @return the debug information - */ - public String debug(); - - - /** - * Determines if this argument object is unique. This typically stipulates - * that this object has been named, or has some unique identifier that - * Denizen can use to recall it. - * - * @return true if this object is unique, false if it is a 'singleton generic argument/object' - */ - public boolean isUnique(); - - - /** - * Returns the string type of the object. This is fairly verbose and crude, but used with - * a basic dScriptArg attribute. - * - * @return a straight-up string description of the type of dScriptArg. ie. dList, dLocation - */ - public String getObjectType(); - - - /** - * Gets an ugly, but exact, string representation of this dObject. - * While not specified in the dObject Interface, this value should be - * able to be used with a static valueOf(String) method to reconstruct the object. - * - * @return a single-line string representation of this argument - */ - public String identify(); - - - /** - * Gets an overall string representation of this dObject. - * This should give the basic jist of the object being identified, but - * won't include the exactness that identify() uses. - * - * - * Example: i@gold_sword vs. i@gold_sword[display_name=Shiny Sword] - * ^ ^ - * +--- identifySimple() +--- identify() - * - * - * This may produce the same results as identify(), depending on the complexity - * of the object being identified. - * - * @return a single-line, 'simple' string representation of this argument - */ - public String identifySimple(); - - - /** - * Sets the prefix for this argument, otherwise uses the default. - * - * @return the dObject - */ - public dObject setPrefix(String prefix); - - - /** - * Gets a specific attribute using this object to fetch the necessary data. - * - * @param attribute the name of the attribute - * @return a string result of the fetched attribute - */ - public String getAttribute(Attribute attribute); -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/dScript.java b/src/main/java/net/aufdemrand/denizen/objects/dScript.java deleted file mode 100644 index ed8567ae3a..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/dScript.java +++ /dev/null @@ -1,426 +0,0 @@ -package net.aufdemrand.denizen.objects; - -import java.util.List; - -import net.aufdemrand.denizen.objects.properties.Property; -import net.aufdemrand.denizen.objects.properties.PropertyParser; -import net.aufdemrand.denizen.scripts.ScriptRegistry; -import net.aufdemrand.denizen.scripts.containers.ScriptContainer; -import net.aufdemrand.denizen.tags.Attribute; -import net.aufdemrand.denizen.tags.BukkitTagContext; -import net.aufdemrand.denizen.tags.TagManager; -import net.aufdemrand.denizen.utilities.DenizenAPI; -import net.aufdemrand.denizen.utilities.debugging.dB; -import net.aufdemrand.denizencore.utilities.YamlConfiguration; -import org.json.JSONObject; - -public class dScript implements dObject { - - // <--[language] - // @name Script - // @description - // A somewhat vague term used to describe a collection of script entries and other script parts. - // - // For example, 'Hey, check out this script I just wrote!', probably refers to a collection of script entries - // that make up some kind of script container. Perhaps it is a NPC Assignment Script Container that provides - // waypoint functionality, or a world script that implements and keeps track of a new player stat. 'Script' can - // refer to a single container, as well as a collection of containers that share a common theme. - // - // Scripts that contain a collection of containers are typically kept to a single file. Multiple containers are - // permitted inside a single file, but it should be noted that container names are stored on a global level. That - // is, naming scripts should be done with care to avoid duplicate script names. - // - // --> - - // <--[language] - // @name dScript - // @group Object System - // @description - // 1) A dObject that represents a script container. dScripts contain all information inside the script, and can be - // used in a variety of commands that require script arguments. For example, run and inject will 'execute' - // script entries inside of a script container when given a matching dScript object. - // - // dScripts also provide a way to access attributes accessed by the replaceable tag system by using the object - // fetcher or any other entry point to a dScript object. dScript objects have the object identifier of 's@'. - // For example: s@script_name - // - // 2) The overall 'scripting language' that Denizen implements is referred to as 'dScripting', or 'dScript'. - // dScripts use YAML + Denizen's Scripting API to parse scripts that are stored as .yml or .dscript files. Scripts - // go in the .../plugins/Denizen/scripts folder. - // - // --> - - /////////////// - // Object Fetcher - ///////////// - - // <--[language] - // @name s@ - // @group Object Fetcher System - // @description - // s@ refers to the 'object identifier' of a dScript. The 's@' is notation for Denizen's Object - // Fetcher. The only valid constructor for a dScript is the name of the script container that it should be - // associated with. For example, if my script container is called 'cool_script', the dScript object for that script - // would be able to be referenced (fetched) with s@cool_script. - // --> - - - /** - * Gets a dContainer Object from a dScript argument. - * - * @param string the dScript argument String - * @return a Script, or null if incorrectly formatted - */ - @Fetchable("s") - public static dScript valueOf(String string) { - - if (string.startsWith("s@")) - string = string.substring(2); - - dScript script = new dScript(string); - // Make sure it's valid. - if (script.isValid()) - return script; - else - return null; - } - - - public static boolean matches(String string) { - - if (string.toLowerCase().startsWith("s@")) return true; - - dScript script = new dScript(string); - // Make sure it's valid. - return script.isValid(); - } - - ////////////////// - // Constructor - //////////////// - - - /** - * Creates a script object from a script name. If the script is valid, {@link #isValid()} will return true. - * - * @param scriptName the name of the script - */ - public dScript(String scriptName) { - if (ScriptRegistry.getScriptContainer(scriptName) != null) { - container = ScriptRegistry.getScriptContainer(scriptName); - name = scriptName.toUpperCase(); - valid = true; - } - } - - public dScript(ScriptContainer container) { - this.container = container; - name = container.getName().toUpperCase(); - valid = true; - } - - /////////////////////// - // Instance fields and methods - ///////////////////// - - // Keep track of the corresponding ScriptContainer - private ScriptContainer container; - - // Make the default prefix "Container" - private String prefix = "Container"; - - - private boolean valid = false; - - /** - * Confirms that the script references a valid name and type in current loaded ScriptsContainers. - * - * @return true if the script is valid, false if the script was not found, or the type is missing - */ - public boolean isValid() { - return valid; - } - - /** - * Gets the type of the ScriptContainer, as defined by the TYPE: key. - * - * @return the type of the Script Container - */ - public String getType() { - return (container != null ? container.getContainerType() : "invalid"); - } - - - private String name = null; - - /** - * Gets the name of the ScriptContainer. - * - * @return script name - */ - public String getName() { - return name; - } - - - /** - * Gets the contents of the scriptContainer. - * - * @return ConfigurationSection of the script contents - */ - public ScriptContainer getContainer() { - return container; - } - - /////////////// - // dObject Methods - //////////// - - @Override - public String getObjectType() { - return "Container"; - } - - @Override - public String identify() { - return "s@" + name; - } - - @Override - public String identifySimple() { - return identify(); - } - - @Override - public String toString() { - return identify(); - } - - @Override - public String getPrefix() { - return prefix; - } - - @Override - public dObject setPrefix(String prefix) { - this.prefix = prefix; - return this; - } - - @Override - public String debug() { - return String.format("%s='
%s(%s)' ", prefix, name, getType()); - } - - @Override - public boolean isUnique() { - return true; - } - - @Override - public String getAttribute(Attribute attribute) { - if (attribute == null) return "null"; - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the type of script container that is associated with this dScript object. For example: 'task', or - // 'world'. - // --> - if (attribute.startsWith("container_type")) - return new Element(container.getContainerType()) - .getAttribute(attribute.fulfill(1)); - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the name of the script container. - // --> - if (attribute.startsWith("name")) { - return new Element(name) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the filename that contains the script, relative to the denizen/ folder. - // --> - if (attribute.startsWith("relative_filename")) { - return new Element(container.getFileName().replace(DenizenAPI.getCurrentInstance().getDataFolder().getAbsolutePath(), "").replace("\\", "/")) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the absolute filename that contains the script. - // --> - if (attribute.startsWith("filename")) { - return new Element(container.getFileName().replace("\\", "/")) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the originally cased script name. - // --> - if (attribute.startsWith("original_name")) { - return new Element(container.getOriginalName()) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element or dList - // @description - // Returns the value of the constant as either an Element or dList. - // --> - if (attribute.startsWith("cons")) { - if (!attribute.hasContext(1)) return null; - - YamlConfiguration section = getContainer().getConfigurationSection("constants"); - if (section == null) return null; - Object obj = section.get(attribute.getContext(1).toUpperCase()); - if (obj == null) return null; - - if (obj instanceof List) { - dList list = new dList(); - for (Object each : (List) obj) { - if (each == null) { - each = "null"; - } - list.add(TagManager.tag(each.toString(), new BukkitTagContext(attribute.getScriptEntry(), false))); - } - return list.getAttribute(attribute.fulfill(1)); - - } - else return new Element(TagManager.tag(obj.toString(), new BukkitTagContext(attribute.getScriptEntry(), false))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns Element or dList - // @description - // Returns the value of the script's YAML as either an Element or dList. - // --> - if (attribute.startsWith("yaml_key") - && attribute.hasContext(1)) { - ScriptContainer container = getContainer(); - if (container == null) { - dB.echoError("Missing script container?!"); - return new Element(identify()).getAttribute(attribute); - } - YamlConfiguration section = container.getConfigurationSection(""); - if (section == null) { - dB.echoError("Missing YAML section?!"); - return new Element(identify()).getAttribute(attribute); - } - Object obj = section.get(attribute.getContext(1).toUpperCase()); - if (obj == null) return null; - - if (obj instanceof List) { - dList list = new dList(); - for (Object each : (List) obj) { - if (each == null) { - each = "null"; - } - list.add(TagManager.tag(each.toString(), new BukkitTagContext(attribute.getScriptEntry(), false))); - } - return list.getAttribute(attribute.fulfill(1)); - - } - else return new Element(TagManager.tag(obj.toString(), new BukkitTagContext(attribute.getScriptEntry(), false))) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // Returns a list of all keys within a script. - // --> - if (attribute.startsWith("list_keys")) { - return new dList(getContainer().getConfigurationSection(attribute.hasContext(1) ? attribute.getContext(1): "").getKeys(false)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // Returns a list of all keys within a script, searching recursively. - // --> - if (attribute.startsWith("list_deep_keys")) { - return new dList(getContainer().getConfigurationSection(attribute.hasContext(1) ? attribute.getContext(1): "").getKeys(true)) - .getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Converts the YAML Script Container to a JSON array. - // Best used with 'yaml data' type scripts. - // --> - if (attribute.startsWith("to_json")) { - JSONObject jsobj = new JSONObject(container.getConfigurationSection("").getMap()); - jsobj.remove("TYPE"); - return new Element(jsobj.toString()).getAttribute(attribute.fulfill(1)); - } - - ///////////////// - // dObject attributes - /////////////// - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the debug entry for this object. This contains the prefix, the name of the dScript object, and the - // type of ScriptContainer is held within. All objects fetchable by the Object Fetcher will return a valid - // debug entry for the object that is fulfilling this attribute. - // --> - if (attribute.startsWith("debug")) { - return new Element(debug()).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the prefix for this object. By default this will return 'Script', however certain situations will - // return a finer scope. All objects fetchable by the Object Fetcher will return a valid prefix for the object - // that is fulfilling this attribute. - // --> - if (attribute.startsWith("prefix")) { - return new Element(prefix).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Always returns 'Script' for dScript objects. All objects fetchable by the Object Fetcher will return the - // type of object that is fulfilling this attribute. - // --> - if (attribute.startsWith("type")) { - return new Element("Script").getAttribute(attribute.fulfill(1)); - } - - // Iterate through this object's properties' attributes - for (Property property : PropertyParser.getProperties(this)) { - String returned = property.getAttribute(attribute); - if (returned != null) return returned; - } - - return new Element(identify()).getAttribute(attribute); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/notable/Notable.java b/src/main/java/net/aufdemrand/denizen/objects/notable/Notable.java deleted file mode 100644 index dc3379005c..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/notable/Notable.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.aufdemrand.denizen.objects.notable; - -public interface Notable { - - public boolean isUnique(); - - /** - * Gets the object to be saved to the notables.yml. - * This should either be a String, or a ConfigurationSerializable object. - * - * @return the object to be saved - */ - public Object getSaveObject(); - - /** - * Saves the object in the NotableManager. Notable objects are saved through - * a server restart. - * - * @param id the id of the notable - */ - public void makeUnique(String id); - - public void forget(); -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/notable/Note.java b/src/main/java/net/aufdemrand/denizen/objects/notable/Note.java deleted file mode 100644 index 43cba80742..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/notable/Note.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.aufdemrand.denizen.objects.notable; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) - -public @interface Note { - String value(); -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/properties/Property.java b/src/main/java/net/aufdemrand/denizen/objects/properties/Property.java deleted file mode 100644 index f54d342d06..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/properties/Property.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.aufdemrand.denizen.objects.properties; - -import net.aufdemrand.denizen.objects.Mechanism; -import net.aufdemrand.denizen.tags.Attribute; - -public interface Property { - - public String getPropertyString(); - - public String getPropertyId(); - - public String getAttribute(Attribute attribute); - - public void adjust(Mechanism mechanism); -} diff --git a/src/main/java/net/aufdemrand/denizen/objects/properties/PropertyParser.java b/src/main/java/net/aufdemrand/denizen/objects/properties/PropertyParser.java deleted file mode 100644 index c65ca1b4fa..0000000000 --- a/src/main/java/net/aufdemrand/denizen/objects/properties/PropertyParser.java +++ /dev/null @@ -1,144 +0,0 @@ -package net.aufdemrand.denizen.objects.properties; - -import net.aufdemrand.denizen.objects.*; -import net.aufdemrand.denizen.objects.properties.bukkit.BukkitScriptProperties; -import net.aufdemrand.denizen.objects.properties.entity.*; -import net.aufdemrand.denizen.objects.properties.inventory.*; -import net.aufdemrand.denizen.objects.properties.item.*; -import net.aufdemrand.denizen.utilities.debugging.dB; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.*; - -public class PropertyParser { - - // Keep track of which Property belongs to which dObject - static Map, List> properties - = new HashMap, List>(); - - // Keep track of the static 'describes' and 'getFrom' methods for each Property - static Map describes = new WeakHashMap(); - static Map getFrom = new WeakHashMap(); - - - public PropertyParser() { - properties.clear(); - describes.clear(); - getFrom.clear(); - - // register properties that add Bukkit code to core objects - registerProperty(BukkitScriptProperties.class, dScript.class); - - // register core dEntity properties - registerProperty(EntityAge.class, dEntity.class); - registerProperty(EntityAngry.class, dEntity.class); - registerProperty(EntityColor.class, dEntity.class); - registerProperty(EntityCritical.class, dEntity.class); - registerProperty(EntityFirework.class, dEntity.class); - registerProperty(EntityFramed.class, dEntity.class); - registerProperty(EntityInfected.class, dEntity.class); - registerProperty(EntityItem.class, dEntity.class); - registerProperty(EntityJumpStrength.class, dEntity.class); - registerProperty(EntityKnockback.class, dEntity.class); - registerProperty(EntityPainting.class, dEntity.class); - registerProperty(EntityPotion.class, dEntity.class); - registerProperty(EntityPowered.class, dEntity.class); - registerProperty(EntityProfession.class, dEntity.class); - registerProperty(EntityRotation.class, dEntity.class); - registerProperty(EntitySitting.class, dEntity.class); - registerProperty(EntitySize.class, dEntity.class); - registerProperty(EntitySkeleton.class, dEntity.class); - registerProperty(EntityTame.class, dEntity.class); - - // register core dInventory properties - registerProperty(InventoryHolder.class, dInventory.class); // Holder must be loaded first to initiate correctly - registerProperty(InventorySize.class, dInventory.class); // Same with size...(Too small for contents) - registerProperty(InventoryContents.class, dInventory.class); - registerProperty(InventoryTitle.class, dInventory.class); - - // register core dItem properties - registerProperty(ItemApple.class, dItem.class); - registerProperty(ItemBook.class, dItem.class); - registerProperty(ItemDisplayname.class, dItem.class); - registerProperty(ItemDurability.class, dItem.class); - registerProperty(ItemDye.class, dItem.class); - registerProperty(ItemEnchantments.class, dItem.class); - registerProperty(ItemFirework.class, dItem.class); - registerProperty(ItemLore.class, dItem.class); - registerProperty(ItemMap.class, dItem.class); - registerProperty(ItemPlantgrowth.class, dItem.class); - registerProperty(ItemPotion.class, dItem.class); - registerProperty(ItemQuantity.class, dItem.class); - registerProperty(ItemSkullskin.class, dItem.class); - registerProperty(ItemSpawnEgg.class, dItem.class); - - } - - public void registerProperty(Class property, Class object) { - // Add property to the dObject's Properties list - List prop_list; - - // Get current properties list, or make a new one - if (properties.containsKey(object)) - prop_list = properties.get(object); - else prop_list = new ArrayList(); - - // Add this property to the list - prop_list.add(property); - - // Put the list back into the Map - properties.put(object, prop_list); - - // Cache methods used for fetching new properties - try { - describes.put(property, property.getMethod("describes", dObject.class)); - getFrom.put(property, property.getMethod("getFrom", dObject.class)); - - } catch (NoSuchMethodException e) { - dB.echoError("Unable to register property '" + property.getSimpleName() + "'!"); - } - - } - - public static String getPropertiesString(dObject object) { - StringBuilder prop_string = new StringBuilder(); - - // Iterate through each property associated with the dObject type, invoke 'describes' - // and if 'true', add property string from the property to the prop_string. - for (Property property: getProperties(object)) { - String description = property.getPropertyString(); - if (description != null) { - prop_string.append(property.getPropertyId()).append('=') - .append(description.replace(';', (char)0x2011)).append(';'); - } - } - - // Return the list of properties - if (prop_string.length() > 0) // Remove final semicolon - return "[" + prop_string.substring(0, prop_string.length() - 1) + "]"; - else - return ""; - } - - public static List getProperties(dObject object) { - List props = new ArrayList(); - - try { - if (properties.containsKey(object.getClass())) { - for (Class property : properties.get(object.getClass())) { - if ((Boolean) describes.get(property).invoke(null, object)) - props.add((Property) getFrom.get(property).invoke(null, object)); - } - } - - } catch (IllegalAccessException e) { - dB.echoError(e); - } catch (InvocationTargetException e) { - dB.echoError(e); - } - - return props; - - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/ScriptBuilder.java b/src/main/java/net/aufdemrand/denizen/scripts/ScriptBuilder.java deleted file mode 100644 index 665bcbecdf..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/ScriptBuilder.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.aufdemrand.denizen.scripts; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import net.aufdemrand.denizen.BukkitScriptEntryData; -import net.aufdemrand.denizen.objects.aH; -import net.aufdemrand.denizen.objects.dNPC; -import net.aufdemrand.denizen.objects.dPlayer; -import net.aufdemrand.denizen.scripts.containers.ScriptContainer; -import net.aufdemrand.denizen.utilities.debugging.dB; - -public class ScriptBuilder { - /** - * Adds an object to a list of ScriptEntries. Can later be retrieved from the ScriptEntry - * by using getObject(String key) - * - * @param scriptEntryList the list of ScriptEntries - * @param key the key (name) of the object being added - * @param obj the object - * - * @return the List of ScriptEntries, with the object added in each member - * - */ - public static List addObjectToEntries(List scriptEntryList, String key, Object obj) { - for (ScriptEntry entry : scriptEntryList) { - entry.addObject(key, obj); - entry.trackObject(key); - } - return scriptEntryList; - } - - /* - * Builds ScriptEntry(ies) of items read from a script - */ - - public static List buildScriptEntries(List contents, ScriptContainer parent, dPlayer player, dNPC npc) { - List scriptCommands = new ArrayList(); - - if (contents == null || contents.isEmpty()) { - if (dB.showScriptBuilder) - dB.echoError("Building script entries... no entries to build!"); - return null; - } - - if (dB.showScriptBuilder) - dB.echoDebug(parent, "Building script entries:"); - - for (String entry : contents) { - - - String[] scriptEntry = new String[2]; - String[] splitEntry = entry.split(" ", 2); - - if (splitEntry.length == 1) { - scriptEntry[0] = entry; - scriptEntry[1] = null; - } else { - scriptEntry = splitEntry; - } - - try { - /* Build new script commands */ - String[] args = aH.buildArgs(scriptEntry[1]); - if (dB.showScriptBuilder) - dB.echoDebug(parent, "Adding '" + scriptEntry[0] + "' Args: " + Arrays.toString(args)); - ScriptEntry newEntry = new ScriptEntry(scriptEntry[0], args, parent); - ((BukkitScriptEntryData)newEntry.entryData).setPlayer(player); - ((BukkitScriptEntryData)newEntry.entryData).setNPC(npc); - scriptCommands.add(newEntry); - } catch (Exception e) { - dB.echoError(e); - } - } - - return scriptCommands; - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/ScriptEntry.java b/src/main/java/net/aufdemrand/denizen/scripts/ScriptEntry.java deleted file mode 100644 index 673224ec0a..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/ScriptEntry.java +++ /dev/null @@ -1,382 +0,0 @@ -package net.aufdemrand.denizen.scripts; - -import java.util.*; - -import net.aufdemrand.denizencore.DenizenCore; -import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException; -import net.aufdemrand.denizencore.exceptions.ScriptEntryCreationException; -import net.aufdemrand.denizen.objects.Element; -import net.aufdemrand.denizen.objects.dObject; -import net.aufdemrand.denizen.objects.dScript; -import net.aufdemrand.denizen.scripts.commands.BracedCommand; -import net.aufdemrand.denizencore.scripts.ScriptEntryData; -import net.aufdemrand.denizencore.scripts.commands.BaseAbstractCommand; -import net.aufdemrand.denizencore.scripts.commands.Holdable; -import net.aufdemrand.denizen.scripts.containers.ScriptContainer; -import net.aufdemrand.denizen.scripts.queues.ScriptQueue; -import net.aufdemrand.denizencore.utilities.debugging.Debuggable; -import net.aufdemrand.denizencore.utilities.debugging.dB; - - -/** - * ScriptEntry contain information about a single entry from a dScript. It is used - * by the CommandExecuter, among other parts of Denizen. - * - * @author Jeremy Schroeder - * @version 1.0 - * - */ -public class ScriptEntry implements Cloneable, Debuggable { - - // The name of the command that will be executed - private String command; - private BaseAbstractCommand actualCommand; - - // Command Arguments - private List args; - private List pre_tagged_args; - - // TimedQueue features - private boolean instant = false; - private boolean waitfor = false; - - // 'Attached' core context - public ScriptEntryData entryData; - private dScript script = null; - private ScriptQueue queue = null; - - private LinkedHashMap> bracedSet = null; - - public LinkedHashMap> getBracedSet() { - return bracedSet; - } - - public void setBracedSet(LinkedHashMap> set) { - bracedSet = set; - } - - // ScriptEntry Context - private Map objects = new HashMap(); - - - // Allow cloning of the scriptEntry. Can be useful in 'loops', etc. - @Override - public ScriptEntry clone() throws CloneNotSupportedException { - ScriptEntry se = (ScriptEntry) super.clone(); - se.objects = new HashMap(); - se.entryData = entryData.clone(); - return se; - } - - - /** - * Get a hot, fresh, script entry, ready for execution! Just supply a valid command, - * some arguments, and bonus points for a script container (can be null)! - * - * @param command the name of the command this entry will be handed to - * @param arguments an array of the arguments - * @param script optional ScriptContainer reference - * @throws ScriptEntryCreationException if 'command' is null - */ - public ScriptEntry(String command, String[] arguments, ScriptContainer script) throws ScriptEntryCreationException { - - if (command == null) - throw new ScriptEntryCreationException("dCommand 'name' cannot be null!"); - - entryData = DenizenCore.getImplementation().getEmptyScriptEntryData(); - - this.command = command.toUpperCase(); - - // Knowing which script created this entry provides important context. We'll store - // a dScript object of the container if script is not null. - // Side note: When is script ever null? Think about situations such as the /ex command, - // in which a single script entry is created and sent to be executed. - if (script != null) - this.script = script.getAsScriptArg(); - - // Check if this is an 'instant' or 'waitfor' command. These are - // features that are used with 'TimedScriptQueues' - if (command.length() > 0) { - if (command.charAt(0) == '^') { - instant = true; - this.command = command.substring(1).toUpperCase(); - } - else if (command.charAt(0) == '~') { - this.command = command.substring(1).toUpperCase(); - // Make sure this command can be 'waited for' - if (DenizenCore.getCommandRegistry().get(this.command) - instanceof Holdable) { - waitfor = true; - } - else { - dB.echoError("The command '" + this.command + "' cannot be waited for!"); - } - } - actualCommand = DenizenCore.getCommandRegistry().get(this.command); - } - else { - actualCommand = null; - } - - // Store the args. The CommandExecuter will fill these out. - if (arguments != null) { - this.args = Arrays.asList(arguments); - // Keep seperate list for 'un-tagged' copy of the arguments. - // This will be useful if cloning the script entry for use in a loop, etc. - this.pre_tagged_args = Arrays.asList(arguments); - } else { - this.args = new ArrayList(); - this.pre_tagged_args = new ArrayList(); - } - - // Check for replaceable tags. We'll try not to make a habit of checking for tags/doing - // tag stuff if the script entry doesn't have any to begin with. - argLoop: for (String arg : args) { - boolean left = false, right = false; - for (int i = 0; i < arg.length(); i++) { - char c = arg.charAt(i); - if (c == '<') - left = true; - if (c == '>') - right = true; - if (left && right) { - has_tags = true; - break argLoop; - } - } - } - - if (actualCommand != null && actualCommand.isBraced() && actualCommand instanceof BracedCommand) { - BracedCommand.getBracedCommands(this); - } - } - - - // As explained, this is really just a micro-performance enhancer - public boolean has_tags = false; - - - /** - * Adds a context object to the script entry. Just provide a key and an object. - * Technically any type of object can be stored, however providing dObjects - * is preferred. - * - * @param key the name of the object - * @param object the object, preferably a dObject - */ - public ScriptEntry addObject(String key, Object object) { - if (object == null) return this; - if (object instanceof dObject) - ((dObject) object).setPrefix(key); - objects.put(key.toLowerCase(), object); - return this; - } - - - /** - * If the scriptEntry lacks the object corresponding to the - * key, set it to the first non-null argument - * - * @param key The key of the object to check - * @return The scriptEntry - */ - public ScriptEntry defaultObject(String key, Object... objects) throws InvalidArgumentsException { - if (!this.objects.containsKey(key.toLowerCase())) - for (Object obj : objects) - if (obj != null) { - this.addObject(key, obj); - break; - } - - // Check if the object has been filled. If not, throw new Invalid Arguments Exception. - // TODO: Should this be here? Most checks are done separately. - if (!hasObject(key)) throw new InvalidArgumentsException("Missing '" + key + "' argument!"); - else - return this; - } - - - public List getArguments() { - return args; - } - - //////////// - // INSTANCE METHODS - ////////// - - /** - * Gets the original, pre-tagged arguments, as constructed. This is simply a copy of - * the original arguments, immune from any changes that may be made (such as tag filling) - * by the CommandExecuter. - * - * @return unmodified arguments from entry creation - */ - public List getOriginalArguments() { - return pre_tagged_args; - } - - - public String getCommandName() { - return command; - } - - public BaseAbstractCommand getCommand() { - return actualCommand; - } - - - public ScriptEntry setArguments(List arguments) { - args = arguments; - return this; - } - - - public void setCommandName(String commandName) { - this.command = commandName; - } - - private ScriptEntry owner = null; - - public void setOwner(ScriptEntry owner) { - this.owner = owner; - } - - public ScriptEntry getOwner() { - return owner; - } - - private Object data; - - public Object getData() { - return data; - } - - public void setData(Object result) { - this.data = result; - } - - public void copyFrom(ScriptEntry entry) { - entryData = entry.entryData.clone(); - setSendingQueue(entry.getResidingQueue()); - } - - - ////////////////// - // SCRIPTENTRY CONTEXT - ////////////// - - public Map getObjects() { - return objects; - } - - - public Object getObject(String key) { - try { - return objects.get(key.toLowerCase()); - } catch (Exception e) { return null; } - } - - public T getdObject(String key) { - try { - // If an ENUM, return as an Element - Object gotten = objects.get(key.toLowerCase()); - if (gotten instanceof Enum) - return (T) new Element(((Enum) gotten).name()); - // Otherwise, just return the stored dObject - return (T) gotten; - // If not a dObject, return null - } catch (Exception e) { return null; } - } - - public Element getElement(String key) { - try { - return (Element) objects.get(key.toLowerCase()); - } catch (Exception e) { return null; } - } - - - public boolean hasObject(String key) { - return objects.containsKey(key.toLowerCase()); - } - - ///////////// - // CORE LINKED OBJECTS - /////// - - public dScript getScript() { - return script; - } - - - public ScriptEntry setScript(String scriptName) { - this.script = dScript.valueOf(scriptName); - return this; - } - - - public ScriptQueue getResidingQueue() { - return queue; - } - - - public void setSendingQueue(ScriptQueue scriptQueue) { - queue = scriptQueue; - } - - ////////////// - // TimedQueue FEATURES - ///////// - - - public boolean isInstant() { - return instant; - } - - - public ScriptEntry setInstant(boolean instant) { - this.instant = instant; - return this; - } - - public boolean shouldWaitFor() { - return waitfor; - } - - - public ScriptEntry setFinished(boolean finished) { - waitfor = !finished; - return this; - } - - //////////// - // COMPATIBILITY - ////////// - - // Keep track of objects which were added by mass - // so that IF can inject them into new entries. - // This is ugly, but it will keep from breaking - // previous versions of Denizen. - // TODO: Get rid of this - public List tracked_objects = new ArrayList(); - public ScriptEntry trackObject(String key) { - tracked_objects.add(key.toLowerCase()); - return this; - } - - ///////////// - // DEBUGGABLE - ///////// - - @Override - public boolean shouldDebug() { - if (script != null && script.getContainer() != null) - return script.getContainer().shouldDebug(); - else - return true; - } - - @Override - public boolean shouldFilter(String criteria) throws Exception { - return script.getName().equalsIgnoreCase(criteria.replace("s@", "")); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/ScriptEntrySet.java b/src/main/java/net/aufdemrand/denizen/scripts/ScriptEntrySet.java deleted file mode 100644 index 7da72363af..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/ScriptEntrySet.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.aufdemrand.denizen.scripts; - -import net.aufdemrand.denizen.utilities.debugging.dB; - -import java.util.ArrayList; -import java.util.List; - -public class ScriptEntrySet { - private List entries; - - public ScriptEntrySet(List baseEntries) { - entries = baseEntries; - } - - public ScriptEntrySet Duplicate() { - int count = entries.size(); - List newEntries = new ArrayList(count); - try { - for (ScriptEntry entry: entries) { - newEntries.add(entry.clone()); - } - } - catch (CloneNotSupportedException e) { - dB.echoError(e); // This should never happen - } - return new ScriptEntrySet(newEntries); - } - - public List getEntries() { - return entries; - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/ScriptRegistry.java b/src/main/java/net/aufdemrand/denizen/scripts/ScriptRegistry.java deleted file mode 100644 index 173657938c..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/ScriptRegistry.java +++ /dev/null @@ -1,138 +0,0 @@ -package net.aufdemrand.denizen.scripts; - -import net.aufdemrand.denizen.events.EventManager; -import net.aufdemrand.denizen.scripts.containers.ScriptContainer; -import net.aufdemrand.denizen.scripts.containers.core.*; -import net.aufdemrand.denizen.utilities.debugging.dB; -import net.aufdemrand.denizencore.DenizenCore; -import net.aufdemrand.denizencore.scripts.ScriptHelper; -import net.aufdemrand.denizencore.utilities.YamlConfiguration; - -import java.util.*; - -public class ScriptRegistry { - - // Currently loaded 'script-containers' - private static Map scriptContainers = new HashMap(); - private static Map> scriptContainerTypes = new HashMap>(); - - public static void _registerType(String typeName, Class scriptContainerClass) { - scriptContainerTypes.put(typeName.toUpperCase(), scriptContainerClass); - } - - public static Set _getScriptNames() { - return scriptContainers.keySet(); - } - - public static void _registerCoreTypes() { - _registerType("interact", InteractScriptContainer.class); - _registerType("book", BookScriptContainer.class); - _registerType("item", ItemScriptContainer.class); - _registerType("entity", EntityScriptContainer.class); - _registerType("task", TaskScriptContainer.class); - _registerType("assignment", AssignmentScriptContainer.class); - _registerType("procedure", ProcedureScriptContainer.class); - _registerType("world", WorldScriptContainer.class); - _registerType("format", FormatScriptContainer.class); - _registerType("inventory", InventoryScriptContainer.class); - _registerType("player listener", PlayerListenerScriptContainer.class); - _registerType("command", CommandScriptContainer.class); - _registerType("yaml data", YamlDataScriptContainer.class); - _registerType("map", MapScriptContainer.class); - } - - public static boolean containsScript(String id) { - return scriptContainers.containsKey(id.toUpperCase()); - } - - public static boolean containsScript(String id, Class scriptContainerType) { - if (!scriptContainers.containsKey(id.toUpperCase())) return false; - ScriptContainer script = (ScriptContainer) scriptContainers.get(id.toUpperCase()); - String type = null; - for (Map.Entry> entry : scriptContainerTypes.entrySet()) { - if (entry.getValue() == scriptContainerType) - type = entry.getKey(); - } - return type != null && (script.getContainerType().equalsIgnoreCase(type)); - } - - public static void _buildCoreYamlScriptContainers(YamlConfiguration yamlScripts) { - scriptContainers.clear(); - EventManager.world_scripts.clear(); - EventManager.events.clear(); - ItemScriptHelper.item_scripts.clear(); - ItemScriptHelper.item_scripts_by_hash_id.clear(); - InventoryScriptHelper.inventory_scripts.clear(); - // Get a set of key names in concatenated Denizen Scripts - Set scripts = yamlScripts.getKeys(false); - // Iterate through set - for (String scriptName : scripts) { - // Make sure the script has a type - if (yamlScripts.contains(scriptName + ".TYPE")) { - String type = yamlScripts.getString(scriptName + ".TYPE"); - // Check that types is a registered type - if (!scriptContainerTypes.containsKey(type.toUpperCase())) { - dB.log("Trying to load an invalid script. '" + scriptName + "(" + type + ")' is an unknown type."); - ScriptHelper.setHadError(); - continue; - } - // Instantiate a new scriptContainer of specified type. - Class typeClass = scriptContainerTypes.get(type.toUpperCase()); - dB.log("Adding script " + scriptName + " as type " + type.toUpperCase()); - try { - scriptContainers.put(scriptName, typeClass.getConstructor(YamlConfiguration.class, String.class) - .newInstance(ScriptHelper._gs().getConfigurationSection(scriptName), scriptName)); - } catch (Exception e) { - dB.echoError(e); - ScriptHelper.setHadError(); - } - } - else { - dB.echoError("Found type-less container: '" + scriptName + "'."); - ScriptHelper.setHadError(); - } - } - } - - public static List outside_scripts = new ArrayList(); - - /** - * Adds a YAML FileConfiguration to the list of scripts to be loaded. Adding a new - * FileConfiguration will reload the scripts automatically. - * - * @param yaml_script the FileConfiguration containing the script - * - */ - public static void addYamlScriptContainer(net.aufdemrand.denizencore.utilities.YamlConfiguration yaml_script) { - outside_scripts.add(yaml_script); - } - - /** - * Removes a YAML FileConfiguration to the list of scripts to be loaded. Removing a - * FileConfiguration will reload the scripts automatically. - * - * @param yaml_script the FileConfiguration containing the script - * - */ - public static void removeYamlScriptContainer(YamlConfiguration yaml_script) { - outside_scripts.remove(yaml_script); - DenizenCore.reloadScripts(); - } - - public static T getScriptContainerAs(String name, Class type) { - try { - if (scriptContainers.containsKey(name.toUpperCase())) - return type.cast(scriptContainers.get(name.toUpperCase())); - else return null; - } catch (Exception e) { } - - return null; - } - - public static T getScriptContainer(String name) { - if (scriptContainers.containsKey(name.toUpperCase())) - return (T) scriptContainers.get(name.toUpperCase()); - - else return null; - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/AbstractCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/AbstractCommand.java deleted file mode 100644 index 42ed238231..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/AbstractCommand.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.aufdemrand.denizen.scripts.commands; - -import net.aufdemrand.denizencore.exceptions.CommandExecutionException; -import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException; -import net.aufdemrand.denizen.scripts.ScriptEntry; - -import net.aufdemrand.denizencore.scripts.commands.BaseAbstractCommand; - -public abstract class AbstractCommand extends BaseAbstractCommand { - - public abstract void execute(ScriptEntry scriptEntry) throws CommandExecutionException; - - /** - * Called by the CommandExecuter before the execute() method is called. Arguments - * should be iterated through and checked before continuing to execute(). Note that - * PLAYER:player_name and NPCID:# arguments are parsed automatically by the Executer - * and should not be handled by this Command otherwise. Their output is stored in the - * attached {@link ScriptEntry} and can be retrieved with ((BukkitScriptEntryData)scriptEntry.entryData).getPlayer(), - * scriptEntry.getOfflinePlayer() (if the player specified is not online), and - * ((BukkitScriptEntryData)scriptEntry.entryData).getNPC(). Remember that any of these have a possibility of being null - * and should be handled accordingly if required by this Command. - * - * @param scriptEntry - * The {@link ScriptEntry}, which contains run-time context that may - * be utilized by this Command. - * @throws InvalidArgumentsException - * Will halt execution of this Command and hint usage to the console to avoid - * unwanted behavior due to missing information. - * - */ - public abstract void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException; - -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/BracedCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/BracedCommand.java deleted file mode 100644 index 05f90789d2..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/BracedCommand.java +++ /dev/null @@ -1,180 +0,0 @@ -package net.aufdemrand.denizen.scripts.commands; - -import java.util.*; - -import net.aufdemrand.denizen.BukkitScriptEntryData; -import net.aufdemrand.denizencore.exceptions.ScriptEntryCreationException; -import net.aufdemrand.denizen.objects.aH; -import net.aufdemrand.denizen.scripts.ScriptEntry; -import net.aufdemrand.denizen.utilities.debugging.dB; - -public abstract class BracedCommand extends AbstractCommand { - - public static final boolean hyperdebug = false; - - /** - * Gets the commands inside the braces of this ScriptEntry. - * - * @param scriptEntry - * The ScriptEntry to get the braced commands from. - * - * @return - * The list of ScriptEntries to be executed in the command. - */ - public static LinkedHashMap> getBracedCommands(ScriptEntry scriptEntry) { - - // And a place to store all the final braces... - LinkedHashMap> bracedSections = new LinkedHashMap>(); - - LinkedHashMap> entryBracedSet = scriptEntry.getBracedSet(); - if (entryBracedSet != null) { - try { - for (Map.Entry> entry: entryBracedSet.entrySet()) { - ArrayList array = new ArrayList(entry.getValue().size()); - for (ScriptEntry sEntry: entry.getValue()) { - ScriptEntry newEntry = sEntry.clone(); - // TODO: should this be cloning entryData? - ((BukkitScriptEntryData)newEntry.entryData).setPlayer(((BukkitScriptEntryData)scriptEntry.entryData).getPlayer()); - ((BukkitScriptEntryData)newEntry.entryData).setNPC(((BukkitScriptEntryData)scriptEntry.entryData).getNPC()); - array.add(newEntry); - } - bracedSections.put(entry.getKey(), array); - } - return bracedSections; - } - catch (CloneNotSupportedException e) { - dB.echoError(scriptEntry.getResidingQueue(), e); - } - } - - // We need a place to store the commands being built at... - TreeMap> commandList = new TreeMap>(); - - int bracesEntered = 0; - boolean newCommand = true; - boolean waitingForDash = false; - - // Inject the scriptEntry into the front of the queue, otherwise it doesn't exist - //scriptEntry.getResidingQueue().injectEntry(scriptEntry, 0); - // Send info to debug - if (hyperdebug) dB.echoDebug(scriptEntry, "Starting getBracedCommands..."); - - // If the specified amount of possible entries is less than the queue size, print that instead - //if (hyperdebug) dB.echoDebug(scriptEntry, "...with queue size: " + scriptEntry.getResidingQueue().getQueueSize()); - if (hyperdebug) dB.echoDebug(scriptEntry, "...with first command name: " + scriptEntry.getCommandName()); - if (hyperdebug) dB.echoDebug(scriptEntry, "...with first command arguments: " + scriptEntry.getArguments()); - - ScriptEntry entry = scriptEntry;//scriptEntry.getResidingQueue().getEntry(0); - if (hyperdebug) dB.echoDebug(scriptEntry, "Entry found: " + entry.getCommandName()); - - // Loop through the arguments of each entry - List argList = aH.interpret(entry.getArguments()); - - // Set the variable to use for naming braced command lists; the first should be the command name - String bracesName = scriptEntry.getCommandName(); - - int startArg = 0; - for (int i = 0; i < argList.size(); i++) { - aH.Argument arg = argList.get(i); - if (arg.asElement().asString().equals("{")) { - startArg = i; - break; - } - } - - for (int i = startArg; i < argList.size(); i++) { - aH.Argument arg = argList.get(i); - if (hyperdebug) dB.echoDebug(scriptEntry, "Arg found: " + arg.raw_value); - - // Listen for opened braces - if (arg.matches("{")) { - bracesEntered++; - newCommand = false; - waitingForDash = bracesEntered == 1; - if (hyperdebug) dB.echoDebug(scriptEntry, "Opened brace; " + String.valueOf(bracesEntered) + " now"); - if (bracesEntered > 1) { - commandList.get(commandList.lastKey()).add(arg.raw_value); - } - } - - // Listen for closed braces - else if (arg.matches("}")) { - bracesEntered--; - newCommand = false; - if (hyperdebug) dB.echoDebug(scriptEntry, "Closed brace; " + String.valueOf(bracesEntered) + " now"); - if (bracesEntered > 0) { - commandList.get(commandList.lastKey()).add(arg.raw_value); - } - else { - if (bracedSections.containsKey(bracesName)) { - dB.echoError(scriptEntry.getResidingQueue(), "You may not have braced commands with the same arguments."); - break; - } - ArrayList bracesSection = new ArrayList(); - for (ArrayList command : commandList.values()) { - try { - if (command.isEmpty()) { - if (hyperdebug) dB.echoError(scriptEntry.getResidingQueue(), "Empty command?"); - continue; - } - String cmd = command.get(0); - if (hyperdebug) dB.echoDebug(scriptEntry, "Calculating " + cmd); - command.remove(0); - String[] args = new String[command.size()]; - args = command.toArray(args); - bracesSection.add(new ScriptEntry(cmd, - args, - scriptEntry.getScript() != null ? scriptEntry.getScript().getContainer() : null)); - ((BukkitScriptEntryData)bracesSection.get(bracesSection.size() - 1).entryData) - .setPlayer(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer()); - ((BukkitScriptEntryData)bracesSection.get(bracesSection.size() - 1).entryData) - .setNPC(((BukkitScriptEntryData) scriptEntry.entryData).getNPC()); - if (hyperdebug) dB.echoDebug(scriptEntry, "Command added: " + cmd + ", with " + String.valueOf(args.length) + " arguments"); - } catch (ScriptEntryCreationException e) { - if (hyperdebug) dB.echoError(scriptEntry.getResidingQueue(), e.getMessage()); - } - } - if (hyperdebug) dB.echoDebug(scriptEntry, "Adding section " + bracesName); - bracedSections.put(bracesName.toUpperCase(), bracesSection); - bracesName = ""; - } - } - - // Finish building a command - else if (newCommand && bracesEntered == 1) { - commandList.put(commandList.size(), new ArrayList()); - commandList.get(commandList.lastKey()).add(arg.raw_value); - newCommand = false; - if (hyperdebug) dB.echoDebug(scriptEntry, "Treating as new command"); - } - - // Start building a command - else if (arg.matches("-") && bracesEntered == 1) { - newCommand = true; - waitingForDash = false; - if (hyperdebug) dB.echoDebug(scriptEntry, "Assuming following is a new command"); - } - - // Add to the name of the braced command list - else if (bracesEntered == 0) { - bracesName += arg.raw_value; - } - - // Continue building the current command - else { - if (waitingForDash) { - dB.echoError(scriptEntry.getResidingQueue(), "Malformed braced section! Missing a - symbol!"); - break; - } - newCommand = false; - commandList.get(commandList.lastKey()).add(arg.raw_value); - if (hyperdebug) dB.echoDebug(scriptEntry, "Adding to the command"); - } - } - - //scriptEntry.getResidingQueue().removeEntry(0); - scriptEntry.setBracedSet(bracedSections); - return bracedSections; - - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/CommandExecuter.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/CommandExecuter.java deleted file mode 100644 index 9ebcdb3b48..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/CommandExecuter.java +++ /dev/null @@ -1,253 +0,0 @@ -package net.aufdemrand.denizen.scripts.commands; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import net.aufdemrand.denizen.BukkitScriptEntryData; -import net.aufdemrand.denizen.tags.BukkitTagContext; -import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException; -import net.aufdemrand.denizen.objects.aH; -import net.aufdemrand.denizen.objects.dNPC; -import net.aufdemrand.denizen.objects.dPlayer; -import net.aufdemrand.denizen.scripts.ScriptEntry; -import net.aufdemrand.denizen.tags.TagManager; -import net.aufdemrand.denizen.utilities.DenizenAPI; -import net.aufdemrand.denizen.utilities.debugging.dB; -import net.aufdemrand.denizencore.utilities.debugging.dB.DebugElement; - -import net.aufdemrand.denizencore.scripts.commands.BaseAbstractCommand; -import org.bukkit.ChatColor; - -public class CommandExecuter { - - private static final Pattern definition_pattern = Pattern.compile("%(.+?)%"); - - - public CommandExecuter() { - } - - /* - * Executes a command defined in scriptEntry - */ - - public boolean execute(ScriptEntry scriptEntry) { - StringBuilder output = new StringBuilder(); - output.append(scriptEntry.getCommandName()); - if (scriptEntry.getOriginalArguments() == null) { - dB.echoError("Original Arguments null for " + scriptEntry.getCommandName()); - } - else { - for (String arg: scriptEntry.getOriginalArguments()) - output.append(" \"").append(arg).append("\""); - } - - dB.echoDebug(scriptEntry, "Queue '" + scriptEntry.getResidingQueue().id + "' Executing: " + output.toString()); - - Matcher m; - StringBuffer sb; - if (scriptEntry.getCommandName().indexOf('%') != -1) { - m = definition_pattern.matcher(scriptEntry.getCommandName()); - sb = new StringBuffer(); - while (m.find()) { - String definition = scriptEntry.getResidingQueue().getDefinition(m.group(1)); - if (definition == null) { - dB.echoError("Unknown definition %" + m.group(1) + "%."); - definition = "null"; - } - dB.echoDebug(scriptEntry, "Filled definition %" + m.group(1) + "% with '" + definition + "'."); - m.appendReplacement(sb, Matcher.quoteReplacement(definition)); - } - m.appendTail(sb); - scriptEntry.setCommandName(sb.toString()); - } - - // Get the command instance ready for the execution of the scriptEntry - BaseAbstractCommand command = scriptEntry.getCommand(); - if (command == null) { - command = DenizenAPI.getCurrentInstance().getCommandRegistry().get(scriptEntry.getCommandName()); - } - - if (command == null) { - dB.echoDebug(scriptEntry, DebugElement.Header, "Executing command: " + scriptEntry.getCommandName()); - dB.echoError(scriptEntry.getResidingQueue(), scriptEntry.getCommandName() + " is an invalid dCommand! Are you sure it loaded?"); - dB.echoDebug(scriptEntry, DebugElement.Footer); - return false; - } - - if (((BukkitScriptEntryData)scriptEntry.entryData).hasNPC() && ((BukkitScriptEntryData)scriptEntry.entryData).getNPC().getCitizen() == null) - ((BukkitScriptEntryData)scriptEntry.entryData).setNPC(null); - - // Debugger information - if (scriptEntry.getOriginalArguments() == null || - scriptEntry.getOriginalArguments().size() == 0 || - !scriptEntry.getOriginalArguments().get(0).equals("\0CALLBACK")) { - if (((BukkitScriptEntryData)scriptEntry.entryData).getPlayer() != null) - dB.echoDebug(scriptEntry, DebugElement.Header, "Executing dCommand: " + scriptEntry.getCommandName() + "/p@" + ((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().getName()); - else - dB.echoDebug(scriptEntry, DebugElement.Header, "Executing dCommand: " + - scriptEntry.getCommandName() + (((BukkitScriptEntryData)scriptEntry.entryData).getNPC() != null ? "/n@" + ((BukkitScriptEntryData)scriptEntry.entryData).getNPC().getName() : "")); - } - - // Don't execute() if problems arise in parseArgs() - boolean keepGoing = true; - - try { - - // Throw exception if arguments are required for this command, but not supplied. - if (command.getOptions().REQUIRED_ARGS > scriptEntry.getArguments().size()) throw new InvalidArgumentsException(""); - - if (scriptEntry.has_tags) { - scriptEntry.setArguments(TagManager.fillArguments(scriptEntry.getArguments(), - new BukkitTagContext(scriptEntry != null ? ((BukkitScriptEntryData)scriptEntry.entryData).getPlayer(): null, - scriptEntry != null ? ((BukkitScriptEntryData)scriptEntry.entryData).getNPC(): null, - true, scriptEntry, scriptEntry != null ? scriptEntry.shouldDebug(): true, - scriptEntry != null ? scriptEntry.getScript(): null - ))); // Replace tags - } - - /* If using NPC:# or PLAYER:Name arguments, these need to be changed out immediately because... - * 1) Denizen/Player flags need the desired NPC/PLAYER before parseArgs's getFilledArguments() so that - * the Player/Denizen flags will read from the correct Object. If using PLAYER or NPCID arguments, - * the desired Objects are obviously not the same objects that were sent with the ScriptEntry. - * 2) These arguments should be valid for EVERY ScriptCommand, so why not just take care of it - * here, instead of requiring each command to take care of the argument. - */ - - List newArgs = new ArrayList(); - - // Don't fill in tags if there were brackets detected.. - // This means we're probably in a nested if. - int nested_depth = 0; - // Watch for IF command to avoid filling player and npc arguments - // prematurely - boolean if_ignore = false; - - for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) { - if (arg.getValue().equals("{")) nested_depth++; - if (arg.getValue().equals("}")) nested_depth--; - - // If nested, continue. - if (nested_depth > 0) { - newArgs.add(arg.raw_value); - continue; - } - - if (arg.raw_value.indexOf('%') != -1) { - m = definition_pattern.matcher(arg.raw_value); - sb = new StringBuffer(); - while (m.find()) { - String def = m.group(1); - boolean dynamic = false; - if (def.startsWith("|")) { - def = def.substring(1, def.length() - 1); - dynamic = true; - } - String definition; - String defval = scriptEntry.getResidingQueue().getDefinition(def); - if (dynamic) - definition = scriptEntry.getResidingQueue().getDefinition(def); - else - definition = TagManager.escapeOutput(scriptEntry.getResidingQueue().getDefinition(def)); - if (defval == null) { - dB.echoError("Unknown definition %" + m.group(1) + "%."); - definition = "null"; - } - dB.echoDebug(scriptEntry, "Filled definition %" + m.group(1) + "% with '" + definition + "'."); - m.appendReplacement(sb, Matcher.quoteReplacement(definition)); - } - m.appendTail(sb); - arg = aH.Argument.valueOf(sb.toString()); - } - - // If using IF, check if we've reached the command + args - // so that we don't fill player: or npc: prematurely - if (command.getName().equalsIgnoreCase("if") - && DenizenAPI.getCurrentInstance().getCommandRegistry().get(arg.getValue()) != null) - if_ignore = true; - - // Fill player/off-line player - if (arg.matchesPrefix("player") && !if_ignore) { - dB.echoDebug(scriptEntry, "...replacing the linked player with " + arg.getValue()); - String value = TagManager.tag(arg.getValue(), new BukkitTagContext(scriptEntry, false)); - dPlayer player = dPlayer.valueOf(value); - if (player == null || !player.isValid()) { - dB.echoError(scriptEntry.getResidingQueue(), value + " is an invalid player!"); - return false; - } - ((BukkitScriptEntryData)scriptEntry.entryData).setPlayer(player); - } - - // Fill NPCID/NPC argument - else if (arg.matchesPrefix("npc, npcid") && !if_ignore) { - dB.echoDebug(scriptEntry, "...replacing the linked NPC with " + arg.getValue()); - String value = TagManager.tag(arg.getValue(), new BukkitTagContext(scriptEntry, false)); - dNPC npc = dNPC.valueOf(value); - if (npc == null || !npc.isValid()) { - dB.echoError(scriptEntry.getResidingQueue(), value + " is an invalid NPC!"); - return false; - } - ((BukkitScriptEntryData)scriptEntry.entryData).setNPC(npc); - } - - // Save the scriptentry if needed later for fetching scriptentry context - else if (arg.matchesPrefix("save") && !if_ignore) { - String saveName = TagManager.tag(arg.getValue(), new BukkitTagContext(scriptEntry, false)); - dB.echoDebug(scriptEntry, "...remembering this script entry as '" + saveName + "'!"); - scriptEntry.getResidingQueue().holdScriptEntry(saveName, scriptEntry); - } - - else newArgs.add(arg.raw_value); - } - - // Add the arguments back to the scriptEntry. - scriptEntry.setArguments(newArgs); - - // Now process non-instant tags. - scriptEntry.setArguments(TagManager.fillArguments(scriptEntry.getArguments(), - new BukkitTagContext(scriptEntry != null ? ((BukkitScriptEntryData)scriptEntry.entryData).getPlayer(): null, - scriptEntry != null ? ((BukkitScriptEntryData)scriptEntry.entryData).getNPC(): null, - false, scriptEntry, scriptEntry != null ? scriptEntry.shouldDebug(): true, - scriptEntry != null ? scriptEntry.getScript(): null - ))); // Replace tags - - // Parse the rest of the arguments for execution. - ((AbstractCommand)command).parseArgs(scriptEntry); - - } catch (InvalidArgumentsException e) { - - keepGoing = false; - // Give usage hint if InvalidArgumentsException was called. - dB.echoError(scriptEntry.getResidingQueue(), "Woah! Invalid arguments were specified!"); - if (e.getMessage() != null && e.getMessage().length() > 0) - dB.log(ChatColor.YELLOW + "+> MESSAGE follows: " + ChatColor.WHITE + "'" + e.getMessage() + "'"); - dB.log("Usage: " + command.getUsageHint()); - dB.echoDebug(scriptEntry, DebugElement.Footer); - scriptEntry.setFinished(true); - - } catch (Exception e) { - - keepGoing = false; - dB.echoError(scriptEntry.getResidingQueue(), "Woah! An exception has been called with this command!"); - dB.echoError(scriptEntry.getResidingQueue(), e); - dB.echoDebug(scriptEntry, DebugElement.Footer); - scriptEntry.setFinished(true); - - } finally { - - if (keepGoing) - try { - // Run the execute method in the command - ((AbstractCommand)command).execute(scriptEntry); - } catch (Exception e) { - dB.echoError(scriptEntry.getResidingQueue(), "Woah!! An exception has been called with this command!"); - dB.echoError(scriptEntry.getResidingQueue(), e); - scriptEntry.setFinished(true); - } - - } - - return true; - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/containers/ScriptContainer.java b/src/main/java/net/aufdemrand/denizen/scripts/containers/ScriptContainer.java deleted file mode 100644 index 754ba71605..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/containers/ScriptContainer.java +++ /dev/null @@ -1,262 +0,0 @@ -package net.aufdemrand.denizen.scripts.containers; - -import net.aufdemrand.denizen.objects.dScript; -import net.aufdemrand.denizen.scripts.ScriptBuilder; -import net.aufdemrand.denizen.scripts.ScriptEntry; -import net.aufdemrand.denizen.scripts.ScriptEntrySet; -import net.aufdemrand.denizencore.scripts.ScriptEntryData; -import net.aufdemrand.denizencore.scripts.ScriptHelper; -import net.aufdemrand.denizencore.utilities.CoreUtilities; -import net.aufdemrand.denizencore.utilities.YamlConfiguration; -import net.aufdemrand.denizencore.utilities.debugging.Debuggable; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ScriptContainer implements Debuggable { - - // <--[language] - // @name Script Container - // @group Script Container System - // @description - // Script Containers are the basic structure that Denizen uses inside its YAML-based scripting files found in your - // plugins/Denizen/scripts/ folder. Regardless of type, all script containers have basic parts that can usually be - // described as keys, list keys, parent keys, child keys, values, and list values. While specific container types - // probably have more specific names, just remember that no matter how complicated a script, this basic structure - // still applies. - // - // It's important to keep in mind that all child keys, including all the main keys of the script, must line up with - // one another, hierarchically. If you are familiar with YAML, great, because all script containers use it at the - // core. Every value, in one way or another, belongs to some kind of 'key'. To define a key, use a string value plus - // a colon (:). Keys can have a single value, a list value, or own another key: - // - // - // script name: - // key: value - // list key: - // - list value - // - ... - // parent key: - // child key: value - // - // - // And here's a container, put into a more familiar context: - // - // - // a haiku script: - // type: task - // script: - // - narrate "A simple script," - // - narrate "with a key value relationship." - // - narrate "Oh look, a list!" - // - // - // --> - - - public ScriptContainer(YamlConfiguration configurationSection, String scriptContainerName) { - contents = configurationSection; - this.name = scriptContainerName.toUpperCase(); - } - - - // The contents of the script container - YamlConfiguration contents; - - /** - * Gets the contents of the container. - * - * @return a ConfigurationSection object - */ - public YamlConfiguration getContents() { - return contents; - } - - - /** - * Casts this container to a specify type of script container. Must be a valid - * container type of the type casting to. - * - * @param type the class of the ScriptContainer casting to - * @param the ScriptContainer object - * @return a ScriptContainer of the type specified - */ - public T getAsContainerType(Class type) { - return type.cast(this); - } - - - // <--[language] - // @name Script Name - // @group Script Container System - // @description - // Typically refers to the name of a script container. When using the object fetcher with dScript objects, - // (s@script_name), the script_name referred to is the name of the container. - // - // - // script name: <--- script name - // type: script_type - // script: <--- base script - // - script entries - // - ... - // local script: <--- local script path - // - script entries - // - ... - // - // - // --> - - // The name of the script container - private String name; - - /** - * Gets the name of the script container. - * - * @return the script container name. - */ - public String getName() { - return name; - } - - public String getFileName() { - return ScriptHelper.getSource(getName()); - } - - public String getOriginalName() { - return ScriptHelper.getOriginalName(getName()); - } - - - /** - * Gets a dScript object that represents this container. - * - * @return a dScript object linking this script container. - */ - public dScript getAsScriptArg() { - return dScript.valueOf(name); - } - - - // <--[language] - // @name Script Type - // @group Script Container System - // @description - // The type of container that a script is in. For example, 'task script' is a script type that has some sort of - // utility script or - // - // - // script name: - // type: script_type <--- script type - // script: - // - script entries - // - ... - // - // - // --> - - /** - * Gets the value of the type: node specified in the script container structure. - * - * @return the type of container - */ - public String getContainerType() { - return contents.contains("TYPE") - ? contents.getString("TYPE").toUpperCase() - : null; - } - - - /** - * Checks the ConfigurationSection for the key/path to key specified. - * - * @param path the path of the key - * @return true if the key exists - */ - public boolean contains(String path) { - return contents.contains(path.toUpperCase()); - } - - - public String getString(String path) { - return contents.getString(path.toUpperCase()); - } - - - public String getString(String path, String def) { - return contents.getString(path.toUpperCase(), def); - } - - - public List getStringList(String path) { - return contents.getStringList(path.toUpperCase()); - } - - - public YamlConfiguration getConfigurationSection(String path) { - if (path.length() == 0) - return contents; - return contents.getConfigurationSection(path.toUpperCase()); - } - - - public void set(String path, Object object) { - contents.set(path.toUpperCase(), object); - } - - - public List getBaseEntries(ScriptEntryData data) { - return getEntries(data, "script"); - } - - public List getEntries(ScriptEntryData data, String path) { - if (path == null) path = "script"; - ScriptEntrySet set = getSetFor(path.toUpperCase()); - if (set == null) - return new ArrayList(); - for (ScriptEntry entry: set.getEntries()) { - entry.entryData = data.clone(); - } - return set.getEntries(); - } - - ScriptEntrySet getSetFor(String path) { - ScriptEntrySet got = scriptsMap.get(path); - if (got != null) { - return got.Duplicate(); - } - List stringEntries = contents.getStringList(path); - if (stringEntries == null || stringEntries.size() == 0) return null; - List entries = ScriptBuilder.buildScriptEntries(stringEntries, this, null, null); - got = new ScriptEntrySet(entries); - scriptsMap.put(path, got); - return got.Duplicate(); - } - - private Map scriptsMap = new HashMap(); - - ///////////// - // DEBUGGABLE - ///////// - - // Cached debug value to avoid repeated complex YAML calls - private Boolean shouldDebug = null; - - @Override - public boolean shouldDebug() { - if (shouldDebug == null) - shouldDebug = (!(contents.contains("DEBUG") && contents.getString("DEBUG").equalsIgnoreCase("false"))); - return shouldDebug; - } - - @Override - public boolean shouldFilter(String criteria) throws Exception { - return name.equalsIgnoreCase(criteria.replace("s@", "")); - } - - @Override - public String toString() { - return "s@" + CoreUtilities.toLowerCase(getName()); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/containers/core/YamlDataScriptContainer.java b/src/main/java/net/aufdemrand/denizen/scripts/containers/core/YamlDataScriptContainer.java deleted file mode 100644 index f14869bf40..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/containers/core/YamlDataScriptContainer.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.aufdemrand.denizen.scripts.containers.core; - -import net.aufdemrand.denizen.scripts.containers.ScriptContainer; -import net.aufdemrand.denizencore.utilities.YamlConfiguration; - -public class YamlDataScriptContainer extends ScriptContainer { - - public YamlDataScriptContainer(YamlConfiguration configurationSection, String scriptContainerName) { - super(configurationSection, scriptContainerName); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/queues/ScriptEngine.java b/src/main/java/net/aufdemrand/denizen/scripts/queues/ScriptEngine.java deleted file mode 100644 index 76ea4384fe..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/queues/ScriptEngine.java +++ /dev/null @@ -1,93 +0,0 @@ -package net.aufdemrand.denizen.scripts.queues; - -import net.aufdemrand.denizen.scripts.ScriptEntry; -import net.aufdemrand.denizen.scripts.commands.CommandExecuter; -import net.aufdemrand.denizen.scripts.queues.core.Delayable; -import net.aufdemrand.denizen.utilities.debugging.dB; - -public class ScriptEngine { - - - final private CommandExecuter commandExecuter; - - - public ScriptEngine() { - // Create Denizen CommandExecuter - commandExecuter = new CommandExecuter(); - } - - - boolean shouldHold(ScriptQueue scriptQueue) { - if (scriptQueue instanceof Delayable && ((Delayable)scriptQueue).isPaused()) - return true; - if (scriptQueue.getLastEntryExecuted() != null - && scriptQueue.getLastEntryExecuted().shouldWaitFor()) { - if (!(scriptQueue instanceof Delayable)) { - dB.echoDebug(scriptQueue.getLastEntryExecuted(), "Forcing queue " + scriptQueue.id + " into a timed queue..."); - scriptQueue.forceToTimed(null); - return true; - } - else { - return true; - } - } - return false; - } - public void revolve(ScriptQueue scriptQueue) { - // Check last ScriptEntry to see if it should be waited for - if (shouldHold(scriptQueue)) - return; - - // Okay to run next scriptEntry - ScriptEntry scriptEntry = scriptQueue.getNext(); - - // Loop through the entries - while (scriptEntry != null) { - // Mark script entry with Queue that is sending it to the executor - scriptEntry.setSendingQueue(scriptQueue); - - try { - // Execute the scriptEntry - getScriptExecuter().execute(scriptEntry); - } - // Absolutely NO errors beyond this point! - catch (Throwable e) { - dB.echoError(scriptEntry.getResidingQueue(), "Woah! An exception has been called with this command!"); - dB.echoError(scriptEntry.getResidingQueue(), e); - } - // Set as last entry executed - scriptQueue.setLastEntryExecuted(scriptEntry); - - // Check if the scriptQueue is delayed (EG, via wait) - if (scriptQueue instanceof Delayable) { - if (((Delayable) scriptQueue).isDelayed()) - break; - if (((Delayable) scriptQueue).isPaused()) - break; - } - - // If the entry is instant, and not injected, get the next Entry - if (scriptEntry.isInstant()) { - // If it's holding, even if it's instant, just stop and wait - if (shouldHold(scriptQueue)) - return; - // Remove from execution list - scriptEntry = scriptQueue.getNext(); - } - - // If entry isn't instant, end the revolutions and wait - else - break; - } - } - - /** - * Gets the currently loaded instance of the Command Executer - * - * @return CommandExecuter - * - */ - public CommandExecuter getScriptExecuter() { - return commandExecuter; - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/queues/ScriptQueue.java b/src/main/java/net/aufdemrand/denizen/scripts/queues/ScriptQueue.java deleted file mode 100644 index e0d17d20a5..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/queues/ScriptQueue.java +++ /dev/null @@ -1,926 +0,0 @@ -package net.aufdemrand.denizen.scripts.queues; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import net.aufdemrand.denizen.objects.*; -import net.aufdemrand.denizen.objects.properties.Property; -import net.aufdemrand.denizen.objects.properties.PropertyParser; -import net.aufdemrand.denizen.scripts.ScriptEntry; -import net.aufdemrand.denizen.scripts.commands.core.DetermineCommand; -import net.aufdemrand.denizen.scripts.queues.core.TimedQueue; -import net.aufdemrand.denizen.tags.Attribute; -import net.aufdemrand.denizen.utilities.DenizenAPI; -import net.aufdemrand.denizencore.DenizenCore; -import net.aufdemrand.denizencore.utilities.CoreUtilities; -import net.aufdemrand.denizencore.utilities.QueueWordList; -import net.aufdemrand.denizencore.utilities.debugging.Debuggable; -import net.aufdemrand.denizen.utilities.debugging.dB; -import net.aufdemrand.denizencore.utilities.scheduling.OneTimeSchedulable; - -/** - * ScriptQueues hold/control ScriptEntries while being sent - * to the CommandExecuter - */ - -public abstract class ScriptQueue implements Debuggable, dObject { - private static final Map, String> classNameCache = new HashMap, String>(); - - protected static long total_queues = 0; - - - /** - * Returns the number of queues created in the current instance - * as well as the number of currently active queues. - * - * @return stats - */ - public static String _getStats() { - return "Total number of queues created: " - + total_queues - + ", currently active queues: " - + _queues.size() + "."; - } - - - /** - * Gets an existing queue. Cast to the correct QueueType to - * access further methods. - * - * @param id the id of the queue - * @return a ScriptQueue instance, or null - */ - public static ScriptQueue _getExistingQueue(String id) { - if (!_queueExists(id)) return null; - else return _queues.get(id); - } - - /* - private static String randomEntry(String[] strings) { - return strings[CoreUtilities.getRandom().nextInt(strings.length)]; - }*/ - - /** - * Gets a random id for use in creating a 'nameless' queue. - * - * @param prefix the name of the script running the new queue. - * @return String value of a random id - */ - public static String getNextId(String prefix) { - // DUUIDs v2.1 - int size = QueueWordList.FinalWordList.size(); - String id = prefix + "_" - + QueueWordList.FinalWordList.get(CoreUtilities.getRandom().nextInt(size)) - + QueueWordList.FinalWordList.get(CoreUtilities.getRandom().nextInt(size)) - + QueueWordList.FinalWordList.get(CoreUtilities.getRandom().nextInt(size)); - // DUUIDs v3.1 - /* - String id = prefix.replace(' ', '_') - + "_" - + randomEntry(QueueWordList.Pronouns) - + randomEntry(QueueWordList.Verbs) - + randomEntry(QueueWordList.Modifiers) - + randomEntry(QueueWordList.Adjectives) - + randomEntry(QueueWordList.Nouns);*/ - return _queues.containsKey(id) ? getNextId(prefix) : id; - } - - - /** - * Checks the type of an existing queue with the type given. - * - * @param queue id of the queue - * @param type class of the queue type - * @return true if they match, false if the queue - * doesn't exist or does not match - */ - public static boolean _matchesType(String queue, Class type) { - return (_queueExists(queue)) && _queues.get(queue).getClass() == type; - } - - - // Contains all currently active queues, keyed by a String id. - protected static Map _queues = - new ConcurrentHashMap(8, 0.9f, 1); - - - /** - * Returns a collection of all active queues. - * - * @return a collection of ScriptQueues - */ - public static Collection _getQueues() { - return _queues.values(); - } - - - /** - * Checks if a queue exists with the given id. - * - * @param id the String ID of the queue to check. - * @return true if it exists. - */ - public static boolean _queueExists(String id) { - return _queues.containsKey(id); - } - - ///////////////////// - // Public instance fields - ///////////////////// - - - // Name of the queue -- this identifies - // the ScriptQueue when using _getQueue() - public String id; - - // Whether the queue was cleared - public boolean was_cleared = false; - - - ///////////////////// - // Private instance fields and constructors - ///////////////////// - - - // List of ScriptEntries in the queue - private final List - script_entries = new ArrayList(); - - - // The last script entry that was executed - // in this queue. - private ScriptEntry lastEntryExecuted = null; - - - // If this number is larger than Java's - // getCurrentTimeMillis(), the queue will - // delay execution of the next ScriptEntry - private long delay_time = 0; - - - // ScriptQueues can have a definitions, - // keyed by a String Id. Denizen's - // 'Definitions' system uses this map. - // This information is fetched by using - // %definition_name% - private final Map - definitions = new ConcurrentHashMap(8, 0.9f, 1); - - - // ScriptQueues can also have a list of context, added - // by events/actions/etc. This is kind of like the context - // inside scriptEntries, but within the scope of the entire - // queue. - // To access this context, use or - private final Map - context = new ConcurrentHashMap(8, 0.9f, 1); - - - // Held script entries can be recalled later in the script - // and their scriptEntry context can be recalled. Good for - // commands that contain unique items/objects that it's - // created. - private final Map - held_entries = new ConcurrentHashMap(8, 0.9f, 1); - - private dScript script; - - /** - * Creates a ScriptQueue instance. Users of - * the API should instead use the static members - * of classes that extend ScriptQueue. - * - * @param id the name of the ScriptQueue - */ - protected ScriptQueue(String id) { - // Remember the 'id' - this.id = id; - // Save the instance to the _queues static map - _queues.put(id, this); - // Increment the stats - total_queues++; - } - - ///////////////////// - // Public instance setters and getters - ///////////////////// - - /** - * Gets a boolean indicating whether the queue - * was cleared. - * - * @return whether the queue has been cleared. - */ - public boolean getWasCleared() { - return was_cleared; - } - - /** - * Gets a held script entry. Held script entries might - * contains some script entry context that might need - * to be fetched! - * - */ - public ScriptEntry getHeldScriptEntry(String id) { - return held_entries.get(id.toLowerCase()); - } - - /** - * Provides a way to hold a script entry for retrieval later in the - * script. Keyed by an id, which is turned to lowercase making - * it case insensitive. - * - * @param id intended name of the entry - * @param entry the ScriptEntry instance - * @return the ScriptQueue, just in case you need to do more with it - */ - - public ScriptQueue holdScriptEntry(String id, ScriptEntry entry) { - // to lowercase to avoid case sensitivity. - held_entries.put(id.toLowerCase(), entry); - - return this; - } - - - /** - * Gets a context from the queue. Script writers can - * use the or tags - * to fetch this data. - * - * @param id The name of the definitions - * @return The value of the definitions, or null - */ - public dObject getContext(String id) { - return context.get(id.toLowerCase()); - } - - - /** - * Checks for a piece of context. - * - * @param id The name of the context - * @return true if the context exists. - */ - public boolean hasContext(String id) { - return context.containsKey(id.toLowerCase()); - } - - - /** - * Adds a new piece of context to the queue. This is usually - * done within events or actions, or wherever script creation has - * some information to pass along, other than a player and npc. - * - * @param id the name of the context - * @param value the value of the context - */ - public void addContext(String id, dObject value) { - if (value != null && id != null) - context.put(id.toLowerCase(), value); - } - - - /** - * Returns a Map of all the current context - * stored in the queue, keyed by 'id' - * - * @return all current context, empty if none. - */ - public Map getAllContext() { - return context; - } - - - private long reqId = -1L; - - /** - * Sets the instant-queue ID for usage by the determine command. - * - * @param ID the ID to use. - * @return the queue for re-use. - */ - public ScriptQueue setReqId(long ID) { - reqId = ID; - return this; - } - - /** - * Gets a definition from the queue. Denizen's - * CommandExecuter will fetch this information - * by using the %definition_name% format, similar - * to 'replaceable tags' - * - * @param definition The name of the definitions - * @return The value of the definitions, or null - */ - public String getDefinition(String definition) { - if (definition == null) - return null; - return definitions.get(definition.toLowerCase()); - } - - - /** - * Checks for a piece of definitions. - * - * @param definition The name of the definitions - * @return true if the definition exists. - */ - public boolean hasDefinition(String definition) { - return definitions.containsKey(definition.toLowerCase()); - } - - - /** - * Adds a new piece of definitions to the queue. This - * can be done with dScript as well by using the - * 'define' command. - * - * @param definition the name of the definitions - * @param value the value of the definition - */ - public void addDefinition(String definition, String value) { - definitions.put(definition.toLowerCase(), value); - } - - - /** - * Removes an existing definitions from the queue. This - * can be done with dScript as well by using the - * 'define' command, with :! as the value using the definition - * name as a prefix. - * - * @param definition the name of the definitions - */ - public void removeDefinition(String definition) { - definitions.remove(definition.toLowerCase()); - } - - /** - * Returns a Map of all the current definitions - * stored in the queue, keyed by 'definition id' - * - * @return all current definitions, empty if none. - */ - public Map getAllDefinitions() { - return definitions; - } - - - /** - * The last entry that was executed. Note: any - * replaceable tags/etc. are already replaced - * in this ScriptEntry. - * - * @return the last entry executed - */ - public ScriptEntry getLastEntryExecuted() { - return lastEntryExecuted; - } - - - /** - * Clears the script queue. - * - * Use the 'queue clear' command in dScript to - * access this method. - */ - public void clear() { - was_cleared = true; - script_entries.clear(); - } - - - /** - * Will delay the start of the queue until Java's - * System.currentTimeMillis() is less than the - * delayTime. - * - * @param delayTime the time to start the queue, in - * System.currentTimeMillis() format. - */ - public void delayUntil(long delayTime) { - this.delay_time = delayTime; - } - - /////////////////// - // Public 'functional' methods - ////////////////// - - - /** - * Converts any queue type to a timed queue. - * - * @param delay how long to delay initially. - * @return the newly created queue. - */ - public TimedQueue forceToTimed(Duration delay) { - stop(); - TimedQueue newQueue = TimedQueue.getQueue(id); - for (ScriptEntry entry: getEntries()) { - entry.setInstant(true); - } - newQueue.addEntries(getEntries()); - for (Map.Entry def: getAllDefinitions().entrySet()) { - newQueue.addDefinition(def.getKey(), def.getValue()); - } - for (Map.Entry entry: getAllContext().entrySet()) { - newQueue.addContext(entry.getKey(), entry.getValue()); - } - for (Map.Entry entry: held_entries.entrySet()) { - newQueue.holdScriptEntry(entry.getKey(), entry.getValue()); - } - newQueue.setLastEntryExecuted(getLastEntryExecuted()); - newQueue.setSpeed(1); - clear(); - if (delay != null) - newQueue.delayFor(delay); - newQueue.start(); - return newQueue; - } - - - /** - * Called when the script queue is started. - * - */ - protected abstract void onStart(); - - - protected boolean is_started; - - private Class cachedClass; - - private long startTime = 0; - - - /** - * Starts the script queue. - * - */ - public void start() { - if (is_started) return; - - // Set as started, and check for a valid delay_time. - is_started = true; - boolean is_delayed = delay_time > System.currentTimeMillis(); - - // Record what script generated the first entry in the queue - if (script_entries.size() > 0) - script = script_entries.get(0).getScript(); - - // Debug info - Class clazz = this.cachedClass == null ? this.cachedClass = getClass() : this.cachedClass; - String name = classNameCache.get(clazz); - if (name == null) - classNameCache.put(clazz, name = clazz.getSimpleName()); - if (is_delayed) { - dB.echoDebug(this, "Delaying " + name + " '" + id + "'" + " for '" - + new Duration(((double)(delay_time - System.currentTimeMillis())) / 1000f).identify() + "'..."); - } else - dB.echoDebug(this, "Starting " + name + " '" + id + "'..."); - - // If it's delayed, schedule it for later - if (is_delayed) { - DenizenCore.schedule(new OneTimeSchedulable( - new Runnable() { - @Override - public void run() { - startTime = System.currentTimeMillis(); - onStart(); /* Start the engine */ - } - - // Take the delay time, find out how many milliseconds away - // it is, turn it into seconds, then divide by 20 for ticks. - }, - ((float)(delay_time - System.currentTimeMillis())) / 1000)); - - } else { - // If it's not, start the engine now! - startTime = System.currentTimeMillis(); - onStart(); - } - } - - /** - * Immediately runs a list of entries within the script queue. - * Primarily used as a simple method of instant command injection. - * - * @param entries the entries to be run. - */ - public String runNow(List entries, String type) { - // Inject the entries at the start - injectEntries(entries, 0); - //Note which entry comes next in the existing queue - ScriptEntry nextup = getQueueSize() > entries.size() ? getEntry(entries.size()): null; - // Loop through until the queue is emptied or the entry noted above is reached - while (getQueueSize() > 0 && getEntry(0) != nextup && !was_cleared) { - if (breakMe != null) { - removeEntry(0); - } - else { - // Ensure the engine won't try to run its own instant code on the entry. - getEntry(0).setInstant(false); - // Don't let the system try to 'hold' this entry. - getEntry(0).setFinished(true); - // Execute the ScriptEntry properly through the Script Engine. - DenizenAPI.getCurrentInstance().getScriptEngine().revolve(this); - } - } - if (breakMe != null && breakMe.startsWith(type)) { - String origBreakMe = breakMe; - breakMe = null; - return origBreakMe; - } - return null; - } - - private Runnable callback = null; - - /** - * Adds a runnable to call back when the queue is completed. - * - * @param r the Runnable to call back - */ - public void callBack(Runnable r) { - callback = r; - } - - private String breakMe = null; - - public void breakLoop(String toBreak) { - breakMe = toBreak; - } - - public String isLoopBroken() { - return breakMe; - } - - - /** - * Stops the script_queue and breaks it down. - * - */ - protected abstract void onStop(); - - - protected boolean is_stopping = false; - - - public void stop() { - - // If this is the first time this has been called, check the - // ScriptContainer event 'on queue completes' which may have - // a few more script entries to run. - if (!is_stopping) { - is_stopping = true; - - // Get the entries - List entries = - (lastEntryExecuted != null && lastEntryExecuted.getScript() != null ? - lastEntryExecuted.getScript().getContainer() - .getEntries(lastEntryExecuted.entryData.clone(), "on queue completes") : new ArrayList()); - // Add the 'finishing' entries back into the queue (if not empty) - if (!entries.isEmpty()) { - script_entries.addAll(entries); - dB.echoDebug(this, "Finishing up queue '" + id + "'..."); - } else /* if empty, just stop the queue like normal */ { - if (_queues.get(id) == this) - _queues.remove(id); - dB.echoDebug(this, "Completing queue '" + id + "' in " + (System.currentTimeMillis() - startTime) + "ms."); - if (callback != null) - callback.run(); - is_started = false; - onStop(); - } - } - - // Else, just complete the queue. - // 1) Remove the id from active queue list - // 2) Cancel the corresponding task_id - else { - if (_queues.get(id) == this) - _queues.remove(id); - dB.echoDebug(this, "Re-completing queue '" + id + "' in " + (System.currentTimeMillis() - startTime) + "ms."); - if (callback != null) - callback.run(); - is_started = false; - onStop(); - } - } - - //////////////////// - // Internal methods and fields - //////////////////// - - - /** - * Sets the last entry executed by the ScriptEngine. - * - * @param entry the ScriptEntry last executed. - */ - public void setLastEntryExecuted(ScriptEntry entry) { - lastEntryExecuted = entry; - } - - - protected abstract boolean shouldRevolve(); - - - protected void revolve() { - // If entries queued up are empty, deconstruct the queue. - if (script_entries.isEmpty()) { - stop(); - return; - } - - if (!shouldRevolve()) return; - - // Criteria met for a successful 'revolution' of this queue, - // so send the next script entry to the ScriptEngine. - DenizenAPI.getCurrentInstance().getScriptEngine().revolve(this); - - if (script_entries.isEmpty()) { - stop(); - } - } - - - public ScriptEntry getNext() { - if (!script_entries.isEmpty()) { - return script_entries.remove(0); - } - else return null; - } - - - public ScriptQueue addEntries(List entries) { - script_entries.addAll(entries); - return this; - } - - - public List getEntries() { - return script_entries; - } - - - public boolean hasInjectedItems = false; - - - public ScriptQueue injectEntries(List entries, int position) { - if (position > script_entries.size() || position < 0) position = 1; - if (script_entries.size() == 0) position = 0; - script_entries.addAll(position, entries); - hasInjectedItems = true; - return this; - } - - - public boolean removeEntry(int position) { - if (script_entries.size() < position) return false; - script_entries.remove(position); - return true; - } - - - public ScriptEntry getEntry(int position) { - if (script_entries.size() < position) return null; - return script_entries.get(position); - } - - - public ScriptQueue injectEntry(ScriptEntry entry, int position) { - if (position > script_entries.size() || position < 0) position = 1; - if (script_entries.size() == 0) position = 0; - script_entries.add(position, entry); - hasInjectedItems = true; - return this; - } - - - public int getQueueSize() { - return script_entries.size(); - } - - - // DEBUGGABLE - // - - @Override - public boolean shouldDebug() throws Exception { - return (lastEntryExecuted != null ? lastEntryExecuted.shouldDebug() - : script_entries.get(0).shouldDebug()); - } - - @Override - public boolean shouldFilter(String criteria) throws Exception { - return (lastEntryExecuted != null ? lastEntryExecuted.getScript().getName().equalsIgnoreCase(criteria.replace("s@", "")) - : script_entries.get(0).getScript().getName().equalsIgnoreCase(criteria.replace("s@", ""))); - } - - - // dOBJECT - // - - /** - * Gets a Queue Object from a string form of q@queue_name. - * - * @param string the string or dScript argument String - * @return a ScriptQueue, or null if incorrectly formatted - * - */ - @Fetchable("q") - public static ScriptQueue valueOf(String string) { - if (string == null) return null; - - if (string.startsWith("q@") && string.length() > 2) - string = string.substring(2); - - if (_queueExists(string)) - return _getExistingQueue(string); - - return null; - } - - - public static boolean matches(String string) { - // Starts with q@? Assume match. - if (string.toLowerCase().startsWith("q@")) return true; - else return false; - } - - String prefix = "Queue"; - - - @Override - public String getPrefix() { - return prefix; - } - - - @Override - public ScriptQueue setPrefix(String prefix) { - this.prefix = prefix; - return this; - } - - - @Override - public String debug() { - return "" + prefix + "='" + identify() + "' "; - } - - @Override - public boolean isUnique() { - return true; - } - - @Override - public String getObjectType() { - return "queue"; - } - - @Override - public String identify() { - return "q@" + id; - } - - @Override - public String identifySimple() { - return identify(); - } - - @Override - public String toString() { - return identify(); - } - - @Override - public String getAttribute(Attribute attribute) { - if (attribute == null) return null; - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the id of the queue. - // --> - if (attribute.startsWith("id")) { - return new Element(id).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the number of script entries in the queue. - // --> - if (attribute.startsWith("size")) { - return new Element(script_entries.size()).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Duration - // @description - // Returns the time this queue started as a duration. - // --> - if (attribute.startsWith("start_time")) { - return new Duration(startTime / 50).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns 'stopping', 'running', or 'unknown'. - // --> - if (attribute.startsWith("state")) { - String state; - if (is_started) state = "running"; - else if (is_stopping) state = "stopping"; - else state = "unknown"; - return new Element(state).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dScript - // @description - // Returns the script that started this queue. - // --> - if (attribute.startsWith("script") && script != null) { - return script.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // Returns a list of commands waiting in the queue. - // --> - if (attribute.startsWith("commands")) { - dList commands = new dList(); - for (ScriptEntry entry: script_entries) { - StringBuilder sb = new StringBuilder(); - sb.append(entry.getCommandName()).append(" "); - for (String arg: entry.getOriginalArguments()) { - sb.append(arg).append(" "); - } - commands.add(sb.substring(0, sb.length() - 1)); - } - return commands.getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dList - // @description - // Returns the names of all definitions that were passed to the current queue. - // --> - if (attribute.startsWith("definitions")) { - return new dList(getAllDefinitions().keySet()).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute ]> - // @returns dList - // @description - // Returns the value of the specified definition. - // Returns null if the queue lacks the definition. - // --> - if (attribute.startsWith("definition") - && attribute.hasContext(1)) { - return new Element(getDefinition(attribute.getContext(1))).getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns dObject - // @description - // Returns the value that has been determined via <@link command Determine> - // for this queue, or null if there is none. - // The object will be returned as the most-valid type based on the input. - // --> - if (attribute.startsWith("determination")) { - if (reqId < 0 || !DetermineCommand.hasOutcome(reqId)) - return null; - else - return ObjectFetcher.pickObjectFor(DetermineCommand.readOutcome(reqId)).getAttribute(attribute.fulfill(1)); - } - - // Iterate through this object's properties' attributes - for (Property property : PropertyParser.getProperties(this)) { - String returned = property.getAttribute(attribute); - if (returned != null) return returned; - } - - return new Element(identify()).getAttribute(attribute); - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/queues/core/Delayable.java b/src/main/java/net/aufdemrand/denizen/scripts/queues/core/Delayable.java deleted file mode 100644 index a8baba6811..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/queues/core/Delayable.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.aufdemrand.denizen.scripts.queues.core; - -import net.aufdemrand.denizen.objects.Duration; - -public interface Delayable { - - public Delayable setPaused(boolean paused); - - public boolean isPaused(); - - public void delayFor(Duration duration); - - public boolean isDelayed(); -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/queues/core/InstantQueue.java b/src/main/java/net/aufdemrand/denizen/scripts/queues/core/InstantQueue.java deleted file mode 100644 index 3ffe6a3121..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/queues/core/InstantQueue.java +++ /dev/null @@ -1,85 +0,0 @@ -package net.aufdemrand.denizen.scripts.queues.core; - - -import net.aufdemrand.denizen.objects.Duration; -import net.aufdemrand.denizen.objects.Element; -import net.aufdemrand.denizen.scripts.queues.ScriptQueue; -import net.aufdemrand.denizen.tags.Attribute; - -public class InstantQueue extends ScriptQueue { - - /** - * Gets an InstantQueue instance. - * - * If a queue already exists with the given id, it will return that instance, - * which may be currently running, unless the type of Queue is not an InstantQueue. - * If a queue does not exist, a new stopped queue is created instead. - * - * IDs are case insensitive. If having an easy-to-recall ID is not necessary, just - * pass along null as the id, and it will use ScriptQueue's static method _getNextId() - * which will return a random UUID. - * - * The default speed node will be automatically read from the configuration, - * and new ScriptQueues may need further information before they - * can start(), including entries, delays, loops, and possibly context. - * - * @param id unique id of the queue - * @return a ScriptQueue - */ - public static InstantQueue getQueue(String id) { - // Get id if not specified. - if (id == null) throw new IllegalArgumentException("ID cannot be null!"); - InstantQueue scriptQueue; - // Does the queue already exist? - if (_queueExists(id)) - scriptQueue = (InstantQueue) _queues.get(id); - // If not, create a new one. - else { - scriptQueue = new InstantQueue(id); - } - return scriptQueue; - } - - - ///////////////////// - // Private instance fields and constructors - ///////////////////// - - public InstantQueue(String id) { - super(id); - } - - @Override - public void onStart() { - while (is_started) revolve(); - } - - public void onStop() { - // Nothing to do here! - } - - @Override - protected boolean shouldRevolve() { - // Instant queues aren't picky! - return true; - } - - - @Override - public String getAttribute(Attribute attribute) { - - // Meta defined in TimedQueue - if (attribute.startsWith("speed")) { - return new Duration(0).getAttribute(attribute.fulfill(1)); - } - - // Meta defined in TimedQueue - if (attribute.startsWith("type")) { - - return new Element("Instant").getAttribute(attribute.fulfill(1)); - } - - return super.getAttribute(attribute); - - } -} diff --git a/src/main/java/net/aufdemrand/denizen/scripts/queues/core/TimedQueue.java b/src/main/java/net/aufdemrand/denizen/scripts/queues/core/TimedQueue.java deleted file mode 100644 index e2812fef99..0000000000 --- a/src/main/java/net/aufdemrand/denizen/scripts/queues/core/TimedQueue.java +++ /dev/null @@ -1,197 +0,0 @@ -package net.aufdemrand.denizen.scripts.queues.core; - -import net.aufdemrand.denizen.Settings; -import net.aufdemrand.denizen.objects.Duration; -import net.aufdemrand.denizen.objects.Element; -import net.aufdemrand.denizen.scripts.queues.ScriptQueue; -import net.aufdemrand.denizen.tags.Attribute; -import net.aufdemrand.denizen.utilities.DenizenAPI; -import org.bukkit.Bukkit; - -public class TimedQueue extends ScriptQueue implements Delayable { - - /** - * Gets a TimedQueue instance. - * - * If a queue already exists with the given id, it will return that instance, - * which may be currently running, unless the type of queue is not a TimedQueue. - * If a queue does not exist, a new stopped queue is created instead. - * - * IDs are case insensitive. If having an easy-to-recall ID is not necessary, just - * pass along null as the id, and it will use ScriptQueue's static method _getNextId() - * which will return a random UUID. - * - * The speed node will be automatically read from the configuration, - * and new ScriptQueues may need further information before they - * can start(), including entries, delays, loops, and possibly context. - * - * @param id unique id of the queue - * @return a TimedQueue - */ - public static TimedQueue getQueue(String id) { - // Get id if not specified. - if (id == null) throw new IllegalArgumentException("ID cannot be null!"); - TimedQueue scriptQueue; - // Does the queue already exist? Get it if it does. - if (_queueExists(id)) - scriptQueue = (TimedQueue) ScriptQueue._queues.get(id); - // If not, create a new one. - else { - scriptQueue = new TimedQueue(id, - Duration.valueOf(Settings.scriptQueueSpeed())); - } - // Return the queue - return scriptQueue; - } - - ///////////////////// - // Private instance fields and constructors - ///////////////////// - - - // Keep track of Bukkit's Scheduler taskId - // for the engine, used when it times out. - private int task_id; - - - // The speed of the engine, the # of ticks - // between each revolution. Use setSpeed() - // to change this. - private long ticks; - - - // ScriptQueues can be paused mid-rotation. - // The next entry will be held up until - // un-paused. - protected boolean paused = false; - - - // The delay in ticks can put off the - // start of a queue - protected long delay_ticks = 0; - - - @Override - public void delayFor(Duration duration) { - delay_ticks = System.currentTimeMillis() + duration.getMillis(); - } - - @Override - public boolean isDelayed() { - return (delay_ticks > System.currentTimeMillis()); - } - - - public TimedQueue(String id, Duration timing) { - super(id); - ticks = timing.getTicks(); - } - - ///////////////////// - // Public instance setters and getters - ///////////////////// - - - /** - * Gets the speed of the queue. This is the - * time in between each revolution. ' - * - * @return a Duration of the speed. - */ - public Duration getSpeed() { - return new Duration(ticks); - } - - - /** - * Pauses the queue. Paused queues will check - * to be re-resumed every 'rotation', defined - * by the speed of the queue. - * - * @param paused whether the queue should be paused - */ - @Override - public Delayable setPaused(boolean paused) { - this.paused = paused; - return this; - } - - - /** - * Checks if the queue is currently paused. - * - * @return true if paused. - */ - @Override - public boolean isPaused() { - return paused; - } - - - /** - * Sets the speed of a queue. Uses bukkit's 'ticks', which is - * 20 ticks per second. - * - * @param ticks the number of ticks between each rotation. - */ - public TimedQueue setSpeed(long ticks) { - this.ticks = ticks; - return this; - } - - - @Override - protected void onStart() { - // Do the first revolution now... - revolve(); - // ...and schedule the rest for later. - task_id = Bukkit.getScheduler().scheduleSyncRepeatingTask(DenizenAPI.getCurrentInstance(), - new Runnable() { - @Override public void run() { revolve(); } - }, ticks == 0 ? 1 : ticks, ticks == 0 ? 1 : ticks); - } - - - @Override - protected void onStop() { - Bukkit.getScheduler().cancelTask(task_id); - } - - - @Override - protected boolean shouldRevolve() { - // Check if this Queue isn't paused - if (paused) return false; - - // If it's delayed, schedule it for later - return !isDelayed(); - } - - - @Override - public String getAttribute(Attribute attribute) { - - // <--[tag] - // @attribute - // @returns Duration - // @description - // Returns the speed of the queue as a Duration. A return of '0t' implies it is 'instant'. - // --> - if (attribute.startsWith("speed")) { - return getSpeed().getAttribute(attribute.fulfill(1)); - } - - // <--[tag] - // @attribute - // @returns Element - // @description - // Returns the type of queue. - // --> - if (attribute.startsWith("type")) { - return new Element("Timed").getAttribute(attribute.fulfill(1)); - } - - return super.getAttribute(attribute); - - } -}