Allow /npc spawn and /npc despawn to use names as well instead of ids

This commit is contained in:
fullwall 2013-11-08 00:08:50 +08:00
parent 79fcba4ec7
commit c4c1594e4b
3 changed files with 187 additions and 138 deletions

View File

@ -0,0 +1,123 @@
package net.citizensnpcs.commands;
import java.util.List;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.command.CommandContext;
import net.citizensnpcs.api.command.CommandMessages;
import net.citizensnpcs.api.command.exception.CommandException;
import net.citizensnpcs.api.command.exception.CommandUsageException;
import net.citizensnpcs.api.command.exception.ServerCommandException;
import net.citizensnpcs.api.command.exception.UnhandledCommandException;
import net.citizensnpcs.api.command.exception.WrappedCommandException;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCRegistry;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Util;
import org.bukkit.command.CommandSender;
import org.bukkit.conversations.Conversable;
import org.bukkit.conversations.Conversation;
import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.conversations.NumericPrompt;
import org.bukkit.conversations.Prompt;
import com.google.common.collect.Lists;
public class NPCCommandSelector extends NumericPrompt {
private final Callback callback;
private final List<NPC> choices;
public NPCCommandSelector(Callback callback, List<NPC> possible) {
this.callback = callback;
this.choices = possible;
}
@Override
protected Prompt acceptValidatedInput(ConversationContext context, Number input) {
boolean found = false;
for (NPC npc : choices) {
if (input.intValue() == npc.getId()) {
found = true;
break;
}
}
CommandSender sender = (CommandSender) context.getForWhom();
if (!found) {
Messaging.sendErrorTr(sender, Messages.SELECTION_PROMPT_INVALID_CHOICE, input);
return this;
}
NPC toSelect = CitizensAPI.getNPCRegistry().getById(input.intValue());
try {
callback.run(toSelect);
} catch (ServerCommandException ex) {
Messaging.sendTr(sender, CommandMessages.MUST_BE_INGAME);
} catch (CommandUsageException ex) {
Messaging.sendError(sender, ex.getMessage());
Messaging.sendError(sender, ex.getUsage());
} catch (UnhandledCommandException ex) {
ex.printStackTrace();
} catch (WrappedCommandException ex) {
ex.getCause().printStackTrace();
} catch (CommandException ex) {
Messaging.sendError(sender, ex.getMessage());
} catch (NumberFormatException ex) {
Messaging.sendErrorTr(sender, CommandMessages.INVALID_NUMBER);
}
return null;
}
@Override
public String getPromptText(ConversationContext context) {
String text = Messaging.tr(Messages.SELECTION_PROMPT);
for (NPC npc : choices) {
text += "\n - " + npc.getId();
}
return text;
}
public static interface Callback {
public void run(NPC npc) throws CommandException;
}
public static void start(Callback callback, Conversable player, List<NPC> possible) {
final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()).withLocalEcho(false)
.withEscapeSequence("exit").withModality(false)
.withFirstPrompt(new NPCCommandSelector(callback, possible)).buildConversation(player);
conversation.begin();
}
public static void startWithCallback(Callback callback, NPCRegistry npcRegistry, CommandSender sender,
CommandContext args, String raw) throws CommandException {
try {
int id = Integer.parseInt(raw);
callback.run(npcRegistry.getById(id));
return;
} catch (NumberFormatException ex) {
String name = args.getString(1);
List<NPC> possible = Lists.newArrayList();
double range = -1;
if (args.hasValueFlag("r")) {
range = Math.abs(args.getFlagDouble("r"));
}
for (NPC test : npcRegistry) {
if (test.getName().equalsIgnoreCase(name)) {
if (range > 0
&& test.isSpawned()
&& !Util.locationWithinRange(args.getSenderLocation(), test.getEntity().getLocation(),
range))
continue;
possible.add(test);
}
}
if (possible.size() == 1) {
callback.run(possible.get(0));
} else if (possible.size() > 1) {
NPCCommandSelector.start(callback, (Conversable) sender, possible);
return;
}
}
}
}

View File

@ -62,7 +62,6 @@ import org.bukkit.World;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.conversations.Conversable;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -78,7 +77,6 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@Requirements(selected = true, ownership = true)
public class NPCCommands {
@ -406,18 +404,26 @@ public class NPCCommands {
max = 2,
permission = "citizens.npc.despawn")
@Requirements
public void despawn(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
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());
}
};
if (npc == null || args.argsLength() == 2) {
if (args.argsLength() < 2)
if (args.argsLength() < 2) {
throw new CommandException(Messages.COMMAND_MUST_HAVE_SELECTED);
int id = args.getInteger(1);
npc = CitizensAPI.getNPCRegistry().getById(id);
if (npc == null)
throw new CommandException(Messages.NO_NPC_WITH_ID_FOUND, id);
}
NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1));
} else {
callback.run(npc);
}
npc.getTrait(Spawned.class).setSpawned(false);
npc.despawn(DespawnReason.REMOVAL);
Messaging.sendTr(sender, Messages.NPC_DESPAWNED, npc.getName());
}
@Command(
@ -1013,8 +1019,18 @@ public class NPCCommands {
max = 2,
permission = "citizens.npc.select")
@Requirements
public void select(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
NPC toSelect = null;
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 {
if (toSelect == null || !toSelect.getTrait(Spawned.class).shouldSpawn())
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);
}
};
if (args.argsLength() <= 1) {
if (!(sender instanceof Player))
throw new ServerCommandException();
@ -1033,44 +1049,12 @@ public class NPCCommands {
NPC test = npcRegistry.getNPC(possibleNPC);
if (test == null)
continue;
toSelect = test;
callback.run(test);
break;
}
} else {
try {
int id = args.getInteger(1);
toSelect = npcRegistry.getById(id);
} catch (NumberFormatException ex) {
String name = args.getString(1);
List<NPC> possible = Lists.newArrayList();
double range = -1;
if (args.hasValueFlag("r")) {
range = Math.abs(args.getFlagDouble("r"));
}
for (NPC test : npcRegistry) {
if (test.getName().equalsIgnoreCase(name)) {
if (range > 0
&& test.isSpawned()
&& !Util.locationWithinRange(args.getSenderLocation(), test.getEntity().getLocation(),
range))
continue;
possible.add(test);
}
}
if (possible.size() == 1) {
toSelect = possible.get(0);
} else if (possible.size() > 1) {
SelectionPrompt.start(selector, (Conversable) sender, possible);
return;
}
}
NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1));
}
if (toSelect == null || !toSelect.getTrait(Spawned.class).shouldSpawn())
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);
}
@Command(aliases = { "npc" }, usage = "skeletontype [type]", desc = "Sets the NPC's skeleton type", modifiers = {
@ -1106,40 +1090,44 @@ public class NPCCommands {
@Command(
aliases = { "npc" },
usage = "spawn (id)",
usage = "spawn (id|name)",
desc = "Spawn an existing NPC",
modifiers = { "spawn" },
min = 1,
max = 2,
permission = "citizens.npc.spawn")
@Requirements(ownership = true)
public void spawn(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
NPC respawn = null;
try {
respawn = args.argsLength() > 1 ? npcRegistry.getById(args.getInteger(1)) : npc;
} catch (NumberFormatException ex) {
Messaging.sendTr(sender, Messages.SPAWN_NUMERIC_ID_ONLY);
return;
}
if (respawn == null) {
if (args.argsLength() > 1) {
throw new CommandException(Messages.NO_NPC_WITH_ID_FOUND, args.getInteger(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);
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);
location = args.getSenderLocation();
}
if (respawn.spawn(location)) {
selector.select(sender, respawn);
Messaging.sendTr(sender, Messages.NPC_SPAWNED, respawn.getName());
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);
}
}
@ -1278,8 +1266,9 @@ public class NPCCommands {
try {
int id = args.getInteger(1);
NPC fromNPC = CitizensAPI.getNPCRegistry().getById(id);
if (fromNPC != null)
if (fromNPC != null) {
from = fromNPC.getEntity();
}
} catch (NumberFormatException e) {
from = Bukkit.getPlayerExact(args.getString(1));
firstWasPlayer = true;

View File

@ -1,63 +0,0 @@
package net.citizensnpcs.commands;
import java.util.List;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.NPCSelector;
import net.citizensnpcs.util.Messages;
import org.bukkit.command.CommandSender;
import org.bukkit.conversations.Conversable;
import org.bukkit.conversations.Conversation;
import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.conversations.NumericPrompt;
import org.bukkit.conversations.Prompt;
public class SelectionPrompt extends NumericPrompt {
private final List<NPC> choices;
private final NPCSelector selector;
public SelectionPrompt(NPCSelector selector, List<NPC> possible) {
choices = possible;
this.selector = selector;
}
@Override
protected Prompt acceptValidatedInput(ConversationContext context, Number input) {
boolean found = false;
for (NPC npc : choices) {
if (input.intValue() == npc.getId()) {
found = true;
break;
}
}
CommandSender sender = (CommandSender) context.getForWhom();
if (!found) {
Messaging.sendErrorTr(sender, Messages.SELECTION_PROMPT_INVALID_CHOICE, input);
return this;
}
NPC toSelect = CitizensAPI.getNPCRegistry().getById(input.intValue());
selector.select(sender, toSelect);
Messaging.sendWithNPC(sender, Setting.SELECTION_MESSAGE.asString(), toSelect);
return null;
}
@Override
public String getPromptText(ConversationContext context) {
String text = Messaging.tr(Messages.SELECTION_PROMPT);
for (NPC npc : choices)
text += "\n - " + npc.getId();
return text;
}
public static void start(NPCSelector selector, Conversable player, List<NPC> possible) {
final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()).withLocalEcho(false)
.withEscapeSequence("exit").withModality(false)
.withFirstPrompt(new SelectionPrompt(selector, possible)).buildConversation(player);
conversation.begin();
}
}