Package net.aufdemrand.denizen.scripts.commands.npc

Source Code of net.aufdemrand.denizen.scripts.commands.npc.WalkCommand

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

import net.aufdemrand.denizen.BukkitScriptEntryData;
import net.aufdemrand.denizencore.exceptions.CommandExecutionException;
import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException;
import net.aufdemrand.denizen.objects.*;
import net.aufdemrand.denizen.scripts.ScriptEntry;
import net.aufdemrand.denizen.scripts.commands.AbstractCommand;
import net.aufdemrand.denizencore.scripts.commands.Holdable;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.citizensnpcs.api.ai.event.NavigationCancelEvent;
import net.citizensnpcs.api.ai.event.NavigationCompleteEvent;
import net.citizensnpcs.api.ai.event.NavigationEvent;
import net.citizensnpcs.api.ai.flocking.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* Handles NPC walking with the Citizens API.
*
* @author Jeremy Schroeder
*/
public class WalkCommand extends AbstractCommand implements Listener, Holdable {

    //                        percentage
    // walk [location] (speed:#.#) (auto_range)
    //

    @Override
    public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {

        // Interpret arguments

        for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) {

            if (!scriptEntry.hasObject("location")
                    && arg.matchesArgumentType(dLocation.class))
                scriptEntry.addObject("location", arg.asType(dLocation.class));

            else if (!scriptEntry.hasObject("speed")
                    && arg.matchesPrimitive(aH.PrimitiveType.Percentage)
                    && arg.matchesPrefix("s, speed"))
                scriptEntry.addObject("speed", arg.asElement());

            else if (!scriptEntry.hasObject("auto_range")
                    && arg.matches("auto_range"))
                scriptEntry.addObject("auto_range", Element.TRUE);

            else if (!scriptEntry.hasObject("radius")
                    && arg.matchesPrimitive(aH.PrimitiveType.Double)
                    && arg.matchesPrefix("radius"))
                scriptEntry.addObject("radius", arg.asElement());

            else if (!scriptEntry.hasObject("npcs")
                    && arg.matchesArgumentList(dNPC.class))
                scriptEntry.addObject("npcs", arg.asType(dList.class).filter(dNPC.class));

            else
                arg.reportUnhandled();
        }


        // Check for required information

        if (!scriptEntry.hasObject("location"))
            throw new InvalidArgumentsException("Must specify a location!");

        if (!scriptEntry.hasObject("npcs")) {
            if (((BukkitScriptEntryData)scriptEntry.entryData).getNPC() == null
                    || !((BukkitScriptEntryData)scriptEntry.entryData).getNPC().isValid()
                    || !((BukkitScriptEntryData)scriptEntry.entryData).getNPC().isSpawned())
                throw new InvalidArgumentsException("Must have a valid spawned NPC attached.");
            else
                scriptEntry.addObject("npcs", Arrays.asList(((BukkitScriptEntryData)scriptEntry.entryData).getNPC()));
        }


    }


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

        // Fetch required objects

        dLocation loc = (dLocation) scriptEntry.getObject("location");
        Element speed = scriptEntry.getElement("speed");
        Element auto_range = scriptEntry.getElement("auto_range");
        Element radius = scriptEntry.getElement("radius");
        List<dNPC> npcs = (List<dNPC>) scriptEntry.getObject("npcs");


        // Debug the execution

        dB.report(scriptEntry, getName(), loc.debug()
                + (speed != null ? speed.debug() : "")
                + (auto_range != null ? auto_range.debug() : "")
                + (radius != null ? radius.debug(): "")
                + (aH.debugObj("npcs", npcs)));

        // Do the execution

        for (dNPC npc: npcs) {
            if (!npc.isSpawned()) {
                dB.echoError(scriptEntry.getResidingQueue(), "NPC " + npc.identify() + " is not spawned!");
                continue;
            }
            if (auto_range != null
                    && auto_range == Element.TRUE) {
                double distance = npc.getLocation().distance(loc);
                if (npc.getNavigator().getLocalParameters().range() < distance + 10)
                    npc.getNavigator().getDefaultParameters().range((float) distance + 10);
                // TODO: Should be using local params rather than default?
            }

            npc.getNavigator().setTarget(loc);

            if (speed != null)
                npc.getNavigator().getLocalParameters().speedModifier(speed.asFloat());

            if (radius != null) {
                NPCFlock flock = new RadiusNPCFlock(radius.asDouble());
                Flocker flocker = new Flocker(npc.getCitizen(), flock, new SeparationBehavior(Flocker.LOW_INFLUENCE),
                        new CohesionBehavior(Flocker.LOW_INFLUENCE), new AlignmentBehavior(Flocker.HIGH_INFLUENCE));
                npc.getNavigator().getLocalParameters().addRunCallback(flocker);
            }
        }

        if (scriptEntry.shouldWaitFor()) {
            held.add(scriptEntry);
            scriptEntry.addObject("tally", new ArrayList<dNPC>(npcs));
        }

    }


    // Held script entries
    public static List<ScriptEntry> held = new ArrayList<ScriptEntry>();

    @EventHandler
    public void finish(NavigationCompleteEvent e) {

        if (held.isEmpty()) return;

        checkHeld(e);

    }

    @EventHandler
    public void cancel(NavigationCancelEvent e) {

        if (held.isEmpty()) return;

        checkHeld(e);

    }


    public void checkHeld(NavigationEvent e) {
        if (e.getNPC() == null)
            return;

        // Check each held entry -- the scriptExecuter is waiting on
        // the entry to be marked 'waited for'.
        for (int i = 0; i < held.size(); i++) {
            ScriptEntry entry = held.get(i);

            // Get all NPCs associated with the entry. They must all
            // finish navigation before the entry can be let go
            List<dNPC> tally = (List<dNPC>) entry.getObject("tally");
            // If the NPC is the NPC from the event, take it from the list.
            tally.remove(dNPC.mirrorCitizensNPC(e.getNPC()));

            // Check if tally is empty.
            if (tally.isEmpty()) {
                entry.setFinished(true);
                held.remove(i);
                i--;
            }
        }
    }

    @Override
    public void onEnable() {
        DenizenAPI.getCurrentInstance().getServer().getPluginManager()
                .registerEvents(this, DenizenAPI.getCurrentInstance());
    }
}
TOP

Related Classes of net.aufdemrand.denizen.scripts.commands.npc.WalkCommand

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.