diff --git a/lib/CitizensAPI.jar b/lib/CitizensAPI.jar index 089f0383e..9e4c3083c 100644 Binary files a/lib/CitizensAPI.jar and b/lib/CitizensAPI.jar differ diff --git a/src/net/citizensnpcs/Citizens.java b/src/net/citizensnpcs/Citizens.java index db01566f2..174a8ec56 100644 --- a/src/net/citizensnpcs/Citizens.java +++ b/src/net/citizensnpcs/Citizens.java @@ -29,12 +29,10 @@ import net.citizensnpcs.command.exception.RequirementMissingException; import net.citizensnpcs.command.exception.ServerCommandException; import net.citizensnpcs.command.exception.UnhandledCommandException; import net.citizensnpcs.command.exception.WrappedCommandException; -import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.npc.CitizensNPCManager; import net.citizensnpcs.storage.Storage; import net.citizensnpcs.storage.database.DatabaseStorage; import net.citizensnpcs.storage.flatfile.YamlStorage; -import net.citizensnpcs.util.ByIdArray; import net.citizensnpcs.util.Messaging; import net.citizensnpcs.util.StringHelper; @@ -50,7 +48,7 @@ import org.bukkit.plugin.java.JavaPlugin; public class Citizens extends JavaPlugin { private static Storage saves; - private CitizensNPCManager npcManager; + private volatile CitizensNPCManager npcManager; private final InstanceFactory characterManager = new DefaultInstanceFactory(); private final InstanceFactory traitManager = new DefaultInstanceFactory(); private CommandManager cmdManager; @@ -117,9 +115,8 @@ public class Citizens extends JavaPlugin { // Save and despawn all NPCs config.save(); saveNPCs(); - for (NPC npc : npcManager.getAllNPCs()) + for (NPC npc : npcManager) npc.despawn(); - Bukkit.getScheduler().cancelTasks(this); Messaging.log("v" + getDescription().getVersion() + " disabled."); @@ -174,8 +171,8 @@ public class Citizens extends JavaPlugin { } private void saveNPCs() { - for (NPC npc : npcManager.getAllNPCs()) - ((CitizensNPC) npc).save(); + for (NPC npc : npcManager) + npc.save(getNPCStorage().getKey("npc." + npc.getId())); getNPCStorage().save(); } @@ -187,7 +184,7 @@ public class Citizens extends JavaPlugin { int id = Integer.parseInt(key.name()); if (!key.keyExists("name")) throw new NPCLoadException("Could not find a name for the NPC with ID '" + id + "'."); - Character character = characterManager.getInstance(key.getString("character")); + Character character = characterManager.getInstance(key.getString("character"), null); NPC npc = npcManager.createNPC(id, key.getString("name"), character); // Load the character if it exists, otherwise remove the character @@ -203,7 +200,7 @@ public class Citizens extends JavaPlugin { // Load traits for (DataKey traitKey : key.getSubKeys()) { - Trait trait = traitManager.getInstance(traitKey.name()); + Trait trait = traitManager.getInstance(traitKey.name(), npc); if (trait == null) continue; trait.load(traitKey); @@ -214,8 +211,7 @@ public class Citizens extends JavaPlugin { if (key.getBoolean("spawned")) npc.spawn(npc.getTrait(SpawnLocation.class).getLocation()); } - Messaging.log("Loaded " + ((ByIdArray) npcManager.getAllNPCs()).size() + " NPCs (" - + ((ByIdArray) npcManager.getSpawnedNPCs()).size() + " spawned)."); + Messaging.log("Loaded " + npcManager.size() + " NPCs"); } private void registerPermissions() { diff --git a/src/net/citizensnpcs/EventListen.java b/src/net/citizensnpcs/EventListen.java index baf88691b..90760fbf7 100644 --- a/src/net/citizensnpcs/EventListen.java +++ b/src/net/citizensnpcs/EventListen.java @@ -25,7 +25,7 @@ import org.bukkit.event.world.ChunkUnloadEvent; public class EventListen implements Listener { private final List toRespawn = new ArrayList(); - private final CitizensNPCManager npcManager; + private volatile CitizensNPCManager npcManager; public EventListen(CitizensNPCManager npcManager) { this.npcManager = npcManager; @@ -49,7 +49,7 @@ public class EventListen implements Listener { if (event.isCancelled()) return; - for (NPC npc : npcManager.getAllNPCs()) { + for (NPC npc : npcManager) { Location loc = npc.getBukkitEntity().getLocation(); if (event.getWorld().equals(loc.getWorld()) && event.getChunk().getX() == loc.getChunk().getX() && event.getChunk().getZ() == loc.getChunk().getZ()) { diff --git a/src/net/citizensnpcs/Settings.java b/src/net/citizensnpcs/Settings.java index 086c43ecd..1d429f0bd 100644 --- a/src/net/citizensnpcs/Settings.java +++ b/src/net/citizensnpcs/Settings.java @@ -34,8 +34,7 @@ public class Settings { USE_DATABASE("use-database", false), SELECTION_ITEM("npc.selection.item", 280), SELECTION_MESSAGE("npc.selection.message", "You selected !"), - QUICK_SELECT("npc.selection.quick-select", false), - PRINT_CHAT_TO_CONSOLE("npc.chat.print-to-console", true); + QUICK_SELECT("npc.selection.quick-select", false); private String path; private Object value; diff --git a/src/net/citizensnpcs/command/command/NPCCommands.java b/src/net/citizensnpcs/command/command/NPCCommands.java index dc4440b54..fbbc9b1eb 100644 --- a/src/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/net/citizensnpcs/command/command/NPCCommands.java @@ -1,8 +1,5 @@ package net.citizensnpcs.command.command; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; - import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.trait.Character; import net.citizensnpcs.api.npc.trait.DefaultInstanceFactory; @@ -16,6 +13,9 @@ import net.citizensnpcs.npc.CitizensNPCManager; import net.citizensnpcs.util.Messaging; import net.citizensnpcs.util.StringHelper; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + @Requirements(selected = true, ownership = true) public class NPCCommands { private final CitizensNPCManager npcManager; @@ -26,20 +26,15 @@ public class NPCCommands { this.characterManager = characterManager; } - @Command( - aliases = { "npc" }, - usage = "create [name] (character)", - desc = "Create a new NPC", - modifiers = { "create" }, - min = 2, - max = 3) + @Command(aliases = { "npc" }, usage = "create [name] (character)", desc = "Create a new NPC", + modifiers = { "create" }, min = 2, max = 3) @Permission("npc.create") @Requirements public void createNPC(CommandContext args, Player player, NPC npc) { CitizensNPC create = (CitizensNPC) npcManager.createNPC(args.getString(1)); String msg = ChatColor.GREEN + "You created " + StringHelper.wrap(create.getName()); - if (args.argsLength() == 3 && characterManager.getInstance(args.getString(2)) != null) { - create.setCharacter(characterManager.getInstance(args.getString(2))); + if (args.argsLength() == 3 && characterManager.getInstance(args.getString(2), create) != null) { + create.setCharacter(characterManager.getInstance(args.getString(2), create)); msg += " with the character " + StringHelper.wrap(args.getString(2)); } msg += " at your location."; @@ -53,13 +48,8 @@ public class NPCCommands { Messaging.send(player, msg); } - @Command( - aliases = { "npc" }, - usage = "spawn [id]", - desc = "Spawn an existing NPC", - modifiers = { "spawn" }, - min = 2, - max = 2) + @Command(aliases = { "npc" }, usage = "spawn [id]", desc = "Spawn an existing NPC", modifiers = { "spawn" }, + min = 2, max = 2) @Permission("npc.spawn") @Requirements(ownership = true) public void spawnNPC(CommandContext args, Player player, NPC npc) { @@ -78,13 +68,8 @@ public class NPCCommands { + " is already spawned at another location. Use '/npc tp' to teleport the NPC to your location."); } - @Command( - aliases = { "npc" }, - usage = "despawn", - desc = "Despawn an NPC", - modifiers = { "despawn" }, - min = 1, - max = 1) + @Command(aliases = { "npc" }, usage = "despawn", desc = "Despawn an NPC", modifiers = { "despawn" }, min = 1, + max = 1) @Permission("npc.despawn") public void despawnNPC(CommandContext args, Player player, NPC npc) { npc.despawn(); diff --git a/src/net/citizensnpcs/npc/CitizensNPC.java b/src/net/citizensnpcs/npc/CitizensNPC.java index 4d099fdc1..a80399e08 100644 --- a/src/net/citizensnpcs/npc/CitizensNPC.java +++ b/src/net/citizensnpcs/npc/CitizensNPC.java @@ -1,13 +1,10 @@ package net.citizensnpcs.npc; -import net.citizensnpcs.Citizens; -import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.DataKey; import net.citizensnpcs.api.event.NPCDespawnEvent; import net.citizensnpcs.api.event.NPCSpawnEvent; import net.citizensnpcs.api.npc.AbstractNPC; import net.citizensnpcs.api.npc.ai.Navigator; -import net.citizensnpcs.api.npc.trait.Trait; import net.citizensnpcs.api.npc.trait.trait.SpawnLocation; import net.citizensnpcs.npc.ai.CitizensNavigator; import net.citizensnpcs.resources.lib.CraftNPC; @@ -16,7 +13,6 @@ import net.citizensnpcs.util.Messaging; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; public class CitizensNPC extends AbstractNPC { private CraftNPC mcEntity; @@ -41,7 +37,6 @@ public class CitizensNPC extends AbstractNPC { getHandle().die(); spawned = false; - save(); return true; } @@ -92,35 +87,10 @@ public class CitizensNPC extends AbstractNPC { addTrait(new SpawnLocation(loc)); spawned = true; - save(); return true; } @Override - public void chat(String message) { - String formatted = "<" + getName() + "> " + message; - for (Player player : Bukkit.getOnlinePlayers()) - player.sendMessage(formatted); - if (Setting.PRINT_CHAT_TO_CONSOLE.getBoolean()) - Messaging.log(formatted); - } - - public void save() { - DataKey key = Citizens.getNPCStorage().getKey("npc." + getId()); - key.setString("name", getFullName()); - if (!key.keyExists("spawned")) - key.setBoolean("spawned", true); - if (key.getBoolean("spawned")) - key.setBoolean("spawned", !getBukkitEntity().isDead()); - - // Save the character if it exists - if (getCharacter() != null) { - key.setString("character", getCharacter().getName()); - getCharacter().save(key.getRelative("characters." + getCharacter().getName())); - } - - // Save all existing traits - for (Trait trait : getTraits()) - trait.save(key.getRelative(trait.getName())); + public void load(DataKey root) { } } \ No newline at end of file diff --git a/src/net/citizensnpcs/npc/CitizensNPCManager.java b/src/net/citizensnpcs/npc/CitizensNPCManager.java index ec9410745..05cac0fe7 100644 --- a/src/net/citizensnpcs/npc/CitizensNPCManager.java +++ b/src/net/citizensnpcs/npc/CitizensNPCManager.java @@ -2,6 +2,7 @@ package net.citizensnpcs.npc; import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -16,7 +17,6 @@ import net.citizensnpcs.api.npc.trait.trait.SpawnLocation; import net.citizensnpcs.resources.lib.CraftNPC; import net.citizensnpcs.storage.Storage; import net.citizensnpcs.util.ByIdArray; - import net.minecraft.server.ItemInWorldManager; import net.minecraft.server.MinecraftServer; import net.minecraft.server.Packet29DestroyEntity; @@ -71,8 +71,8 @@ public class CitizensNPCManager implements NPCManager { } @Override - public Iterable getAllNPCs() { - return byID; + public Iterator iterator() { + return byID.iterator(); } private MinecraftServer getMinecraftServer(Server server) { @@ -92,9 +92,9 @@ public class CitizensNPCManager implements NPCManager { @Override public Collection getNPCs(Class character) { List npcs = new ArrayList(); - for (NPC npc : getAllNPCs()) { + for (NPC npc : this) { if (npc.getCharacter() != null - && CitizensAPI.getCharacterManager().getInstance(npc.getCharacter().getName()) != null) + && CitizensAPI.getCharacterManager().getInstance(npc.getCharacter().getName(), npc) != null) npcs.add(npc); } return npcs; @@ -171,4 +171,8 @@ public class CitizensNPCManager implements NPCManager { return null; return getNPC(selected.get(player.getName())); } + + public int size() { + return byID.size(); + } } \ No newline at end of file diff --git a/src/net/citizensnpcs/util/ByIdArray.java b/src/net/citizensnpcs/util/ByIdArray.java index bf9ed4fcc..5c4b478b1 100644 --- a/src/net/citizensnpcs/util/ByIdArray.java +++ b/src/net/citizensnpcs/util/ByIdArray.java @@ -35,7 +35,6 @@ public class ByIdArray implements Iterable { int index = 0; while (elementData[index++] != null) { if (index >= elementData.length) { - System.out.println(elementData.length + " " + index); ensureCapacity(elementData.length + 1); index = elementData.length - 1; } @@ -82,11 +81,13 @@ public class ByIdArray implements Iterable { @Override public Iterator iterator() { return new Iterator() { - private final int expected = ByIdArray.this.modCount; + private int expected = ByIdArray.this.modCount; private int idx = lowest; @Override public boolean hasNext() { + if (ByIdArray.this.modCount != expected) + throw new ConcurrentModificationException(); return highest + 1 > idx && size > 0; } @@ -106,7 +107,10 @@ public class ByIdArray implements Iterable { @Override public void remove() { + if (ByIdArray.this.modCount != expected) + throw new ConcurrentModificationException(); ByIdArray.this.fastRemove(idx); + expected = ByIdArray.this.modCount; } }; }