Format and potential fix for incorrect chunk unload logic

This commit is contained in:
fullwall 2013-01-04 14:57:21 +08:00
parent c053fa9871
commit dc4fb0a33e
49 changed files with 456 additions and 464 deletions

View File

@ -62,8 +62,8 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
private CitizensNPCRegistry npcRegistry; private CitizensNPCRegistry npcRegistry;
private NPCDataStore saves; private NPCDataStore saves;
private NPCSelector selector; private NPCSelector selector;
private CitizensTraitFactory traitFactory;
private CitizensSpeechFactory speechFactory; private CitizensSpeechFactory speechFactory;
private CitizensTraitFactory traitFactory;
private void despawnNPCs() { private void despawnNPCs() {
Iterator<NPC> itr = npcRegistry.iterator(); Iterator<NPC> itr = npcRegistry.iterator();
@ -131,13 +131,13 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
} }
@Override @Override
public TraitFactory getTraitFactory() { public SpeechFactory getSpeechFactory() {
return traitFactory; return speechFactory;
} }
@Override @Override
public SpeechFactory getSpeechFactory() { public TraitFactory getTraitFactory() {
return speechFactory; return traitFactory;
} }
@Override @Override

View File

@ -69,21 +69,13 @@ public class EventListen implements Listener {
/* /*
* Chunk events * Chunk events
*/ */
@EventHandler(ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onChunkLoad(ChunkLoadEvent event) { public void onChunkLoad(ChunkLoadEvent event) {
ChunkCoord coord = toCoord(event.getChunk()); ChunkCoord coord = toCoord(event.getChunk());
List<Integer> ids = toRespawn.get(coord); respawnAllFromCoord(coord);
for (int i = 0; i < ids.size(); i++) {
int id = ids.get(i);
boolean success = spawn(id);
if (!success)
continue;
ids.remove(i);
Messaging.debug("Spawned", id, "due to chunk load at [" + coord.x + "," + coord.z + "]");
}
} }
@EventHandler(ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onChunkUnload(ChunkUnloadEvent event) { public void onChunkUnload(ChunkUnloadEvent event) {
ChunkCoord coord = toCoord(event.getChunk()); ChunkCoord coord = toCoord(event.getChunk());
Location location = new Location(null, 0, 0, 0); Location location = new Location(null, 0, 0, 0);
@ -93,13 +85,15 @@ public class EventListen implements Listener {
location = npc.getBukkitEntity().getLocation(location); location = npc.getBukkitEntity().getLocation(location);
boolean sameChunkCoordinates = coord.z == location.getBlockZ() >> 4 && coord.x == location.getBlockX() >> 4; boolean sameChunkCoordinates = coord.z == location.getBlockZ() >> 4 && coord.x == location.getBlockX() >> 4;
if (sameChunkCoordinates && event.getWorld().equals(location.getWorld())) { if (sameChunkCoordinates && event.getWorld().equals(location.getWorld())) {
npc.despawn(DespawnReason.CHUNK_UNLOAD); if (!npc.despawn(DespawnReason.CHUNK_UNLOAD)) {
if (event.getChunk().isLoaded()) { event.setCancelled(true);
toRespawn.removeAll(coord); Messaging.debug("Cancelled chunk unload at [" + coord.x + "," + coord.z + "]");
respawnAllFromCoord(coord);
return; return;
} }
toRespawn.put(coord, npc.getId()); toRespawn.put(coord, npc.getId());
Messaging.debug("Despawned", npc.getId(), "due to chunk unload at [" + coord.x + "," + coord.z + "]"); Messaging.debug("Despawned id ", npc.getId(), "due to chunk unload at [" + coord.x + "," + coord.z
+ "]");
} }
} }
} }
@ -189,10 +183,6 @@ public class EventListen implements Listener {
// undesirable as player NPCs are not real players and confuse plugins. // undesirable as player NPCs are not real players and confuse plugins.
} }
/*
* Player events
*/
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onPlayerCreateNPC(PlayerCreateNPCEvent event) { public void onPlayerCreateNPC(PlayerCreateNPCEvent event) {
if (event.getCreator().hasPermission("citizens.admin.avoid-limits")) if (event.getCreator().hasPermission("citizens.admin.avoid-limits"))
@ -219,6 +209,10 @@ public class EventListen implements Listener {
} }
} }
/*
* Player events
*/
@EventHandler @EventHandler
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
NPC npc = npcRegistry.getNPC(event.getRightClicked()); NPC npc = npcRegistry.getNPC(event.getRightClicked());
@ -232,7 +226,7 @@ public class EventListen implements Listener {
Bukkit.getPluginManager().callEvent(rightClickEvent); Bukkit.getPluginManager().callEvent(rightClickEvent);
} }
@EventHandler(ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
Editor.leave(event.getPlayer()); Editor.leave(event.getPlayer());
} }
@ -255,17 +249,34 @@ public class EventListen implements Listener {
} }
} }
@EventHandler(ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onWorldUnload(WorldUnloadEvent event) { public void onWorldUnload(WorldUnloadEvent event) {
for (NPC npc : npcRegistry) { for (NPC npc : npcRegistry) {
if (!npc.isSpawned() || !npc.getBukkitEntity().getWorld().equals(event.getWorld())) if (!npc.isSpawned() || !npc.getBukkitEntity().getWorld().equals(event.getWorld()))
continue; continue;
storeForRespawn(npc); storeForRespawn(npc);
npc.despawn(); npc.despawn(DespawnReason.WORLD_UNLOAD);
if (event.isCancelled())
return;
Messaging.debug("Despawned", npc.getId() + "due to world unload at", event.getWorld().getName()); Messaging.debug("Despawned", npc.getId() + "due to world unload at", event.getWorld().getName());
} }
} }
private void respawnAllFromCoord(ChunkCoord coord) {
List<Integer> ids = toRespawn.get(coord);
for (int i = 0; i < ids.size(); i++) {
int id = ids.get(i);
boolean success = spawn(id);
if (!success) {
Messaging.debug("Couldn't respawn id " + id + " during chunk event at [" + coord.x + "," + coord.z
+ "]");
continue;
}
ids.remove(i);
Messaging.debug("Spawned id ", id, "due to chunk event at [" + coord.x + "," + coord.z + "]");
}
}
private boolean spawn(int id) { private boolean spawn(int id) {
NPC npc = npcRegistry.getById(id); NPC npc = npcRegistry.getById(id);
if (npc == null) if (npc == null)

View File

@ -28,6 +28,27 @@ public class NPCDataStore {
root = saves; root = saves;
} }
public void addPlotters(Graph graph) {
graph.addPlotter(new Plotter("Database") {
@Override
public int getValue() {
return root instanceof DatabaseStorage ? 1 : 0;
}
});
graph.addPlotter(new Plotter("YAML") {
@Override
public int getValue() {
return root instanceof YamlStorage ? 1 : 0;
}
});
graph.addPlotter(new Plotter("NBT") {
@Override
public int getValue() {
return root instanceof NBTStorage ? 1 : 0;
}
});
}
public void loadInto(CitizensNPCRegistry registry) { public void loadInto(CitizensNPCRegistry registry) {
int created = 0; int created = 0;
for (DataKey key : root.getKey("npc").getIntegerSubKeys()) { for (DataKey key : root.getKey("npc").getIntegerSubKeys()) {
@ -81,16 +102,14 @@ public class NPCDataStore {
String type = Setting.STORAGE_TYPE.asString(); String type = Setting.STORAGE_TYPE.asString();
if (type.equalsIgnoreCase("db") || type.equalsIgnoreCase("database")) { if (type.equalsIgnoreCase("db") || type.equalsIgnoreCase("database")) {
try { try {
saves = new DatabaseStorage(Setting.DATABASE_DRIVER.asString(), saves = new DatabaseStorage(Setting.DATABASE_DRIVER.asString(), Setting.DATABASE_URL.asString(),
Setting.DATABASE_URL.asString(), Setting.DATABASE_USERNAME.asString(), Setting.DATABASE_USERNAME.asString(), Setting.DATABASE_PASSWORD.asString());
Setting.DATABASE_PASSWORD.asString());
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
Messaging.logTr(Messages.DATABASE_CONNECTION_FAILED); Messaging.logTr(Messages.DATABASE_CONNECTION_FAILED);
} }
} else if (type.equalsIgnoreCase("nbt")) { } else if (type.equalsIgnoreCase("nbt")) {
saves = new NBTStorage(folder + File.separator + Setting.STORAGE_FILE.asString(), saves = new NBTStorage(folder + File.separator + Setting.STORAGE_FILE.asString(), "Citizens NPC Storage");
"Citizens NPC Storage");
} }
if (saves == null) if (saves == null)
saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage"); saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage");
@ -98,25 +117,4 @@ public class NPCDataStore {
return null; return null;
return new NPCDataStore(saves); return new NPCDataStore(saves);
} }
public void addPlotters(Graph graph) {
graph.addPlotter(new Plotter("Database") {
@Override
public int getValue() {
return root instanceof DatabaseStorage ? 1 : 0;
}
});
graph.addPlotter(new Plotter("YAML") {
@Override
public int getValue() {
return root instanceof YamlStorage ? 1 : 0;
}
});
graph.addPlotter(new Plotter("NBT") {
@Override
public int getValue() {
return root instanceof NBTStorage ? 1 : 0;
}
});
}
} }

View File

@ -43,14 +43,16 @@ public class Settings {
} }
public enum Setting { public enum Setting {
CHAT_FORMAT("npc.chat.format.no-targets", "[<npc>]: <text>"),
CHAT_FORMAT_TO_TARGET("npc.chat.format.to-target", "[<npc>] -> You: <text>"),
CHAT_FORMAT_TO_BYSTANDERS("npc.chat.format.with-target-to-bystanders", "[<npc>] -> [<target>]: <text>"),
CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS("npc.chat.format.with-targets-to-bystanders", "[<npc>] -> [<targets>]: <text>"),
CHAT_RANGE("npc.chat.options.range", 5),
CHAT_BYSTANDERS_HEAR_TARGETED_CHAT("npc.chat.options.bystanders-hear-targeted-chat", true), CHAT_BYSTANDERS_HEAR_TARGETED_CHAT("npc.chat.options.bystanders-hear-targeted-chat", true),
CHAT_FORMAT("npc.chat.format.no-targets", "[<npc>]: <text>"),
CHAT_FORMAT_TO_BYSTANDERS("npc.chat.format.with-target-to-bystanders", "[<npc>] -> [<target>]: <text>"),
CHAT_FORMAT_TO_TARGET("npc.chat.format.to-target", "[<npc>] -> You: <text>"),
CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS("npc.chat.format.with-targets-to-bystanders",
"[<npc>] -> [<targets>]: <text>"),
CHAT_MAX_NUMBER_OF_TARGETS("npc.chat.options.max-number-of-targets-to-show", 2), CHAT_MAX_NUMBER_OF_TARGETS("npc.chat.options.max-number-of-targets-to-show", 2),
CHAT_MULTIPLE_TARGETS_FORMAT("npc.chat.options.multiple-targets-format", "<target>|, <target>| & <target>| & others"), CHAT_MULTIPLE_TARGETS_FORMAT("npc.chat.options.multiple-targets-format",
"<target>|, <target>| & <target>| & others"),
CHAT_RANGE("npc.chat.options.range", 5),
DATABASE_DRIVER("storage.database.driver", ""), DATABASE_DRIVER("storage.database.driver", ""),
DATABASE_PASSWORD("storage.database.password", ""), DATABASE_PASSWORD("storage.database.password", ""),
DATABASE_URL("storage.database.url", ""), DATABASE_URL("storage.database.url", ""),

View File

@ -215,7 +215,7 @@ public class CommandContext {
location = ((BlockCommandSender) sender).getBlock().getLocation(); location = ((BlockCommandSender) sender).getBlock().getLocation();
return location; return location;
} }
public String[] getSlice(int index) { public String[] getSlice(int index) {
String[] slice = new String[args.length - index]; String[] slice = new String[args.length - index];
System.arraycopy(args, index, slice, 0, args.length - index); System.arraycopy(args, index, slice, 0, args.length - index);

View File

@ -35,8 +35,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
public class CommandManager { public class CommandManager {
private final Map<Class<? extends Annotation>, CommandAnnotationProcessor> annotationProcessors = Maps private final Map<Class<? extends Annotation>, CommandAnnotationProcessor> annotationProcessors = Maps.newHashMap();
.newHashMap();
/* /*
* Mapping of commands (including aliases) with a description. Root commands * Mapping of commands (including aliases) with a description. Root commands
@ -77,8 +76,8 @@ public class CommandManager {
* @throws CommandException * @throws CommandException
* Any exceptions caused from execution of the command * Any exceptions caused from execution of the command
*/ */
public void execute(org.bukkit.command.Command command, String[] args, CommandSender sender, public void execute(org.bukkit.command.Command command, String[] args, CommandSender sender, Object... methodArgs)
Object... methodArgs) throws CommandException { throws CommandException {
// must put command into split. // must put command into split.
String[] newArgs = new String[args.length + 1]; String[] newArgs = new String[args.length + 1];
System.arraycopy(args, 0, newArgs, 1, args.length); System.arraycopy(args, 0, newArgs, 1, args.length);
@ -90,8 +89,7 @@ public class CommandManager {
} }
// Attempt to execute a command. // Attempt to execute a command.
private void executeMethod(String[] args, CommandSender sender, Object[] methodArgs) private void executeMethod(String[] args, CommandSender sender, Object[] methodArgs) throws CommandException {
throws CommandException {
String cmdName = args[0]; String cmdName = args[0];
String modifier = args.length > 1 ? args[1] : ""; String modifier = args.length > 1 ? args[1] : "";
@ -288,8 +286,7 @@ public class CommandManager {
// Returns whether a player has access to a command. // Returns whether a player has access to a command.
private boolean hasPermission(Method method, CommandSender sender) { private boolean hasPermission(Method method, CommandSender sender) {
Command cmd = method.getAnnotation(Command.class); Command cmd = method.getAnnotation(Command.class);
if (cmd.permission().isEmpty() || hasPermission(sender, cmd.permission()) if (cmd.permission().isEmpty() || hasPermission(sender, cmd.permission()) || hasPermission(sender, "admin"))
|| hasPermission(sender, "admin"))
return true; return true;
return false; return false;

View File

@ -64,8 +64,8 @@ public class RequirementsProcessor implements CommandAnnotationProcessor {
EntityType type = npc.getTrait(MobType.class).getType(); EntityType type = npc.getTrait(MobType.class).getType();
if (!types.contains(type)) { if (!types.contains(type)) {
throw new RequirementMissingException(Messaging.tr( throw new RequirementMissingException(Messaging.tr(Messages.COMMAND_REQUIREMENTS_INVALID_MOB_TYPE,
Messages.COMMAND_REQUIREMENTS_INVALID_MOB_TYPE, type.getName())); type.getName()));
} }
} }
} }

View File

@ -23,10 +23,8 @@ public class AdminCommands {
@Command(aliases = { "citizens" }, desc = "Show basic plugin information", max = 0, permission = "admin") @Command(aliases = { "citizens" }, desc = "Show basic plugin information", max = 0, permission = "admin")
public void citizens(CommandContext args, CommandSender sender, NPC npc) { public void citizens(CommandContext args, CommandSender sender, NPC npc) {
Messaging.send( Messaging.send(sender,
sender, " " + StringHelper.wrapHeader("<e>Citizens v" + plugin.getDescription().getVersion()));
" "
+ StringHelper.wrapHeader("<e>Citizens v" + plugin.getDescription().getVersion()));
Messaging.send(sender, " <7>-- <c>Written by fullwall and aPunch"); Messaging.send(sender, " <7>-- <c>Written by fullwall and aPunch");
Messaging.send(sender, " <7>-- <c>Source Code: http://github.com/CitizensDev"); Messaging.send(sender, " <7>-- <c>Source Code: http://github.com/CitizensDev");
Messaging.send(sender, " <7>-- <c>Website: " + plugin.getDescription().getWebsite()); Messaging.send(sender, " <7>-- <c>Website: " + plugin.getDescription().getWebsite());

View File

@ -23,8 +23,8 @@ public class EditorCommands {
min = 1, min = 1,
max = 1, max = 1,
permission = "npc.edit.equip") permission = "npc.edit.equip")
@Requirements(selected = true, ownership = true, types = { EntityType.ENDERMAN, EntityType.PLAYER, @Requirements(selected = true, ownership = true, types = { EntityType.ENDERMAN, EntityType.PLAYER, EntityType.PIG,
EntityType.PIG, EntityType.SHEEP }) EntityType.SHEEP })
public void equip(CommandContext args, Player player, NPC npc) { public void equip(CommandContext args, Player player, NPC npc) {
Editor.enterOrLeave(player, new EquipmentEditor(player, npc)); Editor.enterOrLeave(player, new EquipmentEditor(player, npc));
} }
@ -37,8 +37,8 @@ public class EditorCommands {
min = 1, min = 1,
max = 1, max = 1,
permission = "npc.edit.path") permission = "npc.edit.path")
@Requirements(selected = true, ownership = true, excludedTypes = { EntityType.BLAZE, @Requirements(selected = true, ownership = true, excludedTypes = { EntityType.BLAZE, EntityType.ENDER_DRAGON,
EntityType.ENDER_DRAGON, EntityType.GHAST, EntityType.BAT, EntityType.WITHER, EntityType.SQUID }) EntityType.GHAST, EntityType.BAT, EntityType.WITHER, EntityType.SQUID })
public void path(CommandContext args, Player player, NPC npc) { public void path(CommandContext args, Player player, NPC npc) {
Editor.enterOrLeave(player, npc.getTrait(Waypoints.class).getEditor(player)); Editor.enterOrLeave(player, npc.getTrait(Waypoints.class).getEditor(player));
} }

View File

@ -112,8 +112,7 @@ public class HelpCommands {
throw new CommandException(Messages.COMMAND_PAGE_MISSING, page); throw new CommandException(Messages.COMMAND_PAGE_MISSING, page);
} }
private void sendSpecificHelp(CommandSender sender, String rootCommand, String modifier) private void sendSpecificHelp(CommandSender sender, String rootCommand, String modifier) throws CommandException {
throws CommandException {
CommandInfo info = plugin.getCommandInfo(rootCommand, modifier); CommandInfo info = plugin.getCommandInfo(rootCommand, modifier);
if (info == null) if (info == null)
throw new CommandException(Messages.COMMAND_MISSING, rootCommand + " " + modifier); throw new CommandException(Messages.COMMAND_MISSING, rootCommand + " " + modifier);
@ -165,7 +164,7 @@ public class HelpCommands {
private static final String COMMAND_FORMAT = "<7>/<c>%s%s <7>- <e>%s"; private static final String COMMAND_FORMAT = "<7>/<c>%s%s <7>- <e>%s";
private static final String format(Command command) { private static final String format(Command command) {
return String.format(COMMAND_FORMAT, command.aliases()[0], (command.usage().isEmpty() ? "" : " " return String.format(COMMAND_FORMAT, command.aliases()[0],
+ command.usage()), Messaging.tryTranslate(command.desc())); (command.usage().isEmpty() ? "" : " " + command.usage()), Messaging.tryTranslate(command.desc()));
} }
} }

View File

@ -30,8 +30,7 @@ public class ScriptCommands {
min = 2, min = 2,
max = 2, max = 2,
permission = "script.compile") permission = "script.compile")
public void runScript(final CommandContext args, final CommandSender sender, NPC npc) public void runScript(final CommandContext args, final CommandSender sender, NPC npc) throws CommandException {
throws CommandException {
File file = new File(CitizensAPI.getScriptFolder(), args.getString(1)); File file = new File(CitizensAPI.getScriptFolder(), args.getString(1));
if (!file.exists()) if (!file.exists())
throw new CommandException(Messages.SCRIPT_FILE_MISSING, args.getString(1)); throw new CommandException(Messages.SCRIPT_FILE_MISSING, args.getString(1));

View File

@ -55,8 +55,8 @@ public class SelectionPrompt extends NumericPrompt {
} }
public static void start(NPCSelector selector, Player player, List<NPC> possible) { public static void start(NPCSelector selector, Player player, List<NPC> possible) {
final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()) final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()).withLocalEcho(false)
.withLocalEcho(false).withEscapeSequence("exit").withModality(false) .withEscapeSequence("exit").withModality(false)
.withFirstPrompt(new SelectionPrompt(selector, possible)).buildConversation(player); .withFirstPrompt(new SelectionPrompt(selector, possible)).buildConversation(player);
conversation.begin(); conversation.begin();
} }

View File

@ -24,13 +24,8 @@ import com.google.common.collect.Lists;
@Requirements(selected = true, ownership = true) @Requirements(selected = true, ownership = true)
public class TraitCommands { public class TraitCommands {
@Command( @Command(aliases = { "trait", "tr" }, usage = "add [trait name]...", desc = "Adds traits to the NPC", modifiers = {
aliases = { "trait", "tr" }, "add", "a" }, min = 1, permission = "npc.trait")
usage = "add [trait name]...",
desc = "Adds traits to the NPC",
modifiers = { "add", "a" },
min = 1,
permission = "npc.trait")
public void add(CommandContext args, CommandSender sender, NPC npc) throws CommandException { public void add(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
List<String> added = Lists.newArrayList(); List<String> added = Lists.newArrayList();
List<String> failed = Lists.newArrayList(); List<String> failed = Lists.newArrayList();

View File

@ -26,8 +26,7 @@ public class WaypointCommands {
min = 1, min = 1,
max = 1, max = 1,
permission = "waypoints.disableteleport") permission = "waypoints.disableteleport")
public void disableTeleporting(CommandContext args, CommandSender sender, NPC npc) public void disableTeleporting(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
throws CommandException {
npc.getNavigator().getDefaultParameters().stuckAction(null); npc.getNavigator().getDefaultParameters().stuckAction(null);
Messaging.sendTr(sender, Messages.WAYPOINT_TELEPORTING_DISABLED); Messaging.sendTr(sender, Messages.WAYPOINT_TELEPORTING_DISABLED);
} }
@ -47,8 +46,7 @@ public class WaypointCommands {
if (args.hasFlag('a')) { if (args.hasFlag('a')) {
waypoints.describeProviders(sender); waypoints.describeProviders(sender);
} else } else
Messaging.sendTr(sender, Messages.CURRENT_WAYPOINT_PROVIDER, Messaging.sendTr(sender, Messages.CURRENT_WAYPOINT_PROVIDER, waypoints.getCurrentProviderName());
waypoints.getCurrentProviderName());
return; return;
} }
boolean success = waypoints.setWaypointProvider(args.getString(1)); boolean success = waypoints.setWaypointProvider(args.getString(1));

View File

@ -27,8 +27,7 @@ public class EndermanEquipper implements Equipper {
return; return;
} }
} else { } else {
equipper.getWorld() equipper.getWorld().dropItemNaturally(npc.getBukkitEntity().getLocation(), carried.toItemStack(1));
.dropItemNaturally(npc.getBukkitEntity().getLocation(), carried.toItemStack(1));
((Enderman) npc.getBukkitEntity()).setCarriedMaterial(hand.getData()); ((Enderman) npc.getBukkitEntity()).setCarriedMaterial(hand.getData());
} }

View File

@ -56,8 +56,7 @@ public class GenericEquipper implements Equipper {
case AIR: case AIR:
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
if (trait.get(i) != null && trait.get(i).getType() != Material.AIR) { if (trait.get(i) != null && trait.get(i).getType() != Material.AIR) {
equipper.getWorld().dropItemNaturally(toEquip.getBukkitEntity().getLocation(), equipper.getWorld().dropItemNaturally(toEquip.getBukkitEntity().getLocation(), trait.get(i));
trait.get(i));
trait.set(i, null); trait.set(i, null);
} }
} }

View File

@ -26,8 +26,8 @@ public class SheepEquipper implements Equipper {
DyeColor color = DyeColor.getByData((byte) (15 - hand.getData().getData())); DyeColor color = DyeColor.getByData((byte) (15 - hand.getData().getData()));
toEquip.getTrait(WoolColor.class).setColor(color); toEquip.getTrait(WoolColor.class).setColor(color);
Messaging.sendTr(equipper, Messages.EQUIPMENT_EDITOR_SHEEP_COLOURED, toEquip.getName(), color Messaging.sendTr(equipper, Messages.EQUIPMENT_EDITOR_SHEEP_COLOURED, toEquip.getName(), color.name()
.name().toLowerCase().replace("_", " ")); .toLowerCase().replace("_", " "));
hand.setAmount(hand.getAmount() - 1); hand.setAmount(hand.getAmount() - 1);
} else { } else {

View File

@ -58,8 +58,7 @@ public class CitizensNPC extends AbstractNPC {
event.setCancelled(Setting.KEEP_CHUNKS_LOADED.asBoolean()); event.setCancelled(Setting.KEEP_CHUNKS_LOADED.asBoolean());
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
getBukkitEntity().getLocation().getChunk(); getBukkitEntity().getLocation().getChunk().load();
// ensure that we are in a loaded chunk.
return false; return false;
} }
boolean keepSelected = getTrait(Spawned.class).shouldSpawn(); boolean keepSelected = getTrait(Spawned.class).shouldSpawn();
@ -97,8 +96,8 @@ public class CitizensNPC extends AbstractNPC {
// Load traits // Load traits
String traitNames = root.getString("traitnames"); String traitNames = root.getString("traitnames");
Iterable<DataKey> keys = traitNames.isEmpty() ? root.getRelative("traits").getSubKeys() : Iterables Iterable<DataKey> keys = traitNames.isEmpty() ? root.getRelative("traits").getSubKeys() : Iterables.transform(
.transform(Splitter.on(',').split(traitNames), new Function<String, DataKey>() { Splitter.on(',').split(traitNames), new Function<String, DataKey>() {
@Override @Override
public DataKey apply(@Nullable String input) { public DataKey apply(@Nullable String input) {
return root.getRelative("traits." + input); return root.getRelative("traits." + input);
@ -196,8 +195,7 @@ public class CitizensNPC extends AbstractNPC {
entityController.spawn(at, this); entityController.spawn(at, this);
EntityLiving mcEntity = getHandle(); EntityLiving mcEntity = getHandle();
boolean couldSpawn = !Util.isLoaded(at) ? false : mcEntity.world.addEntity(mcEntity, boolean couldSpawn = !Util.isLoaded(at) ? false : mcEntity.world.addEntity(mcEntity, SpawnReason.CUSTOM);
SpawnReason.CUSTOM);
if (!couldSpawn) { if (!couldSpawn) {
// we need to wait for a chunk load before trying to spawn // we need to wait for a chunk load before trying to spawn
mcEntity = null; mcEntity = null;
@ -213,8 +211,7 @@ public class CitizensNPC extends AbstractNPC {
} }
NMS.setHeadYaw(mcEntity, at.getYaw()); NMS.setHeadYaw(mcEntity, at.getYaw());
getBukkitEntity().setMetadata(NPC_METADATA_MARKER, getBukkitEntity().setMetadata(NPC_METADATA_MARKER, new FixedMetadataValue(CitizensAPI.getPlugin(), true));
new FixedMetadataValue(CitizensAPI.getPlugin(), true));
// Set the spawned state // Set the spawned state
getTrait(CurrentLocation.class).setLocation(at); getTrait(CurrentLocation.class).setLocation(at);

View File

@ -38,8 +38,8 @@ import com.google.common.collect.Maps;
public class EntityControllers { public class EntityControllers {
private static final Map<EntityType, Class<? extends EntityController>> TYPES = Maps private static final Map<EntityType, Class<? extends EntityController>> TYPES = Maps.newEnumMap(EntityType.class);
.newEnumMap(EntityType.class);
public static EntityController createForType(EntityType type) { public static EntityController createForType(EntityType type) {
Class<? extends EntityController> controllerClass = TYPES.get(type); Class<? extends EntityController> controllerClass = TYPES.get(type);
if (controllerClass == null) if (controllerClass == null)

View File

@ -102,8 +102,7 @@ public class Template {
} }
} }
private static YamlStorage templates = new YamlStorage(new File(CitizensAPI.getDataFolder(), private static YamlStorage templates = new YamlStorage(new File(CitizensAPI.getDataFolder(), "templates.yml"));
"templates.yml"));
public static Template byName(String name) { public static Template byName(String name) {
if (!templates.getKey("").keyExists(name)) if (!templates.getKey("").keyExists(name))

View File

@ -31,8 +31,9 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
this.destination = dest; this.destination = dest;
this.npc = npc; this.npc = npc;
Location location = npc.getBukkitEntity().getEyeLocation(); Location location = npc.getBukkitEntity().getEyeLocation();
plan = ASTAR.runFully(new VectorGoal(dest), new VectorNode(location, new ChunkBlockSource(location, plan = ASTAR.runFully(new VectorGoal(dest),
params.range()), params.examiners()), (int) (params.range() * 10)); new VectorNode(location, new ChunkBlockSource(location, params.range()), params.examiners()),
(int) (params.range() * 10));
if (plan == null || plan.isComplete()) { if (plan == null || plan.isComplete()) {
setCancelReason(CancelReason.STUCK); setCancelReason(CancelReason.STUCK);
} else { } else {

View File

@ -23,10 +23,10 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
public class CitizensNavigator implements Navigator, Runnable { public class CitizensNavigator implements Navigator, Runnable {
private final NavigatorParameters defaultParams = new NavigatorParameters() private final NavigatorParameters defaultParams = new NavigatorParameters().baseSpeed(UNINITIALISED_SPEED)
.baseSpeed(UNINITIALISED_SPEED).range(Setting.DEFAULT_PATHFINDING_RANGE.asFloat()) .range(Setting.DEFAULT_PATHFINDING_RANGE.asFloat())
.stationaryTicks(Setting.DEFAULT_STATIONARY_TICKS.asInt()) .stationaryTicks(Setting.DEFAULT_STATIONARY_TICKS.asInt()).stuckAction(TeleportStuckAction.INSTANCE)
.stuckAction(TeleportStuckAction.INSTANCE).examiner(new MinecraftBlockExaminer()); .examiner(new MinecraftBlockExaminer());
private PathStrategy executing; private PathStrategy executing;
private int lastX, lastY, lastZ; private int lastX, lastY, lastZ;
private NavigatorParameters localParams = defaultParams; private NavigatorParameters localParams = defaultParams;
@ -82,15 +82,12 @@ public class CitizensNavigator implements Navigator, Runnable {
public void load(DataKey root) { public void load(DataKey root) {
defaultParams.baseSpeed((float) root.getDouble("speed", UNINITIALISED_SPEED)); defaultParams.baseSpeed((float) root.getDouble("speed", UNINITIALISED_SPEED));
defaultParams.range((float) root.getDouble("pathfindingrange", defaultParams.range((float) root.getDouble("pathfindingrange", Setting.DEFAULT_PATHFINDING_RANGE.asFloat()));
Setting.DEFAULT_PATHFINDING_RANGE.asFloat())); defaultParams.stationaryTicks(root.getInt("stationaryticks", Setting.DEFAULT_STATIONARY_TICKS.asInt()));
defaultParams
.stationaryTicks(root.getInt("stationaryticks", Setting.DEFAULT_STATIONARY_TICKS.asInt()));
defaultParams.speedModifier((float) root.getDouble("speedmodifier", 1F)); defaultParams.speedModifier((float) root.getDouble("speedmodifier", 1F));
if (root.keyExists("avoidwater")) if (root.keyExists("avoidwater"))
defaultParams.avoidWater(root.getBoolean("avoidwater")); defaultParams.avoidWater(root.getBoolean("avoidwater"));
if (!root.getBoolean("usedefaultstuckaction") if (!root.getBoolean("usedefaultstuckaction") && defaultParams.stuckAction() == TeleportStuckAction.INSTANCE)
&& defaultParams.stuckAction() == TeleportStuckAction.INSTANCE)
defaultParams.stuckAction(null); defaultParams.stuckAction(null);
} }

View File

@ -48,6 +48,7 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
return handle.getBukkitEntity().getLocation(HANDLE_LOCATION) return handle.getBukkitEntity().getLocation(HANDLE_LOCATION)
.distanceSquared(target.getBukkitEntity().getLocation(TARGET_LOCATION)); .distanceSquared(target.getBukkitEntity().getLocation(TARGET_LOCATION));
} }
@Override @Override
public CancelReason getCancelReason() { public CancelReason getCancelReason() {
return cancelReason; return cancelReason;

View File

@ -17,101 +17,120 @@ import net.citizensnpcs.util.Messaging;
public class Chat implements VocalChord { public class Chat implements VocalChord {
public final String VOCAL_CHORD_NAME = "chat"; public final String VOCAL_CHORD_NAME = "chat";
@Override @Override
public String getName() { public String getName() {
return VOCAL_CHORD_NAME; return VOCAL_CHORD_NAME;
} }
@Override @Override
public void talk(SpeechContext context) { public void talk(SpeechContext context) {
// Check valid talker
if (context.getTalker() == null) return;
NPC npc = CitizensAPI.getNPCRegistry().getNPC(context.getTalker().getEntity());
if (npc == null) return;
// If no recipients, chat to the world with CHAT_FORMAT and CHAT_RANGE settings
if (!context.hasRecipients()) {
String text = Setting.CHAT_FORMAT.asString().replace("<npc>", npc.getName()).replace("<text>", context.getMessage());
talkToBystanders(npc, text, context);
return;
}
// Assumed recipients at this point // Check valid talker
else if (context.size() <= 1) { // One recipient if (context.getTalker() == null)
String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("<npc>", npc.getName()).replace("<text>", context.getMessage()); return;
String targetName = ""; NPC npc = CitizensAPI.getNPCRegistry().getNPC(context.getTalker().getEntity());
// For each recipient if (npc == null)
for (Talkable entity : context) { return;
entity.talkTo(context, text, this);
targetName = entity.getName();
}
// Check if bystanders hear targeted chat
if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean()) return;
// Format message with config setting and send to bystanders
String bystanderText = Setting.CHAT_FORMAT_TO_BYSTANDERS.asString().replace("<npc>", npc.getName()).replace("<target>", targetName).replace("<text>", context.getMessage());
talkToBystanders(npc, bystanderText, context);
return;
}
else { // Multiple recipients // If no recipients, chat to the world with CHAT_FORMAT and CHAT_RANGE
String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("<npc>", npc.getName()).replace("<text>", context.getMessage()); // settings
List<String> targetNames = Collections.emptyList(); if (!context.hasRecipients()) {
// Talk to each recipient String text = Setting.CHAT_FORMAT.asString().replace("<npc>", npc.getName())
for (Talkable entity : context) { .replace("<text>", context.getMessage());
entity.talkTo(context, text, this); talkToBystanders(npc, text, context);
targetNames.add(entity.getName()); return;
} }
if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean()) return; // Assumed recipients at this point
String targets = ""; else if (context.size() <= 1) { // One recipient
int max = Setting.CHAT_MAX_NUMBER_OF_TARGETS.asInt(); String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("<npc>", npc.getName())
String[] format = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString().split("\\|"); .replace("<text>", context.getMessage());
if (format.length != 4) Messaging.log(Level.WARNING, "npc.chat.format.with-target-to-bystanders invalid!"); String targetName = "";
if (max == 1) { // For each recipient
targets = format[0].replace("<npc>", targetNames.get(0)) + format[3]; for (Talkable entity : context) {
} entity.talkTo(context, text, this);
else if (max == 2 || targetNames.size() == 2) { targetName = entity.getName();
if (targetNames.size() == 2) }
targets = format[0].replace("<npc>", targetNames.get(0)) + format[2].replace("<npc>", targetNames.get(1)); // Check if bystanders hear targeted chat
else if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean())
targets = format[0].replace("<npc>", targetNames.get(0)) + format[1].replace("<npc>", targetNames.get(1)) + format[3]; return;
} // Format message with config setting and send to bystanders
else if (max >= 3) { String bystanderText = Setting.CHAT_FORMAT_TO_BYSTANDERS.asString().replace("<npc>", npc.getName())
targets = format[0].replace("<npc>", targetNames.get(0)); .replace("<target>", targetName).replace("<text>", context.getMessage());
talkToBystanders(npc, bystanderText, context);
return;
}
int x = 1; else { // Multiple recipients
for (x = 1; x < max - 1; x++) { String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("<npc>", npc.getName())
if (targetNames.size() - 1 == x) break; .replace("<text>", context.getMessage());
targets = targets + format[1].replace("<npc>", targetNames.get(x)); List<String> targetNames = Collections.emptyList();
} // Talk to each recipient
if (targetNames.size() == max) for (Talkable entity : context) {
targets = targets + format[2].replace("<npc>", targetNames.get(x)); entity.talkTo(context, text, this);
else targets = targets + format[3]; targetNames.add(entity.getName());
} }
String bystanderText = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString().replace("<npc>", npc.getName()).replace("<targets>", targets).replace("<text>", context.getMessage());
talkToBystanders(npc, bystanderText, context);
}
}
private void talkToBystanders(NPC npc, String text, SpeechContext context) { if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean())
// Get list of nearby entities return;
List<Entity> bystanderEntities = npc.getBukkitEntity().getNearbyEntities(Setting.CHAT_RANGE.asDouble(), Setting.CHAT_RANGE.asDouble(), Setting.CHAT_RANGE.asDouble()); String targets = "";
for (Entity bystander : bystanderEntities) int max = Setting.CHAT_MAX_NUMBER_OF_TARGETS.asInt();
// Continue if a LivingEntity, which is compatible with TalkableEntity String[] format = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString().split("\\|");
if (bystander instanceof LivingEntity) { if (format.length != 4)
// Exclude targeted recipients Messaging.log(Level.WARNING, "npc.chat.format.with-target-to-bystanders invalid!");
if (context.hasRecipients()) { if (max == 1) {
for (Talkable target : context) targets = format[0].replace("<npc>", targetNames.get(0)) + format[3];
if (target.getEntity() == bystander) continue; } else if (max == 2 || targetNames.size() == 2) {
else new TalkableEntity((LivingEntity) bystander).talkNear(context, text, this); if (targetNames.size() == 2)
} else targets = format[0].replace("<npc>", targetNames.get(0))
// Found a nearby LivingEntity, make it Talkable and talkNear it + format[2].replace("<npc>", targetNames.get(1));
new TalkableEntity((LivingEntity) bystander).talkNear(context, text, this); else
} targets = format[0].replace("<npc>", targetNames.get(0))
} + format[1].replace("<npc>", targetNames.get(1)) + format[3];
} else if (max >= 3) {
targets = format[0].replace("<npc>", targetNames.get(0));
int x = 1;
for (x = 1; x < max - 1; x++) {
if (targetNames.size() - 1 == x)
break;
targets = targets + format[1].replace("<npc>", targetNames.get(x));
}
if (targetNames.size() == max)
targets = targets + format[2].replace("<npc>", targetNames.get(x));
else
targets = targets + format[3];
}
String bystanderText = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString()
.replace("<npc>", npc.getName()).replace("<targets>", targets)
.replace("<text>", context.getMessage());
talkToBystanders(npc, bystanderText, context);
}
}
private void talkToBystanders(NPC npc, String text, SpeechContext context) {
// Get list of nearby entities
List<Entity> bystanderEntities = npc.getBukkitEntity().getNearbyEntities(Setting.CHAT_RANGE.asDouble(),
Setting.CHAT_RANGE.asDouble(), Setting.CHAT_RANGE.asDouble());
for (Entity bystander : bystanderEntities)
// Continue if a LivingEntity, which is compatible with
// TalkableEntity
if (bystander instanceof LivingEntity) {
// Exclude targeted recipients
if (context.hasRecipients()) {
for (Talkable target : context)
if (target.getEntity() == bystander)
continue;
else
new TalkableEntity((LivingEntity) bystander).talkNear(context, text, this);
} else
// Found a nearby LivingEntity, make it Talkable and
// talkNear it
new TalkableEntity((LivingEntity) bystander).talkNear(context, text, this);
}
}
} }

View File

@ -14,66 +14,68 @@ import net.citizensnpcs.api.ai.speech.VocalChord;
public class CitizensSpeechFactory implements SpeechFactory { public class CitizensSpeechFactory implements SpeechFactory {
Map<String, Class<? extends VocalChord>> registered = new HashMap<String, Class <? extends VocalChord>>(); Map<String, Class<? extends VocalChord>> registered = new HashMap<String, Class<? extends VocalChord>>();
@Override
public VocalChord getVocalChord(Class<? extends VocalChord> clazz) {
// Return a new instance of the VocalChord specified
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override @Override
public VocalChord getVocalChord(String name) { public VocalChord getVocalChord(Class<? extends VocalChord> clazz) {
// Check if VocalChord name is a registered type // Return a new instance of the VocalChord specified
if (isRegistered(name)) try {
// Return a new instance of the VocalChord specified return clazz.newInstance();
try { } catch (InstantiationException e) {
return registered.get(name.toLowerCase()).newInstance(); e.printStackTrace();
} catch (InstantiationException e) { } catch (IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} catch (IllegalAccessException e) { }
e.printStackTrace(); return null;
} }
return null;
}
@Override @Override
public String getVocalChordName(Class<? extends VocalChord> clazz) { public VocalChord getVocalChord(String name) {
// Get the name of a VocalChord class that has been registered // Check if VocalChord name is a registered type
for (Entry<String, Class<? extends VocalChord>> vocalChord : registered.entrySet()) if (isRegistered(name))
if (vocalChord.getValue() == clazz) return vocalChord.getKey(); // Return a new instance of the VocalChord specified
try {
return null; return registered.get(name.toLowerCase()).newInstance();
} } catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override @Override
public boolean isRegistered(String name) { public String getVocalChordName(Class<? extends VocalChord> clazz) {
if (registered.containsKey(name.toLowerCase())) return true; // Get the name of a VocalChord class that has been registered
else return false; for (Entry<String, Class<? extends VocalChord>> vocalChord : registered.entrySet())
} if (vocalChord.getValue() == clazz)
return vocalChord.getKey();
@Override return null;
public void register(Class<? extends VocalChord> clazz, String name) { }
@Override
public boolean isRegistered(String name) {
if (registered.containsKey(name.toLowerCase()))
return true;
else
return false;
}
@Override
public Talkable newTalkableEntity(LivingEntity entity) {
if (entity == null)
return null;
return new TalkableEntity(entity);
}
@Override
public void register(Class<? extends VocalChord> clazz, String name) {
Preconditions.checkNotNull(name, "info cannot be null"); Preconditions.checkNotNull(name, "info cannot be null");
Preconditions.checkNotNull(clazz, "vocalchord cannot be null"); Preconditions.checkNotNull(clazz, "vocalchord cannot be null");
if (registered.containsKey(name.toLowerCase())) if (registered.containsKey(name.toLowerCase()))
throw new IllegalArgumentException("vocalchord name already registered"); throw new IllegalArgumentException("vocalchord name already registered");
registered.put(name.toLowerCase(), clazz); registered.put(name.toLowerCase(), clazz);
} }
@Override
public Talkable newTalkableEntity(LivingEntity entity) {
if (entity == null) return null;
return new TalkableEntity(entity);
}
} }

View File

@ -15,77 +15,82 @@ import org.bukkit.entity.Player;
public class TalkableEntity implements Talkable { public class TalkableEntity implements Talkable {
LivingEntity entity; LivingEntity entity;
public TalkableEntity(LivingEntity entity) {
this.entity = entity;
}
public TalkableEntity(NPC npc) {
entity = npc.getBukkitEntity();
}
public TalkableEntity(Player player) {
entity = (LivingEntity) player;
}
/**
* Used to compare a LivingEntity to this TalkableEntity
*
* @return
* 0 if the Entities are the same, 1 if they are not, -1 if
* the object compared is not a valid LivingEntity
*/
@Override
public int compareTo(Object o) {
// If not living entity, return -1
if (!(o instanceof LivingEntity)) return -1;
// If NPC and matches, return 0
else if (CitizensAPI.getNPCRegistry().isNPC((LivingEntity) o)
&& CitizensAPI.getNPCRegistry().isNPC((LivingEntity) entity)
&& CitizensAPI.getNPCRegistry().getNPC((LivingEntity) o).getId() ==
CitizensAPI.getNPCRegistry().getNPC((LivingEntity) entity).getId())
return 0;
else if ((LivingEntity) o == entity) return 0;
// Not a match, return 1
else return 1;
}
@Override public TalkableEntity(LivingEntity entity) {
public LivingEntity getEntity() { this.entity = entity;
return entity; }
}
@Override
public String getName() {
if (CitizensAPI.getNPCRegistry().isNPC(entity))
return CitizensAPI.getNPCRegistry().getNPC(entity).getName();
else if (entity instanceof Player)
return ((Player) entity).getName();
else
return entity.getType().name().replace("_", " ");
}
private void talk(String message) {
if (entity instanceof Player
&& !CitizensAPI.getNPCRegistry().isNPC(entity))
Messaging.send((Player) entity, message);
}
@Override
public void talkNear(SpeechContext context, String text, VocalChord vocalChord) {
SpeechBystanderEvent event = new SpeechBystanderEvent(this, context, text, vocalChord);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) return;
else talk(event.getMessage());
}
@Override public TalkableEntity(NPC npc) {
public void talkTo(SpeechContext context, String text, VocalChord vocalChord) { entity = npc.getBukkitEntity();
SpeechTargetedEvent event = new SpeechTargetedEvent(this, context, text, vocalChord); }
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) return; public TalkableEntity(Player player) {
else talk(event.getMessage()); entity = (LivingEntity) player;
} }
/**
* Used to compare a LivingEntity to this TalkableEntity
*
* @return 0 if the Entities are the same, 1 if they are not, -1 if the
* object compared is not a valid LivingEntity
*/
@Override
public int compareTo(Object o) {
// If not living entity, return -1
if (!(o instanceof LivingEntity))
return -1;
// If NPC and matches, return 0
else if (CitizensAPI.getNPCRegistry().isNPC((LivingEntity) o)
&& CitizensAPI.getNPCRegistry().isNPC((LivingEntity) entity)
&& CitizensAPI.getNPCRegistry().getNPC((LivingEntity) o).getId() == CitizensAPI.getNPCRegistry()
.getNPC((LivingEntity) entity).getId())
return 0;
else if ((LivingEntity) o == entity)
return 0;
// Not a match, return 1
else
return 1;
}
@Override
public LivingEntity getEntity() {
return entity;
}
@Override
public String getName() {
if (CitizensAPI.getNPCRegistry().isNPC(entity))
return CitizensAPI.getNPCRegistry().getNPC(entity).getName();
else if (entity instanceof Player)
return ((Player) entity).getName();
else
return entity.getType().name().replace("_", " ");
}
private void talk(String message) {
if (entity instanceof Player && !CitizensAPI.getNPCRegistry().isNPC(entity))
Messaging.send((Player) entity, message);
}
@Override
public void talkNear(SpeechContext context, String text, VocalChord vocalChord) {
SpeechBystanderEvent event = new SpeechBystanderEvent(this, context, text, vocalChord);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled())
return;
else
talk(event.getMessage());
}
@Override
public void talkTo(SpeechContext context, String text, VocalChord vocalChord) {
SpeechTargetedEvent event = new SpeechTargetedEvent(this, context, text, vocalChord);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled())
return;
else
talk(event.getMessage());
}
} }

View File

@ -189,8 +189,7 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder {
net.minecraft.server.v1_4_6.ItemStack previous = previousEquipment[i]; net.minecraft.server.v1_4_6.ItemStack previous = previousEquipment[i];
net.minecraft.server.v1_4_6.ItemStack current = getEquipment(i); net.minecraft.server.v1_4_6.ItemStack current = getEquipment(i);
if (previous != current) { if (previous != current) {
NMS.sendPacketNearby(getBukkitEntity().getLocation(), new Packet5EntityEquipment(id, i, NMS.sendPacketNearby(getBukkitEntity().getLocation(), new Packet5EntityEquipment(id, i, current));
current));
previousEquipment[i] = current; previousEquipment[i] = current;
} }
} }

View File

@ -19,8 +19,8 @@ public class HumanController extends AbstractEntityController {
@Override @Override
protected LivingEntity createEntity(final Location at, final NPC npc) { protected LivingEntity createEntity(final Location at, final NPC npc) {
WorldServer ws = ((CraftWorld) at.getWorld()).getHandle(); WorldServer ws = ((CraftWorld) at.getWorld()).getHandle();
final EntityHumanNPC handle = new EntityHumanNPC(ws.getServer().getServer(), ws, final EntityHumanNPC handle = new EntityHumanNPC(ws.getServer().getServer(), ws, StringHelper.parseColors(npc
StringHelper.parseColors(npc.getFullName()), new PlayerInteractManager(ws), npc); .getFullName()), new PlayerInteractManager(ws), npc);
handle.getBukkitEntity().teleport(at); handle.getBukkitEntity().teleport(at);
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override @Override

View File

@ -18,8 +18,7 @@ import net.minecraft.server.v1_4_6.Packet3Chat;
import net.minecraft.server.v1_4_6.Packet51MapChunk; import net.minecraft.server.v1_4_6.Packet51MapChunk;
public class EmptyNetHandler extends PlayerConnection { public class EmptyNetHandler extends PlayerConnection {
public EmptyNetHandler(MinecraftServer minecraftServer, NetworkManager networkManager, public EmptyNetHandler(MinecraftServer minecraftServer, NetworkManager networkManager, EntityPlayer entityPlayer) {
EntityPlayer entityPlayer) {
super(minecraftServer, networkManager, entityPlayer); super(minecraftServer, networkManager, entityPlayer);
} }

View File

@ -11,8 +11,7 @@ import net.minecraft.server.v1_4_6.Packet;
public class EmptyNetworkManager extends NetworkManager { public class EmptyNetworkManager extends NetworkManager {
public EmptyNetworkManager(Socket socket, String string, Connection conn, PrivateKey key) public EmptyNetworkManager(Socket socket, String string, Connection conn, PrivateKey key) throws IOException {
throws IOException {
super(socket, string, conn, key); super(socket, string, conn, key);
NMS.stopNetworkThreads(this); NMS.stopNetworkThreads(this);

View File

@ -202,16 +202,6 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
} }
} }
public static interface MovementController {
void leftClick(PlayerInteractEvent event);
void rightClick(PlayerInteractEvent event);
void rightClickEntity(NPCRightClickEvent event);
void run(Player rider);
}
public class GroundController implements MovementController { public class GroundController implements MovementController {
private void jump() { private void jump() {
boolean allowed = getHandle().onGround; boolean allowed = getHandle().onGround;
@ -249,6 +239,16 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
private static final float JUMP_VELOCITY = 0.6F; private static final float JUMP_VELOCITY = 0.6F;
} }
public static interface MovementController {
void leftClick(PlayerInteractEvent event);
void rightClick(PlayerInteractEvent event);
void rightClickEntity(NPCRightClickEvent event);
void run(Player rider);
}
private static final Map<EntityType, Class<? extends MovementController>> controllerTypes = Maps private static final Map<EntityType, Class<? extends MovementController>> controllerTypes = Maps
.newEnumMap(EntityType.class); .newEnumMap(EntityType.class);

View File

@ -53,8 +53,7 @@ public class Poses extends Trait {
paginator.addLine("<e>Key: <a>ID <b>Name <c>Pitch/Yaw"); paginator.addLine("<e>Key: <a>ID <b>Name <c>Pitch/Yaw");
int i = 0; int i = 0;
for (Pose pose : poses.values()) { for (Pose pose : poses.values()) {
String line = "<a>" + i + "<b> " + pose.getName() + "<c> " + pose.getPitch() + "/" String line = "<a>" + i + "<b> " + pose.getName() + "<c> " + pose.getPitch() + "/" + pose.getYaw();
+ pose.getYaw();
paginator.addLine(line); paginator.addLine(line);
i++; i++;
} }

View File

@ -11,13 +11,11 @@ import java.util.concurrent.TimeUnit;
import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.speech.SpeechContext; import net.citizensnpcs.api.ai.speech.SpeechContext;
import net.citizensnpcs.api.ai.speech.Talkable;
import net.citizensnpcs.api.event.NPCRightClickEvent; import net.citizensnpcs.api.event.NPCRightClickEvent;
import net.citizensnpcs.api.exception.NPCLoadException; import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.editor.Editor; import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.npc.ai.speech.TalkableEntity;
import net.citizensnpcs.trait.Toggleable; import net.citizensnpcs.trait.Toggleable;
import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging; import net.citizensnpcs.util.Messaging;
@ -65,10 +63,9 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
} }
public Editor getEditor(final Player player) { public Editor getEditor(final Player player) {
final Conversation conversation = new ConversationFactory(plugin) final Conversation conversation = new ConversationFactory(plugin).addConversationAbandonedListener(this)
.addConversationAbandonedListener(this).withLocalEcho(false).withEscapeSequence("/npc text") .withLocalEcho(false).withEscapeSequence("/npc text").withEscapeSequence("exit").withModality(false)
.withEscapeSequence("exit").withModality(false).withFirstPrompt(new TextStartPrompt(this)) .withFirstPrompt(new TextStartPrompt(this)).buildConversation(player);
.buildConversation(player);
return new Editor() { return new Editor() {
@Override @Override
@ -111,8 +108,7 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
public void onRightClick(NPCRightClickEvent event) { public void onRightClick(NPCRightClickEvent event) {
if (!event.getNPC().equals(npc)) if (!event.getNPC().equals(npc))
return; return;
String localPattern = itemInHandPattern.equals("default") ? Setting.TALK_ITEM.asString() String localPattern = itemInHandPattern.equals("default") ? Setting.TALK_ITEM.asString() : itemInHandPattern;
: itemInHandPattern;
if (Util.matchesItemInHand(event.getClicker(), localPattern) && !shouldTalkClose()) if (Util.matchesItemInHand(event.getClicker(), localPattern) && !shouldTalkClose())
sendText(event.getClicker()); sendText(event.getClicker());
} }
@ -192,9 +188,10 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
currentIndex = 0; currentIndex = 0;
index = currentIndex++; index = currentIndex++;
} }
npc.getDefaultSpeechController().speak(new SpeechContext(text.get(index), player)); npc.getDefaultSpeechController().speak(new SpeechContext(text.get(index), player));
// Messaging.sendWithNPC(player, Setting.CHAT_PREFIX.asString() + text.get(index), npc); // Messaging.sendWithNPC(player, Setting.CHAT_PREFIX.asString() +
// text.get(index), npc);
return true; return true;
} }

View File

@ -20,8 +20,7 @@ public class TextEditPrompt extends StringPrompt {
public Prompt acceptInput(ConversationContext context, String input) { public Prompt acceptInput(ConversationContext context, String input) {
int index = (Integer) context.getSessionData("index"); int index = (Integer) context.getSessionData("index");
text.edit(index, input); text.edit(index, input);
Messaging Messaging.sendTr((CommandSender) context.getForWhom(), Messages.TEXT_EDITOR_EDITED_TEXT, index, input);
.sendTr((CommandSender) context.getForWhom(), Messages.TEXT_EDITOR_EDITED_TEXT, index, input);
return new TextStartPrompt(text); return new TextStartPrompt(text);
} }

View File

@ -30,8 +30,7 @@ public class TextStartPrompt extends StringPrompt {
else if (input.equalsIgnoreCase("random")) else if (input.equalsIgnoreCase("random"))
Messaging.sendTr(sender, Messages.TEXT_EDITOR_RANDOM_TALKER_SET, text.toggleRandomTalker()); Messaging.sendTr(sender, Messages.TEXT_EDITOR_RANDOM_TALKER_SET, text.toggleRandomTalker());
else if (input.equalsIgnoreCase("realistic looking")) else if (input.equalsIgnoreCase("realistic looking"))
Messaging.sendTr(sender, Messages.TEXT_EDITOR_REALISTIC_LOOKING_SET, Messaging.sendTr(sender, Messages.TEXT_EDITOR_REALISTIC_LOOKING_SET, text.toggleRealisticLooking());
text.toggleRealisticLooking());
else if (input.equalsIgnoreCase("close") || input.equalsIgnoreCase("talk-close")) else if (input.equalsIgnoreCase("close") || input.equalsIgnoreCase("talk-close"))
Messaging.sendTr(sender, Messages.TEXT_EDITOR_CLOSE_TALKER_SET, text.toggle()); Messaging.sendTr(sender, Messages.TEXT_EDITOR_CLOSE_TALKER_SET, text.toggle());
else if (input.equalsIgnoreCase("range")) { else if (input.equalsIgnoreCase("range")) {

View File

@ -267,8 +267,8 @@ public class LinearWaypointProvider implements WaypointProvider {
if (!event.getRightClicked().hasMetadata("waypointindex")) if (!event.getRightClicked().hasMetadata("waypointindex"))
return; return;
editingSlot = event.getRightClicked().getMetadata("waypointindex").get(0).asInt(); editingSlot = event.getRightClicked().getMetadata("waypointindex").get(0).asInt();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_EDIT_SLOT_SET, editingSlot, Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_EDIT_SLOT_SET, editingSlot, formatLoc(waypoints
formatLoc(waypoints.get(editingSlot).getLocation())); .get(editingSlot).getLocation()));
} }
@EventHandler @EventHandler
@ -288,8 +288,8 @@ public class LinearWaypointProvider implements WaypointProvider {
editingSlot += diff > 0 ? 1 : -1; editingSlot += diff > 0 ? 1 : -1;
} }
normaliseEditingSlot(); normaliseEditingSlot();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_EDIT_SLOT_SET, editingSlot, Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_EDIT_SLOT_SET, editingSlot, formatLoc(waypoints
formatLoc(waypoints.get(editingSlot).getLocation())); .get(editingSlot).getLocation()));
} }
private void onWaypointsModified() { private void onWaypointsModified() {
@ -339,8 +339,8 @@ public class LinearWaypointProvider implements WaypointProvider {
} }
private Iterator<Waypoint> getNewIterator() { private Iterator<Waypoint> getNewIterator() {
LinearWaypointsCompleteEvent event = new LinearWaypointsCompleteEvent( LinearWaypointsCompleteEvent event = new LinearWaypointsCompleteEvent(LinearWaypointProvider.this,
LinearWaypointProvider.this, waypoints.iterator()); waypoints.iterator());
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
Iterator<Waypoint> next = event.getNextWaypoints(); Iterator<Waypoint> next = event.getNextWaypoints();
return next; return next;

View File

@ -23,8 +23,7 @@ public class AnimationTriggerPrompt extends StringPrompt implements WaypointTrig
if (input.equalsIgnoreCase("back")) if (input.equalsIgnoreCase("back"))
return (Prompt) context.getSessionData("previous"); return (Prompt) context.getSessionData("previous");
if (input.equalsIgnoreCase("finish")) { if (input.equalsIgnoreCase("finish")) {
context.setSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY, context.setSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY, new AnimationTrigger(animations));
new AnimationTrigger(animations));
return (Prompt) context.getSessionData(WaypointTriggerPrompt.RETURN_PROMPT_KEY); return (Prompt) context.getSessionData(WaypointTriggerPrompt.RETURN_PROMPT_KEY);
} }
PlayerAnimation animation = Util.matchEnum(PlayerAnimation.values(), input); PlayerAnimation animation = Util.matchEnum(PlayerAnimation.values(), input);
@ -36,8 +35,7 @@ public class AnimationTriggerPrompt extends StringPrompt implements WaypointTrig
@Override @Override
public String getPromptText(ConversationContext context) { public String getPromptText(ConversationContext context) {
Messaging.sendTr((CommandSender) context.getForWhom(), Messages.ANIMATION_TRIGGER_PROMPT, Messaging.sendTr((CommandSender) context.getForWhom(), Messages.ANIMATION_TRIGGER_PROMPT, getValidAnimations());
getValidAnimations());
return ""; return "";
} }

View File

@ -27,8 +27,7 @@ public class ChatTriggerPrompt extends StringPrompt implements WaypointTriggerPr
Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messaging.sendErrorTr((CommandSender) context.getForWhom(),
Messages.WAYPOINT_TRIGGER_CHAT_INVALID_RADIUS); Messages.WAYPOINT_TRIGGER_CHAT_INVALID_RADIUS);
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_CHAT_NO_RADIUS);
Messages.WAYPOINT_TRIGGER_CHAT_NO_RADIUS);
} }
return this; return this;
} }

View File

@ -18,8 +18,8 @@ public class TeleportTrigger implements WaypointTrigger {
@Override @Override
public String description() { public String description() {
return String.format("Teleport to [%s, %d, %d, %d]", location.getWorld().getName(), return String.format("Teleport to [%s, %d, %d, %d]", location.getWorld().getName(), location.getBlockX(),
location.getBlockX(), location.getBlockY(), location.getBlockZ()); location.getBlockY(), location.getBlockZ());
} }
@Override @Override

View File

@ -29,8 +29,7 @@ public class TeleportTriggerPrompt extends RegexPrompt implements WaypointTrigge
return (Prompt) context.getSessionData("previous"); return (Prompt) context.getSessionData("previous");
if (input.equalsIgnoreCase("here")) { if (input.equalsIgnoreCase("here")) {
Player player = (Player) context.getForWhom(); Player player = (Player) context.getForWhom();
context.setSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY, context.setSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY, new TeleportTrigger(player.getLocation()));
new TeleportTrigger(player.getLocation()));
return (Prompt) context.getSessionData(WaypointTriggerPrompt.RETURN_PROMPT_KEY); return (Prompt) context.getSessionData(WaypointTriggerPrompt.RETURN_PROMPT_KEY);
} }
String[] parts = Iterables.toArray(Splitter.on(':').split(input), String.class); String[] parts = Iterables.toArray(Splitter.on(':').split(input), String.class);

View File

@ -35,23 +35,20 @@ public class TriggerAddPrompt extends StringPrompt {
@Override @Override
public String getPromptText(ConversationContext context) { public String getPromptText(ConversationContext context) {
WaypointTrigger returned = (WaypointTrigger) context WaypointTrigger returned = (WaypointTrigger) context.getSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY);
.getSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY);
if (returned != null) { if (returned != null) {
if (editor.getCurrentWaypoint() != null) { if (editor.getCurrentWaypoint() != null) {
editor.getCurrentWaypoint().addTrigger(returned); editor.getCurrentWaypoint().addTrigger(returned);
context.setSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY, null); context.setSessionData(WaypointTriggerPrompt.CREATED_TRIGGER_KEY, null);
Messaging.sendTr((CommandSender) context.getForWhom(), Messaging.sendTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_ADDED_SUCCESSFULLY,
Messages.WAYPOINT_TRIGGER_ADDED_SUCCESSFULLY, returned.description()); returned.description());
} else } else
Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_EDITOR_INACTIVE);
Messages.WAYPOINT_TRIGGER_EDITOR_INACTIVE);
} }
if (context.getSessionData("said") == Boolean.TRUE) if (context.getSessionData("said") == Boolean.TRUE)
return ""; return "";
context.setSessionData("said", true); context.setSessionData("said", true);
context.setSessionData(WaypointTriggerPrompt.RETURN_PROMPT_KEY, this); context.setSessionData(WaypointTriggerPrompt.RETURN_PROMPT_KEY, this);
return Messaging.tr(Messages.WAYPOINT_TRIGGER_ADD_PROMPT, return Messaging.tr(Messages.WAYPOINT_TRIGGER_ADD_PROMPT, WaypointTriggerRegistry.describeValidTriggerNames());
WaypointTriggerRegistry.describeValidTriggerNames());
} }
} }

View File

@ -53,9 +53,9 @@ public class TriggerEditPrompt extends StringPrompt {
} }
public static Conversation start(Player player, WaypointEditor editor) { public static Conversation start(Player player, WaypointEditor editor) {
final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()) final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()).withLocalEcho(false)
.withLocalEcho(false).withEscapeSequence("exit").withEscapeSequence("/npc path") .withEscapeSequence("exit").withEscapeSequence("/npc path").withModality(false)
.withModality(false).withFirstPrompt(new TriggerEditPrompt(editor)).buildConversation(player); .withFirstPrompt(new TriggerEditPrompt(editor)).buildConversation(player);
conversation.begin(); conversation.begin();
return conversation; return conversation;
} }

View File

@ -25,16 +25,15 @@ public class TriggerRemovePrompt extends StringPrompt {
return (Prompt) context.getSessionData("previous"); return (Prompt) context.getSessionData("previous");
} }
if (editor.getCurrentWaypoint() == null) { if (editor.getCurrentWaypoint() == null) {
Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_EDITOR_INACTIVE);
Messages.WAYPOINT_TRIGGER_EDITOR_INACTIVE);
return this; return this;
} }
int index = 0; int index = 0;
try { try {
index = Math.max(0, Integer.parseInt(input) - 1); index = Math.max(0, Integer.parseInt(input) - 1);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messaging
Messages.WAYPOINT_TRIGGER_REMOVE_INVALID_NUMBER); .sendErrorTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_REMOVE_INVALID_NUMBER);
return this; return this;
} }
List<WaypointTrigger> triggers = editor.getCurrentWaypoint().getTriggers(); List<WaypointTrigger> triggers = editor.getCurrentWaypoint().getTriggers();
@ -43,8 +42,7 @@ public class TriggerRemovePrompt extends StringPrompt {
Messages.WAYPOINT_TRIGGER_REMOVE_INDEX_OUT_OF_RANGE, triggers.size()); Messages.WAYPOINT_TRIGGER_REMOVE_INDEX_OUT_OF_RANGE, triggers.size());
} else { } else {
triggers.remove(index); triggers.remove(index);
Messaging.sendTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_REMOVE_REMOVED, Messaging.sendTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_REMOVE_REMOVED, index + 1);
index + 1);
} }
return this; return this;
} }
@ -52,8 +50,7 @@ public class TriggerRemovePrompt extends StringPrompt {
@Override @Override
public String getPromptText(ConversationContext context) { public String getPromptText(ConversationContext context) {
if (editor.getCurrentWaypoint() == null) { if (editor.getCurrentWaypoint() == null) {
Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_EDITOR_INACTIVE);
Messages.WAYPOINT_TRIGGER_EDITOR_INACTIVE);
return ""; return "";
} }
if (context.getSessionData("said") == Boolean.TRUE) if (context.getSessionData("said") == Boolean.TRUE)
@ -64,8 +61,7 @@ public class TriggerRemovePrompt extends StringPrompt {
for (WaypointTrigger trigger : editor.getCurrentWaypoint().getTriggers()) { for (WaypointTrigger trigger : editor.getCurrentWaypoint().getTriggers()) {
root += String.format("<br> %d. " + trigger.description(), i++); root += String.format("<br> %d. " + trigger.description(), i++);
} }
Messaging Messaging.sendTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_REMOVE_PROMPT + root);
.sendTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_REMOVE_PROMPT + root);
return ""; return "";
} }
} }

View File

@ -44,14 +44,14 @@ public class Anchor {
} }
public String stringValue() { public String stringValue() {
return name + ";" + location.getWorld().getName() + ";" + location.getX() + ";" + location.getY() return name + ";" + location.getWorld().getName() + ";" + location.getX() + ";" + location.getY() + ";"
+ ";" + location.getZ(); + location.getZ();
} }
@Override @Override
public String toString() { public String toString() {
return "Name: " + name + " World: " + location.getWorld().getName() + " Location: " return "Name: " + name + " World: " + location.getWorld().getName() + " Location: " + location.getBlockX()
+ location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ(); + "," + location.getBlockY() + "," + location.getBlockZ();
} }
} }

View File

@ -50,38 +50,12 @@ public class NMS {
// util class // util class
} }
public static void sendToOnline(Packet... packets) {
Validate.notNull(packets, "packets cannot be null");
for (Player player : Bukkit.getOnlinePlayers()) {
if (player == null || !player.isOnline())
continue;
for (Packet packet : packets) {
sendPacket(player, packet);
}
}
}
public static void sendPacketNearby(Location location, Packet packet, double radius) {
radius *= radius;
final org.bukkit.World world = location.getWorld();
for (Player ply : Bukkit.getServer().getOnlinePlayers()) {
if (ply == null || world != ply.getWorld()) {
continue;
}
if (location.distanceSquared(ply.getLocation()) > radius) {
continue;
}
sendPacket(ply, packet);
}
}
public static void sendPacketNearby(Location location, Packet packet) {
NMS.sendPacketNearby(location, packet, 64);
}
private static final float DEFAULT_SPEED = 0.4F; private static final float DEFAULT_SPEED = 0.4F;
private static Map<Class<?>, Integer> ENTITY_CLASS_TO_INT; private static Map<Class<?>, Integer> ENTITY_CLASS_TO_INT;
private static final Map<Class<?>, Constructor<?>> ENTITY_CONSTRUCTOR_CACHE = new WeakHashMap<Class<?>, Constructor<?>>(); private static final Map<Class<?>, Constructor<?>> ENTITY_CONSTRUCTOR_CACHE = new WeakHashMap<Class<?>, Constructor<?>>();
private static Map<Integer, Class<?>> ENTITY_INT_TO_CLASS; private static Map<Integer, Class<?>> ENTITY_INT_TO_CLASS;
private static Field GOAL_FIELD; private static Field GOAL_FIELD;
private static Field LAND_SPEED_MODIFIER_FIELD; private static Field LAND_SPEED_MODIFIER_FIELD;
@ -92,9 +66,7 @@ public class NMS {
private static Set<Integer> SLAB_MATERIALS = Sets.newHashSet(); private static Set<Integer> SLAB_MATERIALS = Sets.newHashSet();
private static Field SPEED_FIELD; private static Field SPEED_FIELD;
private static Set<Integer> STAIR_MATERIALS = Sets.newHashSet(); private static Set<Integer> STAIR_MATERIALS = Sets.newHashSet();
private static Field THREAD_STOPPER; private static Field THREAD_STOPPER;
public static void addOrRemoveFromPlayerList(LivingEntity bukkitEntity, boolean remove) { public static void addOrRemoveFromPlayerList(LivingEntity bukkitEntity, boolean remove) {
if (bukkitEntity == null) if (bukkitEntity == null)
return; return;
@ -107,7 +79,6 @@ public class NMS {
handle.world.players.add(handle); handle.world.players.add(handle);
} }
} }
public static void attack(EntityLiving handle, EntityLiving target) { public static void attack(EntityLiving handle, EntityLiving target) {
int damage = handle instanceof EntityMonster ? ((EntityMonster) handle).c((Entity) target) : 2; int damage = handle instanceof EntityMonster ? ((EntityMonster) handle).c((Entity) target) : 2;
@ -157,8 +128,8 @@ public class NMS {
} }
} }
private static Constructor<?> getCustomEntityConstructor(Class<?> clazz, EntityType type) private static Constructor<?> getCustomEntityConstructor(Class<?> clazz, EntityType type) throws SecurityException,
throws SecurityException, NoSuchMethodException { NoSuchMethodException {
Constructor<?> constructor = ENTITY_CONSTRUCTOR_CACHE.get(clazz); Constructor<?> constructor = ENTITY_CONSTRUCTOR_CACHE.get(clazz);
if (constructor == null) { if (constructor == null) {
constructor = clazz.getConstructor(World.class); constructor = clazz.getConstructor(World.class);
@ -241,6 +212,35 @@ public class NMS {
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
} }
public static void sendPacketNearby(Location location, Packet packet) {
NMS.sendPacketNearby(location, packet, 64);
}
public static void sendPacketNearby(Location location, Packet packet, double radius) {
radius *= radius;
final org.bukkit.World world = location.getWorld();
for (Player ply : Bukkit.getServer().getOnlinePlayers()) {
if (ply == null || world != ply.getWorld()) {
continue;
}
if (location.distanceSquared(ply.getLocation()) > radius) {
continue;
}
sendPacket(ply, packet);
}
}
public static void sendToOnline(Packet... packets) {
Validate.notNull(packets, "packets cannot be null");
for (Player player : Bukkit.getOnlinePlayers()) {
if (player == null || !player.isOnline())
continue;
for (Packet packet : packets) {
sendPacket(player, packet);
}
}
}
public static void setDestination(LivingEntity bukkitEntity, double x, double y, double z, float speed) { public static void setDestination(LivingEntity bukkitEntity, double x, double y, double z, float speed) {
((CraftLivingEntity) bukkitEntity).getHandle().getControllerMove().a(x, y, z, speed); ((CraftLivingEntity) bukkitEntity).getHandle().getControllerMove().a(x, y, z, speed);
} }

View File

@ -20,8 +20,7 @@ public class Paginator {
} }
public boolean sendPage(CommandSender sender, int page) { public boolean sendPage(CommandSender sender, int page) {
int pages = (int) ((lines.size() / LINES_PER_PAGE == 0) ? 1 : Math.ceil((double) lines.size() int pages = (int) ((lines.size() / LINES_PER_PAGE == 0) ? 1 : Math.ceil((double) lines.size() / LINES_PER_PAGE));
/ LINES_PER_PAGE));
if (page < 0 || page > pages) if (page < 0 || page > pages)
return false; return false;

View File

@ -33,8 +33,8 @@ public enum PlayerAnimation {
SLEEP { SLEEP {
@Override @Override
protected void playAnimation(EntityPlayer player, int radius) { protected void playAnimation(EntityPlayer player, int radius) {
Packet17EntityLocationAction packet = new Packet17EntityLocationAction(player, 0, Packet17EntityLocationAction packet = new Packet17EntityLocationAction(player, 0, (int) player.locX,
(int) player.locX, (int) player.locY, (int) player.locZ); (int) player.locY, (int) player.locZ);
sendPacketNearby(packet, player, radius); sendPacketNearby(packet, player, radius);
} }
}, },
@ -42,8 +42,7 @@ public enum PlayerAnimation {
@Override @Override
protected void playAnimation(EntityPlayer player, int radius) { protected void playAnimation(EntityPlayer player, int radius) {
player.getBukkitEntity().setSneaking(true); player.getBukkitEntity().setSneaking(true);
sendPacketNearby(new Packet40EntityMetadata(player.id, player.getDataWatcher(), true), player, sendPacketNearby(new Packet40EntityMetadata(player.id, player.getDataWatcher(), true), player, radius);
radius);
} }
}, },
STOP_SITTING { STOP_SITTING {
@ -63,8 +62,7 @@ public enum PlayerAnimation {
@Override @Override
protected void playAnimation(EntityPlayer player, int radius) { protected void playAnimation(EntityPlayer player, int radius) {
player.getBukkitEntity().setSneaking(false); player.getBukkitEntity().setSneaking(false);
sendPacketNearby(new Packet40EntityMetadata(player.id, player.getDataWatcher(), true), player, sendPacketNearby(new Packet40EntityMetadata(player.id, player.getDataWatcher(), true), player, radius);
radius);
} }
}; };

View File

@ -93,7 +93,6 @@ public class StringHelper {
String colors = ""; String colors = "";
for (ChatColor color : ChatColor.values()) for (ChatColor color : ChatColor.values())
colors += color.getChar(); colors += color.getChar();
COLOR_MATCHER = Pattern.compile("\\<([COLORS])\\>".replace("COLORS", colors), COLOR_MATCHER = Pattern.compile("\\<([COLORS])\\>".replace("COLORS", colors), Pattern.CASE_INSENSITIVE);
Pattern.CASE_INSENSITIVE);
} }
} }

View File

@ -37,8 +37,8 @@ public class Translator {
this.resourceFile = resourceFile; this.resourceFile = resourceFile;
this.defaultLocale = locale; this.defaultLocale = locale;
try { try {
preferredBundle = ResourceBundle.getBundle(PREFIX, defaultLocale, new FileClassLoader( preferredBundle = ResourceBundle.getBundle(PREFIX, defaultLocale,
Translator.class.getClassLoader(), resourceFile)); new FileClassLoader(Translator.class.getClassLoader(), resourceFile));
} catch (MissingResourceException e) { } catch (MissingResourceException e) {
preferredBundle = getDefaultBundle(); preferredBundle = getDefaultBundle();
Messaging.log(translate(Messages.MISSING_TRANSLATIONS, locale)); Messaging.log(translate(Messages.MISSING_TRANSLATIONS, locale));
@ -53,8 +53,8 @@ public class Translator {
private ResourceBundle getBundle(Locale locale) { private ResourceBundle getBundle(Locale locale) {
try { try {
ResourceBundle bundle = ResourceBundle.getBundle(PREFIX, locale, new FileClassLoader( ResourceBundle bundle = ResourceBundle.getBundle(PREFIX, locale,
Translator.class.getClassLoader(), resourceFile)); new FileClassLoader(Translator.class.getClassLoader(), resourceFile));
return bundle == null ? preferredBundle : bundle; return bundle == null ? preferredBundle : bundle;
} catch (MissingResourceException e) { } catch (MissingResourceException e) {
return preferredBundle; return preferredBundle;
@ -275,8 +275,8 @@ public class Translator {
public static String translate(String key, Locale preferredLocale, Object... msg) { public static String translate(String key, Locale preferredLocale, Object... msg) {
if (instance == null) if (instance == null)
createInstance(); createInstance();
return StringHelper.parseColors(msg.length == 0 ? instance.translate(key, preferredLocale) : instance return StringHelper.parseColors(msg.length == 0 ? instance.translate(key, preferredLocale) : instance.format(
.format(key, preferredLocale, msg)); key, preferredLocale, msg));
} }
public static String translate(String key, Object... msg) { public static String translate(String key, Object... msg) {