diff --git a/src/main/java/com/denizenscript/denizencore/DenizenImplementation.java b/src/main/java/com/denizenscript/denizencore/DenizenImplementation.java index 80276c91..940eab9d 100644 --- a/src/main/java/com/denizenscript/denizencore/DenizenImplementation.java +++ b/src/main/java/com/denizenscript/denizencore/DenizenImplementation.java @@ -9,6 +9,7 @@ import com.denizenscript.denizencore.scripts.containers.ScriptContainer; import com.denizenscript.denizencore.scripts.queues.ScriptQueue; import com.denizenscript.denizencore.tags.TagContext; +import com.denizenscript.denizencore.utilities.DefinitionProvider; import java.io.File; @@ -91,6 +92,8 @@ public interface DenizenImplementation { void doFinalDebugOutput(String rawText); + void addFormatScriptDefinitions(DefinitionProvider provider, TagContext context); + String stripColor(String message); void reloadConfig(); 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 dcef3f4f..e26f9d98 100644 --- a/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java +++ b/src/main/java/com/denizenscript/denizencore/objects/core/ElementTag.java @@ -2,6 +2,7 @@ import com.denizenscript.denizencore.events.ScriptEvent; import com.denizenscript.denizencore.objects.*; +import com.denizenscript.denizencore.scripts.containers.core.FormatScriptContainer; import com.denizenscript.denizencore.tags.*; import com.denizenscript.denizencore.tags.core.EscapeTagUtil; import com.denizenscript.denizencore.utilities.*; @@ -2286,7 +2287,7 @@ else if (elem.equals("false")) { // Returns a BinaryTag holding 8 bytes of this integer number converted to binary format using big-endian 64-bit integer twos-complement encoding. // @example // # Narrates '00000000000000ff' - // - narrate + // - narrate // --> tagProcessor.registerStaticTag(BinaryTag.class, "integer_to_binary", (attribute, object) -> { ByteBuffer buffer = ByteBuffer.allocate(8); @@ -2536,6 +2537,21 @@ else if (elem.equals("false")) { tagProcessor.registerStaticTag(ElementTag.class, "unaccented", (attribute, object) -> { return new ElementTag(UNACCENTED_PATTERN.matcher(Normalizer.normalize(object.asString(), Normalizer.Form.NFKD)).replaceAll(""), true); }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Returns the text re-formatted according to a <@link language Format Script Containers>. + // --> + ElementTag.tagProcessor.registerTag(ElementTag.class, ScriptTag.class, "format", (attribute, object, format) -> { + if (!(format.getContainer() instanceof FormatScriptContainer formatScript) || formatScript.getFormatTag() == null) { + attribute.echoError("Script '" + format + "' is not a format script."); + return null; + } + return new ElementTag(formatScript.getFormattedText(object.asString(), attribute.context)); + }); } public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>(); diff --git a/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java b/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java index 0b626797..b04a0637 100644 --- a/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java +++ b/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java @@ -142,6 +142,10 @@ public MapTag(Map map) { this.map = new LinkedHashMap<>(map); } + public MapTag(MapTag mapTag) { + this(mapTag.map); + } + @Override public MapTag duplicate() { MapTag newMap = new MapTag(); diff --git a/src/main/java/com/denizenscript/denizencore/scripts/ScriptEntry.java b/src/main/java/com/denizenscript/denizencore/scripts/ScriptEntry.java index 4686e588..1da78c8b 100644 --- a/src/main/java/com/denizenscript/denizencore/scripts/ScriptEntry.java +++ b/src/main/java/com/denizenscript/denizencore/scripts/ScriptEntry.java @@ -766,6 +766,10 @@ public ScriptTag getScript() { return internal.script; } + public ScriptContainer getScriptContainer() { + return getScript() != null ? getScript().getContainer() : null; + } + public ScriptEntry setScript(String scriptName) { internal.script = ScriptTag.valueOf(scriptName, CoreUtilities.basicContext); return this; diff --git a/src/main/java/com/denizenscript/denizencore/scripts/ScriptFormattingContext.java b/src/main/java/com/denizenscript/denizencore/scripts/ScriptFormattingContext.java new file mode 100644 index 00000000..6f0c6940 --- /dev/null +++ b/src/main/java/com/denizenscript/denizencore/scripts/ScriptFormattingContext.java @@ -0,0 +1,103 @@ +package com.denizenscript.denizencore.scripts; + +import com.denizenscript.denizencore.DenizenCore; +import com.denizenscript.denizencore.scripts.containers.ScriptContainer; +import com.denizenscript.denizencore.scripts.containers.core.FormatScriptContainer; +import com.denizenscript.denizencore.tags.ParseableTag; +import com.denizenscript.denizencore.tags.TagContext; +import com.denizenscript.denizencore.tags.TagManager; +import com.denizenscript.denizencore.utilities.CoreUtilities; +import com.denizenscript.denizencore.utilities.YamlConfiguration; +import com.denizenscript.denizencore.utilities.debugging.Debug; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public record ScriptFormattingContext(Map formats, ParseableTag singleFormat) { + + // <--[language] + // @name Script Logging Format + // @group Script Container System + // @description + // Script logging contexts provide the format certain commands will use for their texts. Most notably, this includes <@link command debug>. + // See specific command's documentation for information on which formats they use (for example, the 'debug' command supports a 'debug' format and an 'error' format). + // The formats are specified under a 'formats' key, and can be either a <@link language Format Script Containers> or a direct format with the same syntax as format scripts. + // When specifying a direct format, use the format name as the key; When specifying a format script, use '_script' as the key (see example below). + // + // my_project_task: + // type: task + // formats: + // # A direct format + // debug: [MyProject] <[text]> + // # A separate format script + // error_script: my_project_error + // script: + // - if > 20: + // # Will be formatted by the 'my_project_error' format script. + // - debug error "The system has been running for over 20 hours! Please restart!" + // - else: + // # Will print "[MyProject] The system does not need a restart yet." + // - debug "The system does not need a restart yet." + // + // --> + + public static final Set FORMAT_TYPES = new HashSet<>(); + + public static String registerFormatType(String name) { + String nameLower = CoreUtilities.toLowerCase(name); + if (!FORMAT_TYPES.add(nameLower)) { + throw new IllegalArgumentException("Tried registering duplicate format type! format '" + name + "' already exists."); + } + return nameLower; + } + + public static ScriptFormattingContext parseFromConfiguration(ScriptContainer script) { + YamlConfiguration formatsConfig = script.getConfigurationSection("formats"); + if (formatsConfig == null) { + return null; + } + Map formats = new HashMap<>(); + TagContext context = null; + for (String formatType : FORMAT_TYPES) { + String rawFormat = formatsConfig.getString(formatType); + if (rawFormat != null) { + if (context == null) { + context = DenizenCore.implementation.getTagContext(script); + } + formats.put(formatType, TagManager.parseTextToTag(rawFormat, context)); + continue; + } + String formatScriptInput = formatsConfig.getString(formatType + "_script"); + if (formatScriptInput == null) { + continue; + } + FormatScriptContainer formatScript = ScriptRegistry.getScriptContainerAs(formatScriptInput, FormatScriptContainer.class); + if (formatScript == null || formatScript.getFormatTag() == null) { + Debug.echoError(script, "Invalid format script '" + formatScriptInput + "' specified for format '" + formatType + "'."); + continue; + } + formats.put(formatType, formatScript.getFormatTag()); + } + if (formats.isEmpty()) { + Debug.echoError(script, "Invalid formats config, must specify at least one valid format."); + return null; + } + return new ScriptFormattingContext(formats, null); + } + + public boolean hasFormat(String formatType) { + return singleFormat != null || formats.containsKey(formatType); + } + + public String formatOrNull(String formatType, String rawText, ScriptEntry entry) { + ParseableTag formatTag = singleFormat == null ? formats.get(formatType) : singleFormat; + return formatTag != null ? FormatScriptContainer.formatText(formatTag, rawText, entry.getContext(), entry.getScript()) : null; + } + + public String format(String formatType, String rawText, ScriptEntry entry) { + String formatted = formatOrNull(formatType, rawText, entry); + return formatted != null ? formatted : rawText; + } +} diff --git a/src/main/java/com/denizenscript/denizencore/scripts/ScriptRegistry.java b/src/main/java/com/denizenscript/denizencore/scripts/ScriptRegistry.java index 7ead4672..f99d9e5f 100644 --- a/src/main/java/com/denizenscript/denizencore/scripts/ScriptRegistry.java +++ b/src/main/java/com/denizenscript/denizencore/scripts/ScriptRegistry.java @@ -29,6 +29,7 @@ public static void _registerCoreTypes() { _registerType("world", WorldScriptContainer.class); _registerType("data", DataScriptContainer.class); _registerType("yaml data", DataScriptContainer.class); + _registerType("format", FormatScriptContainer.class); } public static boolean containsScript(String id, Class scriptContainerType) { diff --git a/src/main/java/com/denizenscript/denizencore/scripts/commands/core/DebugCommand.java b/src/main/java/com/denizenscript/denizencore/scripts/commands/core/DebugCommand.java index 290bb4d3..861b2b94 100644 --- a/src/main/java/com/denizenscript/denizencore/scripts/commands/core/DebugCommand.java +++ b/src/main/java/com/denizenscript/denizencore/scripts/commands/core/DebugCommand.java @@ -1,20 +1,27 @@ package com.denizenscript.denizencore.scripts.commands.core; +import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.ScriptTag; +import com.denizenscript.denizencore.scripts.ScriptEntry; +import com.denizenscript.denizencore.scripts.ScriptFormattingContext; import com.denizenscript.denizencore.scripts.commands.AbstractCommand; import com.denizenscript.denizencore.scripts.commands.Holdable; import com.denizenscript.denizencore.scripts.commands.generator.*; +import com.denizenscript.denizencore.scripts.containers.ScriptContainer; +import com.denizenscript.denizencore.scripts.containers.core.FormatScriptContainer; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.debugging.Debug; -import com.denizenscript.denizencore.objects.core.ElementTag; -import com.denizenscript.denizencore.scripts.ScriptEntry; import com.denizenscript.denizencore.utilities.debugging.DebugSubmitter; public class DebugCommand extends AbstractCommand implements Holdable { + public static final String DEBUG_FORMAT = ScriptFormattingContext.registerFormatType("debug"); + public static final String ERROR_FORMAT = ScriptFormattingContext.registerFormatType("error"); + public DebugCommand() { setName("debug"); - setSyntax("debug [] [] (name:)"); - setRequiredArguments(2, 3); + setSyntax("debug () [] (name:) (format:)"); + setRequiredArguments(1, 3); isProcedural = true; generateDebug = false; autoCompile(); @@ -22,8 +29,8 @@ public DebugCommand() { // <--[command] // @Name Debug - // @Syntax debug [] [] (name:) - // @Required 2 + // @Syntax debug () [] (name:) (format:) + // @Required 1 // @Maximum 3 // @Short Shows a debug message. // @Group core @@ -32,20 +39,20 @@ public DebugCommand() { // @Description // Use to quickly output debug information to console. // - // Valid types include: + // Outputs plain text debug to the console by default, supporting the 'debug' format type (see <@link language Script Logging Formats>). + // + // Alternatively, specify one of the following debug types: // DEBUG: standard hideable debug. // HEADER: standard hideable debug inside a header line. // FOOTER: a footer line. // SPACER: a spacer line. // LOG: global output, non-hideable. // APPROVAL: "Okay!" output, non-hideable. - // ERROR: "Error!" output, non-hideable. + // ERROR: "Error!" output, non-hideable. Supports the 'error' format type, see <@link language Script Logging Formats>. // REPORT: normally used to describe the arguments of a command, requires a name, hideable. // EXCEPTION: outputs a full java stacktrace. // RECORD: Use message 'start' to start recording, 'submit' to submit a recording, or 'cancel' to cancel a recording. // - // TODO: Should [] be required? Perhaps default to 'debug' mode? - // // @Tags // returns the submit link (if any). // @@ -55,7 +62,7 @@ public DebugCommand() { // // @Usage // Use to add some information to help your own ability to read debug output from you script. - // - debug debug "Time is currently <[milliseconds].div[1000].round> seconds!" + // - debug "Time is currently <[milliseconds].div[1000].round> seconds!" // // @Usage // Use to record a debug log of a certain script. @@ -68,6 +75,7 @@ public DebugCommand() { // --> public enum DebugType { + OUTPUT, DEBUG, HEADER, FOOTER, @@ -88,42 +96,51 @@ public void addCustomTabCompletions(TabCompletionsBuilder tab) { public static void autoExecute(ScriptEntry scriptEntry, @ArgRaw @ArgLinear @ArgName("debug") String debug, - @ArgName("type") DebugType dbType, - @ArgPrefixed @ArgName("name") @ArgDefaultText("name") String name) { + @ArgName("type") @ArgDefaultText("output") DebugType dbType, + @ArgPrefixed @ArgName("name") @ArgDefaultNull String name, + @ArgName("format") @ArgPrefixed @ArgDefaultNull ScriptTag formatScript) { + ScriptFormattingContext formattingContext = null; + ScriptContainer scriptContainer = scriptEntry.getScriptContainer(); + if (formatScript != null) { + if (!(formatScript.getContainer() instanceof FormatScriptContainer formatScriptContainer) || formatScriptContainer.getFormatTag() == null) { + Debug.echoError("Invalid 'format:' script specified: must be a format script container."); + return; + } + formattingContext = formatScriptContainer.getAsFormattingContext(); + } + else if (scriptContainer != null) { + formattingContext = scriptContainer.getFormattingContext(); + } + if (name == null) { + name = scriptContainer != null ? scriptContainer.getOriginalName() : "DebugCommand"; + } if (dbType != DebugType.RECORD) { scriptEntry.setFinished(true); } switch (dbType) { - case DEBUG: - Debug.echoDebug(scriptEntry, debug); - break; - case HEADER: - Debug.echoDebug(scriptEntry, Debug.DebugElement.Header, debug); - break; - case FOOTER: - Debug.echoDebug(scriptEntry, Debug.DebugElement.Footer, debug); - break; - case SPACER: - Debug.echoDebug(scriptEntry, Debug.DebugElement.Spacer, debug); - break; - case LOG: - Debug.log(debug); - break; - case APPROVAL: - Debug.echoApproval(debug); - break; - case ERROR: - Debug.echoError(scriptEntry, debug); - break; - case REPORT: + case OUTPUT -> Debug.echoDebug(null, formattingContext == null ? debug : formattingContext.format(DEBUG_FORMAT, debug, scriptEntry)); + case DEBUG -> Debug.echoDebug(scriptEntry, debug); + case HEADER -> Debug.echoDebug(scriptEntry, Debug.DebugElement.Header, debug); + case FOOTER -> Debug.echoDebug(scriptEntry, Debug.DebugElement.Footer, debug); + case SPACER -> Debug.echoDebug(scriptEntry, Debug.DebugElement.Spacer, debug); + case LOG -> Debug.log(name, debug); + case APPROVAL -> Debug.echoApproval(debug); + case ERROR -> { + String formatted = formattingContext != null ? formattingContext.formatOrNull(ERROR_FORMAT, debug, scriptEntry) : null; + if (formatted != null) { + Debug.echoDebug(null, formatted); + } + else { + Debug.echoError(scriptEntry, debug); + } + } + case REPORT -> { if (scriptEntry.dbCallShouldDebug()) { Debug.report(scriptEntry, name, debug); } - break; - case EXCEPTION: - Debug.echoError(scriptEntry, new RuntimeException(debug)); - break; - case RECORD: + } + case EXCEPTION -> Debug.echoError(scriptEntry, new RuntimeException(debug)); + case RECORD -> { String form = CoreUtilities.toLowerCase(debug); switch (form) { case "start": @@ -156,7 +173,7 @@ else if (s.equals("disabled")) { scriptEntry.setFinished(true); break; } - break; + } } } } diff --git a/src/main/java/com/denizenscript/denizencore/scripts/containers/ScriptContainer.java b/src/main/java/com/denizenscript/denizencore/scripts/containers/ScriptContainer.java index 57610fc4..95876551 100644 --- a/src/main/java/com/denizenscript/denizencore/scripts/containers/ScriptContainer.java +++ b/src/main/java/com/denizenscript/denizencore/scripts/containers/ScriptContainer.java @@ -1,18 +1,20 @@ package com.denizenscript.denizencore.scripts.containers; +import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ListTag; +import com.denizenscript.denizencore.objects.core.ScriptTag; import com.denizenscript.denizencore.scripts.*; +import com.denizenscript.denizencore.tags.ParseableTag; import com.denizenscript.denizencore.tags.TagContext; import com.denizenscript.denizencore.tags.TagManager; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; +import com.denizenscript.denizencore.utilities.Deprecations; import com.denizenscript.denizencore.utilities.YamlConfiguration; +import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizencore.utilities.debugging.DebugInternals; import com.denizenscript.denizencore.utilities.debugging.Debuggable; -import com.denizenscript.denizencore.utilities.debugging.Debug; -import com.denizenscript.denizencore.DenizenCore; -import com.denizenscript.denizencore.objects.core.ScriptTag; import java.util.ArrayList; import java.util.HashMap; @@ -59,6 +61,8 @@ public class ScriptContainer implements Debuggable { // // --> + public ScriptFormattingContext formattingContext; + public ScriptContainer(YamlConfiguration configurationSection, String scriptContainerName) { if (configurationSection == null) { Debug.echoError("Null configuration section while generating a ScriptContainer?!"); @@ -71,6 +75,7 @@ public ScriptContainer(YamlConfiguration configurationSection, String scriptCont configurationSection.forceLoweredRootKey("speed"); configurationSection.forceLoweredRootKey("enabled"); this.name = CoreUtilities.toUpperCase(scriptContainerName); + this.formattingContext = ScriptFormattingContext.parseFromConfiguration(this); } public T tagObject(String text, Class type) { @@ -82,6 +87,11 @@ public String tag(String text) { return TagManager.tag(text, DenizenCore.implementation.getTagContext(this)); } + public ParseableTag getCachedTag(String path) { + String rawString = getString(path); + return rawString != null ? TagManager.parseTextToTag(rawString, DenizenCore.implementation.getTagContext(this)) : null; + } + public Boolean enabledCache = null; public boolean shouldEnable() { @@ -99,6 +109,10 @@ public boolean shouldEnable() { public void postCheck() { } + public ScriptFormattingContext getFormattingContext() { + return formattingContext; + } + /** * Whether this script container type can run script logic. * If this is false, this is a data-only script container. @@ -291,7 +305,7 @@ else if (parseTags) { } public YamlConfiguration getConfigurationSection(String path) { - if (path.length() == 0) { + if (path.isEmpty()) { return contents; } return contents.getConfigurationSection(path); @@ -374,4 +388,17 @@ public boolean shouldDebug() { public String toString() { return "s@" + CoreUtilities.toLowerCase(getName()); } + + public void handlePseudoTagBasesDeprecation(String key, String... tags) { + String value = getString(key); + if (value == null) { + return; + } + for (String tag : tags) { + if (value.contains(tag)) { + Deprecations.pseudoTagBases.warn(this); + return; + } + } + } } diff --git a/src/main/java/com/denizenscript/denizencore/scripts/containers/core/FormatScriptContainer.java b/src/main/java/com/denizenscript/denizencore/scripts/containers/core/FormatScriptContainer.java new file mode 100644 index 00000000..093bb453 --- /dev/null +++ b/src/main/java/com/denizenscript/denizencore/scripts/containers/core/FormatScriptContainer.java @@ -0,0 +1,84 @@ +package com.denizenscript.denizencore.scripts.containers.core; + +import com.denizenscript.denizencore.DenizenCore; +import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.ScriptTag; +import com.denizenscript.denizencore.scripts.ScriptEntry; +import com.denizenscript.denizencore.scripts.ScriptFormattingContext; +import com.denizenscript.denizencore.scripts.containers.ScriptContainer; +import com.denizenscript.denizencore.tags.ParseableTag; +import com.denizenscript.denizencore.tags.TagContext; +import com.denizenscript.denizencore.utilities.SimpleDefinitionProvider; +import com.denizenscript.denizencore.utilities.YamlConfiguration; +import com.denizenscript.denizencore.utilities.debugging.Debug; + +public class FormatScriptContainer extends ScriptContainer { + + // <--[language] + // @name Format Script Containers + // @group Script Container System + // @description + // Format script containers are very simple script containers used for formatting messages. + // + // + // Format_Script_Name: + // + // type: format + // + // # The only key is the format. The format can use '<[text]>' as a special def to contain the message being sent. + // # | All format scripts MUST have this key! + // format: [MyProject] <[text]> + // + // + // --> + + public FormatScriptContainer(YamlConfiguration configurationSection, String scriptContainerName) { + super(configurationSection, scriptContainerName); + canRunScripts = false; + this.formatTag = getCachedTag("format"); + if (this.formatTag == null) { + Debug.echoError(this, "Invalid format script: must have a 'format' key."); + } + else { + handlePseudoTagBasesDeprecation("format", ""); + } + + public String getFormattedText(String text, ScriptEntry entry) { + return getFormattedText(text, entry.getContext()); + } + + public String getFormattedText(String textToReplace, TagContext context) { + return formatText(formatTag, textToReplace, context, getAsScriptArg()); + } + + public static String formatText(ParseableTag formatTag, String rawText, TagContext context, ScriptTag source) { + if (formatTag == null) { + return rawText; + } + TagContext changedContext = context.clone(); + changedContext.script = source; + changedContext.definitionProvider = new SimpleDefinitionProvider(changedContext.definitionProvider); + changedContext.definitionProvider.addDefinition("text", new ElementTag(rawText, true)); + DenizenCore.implementation.addFormatScriptDefinitions(changedContext.definitionProvider, changedContext); + return formatTag.parse(changedContext).identify(); + } +} diff --git a/src/main/java/com/denizenscript/denizencore/utilities/Deprecations.java b/src/main/java/com/denizenscript/denizencore/utilities/Deprecations.java index 52897831..c549e60c 100644 --- a/src/main/java/com/denizenscript/denizencore/utilities/Deprecations.java +++ b/src/main/java/com/denizenscript/denizencore/utilities/Deprecations.java @@ -1,6 +1,9 @@ package com.denizenscript.denizencore.utilities; -import com.denizenscript.denizencore.utilities.debugging.*; +import com.denizenscript.denizencore.utilities.debugging.SlowWarning; +import com.denizenscript.denizencore.utilities.debugging.StrongWarning; +import com.denizenscript.denizencore.utilities.debugging.VerySlowWarning; +import com.denizenscript.denizencore.utilities.debugging.Warning; import java.util.concurrent.ConcurrentHashMap; @@ -163,4 +166,7 @@ public class Deprecations { // Added on 2021/04/16. public static Warning dscriptFileExtension = new StrongWarning("dscriptFileExtension", "'.dscript' extension has never been officially supported. Please use '.dsc'."); + + // Added 2021/11/20, made very-slow 2022/12/31, made slow 2025/01/15, made past 2025/07/19. + public static Warning pseudoTagBases = new StrongWarning("pseudoTagBases", "Pseudo-tags like '', '', '', and '' are deprecated in favor of definitions: just replace with <[text]> or similar."); } diff --git a/src/main/java/com/denizenscript/denizencore/utilities/SimpleDefinitionProvider.java b/src/main/java/com/denizenscript/denizencore/utilities/SimpleDefinitionProvider.java index 2bf2a505..a03c7a4f 100644 --- a/src/main/java/com/denizenscript/denizencore/utilities/SimpleDefinitionProvider.java +++ b/src/main/java/com/denizenscript/denizencore/utilities/SimpleDefinitionProvider.java @@ -6,7 +6,19 @@ public class SimpleDefinitionProvider implements DefinitionProvider { - private final MapTag definitions = new MapTag(); + private final MapTag definitions; + + public SimpleDefinitionProvider(MapTag map) { + this.definitions = new MapTag(map); + } + + public SimpleDefinitionProvider() { + this.definitions = new MapTag(); + } + + public SimpleDefinitionProvider(DefinitionProvider definitionProvider) { + this(definitionProvider.getAllDefinitions()); + } @Override public void addDefinition(String definition, ObjectTag value) {