diff --git a/TODO b/TODO index 805271afd..1c848be86 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,7 @@ -Citizens2 TODO List- --Add proper color parsing for names (separate it into a trait?) +-Add proper color parsing for names -Properly implement commands --Finish saving +-Add NPC templates -Finish pathfinding API -Add database support (MySQL and/or SQLite) \ No newline at end of file diff --git a/lib/CitizensAPI.jar b/lib/CitizensAPI.jar index c994d6a76..00e47c700 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 26d3357bc..3142e42f7 100644 --- a/src/net/citizensnpcs/Citizens.java +++ b/src/net/citizensnpcs/Citizens.java @@ -1,7 +1,10 @@ package net.citizensnpcs; import java.io.File; +import java.util.HashMap; +import java.util.Map; +import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.DataKey; import net.citizensnpcs.api.exception.NPCLoadException; @@ -11,9 +14,9 @@ import net.citizensnpcs.api.npc.trait.DefaultInstanceFactory; import net.citizensnpcs.api.npc.trait.InstanceFactory; import net.citizensnpcs.api.npc.trait.Trait; import net.citizensnpcs.api.npc.trait.trait.SpawnLocation; -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; @@ -23,6 +26,8 @@ import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.java.JavaPlugin; public class Citizens extends JavaPlugin { @@ -66,12 +71,17 @@ public class Citizens extends JavaPlugin { config = new Settings(this); config.load(); - // TODO database support - saves = new YamlStorage(getDataFolder() + File.separator + "saves.yml"); + // NPC storage + if (Setting.USE_DATABASE.getBoolean()) + saves = new DatabaseStorage(); + else + saves = new YamlStorage(getDataFolder() + File.separator + "saves.yml"); // Register events getServer().getPluginManager().registerEvents(new EventListen(npcManager), this); + registerPermissions(); + Messaging.log("v" + getDescription().getVersion() + " enabled."); // Setup NPCs after all plugins have been enabled (allows for multiworld @@ -82,7 +92,7 @@ public class Citizens extends JavaPlugin { try { setupNPCs(); } catch (NPCLoadException ex) { - Messaging.log("Failed to create NPC: " + ex.getMessage()); + Messaging.log("Issue when loading NPCs: " + ex.getMessage()); } } }) == -1) { @@ -105,13 +115,12 @@ public class Citizens extends JavaPlugin { } // Save all existing traits - for (Trait trait : ((CitizensNPC) npc).getTraits()) + for (Trait trait : npc.getTraits()) trait.save(root.getRelative(trait.getName())); } saves.save(); } - // TODO separate this out some more private void setupNPCs() throws NPCLoadException { traitManager.register("location", SpawnLocation.class); @@ -149,4 +158,12 @@ public class Citizens extends JavaPlugin { Messaging.log("Loaded " + ((ByIdArray) npcManager.getAllNPCs()).size() + " NPCs (" + ((ByIdArray) npcManager.getSpawnedNPCs()).size() + " spawned)."); } + + private void registerPermissions() { + Map children = new HashMap(); + children.put("citizens.npc.select", true); + + Permission perm = new Permission("citizens.*", PermissionDefault.OP, children); + getServer().getPluginManager().addPermission(perm); + } } \ No newline at end of file diff --git a/src/net/citizensnpcs/EventListen.java b/src/net/citizensnpcs/EventListen.java index 805ffecf1..cf99c91b4 100644 --- a/src/net/citizensnpcs/EventListen.java +++ b/src/net/citizensnpcs/EventListen.java @@ -4,10 +4,13 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.npc.NPCManager; import net.citizensnpcs.api.npc.trait.trait.SpawnLocation; +import net.citizensnpcs.npc.CitizensNPCManager; +import net.citizensnpcs.util.Messaging; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -15,14 +18,16 @@ import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.event.entity.EntityTargetEvent.TargetReason; +import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkUnloadEvent; public class EventListen implements Listener { private final List toRespawn = new ArrayList(); - private final NPCManager manager; + private final CitizensNPCManager manager; - public EventListen(NPCManager manager) { + public EventListen(CitizensNPCManager manager) { this.manager = manager; } @@ -63,7 +68,7 @@ public class EventListen implements Listener { if (!manager.isNPC(event.getEntity())) return; - event.setCancelled(true); // TODO: implement damage handlers + event.setCancelled(true); // TODO implement damage handlers if (event instanceof EntityDamageByEntityEvent) { EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event; if (e.getDamager() instanceof Player) { @@ -76,11 +81,27 @@ public class EventListen implements Listener { @EventHandler public void onEntityTarget(EntityTargetEvent event) { - if (event.isCancelled() || !manager.isNPC(event.getEntity()) || !(event.getTarget() instanceof Player)) - return; + if (manager.isNPC(event.getTarget())) + if (event.isCancelled() || !manager.isNPC(event.getEntity()) || !(event.getTarget() instanceof Player)) + return; NPC npc = manager.getNPC(event.getEntity()); - if (npc.getCharacter() != null) - npc.getCharacter().onRightClick(npc, (Player) event.getTarget()); + Player player = (Player) event.getTarget(); + if (manager.canSelect(player, npc)) { + manager.selectNPC(player, npc); + Messaging.sendWithNPC(player, Setting.SELECTION_MESSAGE.getString(), npc); + } else { + if (npc.getCharacter() != null) + npc.getCharacter().onRightClick(npc, player); + } + } + + @EventHandler + public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { + if (!manager.isNPC(event.getRightClicked())) + return; + + Bukkit.getPluginManager().callEvent( + new EntityTargetEvent(event.getRightClicked(), event.getPlayer(), TargetReason.CUSTOM)); } } \ No newline at end of file diff --git a/src/net/citizensnpcs/Settings.java b/src/net/citizensnpcs/Settings.java index 67aeffcea..4b41f853c 100644 --- a/src/net/citizensnpcs/Settings.java +++ b/src/net/citizensnpcs/Settings.java @@ -9,13 +9,12 @@ import net.citizensnpcs.util.Messaging; public class Settings { private final YamlStorage config; - private final DataKey root; public Settings(Citizens plugin) { config = new YamlStorage(plugin.getDataFolder() + File.separator + "config.yml"); - root = config.getKey(""); } public void load() { + DataKey root = config.getKey(""); for (Setting setting : Setting.values()) { if (!root.keyExists(setting.getPath())) { Messaging.log("Writing default setting: '" + setting.getPath() + "'"); @@ -31,7 +30,10 @@ public class Settings { } public enum Setting { - DEBUG_MODE("general.debug-mode", false); + DEBUG_MODE("general.debug-mode", false), + USE_DATABASE("use-database", false), + SELECTION_ITEM("npc.selection.item", 280), + SELECTION_MESSAGE("npc.selection.message", "You selected !"); private String path; private Object value; diff --git a/src/net/citizensnpcs/npc/CitizensNPCManager.java b/src/net/citizensnpcs/npc/CitizensNPCManager.java index 5aaf39a9d..e67f4893f 100644 --- a/src/net/citizensnpcs/npc/CitizensNPCManager.java +++ b/src/net/citizensnpcs/npc/CitizensNPCManager.java @@ -3,7 +3,10 @@ package net.citizensnpcs.npc; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPCManager; import net.citizensnpcs.api.npc.trait.Character; @@ -11,6 +14,7 @@ import net.citizensnpcs.api.npc.trait.Trait; import net.citizensnpcs.api.npc.trait.trait.SpawnLocation; import net.citizensnpcs.resources.lib.CraftNPC; import net.citizensnpcs.util.ByIdArray; + import net.minecraft.server.ItemInWorldManager; import net.minecraft.server.MinecraftServer; import net.minecraft.server.Packet29DestroyEntity; @@ -29,6 +33,7 @@ import org.bukkit.entity.Player; public class CitizensNPCManager implements NPCManager { private final ByIdArray spawned = new ByIdArray(); private final ByIdArray byID = new ByIdArray(); + private final Map selected = new ConcurrentHashMap(); @Override public NPC createNPC(String name) { @@ -45,9 +50,8 @@ public class CitizensNPCManager implements NPCManager { public void despawn(NPC npc) { CraftNPC mcEntity = ((CitizensNPC) npc).getHandle(); - for (Player player : Bukkit.getOnlinePlayers()) { + for (Player player : Bukkit.getOnlinePlayers()) ((CraftPlayer) player).getHandle().netServerHandler.sendPacket(new Packet29DestroyEntity(mcEntity.id)); - } Location loc = npc.getBukkitEntity().getLocation(); getWorldServer(loc.getWorld()).removeEntity(mcEntity); npc.getTrait(SpawnLocation.class).setLocation(loc); @@ -123,4 +127,18 @@ public class CitizensNPCManager implements NPCManager { spawned.put(mcEntity.getPlayer().getEntityId(), npc); return mcEntity; } + + public void selectNPC(Player player, NPC npc) { + selected.put(player.getName(), npc); + } + + public boolean canSelect(Player player, NPC npc) { + if (player.hasPermission("citizens.npc.select")) { + if (!selected.containsKey(player.getName())) + return true; + return selected.get(player.getName()).getId() != npc.getId() + && player.getItemInHand().getTypeId() == Setting.SELECTION_ITEM.getInt(); + } + return false; + } } \ No newline at end of file diff --git a/src/net/citizensnpcs/resources/lib/CraftNPC.java b/src/net/citizensnpcs/resources/lib/CraftNPC.java index 789abfa25..dad200419 100644 --- a/src/net/citizensnpcs/resources/lib/CraftNPC.java +++ b/src/net/citizensnpcs/resources/lib/CraftNPC.java @@ -36,8 +36,8 @@ public class CraftNPC extends EntityPlayer { try { socket.close(); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ex) { + ex.printStackTrace(); } } diff --git a/src/net/citizensnpcs/util/Messaging.java b/src/net/citizensnpcs/util/Messaging.java index dc431e19d..55f516785 100644 --- a/src/net/citizensnpcs/util/Messaging.java +++ b/src/net/citizensnpcs/util/Messaging.java @@ -3,8 +3,11 @@ package net.citizensnpcs.util; import java.util.logging.Level; import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.npc.NPC; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; public class Messaging { @@ -20,4 +23,26 @@ public class Messaging { public static void log(Object msg) { log(Level.INFO, msg); } + + public static void send(Player player, Object msg) { + String send = "" + msg; + + for (ChatColor color : ChatColor.values()) { + if (send.contains("<" + color.getChar() + ">")) + send = send.replace("<" + color.getChar() + ">", "" + ChatColor.getByChar(color.getChar())); + } + + player.sendMessage(send); + } + + public static void sendWithNPC(Player player, Object msg, NPC npc) { + String send = "" + msg; + + if (send.contains("")) + send = send.replace("", npc.getName()); + if (send.contains("")) + send = send.replace("", "" + npc.getId()); + + send(player, send); + } } \ No newline at end of file