Package net.aufdemrand.denizen.scripts.commands.core

Source Code of net.aufdemrand.denizen.scripts.commands.core.ZapCommand

package net.aufdemrand.denizen.scripts.commands.core;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import net.aufdemrand.denizen.BukkitScriptEntryData;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizencore.exceptions.CommandExecutionException;
import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException;
import net.aufdemrand.denizen.objects.Duration;
import net.aufdemrand.denizen.objects.Element;
import net.aufdemrand.denizen.objects.aH;
import net.aufdemrand.denizen.objects.dScript;
import net.aufdemrand.denizen.scripts.ScriptEntry;
import net.aufdemrand.denizen.scripts.commands.AbstractCommand;
import net.aufdemrand.denizen.scripts.containers.core.InteractScriptHelper;
import net.aufdemrand.denizen.utilities.debugging.dB;

import org.bukkit.event.Listener;

/**
* <p>Changes a Player's current step for a script. Reminder: ZAP does NOT trigger anything. It merely
* tells Denizen's ScriptEngine which step should be used WHEN interacting.</p>
*
* <b>dScript Usage:</b><br>
* <pre>ZAP [#|STEP:step_name] (SCRIPT:script_name{current_script}) (DURATION:#{0})</pre>
*
* <ol><tt>Arguments: [] - Required () - Optional  {} - Default</ol></tt>
*
* <ol><tt>[#|STEP:step_name]</tt><br>
*         The name of the step that should be enabled. If using numbered steps, an plain integer will
*         suffice.</ol>
*
* <ol><tt>(SCRIPT:script_name{current_script})</tt><br>
*         Specifies which script should be affected. If not specified, the current interact script will
*         be used.</ol>
*
* <ol><tt>(DURATION:#{0})</tt><br>
*         Optional. If not specified, no duration is used. If specified, after the duration period,
*         Denizen will automatically reset the step to the original step. Note: If another ZAP command
*         is utilized for the same Player and Script during a duration period, the reset in progress
*         is cancelled.</ol>
*
* <br><b>Example Usage:</b><br>
* <ol><tt>
*  - ZAP SCRIPT:OtherScript 6<br>
*  - ZAP 'STEP:Just for a minute' DURATION:1m<br>
* </ol></tt>
*
* @author Jeremy Schroeder
*/

public class ZapCommand extends AbstractCommand implements Listener{

    @Override
    public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
        for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) {

            // If the scripter uses the 'script:step' format, handle it.
            if (!scriptEntry.hasObject("script")
                    && !scriptEntry.hasObject("step")
                    && arg.hasPrefix()
                    && arg.getPrefix().matchesArgumentType(dScript.class)) {
                scriptEntry.addObject("script", arg.getPrefix().asType(dScript.class));
                scriptEntry.addObject("step", arg.asElement());
            }

            // If a script is found, use that to ZAP
            else if (!scriptEntry.hasObject("script")
                    && arg.matchesArgumentType(dScript.class)
                    && !arg.matchesPrefix("step"))
                scriptEntry.addObject("script", arg.asType(dScript.class));

            // Add argument as step
            else if (!scriptEntry.hasObject("step"))
                scriptEntry.addObject("step", arg.asElement());

            // Lastly duration
            else if (!scriptEntry.hasObject("duration")
                    && arg.matchesArgumentType(Duration.class))
                scriptEntry.addObject("duration", arg.asType(Duration.class));

            else arg.reportUnhandled();
        }

        // Add default script if none was specified.
        scriptEntry.defaultObject("script", scriptEntry.getScript());

        // Check if player is valid
        if (!((BukkitScriptEntryData)scriptEntry.entryData).hasPlayer() || !((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().isValid())
            throw new InvalidArgumentsException("Must have player context!");
    }

    //"PlayerName,ScriptName", TaskID
    private static Map<String, Integer> durations = new ConcurrentHashMap<String, Integer>(8, 0.9f, 1);

    @Override
    public void execute(final ScriptEntry scriptEntry) throws CommandExecutionException {

        final dScript script = (dScript) scriptEntry.getObject("script");
        Duration duration = (Duration) scriptEntry.getObject("duration");

        dB.report(scriptEntry, getName(), ((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().debug() + script.debug()
                + (scriptEntry.hasObject("step")
                ? scriptEntry.getElement("step").debug() : aH.debugObj("step", "++ (inc)"))
                + (duration != null ? duration.debug() : ""));

        String step = scriptEntry.hasObject("step") ? scriptEntry.getElement("step").asString() : null;

        // Let's get the current step for reference.
        String currentStep = InteractScriptHelper.getCurrentStep(((BukkitScriptEntryData)scriptEntry.entryData).getPlayer(), script.getName());

        // Special-case for backwards compatibility: ability to use ZAP to count up steps.
        if (step == null) {
            // Okay, no step was identified.. that means we should count up,
            // ie. if currentStep = 1, new step should = 2
            // If the currentStep is a number, increment it. If not, set it
            // to '1' so it can be incremented next time.
            if (aH.matchesInteger(currentStep)) {
                step = String.valueOf(aH.getIntegerFrom(currentStep) + 1);
            } else step = "1";
        }

        if (step.equalsIgnoreCase(currentStep)) {
            dB.echoError(scriptEntry.getResidingQueue(), "Zapping to own current step!");
            return;
        }

        // If the durationsMap already contains an entry for this player/script combination,
        // cancel the task since it's probably not desired to change back anymore if another
        // ZAP for this script is taking place.
        if (durations.containsKey(((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName()))
            try {
                DenizenAPI.getCurrentInstance().getServer().getScheduler().cancelTask(durations.get(((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName()));
            } catch (Exception e) { }

        // One last thing... check for duration.
        if (duration != null && duration.getSeconds() > 0) {
            // If a DURATION is specified, the currentStep should be remembered and
            // restored after the duration.
            scriptEntry.addObject("step", new Element(currentStep));
            // And let's take away the duration that was set to avoid a re-duration
            // inception-ion-ion-ion-ion... ;)
            scriptEntry.addObject("duration", Duration.ZERO);

            // Now let's add a delayed task to set it back after the duration

            // Delays are in ticks, so let's multiply our duration (which is in seconds) by 20.
            // 20 ticks per second.
            long delay = (long) (duration.getSeconds() * 20);

            // Set delayed task and put id in a map
            dB.log("Setting delayed task 'RESET ZAP' for '" + script.identify() + "'");
            durations.put(((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName(),
                    DenizenAPI.getCurrentInstance().getServer().getScheduler().scheduleSyncDelayedTask(DenizenAPI.getCurrentInstance(),
                            new Runnable() {
                                @Override
                                public void run() {
                                    dB.log("Running delayed task 'RESET ZAP' for '" + script.identify() + "'");
                                    try {
                                        durations.remove(((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName().toUpperCase());
                                        execute(scriptEntry);
                                    } catch (CommandExecutionException e) {
                                        dB.echoError(scriptEntry.getResidingQueue(), "Could not run delayed task!");
                                        dB.echoError(scriptEntry.getResidingQueue(), e);
                                    }
                                }
                            }, delay));
        }

        //
        // FINALLY! ZAP! Change the step in Saves... your step is now ZAPPED!
        // Fun fact: ZAP is named in homage of ZZT-OOPs ZAP command. Google it.
        //
        DenizenAPI.getCurrentInstance().getSaves().set("Players." + ((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().getSaveName()
                + ".Scripts." + script.getName().toUpperCase() + "." + "Current Step", step);
    }
}
TOP

Related Classes of net.aufdemrand.denizen.scripts.commands.core.ZapCommand

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.