package net.aufdemrand.denizen.objects;
import net.aufdemrand.denizen.flags.FlagManager;
import net.aufdemrand.denizen.npc.dNPCRegistry;
import net.aufdemrand.denizen.npc.examiners.PathBlockExaminer;
import net.aufdemrand.denizen.npc.traits.*;
import net.aufdemrand.denizen.objects.properties.Property;
import net.aufdemrand.denizen.objects.properties.PropertyParser;
import net.aufdemrand.denizen.scripts.commands.npc.EngageCommand;
import net.aufdemrand.denizen.scripts.containers.core.InteractScriptContainer;
import net.aufdemrand.denizen.scripts.containers.core.InteractScriptHelper;
import net.aufdemrand.denizen.scripts.triggers.AbstractTrigger;
import net.aufdemrand.denizen.tags.Attribute;
import net.aufdemrand.denizen.tags.core.NPCTags;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.Navigator;
import net.citizensnpcs.api.ai.TeleportStuckAction;
import net.citizensnpcs.api.astar.pathfinder.FlyingBlockExaminer;
import net.citizensnpcs.api.astar.pathfinder.MinecraftBlockExaminer;
import net.citizensnpcs.api.event.DespawnReason;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.trait.Equipment;
import net.citizensnpcs.api.trait.trait.Owner;
import net.citizensnpcs.npc.entity.nonliving.FallingBlockController;
import net.citizensnpcs.npc.entity.nonliving.ItemController;
import net.citizensnpcs.npc.entity.nonliving.ItemFrameController;
import net.citizensnpcs.trait.Anchors;
import net.citizensnpcs.trait.LookClose;
import net.citizensnpcs.trait.Poses;
import net.citizensnpcs.util.Anchor;
import net.citizensnpcs.util.Pose;
import net.minecraft.server.v1_7_R4.EntityLiving;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftLivingEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
public class dNPC implements dObject, Adjustable, InventoryHolder {
public static dNPC mirrorCitizensNPC(NPC npc) {
if (dNPCRegistry._isRegistered(npc)) return dNPCRegistry.getDenizen(npc);
else return new dNPC(npc);
}
public static dNPC fromEntity(Entity entity) {
return mirrorCitizensNPC(CitizensAPI.getNPCRegistry().getNPC(entity));
}
@Fetchable("n")
public static dNPC valueOf(String string) {
if (string == null) return null;
////////
// Match NPC id
string = string.toUpperCase().replace("N@", "");
NPC npc;
if (aH.matchesInteger(string)) {
int id = aH.getIntegerFrom(string);
if (dNPCRegistry._isRegistered(id))
return dNPCRegistry.getDenizen(id);
npc = CitizensAPI.getNPCRegistry().getById(id);
if (npc != null) return new dNPC(npc);
}
////////
// Match NPC name
else {
for (NPC test : CitizensAPI.getNPCRegistry()) {
if (test.getName().equalsIgnoreCase(string)) {
return new dNPC(test);
}
}
}
return null;
}
public static boolean matches(String string) {
// If using object notation, assume it's valid
if (string.toLowerCase().startsWith("n@")) return true;
// Otherwise, let's do checks
string = string.toUpperCase().replace("N@", "");
NPC npc;
if (aH.matchesInteger(string)) {
npc = CitizensAPI.getNPCRegistry().getById(aH.getIntegerFrom(string));
if (npc != null) return true;
}
else {
for (NPC test : CitizensAPI.getNPCRegistry()) {
if (test.getName().equalsIgnoreCase(string)) {
return true;
}
}
}
return false;
}
public boolean isValid() {
return getCitizen() != null;
}
private int npcid = -1;
private final org.bukkit.Location locationCache = new org.bukkit.Location(null, 0, 0, 0);
public dNPC(NPC citizensNPC) {
if (citizensNPC != null)
this.npcid = citizensNPC.getId();
if (npcid >= 0 && !dNPCRegistry._isRegistered(citizensNPC))
dNPCRegistry._registerNPC(this);
}
public EntityLiving getHandle() {
return ((CraftLivingEntity) getEntity()).getHandle();
}
public NPC getCitizen() {
NPC npc = CitizensAPI.getNPCRegistry().getById(npcid);
if (npc == null)
dB.log("Uh oh! Denizen has encountered a NPE while trying to fetch an NPC. " +
"Has this NPC been removed?");
return npc;
}
public Entity getEntity() {
try {
return getCitizen().getEntity();
} catch (NullPointerException e) {
dB.log("Uh oh! Denizen has encountered a NPE while trying to fetch an NPC entity. " +
"Has this NPC been removed?");
return null;
}
}
public LivingEntity getLivingEntity() {
try {
if (getCitizen().getEntity() instanceof LivingEntity)
return (LivingEntity) getCitizen().getEntity();
else {
dB.log("Uh oh! Tried to get the living entity of a non-living NPC!");
return null;
}
} catch (NullPointerException e) {
dB.log("Uh oh! Denizen has encountered a NPE while trying to fetch an NPC livingEntity. " +
"Has this NPC been removed?");
return null;
}
}
public dEntity getDenizenEntity() {
try {
return new dEntity(getCitizen().getEntity());
} catch (NullPointerException e) {
dB.log("Uh oh! Denizen has encountered a NPE while trying to fetch an NPC dEntity. " +
"Has this NPC been removed?");
return null;
}
}
@Override
public Inventory getInventory() { return dNPCRegistry.getInventory(getCitizen()); }
public dInventory getDenizenInventory() { return new dInventory(this); }
public EntityType getEntityType() {
return getCitizen().getEntity().getType();
}
public Navigator getNavigator() {
return getCitizen().getNavigator();
}
public int getId() {
return getCitizen().getId();
}
public String getName() {
return getCitizen().getName();
}
public InteractScriptContainer getInteractScript(dPlayer player, Class<? extends AbstractTrigger> triggerType) {
return InteractScriptHelper.getInteractScript(this, player, triggerType);
}
public InteractScriptContainer getInteractScriptQuietly(dPlayer player, Class<? extends AbstractTrigger> triggerType) {
boolean db = dB.showDebug;
dB.showDebug = false;
InteractScriptContainer script = InteractScriptHelper.getInteractScript(this, player, triggerType);
dB.showDebug = db;
return script;
}
public void destroy() {
getCitizen().destroy();
}
public dLocation getLocation() {
if (isSpawned())
return new dLocation(getEntity().getLocation());
else
return new dLocation(getCitizen().getStoredLocation());
}
public dLocation getEyeLocation() {
if (isSpawned() && getCitizen().getEntity() instanceof LivingEntity)
return new dLocation(((LivingEntity) getCitizen().getEntity()).getEyeLocation());
else if (isSpawned())
return new dLocation(getEntity().getLocation());
else
return new dLocation(getCitizen().getStoredLocation());
}
public World getWorld() {
if (isSpawned()) return getEntity().getWorld();
else return null;
}
@Override
public String toString() {
return getCitizen().getName() + '/' + getCitizen().getId();
}
public boolean isEngaged() {
return EngageCommand.getEngaged(getCitizen());
}
public boolean isSpawned() {
return getCitizen().isSpawned();
}
public String getOwner() {
return getCitizen().getTrait(Owner.class).getOwner();
}
public AssignmentTrait getAssignmentTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(AssignmentTrait.class))
npc.addTrait(AssignmentTrait.class);
return npc.getTrait(AssignmentTrait.class);
}
public Equipment getEquipmentTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(Equipment.class))
npc.addTrait(Equipment.class);
return npc.getTrait(Equipment.class);
}
public NicknameTrait getNicknameTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(NicknameTrait.class))
npc.addTrait(NicknameTrait.class);
return npc.getTrait(NicknameTrait.class);
}
public FishingTrait getFishingTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(FishingTrait.class))
npc.addTrait(FishingTrait.class);
return npc.getTrait(FishingTrait.class);
}
public HealthTrait getHealthTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(HealthTrait.class))
npc.addTrait(HealthTrait.class);
return npc.getTrait(HealthTrait.class);
}
public net.citizensnpcs.api.trait.trait.Inventory getInventoryTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(net.citizensnpcs.api.trait.trait.Inventory.class))
npc.addTrait(net.citizensnpcs.api.trait.trait.Inventory.class);
return npc.getTrait(net.citizensnpcs.api.trait.trait.Inventory.class);
}
public LookClose getLookCloseTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(LookClose.class))
npc.addTrait(LookClose.class);
return npc.getTrait(LookClose.class);
}
public TriggerTrait getTriggerTrait() {
NPC npc = getCitizen();
if (!npc.hasTrait(TriggerTrait.class))
npc.addTrait(TriggerTrait.class);
return npc.getTrait(TriggerTrait.class);
}
public String action(String actionName, dPlayer player, Map<String, dObject> context) {
if (getCitizen() != null)
{
if (getCitizen().hasTrait(AssignmentTrait.class))
// Return the result from the ActionHandler
return DenizenAPI.getCurrentInstance().getNPCRegistry()
.getActionHandler().doAction(
actionName,
this,
player,
getAssignmentTrait().getAssignment(),
context);
}
return "none";
}
public String action(String actionName, dPlayer player) {
return action(actionName, player, null);
}
private String prefix = "npc";
@Override
public String getPrefix() {
return prefix;
}
@Override
public String debug() {
return (prefix + "='<A>" + identify() + "<G>' ");
}
@Override
public boolean isUnique() {
return true;
}
@Override
public String getObjectType() {
return "NPC";
}
@Override
public String identify() {
return "n@" + npcid;
}
@Override
public String identifySimple() {
return identify();
}
@Override
public dNPC setPrefix(String prefix) {
return this;
}
@Override
public boolean equals(Object o) {
if (o == null) return false;
if (!(o instanceof dNPC)) return false;
return getId() == ((dNPC) o).getId();
}
@Override
public int hashCode() {
return getId();
}
@Override
public String getAttribute(Attribute attribute) {
if (attribute == null) return "null";
// Defined in dEntity
if (attribute.startsWith("is_npc")) {
return Element.TRUE.getAttribute(attribute.fulfill(1));
}
// Defined in dEntity
if (attribute.startsWith("location") && !isSpawned()) {
return getLocation().getAttribute(attribute.fulfill(1));
}
// Defined in dEntity
if (attribute.startsWith("eye_location")) {
return getEyeLocation().getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.has_nickname>
// @returns Element(Boolean)
// @description
// Returns true if the NPC has a nickname.
// -->
if (attribute.startsWith("has_nickname")) {
NPC citizen = getCitizen();
return new Element(citizen.hasTrait(NicknameTrait.class) && citizen.getTrait(NicknameTrait.class).hasNickname())
.getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.name.nickname>
// @returns Element
// @description
// returns the NPC's display name.
// -->
if (attribute.startsWith("name.nickname"))
return new Element(getCitizen().hasTrait(NicknameTrait.class) ? getCitizen().getTrait(NicknameTrait.class)
.getNickname() : getName()).getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.name>
// @returns Element
// @description
// returns the name of the NPC.
// -->
if (attribute.startsWith("name"))
return new Element(getName())
.getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.list_traits>
// @returns dList
// @description
// Returns a list of all of the NPC's traits.
// -->
if (attribute.startsWith("list_traits")) {
List<String> list = new ArrayList<String>();
for (Trait trait : getCitizen().getTraits())
list.add(trait.getName());
return new dList(list).getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.has_trait[<trait>]>
// @returns Element(Boolean)
// @description
// Returns whether the NPC has a specified trait.
// -->
if (attribute.startsWith("has_trait")) {
if (attribute.hasContext(1)) {
Class<? extends Trait> trait = CitizensAPI.getTraitFactory().getTraitClass(attribute.getContext(1));
if (trait != null)
return new Element(getCitizen().hasTrait(trait))
.getAttribute(attribute.fulfill(1));
}
}
// <--[tag]
// @attribute <n@npc.has_trigger[<trigger>]>
// @returns Element(Boolean)
// @description
// Returns whether the NPC has a specified trigger.
// -->
if (attribute.startsWith("has_trigger")
&& attribute.hasContext(1)) {
if (!getCitizen().hasTrait(TriggerTrait.class))
return Element.FALSE.getAttribute(attribute.fulfill(1));
TriggerTrait trait = getCitizen().getTrait(TriggerTrait.class);
return new Element(trait.hasTrigger(attribute.getContext(1)))
.getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.anchor.list>
// @returns dList
// @description
// returns a list of anchor names currently assigned to the NPC.
// -->
if (attribute.startsWith("anchor.list")
|| attribute.startsWith("anchors.list")) {
List<String> list = new ArrayList<String>();
for (Anchor anchor : getCitizen().getTrait(Anchors.class).getAnchors())
list.add(anchor.getName());
return new dList(list).getAttribute(attribute.fulfill(2));
}
// <--[tag]
// @attribute <n@npc.has_anchors>
// @returns Element(Boolean)
// @description
// returns whether the NPC has anchors assigned.
// -->
if (attribute.startsWith("has_anchors")) {
return (new Element(getCitizen().getTrait(Anchors.class).getAnchors().size() > 0))
.getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.anchor[<name>]>
// @returns dLocation
// @description
// returns the location associated with the specified anchor, or null if it doesn't exist.
// -->
if (attribute.startsWith("anchor")) {
if (attribute.hasContext(1)
&& getCitizen().getTrait(Anchors.class).getAnchor(attribute.getContext(1)) != null)
return new dLocation(getCitizen().getTrait(Anchors.class)
.getAnchor(attribute.getContext(1)).getLocation())
.getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.has_flag[<flag_name>]>
// @returns Element(Boolean)
// @description
// returns true if the NPC has the specified flag, otherwise returns false.
// -->
if (attribute.startsWith("has_flag")) {
String flag_name;
if (attribute.hasContext(1)) flag_name = attribute.getContext(1);
else return null;
return new Element(FlagManager.npcHasFlag(this, flag_name)).getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.flag[<flag_name>]>
// @returns Flag dList
// @description
// returns the specified flag from the NPC.
// -->
if (attribute.startsWith("flag")) {
String flag_name;
if (attribute.hasContext(1)) flag_name = attribute.getContext(1);
else return null;
if (attribute.getAttribute(2).equalsIgnoreCase("is_expired")
|| attribute.startsWith("isexpired"))
return new Element(!FlagManager.npcHasFlag(this, flag_name))
.getAttribute(attribute.fulfill(2));
if (attribute.getAttribute(2).equalsIgnoreCase("size") && !FlagManager.npcHasFlag(this, flag_name))
return new Element(0).getAttribute(attribute.fulfill(2));
if (FlagManager.npcHasFlag(this, flag_name))
return new dList(DenizenAPI.getCurrentInstance().flagManager()
.getNPCFlag(getId(), flag_name))
.getAttribute(attribute.fulfill(1));
return new Element(identify()).getAttribute(attribute);
}
// <--[tag]
// @attribute <n@npc.list_flags[(regex:)<search>]>
// @returns dList
// @description
// Returns a list of an NPC's flag names, with an optional search for
// names containing a certain pattern.
// -->
if (attribute.startsWith("list_flags")) {
dList allFlags = new dList(DenizenAPI.getCurrentInstance().flagManager().listNPCFlags(getId()));
dList searchFlags = null;
if (!allFlags.isEmpty() && attribute.hasContext(1)) {
searchFlags = new dList();
String search = attribute.getContext(1).toLowerCase();
if (search.startsWith("regex:")) {
try {
Pattern pattern = Pattern.compile(search.substring(6));
for (String flag : allFlags)
if (pattern.matcher(flag).matches())
searchFlags.add(flag);
} catch (Exception e) {
dB.echoError(e);
}
}
else {
for (String flag : allFlags)
if (flag.toLowerCase().contains(search))
searchFlags.add(flag);
}
}
return searchFlags == null ? allFlags.getAttribute(attribute.fulfill(1))
: searchFlags.getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.constant[<constant_name>]>
// @returns Element
// @description
// returns the specified constant from the NPC.
// -->
if (attribute.startsWith("constant")) {
if (attribute.hasContext(1)) {
if (getCitizen().hasTrait(ConstantsTrait.class)
&& getCitizen().getTrait(ConstantsTrait.class).getConstant(attribute.getContext(1)) != null) {
return new Element(getCitizen().getTrait(ConstantsTrait.class)
.getConstant(attribute.getContext(1))).getAttribute(attribute.fulfill(1));
}
else {
return null;
}
}
}
// <--[tag]
// @attribute <n@npc.has_pose[<name>]>
// @returns Element(Boolean)
// @description
// Returns true if the NPC has the specified pose, otherwise returns false.
// -->
if (attribute.startsWith("has_pose")) {
if (attribute.hasContext(1))
return new Element(getCitizen().getTrait(Poses.class).hasPose(attribute.getContext(1)))
.getAttribute(attribute.fulfill(1));
else
return null;
}
// <--[tag]
// @attribute <n@npc.get_pose[<name>]>
// @returns dLocation
// @description
// Returns the pose as a dLocation with x, y, and z set to 0, and the world set to the first
// possible available world Bukkit knows about.
// -->
if (attribute.startsWith("get_pose")) {
if (attribute.hasContext(1)) {
Pose pose = getCitizen().getTrait(Poses.class).getPose(attribute.getContext(1));
return new dLocation(org.bukkit.Bukkit.getWorlds().get(0), 0, 0 ,0, pose.getYaw(), pose.getPitch())
.getAttribute(attribute.fulfill(1));
}
else
return null;
}
// <--[tag]
// @attribute <n@npc.is_engaged>
// @returns Element(Boolean)
// @description
// returns whether the NPC is currently engaged.
// See <@link command Engage>
// -->
if (attribute.startsWith("engaged") || attribute.startsWith("is_engaged"))
return new Element(isEngaged()).getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.id>
// @returns Element(Number)
// @description
// returns the NPC's ID number.
// -->
if (attribute.startsWith("id"))
return new Element(getId()).getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.owner>
// @returns dPlayer/Element
// @description
// returns the owner of the NPC as a dPlayer if it's a player, otherwise as just the name.
// -->
if (attribute.startsWith("owner")) {
if (dPlayer.matches(getOwner())) {
return dPlayer.valueOf(getOwner()).getAttribute(attribute.fulfill(1));
}
else return new Element(getOwner()).getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.has_skin>
// @returns Element
// @description
// returns whether the NPC has a custom skinskin.
// -->
if (attribute.startsWith("has_skin"))
return new Element(getCitizen().data().has(NPC.PLAYER_SKIN_UUID_METADATA)).getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.skin>
// @returns Element
// @description
// returns the NPC's custom skin, if any.
// -->
if (attribute.startsWith("skin")) {
if (getCitizen().data().has(NPC.PLAYER_SKIN_UUID_METADATA))
return new Element(getCitizen().data().get(NPC.PLAYER_SKIN_UUID_METADATA).toString()).getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.inventory>
// @returns dInventory
// @description
// Returns the dInventory of the NPC.
// -->
if (attribute.startsWith("inventory"))
return getDenizenInventory().getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.is_spawned>
// @returns Element(Boolean)
// @description
// returns whether the NPC is spawned.
// -->
if (attribute.startsWith("is_spawned"))
return new Element(isSpawned()).getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.is_protected>
// @returns Element(Boolean)
// @description
// Returns whether the NPC is protected.
// -->
if (attribute.startsWith("is_protected"))
return new Element(getCitizen().isProtected()).getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.lookclose>
// @returns Element(Boolean)
// @description
// Returns the NPC's "lookclose" value.
// -->
if (attribute.startsWith("lookclose")) {
NPC citizen = getCitizen();
if (citizen.hasTrait(LookClose.class)) {
// There is no method to check if the NPC has LookClose enabled...
// LookClose.toString() returns "LookClose{" + enabled + "}"
String lookclose = citizen.getTrait(LookClose.class).toString();
lookclose = lookclose.substring(10, lookclose.length() - 1);
return new Element(Boolean.valueOf(lookclose)).getAttribute(attribute.fulfill(1));
}
return Element.FALSE.getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.location.previous_location>
// @returns dLocation
// @description
// returns the NPC's previous navigated location.
// -->
if (attribute.startsWith("location.previous_location"))
return (NPCTags.previousLocations.containsKey(getId())
? NPCTags.previousLocations.get(getId()).getAttribute(attribute.fulfill(2))
: null);
// <--[tag]
// @attribute <n@npc.teleport_on_stuck>
// @returns dLocation
// @mechanism dNPC.teleport_on_stuck
// @description
// returns whether the NPC teleports when it is stuck.
// -->
if (attribute.startsWith("teleport_on_stuck"))
return new Element(getNavigator().getDefaultParameters().stuckAction() == TeleportStuckAction.INSTANCE)
.getAttribute(attribute.fulfill(1));
// <--[tag]
// @attribute <n@npc.has_script>
// @returns Element(Boolean)
// @description
// Returns true if the NPC has an assignment script.
// -->
if (attribute.startsWith("has_script")) {
NPC citizen = getCitizen();
return new Element(citizen.hasTrait(AssignmentTrait.class) && citizen.getTrait(AssignmentTrait.class).hasAssignment())
.getAttribute(attribute.fulfill(1));
}
// <--[tag]
// @attribute <n@npc.script>
// @returns dScript
// @description
// returns the NPC's assigned script.
// -->
if (attribute.startsWith("script")) {
NPC citizen = getCitizen();
if (!citizen.hasTrait(AssignmentTrait.class) || !citizen.getTrait(AssignmentTrait.class).hasAssignment()) {
return null;
}
else {
return new dScript(citizen.getTrait(AssignmentTrait.class).getAssignment().getName())
.getAttribute(attribute.fulfill(1));
}
}
// <--[tag]
// @attribute <n@npc.navigator.is_navigating>
// @returns Element(Boolean)
// @description
// returns whether the NPC is currently navigating.
// -->
if (attribute.startsWith("navigator.is_navigating"))
return new Element(getNavigator().isNavigating()).getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.speed>
// @returns Element(Number)
// @description
// returns the current speed of the NPC.
// -->
if (attribute.startsWith("navigator.speed"))
return new Element(getNavigator().getLocalParameters().speed())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.range>
// @returns Element(Number)
// @description
// returns the maximum pathfinding range.
// -->
if (attribute.startsWith("navigator.range"))
return new Element(getNavigator().getLocalParameters().range())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.attack_range>
// @returns Element(Number)
// @description
// returns the maximum attack range.
// -->
if (attribute.startsWith("navigator.attack_range"))
return new Element(getNavigator().getLocalParameters().attackRange())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.attack_strategy>
// @returns Element
// @description
// returns the NPC's attack strategy.
// -->
if (attribute.startsWith("navigator.attack_strategy"))
return new Element(getNavigator().getLocalParameters().attackStrategy().toString())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.speed_modifier>
// @returns Element(Number)
// @description
// returns the NPC movement speed modifier.
// -->
if (attribute.startsWith("navigator.speed_modifier"))
return new Element(getNavigator().getLocalParameters().speedModifier())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.base_speed>
// @returns Element(Number)
// @description
// returns the base navigation speed.
// -->
if (attribute.startsWith("navigator.base_speed"))
return new Element(getNavigator().getLocalParameters().baseSpeed())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.avoid_water>
// @returns Element(Boolean)
// @description
// returns whether the NPC will avoid water.
// -->
if (attribute.startsWith("navigator.avoid_water"))
return new Element(getNavigator().getLocalParameters().avoidWater())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.target_location>
// @returns dLocation
// @description
// returns the location the NPC is curently navigating towards.
// -->
if (attribute.startsWith("navigator.target_location"))
return (getNavigator().getTargetAsLocation() != null
? new dLocation(getNavigator().getTargetAsLocation()).getAttribute(attribute.fulfill(2))
: null);
// <--[tag]
// @attribute <n@npc.navigator.is_fighting>
// @returns Element(Boolean)
// @description
// returns whether the NPC is in combat.
// -->
if (attribute.startsWith("navigator.is_fighting"))
return new Element(getNavigator().getEntityTarget() != null && getNavigator().getEntityTarget().isAggressive())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.target_type>
// @returns Element
// @description
// returns the entity type of the target.
// -->
if (attribute.startsWith("navigator.target_type"))
// TODO: IMPROVE
return new Element(getNavigator().getTargetType() == null ? "null"
: getNavigator().getTargetType().toString())
.getAttribute(attribute.fulfill(2));
// <--[tag]
// @attribute <n@npc.navigator.target_entity>
// @returns dEntity
// @description
// returns the entity being targeted.
// -->
if (attribute.startsWith("navigator.target_entity"))
return (getNavigator().getEntityTarget() != null && getNavigator().getEntityTarget().getTarget() != null
? new dEntity(getNavigator().getEntityTarget().getTarget()).getAttribute(attribute.fulfill(2))
: null);
// <--[tag]
// @attribute <n@npc.type>
// @returns Element
// @description
// Always returns 'NPC' for dNPC objects. All objects fetchable by the Object Fetcher will return the
// type of object that is fulfilling this attribute.
// -->
if (attribute.startsWith("type")) {
return new Element("NPC").getAttribute(attribute.fulfill(1));
}
// Iterate through this object's properties' attributes
for (Property property : PropertyParser.getProperties(this)) {
String returned = property.getAttribute(attribute);
if (returned != null) return returned;
}
return (getEntity() != null
? new dEntity(this).getAttribute(attribute)
: new Element(identify()).getAttribute(attribute));
}
public void applyProperty(Mechanism mechanism) {
dB.echoError("Cannot apply properties to an NPC!");
}
@Override
public void adjust(Mechanism mechanism) {
Element value = mechanism.getValue();
// TODO: For all the mechanism tags, add the @Mechanism link!
// <--[mechanism]
// @object dNPC
// @name set_assignment
// @input dScript
// @description
// Sets the NPC's assignment script.
// @tags
// <n@npc.script>
// -->
if (mechanism.matches("set_assignment") && mechanism.requireObject(dScript.class)) {
getAssignmentTrait().setAssignment(value.asType(dScript.class).getName(), null);
}
// <--[mechanism]
// @object dNPC
// @name remove_assignment
// @input none
// @description
// Removes the NPC's assigment script.
// @tags
// <n@npc.has_script>
// -->
if (mechanism.matches("remove_assignment")) {
getAssignmentTrait().removeAssignment(null);
}
// <--[mechanism]
// @object dNPC
// @name set_nickname
// @input Element
// @description
// Sets the NPC's nickname.
// @tags
// <n@npc.name.nickname>
// -->
if (mechanism.matches("set_nickname")) {
getNicknameTrait().setNickname(value.asString());
}
// <--[mechanism]
// @object dNPC
// @name remove_nickname
// @input none
// @description
// Removes the NPC's nickname.
// @tags
// <n@npc.has_nickname>
// -->
if (mechanism.matches("remove_nickname")) {
getNicknameTrait().removeNickname();
}
// <--[mechanism]
// @object dNPC
// @name set_entity_type
// @input dEntity
// @description
// Sets the NPC's entity type.
// @tags
// <n@npc.entity_type>
// -->
if (mechanism.matches("set_entity_type") && mechanism.requireObject(dEntity.class)) {
getCitizen().setBukkitEntityType(value.asType(dEntity.class).getEntityType());
}
// <--[mechanism]
// @object dNPC
// @name set_name
// @input Element
// @description
// Sets the name of the NPC.
// @tags
// <n@npc.name>
// -->
if (mechanism.matches("set_name")) {
getCitizen().setName(value.asString().length() > 16 ? value.asString().substring(0, 16): value.asString());
}
// <--[mechanism]
// @object dNPC
// @name owner
// @input Element
// @description
// Sets the owner of the NPC.
// @tags
// <n@npc.owner>
// -->
if (mechanism.matches("owner")) {
getCitizen().getTrait(Owner.class).setOwner(value.asString());
}
// <--[mechanism]
// @object dNPC
// @name skin
// @input Element
// @description
// Sets the skin of an NPC.
// @tags
// <n@npc.skin>
// -->
if (mechanism.matches("skin")) {
if (!mechanism.hasValue())
getCitizen().data().remove(NPC.PLAYER_SKIN_UUID_METADATA);
else {
getCitizen().data().setPersistent(NPC.PLAYER_SKIN_UUID_METADATA, mechanism.getValue().asString());
}
if (getCitizen().isSpawned()) {
getCitizen().despawn(DespawnReason.PENDING_RESPAWN);
getCitizen().spawn(getCitizen().getStoredLocation());
}
}
// <--[mechanism]
// @object dNPC
// @name item_type
// @input dItem
// @description
// Sets the item type of the item.
// @tags
// None
// -->
if (mechanism.matches("item_type") && mechanism.requireObject(dItem.class)) {
dItem item = mechanism.getValue().asType(dItem.class);
Material mat = item.getMaterial().getMaterial();
int data = item.getMaterial().getData((byte)0);
switch (getEntity().getType()) {
case DROPPED_ITEM:
((org.bukkit.entity.Item) getEntity()).getItemStack().setType(mat);
((ItemController.ItemNPC) getEntity()).setType(mat, data);
break;
case ITEM_FRAME:
((ItemFrame) getEntity()).getItem().setType(mat);
((ItemFrameController.ItemFrameNPC) getEntity()).setType(mat, data);
break;
case FALLING_BLOCK:
((FallingBlockController.FallingBlockNPC) getEntity()).setType(mat, data);
break;
default:
dB.echoError("NPC is the not an item type!");
break;
}
}
// <--[mechanism]
// @object dNPC
// @name spawn
// @input dLocation
// @description
// Spawns the NPC at a location. If no location is specified, the NPC will spawn
// at its last known location.
// @tags
// <n@npc.is_spawned>
// -->
if (mechanism.matches("spawn")) {
if (mechanism.requireObject("Invalid dLocation specified. Assuming last known NPC location.", dLocation.class))
getCitizen().spawn(value.asType(dLocation.class));
else
getCitizen().spawn(getCitizen().getStoredLocation());
}
// <--[mechanism]
// @object dNPC
// @name range
// @input Element(Decimal)
// @description
// Sets the maximum movement distance of the NPC.
// @tags
// <n@npc.navigator.range>
// -->
if (mechanism.matches("range") && mechanism.requireFloat()) {
getCitizen().getNavigator().getDefaultParameters().range(mechanism.getValue().asFloat());
}
// <--[mechanism]
// @object dNPC
// @name attack_range
// @input Element(Decimal)
// @description
// Sets the maximum attack distance of the NPC.
// @tags
// <n@npc.navigator.attack_range>
// -->
if (mechanism.matches("attack_range") && mechanism.requireFloat()) {
getCitizen().getNavigator().getDefaultParameters().attackRange(mechanism.getValue().asFloat());
}
// <--[mechanism]
// @object dNPC
// @name speed
// @input Element(Decimal)
// @description
// Sets the movement speed of the NPC.
// @tags
// <n@npc.navigator.speed>
// -->
if (mechanism.matches("speed") && mechanism.requireFloat()) {
getCitizen().getNavigator().getDefaultParameters().speedModifier(mechanism.getValue().asFloat());
}
// <--[mechanism]
// @object dNPC
// @name despawn
// @input none
// @description
// Despawns the NPC.
// @tags
// <n@npc.is_spawned>
// -->
if (mechanism.matches("despawn")) {
getCitizen().despawn(DespawnReason.PLUGIN);
}
// <--[mechanism]
// @object dNPC
// @name set_protected
// @input Element(Boolean)
// @description
// Sets whether or not the NPC is protected.
// @tags
// <n@npc.is_protected>
// -->
if (mechanism.matches("set_protected") && mechanism.requireBoolean()) {
getCitizen().setProtected(value.asBoolean());
}
// <--[mechanism]
// @object dNPC
// @name set_lookclose
// @input Element(Boolean)
// @description
// Sets the NPC's lookclose value.
// @tags
// <n@npc.lookclose>
// -->
if (mechanism.matches("lookclose") && mechanism.requireBoolean()) {
getLookCloseTrait().lookClose(value.asBoolean());
}
// <--[mechanism]
// @object dNPC
// @name set_examiner
// @input Element
// @description
// Sets the NPC's block examiner
// @tags
// TODO
// -->
if (mechanism.matches("set_examiner")) {
if (mechanism.getValue().toString().equalsIgnoreCase("default")) {
getNavigator().getLocalParameters().clearExaminers();
getNavigator().getLocalParameters().examiner(new MinecraftBlockExaminer());
} else if (mechanism.getValue().toString().equalsIgnoreCase("fly")) {
getNavigator().getLocalParameters().clearExaminers();
getNavigator().getLocalParameters().examiner(new FlyingBlockExaminer());
} else if (mechanism.getValue().toString().equalsIgnoreCase("path")) {
getNavigator().getLocalParameters().clearExaminers();
getNavigator().getLocalParameters().examiner(new PathBlockExaminer(this, null));
}
}
// <--[mechanism]
// @object dNPC
// @name teleport_on_stuck
// @input Element(Boolean)
// @description
// Sets whether the NPC teleports when it is stuck.
// @tags
// <n@npc.teleport_on_stuck>
// -->
if (mechanism.matches("teleport_on_stuck") && mechanism.requireBoolean()) {
if (value.asBoolean())
getNavigator().getDefaultParameters().stuckAction(TeleportStuckAction.INSTANCE);
else
getNavigator().getDefaultParameters().stuckAction(null);
}
// <--[mechanism]
// @object dNPC
// @name set_distance
// @input Element
// @description
// Sets the NPC's distance margin
// @tags
// TODO
// -->
if (mechanism.matches("set_distance") && mechanism.requireDouble()) {
getNavigator().getDefaultParameters().distanceMargin(mechanism.getValue().asDouble());
}
// Iterate through this object's properties' mechanisms
for (Property property : PropertyParser.getProperties(this)) {
property.adjust(mechanism);
if (mechanism.fulfilled())
break;
}
// Pass along to dEntity mechanism handler if not already handled.
if (!mechanism.fulfilled()) {
if (isSpawned())
new dEntity(getEntity()).adjust(mechanism);
else
mechanism.reportInvalid();
}
}
}