Package net.aufdemrand.denizen.npc.traits

Source Code of net.aufdemrand.denizen.npc.traits.PushableTrait

package net.aufdemrand.denizen.npc.traits;

import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.citizensnpcs.api.ai.event.NavigationCompleteEvent;
import net.citizensnpcs.api.event.NPCPushEvent;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.minecraft.server.v1_7_R4.EntityLiving;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftLivingEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

// <--[language]
// @name Pushable Trait
// @group NPC Traits
// @description
// By default, NPCs created will allow players to 'noclip' them, or go right through. This is to
// avoid NPCs moving from their set location, but often times, this behavior may be undesired.
// The pushable trait allows NPCs to move when collided with, and optionally return to their
// original location after a specified amount of time.
//
// To enable the trait, use the '/npc pushable' command on any selected NPC. Once the trait is
// enabled, the '-r' option can be used to toggle returnable, and the '--delay #' option can be
// used to specify the number of seconds before the npc returns.
//
// Care should be taken when allowing NPCs to be pushable. Allowing NPCs to be pushed around
// complex structures can result in stuck NPCs. If the NPC is stuck, it may not return. Keeping
// a small delay, in situations like this, can be a good trade-off. Typically the lower the
// delay, the shorter distance a Player is able to push the NPC. The default delay is 2 seconds.
//
// The pushable trait also implements some actions that can be used in assignment scripts.
// This includes 'on push' and 'on push return'.

// -->

public class PushableTrait extends Trait implements Listener {

    // Saved to the C2 saves.yml
    @Persist("toggle")
    private boolean pushable = true;
    @Persist("returnable")
    private boolean returnable = false;
    @Persist("delay")
    private int delay = 2;

    // Used internally
    private boolean pushed = false;
    private Location returnLocation = null;
    private long pushedTimer = 0;

    public PushableTrait() {
        super("pushable");
    }

    /**
     * Gets the delay, as set by {@link #setDelay(int)}.
     *
     * @return delay, in seconds
     */
    public int getDelay() {
        return delay;
    }

    /**
     * Checks if this NPCs pushable setting is toggled.
     *
     * @return true if pushable
     */
    public boolean isPushable() {
        return pushable;
    }

    /**
     * Checks if this NPC is returnable when pushed.
     * Note: Does not take into account whether the NPC
     * is pushable, use {@link #isPushable()}
     *
     * @return true if returnable
     */
    public boolean isReturnable() {
        return returnable;
    }

    /**
     * Sets the delay, in seconds, in which the NPC will
     * return to its position after being pushed.
     * Note: Must be pushable.
     *
     * @param delay time in seconds to return after being pushed
     */
    public void setDelay(int delay) {
        this.delay = delay;
    }

    /**
     * Indicates that the NPC should be pushable. By default,
     * C2 NPCs are not pushable.
     *
     * @param pushable whether the NPC should be pushable
     */
    public void setPushable(boolean pushable) {
        this.pushable = pushable;
    }

    /**
     * Indicates that the NPC should return to its location
     * after being pushed. Takes into account a delay which
     * can be set with {@link #setDelay(int)} and
     * checked with {@link #getDelay()}}.
     *
     * @param returnable whether the NPC can return
     */
    public void setReturnable(boolean returnable) {
        this.returnable = returnable;
    }

    /**
     * Toggles the NPCs current pushable setting.
     *
     * @return {@link #isPushable()} after setting
     */
    public boolean toggle() {
        pushable = !pushable;
        if (!pushable) returnable = false;
        return pushable;
    }

    // <--[action]
    // @Actions
    // push
    //
    // @Triggers when the NPC is pushed by a player
    //
    // @Context
    // None
    //
    // -->
    /**
     * Fires an 'On Push:' action upon being pushed.
     *
     */
    @EventHandler
    public void NPCPush (NPCPushEvent event) {
        if (event.getNPC() == npc && pushable) {
            event.setCancelled(false);
            // On Push action / Push Trigger
            if (System.currentTimeMillis() > pushedTimer) {
                // Get pusher
                Player pusher = null;
                for (Entity le : event.getNPC().getBukkitEntity().getNearbyEntities(1, 1, 1))
                    if (le instanceof Player) pusher = (Player) le;
                if (pusher != null) {
                    DenizenAPI.getDenizenNPC(npc).action("push", dPlayer.mirrorBukkitPlayer(pusher));
                    pushedTimer = System.currentTimeMillis() + (delay * 1000);
                }
            } // End push action
            if (!pushed && returnable) {
                pushed = true;
                returnLocation = npc.getBukkitEntity().getLocation().clone();
                Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(
                        DenizenAPI.getCurrentInstance(), new Runnable() {
                            @Override public void run() { navigateBack(); } }, delay * 20);
            }
        }
    }

    // <--[action]
    // @Actions
    // push return
    //
    // @Triggers when the NPC returns to its center after being pushed by a player.
    //
    // @Context
    // None
    //
    // -->
    /**
     * Fires a 'On Push Return:' action upon return after being pushed.
     *
     */
    @EventHandler
    public void NPCCompleteDestination (NavigationCompleteEvent event) {
        if (event.getNPC() == npc && pushed) {
            EntityLiving handle = ((CraftLivingEntity) npc.getBukkitEntity()).getHandle();
            handle.yaw = returnLocation.getYaw();
            handle.pitch = returnLocation.getPitch();
            // !--- START NMS OBFUSCATED
            handle.az = handle.yaw; // The head's yaw
            // !--- END NMS OBFUSCATED
            pushed = false;
            // Push Return action
            DenizenAPI.getDenizenNPC(npc).action("push return", null);
        }
    }

    protected void navigateBack() {
        if (npc.getNavigator().isNavigating()) {
            pushed = false;
        } else if (pushed) {
            pushed = false; // Avoids NPCCompleteDestination from triggering
            npc.getNavigator().setTarget(returnLocation);
            pushed = true;
        }
    }
}
TOP

Related Classes of net.aufdemrand.denizen.npc.traits.PushableTrait

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.