Package net.aufdemrand.denizen.scripts.commands.entity

Source Code of net.aufdemrand.denizen.scripts.commands.entity.FlyCommand

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

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

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.Element;
import net.aufdemrand.denizen.objects.aH;
import net.aufdemrand.denizen.objects.dEntity;
import net.aufdemrand.denizen.objects.dList;
import net.aufdemrand.denizen.objects.dLocation;
import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.scripts.ScriptEntry;
import net.aufdemrand.denizen.scripts.commands.AbstractCommand;
import net.aufdemrand.denizen.utilities.Conversion;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizen.utilities.entity.Position;
import net.aufdemrand.denizen.utilities.entity.Rotation;

import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;

/**
* Make an entity fly where its controller is looking,
* or - alternatively - make it fly between different destinations.
*
* @author David Cernat
*/

public class FlyCommand extends AbstractCommand {

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

        // Initialize necessary fields

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

            if (!scriptEntry.hasObject("cancel")
                && arg.matches("cancel")) {

                scriptEntry.addObject("cancel", "");
            }

            else if (!scriptEntry.hasObject("destinations")
                     && arg.matchesPrefix("destination", "destinations", "d")) {

                scriptEntry.addObject("destinations", arg.asType(dList.class).filter(dLocation.class));
            }

            else if (!scriptEntry.hasObject("controller")
                     && arg.matchesArgumentType(dPlayer.class)
                     && arg.matchesPrefix("controller", "c")) {

               // Check if it matches a dPlayer, but save it as a dEntity
               scriptEntry.addObject("controller", (arg.asType(dEntity.class)));
            }

            else if (!scriptEntry.hasObject("origin")
                     && arg.matchesArgumentType(dLocation.class)) {

                scriptEntry.addObject("origin", arg.asType(dLocation.class));
            }

            else if (!scriptEntry.hasObject("entities")
                     && arg.matchesArgumentList(dEntity.class)) {

                scriptEntry.addObject("entities", arg.asType(dList.class).filter(dEntity.class));
            }

            else if (!scriptEntry.hasObject("rotationThreshold")
                    && arg.matchesPrefix("rotationthreshold", "rotation", "r")
                    && arg.matchesPrimitive(aH.PrimitiveType.Float)) {

               scriptEntry.addObject("rotationThreshold", arg.asElement());
           }

            else if (!scriptEntry.hasObject("speed")
                     && arg.matchesPrimitive(aH.PrimitiveType.Double)) {

                scriptEntry.addObject("speed", arg.asElement());
            }

            else arg.reportUnhandled();
        }

        // Use the NPC or player's locations as the location if one is not specified
        scriptEntry.defaultObject("origin",
                ((BukkitScriptEntryData)scriptEntry.entryData).hasPlayer() ? ((BukkitScriptEntryData)scriptEntry.entryData).getPlayer().getLocation() : null,
                ((BukkitScriptEntryData)scriptEntry.entryData).hasNPC() ? ((BukkitScriptEntryData)scriptEntry.entryData).getNPC().getLocation() : null);

        // Use a default speed and rotation threshold if they are not specified
        scriptEntry.defaultObject("speed", new Element(1.2));
        scriptEntry.defaultObject("rotationThreshold", new Element(15));

        // Check to make sure required arguments have been filled
        if (!scriptEntry.hasObject("entities"))
            throw new InvalidArgumentsException("Must specify entity/entities!");
        if (!scriptEntry.hasObject("origin"))
            throw new InvalidArgumentsException("Must specify an origin!");
    }

    @SuppressWarnings("unchecked")
    @Override
    public void execute(final ScriptEntry scriptEntry) throws CommandExecutionException {
        // Get objects

        dLocation origin = (dLocation) scriptEntry.getObject("origin");
        List<dEntity> entities = (List<dEntity>) scriptEntry.getObject("entities");
        final List<dLocation> destinations = scriptEntry.hasObject("destinations") ?
                                (List<dLocation>) scriptEntry.getObject("destinations") :
                                new ArrayList<dLocation>();

        // Set freeflight to true only if there are no destinations
        final boolean freeflight = destinations.size() < 1;

        dEntity controller = (dEntity) scriptEntry.getObject("controller");

        // If freeflight is on, we need to do some checks
        if (freeflight) {

            // If no controller was set, we need someone to control the
            // flying entities, so try to find a player in the entity list
            if (controller == null) {
                for (dEntity entity : entities) {
                    if (entity.isPlayer()) {
                        // If this player will be a rider on something, and will not
                        // be at the bottom ridden by the other entities, set it as
                        // the controller
                        if (entities.get(entities.size() - 1) != entity) {
                            controller = entity;
                            dB.report(scriptEntry, getName(), "Flight control defaulting to " + controller);
                            break;
                        }
                    }
                }

                // If the controller is still null, we cannot continue
                if (controller == null) {
                    dB.report(scriptEntry, getName(), "There is no one to control the flight's path!");
                    return;
                }
            }

            // Else, if the controller was set, we need to make sure
            // it is among the flying entities, and add it if it is not
            else {
                boolean found = false;

                for (dEntity entity : entities) {
                    if (entity.identify().equals(controller.identify())) {
                        found = true;
                        break;
                    }
                }

                // Add the controller to the entity list
                if (!found) {
                    dB.report(scriptEntry, getName(), "Adding controller " + controller + " to flying entities.");
                    entities.add(0, controller);
                }
            }
        }

        final double speed = ((Element) scriptEntry.getObject("speed")).asDouble();
        final float rotationThreshold = ((Element) scriptEntry.getObject("rotationThreshold")).asFloat();
        boolean cancel = scriptEntry.hasObject("cancel");

        // Report to dB
        dB.report(scriptEntry, getName(), (cancel ? aH.debugObj("cancel", cancel) : "") +
                             aH.debugObj("origin", origin) +
                             aH.debugObj("entities", entities.toString()) +
                             aH.debugObj("speed", speed) +
                             aH.debugObj("rotation threshold degrees", rotationThreshold) +
                             (freeflight ? aH.debugObj("controller", controller)
                                         : aH.debugObj("destinations", destinations.toString())));

        // Mount or dismount all of the entities
        if (!cancel) {

            // Go through all the entities, spawning/teleporting them
            for (dEntity entity : entities) {
                entity.spawnAt(origin);
            }

            Position.mount(Conversion.convertEntities(entities));
        }
        else {
            Position.dismount(Conversion.convertEntities(entities));

            // Go no further if we are dismounting entities
            return;
        }

        // Get the last entity on the list
        final Entity entity = entities.get(entities.size() - 1).getBukkitEntity();
        final LivingEntity finalController = controller != null ? controller.getLivingEntity() : null;

        BukkitRunnable task = new BukkitRunnable() {

            Location location = null;
            Boolean flying = true;

            public void run() {

                if (freeflight) {

                    // If freeflight is on, and the flying entity
                    // is ridden by another entity, let it keep
                    // flying where the controller is looking

                    if (!entity.isEmpty() && finalController.isInsideVehicle()) {
                        location = finalController.getEyeLocation()
                                     .add(finalController.getEyeLocation().getDirection()
                                     .multiply(30));
                    }
                    else {
                        flying = false;
                    }
                }
                else {

                    // If freelight is not on, keep flying only as long
                    // as there are destinations left

                    if (destinations.size() > 0) {
                        location = destinations.get(0);
                    }
                    else {
                        flying = false;
                    }
                }

                if (flying && entity.isValid()) {

                    // To avoid excessive turbulence, only have the entity rotate
                    // when it really needs to
                    if (!Rotation.isFacingLocation(entity, location, rotationThreshold)) {

                        Rotation.faceLocation(entity, location);
                    }

                    Vector v1 = entity.getLocation().toVector();
                    Vector v2 = location.toVector();
                    Vector v3 = v2.clone().subtract(v1).normalize().multiply(speed);

                    entity.setVelocity(v3);

                    // If freeflight is off, check if the entity has reached its
                    // destination, and remove the destination if that happens
                    // to be the case

                    if (!freeflight) {

                        if (Math.abs(v2.getX() - v1.getX()) < 2 && Math.abs(v2.getY() - v1.getY()) < 2
                            && Math.abs(v2.getZ() - v1.getZ()) < 2) {

                            destinations.remove(0);
                        }
                    }
                }
                else {

                    flying = false;
                    this.cancel();
                }
            }
        };

           task.runTaskTimer(DenizenAPI.getCurrentInstance(), 0, 3);
    }
}
TOP

Related Classes of net.aufdemrand.denizen.scripts.commands.entity.FlyCommand

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.