diff --git a/src/main/java/net/aufdemrand/denizen/objects/dEntity.java b/src/main/java/net/aufdemrand/denizen/objects/dEntity.java index afd579d992..d139a20ad0 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/dEntity.java +++ b/src/main/java/net/aufdemrand/denizen/objects/dEntity.java @@ -154,7 +154,15 @@ else if (entityGroup.matches("P@")) { Entity entity = null; for (World world : Bukkit.getWorlds()) { - entity = ((CraftWorld) world).getHandle().getEntity(entityID).getBukkitEntity(); + net.minecraft.server.v1_6_R2.Entity nmsEntity = ((CraftWorld) world).getHandle().getEntity(entityID); + + if (nmsEntity != null) { + entity = nmsEntity.getBukkitEntity(); + } + else { + return null; + } + if (entity != null) break; } if (entity != null) return new dEntity(entity); @@ -281,6 +289,10 @@ public dEntity(EntityType entityType, String data1, String data2) { private String data2 = null; private DespawnedEntity despawned_entity = null; + public EntityType getEntityType() { + return entity_type; + } + public Entity getBukkitEntity() { return entity; } @@ -294,6 +306,43 @@ public LivingEntity getLivingEntity() { public boolean isLivingEntity() { return (entity instanceof LivingEntity); } + + /** + * Get the NPC corresponding to this entity + * + * @return The NPC + */ + + public NPC getNPC() { + + return CitizensAPI.getNPCRegistry().getNPC(getBukkitEntity()); + } + + /** + * Whether this entity is an NPC + * + * @return true or false + */ + + public boolean isNPC() { + if (CitizensAPI.getNPCRegistry().isNPC(getBukkitEntity())) + return true; + return false; + } + + /** + * Whether this entity identifies as a generic + * entity type instead of a spawned entity + * + * @return true or false + */ + + public boolean isGeneric() { + if (identify().matches("e@\\D+")) + return true; + return false; + } + public void spawnAt(Location location) { // If the entity is already spawned, teleport it. @@ -436,6 +485,10 @@ else if (entity != null) public boolean isSpawned() { return entity != null; } + + public void remove() { + entity.remove(); + } public dEntity rememberAs(String id) { dEntity.saveAs(this, id); @@ -553,14 +606,14 @@ public String identify() { // Check if entity is a Player or NPC if (getBukkitEntity() != null) { - if (CitizensAPI.getNPCRegistry().isNPC(getBukkitEntity())) - return "n@" + CitizensAPI.getNPCRegistry().getNPC(getBukkitEntity()).getId(); + if (isNPC()) + return "n@" + getNPC().getId(); else if (getBukkitEntity() instanceof Player) return "p@" + ((Player) getBukkitEntity()).getName(); } - + // Check if entity is a 'saved entity' - else if (isUnique()) + if (isUnique()) return "e@" + getSaved(this); // Check if entity is spawned, therefore having a bukkit entityId @@ -582,7 +635,7 @@ public String toString() { @Override public boolean isUnique() { if (entity instanceof Player) return true; - if (CitizensAPI.getNPCRegistry().isNPC(entity)) return true; + if (isNPC()) return true; return isSaved(this); } @@ -609,8 +662,8 @@ public String getAttribute(Attribute attribute) { } if (attribute.startsWith("name")) { - if (CitizensAPI.getNPCRegistry().isNPC(entity)) - return new Element(CitizensAPI.getNPCRegistry().getNPC(entity).getName()) + if (isNPC()) + return new Element(getNPC().getName()) .getAttribute(attribute.fulfill(1)); if (entity instanceof Player) return new Element(((Player) entity).getName()) @@ -723,7 +776,7 @@ else if ((float) getLivingEntity().getHealth() / maxHealth < 1) return new Element(String.valueOf(getLivingEntity().getCanPickupItems())) .getAttribute(attribute.fulfill(1)); - if (attribute.startsWith("entity_id")) + if (attribute.startsWith("id")) return new Element(String.valueOf(entity.getEntityId())) .getAttribute(attribute.fulfill(1)); diff --git a/src/main/java/net/aufdemrand/denizen/objects/dList.java b/src/main/java/net/aufdemrand/denizen/objects/dList.java index 2d01655106..5d59e1f567 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/dList.java +++ b/src/main/java/net/aufdemrand/denizen/objects/dList.java @@ -168,7 +168,14 @@ public List filter(Class dClass) { try { if ((Boolean) dClass.getMethod("matches", String.class).invoke(null, element)) { - results.add((dObject) dClass.getMethod("valueOf", String.class).invoke(null, element)); + dObject object = (dObject) dClass.getMethod("valueOf", String.class).invoke(null, element); + + // Only add the object if it is not null, thus filtering useless + // list items + + if (object != null) { + results.add(object); + } } } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/net/aufdemrand/denizen/objects/dNPC.java b/src/main/java/net/aufdemrand/denizen/objects/dNPC.java index 212846d7a5..51f1340cae 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/dNPC.java +++ b/src/main/java/net/aufdemrand/denizen/objects/dNPC.java @@ -133,6 +133,10 @@ public InteractScriptContainer getInteractScriptQuietly(dPlayer player, Class getEntities() { + return getWorld().getEntities(); + } private String prefix; String world_name; diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/BurnCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/BurnCommand.java index 057191e9d5..84f938b3f3 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/BurnCommand.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/BurnCommand.java @@ -43,6 +43,11 @@ else if (!scriptEntry.hasObject("duration") if ((!scriptEntry.hasObject("entities"))) throw new InvalidArgumentsException(Messages.ERROR_MISSING_OTHER, "ENTITIES"); + + // Use default duration if one is not specified + + if ((!scriptEntry.hasObject("duration"))) + scriptEntry.addObject("duration", Duration.valueOf("5s")); } @SuppressWarnings("unchecked") diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/RemoveCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/RemoveCommand.java index 3b761a444a..a88cd17bef 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/RemoveCommand.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/entity/RemoveCommand.java @@ -1,89 +1,135 @@ package net.aufdemrand.denizen.scripts.commands.entity; -import org.bukkit.Bukkit; -import org.bukkit.World; +import java.util.List; import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; import net.aufdemrand.denizen.exceptions.CommandExecutionException; import net.aufdemrand.denizen.exceptions.InvalidArgumentsException; +import net.aufdemrand.denizen.objects.Element; import net.aufdemrand.denizen.objects.aH; -import net.aufdemrand.denizen.objects.aH.ArgumentType; +import net.aufdemrand.denizen.objects.dEntity; +import net.aufdemrand.denizen.objects.dList; +import net.aufdemrand.denizen.objects.dWorld; import net.aufdemrand.denizen.scripts.ScriptEntry; import net.aufdemrand.denizen.scripts.commands.AbstractCommand; import net.aufdemrand.denizen.utilities.debugging.dB; +import net.aufdemrand.denizen.utilities.debugging.dB.Messages; import net.aufdemrand.denizen.utilities.depends.WorldGuardUtilities; /** - * Safely removes an NPC. - * - * To be expanded to use multiple NPCs and possibly other entities as well. + * Delete certain entities or all entities of a type. + * Can permanently remove NPCs if used on them. * + * @author David Cernat */ -public class RemoveCommand extends AbstractCommand { +public class RemoveCommand extends AbstractCommand { + @Override public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException { - - EntityType entityType = null; - String region = null; - for (String arg : scriptEntry.getArguments()) { - if (aH.matchesEntityType(arg)) { - entityType = aH.getEntityTypeFrom(arg); - dB.echoDebug("...will remove all '%s'.", arg); + for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) { + + if (!scriptEntry.hasObject("entities") + && arg.matchesPrefix("entity, entities, e")) { + // Entity arg + scriptEntry.addObject("entities", ((dList) arg.asType(dList.class)).filter(dEntity.class)); } - else if (aH.matchesValueArg("region", arg, ArgumentType.String)) { - region = aH.getStringFrom(arg); - dB.echoDebug("...in region " + region); + + else if (!scriptEntry.hasObject("region") + && arg.matchesPrefix("region, r")) { + // Location arg + scriptEntry.addObject("region", arg.asElement()); } - } - - scriptEntry.addObject("entityType", entityType); - scriptEntry.addObject("region", region); - } + + else if (!scriptEntry.hasObject("world") + && arg.matchesArgumentType(dWorld.class)) { + // add world + scriptEntry.addObject("world", arg.asType(dWorld.class)); + } + } - @Override - public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { + // Check to make sure required arguments have been filled - EntityType entityType = (EntityType) scriptEntry.getObject("entityType"); - String region = (String) scriptEntry.getObject("region"); - - // If no entity type or region chosen, remove this NPC - - if (entityType == null && region == null) { - - scriptEntry.getNPC().getCitizen().destroy(); + if ((!scriptEntry.hasObject("entities"))) + throw new InvalidArgumentsException(Messages.ERROR_MISSING_OTHER, "ENTITIES"); + + // If the world has not been specified, try to use the NPC's or player's + // world, or default to "world" if necessary + + if (!scriptEntry.hasObject("world")) { + + if ((scriptEntry.hasNPC())) { + scriptEntry.addObject("world", new dWorld(scriptEntry.getNPC().getWorld())); + } + else if ((scriptEntry.hasPlayer())) { + scriptEntry.addObject("world", new dWorld(scriptEntry.getPlayer().getWorld())); + } + else { + scriptEntry.addObject("world", dWorld.valueOf("world")); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public void execute(final ScriptEntry scriptEntry) throws CommandExecutionException { - dB.echoDebug("...have removed NPC '%s'.", String.valueOf(scriptEntry.getNPC().getCitizen().getId())); - } - - // Else, remove regular entities - - else { + // Get objects + List entities = (List) scriptEntry.getObject("entities"); + dWorld world = (dWorld) scriptEntry.getObject("world"); + Element region = (Element) scriptEntry.getObject("region"); + + // Report to dB + dB.report(getName(), aH.debugObj("entities", entities.toString()) + + (region != null ? aH.debugObj("region", region) : "")); + + // Go through all of our entities and remove them + + for (dEntity entity : entities) { - for (World world: Bukkit.getWorlds()) { - for (Entity entity : world.getEntities()) { - if (region != null) { - - if (WorldGuardUtilities.inRegion(entity.getLocation(), region)) { - - if (entityType == null) { - entity.remove(); - } - else if (entity.getType().equals(entityType)) { - entity.remove(); - } - } - } - - else if (entity.getType().equals(entityType)) { - - entity.remove(); - } - } - } + // If this is a specific spawned entity, and all + // other applicable conditions are met, remove it + + if (entity.isGeneric() == false + && region == null ? true : + WorldGuardUtilities.inRegion + (entity.getBukkitEntity().getLocation(), + region.asString())) { + + if (entity.isNPC()) { + entity.getNPC().destroy(); + } + else { + entity.remove(); + } + } + + // If this is a generic unspawned entity, remove + // all entities of this type from the world + + else { + + // Note: getting the entities from each loaded chunk + // in the world (like in Essentials' /killall) has the + // exact same effect as the below + + for (Entity worldEntity : world.getEntities()) { + + // If this entity from the world is of the same type + // as our current dEntity, and all other applicable + // conditions are met, remove it + + if (entity.getEntityType().equals(worldEntity.getType()) + && region == null ? true : + WorldGuardUtilities.inRegion + (entity.getBukkitEntity().getLocation(), + region.asString())) { + + worldEntity.remove(); + } + } + } } - } - + } } \ No newline at end of file diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/TimeCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/TimeCommand.java index abe3278f4d..f4081a5f4e 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/TimeCommand.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/TimeCommand.java @@ -7,6 +7,7 @@ import net.aufdemrand.denizen.scripts.ScriptEntry; import net.aufdemrand.denizen.scripts.commands.AbstractCommand; import net.aufdemrand.denizen.objects.Duration; +import net.aufdemrand.denizen.objects.Element; import net.aufdemrand.denizen.objects.aH; import net.aufdemrand.denizen.objects.dWorld; import net.aufdemrand.denizen.utilities.debugging.dB; @@ -50,10 +51,20 @@ else if (!scriptEntry.hasObject("world") if ((!scriptEntry.hasObject("value"))) throw new InvalidArgumentsException(Messages.ERROR_MISSING_OTHER, "VALUE"); - // Use default world if none has been specified + // If the world has not been specified, try to use the NPC's or player's + // world, or default to "world" if necessary if (!scriptEntry.hasObject("world")) { - scriptEntry.addObject("world", dWorld.valueOf("world")); + + if ((scriptEntry.hasNPC())) { + scriptEntry.addObject("world", new dWorld(scriptEntry.getNPC().getWorld())); + } + else if ((scriptEntry.hasPlayer())) { + scriptEntry.addObject("world", new dWorld(scriptEntry.getPlayer().getWorld())); + } + else { + scriptEntry.addObject("world", dWorld.valueOf("world")); + } } } @@ -66,10 +77,12 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { (Type) scriptEntry.getObject("type") : Type.GLOBAL; // Report to dB - dB.report(getName(), type.name() + ", " - + (type.name().equalsIgnoreCase("player") ? scriptEntry.getPlayer().debug() : "") - + (type.name().equalsIgnoreCase("global") ? world.debug() : "") - + value.debug()); + dB.report(getName(), aH.debugObj("type", type.name()) + + (type.name().equalsIgnoreCase("player") ? + aH.debugObj("player", scriptEntry.getPlayer()) : "") + + (type.name().equalsIgnoreCase("global") ? + aH.debugObj("world", world) : "") + + aH.debugObj("value", value)); if (type.equals(Type.GLOBAL)) { world.getWorld().setTime(value.getTicks()); diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/WeatherCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/WeatherCommand.java index f9b9ac54c3..265af8acf4 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/WeatherCommand.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/WeatherCommand.java @@ -48,10 +48,21 @@ else if (!scriptEntry.hasObject("value") if ((!scriptEntry.hasObject("value"))) throw new InvalidArgumentsException(Messages.ERROR_MISSING_OTHER, "VALUE"); - // Use default world if none has been specified + // If the world has not been specified, try to use the NPC's or player's + // world, or default to "world" if necessary - if (!scriptEntry.hasObject("world")) - scriptEntry.addObject("world", dWorld.valueOf("world")); + if (!scriptEntry.hasObject("world")) { + + if ((scriptEntry.hasNPC())) { + scriptEntry.addObject("world", new dWorld(scriptEntry.getNPC().getWorld())); + } + else if ((scriptEntry.hasPlayer())) { + scriptEntry.addObject("world", new dWorld(scriptEntry.getPlayer().getWorld())); + } + else { + scriptEntry.addObject("world", dWorld.valueOf("world")); + } + } } @Override @@ -64,10 +75,12 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { (Type) scriptEntry.getObject("type") : Type.GLOBAL; // Report to dB - dB.report(getName(), type.name() + ", " - + (type.name().equalsIgnoreCase("player") ? scriptEntry.getPlayer().debug() : "") - + (type.name().equalsIgnoreCase("global") ? world.debug() : "") - + value.name()); + dB.report(getName(), aH.debugObj("type", type.name()) + + (type.name().equalsIgnoreCase("player") ? + aH.debugObj("player", scriptEntry.getPlayer()) : "") + + (type.name().equalsIgnoreCase("global") ? + aH.debugObj("world", world) : "") + + aH.debugObj("value", value)); switch(value) { case SUNNY: