Implement new NPCRegistry creation methods

This commit is contained in:
fullwall 2013-02-06 19:43:28 +08:00
parent c3ca4656f8
commit 5184ded750
6 changed files with 88 additions and 146 deletions

View File

@ -2,8 +2,10 @@ package net.citizensnpcs;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
@ -18,14 +20,20 @@ import net.citizensnpcs.api.event.CitizensEnableEvent;
import net.citizensnpcs.api.event.CitizensReloadEvent;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCDataStore;
import net.citizensnpcs.api.npc.NPCRegistry;
import net.citizensnpcs.api.npc.SimpleNPCDataStore;
import net.citizensnpcs.api.scripting.EventRegistrar;
import net.citizensnpcs.api.scripting.ObjectProvider;
import net.citizensnpcs.api.scripting.ScriptCompiler;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitFactory;
import net.citizensnpcs.api.util.DatabaseStorage;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.NBTStorage;
import net.citizensnpcs.api.util.Storage;
import net.citizensnpcs.api.util.Translator;
import net.citizensnpcs.api.util.YamlStorage;
import net.citizensnpcs.commands.AdminCommands;
import net.citizensnpcs.commands.EditorCommands;
import net.citizensnpcs.commands.HelpCommands;
@ -55,6 +63,7 @@ import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
public class Citizens extends JavaPlugin implements CitizensPlugin {
private final CommandManager commands = new CommandManager();
@ -64,8 +73,42 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
private NPCDataStore saves;
private NPCSelector selector;
private CitizensSpeechFactory speechFactory;
private final Map<String, NPCRegistry> storedRegistries = Maps.newHashMap();
private CitizensTraitFactory traitFactory;
@Override
public NPCRegistry createAnonymousNPCRegistry(NPCDataStore store) {
return new CitizensNPCRegistry(store);
}
@Override
public NPCRegistry createNamedNPCRegistry(String name, NPCDataStore store) {
NPCRegistry created = new CitizensNPCRegistry(store);
storedRegistries.put(name, created);
return created;
}
private NPCDataStore createStorage(File folder) {
Storage saves = null;
String type = Setting.STORAGE_TYPE.asString();
if (type.equalsIgnoreCase("db") || type.equalsIgnoreCase("database")) {
try {
saves = new DatabaseStorage(Setting.DATABASE_DRIVER.asString(), Setting.DATABASE_URL.asString(),
Setting.DATABASE_USERNAME.asString(), Setting.DATABASE_PASSWORD.asString());
} catch (SQLException e) {
e.printStackTrace();
Messaging.logTr(Messages.DATABASE_CONNECTION_FAILED);
}
} else if (type.equalsIgnoreCase("nbt")) {
saves = new NBTStorage(folder + File.separator + Setting.STORAGE_FILE.asString(), "Citizens NPC Storage");
}
if (saves == null)
saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage");
if (!saves.load())
return null;
return SimpleNPCDataStore.create(saves);
}
private void despawnNPCs() {
Iterator<NPC> itr = npcRegistry.iterator();
while (itr.hasNext()) {
@ -117,6 +160,11 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
return commands.getCommands(base);
}
@Override
public NPCRegistry getNamedNPCRegistry(String name) {
return storedRegistries.get(name);
}
@Override
public NPCRegistry getNPCRegistry() {
return npcRegistry;
@ -187,7 +235,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
}
registerScriptHelpers();
saves = NPCDataStore.create(getDataFolder());
saves = createStorage(getDataFolder());
if (saves == null) {
Messaging.severeTr(Messages.FAILED_LOAD_SAVES);
getServer().getPluginManager().disablePlugin(this);
@ -200,7 +248,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
speechFactory = new CitizensSpeechFactory();
speechFactory.register(Chat.class, "chat");
getServer().getPluginManager().registerEvents(new EventListen(), this);
getServer().getPluginManager().registerEvents(new EventListen(storedRegistries), this);
if (Setting.NPC_COST.asDouble() > 0)
setupEconomy();
@ -214,6 +262,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
@Override
public void run() {
saves.loadInto(npcRegistry);
Messaging.logTr(Messages.NUM_LOADED_NOTIFICATION, Iterables.size(npcRegistry), "?");
startMetrics();
scheduleSaveTask(Setting.SAVE_TASK_DELAY.asInt());
Bukkit.getPluginManager().callEvent(new CitizensEnableEvent());
@ -267,6 +316,11 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
getServer().getPluginManager().callEvent(new CitizensReloadEvent());
}
@Override
public void removeNamedNPCRegistry(String name) {
storedRegistries.remove(name);
}
private void scheduleSaveTask(int delay) {
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
@ -337,7 +391,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
}
});
traitFactory.addPlotters(metrics.createGraph("traits"));
saves.addPlotters(metrics.createGraph("Storage type"));
metrics.start();
} catch (IOException e) {
Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage());
@ -371,5 +424,4 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
}
private static final String COMPATIBLE_MC_VERSION = "1.4.7";
}

View File

@ -1,6 +1,7 @@
package net.citizensnpcs;
import java.util.List;
import java.util.Map;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
@ -53,11 +54,17 @@ import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
public class EventListen implements Listener {
private final NPCRegistry npcRegistry = CitizensAPI.getNPCRegistry();
private final ListMultimap<ChunkCoord, Integer> toRespawn = ArrayListMultimap.create();
private final ListMultimap<ChunkCoord, NPC> toRespawn = ArrayListMultimap.create();
private final Map<String, NPCRegistry> registries;
EventListen(Map<String, NPCRegistry> registries) {
this.registries = registries;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onChunkLoad(ChunkLoadEvent event) {
@ -69,7 +76,7 @@ public class EventListen implements Listener {
public void onChunkUnload(ChunkUnloadEvent event) {
ChunkCoord coord = toCoord(event.getChunk());
Location location = new Location(null, 0, 0, 0);
for (NPC npc : npcRegistry) {
for (NPC npc : getAllNPCs()) {
if (!npc.isSpawned())
continue;
location = npc.getBukkitEntity().getLocation(location);
@ -81,13 +88,17 @@ public class EventListen implements Listener {
respawnAllFromCoord(coord);
return;
}
toRespawn.put(coord, npc.getId());
toRespawn.put(coord, npc);
Messaging
.debug("Despawned id", npc.getId(), "due to chunk unload at [" + coord.x + "," + coord.z + "]");
}
}
}
private Iterable<NPC> getAllNPCs() {
return Iterables.<NPC> concat(npcRegistry, Iterables.concat(registries.values()));
}
@EventHandler(ignoreCancelled = true)
public void onEntityChangedWorld(EntityTeleportEvent event) {
if (event.getFrom() == null || event.getTo() == null)
@ -165,7 +176,7 @@ public class EventListen implements Listener {
@EventHandler
public void onNeedsRespawn(NPCNeedsRespawnEvent event) {
toRespawn.put(toCoord(event.getSpawnLocation()), event.getNPC().getId());
toRespawn.put(toCoord(event.getSpawnLocation()), event.getNPC());
}
@EventHandler(ignoreCancelled = true)
@ -226,7 +237,7 @@ public class EventListen implements Listener {
if (!chunk.worldName.equals(event.getWorld().getName())
|| !event.getWorld().isChunkLoaded(chunk.x, chunk.z))
continue;
List<Integer> ids = toRespawn.get(chunk);
List<NPC> ids = toRespawn.get(chunk);
for (int i = 0; i < ids.size(); i++) {
spawn(ids.get(i));
Messaging.debug("Spawned", ids.get(0), "due to world " + event.getWorld().getName() + " load");
@ -237,7 +248,7 @@ public class EventListen implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onWorldUnload(WorldUnloadEvent event) {
for (NPC npc : npcRegistry) {
for (NPC npc : getAllNPCs()) {
if (!npc.isSpawned() || !npc.getBukkitEntity().getWorld().equals(event.getWorld()))
continue;
storeForRespawn(npc);
@ -249,9 +260,9 @@ public class EventListen implements Listener {
}
private void respawnAllFromCoord(ChunkCoord coord) {
List<Integer> ids = toRespawn.get(coord);
List<NPC> ids = toRespawn.get(coord);
for (int i = 0; i < ids.size(); i++) {
int id = ids.get(i);
NPC 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 + "]");
@ -262,22 +273,17 @@ public class EventListen implements Listener {
}
}
private boolean spawn(int id) {
NPC npc = npcRegistry.getById(id);
if (npc == null) {
Messaging.debug("Couldn't despawn unknown NPC id", id);
return false;
}
private boolean spawn(NPC npc) {
Location spawn = npc.getTrait(CurrentLocation.class).getLocation();
if (spawn == null) {
Messaging.debug("Couldn't find a spawn location for despawned NPC id", id);
Messaging.debug("Couldn't find a spawn location for despawned NPC id", npc);
return false;
}
return npc.spawn(spawn);
}
private void storeForRespawn(NPC npc) {
toRespawn.put(toCoord(npc.getBukkitEntity().getLocation()), npc.getId());
toRespawn.put(toCoord(npc.getBukkitEntity().getLocation()), npc);
}
private ChunkCoord toCoord(Chunk chunk) {

View File

@ -1,120 +0,0 @@
package net.citizensnpcs;
import java.io.File;
import java.sql.SQLException;
import net.citizensnpcs.Metrics.Graph;
import net.citizensnpcs.Metrics.Plotter;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCRegistry;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.DatabaseStorage;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.NBTStorage;
import net.citizensnpcs.api.util.Storage;
import net.citizensnpcs.api.util.YamlStorage;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.CitizensNPCRegistry;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Util;
import org.bukkit.entity.EntityType;
public class NPCDataStore {
private final Storage root;
private NPCDataStore(Storage 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) {
int created = 0;
for (DataKey key : root.getKey("npc").getIntegerSubKeys()) {
int id = Integer.parseInt(key.name());
if (!key.keyExists("name")) {
Messaging.logTr(Messages.LOAD_NAME_NOT_FOUND, id);
continue;
}
String unparsedEntityType = key.getString("traits.type", "PLAYER");
EntityType type = Util.matchEntityType(unparsedEntityType);
if (type == null) {
Messaging.logTr(Messages.LOAD_UNKNOWN_NPC_TYPE, unparsedEntityType);
continue;
}
NPC npc = registry.createNPC(type, id, key.getString("name"));
((CitizensNPC) npc).load(key);
created++;
}
Messaging.logTr(Messages.NUM_LOADED_NOTIFICATION, created, "?");
}
public void remove(NPC npc) {
root.getKey("npc").removeKey(Integer.toString(npc.getId()));
}
public void saveToDisk() {
new Thread() {
@Override
public void run() {
root.save();
}
}.start();
}
public void saveToDiskImmediate() {
root.save();
}
public void store(NPC npc) {
((CitizensNPC) npc).save(root.getKey("npc." + npc.getId()));
}
public void storeAll(NPCRegistry registry) {
for (NPC npc : registry)
store(npc);
}
public static NPCDataStore create(File folder) {
Storage saves = null;
String type = Setting.STORAGE_TYPE.asString();
if (type.equalsIgnoreCase("db") || type.equalsIgnoreCase("database")) {
try {
saves = new DatabaseStorage(Setting.DATABASE_DRIVER.asString(), Setting.DATABASE_URL.asString(),
Setting.DATABASE_USERNAME.asString(), Setting.DATABASE_PASSWORD.asString());
} catch (SQLException e) {
e.printStackTrace();
Messaging.logTr(Messages.DATABASE_CONNECTION_FAILED);
}
} else if (type.equalsIgnoreCase("nbt")) {
saves = new NBTStorage(folder + File.separator + Setting.STORAGE_FILE.asString(), "Citizens NPC Storage");
}
if (saves == null)
saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage");
if (!saves.load())
return null;
return new NPCDataStore(saves);
}
}

View File

@ -101,8 +101,8 @@ public class Settings {
STORAGE_FILE("storage.file", "saves.yml"),
STORAGE_TYPE("storage.type", "yaml"),
SUBPLUGIN_FOLDER("subplugins.folder", "plugins"),
TALK_CLOSE_MAXIMUM_COOLDOWN("npc.text.max-talk-cooldown", 60),
TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 30),
TALK_CLOSE_MAXIMUM_COOLDOWN("npc.text.max-talk-cooldown", 1),
TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 1),
TALK_ITEM("npc.text.talk-item", "340"),
USE_NEW_PATHFINDER("npc.pathfinding.use-new-finder", false);

View File

@ -2,9 +2,9 @@ package net.citizensnpcs.npc;
import java.util.Iterator;
import net.citizensnpcs.NPCDataStore;
import net.citizensnpcs.api.event.NPCCreateEvent;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCDataStore;
import net.citizensnpcs.api.npc.NPCRegistry;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.npc.ai.NPCHolder;
@ -26,6 +26,7 @@ public class CitizensNPCRegistry implements NPCRegistry {
saves = store;
}
@Override
public NPC createNPC(EntityType type, int id, String name) {
Preconditions.checkNotNull(name, "name cannot be null");
Preconditions.checkNotNull(type, "type cannot be null");
@ -45,7 +46,8 @@ public class CitizensNPCRegistry implements NPCRegistry {
@Override
public void deregister(NPC npc) {
npcs.remove(npc.getId());
saves.remove(npc);
if (saves != null)
saves.clearData(npc);
npc.despawn();
}
@ -58,7 +60,8 @@ public class CitizensNPCRegistry implements NPCRegistry {
npc.despawn();
for (Trait t : npc.getTraits())
t.onRemove();
saves.remove(npc);
if (saves != null)
saves.clearData(npc);
}
}

View File

@ -133,8 +133,9 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
// If the cooldown is not expired, do not send text
Date cooldown = cooldowns.get(player.getName());
if (cooldown != null) {
if (!new Date().after(cooldown))
if (!new Date().after(cooldown)) {
return;
}
cooldowns.remove(player.getName());
}
if (!sendText(player))