package be.isach.ultracosmetics.cosmetics.pets;
import be.isach.ultracosmetics.UltraCosmetics;
import be.isach.ultracosmetics.UltraCosmeticsData;
import be.isach.ultracosmetics.config.SettingsManager;
import be.isach.ultracosmetics.cosmetics.Category;
import be.isach.ultracosmetics.cosmetics.Cosmetic;
import be.isach.ultracosmetics.cosmetics.Updatable;
import be.isach.ultracosmetics.cosmetics.type.PetType;
import be.isach.ultracosmetics.player.UltraPlayer;
import be.isach.ultracosmetics.util.EntitySpawningManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.metadata.FixedMetadataValue;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Represents an instance of a pet summoned by a player.
*
* @author iSach
* @since 03-08-2015
*/
public abstract class Pet extends Cosmetic<PetType> implements Updatable {
/**
* List of items popping out from Pet.
*/
public ArrayList<Item> items = new ArrayList<>();
/**
* ArmorStand for nametags. Most pets don't use this.
*/
public ArmorStand armorStand;
/**
* Runs the task for pets following players
*/
protected ExecutorService pathUpdater;
/**
* Task that forces pets to follow player
*/
protected IPlayerFollower followTask;
/**
* If Pet is a normal entity, it will be stored here.
*/
public Entity entity;
public Pet(UltraPlayer owner, UltraCosmetics ultraCosmetics, PetType petType) {
super(ultraCosmetics, Category.PETS, owner, petType);
this.pathUpdater = Executors.newSingleThreadExecutor();
}
@Override
protected void onEquip() {
if (getOwner().getCurrentPet() != null) {
getOwner().removePet();
}
this.followTask = UltraCosmeticsData.get().getVersionManager().newPlayerFollower(this, getPlayer());
getOwner().setCurrentPet(this);
runTaskTimer(getUltraCosmetics(), 0, 3);
// Bypass WorldGuard protection.
EntitySpawningManager.setBypass(true);
this.entity = getPlayer().getWorld().spawnEntity(getPlayer().getLocation(), getType().getEntityType());
EntitySpawningManager.setBypass(false);
if (entity instanceof Ageable) {
if (SettingsManager.getConfig().getBoolean("Pets-Are-Babies")) {
((Ageable) entity).setBaby();
} else {
((Ageable) entity).setAdult();
}
((Ageable) entity).setAgeLock(true);
}
getEntity().setCustomNameVisible(true);
getEntity().setCustomName(getType().getEntityName(getPlayer()));
if (getOwner().getPetName(getType()) != null) {
getEntity().setCustomName(getOwner().getPetName(getType()));
}
((LivingEntity) entity).setRemoveWhenFarAway(false);
UltraCosmeticsData.get().getVersionManager().getPathfinderUtil().removePathFinders(entity);
this.entity.setMetadata("Pet", new FixedMetadataValue(getUltraCosmetics(), "UltraCosmetics"));
}
@Override
public void run() {
try {
if (!entity.isValid()) {
if (armorStand != null) {
armorStand.remove();
}
entity.remove();
if (getPlayer() != null) {
getOwner().setCurrentPet(null);
}
items.forEach(Entity::remove);
items.clear();
try {
HandlerList.unregisterAll(this);
} catch (Exception ignored) {
// Ignored.
}
cancel();
return;
}
if (Bukkit.getPlayer(getOwnerUniqueId()) != null
&& getOwner().getCurrentPet() != null
&& getOwner().getCurrentPet().getType() == getType()) {
if (SettingsManager.getConfig().getBoolean("Pets-Drop-Items")) {
onUpdate();
}
pathUpdater.submit(followTask.getTask());
} else {
cancel();
if (armorStand != null) {
armorStand.remove();
}
items.forEach(Entity::remove);
items.clear();
clear();
return;
}
} catch (NullPointerException exc) {
exc.printStackTrace();
cancel();
if (armorStand != null) {
armorStand.remove();
}
items.forEach(Entity::remove);
items.clear();
clear();
}
}
@Override
protected void onClear() {
// Remove Armor Stand.
if (armorStand != null) {
armorStand.remove();
}
// Remove Pet Entity.
removeEntity();
// Remove items.
items.stream().filter(Entity::isValid).forEach(Entity::remove);
// Clear items.
items.clear();
// Shutdown path updater.
pathUpdater.shutdown();
// Empty current Pet.
if (getPlayer() != null && getOwner() != null) {
getOwner().setCurrentPet(null);
}
}
public boolean isCustomEntity() {
return false;
}
protected void removeEntity() {
if (entity != null) {
entity.remove();
}
}
public IPlayerFollower getFollowTask() {
return followTask;
}
public Entity getEntity() {
return entity;
}
@EventHandler
public void onEntityDamage(EntityDamageEvent event) {
if (event.getEntity() == getEntity())
event.setCancelled(true);
}
@EventHandler
public void onPlayerTeleport(PlayerTeleportEvent event) {
if (event.getPlayer() == getPlayer())
getEntity().teleport(getPlayer());
}
}