diff --git a/src/main/java/net/citizensnpcs/EventListen.java b/src/main/java/net/citizensnpcs/EventListen.java index 3fdc59f60..886a029d2 100644 --- a/src/main/java/net/citizensnpcs/EventListen.java +++ b/src/main/java/net/citizensnpcs/EventListen.java @@ -73,6 +73,8 @@ public class EventListen implements Listener { for (int i = 0; i < ids.size(); i++) { int id = ids.get(i); NPC npc = npcRegistry.getById(id); + if (npc == null) + continue; npc.spawn(npc.getTrait(CurrentLocation.class).getLocation()); } toRespawn.removeAll(coord); @@ -86,8 +88,8 @@ public class EventListen implements Listener { continue; Location loc = npc.getBukkitEntity().getLocation(); Chunk chunk = loc.getChunk(); - if (event.getWorld().equals(loc.getWorld()) && event.getChunk().getX() == chunk.getX() - && event.getChunk().getZ() == chunk.getZ()) { + boolean sameChunkCoordinates = coord.z == chunk.getZ() && coord.x == chunk.getX(); + if (event.getWorld().equals(loc.getWorld()) && sameChunkCoordinates) { npc.despawn(); toRespawn.put(coord, npc.getId()); } @@ -272,14 +274,25 @@ public class EventListen implements Listener { private static class ChunkCoord { private final int x; private final int z; + private final String name; private ChunkCoord(Chunk chunk) { - this(chunk.getX(), chunk.getZ()); + this(chunk.getWorld().getName(), chunk.getX(), chunk.getZ()); } - private ChunkCoord(int x, int z) { + private ChunkCoord(String worldName, int x, int z) { this.x = x; this.z = z; + this.name = worldName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = prime + ((name == null) ? 0 : name.hashCode()); + result = prime * result + x; + result = prime * result + z; + return result; } @Override @@ -291,13 +304,17 @@ public class EventListen implements Listener { return false; } ChunkCoord other = (ChunkCoord) obj; - return x == other.x && z == other.z; - } - - @Override - public int hashCode() { - final int prime = 31; - return prime * (prime + x) + z; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (x != other.x || z != other.z) { + return false; + } + return true; } } diff --git a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java index e46954f24..b9aa9e651 100644 --- a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java @@ -40,6 +40,7 @@ import net.citizensnpcs.trait.VillagerProfession; import net.citizensnpcs.util.Anchor; import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.Messaging; +import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.Paginator; import net.citizensnpcs.util.Pose; import net.citizensnpcs.util.StringHelper; @@ -652,6 +653,29 @@ public class NPCCommands { 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 = "npc.playerlist") + @Requirements(types = EntityType.PLAYER) + public void playerlist(CommandContext args, CommandSender sender, NPC npc) { + boolean remove = !npc.data().getPersistent("removefromplayerlist", + Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean()); + if (args.hasFlag('a')) + remove = false; + else if (args.hasFlag('r')) + remove = true; + npc.data().setPersistent("removefromplayerlist", remove); + NMS.addOrRemoveFromPlayerList(npc.getBukkitEntity(), remove); + Messaging.sendTr(sender, remove ? Messages.ADDED_TO_PLAYERLIST : Messages.REMOVED_FROM_PLAYERLIST, + npc.getName()); + } + @Command( aliases = { "npc" }, usage = "pose (--save [name]|--assume [name]|--remove [name]) (-a)", diff --git a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java b/src/main/java/net/citizensnpcs/npc/CitizensNPC.java index 01d04dbdf..d831116e5 100644 --- a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java +++ b/src/main/java/net/citizensnpcs/npc/CitizensNPC.java @@ -1,7 +1,6 @@ package net.citizensnpcs.npc; import net.citizensnpcs.EventListen; -import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.ai.Navigator; import net.citizensnpcs.api.event.NPCDespawnEvent; @@ -18,7 +17,6 @@ import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.Messaging; import net.citizensnpcs.util.NMS; import net.minecraft.server.EntityLiving; -import net.minecraft.server.EntityPlayer; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; @@ -137,7 +135,6 @@ public abstract class CitizensNPC extends AbstractNPC { return false; mcEntity = createHandle(loc); - boolean couldSpawn = mcEntity.world.addEntity(mcEntity, SpawnReason.CUSTOM); if (!couldSpawn) { // we need to wait for a chunk load before trying to spawn @@ -145,8 +142,6 @@ public abstract class CitizensNPC extends AbstractNPC { EventListen.add(loc, getId()); return true; } - if (mcEntity instanceof EntityPlayer && Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean()) - mcEntity.world.players.remove(mcEntity); NPCSpawnEvent spawnEvent = new NPCSpawnEvent(this, loc); Bukkit.getPluginManager().callEvent(spawnEvent); diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java index b7f0d1192..5581de20b 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java @@ -1,5 +1,6 @@ package net.citizensnpcs.npc.entity; +import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.trait.trait.Equipment; import net.citizensnpcs.editor.Equipable; @@ -36,6 +37,9 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable { handle.as = loc.getYaw() % 360; // set the head yaw in another tick - if done immediately, // minecraft will not update it. + boolean removeFromPlayerList = Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean(); + NMS.addOrRemoveFromPlayerList(getBukkitEntity(), removeFromPlayerList + || data().getPersistent("removefromplayerlist", removeFromPlayerList)); } }, 5); handle.getBukkitEntity().setSleepingIgnored(true); diff --git a/src/main/java/net/citizensnpcs/util/Messages.java b/src/main/java/net/citizensnpcs/util/Messages.java index 405a836ee..f10d3bd02 100644 --- a/src/main/java/net/citizensnpcs/util/Messages.java +++ b/src/main/java/net/citizensnpcs/util/Messages.java @@ -180,4 +180,6 @@ public class Messages { public static final String WAYPOINT_PROVIDER_SET = "citizens.waypoints.set-provider"; public static final String WAYPOINT_TELEPORTING_DISABLED = "citizens.commands.waypoints.disableteleporting.disabled"; public static final String WRITING_DEFAULT_SETTING = "citizens.settings.writing-default"; + public static final String ADDED_TO_PLAYERLIST = "citizens.commands.npc.playerlist.added"; + public static final String REMOVED_FROM_PLAYERLIST = "citizens.commands.npc.playerlist.removed"; } diff --git a/src/main/java/net/citizensnpcs/util/NMS.java b/src/main/java/net/citizensnpcs/util/NMS.java index 123801ea9..baececfa5 100644 --- a/src/main/java/net/citizensnpcs/util/NMS.java +++ b/src/main/java/net/citizensnpcs/util/NMS.java @@ -12,6 +12,7 @@ import net.minecraft.server.DamageSource; import net.minecraft.server.Entity; import net.minecraft.server.EntityLiving; import net.minecraft.server.EntityMonster; +import net.minecraft.server.EntityPlayer; import net.minecraft.server.EntityTypes; import net.minecraft.server.MobEffectList; import net.minecraft.server.Navigation; @@ -260,4 +261,14 @@ public class NMS { Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); } } + + public static void addOrRemoveFromPlayerList(LivingEntity bukkitEntity, boolean remove) { + EntityLiving handle = ((CraftLivingEntity) bukkitEntity).getHandle(); + if (handle.world == null || !(handle instanceof EntityPlayer)) + return; + if (remove) + handle.world.players.remove(handle); + else + handle.world.players.add(handle); + } } diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 35ce15f30..faa3b1f99 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -1,6 +1,8 @@ citizens.changed-implementation=Citizens implementation changed, disabling plugin. citizens.commands.citizens.save.help=Use the -a flag to save async (off the main server thread). citizens.commands.console-error=Please report this error: [See console] +citizens.commands.npc.playerlist.added=Added [[{0}]] to the player list. +citizens.commands.npc.playerlist.removed=Removed [[{0}]] from the player list. citizens.commands.help.command-missing=Command /{0} not found. citizens.commands.help.header=Help citizens.commands.id-not-found=Couldn't find any NPC with ID {0}.