2013-02-06 08:17:21 +01:00
|
|
|
package net.citizensnpcs.commands;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
2016-01-23 16:00:46 +01:00
|
|
|
import java.util.Arrays;
|
2013-02-06 08:17:21 +01:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Comparator;
|
|
|
|
import java.util.List;
|
2016-03-31 12:14:40 +02:00
|
|
|
import java.util.UUID;
|
2013-02-06 08:17:21 +01:00
|
|
|
|
2015-06-02 18:42:50 +02:00
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
import org.bukkit.Bukkit;
|
2016-03-20 12:32:24 +01:00
|
|
|
import org.bukkit.ChatColor;
|
2015-06-02 18:42:50 +02:00
|
|
|
import org.bukkit.DyeColor;
|
|
|
|
import org.bukkit.GameMode;
|
|
|
|
import org.bukkit.Location;
|
|
|
|
import org.bukkit.Material;
|
|
|
|
import org.bukkit.World;
|
|
|
|
import org.bukkit.command.BlockCommandSender;
|
|
|
|
import org.bukkit.command.CommandSender;
|
|
|
|
import org.bukkit.command.ConsoleCommandSender;
|
|
|
|
import org.bukkit.entity.Ageable;
|
|
|
|
import org.bukkit.entity.Entity;
|
|
|
|
import org.bukkit.entity.EntityType;
|
2015-06-09 18:09:17 +02:00
|
|
|
import org.bukkit.entity.Guardian;
|
2015-06-02 18:42:50 +02:00
|
|
|
import org.bukkit.entity.Horse.Color;
|
|
|
|
import org.bukkit.entity.Horse.Style;
|
|
|
|
import org.bukkit.entity.Horse.Variant;
|
|
|
|
import org.bukkit.entity.ItemFrame;
|
|
|
|
import org.bukkit.entity.LivingEntity;
|
|
|
|
import org.bukkit.entity.Ocelot;
|
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import org.bukkit.entity.Skeleton.SkeletonType;
|
|
|
|
import org.bukkit.entity.Villager.Profession;
|
|
|
|
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
2016-06-05 13:20:42 +02:00
|
|
|
import org.bukkit.potion.PotionEffect;
|
|
|
|
import org.bukkit.potion.PotionEffectType;
|
2015-06-02 18:42:50 +02:00
|
|
|
|
2016-01-23 16:00:46 +01:00
|
|
|
import com.google.common.base.Joiner;
|
2015-06-02 18:42:50 +02:00
|
|
|
import com.google.common.base.Splitter;
|
|
|
|
import com.google.common.collect.Iterables;
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.Citizens;
|
|
|
|
import net.citizensnpcs.Settings.Setting;
|
|
|
|
import net.citizensnpcs.api.CitizensAPI;
|
|
|
|
import net.citizensnpcs.api.ai.speech.SpeechContext;
|
|
|
|
import net.citizensnpcs.api.command.Command;
|
|
|
|
import net.citizensnpcs.api.command.CommandContext;
|
2013-07-27 11:58:40 +02:00
|
|
|
import net.citizensnpcs.api.command.CommandMessages;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.api.command.Requirements;
|
|
|
|
import net.citizensnpcs.api.command.exception.CommandException;
|
|
|
|
import net.citizensnpcs.api.command.exception.NoPermissionsException;
|
|
|
|
import net.citizensnpcs.api.command.exception.ServerCommandException;
|
2013-02-06 09:04:26 +01:00
|
|
|
import net.citizensnpcs.api.event.CommandSenderCreateNPCEvent;
|
2013-03-14 14:38:10 +01:00
|
|
|
import net.citizensnpcs.api.event.DespawnReason;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.api.event.PlayerCreateNPCEvent;
|
|
|
|
import net.citizensnpcs.api.npc.NPC;
|
|
|
|
import net.citizensnpcs.api.npc.NPCRegistry;
|
|
|
|
import net.citizensnpcs.api.trait.Trait;
|
2016-03-29 19:57:14 +02:00
|
|
|
import net.citizensnpcs.api.trait.trait.Inventory;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.api.trait.trait.MobType;
|
|
|
|
import net.citizensnpcs.api.trait.trait.Owner;
|
|
|
|
import net.citizensnpcs.api.trait.trait.Spawned;
|
|
|
|
import net.citizensnpcs.api.trait.trait.Speech;
|
|
|
|
import net.citizensnpcs.api.util.Colorizer;
|
|
|
|
import net.citizensnpcs.api.util.Messaging;
|
2013-07-31 07:38:32 +02:00
|
|
|
import net.citizensnpcs.api.util.Paginator;
|
2013-11-05 15:14:02 +01:00
|
|
|
import net.citizensnpcs.npc.EntityControllers;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.npc.NPCSelector;
|
|
|
|
import net.citizensnpcs.npc.Template;
|
2013-12-17 09:00:15 +01:00
|
|
|
import net.citizensnpcs.npc.entity.nonliving.FallingBlockController.FallingBlockNPC;
|
2014-04-11 08:02:22 +02:00
|
|
|
import net.citizensnpcs.npc.entity.nonliving.ItemController.ItemNPC;
|
|
|
|
import net.citizensnpcs.npc.entity.nonliving.ItemFrameController.ItemFrameNPC;
|
2015-11-16 14:36:00 +01:00
|
|
|
import net.citizensnpcs.npc.skin.SkinnableEntity;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.trait.Age;
|
|
|
|
import net.citizensnpcs.trait.Anchors;
|
2016-01-01 04:33:11 +01:00
|
|
|
import net.citizensnpcs.trait.ArmorStandTrait;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.trait.Controllable;
|
|
|
|
import net.citizensnpcs.trait.CurrentLocation;
|
|
|
|
import net.citizensnpcs.trait.Gravity;
|
2013-07-11 06:29:46 +02:00
|
|
|
import net.citizensnpcs.trait.HorseModifiers;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.trait.LookClose;
|
|
|
|
import net.citizensnpcs.trait.NPCSkeletonType;
|
2013-07-11 06:29:46 +02:00
|
|
|
import net.citizensnpcs.trait.OcelotModifiers;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.trait.Poses;
|
|
|
|
import net.citizensnpcs.trait.Powered;
|
2014-12-18 10:36:44 +01:00
|
|
|
import net.citizensnpcs.trait.RabbitType;
|
|
|
|
import net.citizensnpcs.trait.RabbitType.RabbitTypes;
|
2016-01-23 16:00:46 +01:00
|
|
|
import net.citizensnpcs.trait.ScriptTrait;
|
2015-01-04 12:59:33 +01:00
|
|
|
import net.citizensnpcs.trait.SheepTrait;
|
2015-09-17 06:06:49 +02:00
|
|
|
import net.citizensnpcs.trait.SkinLayers;
|
|
|
|
import net.citizensnpcs.trait.SkinLayers.Layer;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.trait.SlimeSize;
|
|
|
|
import net.citizensnpcs.trait.VillagerProfession;
|
2015-11-16 14:36:00 +01:00
|
|
|
import net.citizensnpcs.trait.WitherTrait;
|
2013-07-11 06:29:46 +02:00
|
|
|
import net.citizensnpcs.trait.WolfModifiers;
|
2013-02-06 08:17:21 +01:00
|
|
|
import net.citizensnpcs.trait.ZombieModifier;
|
|
|
|
import net.citizensnpcs.util.Anchor;
|
|
|
|
import net.citizensnpcs.util.Messages;
|
|
|
|
import net.citizensnpcs.util.NMS;
|
|
|
|
import net.citizensnpcs.util.StringHelper;
|
|
|
|
import net.citizensnpcs.util.Util;
|
|
|
|
|
|
|
|
@Requirements(selected = true, ownership = true)
|
|
|
|
public class NPCCommands {
|
|
|
|
private final NPCRegistry npcRegistry;
|
|
|
|
private final NPCSelector selector;
|
|
|
|
|
|
|
|
public NPCCommands(Citizens plugin) {
|
|
|
|
npcRegistry = CitizensAPI.getNPCRegistry();
|
|
|
|
selector = plugin.getNPCSelector();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "age [age] (-l)",
|
|
|
|
desc = "Set the age of a NPC",
|
|
|
|
help = Messages.COMMAND_AGE_HELP,
|
|
|
|
flags = "l",
|
|
|
|
modifiers = { "age" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.age")
|
|
|
|
public void age(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2013-11-05 12:29:18 +01:00
|
|
|
if (!npc.isSpawned() || !(npc.getEntity() instanceof Ageable))
|
2013-02-17 10:35:58 +01:00
|
|
|
throw new CommandException(Messages.MOBTYPE_CANNOT_BE_AGED);
|
2013-02-06 08:17:21 +01:00
|
|
|
Age trait = npc.getTrait(Age.class);
|
|
|
|
|
|
|
|
boolean toggleLock = args.hasFlag('l');
|
|
|
|
if (toggleLock) {
|
|
|
|
Messaging.sendTr(sender, trait.toggle() ? Messages.AGE_LOCKED : Messages.AGE_UNLOCKED);
|
|
|
|
}
|
|
|
|
if (args.argsLength() <= 1) {
|
|
|
|
if (!toggleLock)
|
|
|
|
trait.describe(sender);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int age = 0;
|
|
|
|
try {
|
|
|
|
age = args.getInteger(1);
|
2014-03-07 06:08:24 +01:00
|
|
|
if (age > 0) {
|
2013-02-06 08:17:21 +01:00
|
|
|
throw new CommandException(Messages.INVALID_AGE);
|
2013-07-09 12:07:37 +02:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, Messages.AGE_SET_NORMAL, npc.getName(), age);
|
|
|
|
} catch (NumberFormatException ex) {
|
|
|
|
if (args.getString(1).equalsIgnoreCase("baby")) {
|
|
|
|
age = -24000;
|
|
|
|
Messaging.sendTr(sender, Messages.AGE_SET_BABY, npc.getName());
|
|
|
|
} else if (args.getString(1).equalsIgnoreCase("adult")) {
|
|
|
|
age = 0;
|
|
|
|
Messaging.sendTr(sender, Messages.AGE_SET_ADULT, npc.getName());
|
|
|
|
} else
|
|
|
|
throw new CommandException(Messages.INVALID_AGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
trait.setAge(age);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "anchor (--save [name]|--assume [name]|--remove [name]) (-a)(-c)",
|
|
|
|
desc = "Changes/Saves/Lists NPC's location anchor(s)",
|
|
|
|
flags = "ac",
|
|
|
|
modifiers = { "anchor" },
|
|
|
|
min = 1,
|
|
|
|
max = 3,
|
|
|
|
permission = "citizens.npc.anchor")
|
|
|
|
public void anchor(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
Anchors trait = npc.getTrait(Anchors.class);
|
|
|
|
if (args.hasValueFlag("save")) {
|
|
|
|
if (args.getFlag("save").isEmpty())
|
|
|
|
throw new CommandException(Messages.INVALID_ANCHOR_NAME);
|
|
|
|
|
|
|
|
if (args.getSenderLocation() == null)
|
|
|
|
throw new ServerCommandException();
|
|
|
|
|
|
|
|
if (args.hasFlag('c')) {
|
2013-10-16 03:07:59 +02:00
|
|
|
if (trait.addAnchor(args.getFlag("save"), args.getSenderTargetBlockLocation())) {
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, Messages.ANCHOR_ADDED);
|
|
|
|
} else
|
|
|
|
throw new CommandException(Messages.ANCHOR_ALREADY_EXISTS, args.getFlag("save"));
|
|
|
|
} else {
|
|
|
|
if (trait.addAnchor(args.getFlag("save"), args.getSenderLocation())) {
|
|
|
|
Messaging.sendTr(sender, Messages.ANCHOR_ADDED);
|
|
|
|
} else
|
|
|
|
throw new CommandException(Messages.ANCHOR_ALREADY_EXISTS, args.getFlag("save"));
|
|
|
|
}
|
|
|
|
} else if (args.hasValueFlag("assume")) {
|
|
|
|
if (args.getFlag("assume").isEmpty())
|
|
|
|
throw new CommandException(Messages.INVALID_ANCHOR_NAME);
|
|
|
|
|
|
|
|
Anchor anchor = trait.getAnchor(args.getFlag("assume"));
|
|
|
|
if (anchor == null)
|
|
|
|
throw new CommandException(Messages.ANCHOR_MISSING, args.getFlag("assume"));
|
2013-08-02 09:04:06 +02:00
|
|
|
npc.teleport(anchor.getLocation(), TeleportCause.COMMAND);
|
2013-02-06 08:17:21 +01:00
|
|
|
} else if (args.hasValueFlag("remove")) {
|
|
|
|
if (args.getFlag("remove").isEmpty())
|
|
|
|
throw new CommandException(Messages.INVALID_ANCHOR_NAME);
|
|
|
|
if (trait.removeAnchor(trait.getAnchor(args.getFlag("remove"))))
|
|
|
|
Messaging.sendTr(sender, Messages.ANCHOR_REMOVED);
|
|
|
|
else
|
|
|
|
throw new CommandException(Messages.ANCHOR_MISSING, args.getFlag("remove"));
|
|
|
|
} else if (!args.hasFlag('a')) {
|
|
|
|
Paginator paginator = new Paginator().header("Anchors");
|
|
|
|
paginator.addLine("<e>Key: <a>ID <b>Name <c>World <d>Location (X,Y,Z)");
|
|
|
|
for (int i = 0; i < trait.getAnchors().size(); i++) {
|
2013-10-16 02:57:41 +02:00
|
|
|
if (trait.getAnchors().get(i).isLoaded()) {
|
|
|
|
String line = "<a>" + i + "<b> " + trait.getAnchors().get(i).getName() + "<c> "
|
|
|
|
+ trait.getAnchors().get(i).getLocation().getWorld().getName() + "<d> "
|
|
|
|
+ trait.getAnchors().get(i).getLocation().getBlockX() + ", "
|
|
|
|
+ trait.getAnchors().get(i).getLocation().getBlockY() + ", "
|
|
|
|
+ trait.getAnchors().get(i).getLocation().getBlockZ();
|
|
|
|
paginator.addLine(line);
|
|
|
|
} else {
|
|
|
|
String[] parts = trait.getAnchors().get(i).getUnloadedValue();
|
2013-11-04 16:42:32 +01:00
|
|
|
String line = "<a>" + i + "<b> " + trait.getAnchors().get(i).getName() + "<c> " + parts[0]
|
|
|
|
+ "<d> " + parts[1] + ", " + parts[2] + ", " + parts[3] + " <f>(unloaded)";
|
2013-10-16 02:57:41 +02:00
|
|
|
paginator.addLine(line);
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int page = args.getInteger(1, 1);
|
|
|
|
if (!paginator.sendPage(sender, page))
|
|
|
|
throw new CommandException(Messages.COMMAND_PAGE_MISSING);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assume Player's position
|
|
|
|
if (!args.hasFlag('a'))
|
|
|
|
return;
|
|
|
|
if (sender instanceof ConsoleCommandSender)
|
|
|
|
throw new ServerCommandException();
|
2013-08-02 09:04:06 +02:00
|
|
|
npc.teleport(args.getSenderLocation(), TeleportCause.COMMAND);
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
2016-01-01 04:33:11 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "armorstand --visible [visible] --small [small] --gravity [gravity] --arms [arms] --baseplate [baseplate]",
|
|
|
|
desc = "C whether the NPC can be ridden and controlled",
|
|
|
|
modifiers = { "armorstand", "control" },
|
|
|
|
min = 1,
|
|
|
|
max = 1)
|
|
|
|
@Requirements(selected = true, ownership = true, types = EntityType.ARMOR_STAND)
|
|
|
|
public void armorstand(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
ArmorStandTrait trait = npc.getTrait(ArmorStandTrait.class);
|
|
|
|
if (args.hasValueFlag("visible")) {
|
|
|
|
trait.setVisible(Boolean.valueOf(args.getFlag("visible")));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("small")) {
|
|
|
|
trait.setSmall(Boolean.valueOf(args.getFlag("small")));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("gravity")) {
|
|
|
|
trait.setGravity(Boolean.valueOf(args.getFlag("gravity")));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("arms")) {
|
|
|
|
trait.setHasArms(Boolean.valueOf(args.getFlag("arms")));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("baseplate")) {
|
|
|
|
trait.setHasBaseplate(Boolean.valueOf(args.getFlag("baseplate")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-20 10:33:41 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "collidable",
|
2016-03-20 10:38:52 +01:00
|
|
|
desc = "Toggles an NPC's collidability",
|
|
|
|
modifiers = { "collidable" },
|
2016-03-20 10:33:41 +01:00
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.collidable")
|
|
|
|
@Requirements(ownership = true, selected = true, types = { EntityType.PLAYER })
|
|
|
|
public void collidable(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
npc.data().setPersistent(NPC.COLLIDABLE_METADATA, !npc.data().get(NPC.COLLIDABLE_METADATA, true));
|
|
|
|
Messaging.sendTr(sender,
|
|
|
|
npc.data().get(NPC.COLLIDABLE_METADATA) ? Messages.COLLIDABLE_SET : Messages.COLLIDABLE_UNSET,
|
|
|
|
npc.getName());
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2014-11-20 08:39:37 +01:00
|
|
|
usage = "controllable|control (-m(ount),-y,-n,-o)",
|
2013-02-06 08:17:21 +01:00
|
|
|
desc = "Toggles whether the NPC can be ridden and controlled",
|
|
|
|
modifiers = { "controllable", "control" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
2014-11-20 08:39:37 +01:00
|
|
|
flags = "myno")
|
2013-02-06 08:17:21 +01:00
|
|
|
public void controllable(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2015-05-26 13:30:58 +02:00
|
|
|
if ((npc.isSpawned() && !sender.hasPermission(
|
|
|
|
"citizens.npc.controllable." + npc.getEntity().getType().name().toLowerCase().replace("_", "")))
|
2013-02-06 08:17:21 +01:00
|
|
|
|| !sender.hasPermission("citizens.npc.controllable"))
|
|
|
|
throw new NoPermissionsException();
|
2013-02-23 05:27:00 +01:00
|
|
|
if (!npc.hasTrait(Controllable.class)) {
|
2013-02-13 15:25:59 +01:00
|
|
|
npc.addTrait(new Controllable(false));
|
2013-02-23 05:27:00 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
Controllable trait = npc.getTrait(Controllable.class);
|
|
|
|
boolean enabled = trait.toggle();
|
2013-08-11 06:20:15 +02:00
|
|
|
if (args.hasFlag('y')) {
|
|
|
|
enabled = trait.setEnabled(true);
|
|
|
|
} else if (args.hasFlag('n')) {
|
|
|
|
enabled = trait.setEnabled(false);
|
|
|
|
}
|
2014-11-20 08:39:37 +01:00
|
|
|
trait.setOwnerRequired(args.hasFlag('o'));
|
2013-02-06 08:17:21 +01:00
|
|
|
String key = enabled ? Messages.CONTROLLABLE_SET : Messages.CONTROLLABLE_REMOVED;
|
|
|
|
Messaging.sendTr(sender, key, npc.getName());
|
2013-07-03 06:36:52 +02:00
|
|
|
if (enabled && args.hasFlag('m') && sender instanceof Player) {
|
|
|
|
trait.mount((Player) sender);
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "copy (--name newname)",
|
|
|
|
desc = "Copies an NPC",
|
|
|
|
modifiers = { "copy" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.copy")
|
2013-04-14 08:55:09 +02:00
|
|
|
public void copy(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2013-02-06 08:17:21 +01:00
|
|
|
String name = args.getFlag("name", npc.getFullName());
|
2013-07-06 06:02:17 +02:00
|
|
|
NPC copy = npc.clone();
|
|
|
|
if (!copy.getFullName().equals(name)) {
|
|
|
|
copy.setName(name);
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
|
2013-07-06 06:02:17 +02:00
|
|
|
if (copy.isSpawned() && args.getSenderLocation() != null) {
|
2013-02-06 08:17:21 +01:00
|
|
|
Location location = args.getSenderLocation();
|
|
|
|
location.getChunk().load();
|
2013-08-02 09:04:06 +02:00
|
|
|
copy.teleport(location, TeleportCause.COMMAND);
|
2013-02-06 08:17:21 +01:00
|
|
|
copy.getTrait(CurrentLocation.class).setLocation(location);
|
|
|
|
}
|
|
|
|
|
2013-04-14 08:55:09 +02:00
|
|
|
CommandSenderCreateNPCEvent event = sender instanceof Player ? new PlayerCreateNPCEvent((Player) sender, copy)
|
2015-05-26 13:30:58 +02:00
|
|
|
: new CommandSenderCreateNPCEvent(sender, copy);
|
2013-04-14 08:55:09 +02:00
|
|
|
Bukkit.getPluginManager().callEvent(event);
|
|
|
|
if (event.isCancelled()) {
|
|
|
|
event.getNPC().destroy();
|
|
|
|
String reason = "Couldn't create NPC.";
|
|
|
|
if (!event.getCancelReason().isEmpty())
|
|
|
|
reason += " Reason: " + event.getCancelReason();
|
|
|
|
throw new CommandException(reason);
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, Messages.NPC_COPIED, npc.getName());
|
|
|
|
selector.select(sender, copy);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
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 = "citizens.npc.create")
|
|
|
|
@Requirements
|
|
|
|
public void create(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2014-01-06 17:48:17 +01:00
|
|
|
String name = Colorizer.parseColors(args.getJoinedStrings(1).trim());
|
2013-02-06 08:17:21 +01:00
|
|
|
|
|
|
|
EntityType type = EntityType.PLAYER;
|
|
|
|
if (args.hasValueFlag("type")) {
|
2014-11-30 07:19:40 +01:00
|
|
|
String inputType = args.getFlag("type");
|
2013-02-06 08:17:21 +01:00
|
|
|
type = Util.matchEntityType(inputType);
|
|
|
|
if (type == null) {
|
2013-11-05 15:14:02 +01:00
|
|
|
throw new CommandException(Messaging.tr(Messages.NPC_CREATE_INVALID_MOBTYPE, inputType));
|
|
|
|
} else if (!EntityControllers.controllerExistsForType(type)) {
|
|
|
|
throw new CommandException(Messaging.tr(Messages.NPC_CREATE_MISSING_MOBTYPE, inputType));
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
}
|
2014-03-07 16:51:07 +01:00
|
|
|
|
2015-06-02 18:42:50 +02:00
|
|
|
int nameLength = type == EntityType.PLAYER ? 46 : 64;
|
2014-03-07 16:51:07 +01:00
|
|
|
if (name.length() > nameLength) {
|
|
|
|
Messaging.sendErrorTr(sender, Messages.NPC_NAME_TOO_LONG);
|
|
|
|
name = name.substring(0, nameLength);
|
|
|
|
}
|
|
|
|
if (name.length() == 0)
|
|
|
|
throw new CommandException();
|
|
|
|
|
2013-04-17 05:41:51 +02:00
|
|
|
if (!sender.hasPermission("citizens.npc.create.*") && !sender.hasPermission("citizens.npc.createall")
|
2013-03-15 11:39:18 +01:00
|
|
|
&& !sender.hasPermission("citizens.npc.create." + type.name().toLowerCase().replace("_", "")))
|
|
|
|
throw new NoPermissionsException();
|
2013-02-06 08:17:21 +01:00
|
|
|
|
|
|
|
npc = npcRegistry.createNPC(type, name);
|
|
|
|
String msg = "You created [[" + npc.getName() + "]]";
|
|
|
|
|
|
|
|
int age = 0;
|
|
|
|
if (args.hasFlag('b')) {
|
|
|
|
if (!Ageable.class.isAssignableFrom(type.getEntityClass()))
|
|
|
|
Messaging.sendErrorTr(sender, Messages.MOBTYPE_CANNOT_BE_AGED,
|
|
|
|
type.name().toLowerCase().replace("_", "-"));
|
|
|
|
else {
|
|
|
|
age = -24000;
|
|
|
|
msg += " as a baby";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize necessary traits
|
2014-03-09 06:04:27 +01:00
|
|
|
if (!Setting.SERVER_OWNS_NPCS.asBoolean()) {
|
|
|
|
npc.getTrait(Owner.class).setOwner(sender);
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
npc.getTrait(MobType.class).setType(type);
|
|
|
|
|
|
|
|
Location spawnLoc = null;
|
|
|
|
if (sender instanceof Player) {
|
|
|
|
spawnLoc = args.getSenderLocation();
|
|
|
|
} else if (sender instanceof BlockCommandSender) {
|
|
|
|
spawnLoc = args.getSenderLocation();
|
|
|
|
}
|
2013-02-06 09:04:26 +01:00
|
|
|
CommandSenderCreateNPCEvent event = sender instanceof Player ? new PlayerCreateNPCEvent((Player) sender, npc)
|
2015-05-26 13:30:58 +02:00
|
|
|
: new CommandSenderCreateNPCEvent(sender, npc);
|
2013-02-06 09:04:26 +01:00
|
|
|
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);
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
|
|
|
|
if (args.hasValueFlag("at")) {
|
2013-07-14 07:47:57 +02:00
|
|
|
spawnLoc = CommandContext.parseLocation(args.getSenderLocation(), args.getFlag("at"));
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
2013-07-14 07:47:57 +02:00
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
if (spawnLoc == null) {
|
|
|
|
npc.destroy();
|
|
|
|
throw new CommandException(Messages.INVALID_SPAWN_LOCATION);
|
|
|
|
}
|
|
|
|
|
2013-03-16 06:10:10 +01:00
|
|
|
if (!args.hasFlag('u')) {
|
2013-02-06 08:17:21 +01:00
|
|
|
npc.spawn(spawnLoc);
|
2013-03-16 06:10:10 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
|
|
|
|
if (args.hasValueFlag("trait")) {
|
|
|
|
Iterable<String> parts = Splitter.on(',').trimResults().split(args.getFlag("trait"));
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
|
|
for (String tr : parts) {
|
|
|
|
Trait trait = CitizensAPI.getTraitFactory().getTrait(tr);
|
|
|
|
if (trait == null)
|
|
|
|
continue;
|
|
|
|
npc.addTrait(trait);
|
|
|
|
builder.append(StringHelper.wrap(tr) + ", ");
|
|
|
|
}
|
|
|
|
if (builder.length() > 0)
|
|
|
|
builder.delete(builder.length() - 2, builder.length());
|
|
|
|
msg += " with traits " + builder.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args.hasValueFlag("template")) {
|
|
|
|
Iterable<String> parts = Splitter.on(',').trimResults().split(args.getFlag("template"));
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
|
|
for (String part : parts) {
|
|
|
|
Template template = Template.byName(part);
|
|
|
|
if (template == null)
|
|
|
|
continue;
|
|
|
|
template.apply(npc);
|
|
|
|
builder.append(StringHelper.wrap(part) + ", ");
|
|
|
|
}
|
|
|
|
if (builder.length() > 0)
|
|
|
|
builder.delete(builder.length() - 2, builder.length());
|
|
|
|
msg += " with templates " + builder.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set age after entity spawns
|
2013-11-05 12:29:18 +01:00
|
|
|
if (npc.getEntity() instanceof Ageable) {
|
2013-02-06 08:17:21 +01:00
|
|
|
npc.getTrait(Age.class).setAge(age);
|
2013-11-05 12:29:18 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
selector.select(sender, npc);
|
2013-04-14 08:55:09 +02:00
|
|
|
Messaging.send(sender, msg + '.');
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "despawn (id)",
|
|
|
|
desc = "Despawn a NPC",
|
|
|
|
modifiers = { "despawn" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.despawn")
|
|
|
|
@Requirements
|
2013-11-07 17:08:50 +01:00
|
|
|
public void despawn(final CommandContext args, final CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() {
|
|
|
|
@Override
|
|
|
|
public void run(NPC npc) throws CommandException {
|
|
|
|
if (npc == null) {
|
|
|
|
throw new CommandException(Messages.NO_NPC_WITH_ID_FOUND, args.getString(1));
|
|
|
|
}
|
|
|
|
npc.getTrait(Spawned.class).setSpawned(false);
|
|
|
|
npc.despawn(DespawnReason.REMOVAL);
|
|
|
|
Messaging.sendTr(sender, Messages.NPC_DESPAWNED, npc.getName());
|
|
|
|
}
|
|
|
|
};
|
2013-02-06 08:17:21 +01:00
|
|
|
if (npc == null || args.argsLength() == 2) {
|
2013-11-07 17:08:50 +01:00
|
|
|
if (args.argsLength() < 2) {
|
2013-02-06 08:17:21 +01:00
|
|
|
throw new CommandException(Messages.COMMAND_MUST_HAVE_SELECTED);
|
2013-11-07 17:08:50 +01:00
|
|
|
}
|
|
|
|
NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1));
|
|
|
|
} else {
|
|
|
|
callback.run(npc);
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-05 14:35:26 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "flyable (true|false)",
|
|
|
|
desc = "Toggles or sets an NPC's flyable status",
|
|
|
|
modifiers = { "flyable" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.flyable")
|
2015-05-26 13:30:58 +02:00
|
|
|
@Requirements(
|
|
|
|
selected = true,
|
|
|
|
ownership = true,
|
|
|
|
excludedTypes = { EntityType.BAT, EntityType.BLAZE, EntityType.ENDER_DRAGON, EntityType.GHAST,
|
|
|
|
EntityType.WITHER })
|
2013-11-05 14:35:26 +01:00
|
|
|
public void flyable(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
boolean flyable = args.argsLength() == 2 ? args.getString(1).equals("true") : !npc.isFlyable();
|
|
|
|
npc.setFlyable(flyable);
|
2014-04-03 17:01:27 +02:00
|
|
|
flyable = npc.isFlyable(); // may not have applied, eg bats always
|
|
|
|
// flyable
|
2013-11-05 14:35:26 +01:00
|
|
|
Messaging.sendTr(sender, flyable ? Messages.FLYABLE_SET : Messages.FLYABLE_UNSET);
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "gamemode [gamemode]",
|
|
|
|
desc = "Changes the gamemode",
|
2013-04-28 15:31:53 +02:00
|
|
|
modifiers = { "gamemode" },
|
2013-02-06 08:17:21 +01:00
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.gravity")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.PLAYER })
|
|
|
|
public void gamemode(CommandContext args, CommandSender sender, NPC npc) {
|
2013-11-05 12:29:18 +01:00
|
|
|
Player player = (Player) npc.getEntity();
|
2013-02-06 08:17:21 +01:00
|
|
|
if (args.argsLength() == 1) {
|
2015-05-26 13:30:58 +02:00
|
|
|
Messaging.sendTr(sender, Messages.GAMEMODE_DESCRIBE, npc.getName(),
|
|
|
|
player.getGameMode().name().toLowerCase());
|
2013-02-06 08:17:21 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
GameMode mode = null;
|
|
|
|
try {
|
|
|
|
int value = args.getInteger(1);
|
|
|
|
mode = GameMode.getByValue(value);
|
|
|
|
} catch (NumberFormatException ex) {
|
|
|
|
try {
|
|
|
|
mode = GameMode.valueOf(args.getString(1));
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mode == null) {
|
|
|
|
Messaging.sendErrorTr(sender, Messages.GAMEMODE_INVALID, args.getString(1));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
player.setGameMode(mode);
|
|
|
|
Messaging.sendTr(sender, Messages.GAMEMODE_SET, mode.name().toLowerCase());
|
|
|
|
}
|
|
|
|
|
2016-03-05 18:11:12 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2016-03-20 12:32:24 +01:00
|
|
|
usage = "glowing --color [minecraft chat color]",
|
2016-03-05 18:11:12 +01:00
|
|
|
desc = "Toggles an NPC's glowing status",
|
|
|
|
modifiers = { "glowing" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.glowing")
|
|
|
|
@Requirements(selected = true, ownership = true)
|
|
|
|
public void glowing(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2016-03-20 12:32:24 +01:00
|
|
|
if (args.hasValueFlag("color")) {
|
|
|
|
ChatColor chatColor = Util.matchEnum(ChatColor.values(), args.getFlag("color"));
|
2016-03-22 14:40:10 +01:00
|
|
|
if (!(npc.getEntity() instanceof Player))
|
2016-03-20 12:32:24 +01:00
|
|
|
throw new CommandException();
|
2016-03-22 14:40:10 +01:00
|
|
|
if (chatColor == null) {
|
|
|
|
npc.data().remove(NPC.GLOWING_COLOR_METADATA);
|
|
|
|
} else {
|
|
|
|
npc.data().setPersistent(NPC.GLOWING_COLOR_METADATA, chatColor.name());
|
|
|
|
}
|
|
|
|
Messaging.sendTr(sender, Messages.GLOWING_COLOR_SET, npc.getName(),
|
|
|
|
chatColor == null ? ChatColor.WHITE + "white" : chatColor + Util.prettyEnum(chatColor));
|
|
|
|
return;
|
2016-03-20 12:32:24 +01:00
|
|
|
}
|
2016-03-05 18:11:12 +01:00
|
|
|
npc.data().setPersistent(NPC.GLOWING_METADATA, !npc.data().get(NPC.GLOWING_METADATA, false));
|
|
|
|
boolean glowing = npc.data().get(NPC.GLOWING_METADATA);
|
2016-03-07 11:58:40 +01:00
|
|
|
Messaging.sendTr(sender, glowing ? Messages.GLOWING_SET : Messages.GLOWING_UNSET, npc.getName());
|
2016-03-05 18:11:12 +01:00
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "gravity",
|
|
|
|
desc = "Toggles gravity",
|
|
|
|
modifiers = { "gravity" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.gravity")
|
|
|
|
public void gravity(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
boolean enabled = npc.getTrait(Gravity.class).toggle();
|
2014-03-17 04:32:52 +01:00
|
|
|
String key = !enabled ? Messages.GRAVITY_ENABLED : Messages.GRAVITY_DISABLED;
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, key, npc.getName());
|
|
|
|
}
|
|
|
|
|
2015-06-09 18:09:17 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "guardian --elder [true|false]",
|
|
|
|
desc = "Changes guardian modifiers",
|
|
|
|
modifiers = { "guardian" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.guardian")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.GUARDIAN })
|
|
|
|
public void guardian(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
Guardian guardian = (Guardian) npc.getEntity();
|
|
|
|
if (args.hasValueFlag("elder")) {
|
|
|
|
guardian.setElder(args.getFlag("elder", "false").equals("true") ? true : false);
|
|
|
|
Messaging.sendTr(sender, guardian.isElder() ? Messages.ELDER_SET : Messages.ELDER_UNSET, npc.getName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-11 06:29:46 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "horse (--color color) (--type type) (--style style) (-cb)",
|
|
|
|
desc = "Sets horse modifiers",
|
|
|
|
help = "Use the -c flag to make the horse have a chest, or the -b flag to stop them from having a chest.",
|
|
|
|
modifiers = { "horse" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
flags = "cb",
|
|
|
|
permission = "citizens.npc.horse")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.HORSE })
|
|
|
|
public void horse(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
HorseModifiers horse = npc.getTrait(HorseModifiers.class);
|
|
|
|
String output = "";
|
|
|
|
if (args.hasFlag('c')) {
|
|
|
|
horse.setCarryingChest(true);
|
|
|
|
output += Messaging.tr(Messages.HORSE_CHEST_SET) + " ";
|
|
|
|
} else if (args.hasFlag('b')) {
|
|
|
|
horse.setCarryingChest(false);
|
|
|
|
output += Messaging.tr(Messages.HORSE_CHEST_UNSET) + " ";
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("color") || args.hasValueFlag("colour")) {
|
|
|
|
String colorRaw = args.getFlag("color", args.getFlag("colour"));
|
|
|
|
Color color = Util.matchEnum(Color.values(), colorRaw);
|
|
|
|
if (color == null) {
|
|
|
|
String valid = Util.listValuesPretty(Color.values());
|
|
|
|
throw new CommandException(Messages.INVALID_HORSE_COLOR, valid);
|
|
|
|
}
|
|
|
|
horse.setColor(color);
|
|
|
|
output += Messaging.tr(Messages.HORSE_COLOR_SET, Util.prettyEnum(color));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("type")) {
|
|
|
|
Variant variant = Util.matchEnum(Variant.values(), args.getFlag("type"));
|
|
|
|
if (variant == null) {
|
|
|
|
String valid = Util.listValuesPretty(Variant.values());
|
|
|
|
throw new CommandException(Messages.INVALID_HORSE_VARIANT, valid);
|
|
|
|
}
|
|
|
|
horse.setType(variant);
|
|
|
|
output += Messaging.tr(Messages.HORSE_TYPE_SET, Util.prettyEnum(variant));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("style")) {
|
|
|
|
Style style = Util.matchEnum(Style.values(), args.getFlag("style"));
|
|
|
|
if (style == null) {
|
|
|
|
String valid = Util.listValuesPretty(Style.values());
|
|
|
|
throw new CommandException(Messages.INVALID_HORSE_STYLE, valid);
|
|
|
|
}
|
|
|
|
horse.setStyle(style);
|
|
|
|
output += Messaging.tr(Messages.HORSE_STYLE_SET, Util.prettyEnum(style));
|
|
|
|
}
|
|
|
|
if (output.isEmpty()) {
|
|
|
|
Messaging.sendTr(sender, Messages.HORSE_DESCRIBE, Util.prettyEnum(horse.getColor()),
|
|
|
|
Util.prettyEnum(horse.getType()), Util.prettyEnum(horse.getStyle()));
|
|
|
|
} else {
|
|
|
|
sender.sendMessage(output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "id",
|
|
|
|
desc = "Sends the selected NPC's ID to the sender",
|
|
|
|
modifiers = { "id" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.id")
|
|
|
|
public void id(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
Messaging.send(sender, npc.getId());
|
|
|
|
}
|
|
|
|
|
2016-03-29 19:57:14 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "inventory",
|
2016-03-29 19:57:52 +02:00
|
|
|
desc = "Show's an NPC's inventory",
|
|
|
|
modifiers = { "inventory" },
|
2016-03-29 19:57:14 +02:00
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.inventory")
|
|
|
|
public void inventory(CommandContext args, CommandSender sender, NPC npc) {
|
2016-04-01 05:49:32 +02:00
|
|
|
npc.getTrait(Inventory.class).openInventory((Player) sender);
|
2016-03-29 19:57:14 +02:00
|
|
|
}
|
|
|
|
|
2013-12-17 09:00:15 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2014-01-09 10:13:27 +01:00
|
|
|
usage = "item [item] (data)",
|
2013-12-17 09:00:15 +01:00
|
|
|
desc = "Sets the NPC's item",
|
|
|
|
modifiers = { "item", },
|
2013-12-19 08:27:26 +01:00
|
|
|
min = 2,
|
2014-01-09 10:13:27 +01:00
|
|
|
max = 3,
|
2013-12-17 09:00:15 +01:00
|
|
|
flags = "",
|
|
|
|
permission = "citizens.npc.item")
|
2015-05-26 13:30:58 +02:00
|
|
|
@Requirements(
|
|
|
|
selected = true,
|
|
|
|
ownership = true,
|
|
|
|
types = { EntityType.DROPPED_ITEM, EntityType.ITEM_FRAME, EntityType.FALLING_BLOCK })
|
2013-12-17 09:00:15 +01:00
|
|
|
public void item(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2013-12-19 08:27:26 +01:00
|
|
|
Material mat = Material.matchMaterial(args.getString(1));
|
2013-12-17 09:00:15 +01:00
|
|
|
if (mat == null)
|
|
|
|
throw new CommandException(Messages.UNKNOWN_MATERIAL);
|
2014-04-11 08:02:22 +02:00
|
|
|
int data = args.getInteger(2, 0);
|
2013-12-17 09:00:15 +01:00
|
|
|
switch (npc.getEntity().getType()) {
|
|
|
|
case DROPPED_ITEM:
|
|
|
|
((org.bukkit.entity.Item) npc.getEntity()).getItemStack().setType(mat);
|
2014-04-11 08:02:22 +02:00
|
|
|
((ItemNPC) npc.getEntity()).setType(mat, data);
|
2013-12-17 09:00:15 +01:00
|
|
|
break;
|
|
|
|
case ITEM_FRAME:
|
|
|
|
((ItemFrame) npc.getEntity()).getItem().setType(mat);
|
2014-04-11 08:02:22 +02:00
|
|
|
((ItemFrameNPC) npc.getEntity()).setType(mat, data);
|
2013-12-17 09:00:15 +01:00
|
|
|
break;
|
|
|
|
case FALLING_BLOCK:
|
2014-04-11 08:02:22 +02:00
|
|
|
((FallingBlockNPC) npc.getEntity()).setType(mat, data);
|
2013-12-17 09:00:15 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Messaging.sendTr(sender, Messages.ITEM_SET, Util.prettyEnum(mat));
|
|
|
|
}
|
|
|
|
|
2013-07-09 16:01:00 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "leashable",
|
|
|
|
desc = "Toggles leashability",
|
|
|
|
modifiers = { "leashable" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
flags = "t",
|
|
|
|
permission = "citizens.npc.leashable")
|
|
|
|
public void leashable(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
boolean vulnerable = !npc.data().get(NPC.LEASH_PROTECTED_METADATA, true);
|
|
|
|
if (args.hasFlag('t')) {
|
|
|
|
npc.data().set(NPC.LEASH_PROTECTED_METADATA, vulnerable);
|
|
|
|
} else {
|
|
|
|
npc.data().setPersistent(NPC.LEASH_PROTECTED_METADATA, vulnerable);
|
|
|
|
}
|
|
|
|
String key = vulnerable ? Messages.LEASHABLE_STOPPED : Messages.LEASHABLE_SET;
|
|
|
|
Messaging.sendTr(sender, key, npc.getName());
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2014-03-04 12:45:52 +01:00
|
|
|
usage = "list (page) ((-a) --owner (owner) --type (type) --char (char) --registry (name))",
|
2013-02-06 08:17:21 +01:00
|
|
|
desc = "List NPCs",
|
|
|
|
flags = "a",
|
|
|
|
modifiers = { "list" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.list")
|
|
|
|
@Requirements
|
|
|
|
public void list(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2014-03-04 12:45:52 +01:00
|
|
|
NPCRegistry source = args.hasValueFlag("registry") ? CitizensAPI.getNamedNPCRegistry(args.getFlag("registry"))
|
|
|
|
: npcRegistry;
|
|
|
|
if (source == null)
|
|
|
|
throw new CommandException();
|
2013-02-06 08:17:21 +01:00
|
|
|
List<NPC> npcs = new ArrayList<NPC>();
|
|
|
|
|
|
|
|
if (args.hasFlag('a')) {
|
2014-03-04 12:45:52 +01:00
|
|
|
for (NPC add : source.sorted()) {
|
2013-02-06 08:17:21 +01:00
|
|
|
npcs.add(add);
|
2013-11-06 08:10:11 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
} else if (args.getValueFlags().size() == 0 && sender instanceof Player) {
|
2014-03-04 12:45:52 +01:00
|
|
|
for (NPC add : source.sorted()) {
|
2013-11-18 08:18:18 +01:00
|
|
|
if (!npcs.contains(add) && add.getTrait(Owner.class).isOwnedBy(sender)) {
|
2013-02-06 08:17:21 +01:00
|
|
|
npcs.add(add);
|
2013-11-18 08:18:18 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (args.hasValueFlag("owner")) {
|
|
|
|
String name = args.getFlag("owner");
|
2014-03-04 12:45:52 +01:00
|
|
|
for (NPC add : source.sorted()) {
|
2013-11-18 08:18:18 +01:00
|
|
|
if (!npcs.contains(add) && add.getTrait(Owner.class).isOwnedBy(name)) {
|
2013-02-06 08:17:21 +01:00
|
|
|
npcs.add(add);
|
2013-11-18 08:18:18 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args.hasValueFlag("type")) {
|
|
|
|
EntityType type = Util.matchEntityType(args.getFlag("type"));
|
|
|
|
|
|
|
|
if (type == null)
|
|
|
|
throw new CommandException(Messages.COMMAND_INVALID_MOBTYPE, type);
|
|
|
|
|
2014-03-04 12:45:52 +01:00
|
|
|
for (NPC add : source) {
|
2013-02-06 08:17:21 +01:00
|
|
|
if (!npcs.contains(add) && add.getTrait(MobType.class).getType() == type)
|
|
|
|
npcs.add(add);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Paginator paginator = new Paginator().header("NPCs");
|
|
|
|
paginator.addLine("<e>Key: <a>ID <b>Name");
|
|
|
|
for (int i = 0; i < npcs.size(); i += 2) {
|
|
|
|
String line = "<a>" + npcs.get(i).getId() + "<b> " + npcs.get(i).getName();
|
|
|
|
if (npcs.size() >= i + 2)
|
|
|
|
line += " " + "<a>" + npcs.get(i + 1).getId() + "<b> " + npcs.get(i + 1).getName();
|
|
|
|
paginator.addLine(line);
|
|
|
|
}
|
|
|
|
|
|
|
|
int page = args.getInteger(1, 1);
|
|
|
|
if (!paginator.sendPage(sender, page))
|
|
|
|
throw new CommandException(Messages.COMMAND_PAGE_MISSING);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "lookclose",
|
|
|
|
desc = "Toggle whether a NPC will look when a player is near",
|
|
|
|
modifiers = { "lookclose", "look", "rotate" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.lookclose")
|
|
|
|
public void lookClose(CommandContext args, CommandSender sender, NPC npc) {
|
2015-05-26 13:30:58 +02:00
|
|
|
Messaging.sendTr(sender,
|
|
|
|
npc.getTrait(LookClose.class).toggle() ? Messages.LOOKCLOSE_SET : Messages.LOOKCLOSE_STOPPED,
|
|
|
|
npc.getName());
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
2014-02-01 05:50:20 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "minecart (--item item_name(:data)) (--offset offset)",
|
|
|
|
desc = "Sets minecart item",
|
|
|
|
modifiers = { "minecart" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
flags = "",
|
|
|
|
permission = "citizens.npc.minecart")
|
2015-05-26 13:30:58 +02:00
|
|
|
@Requirements(
|
|
|
|
selected = true,
|
|
|
|
ownership = true,
|
|
|
|
types = { EntityType.MINECART, EntityType.MINECART_CHEST, EntityType.MINECART_COMMAND,
|
|
|
|
EntityType.MINECART_FURNACE, EntityType.MINECART_HOPPER, EntityType.MINECART_MOB_SPAWNER,
|
|
|
|
EntityType.MINECART_TNT })
|
2014-02-01 05:50:20 +01:00
|
|
|
public void minecart(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
if (args.hasValueFlag("item")) {
|
|
|
|
String raw = args.getFlag("item");
|
|
|
|
int data = 0;
|
|
|
|
if (raw.contains(":")) {
|
|
|
|
int dataIndex = raw.indexOf(':');
|
|
|
|
data = Integer.parseInt(raw.substring(dataIndex + 1));
|
|
|
|
raw = raw.substring(0, dataIndex);
|
|
|
|
}
|
|
|
|
Material material = Material.matchMaterial(raw);
|
|
|
|
if (material == null)
|
|
|
|
throw new CommandException();
|
|
|
|
npc.data().setPersistent(NPC.MINECART_ITEM_METADATA, material.name());
|
|
|
|
npc.data().setPersistent(NPC.MINECART_ITEM_DATA_METADATA, data);
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("offset")) {
|
|
|
|
npc.data().setPersistent(NPC.MINECART_OFFSET_METADATA, args.getFlagInteger("offset"));
|
|
|
|
}
|
|
|
|
|
|
|
|
Messaging.sendTr(sender, Messages.MINECART_SET, npc.data().get(NPC.MINECART_ITEM_METADATA, ""),
|
|
|
|
npc.data().get(NPC.MINECART_ITEM_DATA_METADATA, 0), npc.data().get(NPC.MINECART_OFFSET_METADATA, 0));
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2016-03-31 12:14:40 +02:00
|
|
|
usage = "mount (--onnpc <npc id>)",
|
2013-02-06 08:17:21 +01:00
|
|
|
desc = "Mounts a controllable NPC",
|
|
|
|
modifiers = { "mount" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.controllable")
|
2016-03-31 12:14:40 +02:00
|
|
|
public void mount(CommandContext args, Player player, NPC npc) throws CommandException {
|
|
|
|
if (args.hasValueFlag("onnpc")) {
|
|
|
|
NPC mount;
|
|
|
|
try {
|
|
|
|
UUID uuid = UUID.fromString(args.getFlag("onnpc"));
|
|
|
|
mount = CitizensAPI.getNPCRegistry().getByUniqueId(uuid);
|
|
|
|
} catch (IllegalArgumentException ex) {
|
|
|
|
mount = CitizensAPI.getNPCRegistry().getById(args.getFlagInteger("onnpc"));
|
|
|
|
}
|
|
|
|
if (mount == null || !mount.isSpawned()) {
|
|
|
|
throw new CommandException(Messaging.tr(Messages.MOUNT_NPC_MUST_BE_SPAWNED, args.getFlag("onnpc")));
|
|
|
|
}
|
2016-04-01 05:49:32 +02:00
|
|
|
if (mount.equals(npc)) {
|
|
|
|
throw new CommandException();
|
|
|
|
}
|
2016-03-31 12:14:40 +02:00
|
|
|
NMS.mount(mount.getEntity(), npc.getEntity());
|
|
|
|
return;
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
boolean enabled = npc.hasTrait(Controllable.class) && npc.getTrait(Controllable.class).isEnabled();
|
|
|
|
if (!enabled) {
|
|
|
|
Messaging.sendTr(player, Messages.NPC_NOT_CONTROLLABLE, npc.getName());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
boolean success = npc.getTrait(Controllable.class).mount(player);
|
2016-03-12 05:29:11 +01:00
|
|
|
if (!success) {
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(player, Messages.FAILED_TO_MOUNT_NPC, npc.getName());
|
2016-03-12 05:29:11 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "moveto x:y:z:world | x y z world",
|
|
|
|
desc = "Teleports a NPC to a given location",
|
|
|
|
modifiers = "moveto",
|
|
|
|
min = 1,
|
|
|
|
permission = "citizens.npc.moveto")
|
|
|
|
public void moveto(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
// Spawn the NPC if it isn't spawned to prevent NPEs
|
2013-11-05 12:29:18 +01:00
|
|
|
if (!npc.isSpawned()) {
|
2013-02-06 08:17:21 +01:00
|
|
|
npc.spawn(npc.getTrait(CurrentLocation.class).getLocation());
|
2013-11-05 12:29:18 +01:00
|
|
|
}
|
|
|
|
if (!npc.isSpawned()) {
|
2013-08-10 12:03:20 +02:00
|
|
|
throw new CommandException("NPC could not be spawned.");
|
|
|
|
}
|
2013-11-05 12:29:18 +01:00
|
|
|
Location current = npc.getEntity().getLocation();
|
2013-02-06 08:17:21 +01:00
|
|
|
Location to;
|
|
|
|
if (args.argsLength() > 1) {
|
|
|
|
String[] parts = Iterables.toArray(Splitter.on(':').split(args.getJoinedStrings(1, ':')), String.class);
|
|
|
|
if (parts.length != 4 && parts.length != 3)
|
|
|
|
throw new CommandException(Messages.MOVETO_FORMAT);
|
|
|
|
double x = Double.parseDouble(parts[0]);
|
|
|
|
double y = Double.parseDouble(parts[1]);
|
|
|
|
double z = Double.parseDouble(parts[2]);
|
|
|
|
World world = parts.length == 4 ? Bukkit.getWorld(parts[3]) : current.getWorld();
|
|
|
|
if (world == null)
|
|
|
|
throw new CommandException(Messages.WORLD_NOT_FOUND);
|
|
|
|
to = new Location(world, x, y, z, current.getYaw(), current.getPitch());
|
|
|
|
} else {
|
|
|
|
to = current.clone();
|
|
|
|
if (args.hasValueFlag("x"))
|
|
|
|
to.setX(args.getFlagDouble("x"));
|
|
|
|
if (args.hasValueFlag("y"))
|
|
|
|
to.setY(args.getFlagDouble("y"));
|
|
|
|
if (args.hasValueFlag("z"))
|
|
|
|
to.setZ(args.getFlagDouble("z"));
|
|
|
|
if (args.hasValueFlag("yaw"))
|
|
|
|
to.setYaw((float) args.getFlagDouble("yaw"));
|
|
|
|
if (args.hasValueFlag("pitch"))
|
|
|
|
to.setPitch((float) args.getFlagDouble("pitch"));
|
|
|
|
if (args.hasValueFlag("world")) {
|
|
|
|
World world = Bukkit.getWorld(args.getFlag("world"));
|
|
|
|
if (world == null)
|
|
|
|
throw new CommandException(Messages.WORLD_NOT_FOUND);
|
|
|
|
to.setWorld(world);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-02 09:04:06 +02:00
|
|
|
npc.teleport(to, TeleportCause.COMMAND);
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, Messages.MOVETO_TELEPORTED, npc.getName(), to);
|
|
|
|
}
|
|
|
|
|
2013-03-16 08:06:04 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2013-03-16 08:17:42 +01:00
|
|
|
modifiers = { "name" },
|
|
|
|
usage = "name",
|
2013-03-16 08:06:04 +01:00
|
|
|
desc = "Toggle nameplate visibility",
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
2013-03-16 08:17:42 +01:00
|
|
|
permission = "citizens.npc.name")
|
2013-11-05 12:29:18 +01:00
|
|
|
@Requirements(selected = true, ownership = true, livingEntity = true)
|
2013-03-16 08:17:42 +01:00
|
|
|
public void name(CommandContext args, CommandSender sender, NPC npc) {
|
2013-11-05 12:29:18 +01:00
|
|
|
LivingEntity entity = (LivingEntity) npc.getEntity();
|
|
|
|
entity.setCustomNameVisible(!entity.isCustomNameVisible());
|
2014-02-01 15:48:48 +01:00
|
|
|
npc.data().setPersistent(NPC.NAMEPLATE_VISIBLE_METADATA, entity.isCustomNameVisible());
|
2013-03-16 08:06:04 +01:00
|
|
|
Messaging.sendTr(sender, Messages.NAMEPLATE_VISIBILITY_TOGGLED);
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(aliases = { "npc" }, desc = "Show basic NPC information", max = 0, permission = "citizens.npc.info")
|
|
|
|
public void npc(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
Messaging.send(sender, StringHelper.wrapHeader(npc.getName()));
|
|
|
|
Messaging.send(sender, " <a>ID: <e>" + npc.getId());
|
|
|
|
Messaging.send(sender, " <a>Type: <e>" + npc.getTrait(MobType.class).getType());
|
|
|
|
if (npc.isSpawned()) {
|
2013-11-05 12:29:18 +01:00
|
|
|
Location loc = npc.getEntity().getLocation();
|
2013-02-06 08:17:21 +01:00
|
|
|
String format = " <a>Spawned at <e>%d, %d, %d <a>in world<e> %s";
|
|
|
|
Messaging.send(sender,
|
|
|
|
String.format(format, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), loc.getWorld().getName()));
|
|
|
|
}
|
2016-06-05 13:20:42 +02:00
|
|
|
((LivingEntity) npc.getEntity()).addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1, 10));
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.send(sender, " <a>Traits<e>");
|
|
|
|
for (Trait trait : npc.getTraits()) {
|
|
|
|
if (CitizensAPI.getTraitFactory().isInternalTrait(trait))
|
|
|
|
continue;
|
|
|
|
String message = " <e>- <a>" + trait.getName();
|
|
|
|
Messaging.send(sender, message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-11 06:29:46 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "ocelot (--type type) (-s(itting), -n(ot sitting))",
|
|
|
|
desc = "Set the ocelot type of an NPC and whether it is sitting",
|
|
|
|
modifiers = { "ocelot" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
flags = "sn",
|
|
|
|
permission = "citizens.npc.ocelot")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.OCELOT })
|
|
|
|
public void ocelot(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
OcelotModifiers trait = npc.getTrait(OcelotModifiers.class);
|
|
|
|
if (args.hasFlag('s')) {
|
|
|
|
trait.setSitting(true);
|
|
|
|
} else if (args.hasFlag('n')) {
|
|
|
|
trait.setSitting(false);
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("type")) {
|
|
|
|
Ocelot.Type type = Util.matchEnum(Ocelot.Type.values(), args.getFlag("type"));
|
|
|
|
if (type == null) {
|
|
|
|
String valid = Util.listValuesPretty(Ocelot.Type.values());
|
|
|
|
throw new CommandException(Messages.INVALID_OCELOT_TYPE, valid);
|
|
|
|
}
|
|
|
|
trait.setType(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "owner [name]",
|
|
|
|
desc = "Set the owner of an NPC",
|
|
|
|
modifiers = { "owner" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.owner")
|
|
|
|
public void owner(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
Owner ownerTrait = npc.getTrait(Owner.class);
|
|
|
|
if (args.argsLength() == 1) {
|
|
|
|
Messaging.sendTr(sender, Messages.NPC_OWNER, npc.getName(), ownerTrait.getOwner());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
String name = args.getString(1);
|
|
|
|
if (ownerTrait.isOwnedBy(name))
|
|
|
|
throw new CommandException(Messages.ALREADY_OWNER, name, npc.getName());
|
|
|
|
ownerTrait.setOwner(name);
|
|
|
|
boolean serverOwner = name.equalsIgnoreCase(Owner.SERVER);
|
|
|
|
Messaging.sendTr(sender, serverOwner ? Messages.OWNER_SET_SERVER : Messages.OWNER_SET, npc.getName(), name);
|
|
|
|
}
|
|
|
|
|
2013-11-16 08:08:00 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "passive (--set [true|false])",
|
|
|
|
desc = "Sets whether an NPC damages other entities or not",
|
|
|
|
modifiers = { "passive" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.passive")
|
|
|
|
public void passive(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2015-05-26 13:30:58 +02:00
|
|
|
boolean passive = args.hasValueFlag("set") ? Boolean.parseBoolean(args.getFlag("set"))
|
|
|
|
: npc.data().get(NPC.DAMAGE_OTHERS_METADATA, true);
|
2013-11-16 08:08:00 +01:00
|
|
|
npc.data().setPersistent(NPC.DAMAGE_OTHERS_METADATA, !passive);
|
|
|
|
Messaging.sendTr(sender, passive ? Messages.PASSIVE_SET : Messages.PASSIVE_UNSET, npc.getName());
|
|
|
|
}
|
|
|
|
|
2013-11-04 16:42:32 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2016-01-02 17:33:08 +01:00
|
|
|
usage = "pathopt --avoid-water|aw [true|false] --stationary-ticks [ticks] --attack-range [range] --distance-margin [margin]",
|
2013-11-04 16:42:32 +01:00
|
|
|
desc = "Sets an NPC's pathfinding options",
|
|
|
|
modifiers = { "pathopt", "po", "patho" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.pathfindingoptions")
|
2014-09-12 15:40:11 +02:00
|
|
|
public void pathfindingOptions(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2016-01-02 17:33:08 +01:00
|
|
|
boolean found = false;
|
2013-11-04 16:42:32 +01:00
|
|
|
if (args.hasValueFlag("avoid-water") || args.hasValueFlag("aw")) {
|
|
|
|
String raw = args.getFlag("avoid-water", args.getFlag("aw"));
|
|
|
|
boolean avoid = Boolean.parseBoolean(raw);
|
|
|
|
npc.getNavigator().getDefaultParameters().avoidWater(avoid);
|
|
|
|
Messaging.sendTr(sender, avoid ? Messages.PATHFINDING_OPTIONS_AVOID_WATER_SET
|
|
|
|
: Messages.PATHFINDING_OPTIONS_AVOID_WATER_UNSET, npc.getName());
|
2016-01-02 17:33:08 +01:00
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("stationary-ticks")) {
|
|
|
|
int ticks = Integer.parseInt(args.getFlag("stationary-ticks"));
|
|
|
|
if (ticks < 0)
|
|
|
|
throw new CommandException();
|
|
|
|
npc.getNavigator().getDefaultParameters().stationaryTicks(ticks);
|
|
|
|
Messaging.sendTr(sender, Messages.PATHFINDING_OPTIONS_STATIONARY_TICKS_SET, npc.getName(), ticks);
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("distance-margin")) {
|
|
|
|
double distance = Double.parseDouble(args.getFlag("distance-margin"));
|
|
|
|
if (distance < 0)
|
|
|
|
throw new CommandException();
|
2016-01-15 08:19:25 +01:00
|
|
|
npc.getNavigator().getDefaultParameters().distanceMargin(Math.pow(distance, 2));
|
2016-01-02 17:33:08 +01:00
|
|
|
Messaging.sendTr(sender, Messages.PATHFINDING_OPTIONS_DISTANCE_MARGIN_SET, npc.getName(), distance);
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("attack-range")) {
|
|
|
|
double range = Double.parseDouble(args.getFlag("attack-range"));
|
|
|
|
if (range < 0)
|
|
|
|
throw new CommandException();
|
|
|
|
npc.getNavigator().getDefaultParameters().attackRange(range);
|
|
|
|
Messaging.sendTr(sender, Messages.PATHFINDING_OPTIONS_ATTACK_RANGE_SET, npc.getName(), range);
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
if (!found) {
|
2014-09-12 15:40:11 +02:00
|
|
|
throw new CommandException();
|
2013-11-04 16:42:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 13:30:58 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "pathrange [range]",
|
|
|
|
desc = "Sets an NPC's pathfinding range",
|
|
|
|
modifiers = { "pathrange", "pathfindingrange", "prange" },
|
|
|
|
min = 2,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.pathfindingrange")
|
2013-02-06 08:17:21 +01:00
|
|
|
public void pathfindingRange(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
double range = Math.max(1, args.getDouble(1));
|
|
|
|
npc.getNavigator().getDefaultParameters().range((float) range);
|
|
|
|
Messaging.sendTr(sender, Messages.PATHFINDING_RANGE_SET, range);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "playerlist (-a,r)",
|
|
|
|
desc = "Sets whether the NPC is put in the playerlist",
|
|
|
|
modifiers = { "playerlist" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
flags = "ar",
|
|
|
|
permission = "citizens.npc.playerlist")
|
2013-06-08 12:43:19 +02:00
|
|
|
@Requirements(selected = true, ownership = true, types = EntityType.PLAYER)
|
2013-02-06 08:17:21 +01:00
|
|
|
public void playerlist(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
boolean remove = !npc.data().get("removefromplayerlist", Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean());
|
2013-08-07 17:39:26 +02:00
|
|
|
if (args.hasFlag('a')) {
|
2013-02-06 08:17:21 +01:00
|
|
|
remove = false;
|
2015-08-21 03:32:33 +02:00
|
|
|
} else if (args.hasFlag('r')) {
|
2013-02-06 08:17:21 +01:00
|
|
|
remove = true;
|
2015-08-21 03:32:33 +02:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
npc.data().setPersistent("removefromplayerlist", remove);
|
2013-11-05 12:29:18 +01:00
|
|
|
if (npc.isSpawned()) {
|
2015-08-21 03:32:33 +02:00
|
|
|
npc.despawn(DespawnReason.PENDING_RESPAWN);
|
|
|
|
npc.spawn(npc.getTrait(CurrentLocation.class).getLocation());
|
2015-09-11 14:18:31 +02:00
|
|
|
NMS.addOrRemoveFromPlayerList(npc.getEntity(), remove);
|
2013-11-05 12:29:18 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, remove ? Messages.REMOVED_FROM_PLAYERLIST : Messages.ADDED_TO_PLAYERLIST,
|
|
|
|
npc.getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "pose (--save [name]|--assume [name]|--remove [name]) (-a)",
|
|
|
|
desc = "Changes/Saves/Lists NPC's head pose(s)",
|
|
|
|
flags = "a",
|
|
|
|
modifiers = { "pose" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.pose")
|
|
|
|
public void pose(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
Poses trait = npc.getTrait(Poses.class);
|
|
|
|
if (args.hasValueFlag("save")) {
|
|
|
|
if (args.getFlag("save").isEmpty())
|
|
|
|
throw new CommandException(Messages.INVALID_POSE_NAME);
|
|
|
|
|
|
|
|
if (args.getSenderLocation() == null)
|
|
|
|
throw new ServerCommandException();
|
|
|
|
|
|
|
|
if (trait.addPose(args.getFlag("save"), args.getSenderLocation())) {
|
|
|
|
Messaging.sendTr(sender, Messages.POSE_ADDED);
|
|
|
|
} else
|
2013-02-18 01:42:43 +01:00
|
|
|
throw new CommandException(Messages.POSE_ALREADY_EXISTS, args.getFlag("save"));
|
2013-02-06 08:17:21 +01:00
|
|
|
} else if (args.hasValueFlag("assume")) {
|
|
|
|
String pose = args.getFlag("assume");
|
|
|
|
if (pose.isEmpty())
|
|
|
|
throw new CommandException(Messages.INVALID_POSE_NAME);
|
|
|
|
|
|
|
|
if (!trait.hasPose(pose))
|
|
|
|
throw new CommandException(Messages.POSE_MISSING, pose);
|
|
|
|
trait.assumePose(pose);
|
|
|
|
} else if (args.hasValueFlag("remove")) {
|
|
|
|
if (args.getFlag("remove").isEmpty())
|
|
|
|
throw new CommandException(Messages.INVALID_POSE_NAME);
|
|
|
|
if (trait.removePose(args.getFlag("remove"))) {
|
|
|
|
Messaging.sendTr(sender, Messages.POSE_REMOVED);
|
|
|
|
} else
|
|
|
|
throw new CommandException(Messages.POSE_MISSING, args.getFlag("remove"));
|
|
|
|
} else if (!args.hasFlag('a')) {
|
|
|
|
trait.describe(sender, args.getInteger(1, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assume Player's pose
|
|
|
|
if (!args.hasFlag('a'))
|
|
|
|
return;
|
|
|
|
if (args.getSenderLocation() == null)
|
|
|
|
throw new ServerCommandException();
|
|
|
|
Location location = args.getSenderLocation();
|
|
|
|
trait.assumePose(location);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "power",
|
|
|
|
desc = "Toggle a creeper NPC as powered",
|
|
|
|
modifiers = { "power" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.power")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.CREEPER })
|
|
|
|
public void power(CommandContext args, CommandSender sender, NPC npc) {
|
2015-05-26 13:30:58 +02:00
|
|
|
Messaging.sendTr(sender,
|
|
|
|
npc.getTrait(Powered.class).toggle() ? Messages.POWERED_SET : Messages.POWERED_STOPPED);
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "profession|prof [profession]",
|
|
|
|
desc = "Set a NPC's profession",
|
|
|
|
modifiers = { "profession", "prof" },
|
|
|
|
min = 2,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.profession")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.VILLAGER })
|
|
|
|
public void profession(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
String profession = args.getString(1);
|
2013-07-12 14:32:10 +02:00
|
|
|
Profession parsed = Util.matchEnum(Profession.values(), profession.toUpperCase());
|
|
|
|
if (parsed == null) {
|
2015-05-26 13:30:58 +02:00
|
|
|
throw new CommandException(Messages.INVALID_PROFESSION, args.getString(1),
|
|
|
|
StringUtils.join(Profession.values(), ","));
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
npc.getTrait(VillagerProfession.class).setProfession(parsed);
|
|
|
|
Messaging.sendTr(sender, Messages.PROFESSION_SET, npc.getName(), profession);
|
|
|
|
}
|
|
|
|
|
2015-05-26 13:30:58 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "rabbittype [type]",
|
|
|
|
desc = "Set the Type of a Rabbit NPC",
|
|
|
|
modifiers = { "rabbittype", "rbtype" },
|
|
|
|
min = 2,
|
|
|
|
permission = "citizens.npc.rabbittype")
|
2015-01-04 12:59:33 +01:00
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.RABBIT })
|
|
|
|
public void rabbitType(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
RabbitTypes type;
|
|
|
|
try {
|
|
|
|
type = RabbitTypes.valueOf(args.getString(1).toUpperCase());
|
|
|
|
} catch (IllegalArgumentException ex) {
|
|
|
|
throw new CommandException(Messages.INVALID_RABBIT_TYPE, StringUtils.join(RabbitTypes.values(), ","));
|
|
|
|
}
|
|
|
|
npc.getTrait(RabbitType.class).setType(type);
|
|
|
|
Messaging.sendTr(sender, Messages.RABBIT_TYPE_SET, npc.getName(), type.name());
|
|
|
|
}
|
|
|
|
|
2015-05-26 13:30:58 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "remove|rem (all|id|name)",
|
|
|
|
desc = "Remove a NPC",
|
|
|
|
modifiers = { "remove", "rem" },
|
|
|
|
min = 1,
|
|
|
|
max = 2)
|
2013-02-06 08:17:21 +01:00
|
|
|
@Requirements
|
2014-06-16 17:44:58 +02:00
|
|
|
public void remove(final CommandContext args, final CommandSender sender, NPC npc) throws CommandException {
|
2013-02-06 08:17:21 +01:00
|
|
|
if (args.argsLength() == 2) {
|
2014-06-16 17:44:58 +02:00
|
|
|
if (args.getString(1).equalsIgnoreCase("all")) {
|
|
|
|
if (!sender.hasPermission("citizens.admin.remove.all") && !sender.hasPermission("citizens.admin"))
|
|
|
|
throw new NoPermissionsException();
|
|
|
|
npcRegistry.deregisterAll();
|
|
|
|
Messaging.sendTr(sender, Messages.REMOVED_ALL_NPCS);
|
|
|
|
return;
|
|
|
|
} else {
|
2014-06-30 04:40:32 +02:00
|
|
|
NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() {
|
2014-06-16 17:44:58 +02:00
|
|
|
@Override
|
|
|
|
public void run(NPC npc) throws CommandException {
|
|
|
|
if (npc == null)
|
|
|
|
throw new CommandException(Messages.COMMAND_MUST_HAVE_SELECTED);
|
|
|
|
if (!(sender instanceof ConsoleCommandSender) && !npc.getTrait(Owner.class).isOwnedBy(sender))
|
|
|
|
throw new CommandException(Messages.COMMAND_MUST_BE_OWNER);
|
|
|
|
if (!sender.hasPermission("citizens.npc.remove") && !sender.hasPermission("citizens.admin"))
|
|
|
|
throw new NoPermissionsException();
|
|
|
|
npc.destroy();
|
|
|
|
Messaging.sendTr(sender, Messages.NPC_REMOVED, npc.getName());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1));
|
|
|
|
return;
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
if (npc == null)
|
|
|
|
throw new CommandException(Messages.COMMAND_MUST_HAVE_SELECTED);
|
2013-08-07 17:39:26 +02:00
|
|
|
if (!(sender instanceof ConsoleCommandSender) && !npc.getTrait(Owner.class).isOwnedBy(sender))
|
2013-02-06 08:17:21 +01:00
|
|
|
throw new CommandException(Messages.COMMAND_MUST_BE_OWNER);
|
2013-08-03 14:57:56 +02:00
|
|
|
if (!sender.hasPermission("citizens.npc.remove") && !sender.hasPermission("citizens.admin"))
|
2013-02-06 08:17:21 +01:00
|
|
|
throw new NoPermissionsException();
|
|
|
|
npc.destroy();
|
2013-08-03 14:57:56 +02:00
|
|
|
Messaging.sendTr(sender, Messages.NPC_REMOVED, npc.getName());
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "rename [name]",
|
|
|
|
desc = "Rename a NPC",
|
|
|
|
modifiers = { "rename" },
|
|
|
|
min = 2,
|
|
|
|
permission = "citizens.npc.rename")
|
|
|
|
public void rename(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
String oldName = npc.getName();
|
2014-03-04 12:51:14 +01:00
|
|
|
String newName = Colorizer.parseColors(args.getJoinedStrings(1));
|
2015-07-30 04:51:45 +02:00
|
|
|
int nameLength = npc.getTrait(MobType.class).getType() == EntityType.PLAYER ? 46 : 64;
|
2014-03-07 16:13:36 +01:00
|
|
|
if (newName.length() > nameLength) {
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendErrorTr(sender, Messages.NPC_NAME_TOO_LONG);
|
2014-03-07 16:13:36 +01:00
|
|
|
newName = newName.substring(0, nameLength);
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
2013-11-05 12:29:18 +01:00
|
|
|
Location prev = npc.isSpawned() ? npc.getEntity().getLocation() : null;
|
2013-03-14 14:38:10 +01:00
|
|
|
npc.despawn(DespawnReason.PENDING_RESPAWN);
|
2014-03-04 12:49:32 +01:00
|
|
|
npc.setName(newName);
|
2014-03-04 12:51:14 +01:00
|
|
|
if (prev != null) {
|
2013-02-06 08:17:21 +01:00
|
|
|
npc.spawn(prev);
|
2014-03-04 12:51:14 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
|
|
|
|
Messaging.sendTr(sender, Messages.NPC_RENAMED, oldName, newName);
|
|
|
|
}
|
|
|
|
|
2013-07-14 11:28:35 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "respawn [delay in ticks]",
|
|
|
|
desc = "Sets an NPC's respawn delay in ticks",
|
|
|
|
modifiers = { "respawn" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.respawn")
|
|
|
|
public void respawn(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
if (args.argsLength() > 1) {
|
|
|
|
int delay = args.getInteger(1);
|
|
|
|
npc.data().setPersistent(NPC.RESPAWN_DELAY_METADATA, delay);
|
|
|
|
Messaging.sendTr(sender, Messages.RESPAWN_DELAY_SET, delay);
|
|
|
|
} else {
|
|
|
|
Messaging.sendTr(sender, Messages.RESPAWN_DELAY_DESCRIBE, npc.data().get(NPC.RESPAWN_DELAY_METADATA, -1));
|
|
|
|
}
|
2014-06-27 23:16:30 +02:00
|
|
|
}
|
2013-07-14 11:28:35 +02:00
|
|
|
|
2016-01-23 16:00:46 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "script --add [files] --remove [files]",
|
|
|
|
desc = "Controls an NPC's scripts",
|
|
|
|
modifiers = { "script" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.script")
|
|
|
|
public void script(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
ScriptTrait trait = npc.getTrait(ScriptTrait.class);
|
|
|
|
if (args.hasValueFlag("add")) {
|
|
|
|
List<String> files = new ArrayList<String>();
|
|
|
|
for (String file : args.getFlag("add").split(",")) {
|
|
|
|
if (!trait.validateFile(file)) {
|
|
|
|
Messaging.sendErrorTr(sender, Messages.INVALID_SCRIPT_FILE, file);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
files.add(file);
|
|
|
|
}
|
|
|
|
trait.addScripts(files);
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("remove")) {
|
|
|
|
trait.removeScripts(Arrays.asList(args.getFlag("remove").split(",")));
|
|
|
|
}
|
|
|
|
Messaging.sendTr(sender, Messages.CURRENT_SCRIPTS, npc.getName(), Joiner.on("]],[[ ").join(trait.getScripts()));
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "select|sel [id|name] (--r range)",
|
|
|
|
desc = "Select a NPC with the given ID or name",
|
|
|
|
modifiers = { "select", "sel" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.select")
|
|
|
|
@Requirements
|
2013-11-07 17:08:50 +01:00
|
|
|
public void select(CommandContext args, final CommandSender sender, final NPC npc) throws CommandException {
|
|
|
|
NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() {
|
|
|
|
@Override
|
|
|
|
public void run(NPC toSelect) throws CommandException {
|
2016-01-01 03:55:01 +01:00
|
|
|
if (toSelect == null)
|
2013-11-07 17:08:50 +01:00
|
|
|
throw new CommandException(Messages.NPC_NOT_FOUND);
|
|
|
|
if (npc != null && toSelect.getId() == npc.getId())
|
|
|
|
throw new CommandException(Messages.NPC_ALREADY_SELECTED);
|
|
|
|
selector.select(sender, toSelect);
|
|
|
|
Messaging.sendWithNPC(sender, Setting.SELECTION_MESSAGE.asString(), toSelect);
|
|
|
|
}
|
|
|
|
};
|
2013-02-06 08:17:21 +01:00
|
|
|
if (args.argsLength() <= 1) {
|
|
|
|
if (!(sender instanceof Player))
|
|
|
|
throw new ServerCommandException();
|
|
|
|
double range = Math.abs(args.getFlagDouble("r", 10));
|
|
|
|
Entity player = (Player) sender;
|
|
|
|
final Location location = args.getSenderLocation();
|
|
|
|
List<Entity> search = player.getNearbyEntities(range, range, range);
|
|
|
|
Collections.sort(search, new Comparator<Entity>() {
|
|
|
|
@Override
|
|
|
|
public int compare(Entity o1, Entity o2) {
|
|
|
|
double d = o1.getLocation().distanceSquared(location) - o2.getLocation().distanceSquared(location);
|
|
|
|
return d > 0 ? 1 : d < 0 ? -1 : 0;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
for (Entity possibleNPC : search) {
|
|
|
|
NPC test = npcRegistry.getNPC(possibleNPC);
|
|
|
|
if (test == null)
|
|
|
|
continue;
|
2013-11-07 17:08:50 +01:00
|
|
|
callback.run(test);
|
2013-02-06 08:17:21 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2013-11-07 17:08:50 +01:00
|
|
|
NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1));
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-04 12:59:33 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "sheep (--color [color]) (--sheared [sheared])",
|
|
|
|
desc = "Sets sheep modifiers",
|
|
|
|
modifiers = { "sheep" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.sheep")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.SHEEP })
|
2015-03-24 04:08:37 +01:00
|
|
|
public void sheep(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2015-01-04 12:59:33 +01:00
|
|
|
SheepTrait trait = npc.getTrait(SheepTrait.class);
|
2015-03-24 04:08:37 +01:00
|
|
|
boolean hasArg = false;
|
2015-01-04 12:59:33 +01:00
|
|
|
if (args.hasValueFlag("sheared")) {
|
|
|
|
trait.setSheared(Boolean.valueOf(args.getFlag("sheared")));
|
2015-03-24 04:08:37 +01:00
|
|
|
hasArg = true;
|
2015-01-04 12:59:33 +01:00
|
|
|
}
|
|
|
|
if (args.hasValueFlag("color")) {
|
|
|
|
DyeColor color = Util.matchEnum(DyeColor.values(), args.getFlag("color"));
|
|
|
|
if (color != null) {
|
|
|
|
trait.setColor(color);
|
2015-03-22 09:30:30 +01:00
|
|
|
Messaging.sendTr(sender, Messages.SHEEP_COLOR_SET, color.toString().toLowerCase());
|
|
|
|
} else {
|
|
|
|
Messaging.sendErrorTr(sender, Messages.INVALID_SHEEP_COLOR, Util.listValuesPretty(DyeColor.values()));
|
2015-01-04 12:59:33 +01:00
|
|
|
}
|
2015-03-24 04:08:37 +01:00
|
|
|
hasArg = true;
|
|
|
|
}
|
|
|
|
if (!hasArg) {
|
|
|
|
throw new CommandException();
|
2015-01-04 12:59:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 13:30:58 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "skeletontype [type]",
|
|
|
|
desc = "Sets the NPC's skeleton type",
|
|
|
|
modifiers = { "skeletontype", "sktype" },
|
|
|
|
min = 2,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.skeletontype")
|
2013-02-06 08:17:21 +01:00
|
|
|
@Requirements(selected = true, ownership = true, types = EntityType.SKELETON)
|
|
|
|
public void skeletonType(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2015-01-04 12:59:33 +01:00
|
|
|
SkeletonType type;
|
|
|
|
try {
|
|
|
|
type = SkeletonType.valueOf(args.getString(1).toUpperCase());
|
|
|
|
} catch (IllegalArgumentException ex) {
|
|
|
|
throw new CommandException(Messages.INVALID_SKELETON_TYPE, StringUtils.join(SkeletonType.values(), ","));
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
npc.getTrait(NPCSkeletonType.class).setType(type);
|
|
|
|
Messaging.sendTr(sender, Messages.SKELETON_TYPE_SET, npc.getName(), type);
|
|
|
|
}
|
|
|
|
|
2014-04-18 10:38:44 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2015-02-02 23:24:28 +01:00
|
|
|
usage = "skin (-c -p) [name]",
|
2015-02-02 23:16:13 +01:00
|
|
|
desc = "Sets an NPC's skin name, Use -p to save a skin snapshot that won't change",
|
2014-04-18 10:38:44 +02:00
|
|
|
modifiers = { "skin" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
2015-02-02 22:52:52 +01:00
|
|
|
flags = "cp",
|
2014-04-18 10:38:44 +02:00
|
|
|
permission = "citizens.npc.skin")
|
2014-12-09 13:31:14 +01:00
|
|
|
@Requirements(types = EntityType.PLAYER, selected = true, ownership = true)
|
2014-04-18 10:38:44 +02:00
|
|
|
public void skin(final CommandContext args, final CommandSender sender, final NPC npc) throws CommandException {
|
|
|
|
String skinName = npc.getName();
|
|
|
|
if (args.hasFlag('c')) {
|
|
|
|
npc.data().remove(NPC.PLAYER_SKIN_UUID_METADATA);
|
|
|
|
} else {
|
|
|
|
if (args.argsLength() != 2)
|
|
|
|
throw new CommandException();
|
|
|
|
npc.data().setPersistent(NPC.PLAYER_SKIN_UUID_METADATA, args.getString(1));
|
2015-02-02 22:52:52 +01:00
|
|
|
if (args.hasFlag('p')) {
|
2015-08-29 16:20:09 +02:00
|
|
|
npc.data().setPersistent(NPC.PLAYER_SKIN_USE_LATEST, false);
|
2015-02-02 22:52:52 +01:00
|
|
|
}
|
2014-04-18 10:38:44 +02:00
|
|
|
skinName = args.getString(1);
|
|
|
|
}
|
|
|
|
Messaging.sendTr(sender, Messages.SKIN_SET, npc.getName(), skinName);
|
|
|
|
if (npc.isSpawned()) {
|
2015-08-21 03:32:33 +02:00
|
|
|
|
2015-08-26 04:33:09 +02:00
|
|
|
SkinnableEntity skinnable = NMS.getSkinnable(npc.getEntity());
|
2015-08-21 03:32:33 +02:00
|
|
|
if (skinnable != null) {
|
2016-05-20 10:41:02 +02:00
|
|
|
skinnable.setSkinName(skinName, args.hasFlag('p'));
|
2015-08-21 03:32:33 +02:00
|
|
|
}
|
2014-04-18 10:38:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 06:06:49 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "skinlayers (--cape [true|false]) (--hat [true|false]) (--jacket [true|false]) (--sleeves [true|false]) (--pants [true|false])",
|
|
|
|
desc = "Sets an NPC's skin layers visibility.",
|
|
|
|
modifiers = { "skinlayers" },
|
|
|
|
min = 1,
|
|
|
|
max = 5,
|
|
|
|
permission = "citizens.npc.skinlayers")
|
|
|
|
@Requirements(types = EntityType.PLAYER, selected = true, ownership = true)
|
2015-11-16 14:36:00 +01:00
|
|
|
public void skinLayers(final CommandContext args, final CommandSender sender, final NPC npc)
|
|
|
|
throws CommandException {
|
2015-09-17 06:06:49 +02:00
|
|
|
SkinLayers trait = npc.getTrait(SkinLayers.class);
|
|
|
|
if (args.hasValueFlag("cape")) {
|
|
|
|
trait.setVisible(Layer.CAPE, Boolean.valueOf(args.getFlag("cape")));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("hat")) {
|
|
|
|
trait.setVisible(Layer.HAT, Boolean.valueOf(args.getFlag("hat")));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("jacket")) {
|
|
|
|
trait.setVisible(Layer.JACKET, Boolean.valueOf(args.getFlag("jacket")));
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("sleeves")) {
|
|
|
|
boolean hasSleeves = Boolean.valueOf(args.getFlag("sleeves"));
|
|
|
|
trait.setVisible(Layer.LEFT_SLEEVE, hasSleeves);
|
|
|
|
trait.setVisible(Layer.RIGHT_SLEEVE, hasSleeves);
|
|
|
|
}
|
|
|
|
if (args.hasValueFlag("pants")) {
|
|
|
|
boolean hasPants = Boolean.valueOf(args.getFlag("pants"));
|
|
|
|
trait.setVisible(Layer.LEFT_PANTS, hasPants);
|
|
|
|
trait.setVisible(Layer.RIGHT_PANTS, hasPants);
|
|
|
|
}
|
2015-11-16 14:36:00 +01:00
|
|
|
Messaging.sendTr(sender, Messages.SKIN_LAYERS_SET, npc.getName(), trait.isVisible(Layer.CAPE),
|
|
|
|
trait.isVisible(Layer.HAT), trait.isVisible(Layer.JACKET),
|
2015-09-17 06:06:49 +02:00
|
|
|
trait.isVisible(Layer.LEFT_SLEEVE) || trait.isVisible(Layer.RIGHT_SLEEVE),
|
|
|
|
trait.isVisible(Layer.LEFT_PANTS) || trait.isVisible(Layer.RIGHT_PANTS));
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "size [size]",
|
|
|
|
desc = "Sets the NPC's size",
|
|
|
|
modifiers = { "size" },
|
|
|
|
min = 1,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.size")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.MAGMA_CUBE, EntityType.SLIME })
|
|
|
|
public void slimeSize(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
SlimeSize trait = npc.getTrait(SlimeSize.class);
|
|
|
|
if (args.argsLength() <= 1) {
|
|
|
|
trait.describe(sender);
|
|
|
|
return;
|
|
|
|
}
|
2014-06-27 21:09:25 +02:00
|
|
|
int size = Math.max(-2, args.getInteger(1));
|
2013-02-06 08:17:21 +01:00
|
|
|
trait.setSize(size);
|
|
|
|
Messaging.sendTr(sender, Messages.SIZE_SET, npc.getName(), size);
|
|
|
|
}
|
|
|
|
|
2014-01-29 14:37:27 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "sound (--death [death sound|d]) (--ambient [ambient sound|d]) (--hurt [hurt sound|d]) (-n(one)) (-d(efault))",
|
|
|
|
desc = "Sets an NPC's played sounds",
|
|
|
|
modifiers = { "sound" },
|
|
|
|
flags = "dn",
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.sound")
|
|
|
|
@Requirements(selected = true, ownership = true, livingEntity = true, excludedTypes = { EntityType.PLAYER })
|
|
|
|
public void sound(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
String ambientSound = npc.data().get(NPC.AMBIENT_SOUND_METADATA);
|
|
|
|
String deathSound = npc.data().get(NPC.DEATH_SOUND_METADATA);
|
|
|
|
String hurtSound = npc.data().get(NPC.HURT_SOUND_METADATA);
|
2014-01-29 15:32:42 +01:00
|
|
|
if (args.getValueFlags().size() == 0 && args.getFlags().size() == 0) {
|
2016-03-03 12:05:22 +01:00
|
|
|
Messaging.sendTr(sender, Messages.SOUND_INFO, npc.getName(), ambientSound, hurtSound, deathSound);
|
2014-01-29 15:32:42 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-29 14:37:27 +01:00
|
|
|
if (args.hasFlag('n')) {
|
|
|
|
ambientSound = deathSound = hurtSound = "";
|
|
|
|
}
|
|
|
|
if (args.hasFlag('d')) {
|
|
|
|
ambientSound = deathSound = hurtSound = null;
|
|
|
|
} else {
|
|
|
|
if (args.hasValueFlag("death")) {
|
2014-01-29 15:21:43 +01:00
|
|
|
deathSound = args.getFlag("death").equals("d") ? null : NMS.getSound(args.getFlag("death"));
|
2014-01-29 14:37:27 +01:00
|
|
|
}
|
|
|
|
if (args.hasValueFlag("ambient")) {
|
2014-01-29 15:21:43 +01:00
|
|
|
ambientSound = args.getFlag("ambient").equals("d") ? null : NMS.getSound(args.getFlag("ambient"));
|
2014-01-29 14:37:27 +01:00
|
|
|
}
|
|
|
|
if (args.hasValueFlag("hurt")) {
|
2014-01-29 15:21:43 +01:00
|
|
|
hurtSound = args.getFlag("hurt").equals("d") ? null : NMS.getSound(args.getFlag("hurt"));
|
2014-01-29 14:37:27 +01:00
|
|
|
}
|
|
|
|
}
|
2014-05-22 03:11:44 +02:00
|
|
|
if (deathSound == null) {
|
|
|
|
npc.data().remove(NPC.DEATH_SOUND_METADATA);
|
|
|
|
} else {
|
|
|
|
npc.data().setPersistent(NPC.DEATH_SOUND_METADATA, deathSound);
|
|
|
|
}
|
|
|
|
if (hurtSound == null) {
|
|
|
|
npc.data().remove(NPC.HURT_SOUND_METADATA);
|
|
|
|
} else {
|
|
|
|
npc.data().setPersistent(NPC.HURT_SOUND_METADATA, hurtSound);
|
|
|
|
}
|
|
|
|
if (ambientSound == null) {
|
|
|
|
npc.data().remove(ambientSound);
|
|
|
|
} else {
|
|
|
|
npc.data().setPersistent(NPC.AMBIENT_SOUND_METADATA, ambientSound);
|
|
|
|
}
|
2014-01-29 15:32:42 +01:00
|
|
|
|
2016-03-03 12:05:22 +01:00
|
|
|
if (ambientSound != null && ambientSound.isEmpty())
|
2016-01-02 17:53:11 +01:00
|
|
|
ambientSound = "none";
|
2016-03-03 12:05:22 +01:00
|
|
|
if (hurtSound != null && hurtSound.isEmpty())
|
2016-01-02 17:53:11 +01:00
|
|
|
hurtSound = "none";
|
2016-03-03 12:05:22 +01:00
|
|
|
if (deathSound != null && deathSound.isEmpty())
|
2016-01-02 17:53:11 +01:00
|
|
|
deathSound = "none";
|
2014-01-29 15:32:42 +01:00
|
|
|
Messaging.sendTr(sender, Messages.SOUND_SET, npc.getName(), ambientSound, hurtSound, deathSound);
|
2014-01-29 14:37:27 +01:00
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2013-11-07 17:08:50 +01:00
|
|
|
usage = "spawn (id|name)",
|
2013-02-06 08:17:21 +01:00
|
|
|
desc = "Spawn an existing NPC",
|
|
|
|
modifiers = { "spawn" },
|
2013-05-15 06:00:27 +02:00
|
|
|
min = 1,
|
2013-02-06 08:17:21 +01:00
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.spawn")
|
|
|
|
@Requirements(ownership = true)
|
2013-11-07 17:08:50 +01:00
|
|
|
public void spawn(final CommandContext args, final CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() {
|
|
|
|
@Override
|
|
|
|
public void run(NPC respawn) throws CommandException {
|
|
|
|
if (respawn == null) {
|
|
|
|
if (args.argsLength() > 1) {
|
|
|
|
throw new CommandException(Messages.NO_NPC_WITH_ID_FOUND, args.getString(1));
|
|
|
|
} else {
|
|
|
|
throw new CommandException(CommandMessages.MUST_HAVE_SELECTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (respawn.isSpawned()) {
|
|
|
|
throw new CommandException(Messages.NPC_ALREADY_SPAWNED, respawn.getName());
|
|
|
|
}
|
|
|
|
Location location = respawn.getTrait(CurrentLocation.class).getLocation();
|
|
|
|
if (location == null || args.hasValueFlag("location")) {
|
|
|
|
if (args.getSenderLocation() == null)
|
|
|
|
throw new CommandException(Messages.NO_STORED_SPAWN_LOCATION);
|
2013-02-06 08:17:21 +01:00
|
|
|
|
2013-11-07 17:08:50 +01:00
|
|
|
location = args.getSenderLocation();
|
|
|
|
}
|
|
|
|
if (respawn.spawn(location)) {
|
|
|
|
selector.select(sender, respawn);
|
|
|
|
Messaging.sendTr(sender, Messages.NPC_SPAWNED, respawn.getName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if (args.argsLength() > 1) {
|
|
|
|
NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1));
|
|
|
|
} else {
|
|
|
|
callback.run(npc);
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "speak message to speak --target npcid|player_name --type vocal_type",
|
|
|
|
desc = "Uses the NPCs SpeechController to talk",
|
|
|
|
modifiers = { "speak" },
|
|
|
|
min = 2,
|
|
|
|
permission = "citizens.npc.speak")
|
|
|
|
public void speak(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
String type = npc.getTrait(Speech.class).getDefaultVocalChord();
|
|
|
|
String message = Colorizer.parseColors(args.getJoinedStrings(1));
|
|
|
|
|
|
|
|
if (message.length() <= 0) {
|
|
|
|
Messaging.send(sender, "Default Vocal Chord for " + npc.getName() + ": "
|
|
|
|
+ npc.getTrait(Speech.class).getDefaultVocalChord());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SpeechContext context = new SpeechContext(message);
|
|
|
|
|
|
|
|
if (args.hasValueFlag("target")) {
|
|
|
|
if (args.getFlag("target").matches("\\d+")) {
|
|
|
|
NPC target = CitizensAPI.getNPCRegistry().getById(Integer.valueOf(args.getFlag("target")));
|
|
|
|
if (target != null)
|
2013-11-05 12:29:18 +01:00
|
|
|
context.addRecipient(target.getEntity());
|
2013-02-06 08:17:21 +01:00
|
|
|
} else {
|
|
|
|
Player player = Bukkit.getPlayer(args.getFlag("target"));
|
2014-04-12 16:59:56 +02:00
|
|
|
if (player != null) {
|
2013-11-07 16:47:18 +01:00
|
|
|
context.addRecipient((Entity) player);
|
2014-04-12 16:59:56 +02:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args.hasValueFlag("type")) {
|
|
|
|
if (CitizensAPI.getSpeechFactory().isRegistered(args.getFlag("type")))
|
|
|
|
type = args.getFlag("type");
|
|
|
|
}
|
|
|
|
|
|
|
|
npc.getDefaultSpeechController().speak(context, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "speed [speed]",
|
|
|
|
desc = "Sets the movement speed of an NPC as a percentage",
|
|
|
|
modifiers = { "speed" },
|
|
|
|
min = 2,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.speed")
|
|
|
|
public void speed(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
float newSpeed = (float) Math.abs(args.getDouble(1));
|
|
|
|
if (newSpeed >= Setting.MAX_SPEED.asDouble())
|
|
|
|
throw new CommandException(Messages.SPEED_MODIFIER_ABOVE_LIMIT);
|
|
|
|
npc.getNavigator().getDefaultParameters().speedModifier(newSpeed);
|
|
|
|
|
|
|
|
Messaging.sendTr(sender, Messages.SPEED_MODIFIER_SET, newSpeed);
|
|
|
|
}
|
|
|
|
|
2013-11-15 05:06:18 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "swim (--set [true|false])",
|
|
|
|
desc = "Sets an NPC to swim or not",
|
|
|
|
modifiers = { "swim" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.swim")
|
|
|
|
public void swim(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2015-05-26 13:30:58 +02:00
|
|
|
boolean swim = args.hasValueFlag("set") ? Boolean.parseBoolean(args.getFlag("set"))
|
|
|
|
: !npc.data().get(NPC.SWIMMING_METADATA, true);
|
2013-11-15 05:06:18 +01:00
|
|
|
npc.data().setPersistent(NPC.SWIMMING_METADATA, swim);
|
|
|
|
Messaging.sendTr(sender, swim ? Messages.SWIMMING_SET : Messages.SWIMMING_UNSET, npc.getName());
|
|
|
|
}
|
|
|
|
|
2013-07-18 12:48:57 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "targetable",
|
|
|
|
desc = "Toggles an NPC's targetability",
|
|
|
|
modifiers = { "targetable" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.targetable")
|
|
|
|
public void targetable(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
boolean targetable = !npc.data().get(NPC.TARGETABLE_METADATA,
|
|
|
|
npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true));
|
|
|
|
if (args.hasFlag('t')) {
|
|
|
|
npc.data().set(NPC.TARGETABLE_METADATA, targetable);
|
|
|
|
} else {
|
|
|
|
npc.data().setPersistent(NPC.TARGETABLE_METADATA, targetable);
|
|
|
|
}
|
|
|
|
Messaging.sendTr(sender, targetable ? Messages.TARGETABLE_SET : Messages.TARGETABLE_UNSET, npc.getName());
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "tp",
|
|
|
|
desc = "Teleport to a NPC",
|
|
|
|
modifiers = { "tp", "teleport" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.tp")
|
|
|
|
public void tp(CommandContext args, Player player, NPC npc) {
|
|
|
|
Location to = npc.getTrait(CurrentLocation.class).getLocation();
|
2013-07-03 12:05:18 +02:00
|
|
|
if (to == null) {
|
|
|
|
Messaging.sendError(player, Messages.TELEPORT_NPC_LOCATION_NOT_FOUND);
|
|
|
|
return;
|
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
player.teleport(to, TeleportCause.COMMAND);
|
|
|
|
Messaging.sendTr(player, Messages.TELEPORTED_TO_NPC, npc.getName());
|
|
|
|
}
|
|
|
|
|
2015-05-26 13:30:58 +02:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "tphere",
|
|
|
|
desc = "Teleport a NPC to your location",
|
|
|
|
modifiers = { "tphere", "tph", "move" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.tphere")
|
2013-02-06 08:17:21 +01:00
|
|
|
public void tphere(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
if (args.getSenderLocation() == null)
|
|
|
|
throw new ServerCommandException();
|
|
|
|
// Spawn the NPC if it isn't spawned to prevent NPEs
|
|
|
|
if (!npc.isSpawned()) {
|
|
|
|
npc.spawn(args.getSenderLocation());
|
2013-02-10 15:34:56 +01:00
|
|
|
if (!sender.hasPermission("citizens.npc.tphere.multiworld")
|
2013-11-05 12:29:18 +01:00
|
|
|
&& npc.getEntity().getLocation().getWorld() != args.getSenderLocation().getWorld()) {
|
2013-03-14 14:38:10 +01:00
|
|
|
npc.despawn(DespawnReason.REMOVAL);
|
2013-02-10 15:34:56 +01:00
|
|
|
throw new CommandException(Messages.CANNOT_TELEPORT_ACROSS_WORLDS);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!sender.hasPermission("citizens.npc.tphere.multiworld")
|
2013-11-05 12:29:18 +01:00
|
|
|
&& npc.getEntity().getLocation().getWorld() != args.getSenderLocation().getWorld()) {
|
2013-03-14 14:38:10 +01:00
|
|
|
npc.despawn(DespawnReason.REMOVAL);
|
2013-02-10 15:34:56 +01:00
|
|
|
throw new CommandException(Messages.CANNOT_TELEPORT_ACROSS_WORLDS);
|
|
|
|
}
|
2013-08-02 09:04:06 +02:00
|
|
|
npc.teleport(args.getSenderLocation(), TeleportCause.COMMAND);
|
2013-02-10 15:34:56 +01:00
|
|
|
}
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, Messages.NPC_TELEPORTED, npc.getName());
|
|
|
|
}
|
|
|
|
|
2013-02-17 03:58:27 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2013-02-17 06:26:05 +01:00
|
|
|
usage = "tpto [player name|npc id] [player name|npc id]",
|
2013-02-17 03:58:27 +01:00
|
|
|
desc = "Teleport an NPC or player to another NPC or player",
|
|
|
|
modifiers = { "tpto" },
|
2013-02-17 06:26:05 +01:00
|
|
|
min = 3,
|
|
|
|
max = 3,
|
2013-02-17 03:58:27 +01:00
|
|
|
permission = "citizens.npc.tpto")
|
|
|
|
@Requirements
|
|
|
|
public void tpto(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
Entity from = null, to = null;
|
2013-11-05 12:29:18 +01:00
|
|
|
if (npc != null) {
|
|
|
|
from = npc.getEntity();
|
|
|
|
}
|
2013-02-17 06:26:05 +01:00
|
|
|
boolean firstWasPlayer = false;
|
|
|
|
try {
|
|
|
|
int id = args.getInteger(1);
|
|
|
|
NPC fromNPC = CitizensAPI.getNPCRegistry().getById(id);
|
2013-11-07 17:08:50 +01:00
|
|
|
if (fromNPC != null) {
|
2013-11-05 12:29:18 +01:00
|
|
|
from = fromNPC.getEntity();
|
2013-11-07 17:08:50 +01:00
|
|
|
}
|
2013-02-17 06:26:05 +01:00
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
from = Bukkit.getPlayerExact(args.getString(1));
|
|
|
|
firstWasPlayer = true;
|
2013-02-17 03:58:27 +01:00
|
|
|
}
|
2013-02-17 06:26:05 +01:00
|
|
|
try {
|
|
|
|
int id = args.getInteger(2);
|
|
|
|
NPC toNPC = CitizensAPI.getNPCRegistry().getById(id);
|
2013-11-05 12:29:18 +01:00
|
|
|
if (toNPC != null) {
|
|
|
|
to = toNPC.getEntity();
|
|
|
|
}
|
2013-02-17 06:26:05 +01:00
|
|
|
} catch (NumberFormatException e) {
|
2014-04-12 16:59:56 +02:00
|
|
|
if (!firstWasPlayer) {
|
2013-02-17 06:26:05 +01:00
|
|
|
to = Bukkit.getPlayerExact(args.getString(2));
|
2014-04-12 16:59:56 +02:00
|
|
|
}
|
2013-02-17 03:58:27 +01:00
|
|
|
}
|
|
|
|
if (from == null)
|
|
|
|
throw new CommandException(Messages.FROM_ENTITY_NOT_FOUND);
|
|
|
|
if (to == null)
|
|
|
|
throw new CommandException(Messages.TO_ENTITY_NOT_FOUND);
|
|
|
|
from.teleport(to);
|
|
|
|
Messaging.sendTr(sender, Messages.TPTO_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "type [type]",
|
|
|
|
desc = "Sets an NPC's entity type",
|
|
|
|
modifiers = { "type" },
|
|
|
|
min = 2,
|
|
|
|
max = 2,
|
|
|
|
permission = "citizens.npc.type")
|
|
|
|
public void type(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
EntityType type = Util.matchEntityType(args.getString(1));
|
|
|
|
if (type == null)
|
|
|
|
throw new CommandException(Messages.INVALID_ENTITY_TYPE, args.getString(1));
|
2013-04-12 17:56:18 +02:00
|
|
|
npc.setBukkitEntityType(type);
|
2013-02-06 08:17:21 +01:00
|
|
|
Messaging.sendTr(sender, Messages.ENTITY_TYPE_SET, npc.getName(), args.getString(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "vulnerable (-t)",
|
|
|
|
desc = "Toggles an NPC's vulnerability",
|
|
|
|
modifiers = { "vulnerable" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
flags = "t",
|
|
|
|
permission = "citizens.npc.vulnerable")
|
|
|
|
public void vulnerable(CommandContext args, CommandSender sender, NPC npc) {
|
|
|
|
boolean vulnerable = !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
|
|
|
|
if (args.hasFlag('t')) {
|
|
|
|
npc.data().set(NPC.DEFAULT_PROTECTED_METADATA, vulnerable);
|
|
|
|
} else {
|
|
|
|
npc.data().setPersistent(NPC.DEFAULT_PROTECTED_METADATA, vulnerable);
|
|
|
|
}
|
|
|
|
String key = vulnerable ? Messages.VULNERABLE_STOPPED : Messages.VULNERABLE_SET;
|
|
|
|
Messaging.sendTr(sender, key, npc.getName());
|
|
|
|
}
|
|
|
|
|
2015-11-16 14:36:00 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "wither (--charged [charged])",
|
|
|
|
desc = "Sets wither modifiers",
|
|
|
|
modifiers = { "wither" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.wither")
|
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.WITHER })
|
|
|
|
public void wither(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
WitherTrait trait = npc.getTrait(WitherTrait.class);
|
|
|
|
boolean hasArg = false;
|
|
|
|
if (args.hasValueFlag("charged")) {
|
|
|
|
trait.setCharged(Boolean.valueOf(args.getFlag("charged")));
|
|
|
|
hasArg = true;
|
|
|
|
}
|
|
|
|
if (!hasArg) {
|
|
|
|
throw new CommandException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-08 10:47:03 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
2013-05-08 15:08:12 +02:00
|
|
|
usage = "wolf (-s(itting) a(ngry) t(amed)) --collar [hex rgb color|name]",
|
2013-03-08 10:47:03 +01:00
|
|
|
desc = "Sets wolf modifiers",
|
|
|
|
modifiers = { "wolf" },
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
flags = "sat",
|
|
|
|
permission = "citizens.npc.wolf")
|
|
|
|
@Requirements(selected = true, ownership = true, types = EntityType.WOLF)
|
|
|
|
public void wolf(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
2013-07-11 06:29:46 +02:00
|
|
|
WolfModifiers trait = npc.getTrait(WolfModifiers.class);
|
|
|
|
trait.setAngry(args.hasFlag('a'));
|
|
|
|
trait.setSitting(args.hasFlag('s'));
|
|
|
|
trait.setTamed(args.hasFlag('t'));
|
2013-03-08 10:47:03 +01:00
|
|
|
if (args.hasValueFlag("collar")) {
|
2013-03-16 06:28:26 +01:00
|
|
|
String unparsed = args.getFlag("collar");
|
|
|
|
DyeColor color = null;
|
|
|
|
try {
|
2013-05-08 15:08:12 +02:00
|
|
|
color = DyeColor.valueOf(unparsed.toUpperCase().replace(' ', '_'));
|
2013-03-16 06:28:26 +01:00
|
|
|
} catch (IllegalArgumentException e) {
|
2015-01-04 12:59:33 +01:00
|
|
|
try {
|
|
|
|
int rgb = Integer.parseInt(unparsed.replace("#", ""), 16);
|
|
|
|
color = DyeColor.getByColor(org.bukkit.Color.fromRGB(rgb));
|
|
|
|
} catch (NumberFormatException ex) {
|
|
|
|
throw new CommandException(Messages.COLLAR_COLOUR_NOT_RECOGNISED, unparsed);
|
|
|
|
}
|
2013-03-16 06:28:26 +01:00
|
|
|
}
|
2013-03-08 10:47:03 +01:00
|
|
|
if (color == null)
|
2015-01-04 12:59:33 +01:00
|
|
|
throw new CommandException(Messages.COLLAR_COLOUR_NOT_SUPPORTED, unparsed);
|
2013-07-11 06:29:46 +02:00
|
|
|
trait.setCollarColor(color);
|
2013-03-08 10:47:03 +01:00
|
|
|
}
|
2015-01-04 12:59:33 +01:00
|
|
|
Messaging.sendTr(sender, Messages.WOLF_TRAIT_UPDATED, npc.getName(), args.hasFlag('a'), args.hasFlag('s'),
|
|
|
|
args.hasFlag('t'), trait.getCollarColor().name());
|
2013-03-08 10:47:03 +01:00
|
|
|
}
|
|
|
|
|
2013-02-06 08:17:21 +01:00
|
|
|
@Command(
|
|
|
|
aliases = { "npc" },
|
|
|
|
usage = "zombiemod (-b(aby), -v(illager))",
|
|
|
|
desc = "Sets a zombie NPC to be a baby or villager",
|
|
|
|
modifiers = { "zombie", "zombiemod" },
|
|
|
|
flags = "bv",
|
|
|
|
min = 1,
|
|
|
|
max = 1,
|
|
|
|
permission = "citizens.npc.zombiemodifier")
|
2014-02-01 15:43:46 +01:00
|
|
|
@Requirements(selected = true, ownership = true, types = { EntityType.ZOMBIE, EntityType.PIG_ZOMBIE })
|
2013-02-06 08:17:21 +01:00
|
|
|
public void zombieModifier(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
|
|
|
ZombieModifier trait = npc.getTrait(ZombieModifier.class);
|
|
|
|
if (args.hasFlag('b')) {
|
|
|
|
boolean isBaby = trait.toggleBaby();
|
|
|
|
Messaging.sendTr(sender, isBaby ? Messages.ZOMBIE_BABY_SET : Messages.ZOMBIE_BABY_UNSET, npc.getName());
|
|
|
|
}
|
|
|
|
if (args.hasFlag('v')) {
|
|
|
|
boolean isVillager = trait.toggleVillager();
|
|
|
|
Messaging.sendTr(sender, isVillager ? Messages.ZOMBIE_VILLAGER_SET : Messages.ZOMBIE_VILLAGER_UNSET,
|
|
|
|
npc.getName());
|
|
|
|
}
|
|
|
|
}
|
2013-03-17 04:28:04 +01:00
|
|
|
}
|