From 77d105227c4e8bc13b6a68d62456f635d4617887 Mon Sep 17 00:00:00 2001 From: MCSamuel Date: Wed, 22 Oct 2025 22:06:23 -0700 Subject: [PATCH 1/3] ElementTag meta updates --- .../denizencore/objects/core/ElementTag.java | 124 +++++++++++------- 1 file changed, 79 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java b/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java index e26f9d98..2adf34e3 100644 --- a/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java +++ b/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java @@ -419,7 +419,7 @@ public boolean isUnique() { @Override public boolean isTruthy() { - if (element.equals("") || CoreUtilities.equalsIgnoreCase(element, "null") || CoreUtilities.equalsIgnoreCase(element, "false")) { + if (element.isEmpty() || CoreUtilities.equalsIgnoreCase(element, "null") || CoreUtilities.equalsIgnoreCase(element, "false")) { return false; } if (ArgumentHelper.matchesDouble(element)) { @@ -981,7 +981,9 @@ public static void register() { // @description // Returns the specific group from a regex match. // Specify group 0 for the whole match. - // For example, returns '5'. + // @example + // # Narrates "5" + // - narrate // --> tagProcessor.registerTag(ElementTag.class, "regex", (attribute, object) -> { // non-static due to hacked sub-tag if (!attribute.hasParam() || !attribute.hasContext(2)) { @@ -1158,19 +1160,17 @@ else if (elem.equals("false")) { // @group element manipulation // @description // Returns a copy of the element, repeated the specified number of times. - // For example, "hello" .repeat[3] returns "hellohellohello" // An input value or zero or a negative number will result in an empty element. + // @example + // # Narrates "hellohellohello" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "repeat", (attribute, object, countText) -> { int repeatTimes = countText.asInt(); if (repeatTimes <= 0) { return new ElementTag(""); } - StringBuilder result = new StringBuilder(object.element.length() * repeatTimes); - for (int i = 0; i < repeatTimes; i++) { - result.append(object.element); - } - return new ElementTag(result.toString()); + return new ElementTag(object.element.repeat(repeatTimes)); }); // <--[tag] @@ -1179,7 +1179,9 @@ else if (elem.equals("false")) { // @group element manipulation // @description // Returns the portion of an element after the last occurrence of a specified element. - // For example: abcabc .after_last[b] returns c. + // @example + // # Narrates "c" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "after_last", (attribute, object, delimiter) -> { if (CoreUtilities.toLowerCase(object.element).contains(delimiter.asLowerString())) { @@ -1197,7 +1199,9 @@ else if (elem.equals("false")) { // @group element manipulation // @description // Returns the portion of an element after the first occurrence of a specified element. - // For example: HelloWorld .after[Hello] returns World. + // @example + // # Narrates "World" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "after", (attribute, object, delimiter) -> { if (CoreUtilities.toLowerCase(object.element).contains(delimiter.asLowerString())) { @@ -1215,7 +1219,9 @@ else if (elem.equals("false")) { // @group element manipulation // @description // Returns the portion of an element before the last occurrence of a specified element. - // For example: abcabc .before_last[b] returns abca. + // @example + // # Narrates "abca" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "before_last", (attribute, object, delimiter) -> { if (CoreUtilities.toLowerCase(object.element).contains(delimiter.asLowerString())) { @@ -1233,7 +1239,9 @@ else if (elem.equals("false")) { // @group element manipulation // @description // Returns the portion of an element before the first occurrence of specified element. - // For example: abcd .before[c] returns ab. + // @example + // # Narrates "ab" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "before", (attribute, object, delimiter) -> { if (CoreUtilities.toLowerCase(object.element).contains(delimiter.asLowerString())) { @@ -1258,7 +1266,7 @@ else if (elem.equals("false")) { // @returns ElementTag // @group element manipulation // @description - // Returns the element with all instances of a element replaced with another. + // Returns the element with all instances of an element replaced with another. // Specify regex: at the start of the replace element to use Regex replacement. // Specify firstregex: at the start of the replace element to Regex 'replaceFirst' // --> @@ -1298,9 +1306,11 @@ else if (elem.equals("false")) { // @synonyms ElementTag.number_with_commas, ElementTag.thousands_separated // @description // Returns a number reformatted for easier reading. - // For example: 1234567 will become 1,234,567. // Optionally, specify a standard number format code to instead use that. // For information on that optional input, refer to <@link url https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html>. + // @example + // # Narrates "1,234,567" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, "format_number", (attribute, object) -> { try { @@ -1439,7 +1449,7 @@ else if (elem.equals("false")) { // @returns ElementTag // @group element manipulation // @description - // Returns The Value Of An ElementTag In Title Case (The First Letter Of Each Word Is Capitalized, Based On Spaces). + // Returns The Value Of An ElementTag In Title Case (The First Letter Of Each Word Is Uppercase, Based On Spaces). // --> tagProcessor.registerStaticTag(ElementTag.class, "to_titlecase", (attribute, object) -> { if (object.element.isEmpty()) { @@ -1469,10 +1479,7 @@ else if (elem.equals("false")) { // Returns the value in sentence case (the first letter capitalized, the rest lowercase). // --> tagProcessor.registerStaticTag(ElementTag.class, "to_sentence_case", (attribute, object) -> { - if (object.element.length() == 0) { - return new ElementTag(""); - } - return new ElementTag(Character.toUpperCase(object.element.charAt(0)) + object.element.substring(1).toLowerCase()); + return new ElementTag(object.element.isEmpty() ? "" : Character.toUpperCase(object.element.charAt(0)) + object.element.substring(1).toLowerCase()); }); // <--[tag] @@ -1481,7 +1488,9 @@ else if (elem.equals("false")) { // @group element manipulation // @description // Returns the element in roman numeral form. Must be in the range of 1 and 4000 (inclusive). - // For example: returns MCLXIX. + // @example + // # Narrates "MCLXIX" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, "to_roman_numerals", (attribute, object) -> { if (!object.isInt()) { @@ -1502,7 +1511,9 @@ else if (elem.equals("false")) { // @group element manipulation // @description // Returns the roman numeral string in integer form. - // For example: returns 1169. + // @example + // # Narrates "1169" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, "from_roman_numerals", (attribute, object) -> { int result = RomanNumerals.romanToArabic(object.element); @@ -1521,7 +1532,9 @@ else if (elem.equals("false")) { // Returns the portion of an element between two element indices. // If no second index is specified, it will return the portion of an // element after the specified index. - // For example: returns "ell" + // @example + // # Narrates "ell" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "substring", (attribute, object, indices) -> { String[] split = indices.asString().split(","); @@ -1673,7 +1686,9 @@ else if (elem.equals("false")) { // @group math // @description // Returns the absolute value of the element. - // For example: returns 5. + // @example + // # Narrates "5" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, "abs", (attribute, ele) -> { if (!ele.isDouble()) { @@ -1690,7 +1705,9 @@ else if (elem.equals("false")) { // @group math // @description // Returns the higher number: this element or the specified one. - // For example: returns 10. + // @example + // # Narrates "10" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "max", (attribute, ele, second) -> { if (!ele.isDouble() || !second.isDouble()) { @@ -1707,7 +1724,9 @@ else if (elem.equals("false")) { // @group math // @description // Returns the lower number: this element or the specified one. - // For example: returns 5. + // @example + // # Narrates "5" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "min", (attribute, ele, second) -> { if (!ele.isDouble() || !second.isDouble()) { @@ -1915,10 +1934,7 @@ else if (elem.equals("false")) { attribute.echoError("Element '" + ele + "' is not a valid decimal number!"); return null; } - if (ele.asDouble() < 0) { - return null; - } - return new ElementTag(Math.sqrt(ele.asDouble())); + return ele.asDouble() >= 0 ? new ElementTag(Math.sqrt(ele.asDouble())) : null; }); // <--[tag] @@ -2162,7 +2178,9 @@ else if (elem.equals("false")) { // @group math // @description // Rounds a decimal to the specified place. - // For example, 0.12345 .round_to[3] returns "0.123". + // @example + // # Narrates "0.123" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "round_to", (attribute, object, to) -> { if (!object.isDouble() || !to.isDouble()) { @@ -2182,7 +2200,9 @@ else if (elem.equals("false")) { // @group math // @description // Rounds a decimal to the specified precision. - // For example, 0.12345 .round_to_precision[0.005] returns "0.125". + // @example + // # Narrates "0.125" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "round_to_precision", (attribute, object, precText) -> { if (!object.isDouble() || !precText.isDouble()) { @@ -2249,9 +2269,11 @@ else if (elem.equals("false")) { // @group conversion // @description // Encodes base-10 integer number to hexadecimal (base-16) format. - // For example input of "15" will return "F". // See also <@link tag ElementTag.hex_to_number> // Consider instead <@link tag ElementTag.integer_to_binary> + // @example + // # Narrates "F" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, "number_to_hex", (attribute, object) -> { if (!object.isInt()) { @@ -2267,9 +2289,11 @@ else if (elem.equals("false")) { // @group conversion // @description // Encodes base-16 hexadecimal value to an integer number. - // For example input of "F" will return "15". // See also <@link tag ElementTag.number_to_hex> // Consider instead <@link tag BinaryTag.decode_integer> + // @example + // # Narrates "15" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, "hex_to_number", (attribute, object) -> { if (!ArgumentHelper.HEX_MATCHER.isOnlyMatches(object.element)) { @@ -2449,10 +2473,15 @@ else if (elem.equals("false")) { // Returns true if the element contains only symbols from the given character set. // The character set is expected to be ASCII only. // This tag is case-sensitive. - // For example: - // "alphabet" .matches_character_set[abcdefghijklmnopqrstuvwxyz]> returns "true", - // "Alphabet" .matches_character_set[abcdefghijklmnopqrstuvwxyz]> returns "false" because it has a capital "A", - // and "alphabet1" .matches_character_set[abcdefghijklmnopqrstuvwxyz]> returns "false" because it has a "1". + // @example + // # Narrates "true" + // - narrate + // @example + // # Narrates "false" because it has a capital "A" + // - narrate + // @example + // # Narrates "false" because it has a "1" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "matches_character_set", (attribute, object, set) -> { return new ElementTag(new AsciiMatcher(set.element).isOnlyMatches(object.element)); // TODO: Caching! @@ -2466,10 +2495,15 @@ else if (elem.equals("false")) { // Returns only the characters within the element that match the character set. // The character set is expected to be ASCII only. // This tag is case-sensitive. - // For example: - // "alphabet" .trim_to_character_set[abcdefghijklmnopqrstuvwxyz]> returns "alphabet", - // "Alphabet" .trim_to_character_set[abcdefghijklmnopqrstuvwxyz]> returns "lphabet" without the capital "A". - // and "alphabet1" .trim_to_character_set[abcdefghijklmnopqrstuvwxyz]> returns "alphabet" without the "1". + // @example + // # Narrates "alphabet" + // - narrate + // @example + // # Narrates "lphabet" without the capital "A" + // - narrate + // @example + // # Narrates "alphabet" without the "1" + // - narrate // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "trim_to_character_set", (attribute, object, set) -> { return new ElementTag(new AsciiMatcher(set.element).trimToMatches(object.element)); // TODO: Caching! @@ -2482,8 +2516,9 @@ else if (elem.equals("false")) { // @description // If this element is 'true', returns the first given object. If it isn't 'true', returns the second given object. // If the input objects are tags, only the matching tag will be parsed. - // For example: "].if_false[server]>" - // will return the player's name if there's a player present, or if not will return 'server', and won't show any errors from the '' tag even without a player linked. + // @example + // # Narrates the player's name if there's a player present, or if not will return "server", and won't show any errors from the "" tag even without a player linked. + // - narrate ].if_false[server]> // --> tagProcessor.registerTag(ObjectTag.class, "if_true", (attribute, object) -> { // non-static due to hacked sub-tag if (!attribute.hasParam() || !attribute.startsWith("if_false", 2) || !attribute.hasContext(2)) { @@ -2566,10 +2601,9 @@ public boolean equals(Object o) { if (this == o) { return true; } - if (!(o instanceof ElementTag)) { + if (!(o instanceof ElementTag other)) { return false; } - ElementTag other = (ElementTag) o; return element.equals(other.element); } From 7a5121d3796403d834820ce75718109711e170ab Mon Sep 17 00:00:00 2001 From: MCSamuel Date: Tue, 4 Nov 2025 13:36:52 -0800 Subject: [PATCH 2/3] slight changes --- .../denizencore/objects/core/ElementTag.java | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java b/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java index 2adf34e3..955537f9 100644 --- a/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java +++ b/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java @@ -948,8 +948,7 @@ public static void register() { // Returns whether the element ends with a specified element. // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "ends_with", (attribute, object, compare) -> { - return new ElementTag(CoreUtilities.toLowerCase(object.element). - endsWith(compare.asLowerString())); + return new ElementTag(CoreUtilities.toLowerCase(object.element).endsWith(compare.asLowerString())); }, "endswith"); // <--[tag] @@ -985,11 +984,11 @@ public static void register() { // # Narrates "5" // - narrate // --> - tagProcessor.registerTag(ElementTag.class, "regex", (attribute, object) -> { // non-static due to hacked sub-tag - if (!attribute.hasParam() || !attribute.hasContext(2)) { + tagProcessor.registerTag(ElementTag.class, ElementTag.class, "regex", (attribute, object, param) -> { // non-static due to hacked sub-tag + if (!attribute.hasContext(2)) { return null; } - String regex = attribute.getParam(); + String regex = param.toString(); Matcher m = Pattern.compile(regex).matcher(object.element); if (!m.matches()) { return null; @@ -1111,8 +1110,7 @@ else if (elem.equals("false")) { // Returns 0 if the element never occurs within the element. // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "index_of", (attribute, object, compare) -> { - return new ElementTag(CoreUtilities.toLowerCase(object.element) - .indexOf(compare.asLowerString()) + 1); + return new ElementTag(CoreUtilities.toLowerCase(object.element).indexOf(compare.asLowerString()) + 1); }); // <--[tag] @@ -1124,8 +1122,7 @@ else if (elem.equals("false")) { // Returns 0 if the element never occurs within the element. // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "last_index_of", (attribute, object, compare) -> { - return new ElementTag(CoreUtilities.toLowerCase(object.element) - .lastIndexOf(compare.asLowerString()) + 1); + return new ElementTag(CoreUtilities.toLowerCase(object.element).lastIndexOf(compare.asLowerString()) + 1); }); // <--[tag] @@ -1167,10 +1164,7 @@ else if (elem.equals("false")) { // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "repeat", (attribute, object, countText) -> { int repeatTimes = countText.asInt(); - if (repeatTimes <= 0) { - return new ElementTag(""); - } - return new ElementTag(object.element.repeat(repeatTimes)); + return new ElementTag(repeatTimes <= 0 ? "" : object.element.repeat(repeatTimes)); }); // <--[tag] @@ -1270,12 +1264,8 @@ else if (elem.equals("false")) { // Specify regex: at the start of the replace element to use Regex replacement. // Specify firstregex: at the start of the replace element to Regex 'replaceFirst' // --> - tagProcessor.registerTag(ElementTag.class, "replace_text", (attribute, object) -> { // non-static due to hacked sub-tag - if (!attribute.hasParam()) { - attribute.echoError("The tag ElementTag.replace[...] must have a value."); - return null; - } - String replace = attribute.getParam(); + tagProcessor.registerTag(ElementTag.class, ElementTag.class, "replace_text", (attribute, object, param) -> { // non-static due to hacked sub-tag + String replace = param.toString(); String replacement = ""; if (attribute.startsWith("with", 2)) { if (attribute.hasContext(2)) { @@ -1382,8 +1372,7 @@ else if (elem.equals("false")) { // Spaces will be preferred to become newlines, unless a line does not contain any spaces. // --> tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "split_lines", (attribute, object, countText) -> { - int characterCount = countText.asInt(); - return new ElementTag(CoreUtilities.splitLinesByCharacterCount(object.element, characterCount)); + return new ElementTag(CoreUtilities.splitLinesByCharacterCount(object.element, countText.asInt())); }); // <--[tag] From 44e1426b14f145c9ee5834a9bb2db84342f140af Mon Sep 17 00:00:00 2001 From: MCSamuel Date: Sun, 30 Nov 2025 09:01:48 -0800 Subject: [PATCH 3/3] minor changes --- .../denizencore/objects/core/ElementTag.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java b/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java index 955537f9..fd43ca35 100644 --- a/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java +++ b/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java @@ -988,7 +988,7 @@ public static void register() { if (!attribute.hasContext(2)) { return null; } - String regex = param.toString(); + String regex = param.asString(); Matcher m = Pattern.compile(regex).matcher(object.element); if (!m.matches()) { return null; @@ -1437,8 +1437,9 @@ else if (elem.equals("false")) { // @attribute // @returns ElementTag // @group element manipulation + // @synonyms ElementTag.first_letter_uppercase // @description - // Returns The Value Of An ElementTag In Title Case (The First Letter Of Each Word Is Uppercase, Based On Spaces). + // Returns The Value Of An ElementTag In Title Case (The First Letter Of Each Word Is Capitalized, Based On Spaces). // --> tagProcessor.registerStaticTag(ElementTag.class, "to_titlecase", (attribute, object) -> { if (object.element.isEmpty()) { @@ -1468,7 +1469,10 @@ else if (elem.equals("false")) { // Returns the value in sentence case (the first letter capitalized, the rest lowercase). // --> tagProcessor.registerStaticTag(ElementTag.class, "to_sentence_case", (attribute, object) -> { - return new ElementTag(object.element.isEmpty() ? "" : Character.toUpperCase(object.element.charAt(0)) + object.element.substring(1).toLowerCase()); + if (object.element.isEmpty()) { + return new ElementTag(""); + } + return new ElementTag(Character.toUpperCase(object.element.charAt(0)) + object.element.substring(1).toLowerCase()); }); // <--[tag]