package com.nisovin.magicspells.util;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.spells.targeted.DisguiseSpell;
public abstract class DisguiseManager implements Listener {
protected boolean hideArmor;
protected Set<DisguiseSpell> disguiseSpells = new HashSet<DisguiseSpell>();
protected Map<String, DisguiseSpell.Disguise> disguises = new ConcurrentHashMap<String, DisguiseSpell.Disguise>();
protected Map<Integer, DisguiseSpell.Disguise> disguisedEntityIds = new ConcurrentHashMap<Integer, DisguiseSpell.Disguise>();
protected Set<Integer> dragons = Collections.synchronizedSet(new HashSet<Integer>());
protected Map<Integer, Integer> mounts = new ConcurrentHashMap<Integer, Integer>();
protected Random random = new Random();
public DisguiseManager(MagicConfig config) {
this.hideArmor = config.getBoolean("general.disguise-spell-hide-armor", false);
Bukkit.getPluginManager().registerEvents(this, MagicSpells.plugin);
}
public void registerSpell(DisguiseSpell spell) {
disguiseSpells.add(spell);
}
public void unregisterSpell(DisguiseSpell spell) {
disguiseSpells.remove(spell);
}
public int registeredSpellsCount() {
return disguiseSpells.size();
}
public void addDisguise(Player player, DisguiseSpell.Disguise disguise) {
if (isDisguised(player)) {
removeDisguise(player);
}
disguises.put(player.getName().toLowerCase(), disguise);
disguisedEntityIds.put(player.getEntityId(), disguise);
if (disguise.getEntityType() == EntityType.ENDER_DRAGON) {
dragons.add(player.getEntityId());
}
applyDisguise(player, disguise);
}
public void removeDisguise(Player player) {
removeDisguise(player, true);
}
public void removeDisguise(Player player, boolean sendPlayerPackets) {
removeDisguise(player, sendPlayerPackets, true);
}
public void removeDisguise(Player player, boolean sendPlayerPackets, boolean delaySpawnPacket) {
DisguiseSpell.Disguise disguise = disguises.get(player.getName().toLowerCase());
disguisedEntityIds.remove(player.getEntityId());
dragons.remove(player.getEntityId());
if (disguise != null) {
clearDisguise(player, sendPlayerPackets, delaySpawnPacket);
disguise.getSpell().undisguise(player);
disguises.remove(player.getName().toLowerCase());
}
mounts.remove(player.getEntityId());
}
public boolean isDisguised(Player player) {
return disguises.containsKey(player.getName().toLowerCase());
}
public DisguiseSpell.Disguise getDisguise(Player player) {
return disguises.get(player.getName().toLowerCase());
}
public void destroy() {
HandlerList.unregisterAll(this);
cleanup();
disguises.clear();
disguisedEntityIds.clear();
dragons.clear();
mounts.clear();
disguiseSpells.clear();
}
protected abstract void cleanup();
private void applyDisguise(final Player player, final DisguiseSpell.Disguise disguise) {
sendDestroyEntityPackets(player);
MagicSpells.scheduleDelayedTask(new Runnable() {
public void run() {
sendDisguisedSpawnPackets(player, disguise);
}
}, 5);
}
private void clearDisguise(final Player player, boolean sendPlayerPackets, boolean delaySpawnPacket) {
if (sendPlayerPackets) {
sendDestroyEntityPackets(player);
}
if (mounts.containsKey(player.getEntityId())) {
sendDestroyEntityPackets(player, mounts.remove(player.getEntityId()));
}
if (sendPlayerPackets && player.isValid()) {
if (delaySpawnPacket) {
MagicSpells.scheduleDelayedTask(new Runnable() {
public void run() {
sendPlayerSpawnPackets(player);
}
}, 5);
} else {
sendPlayerSpawnPackets(player);
}
}
}
protected abstract void sendDestroyEntityPackets(Player disguised);
protected abstract void sendDestroyEntityPackets(Player disguised, int entityId);
protected abstract void sendDisguisedSpawnPackets(Player disguised, DisguiseSpell.Disguise disguise);
protected abstract void sendPlayerSpawnPackets(Player player);
@EventHandler
public void onQuit(PlayerQuitEvent event) {
disguisedEntityIds.remove(event.getPlayer().getEntityId());
dragons.remove(event.getPlayer().getEntityId());
if (mounts.containsKey(event.getPlayer().getEntityId())) {
sendDestroyEntityPackets(event.getPlayer(), mounts.remove(event.getPlayer().getEntityId()));
}
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player p = event.getPlayer();
if (isDisguised(p)) {
disguisedEntityIds.put(p.getEntityId(), getDisguise(p));
if (getDisguise(p).getEntityType() == EntityType.ENDER_DRAGON) {
dragons.add(p.getEntityId());
}
}
}
}