2012-01-19 08:38:40 +01:00
|
|
|
package net.citizensnpcs;
|
|
|
|
|
2012-08-29 15:37:00 +02:00
|
|
|
import net.citizensnpcs.Settings.Setting;
|
2012-05-17 15:34:03 +02:00
|
|
|
import net.citizensnpcs.api.CitizensAPI;
|
2012-08-15 18:13:46 +02:00
|
|
|
import net.citizensnpcs.api.event.NPCDamageByBlockEvent;
|
2012-05-13 13:41:21 +02:00
|
|
|
import net.citizensnpcs.api.event.NPCDamageByEntityEvent;
|
2012-05-12 09:13:58 +02:00
|
|
|
import net.citizensnpcs.api.event.NPCDamageEvent;
|
2012-03-11 07:43:18 +01:00
|
|
|
import net.citizensnpcs.api.event.NPCLeftClickEvent;
|
|
|
|
import net.citizensnpcs.api.event.NPCRightClickEvent;
|
2012-08-29 15:37:00 +02:00
|
|
|
import net.citizensnpcs.api.event.PlayerCreateNPCEvent;
|
2012-01-19 08:38:40 +01:00
|
|
|
import net.citizensnpcs.api.npc.NPC;
|
2012-05-17 15:34:03 +02:00
|
|
|
import net.citizensnpcs.api.npc.NPCRegistry;
|
2012-08-29 15:37:00 +02:00
|
|
|
import net.citizensnpcs.api.trait.trait.Owner;
|
2012-02-27 14:01:38 +01:00
|
|
|
import net.citizensnpcs.editor.Editor;
|
2012-03-08 19:01:12 +01:00
|
|
|
import net.citizensnpcs.npc.entity.EntityHumanNPC;
|
2012-03-12 07:26:08 +01:00
|
|
|
import net.citizensnpcs.trait.CurrentLocation;
|
2012-07-21 08:11:32 +02:00
|
|
|
import net.minecraft.server.EntityPlayer;
|
2012-01-19 08:38:40 +01:00
|
|
|
|
2012-01-23 15:30:15 +01:00
|
|
|
import org.bukkit.Bukkit;
|
2012-02-19 18:45:43 +01:00
|
|
|
import org.bukkit.Chunk;
|
2012-01-19 11:52:58 +01:00
|
|
|
import org.bukkit.Location;
|
2012-02-26 07:35:44 +01:00
|
|
|
import org.bukkit.craftbukkit.CraftServer;
|
|
|
|
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
2012-01-19 08:38:40 +01:00
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import org.bukkit.event.EventHandler;
|
|
|
|
import org.bukkit.event.Listener;
|
2012-08-15 18:13:46 +02:00
|
|
|
import org.bukkit.event.entity.EntityDamageByBlockEvent;
|
2012-01-19 08:38:40 +01:00
|
|
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
|
|
import org.bukkit.event.entity.EntityDamageEvent;
|
2012-03-12 11:45:36 +01:00
|
|
|
import org.bukkit.event.entity.EntityDeathEvent;
|
2012-01-19 08:38:40 +01:00
|
|
|
import org.bukkit.event.entity.EntityTargetEvent;
|
2012-01-23 15:30:15 +01:00
|
|
|
import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
|
2012-02-26 07:35:44 +01:00
|
|
|
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
2012-01-23 15:30:15 +01:00
|
|
|
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
2012-02-27 14:01:38 +01:00
|
|
|
import org.bukkit.event.player.PlayerQuitEvent;
|
2012-01-19 08:38:40 +01:00
|
|
|
import org.bukkit.event.world.ChunkLoadEvent;
|
|
|
|
import org.bukkit.event.world.ChunkUnloadEvent;
|
2012-02-26 06:23:43 +01:00
|
|
|
import org.bukkit.event.world.WorldLoadEvent;
|
|
|
|
import org.bukkit.event.world.WorldUnloadEvent;
|
2012-01-19 08:38:40 +01:00
|
|
|
|
2012-03-02 11:59:40 +01:00
|
|
|
import com.google.common.collect.ArrayListMultimap;
|
|
|
|
import com.google.common.collect.ListMultimap;
|
|
|
|
|
2012-01-19 08:38:40 +01:00
|
|
|
public class EventListen implements Listener {
|
2012-05-17 17:14:30 +02:00
|
|
|
private final NPCRegistry npcRegistry = CitizensAPI.getNPCRegistry();
|
2012-07-21 08:11:32 +02:00
|
|
|
private final ListMultimap<ChunkCoord, Integer> toRespawn = ArrayListMultimap.create();
|
2012-01-22 08:10:25 +01:00
|
|
|
|
2012-01-19 12:43:21 +01:00
|
|
|
/*
|
2012-03-06 01:32:53 +01:00
|
|
|
* Chunk events
|
2012-01-19 12:43:21 +01:00
|
|
|
*/
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-01-19 12:43:21 +01:00
|
|
|
public void onChunkLoad(ChunkLoadEvent event) {
|
2012-07-21 08:11:32 +02:00
|
|
|
ChunkCoord coord = toCoord(event.getChunk());
|
2012-03-02 11:59:40 +01:00
|
|
|
if (!toRespawn.containsKey(coord))
|
2012-02-19 18:45:43 +01:00
|
|
|
return;
|
2012-03-02 11:59:40 +01:00
|
|
|
for (int id : toRespawn.get(coord)) {
|
2012-07-19 17:10:30 +02:00
|
|
|
NPC npc = npcRegistry.getById(id);
|
2012-03-12 07:26:08 +01:00
|
|
|
npc.spawn(npc.getTrait(CurrentLocation.class).getLocation());
|
2012-01-19 12:43:21 +01:00
|
|
|
}
|
2012-03-02 11:59:40 +01:00
|
|
|
toRespawn.removeAll(coord);
|
2012-01-19 12:43:21 +01:00
|
|
|
}
|
2012-01-19 08:38:40 +01:00
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-01-19 12:43:21 +01:00
|
|
|
public void onChunkUnload(ChunkUnloadEvent event) {
|
2012-07-21 08:11:32 +02:00
|
|
|
ChunkCoord coord = toCoord(event.getChunk());
|
2012-05-17 17:14:30 +02:00
|
|
|
for (NPC npc : npcRegistry) {
|
2012-01-28 21:16:30 +01:00
|
|
|
if (!npc.isSpawned())
|
2012-02-26 06:23:43 +01:00
|
|
|
continue;
|
2012-01-21 17:21:21 +01:00
|
|
|
Location loc = npc.getBukkitEntity().getLocation();
|
2012-07-21 08:11:32 +02:00
|
|
|
Chunk chunk = loc.getChunk();
|
|
|
|
if (event.getWorld().equals(loc.getWorld()) && event.getChunk().getX() == chunk.getX()
|
|
|
|
&& event.getChunk().getZ() == chunk.getZ()) {
|
2012-01-19 12:43:21 +01:00
|
|
|
npc.despawn();
|
2012-03-02 11:59:40 +01:00
|
|
|
toRespawn.put(coord, npc.getId());
|
2012-01-19 12:43:21 +01:00
|
|
|
}
|
|
|
|
}
|
2012-02-26 06:23:43 +01:00
|
|
|
}
|
|
|
|
|
2012-01-23 09:45:34 +01:00
|
|
|
/*
|
|
|
|
* Entity events
|
|
|
|
*/
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-01-23 09:45:34 +01:00
|
|
|
public void onEntityDamage(EntityDamageEvent event) {
|
2012-05-17 17:14:30 +02:00
|
|
|
if (!npcRegistry.isNPC(event.getEntity()))
|
2012-01-23 09:45:34 +01:00
|
|
|
return;
|
|
|
|
|
2012-05-17 17:14:30 +02:00
|
|
|
NPC npc = npcRegistry.getNPC(event.getEntity());
|
2012-01-23 09:45:34 +01:00
|
|
|
if (event instanceof EntityDamageByEntityEvent) {
|
2012-07-21 08:11:32 +02:00
|
|
|
NPCDamageByEntityEvent damageEvent = new NPCDamageByEntityEvent(npc,
|
|
|
|
(EntityDamageByEntityEvent) event);
|
2012-05-14 13:45:16 +02:00
|
|
|
Bukkit.getPluginManager().callEvent(damageEvent);
|
2012-05-12 09:13:58 +02:00
|
|
|
|
2012-05-14 13:45:16 +02:00
|
|
|
if (!damageEvent.isCancelled() || !(damageEvent.getDamager() instanceof Player))
|
2012-05-12 09:13:58 +02:00
|
|
|
return;
|
2012-05-14 13:45:16 +02:00
|
|
|
Player damager = (Player) damageEvent.getDamager();
|
2012-05-12 09:13:58 +02:00
|
|
|
|
|
|
|
// Call left-click event
|
|
|
|
NPCLeftClickEvent leftClickEvent = new NPCLeftClickEvent(npc, damager);
|
|
|
|
Bukkit.getPluginManager().callEvent(leftClickEvent);
|
2012-08-15 18:13:46 +02:00
|
|
|
} else if (event instanceof EntityDamageByBlockEvent) {
|
|
|
|
Bukkit.getPluginManager().callEvent(
|
|
|
|
new NPCDamageByBlockEvent(npc, (EntityDamageByBlockEvent) event));
|
2012-05-13 13:41:21 +02:00
|
|
|
} else {
|
|
|
|
Bukkit.getPluginManager().callEvent(new NPCDamageEvent(npc, event));
|
2012-01-23 09:45:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-03-27 16:42:15 +02:00
|
|
|
public void onEntityDeath(EntityDeathEvent event) {
|
2012-05-17 17:14:30 +02:00
|
|
|
if (!npcRegistry.isNPC(event.getEntity()))
|
2012-03-27 16:42:15 +02:00
|
|
|
return;
|
2012-05-17 17:14:30 +02:00
|
|
|
NPC npc = npcRegistry.getNPC(event.getEntity());
|
2012-03-27 16:42:15 +02:00
|
|
|
npc.despawn();
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-01-23 09:45:34 +01:00
|
|
|
public void onEntityTarget(EntityTargetEvent event) {
|
2012-07-21 08:11:32 +02:00
|
|
|
if (!npcRegistry.isNPC(event.getEntity()) || !(event.getTarget() instanceof Player))
|
2012-01-29 00:19:45 +01:00
|
|
|
return;
|
2012-01-23 09:45:34 +01:00
|
|
|
|
2012-05-17 17:14:30 +02:00
|
|
|
NPC npc = npcRegistry.getNPC(event.getEntity());
|
2012-01-23 15:30:15 +01:00
|
|
|
Player player = (Player) event.getTarget();
|
2012-03-11 07:43:18 +01:00
|
|
|
|
|
|
|
// Call right-click event
|
|
|
|
NPCRightClickEvent rightClickEvent = new NPCRightClickEvent(npc, player);
|
|
|
|
Bukkit.getPluginManager().callEvent(rightClickEvent);
|
2012-01-23 15:30:15 +01:00
|
|
|
}
|
|
|
|
|
2012-03-06 01:32:53 +01:00
|
|
|
/*
|
|
|
|
* Player events
|
|
|
|
*/
|
2012-08-15 18:06:13 +02:00
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-03-02 11:36:54 +01:00
|
|
|
public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
|
2012-07-21 08:11:32 +02:00
|
|
|
EntityPlayer handle = ((CraftPlayer) event.getPlayer()).getHandle();
|
|
|
|
if (!(handle instanceof EntityHumanNPC))
|
2012-03-02 11:36:54 +01:00
|
|
|
return;
|
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
((CraftServer) Bukkit.getServer()).getHandle().players.remove(handle);
|
|
|
|
// on teleport, player NPCs are added to the server player list. this is
|
|
|
|
// undesirable as player NPCs are not real players and confuse plugins.
|
2012-02-27 14:01:38 +01:00
|
|
|
}
|
|
|
|
|
2012-08-29 15:37:00 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
|
|
|
public void onPlayerCreateNPC(PlayerCreateNPCEvent event) {
|
|
|
|
if (event.getCreator().hasPermission("citizens.admin.avoid-limits"))
|
|
|
|
return;
|
|
|
|
int limit = Setting.DEFAULT_NPC_LIMIT.asInt();
|
|
|
|
int maxChecks = Setting.MAX_NPC_LIMIT_CHECKS.asInt();
|
|
|
|
for (int i = maxChecks; i >= 0; i--) {
|
|
|
|
if (!event.getCreator().hasPermission("citizens.npc.limit." + i))
|
|
|
|
continue;
|
|
|
|
limit = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (limit < 0)
|
|
|
|
return;
|
|
|
|
int owned = 0;
|
|
|
|
for (NPC npc : npcRegistry) {
|
|
|
|
if (npc.getTrait(Owner.class).isOwnedBy(event.getCreator()))
|
|
|
|
owned++;
|
|
|
|
}
|
|
|
|
if (limit >= owned + 1 || limit == 0) {
|
|
|
|
event.setCancelled(true);
|
|
|
|
event.setCancelReason(String.format("Over the NPC limit of %d.", limit));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-01-23 15:30:15 +01:00
|
|
|
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
2012-05-17 17:14:30 +02:00
|
|
|
if (!npcRegistry.isNPC(event.getRightClicked()))
|
2012-01-23 15:30:15 +01:00
|
|
|
return;
|
|
|
|
|
2012-03-11 07:43:18 +01:00
|
|
|
// Call target event for NPCs
|
2012-01-23 15:30:15 +01:00
|
|
|
Bukkit.getPluginManager().callEvent(
|
|
|
|
new EntityTargetEvent(event.getRightClicked(), event.getPlayer(), TargetReason.CUSTOM));
|
2012-01-23 09:45:34 +01:00
|
|
|
}
|
2012-02-26 07:35:44 +01:00
|
|
|
|
2012-07-24 08:47:10 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
|
|
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
|
|
Editor.leave(event.getPlayer());
|
|
|
|
}
|
|
|
|
|
2012-03-06 01:32:53 +01:00
|
|
|
/*
|
|
|
|
* World events
|
|
|
|
*/
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-03-02 11:36:54 +01:00
|
|
|
public void onWorldLoad(WorldLoadEvent event) {
|
2012-07-21 08:11:32 +02:00
|
|
|
for (ChunkCoord chunk : toRespawn.keySet()) {
|
|
|
|
if (!event.getWorld().isChunkLoaded(chunk.x, chunk.z))
|
2012-03-02 11:59:40 +01:00
|
|
|
continue;
|
|
|
|
for (int id : toRespawn.get(chunk)) {
|
2012-07-19 17:10:30 +02:00
|
|
|
NPC npc = npcRegistry.getById(id);
|
2012-03-12 07:26:08 +01:00
|
|
|
npc.spawn(npc.getTrait(CurrentLocation.class).getLocation());
|
2012-03-02 11:36:54 +01:00
|
|
|
}
|
2012-03-02 11:59:40 +01:00
|
|
|
toRespawn.removeAll(chunk);
|
2012-03-02 11:36:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
@EventHandler(ignoreCancelled = true)
|
2012-03-02 11:36:54 +01:00
|
|
|
public void onWorldUnload(WorldUnloadEvent event) {
|
2012-05-17 17:14:30 +02:00
|
|
|
for (NPC npc : npcRegistry) {
|
2012-03-02 11:36:54 +01:00
|
|
|
if (!npc.isSpawned() || !npc.getBukkitEntity().getWorld().equals(event.getWorld()))
|
|
|
|
continue;
|
2012-03-12 07:26:08 +01:00
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
storeForRespawn(npc);
|
2012-07-24 08:21:59 +02:00
|
|
|
npc.despawn();
|
2012-03-02 11:36:54 +01:00
|
|
|
}
|
2012-02-26 07:35:44 +01:00
|
|
|
}
|
2012-03-02 11:59:40 +01:00
|
|
|
|
2012-07-21 08:11:32 +02:00
|
|
|
private void storeForRespawn(NPC npc) {
|
|
|
|
toRespawn.put(toCoord(npc.getBukkitEntity().getLocation().getChunk()), npc.getId());
|
|
|
|
}
|
|
|
|
|
|
|
|
private ChunkCoord toCoord(Chunk chunk) {
|
|
|
|
return new ChunkCoord(chunk);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class ChunkCoord {
|
|
|
|
private final int x;
|
|
|
|
private final int z;
|
|
|
|
|
|
|
|
private ChunkCoord(Chunk chunk) {
|
|
|
|
this(chunk.getX(), chunk.getZ());
|
|
|
|
}
|
|
|
|
|
2012-07-22 08:18:24 +02:00
|
|
|
private ChunkCoord(int x, int z) {
|
|
|
|
this.x = x;
|
|
|
|
this.z = z;
|
2012-07-21 08:11:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
if (this == obj) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (obj == null || getClass() != obj.getClass()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ChunkCoord other = (ChunkCoord) obj;
|
|
|
|
return x == other.x && z == other.z;
|
|
|
|
}
|
2012-07-22 08:18:24 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
final int prime = 31;
|
|
|
|
return prime * (prime + x) + z;
|
|
|
|
}
|
2012-03-02 11:59:40 +01:00
|
|
|
}
|
2012-01-19 08:38:40 +01:00
|
|
|
}
|