package com.github.jamesnorris.ablockalypse.aspect;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import com.github.jamesnorris.ablockalypse.Ablockalypse;
import com.github.jamesnorris.ablockalypse.DataContainer;
import com.github.jamesnorris.ablockalypse.behavior.GameAspect;
import com.github.jamesnorris.ablockalypse.behavior.Targettable;
import com.github.jamesnorris.ablockalypse.threading.DelayedTask;
import com.github.jamesnorris.ablockalypse.threading.inherent.MobTargetterTask;
import com.github.jamesnorris.ablockalypse.utility.SpawnUtility;
import com.github.jamesnorris.mcshot.type.EntityHitBox;
public class ZAMob extends ZALiving implements GameAspect {
protected static DataContainer data = Ablockalypse.getData();
private MobTargetterTask targetter;
private double absorption = 0F;
protected LivingEntity entity;
protected Game game;
private EntityHitBox hitBox;
public ZAMob(LivingEntity entity, Game game) {
super(entity);
this.entity = super.getEntity();
this.game = game;
if (entity == null) {
remove();
return;
}
hitBox = new EntityHitBox(entity, getLength(), getWidth(), getHeight());
data.objects.add(hitBox);
data.objects.add(this);
game.addObject(this);
game.setMobCountSpawnedInThisRound(game.getMobCountSpawnedInThisRound() + 1);
game.setMobCount(game.getMobCount() + 1);
targetter = new MobTargetterTask(this, (Targettable) null, true);
retarget();
}
public ZAMob(Map<String, Object> savings) {
this((LivingEntity) data.getEntityByUUID(Bukkit.getWorld((UUID) savings.get("world_uuid")), (UUID) savings.get("entity_uuid")), Ablockalypse.getData().getGame((String) savings.get("game_name"), true));
absorption = (Double) savings.get("hit_absorption");
}
@Override public Block getDefiningBlock() {
if (entity == null) {
return null;
}
return entity.getLocation().clone().subtract(0, 1, 0).getBlock();
}
/**
* Gets the blocks that defines this object as an object.
*
* @return The blocks assigned to this object
*/
@Override public ArrayList<Block> getDefiningBlocks() {
ArrayList<Block> blocks = new ArrayList<Block>();
blocks.add(getDefiningBlock());
return blocks;
}
/**
* Gets the Entity instance of the mob.
*
* @return The Entity associated with this instance
*/
@Override public LivingEntity getEntity() {
return entity;
}
/**
* Gets the game that this mob is in.
*
* @return The game that this mob is in
*/
@Override public Game getGame() {
return game;
}
@Override public String getHeader() {
return this.getClass().getSimpleName() + " <UUID: " + getUUID().toString() + ">";
}
public double getHeight() {
return 1D;
}
public double getHitAbsorption() {
return absorption;
}
public EntityHitBox getHitBox() {
return hitBox;
}
public double getLength() {
return 1D;
}
@Override public int getLoadPriority() {
return 3;
}
@Override public Map<String, Object> getSave() {
Map<String, Object> savings = new HashMap<String, Object>();
savings.put("hit_absorption", absorption);
savings.put("game_name", game.getName());
savings.put("entity_uuid", entity.getUniqueId());
savings.put("world_uuid", entity.getWorld().getUID());
return savings;
}
/* In nodes per tick */
public double getSpeed() {
return 1D;
}
/**
* Gets the targetter for this mob.
*
* @return The targetter attached to this instance
*/
public MobTargetterTask getTargetter() {
return targetter;
}
@Override public UUID getUUID() {
return entity.getUniqueId();
}
public double getWidth() {
return 1D;
}
/**
* Kills the undead and finalized the instance.
*/
public void kill() {
if (game != null && game.hasMob(this)) {
game.removeObject(this);
}
if (entity != null) {
entity.getWorld().playEffect(entity.getLocation(), Effect.EXTINGUISH, 1);
new DelayedTask(40, true) {
@Override public void run() {
if (entity != null) {
entity.remove();
entity = null;
}
}
};
}
if (hitBox != null) {
data.objects.remove(hitBox);
}
data.objects.remove(this);
game.setMobCount(game.getMobCount() - 1);
}
public boolean isValid() {
return entity != null && !entity.isDead();
}
@Override public void onGameEnd() {
kill();
}
@Override public void onGameStart() {}
@Override public void onLevelEnd() {
kill();// don't know when this would happen, but it doesn't hurt to be safe
}
@Override public void onNextLevel() {}
@Override public void remove() {
kill();
}
public void retarget() {
Player player = game.getClosestLivingPlayer(entity.getLocation());
Barrier barrier = SpawnUtility.getClosestBarrier(game, player == null || !data.isZAPlayer(player) ? entity.getLocation() : player.getLocation());
Targettable target = (barrier != null && barrier.isResponsive()) && (player == null || !data.isZAPlayer(player) || barrier.getCenter().distance(entity.getLocation()) < player.getLocation().distance(entity.getLocation())) ? barrier : data.getZAPlayer(player);
targetter.setTarget(target);
}
public void setHitAbsorption(double absorption) {
this.absorption = absorption;
}
public void setHitBox(EntityHitBox hitBox) {
data.objects.remove(this.hitBox);
this.hitBox = hitBox;
if (hitBox == null) {
return;
}
data.objects.add(hitBox);
}
}