diff --git a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java index 070bf7fd5..a0b213e1d 100644 --- a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java @@ -249,17 +249,17 @@ public class NPCCommands { @Command( aliases = { "npc" }, - usage = "create [name] ((-b -u) --type (type) --trait ('trait1, trait2...') --b (behaviour))", + usage = "create [name] ((-b,u) --at (x:y:z:world) --type (type) --trait ('trait1, trait2...') --b (behaviours))", desc = "Create a new NPC", flags = "bu", modifiers = { "create" }, min = 2, permission = "npc.create") @Requirements - public void create(CommandContext args, final Player player, NPC npc) throws CommandException { + public void create(CommandContext args, CommandSender sender, NPC npc) throws CommandException { String name = StringHelper.parseColors(args.getJoinedStrings(1)); if (name.length() > 16) { - Messaging.sendErrorTr(player, Messages.NPC_NAME_TOO_LONG); + Messaging.sendErrorTr(sender, Messages.NPC_NAME_TOO_LONG); name = name.substring(0, 15); } EntityType type = EntityType.PLAYER; @@ -267,21 +267,21 @@ public class NPCCommands { String inputType = args.getFlag("type"); type = Util.matchEntityType(inputType); if (type == null) { - Messaging.sendErrorTr(player, Messages.NPC_CREATE_INVALID_MOBTYPE, inputType); + Messaging.sendErrorTr(sender, Messages.NPC_CREATE_INVALID_MOBTYPE, inputType); type = EntityType.PLAYER; } else if (!LivingEntity.class.isAssignableFrom(type.getEntityClass())) { - Messaging.sendErrorTr(player, Messages.NOT_LIVING_MOBTYPE, type); + Messaging.sendErrorTr(sender, Messages.NOT_LIVING_MOBTYPE, type); type = EntityType.PLAYER; } } npc = npcRegistry.createNPC(type, name); - String msg = "You created [[" + npc.getName() + "]] at your location"; + String msg = "You created [[" + npc.getName() + "]]"; int age = 0; if (args.hasFlag('b')) { if (!Ageable.class.isAssignableFrom(type.getEntityClass())) - Messaging.sendErrorTr(player, Messages.MOBTYPE_CANNOT_BE_AGED, type.name().toLowerCase() + Messaging.sendErrorTr(sender, Messages.MOBTYPE_CANNOT_BE_AGED, type.name().toLowerCase() .replace("_", "-")); else { age = -24000; @@ -298,21 +298,61 @@ public class NPCCommands { // Initialize necessary traits if (!Setting.SERVER_OWNS_NPCS.asBoolean()) - npc.getTrait(Owner.class).setOwner(player.getName()); + npc.getTrait(Owner.class).setOwner(sender.getName()); npc.getTrait(MobType.class).setType(type); - if (!args.hasFlag('u')) - npc.spawn(player.getLocation()); - - PlayerCreateNPCEvent event = new PlayerCreateNPCEvent(player, npc); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - npc.destroy(); - String reason = "Couldn't create NPC."; - if (!event.getCancelReason().isEmpty()) - reason += " Reason: " + event.getCancelReason(); - throw new CommandException(reason); + Location spawnLoc = null; + if (sender instanceof Player) { + spawnLoc = ((Player) sender).getLocation(); + PlayerCreateNPCEvent event = new PlayerCreateNPCEvent((Player) sender, npc); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + npc.destroy(); + String reason = "Couldn't create NPC."; + if (!event.getCancelReason().isEmpty()) + reason += " Reason: " + event.getCancelReason(); + throw new CommandException(reason); + } } + 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) + 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: + throw new CommandException(Messages.INVALID_SPAWN_LOCATION); + } + 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(); + throw new CommandException(Messages.INVALID_SPAWN_LOCATION); + } + + if (!args.hasFlag('u')) + npc.spawn(spawnLoc); if (args.hasValueFlag("trait")) { Iterable parts = Splitter.on(',').trimResults().split(args.getFlag("trait")); @@ -347,8 +387,8 @@ public class NPCCommands { // Set age after entity spawns if (npc.getBukkitEntity() instanceof Ageable) npc.getTrait(Age.class).setAge(age); - selector.select(player, npc); - Messaging.send(player, msg); + selector.select(sender, npc); + Messaging.send(sender, msg); } @Command( diff --git a/src/main/java/net/citizensnpcs/trait/LookClose.java b/src/main/java/net/citizensnpcs/trait/LookClose.java index 3f5ad9bf7..bf5be23b4 100644 --- a/src/main/java/net/citizensnpcs/trait/LookClose.java +++ b/src/main/java/net/citizensnpcs/trait/LookClose.java @@ -80,6 +80,11 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable realisticLooking = key.getBoolean("realisticlooking", key.getBoolean("realistic-looking")); } + @Override + public void onDespawn() { + lookingAt = null; + } + @Override public void run() { if (!enabled || !npc.isSpawned() || npc.getNavigator().isNavigating()) @@ -90,11 +95,6 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable Util.faceEntity(npc.getBukkitEntity(), lookingAt); } - @Override - public void onDespawn() { - lookingAt = null; - } - @Override public void save(DataKey key) { if (key.keyExists("")) { diff --git a/src/main/java/net/citizensnpcs/util/Messages.java b/src/main/java/net/citizensnpcs/util/Messages.java index 5f0e9b1d2..822de6586 100644 --- a/src/main/java/net/citizensnpcs/util/Messages.java +++ b/src/main/java/net/citizensnpcs/util/Messages.java @@ -63,12 +63,16 @@ public class Messages { public static final String FAILED_LOAD_SAVES = "citizens.saves.load-failed"; public static final String FAILED_TO_MOUNT_NPC = "citizens.commands.npc.mount.failed"; public static final String FAILED_TO_REMOVE = "citizens.commands.trait.failed-to-remove"; + public static final String GAMEMODE_DESCRIBE = "citizens.commands.npc.gamemode.describe"; + public static final String GAMEMODE_INVALID = "citizens.commands.npc.gamemode.invalid"; + public static final String GAMEMODE_SET = "citizens.commands.npc.gamemode.set"; public static final String GRAVITY_DISABLED = "citizens.commands.npc.gravity.disabled"; public static final String GRAVITY_ENABLED = "citizens.commands.npc.gravity.enabled"; public static final String INVALID_AGE = "citizens.commands.npc.age.invalid-age"; public static final String INVALID_ANCHOR_NAME = "citizens.commands.npc.anchor.invalid-name"; public static final String INVALID_POSE_NAME = "citizens.commands.npc.pose.invalid-name"; public static final String INVALID_PROFESSION = "citizens.commands.npc.profession.invalid-profession"; + public static final String INVALID_SPAWN_LOCATION = "citizens.commands.npc.create.invalid-location"; public static final String LINEAR_WAYPOINT_EDITOR_ADDED_WAYPOINT = "citizens.editors.waypoints.linear.added-waypoint"; public static final String LINEAR_WAYPOINT_EDITOR_BEGIN = "citizens.editors.waypoints.linear.begin"; public static final String LINEAR_WAYPOINT_EDITOR_EDIT_SLOT_SET = "citizens.editors.waypoints.linear.edit-slot-set"; @@ -113,6 +117,7 @@ public class Messages { public static final String OVER_NPC_LIMIT = "citizens.limits.over-npc-limit"; public static final String OWNER_SET = "citizens.commands.npc.owner.set"; public static final String OWNER_SET_SERVER = "citizens.commands.npc.owner.set-server"; + public static final String PATHFINDING_RANGE_SET = "citizens.commands.npc.pathfindingrange.set"; public static final String POSE_ADDED = "citizens.commands.npc.pose.added"; public static final String POSE_ALREADY_EXISTS = "citizens.commands.npc.pose.already-exists"; public static final String POSE_MISSING = "citizens.commands.npc.pose.missing"; @@ -174,8 +179,4 @@ public class Messages { public static final String VULNERABLE_STOPPED = "citizens.commands.npc.vulnerable.stopped"; public static final String WAYPOINT_PROVIDER_SET = "citizens.waypoints.set-provider"; public static final String WRITING_DEFAULT_SETTING = "citizens.settings.writing-default"; - public static final String PATHFINDING_RANGE_SET = "citizens.commands.npc.pathfindingrange.set"; - public static final String GAMEMODE_DESCRIBE = "citizens.commands.npc.gamemode.describe"; - public static final String GAMEMODE_INVALID = "citizens.commands.npc.gamemode.invalid"; - public static final String GAMEMODE_SET = "citizens.commands.npc.gamemode.set"; } diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 02fa957f2..35ce15f30 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -10,6 +10,7 @@ citizens.commands.npc.age.cannot-be-aged=The mob type {0} cannot be aged. citizens.commands.npc.age.help=Can only be used on entities that can become babies. Use the [[-l]] flag to lock age over time (note: relogs may be required to see this). citizens.commands.npc.age.invalid-age=Invalid age. Valid ages are adult, baby, number between -24000 and 0 citizens.commands.npc.age.locked=Age locked. +citizens.commands.npc.create.invalid-location=Spawn location could not be parsed or was not found. citizens.commands.npc.gamemode.describe={0}'s gamemode is [[{1}]]. citizens.commands.npc.gamemode.invalid={0} is not a valid gamemode. citizens.commands.npc.gamemode.set=Gamemode set to [[{0}]].