Fix NPC bats, add /npc skeletontype, /npc create now allows creation at another player

This commit is contained in:
fullwall 2012-10-29 17:26:42 +08:00
parent 6ab712f893
commit e9e2c057dc
16 changed files with 120 additions and 127 deletions

View File

@ -38,7 +38,7 @@ public class EditorCommands {
max = 1,
permission = "npc.edit.path")
@Requirements(selected = true, ownership = true, excludedTypes = { EntityType.BLAZE,
EntityType.ENDER_DRAGON, EntityType.GHAST, EntityType.SQUID })
EntityType.ENDER_DRAGON, EntityType.GHAST, EntityType.BAT, EntityType.WITHER, EntityType.SQUID })
public void path(CommandContext args, Player player, NPC npc) {
Editor.enterOrLeave(player, npc.getTrait(Waypoints.class).getEditor(player));
}

View File

@ -35,6 +35,7 @@ import net.citizensnpcs.trait.Gravity;
import net.citizensnpcs.trait.LookClose;
import net.citizensnpcs.trait.Poses;
import net.citizensnpcs.trait.Powered;
import net.citizensnpcs.trait.SkeletonType;
import net.citizensnpcs.trait.SlimeSize;
import net.citizensnpcs.trait.VillagerProfession;
import net.citizensnpcs.util.Anchor;
@ -318,35 +319,36 @@ public class NPCCommands {
}
if (args.hasValueFlag("at")) {
String[] parts = Iterables.toArray(Splitter.on(':').split(args.getFlag("at")), String.class);
String worldName = sender instanceof Player ? ((Player) sender).getLocation().getWorld()
.getName() : "";
int x = 0, y = 0, z = 0;
float yaw = 0F, pitch = 0F;
switch (parts.length) {
case 6:
pitch = Float.parseFloat(parts[5]);
case 5:
yaw = Float.parseFloat(parts[4]);
case 4:
worldName = parts[3];
case 3:
case 2:
case 1:
if (parts.length < 3)
if (parts.length > 0) {
String worldName = sender instanceof Player ? ((Player) sender).getLocation().getWorld()
.getName() : "";
int x = 0, y = 0, z = 0;
float yaw = 0F, pitch = 0F;
switch (parts.length) {
case 6:
pitch = Float.parseFloat(parts[5]);
case 5:
yaw = Float.parseFloat(parts[4]);
case 4:
worldName = parts[3];
case 3:
x = Integer.parseInt(parts[0]);
y = Integer.parseInt(parts[1]);
z = Integer.parseInt(parts[2]);
break;
default:
throw new CommandException(Messages.INVALID_SPAWN_LOCATION);
x = Integer.parseInt(parts[0]);
y = Integer.parseInt(parts[1]);
z = Integer.parseInt(parts[2]);
break;
default:
break;
case 0:
}
World world = Bukkit.getWorld(worldName);
if (world == null)
throw new CommandException(Messages.INVALID_SPAWN_LOCATION);
spawnLoc = new Location(world, x, y, z, yaw, pitch);
} else {
Player search = Bukkit.getPlayerExact(args.getFlag("at"));
if (search == null)
throw new CommandException(Messages.PLAYER_NOT_FOUND_FOR_SPAWN);
spawnLoc = search.getLocation();
}
World world = Bukkit.getWorld(worldName);
if (world == null)
throw new CommandException(Messages.INVALID_SPAWN_LOCATION);
spawnLoc = new Location(world, x, y, z, yaw, pitch);
}
if (spawnLoc == null) {
npc.destroy();
@ -818,6 +820,21 @@ public class NPCCommands {
Messaging.sendTr(sender, Messages.NPC_RENAMED, oldName, newName);
}
@Command(
aliases = { "npc" },
usage = "skeletontype [type]",
desc = "Sets the NPC's skeleton type",
modifiers = { "skeletontype", "sktype" },
min = 2,
max = 2,
permission = "npc.skeletontype")
@Requirements(selected = true, ownership = true, types = EntityType.SKELETON)
public void skeletonType(CommandContext args, CommandSender sender, NPC npc) {
int type = args.getInteger(1);
npc.getTrait(SkeletonType.class).setType(type);
Messaging.sendTr(sender, Messages.SKELETON_TYPE_SET, npc.getName(), type);
}
@Command(
aliases = { "npc" },
usage = "select|sel [id|name] (--r range)",

View File

@ -26,6 +26,7 @@ import net.citizensnpcs.trait.Poses;
import net.citizensnpcs.trait.Powered;
import net.citizensnpcs.trait.Saddle;
import net.citizensnpcs.trait.Sheared;
import net.citizensnpcs.trait.SkeletonType;
import net.citizensnpcs.trait.SlimeSize;
import net.citizensnpcs.trait.VillagerProfession;
import net.citizensnpcs.trait.WoolColor;
@ -41,26 +42,27 @@ public class CitizensTraitFactory implements TraitFactory {
public CitizensTraitFactory() {
registerTrait(TraitInfo.create(Age.class).withName("age"));
registerTrait(TraitInfo.create(CurrentLocation.class).withName("location"));
registerTrait(TraitInfo.create(Anchors.class).withName("anchors"));
registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour"));
registerTrait(TraitInfo.create(Controllable.class).withName("controllable"));
registerTrait(TraitInfo.create(Equipment.class).withName("equipment"));
registerTrait(TraitInfo.create(Inventory.class).withName("inventory"));
registerTrait(TraitInfo.create(LookClose.class).withName("lookclose"));
registerTrait(TraitInfo.create(Gravity.class).withName("gravity"));
registerTrait(TraitInfo.create(SlimeSize.class).withName("slimesize"));
registerTrait(TraitInfo.create(MobType.class).withName("type"));
registerTrait(TraitInfo.create(Inventory.class).withName("inventory"));
registerTrait(TraitInfo.create(CurrentLocation.class).withName("location"));
registerTrait(TraitInfo.create(LookClose.class).withName("lookclose"));
registerTrait(TraitInfo.create(Owner.class).withName("owner"));
registerTrait(TraitInfo.create(Poses.class).withName("poses"));
registerTrait(TraitInfo.create(Powered.class).withName("powered"));
registerTrait(TraitInfo.create(VillagerProfession.class).withName("profession"));
registerTrait(TraitInfo.create(Saddle.class).withName("saddle"));
registerTrait(TraitInfo.create(Sheared.class).withName("sheared"));
registerTrait(TraitInfo.create(SkeletonType.class).withName("skeletontype"));
registerTrait(TraitInfo.create(SlimeSize.class).withName("slimesize"));
registerTrait(TraitInfo.create(Spawned.class).withName("spawned"));
registerTrait(TraitInfo.create(Text.class).withName("text"));
registerTrait(TraitInfo.create(VillagerProfession.class).withName("profession"));
registerTrait(TraitInfo.create(MobType.class).withName("type"));
registerTrait(TraitInfo.create(Waypoints.class).withName("waypoints"));
registerTrait(TraitInfo.create(WoolColor.class).withName("woolcolor"));
registerTrait(TraitInfo.create(Controllable.class).withName("controllable"));
registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour"));
registerTrait(TraitInfo.create(Poses.class).withName("poses"));
registerTrait(TraitInfo.create(Anchors.class).withName("anchors"));
for (String trait : registered.keySet())
INTERNAL_TRAITS.add(trait);

View File

@ -54,13 +54,15 @@ public class CitizensBatNPC extends CitizensMobNPC {
if (npc != null) {
NMS.clearGoals(goalSelector, targetSelector);
NMS.setPersistent(this);
f(false);
}
}
@Override
public void bi() {
super.bi();
if (npc != null)
if (npc == null)
super.bi();
else
npc.update();
}
@ -109,8 +111,8 @@ public class CitizensBatNPC extends CitizensMobNPC {
@Override
public void j_() {
if (npc == null)
super.j_();
super.j_();
npc.update();
}
}
}

View File

@ -34,7 +34,7 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable {
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
handle.ay = loc.getYaw() % 360;
NMS.setHeadYaw(handle, loc.getYaw() % 360);
// set the head yaw in another tick - if done immediately,
// minecraft will not update it.
boolean removeFromPlayerList = Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean();
@ -96,6 +96,7 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable {
}
}
Messaging.sendTr(equipper, Messages.EQUIPMENT_EDITOR_ALL_ITEMS_REMOVED, getName());
break;
default:
break;
}

View File

@ -1,6 +1,7 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.util.Messages;
@ -10,7 +11,9 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Ageable;
public class Age extends Trait implements Toggleable {
@Persist
private int age = 0;
@Persist
private boolean locked = true;
public Age() {
@ -29,8 +32,6 @@ public class Age extends Trait implements Toggleable {
public void load(DataKey key) throws NPCLoadException {
if (npc.isSpawned() && !(npc.getBukkitEntity() instanceof Ageable))
throw new NPCLoadException("NPC must be ageable");
age = key.getInt("age");
locked = key.getBoolean("locked");
}
@Override
@ -48,12 +49,6 @@ public class Age extends Trait implements Toggleable {
age = ((Ageable) npc.getBukkitEntity()).getAge();
}
@Override
public void save(DataKey key) {
key.setInt("age", age);
key.setBoolean("locked", locked);
}
public void setAge(int age) {
this.age = age;
if (isAgeable())

View File

@ -5,6 +5,7 @@ import java.util.Map;
import net.citizensnpcs.api.event.NPCRightClickEvent;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.command.CommandConfigurable;
@ -27,6 +28,7 @@ import com.google.common.collect.Maps;
//TODO: reduce reliance on CitizensNPC
public class Controllable extends Trait implements Toggleable, CommandConfigurable {
private Controller controller = new GroundController();
@Persist
private boolean enabled;
private EntityType explicitType;
@ -68,7 +70,6 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
@Override
public void load(DataKey key) throws NPCLoadException {
enabled = key.getBoolean("enabled");
explicitType = Util.matchEntityType(key.getString("explicittype"));
}
@ -150,7 +151,6 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
@Override
public void save(DataKey key) {
key.setBoolean("enabled", enabled);
if (explicitType == null)
key.removeKey("explicittype");
else

View File

@ -1,13 +1,12 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import org.bukkit.Bukkit;
import org.bukkit.Location;
public class CurrentLocation extends Trait {
@Persist(required = true)
private Location loc;
public CurrentLocation() {
@ -18,15 +17,6 @@ public class CurrentLocation extends Trait {
return loc;
}
@Override
public void load(DataKey key) throws NPCLoadException {
if (Bukkit.getWorld(key.getString("world")) == null)
throw new NPCLoadException("'" + key.getString("world") + "' is not a valid world.");
loc = new Location(Bukkit.getWorld(key.getString("world")), key.getDouble("x"), key.getDouble("y"),
key.getDouble("z"), (float) key.getDouble("yaw"), (float) key.getDouble("pitch"));
}
@Override
public void run() {
if (!npc.isSpawned())
@ -34,21 +24,6 @@ public class CurrentLocation extends Trait {
loc = npc.getBukkitEntity().getLocation();
}
@Override
public void save(DataKey key) {
if (loc == null) {
key.removeKey(getName());
return;
}
key.setString("world", loc.getWorld().getName());
key.setDouble("x", loc.getX());
key.setDouble("y", loc.getY());
key.setDouble("z", loc.getZ());
key.setDouble("yaw", loc.getYaw());
key.setDouble("pitch", loc.getPitch());
}
public void setLocation(Location loc) {
this.loc = loc;
}

View File

@ -11,7 +11,6 @@ import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.command.CommandConfigurable;
import net.citizensnpcs.command.CommandContext;
import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.Util;
import org.bukkit.Location;
@ -30,7 +29,7 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable
}
private boolean canSeeTarget() {
return realisticLooking ? NMS.rayTrace(npc.getBukkitEntity(), lookingAt) : true;
return realisticLooking ? npc.getBukkitEntity().hasLineOfSight(lookingAt) : true;
}
@Override

View File

@ -1,34 +1,24 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import org.bukkit.entity.Creeper;
public class Powered extends Trait implements Toggleable {
@Persist("")
private boolean powered;
public Powered() {
super("powered");
}
@Override
public void load(DataKey key) throws NPCLoadException {
powered = key.getBoolean("");
}
@Override
public void onSpawn() {
if (npc.getBukkitEntity() instanceof Creeper)
((Creeper) npc.getBukkitEntity()).setPowered(powered);
}
@Override
public void save(DataKey key) {
key.setBoolean("", powered);
}
@Override
public boolean toggle() {
powered = !powered;

View File

@ -1,9 +1,8 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import org.bukkit.entity.Pig;
import org.bukkit.event.EventHandler;
@ -11,17 +10,13 @@ import org.bukkit.event.player.PlayerInteractEntityEvent;
public class Saddle extends Trait implements Toggleable {
private boolean pig;
@Persist("")
private boolean saddle;
public Saddle() {
super("saddle");
}
@Override
public void load(DataKey key) throws NPCLoadException {
saddle = key.getBoolean("");
}
@EventHandler
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
if (pig && npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getRightClicked())))
@ -37,11 +32,6 @@ public class Saddle extends Trait implements Toggleable {
pig = false;
}
@Override
public void save(DataKey key) {
key.setBoolean("", saddle);
}
@Override
public boolean toggle() {
saddle = !saddle;

View File

@ -1,26 +1,21 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import org.bukkit.entity.Sheep;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerShearEntityEvent;
public class Sheared extends Trait implements Toggleable {
@Persist("")
private boolean sheared;
public Sheared() {
super("sheared");
}
@Override
public void load(DataKey key) throws NPCLoadException {
sheared = key.getBoolean("");
}
@EventHandler
public void onPlayerShearEntityEvent(PlayerShearEntityEvent event) {
if (npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getEntity())))
@ -32,11 +27,6 @@ public class Sheared extends Trait implements Toggleable {
((Sheep) npc.getBukkitEntity()).setSheared(sheared);
}
@Override
public void save(DataKey key) {
key.setBoolean("", sheared);
}
@Override
public boolean toggle() {
sheared = !sheared;

View File

@ -0,0 +1,31 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import org.bukkit.craftbukkit.entity.CraftSkeleton;
public class SkeletonType extends Trait {
@Persist
private int type = 0;
private boolean skeleton;
public SkeletonType() {
super("skeletontype");
}
public void setType(int type) {
this.type = Math.max(0, Math.min(1, type));
}
@Override
public void onSpawn() {
skeleton = npc.getBukkitEntity() instanceof CraftSkeleton;
}
@Override
public void run() {
if (skeleton)
((CraftSkeleton) npc.getBukkitEntity()).getHandle().setSkeletonType(type);
}
}

View File

@ -202,4 +202,6 @@ public class Messages {
public static final String WAYPOINT_TRIGGER_TELEPORT_PROMPT = "citizens.editors.waypoints.triggers.teleport.prompt";
public static final String WORLD_NOT_FOUND = "citizens.commands.errors.missing-world";
public static final String WRITING_DEFAULT_SETTING = "citizens.settings.writing-default";
public static final String SKELETON_TYPE_SET = "citizens.commands.npc.skeletontype.set";
public static final String PLAYER_NOT_FOUND_FOR_SPAWN = "citizens.commands.npc.create.no-player-for-spawn";
}

View File

@ -141,12 +141,6 @@ public class NMS {
handle.pitch = pitch;
}
public static boolean rayTrace(LivingEntity entity, LivingEntity entity2) {
EntityLiving from = ((CraftLivingEntity) entity).getHandle();
EntityLiving to = ((CraftLivingEntity) entity2).getHandle();
return from.m(to);
}
public static void registerEntityClass(Class<? extends Entity> clazz) {
if (ENTITY_CLASS_TO_INT.containsKey(clazz))
return;
@ -262,7 +256,6 @@ public class NMS {
MOVEMENT_SPEEDS.put(EntityType.SHEEP, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.SNOWMAN, 0.25F);
MOVEMENT_SPEEDS.put(EntityType.PIG, 0.27F);
MOVEMENT_SPEEDS.put(EntityType.PLAYER, 1F);
MOVEMENT_SPEEDS.put(EntityType.VILLAGER, 0.3F);
LAND_SPEED_MODIFIER_FIELD = getField(EntityLiving.class, "bQ");
@ -281,4 +274,8 @@ public class NMS {
Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage());
}
}
public static void setHeadYaw(EntityLiving handle, float yaw) {
handle.ay = yaw;
}
}

View File

@ -32,6 +32,7 @@ citizens.commands.npc.create.invalid-location=Spawn location could not be parsed
citizens.commands.npc.create.invalid-mobtype={0} is not a valid mob type. Using default type.
citizens.commands.npc.create.not-living-mobtype={0} is not a living entity type. Using default type.
citizens.commands.npc.create.npc-name-too-long=NPC names cannot be longer than 16 characters. The name has been shortened.
citizens.commands.npc.create.no-player-for-spawn=No player could be found by that name to spawn an NPC at.
citizens.commands.npc.despawn.despawned=You despawned [[{0}]].
citizens.commands.npc.gamemode.describe={0}''s gamemode is [[{1}]].
citizens.commands.npc.gamemode.invalid={0} is not a valid gamemode.
@ -66,6 +67,7 @@ citizens.commands.npc.rename.renamed=You renamed [[{0}]] to [[{1}]].
citizens.commands.npc.select.already-selected=You already have that NPC selected.
citizens.commands.npc.size.description={0}''s size is [[{1}]].
citizens.commands.npc.size.set={0}''s size set to [[{1}]].
citizens.commands.npc.skeletontype.set={0}''s skeleton type set to [[{1}]].
citizens.commands.npc.spawn.already-spawned={0} is already spawned at another location. Use ''/npc tphere'' to teleport the NPC to your location.
citizens.commands.npc.spawn.missing-npc-id=No NPC with the ID {0} exists.
citizens.commands.npc.spawn.no-location=No stored location available - command must be used ingame.
@ -135,7 +137,7 @@ citizens.editors.text.remove-prompt=Enter the index of the entry you wish to rem
citizens.editors.text.removed-entry=[[Removed]] entry at index [[{0}]].
citizens.editors.text.start-prompt=Type [[add]] to add an entry, [[edit]] to edit entries, [[remove]] to remove entries, [[close]] to toggle the NPC as a close talker, and [[random]] to toggle the NPC as a random talker. Type [[help]] to show this again.
citizens.editors.waypoints.linear.added-waypoint=[[Added]] a waypoint at ({0}) ([[{1}]], [[{2}]])
citizens.editors.waypoints.linear.begin=<b>Entered the linear waypoint editor!<br>[[Left click]] to add a waypoint, [[right click]] to remove.<br>Type [[toggle path]] to toggle showing entities at waypoints.
citizens.editors.waypoints.linear.begin=<b>Entered the linear waypoint editor!<br> [[Left click]] to add a waypoint, [[right click]] to remove.<br> Type [[toggle path]] to toggle showing entities at waypoints.
citizens.editors.waypoints.linear.edit-slot-set=Editing slot set to [[{0}]] ({1}).
citizens.editors.waypoints.linear.end=Exited the linear waypoint editor.
citizens.editors.waypoints.linear.not-showing-markers=[[Stopped]] showing waypoint markers.
@ -147,10 +149,10 @@ citizens.editors.waypoints.triggers.add.invalid-trigger=Couldn''t create a trigg
citizens.editors.waypoints.triggers.add.prompt=Enter in a trigger name to add or type [[back]] to return to the edit prompt. Valid trigger names are {0}.
citizens.editors.waypoints.triggers.chat.invalid-radius=The radius must be a number.
citizens.editors.waypoints.triggers.chat.missing-radius=No radius supplied.
citizens.editors.waypoints.triggers.chat.prompt=Enter in chat lines to say. <br>Type in [[radius (radius)]] to set the block radius to broadcast the messages. <br> Type [[finish]] to finish the chat trigger or [[back]] to return to the previous prompt.
citizens.editors.waypoints.triggers.chat.prompt=Enter in chat lines to say. <br>Type in [[radius (radius)]] to set the block radius to broadcast the messages.<br>Type [[finish]] to finish the chat trigger or [[back]] to return to the previous prompt.
citizens.editors.waypoints.triggers.delay.prompt=Enter the delay in [[server ticks]] to use. (20 ticks = 1 second)
citizens.editors.waypoints.triggers.main.missing-waypoint=Not editing a waypoint.
citizens.editors.waypoints.triggers.main.prompt=<b>Entered the waypoint trigger editor.<br> Type [[add]] to begin adding triggers and [[remove]] to remove triggers.<br><br> Current triggers are:
citizens.editors.waypoints.triggers.main.prompt=<b>Entered the waypoint trigger editor.<br> Type [[add]] to begin adding triggers and [[remove]] to remove triggers.<br> Current triggers are:
citizens.editors.waypoints.triggers.remove.index-out-of-range=Index must be in the range [[1-{0}]].
citizens.editors.waypoints.triggers.remove.not-a-number=Index must be a number.
citizens.editors.waypoints.triggers.remove.prompt=Enter in the index of the trigger to delete or [[back]] to return to the edit prompt. Current triggers are: