Package net.aufdemrand.denizen.scripts

Source Code of net.aufdemrand.denizen.scripts.ScriptEntry

package net.aufdemrand.denizen.scripts;

import java.util.*;

import net.aufdemrand.denizen.BukkitScriptEntryData;
import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException;
import net.aufdemrand.denizencore.exceptions.ScriptEntryCreationException;
import net.aufdemrand.denizen.objects.Element;
import net.aufdemrand.denizen.objects.aH;
import net.aufdemrand.denizen.objects.dNPC;
import net.aufdemrand.denizen.objects.dObject;
import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.objects.dScript;
import net.aufdemrand.denizen.scripts.commands.AbstractCommand;
import net.aufdemrand.denizen.scripts.commands.BracedCommand;
import net.aufdemrand.denizencore.scripts.ScriptEntryData;
import net.aufdemrand.denizencore.scripts.commands.Holdable;
import net.aufdemrand.denizen.scripts.containers.ScriptContainer;
import net.aufdemrand.denizen.scripts.queues.ScriptQueue;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizencore.utilities.debugging.Debuggable;
import net.aufdemrand.denizen.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 AbstractCommand actualCommand;

    // Command Arguments
    private List<String> args;
    private List<String> 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<String, ArrayList<ScriptEntry>> bracedSet = null;

    public LinkedHashMap<String, ArrayList<ScriptEntry>> getBracedSet() {
        return bracedSet;
    }

    public void setBracedSet(LinkedHashMap<String, ArrayList<ScriptEntry>> set) {
        bracedSet = set;
    }

    // ScriptEntry Context
    private Map<String, Object> objects = new HashMap<String, Object>();


    // 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<String, Object>();
        se.entryData = (ScriptEntryData)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 = new BukkitScriptEntryData(null, null); // TODO: Make version-cross-compatible

        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 (DenizenAPI.getCurrentInstance().getCommandRegistry().get(this.command)
                        instanceof Holdable) {
                    waitfor = true;
                }
                else {
                    dB.echoError(null, "The command '" + this.command + "' cannot be waited for!");
                }
            }
            actualCommand = (AbstractCommand)DenizenAPI.getCurrentInstance().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<String>();
            this.pre_tagged_args = new ArrayList<String>();
        }

        // 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<String> 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<String> getOriginalArguments() {
        return pre_tagged_args;
    }


    public String getCommandName() {
        return command;
    }

    public AbstractCommand getCommand() {
        return actualCommand;
    }


    public ScriptEntry setArguments(List<String> 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) {
        setPlayer(((BukkitScriptEntryData)entry.entryData).getPlayer());
        setNPC(((BukkitScriptEntryData)entry.entryData).getNPC());
        setSendingQueue(entry.getResidingQueue());
    }


    //////////////////
    // SCRIPTENTRY CONTEXT
    //////////////

    public Map<String, Object> getObjects() {
        return objects;
    }


    public Object getObject(String key) {
        try {
            return objects.get(key.toLowerCase());
        } catch (Exception e) { return null; }
    }

    public <T extends dObject> 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; }
    }

    @Deprecated
    public <T extends dObject> T getdObjectAs(String key, Class<T> type) {
        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
    ///////

    /**
     * Gets a dNPC reference to any linked NPC set by the CommandExecuter.
     *
     * @return the NPC linked to this script entry
     */
    @Deprecated
    public dNPC getNPC() {
        return ((BukkitScriptEntryData)entryData).getNPC();
    }

    @Deprecated
    public boolean hasNPC() {
        return ((BukkitScriptEntryData)entryData).hasNPC();
    }


    @Deprecated
    public ScriptEntry setNPC(dNPC dNPC) {
        ((BukkitScriptEntryData)entryData).setNPC(dNPC);
        return this;
    }


    @Deprecated
    public dPlayer getPlayer() {
        return ((BukkitScriptEntryData)entryData).getPlayer();
    }

    @Deprecated
    public boolean hasPlayer() {
        return ((BukkitScriptEntryData)entryData).hasPlayer();
    }

    @Deprecated
    public ScriptEntry setPlayer(dPlayer player) {
        ((BukkitScriptEntryData)entryData).setPlayer(player);
        return this;
    }


    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.
    public List<String> tracked_objects = new ArrayList<String>();
    public ScriptEntry trackObject(String key) {
        tracked_objects.add(key.toLowerCase());
        return this;
    }

    /////////////
    // DEBUGGABLE
    /////////

    @Override
    public boolean shouldDebug() throws Exception {
        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@", ""));
    }

    public String reportObject(String id) {
        // If this script entry doesn't have the object being reported,
        // just return nothing.
        if (!hasObject(id))
            return "";

        // If the object is a dObject, there's a method for reporting them
        // in the proper format.
        if (getObject(id) instanceof dObject)
            return getdObject(id).debug();

            // If all else fails, fall back on the toString() method with the id of the
            // object being passed to aH.report(...)
        else return aH.debugObj(id, getObject(id));
    }
}
TOP

Related Classes of net.aufdemrand.denizen.scripts.ScriptEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.