/*
* Copyright (C) 2016 eccentric_nz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.eccentric_nz.TARDIS.move;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import me.eccentric_nz.TARDIS.ARS.TARDISARSMethods;
import me.eccentric_nz.TARDIS.TARDIS;
import me.eccentric_nz.TARDIS.builders.TARDISInteriorPostioning;
import me.eccentric_nz.TARDIS.builders.TARDISTIPSData;
import me.eccentric_nz.TARDIS.database.ResultSetARS;
import me.eccentric_nz.TARDIS.database.ResultSetCompanions;
import me.eccentric_nz.TARDIS.database.ResultSetControls;
import me.eccentric_nz.TARDIS.database.ResultSetHidden;
import me.eccentric_nz.TARDIS.database.ResultSetTardis;
import me.eccentric_nz.TARDIS.database.ResultSetTravellers;
import me.eccentric_nz.TARDIS.planets.TARDISAngelsAPI;
import me.eccentric_nz.TARDIS.utility.TARDISDalekDisguiser;
import me.eccentric_nz.TARDIS.utility.TARDISLocationGetters;
import me.eccentric_nz.TARDIS.utility.TARDISMessage;
import me.eccentric_nz.TARDIS.utility.TARDISSounds;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Difficulty;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.PigZombie;
import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton;
import org.bukkit.entity.Skeleton.SkeletonType;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Villager.Profession;
import org.bukkit.entity.Zombie;
import org.bukkit.inventory.EntityEquipment;
/**
*
* @author eccentric_nz
*/
public class TARDISMonsterRunnable implements Runnable {
private final TARDIS plugin;
private final List<EntityType> monsters = new ArrayList<EntityType>();
private final List<EntityType> random_monsters = new ArrayList<EntityType>();
public TARDISMonsterRunnable(TARDIS plugin) {
this.plugin = plugin;
monsters.add(EntityType.CAVE_SPIDER);
monsters.add(EntityType.CREEPER);
monsters.add(EntityType.ENDERMAN);
monsters.add(EntityType.ENDERMITE);
monsters.add(EntityType.PIG_ZOMBIE);
monsters.add(EntityType.SILVERFISH);
monsters.add(EntityType.SKELETON);
monsters.add(EntityType.SLIME);
monsters.add(EntityType.SPIDER);
monsters.add(EntityType.WITCH);
monsters.add(EntityType.ZOMBIE);
if (this.plugin.getConfig().getBoolean("allow.guardians")) {
monsters.add(EntityType.GUARDIAN);
} else {
random_monsters.add(EntityType.GUARDIAN);
}
random_monsters.addAll(monsters);
}
@Override
public void run() {
// get open portals
for (Map.Entry<Location, TARDISTeleportLocation> map : plugin.getTrackerKeeper().getPortals().entrySet()) {
// only portals in police box worlds
if (!map.getKey().getWorld().getName().contains("TARDIS") && !map.getValue().isAbandoned()) {
// only police boxes that are not hidden
boolean hidden = new ResultSetHidden(plugin, map.getValue().getTardisId()).isVisible();
if (!hidden) {
Entity ent = map.getKey().getWorld().spawnEntity(map.getKey(), EntityType.EXPERIENCE_ORB);
List<Entity> entities = ent.getNearbyEntities(16, 16, 16);
ent.remove();
boolean found = false;
if (entities.size() > 0) {
// check if a Time Lord or companion is near
boolean take_action = true;
for (Entity e : entities) {
if (e instanceof Player && isTimelord(map.getValue(), e)) {
take_action = false;
break;
}
}
// nobody there so continue
if (take_action) {
boolean twa = plugin.getPM().isPluginEnabled("TARDISWeepingAngels");
for (Entity e : entities) {
EntityType type = e.getType();
TARDISMonster tm = new TARDISMonster();
String dn = WordUtils.capitalize(type.toString().toLowerCase());
if (monsters.contains(type)) {
found = true;
switch (type) {
case CREEPER:
Creeper creeper = (Creeper) e;
tm.setCharged(creeper.isPowered());
dn = (creeper.isPowered()) ? "Charged Creeper" : "Creeper";
break;
case ENDERMAN:
Enderman enderman = (Enderman) e;
tm.setCarried(enderman.getCarriedMaterial());
if (twa && e.getPassenger() != null && e.getPassenger().getType().equals(EntityType.GUARDIAN)) {
dn = "Silent";
}
break;
case PIG_ZOMBIE:
PigZombie pigzombie = (PigZombie) e;
tm.setAggressive(pigzombie.isAngry());
tm.setAnger(pigzombie.getAnger());
tm.setEquipment(pigzombie.getEquipment());
if (twa && pigzombie.getEquipment().getHelmet() != null && pigzombie.getEquipment().getHelmet().hasItemMeta() && pigzombie.getEquipment().getHelmet().getItemMeta().hasDisplayName()) {
String name = pigzombie.getEquipment().getHelmet().getItemMeta().getDisplayName();
if (name.equals("Ice Warrior Head") || name.equals("Strax Head")) {
dn = name.substring(0, name.length() - 5);
}
} else {
dn = "Pig Zombie";
}
break;
case SKELETON:
Skeleton skeleton = (Skeleton) e;
tm.setEquipment(skeleton.getEquipment());
tm.setSkeletonType(skeleton.getSkeletonType());
if (twa && skeleton.getEquipment().getHelmet() != null && skeleton.getEquipment().getHelmet().hasItemMeta() && skeleton.getEquipment().getHelmet().getItemMeta().hasDisplayName()) {
String name = skeleton.getEquipment().getHelmet().getItemMeta().getDisplayName();
if (name.equals("Dalek Head") || name.equals("Silurian Head") || name.equals("Weeping Angel Head")) {
dn = name.substring(0, name.length() - 5);
}
}
switch (skeleton.getSkeletonType()) {
case WITHER:
dn = "Wither Skeleton";
break;
case STRAY:
dn = "Stray";
break;
default:
break;
}
break;
case SLIME:
Slime slime = (Slime) e;
tm.setSize(slime.getSize());
break;
case ZOMBIE:
Zombie zombie = (Zombie) e;
Profession prof = zombie.getVillagerProfession();
tm.setProfession(prof);
if (prof != null) {
switch (prof) {
case NORMAL:
break;
case HUSK:
dn = "Husk";
break;
default:
dn = "Zombie " + WordUtils.capitalize(prof.toString().toLowerCase());
}
}
tm.setBaby(zombie.isBaby());
tm.setEquipment(zombie.getEquipment());
if (twa && zombie.getEquipment().getHelmet() != null && zombie.getEquipment().getHelmet().hasItemMeta() && zombie.getEquipment().getHelmet().getItemMeta().hasDisplayName()) {
String name = zombie.getEquipment().getHelmet().getItemMeta().getDisplayName();
if (name.equals("Cyberman Head") || name.equals("Empty Child Head") || name.equals("Sontaran Head") || name.equals("Vashta Nerada Head") || name.equals("Zygon Head")) {
dn = name.substring(0, name.length() - 5);
}
}
break;
default:
break;
}
tm.setDisplayName(dn);
tm.setType(type);
tm.setAge(e.getTicksLived());
tm.setHealth(((LivingEntity) e).getHealth());
tm.setName(((LivingEntity) e).getCustomName());
if (e.getPassenger() != null) {
tm.setPassenger(e.getPassenger().getType());
}
moveMonster(map.getValue(), tm, e, type.equals(EntityType.GUARDIAN));
}
}
}
}
if (found == false && plugin.getConfig().getBoolean("preferences.spawn_random_monsters")) {
// spawn a random mob inside TARDIS?
Random r = new Random();
// 25% chance + must not be peaceful, a Mooshroom biome or WG mob-spawning: deny
if (r.nextInt(4) == 0 && canSpawn(map.getKey(), r.nextInt(4))) {
HashMap<String, Object> wheret = new HashMap<String, Object>();
wheret.put("tardis_id", map.getValue().getTardisId());
ResultSetTardis rs = new ResultSetTardis(plugin, wheret, "", false, 2);
if (rs.resultSet() && rs.getTardis().getMonsters() < plugin.getConfig().getInt("preferences.spawn_limit")) {
TARDISMonster rtm = new TARDISMonster();
// choose a random monster
EntityType type = random_monsters.get(r.nextInt(random_monsters.size()));
rtm.setType(type);
String dn = WordUtils.capitalize(type.toString().toLowerCase());
// set random sub types eg. Husk, Zombie Villagers, Stray & Wither Skeletons
switch (type) {
case SKELETON:
SkeletonType st = SkeletonType.values()[r.nextInt(3)];
rtm.setSkeletonType(st);
switch (st) {
case WITHER:
dn = "Wither Skeleton";
break;
case STRAY:
dn = "Stray";
break;
default:
break;
}
break;
case ZOMBIE:
Profession prof = Profession.values()[r.nextInt(7)];
rtm.setProfession(prof);
switch (prof) {
case NORMAL:
break;
case HUSK:
dn = "Husk";
break;
default:
dn = "Zombie " + WordUtils.capitalize(prof.toString().toLowerCase());
}
break;
default:
break;
}
rtm.setDisplayName(dn);
moveMonster(map.getValue(), rtm, null, type.equals(EntityType.GUARDIAN));
}
}
}
}
}
}
}
private boolean canSpawn(Location l, int r) {
// get biome
Biome biome = l.getBlock().getRelative(plugin.getGeneralKeeper().getFaces().get(r), 2).getBiome();
if (biome.equals(Biome.MUSHROOM_ISLAND) || biome.equals(Biome.MUSHROOM_ISLAND_SHORE)) {
return false;
}
// worldguard
if (plugin.isWorldGuardOnServer() && !plugin.getWorldGuardUtils().mobsCanSpawnAtLocation(l)) {
return false;
}
// difficulty
return !l.getWorld().getDifficulty().equals(Difficulty.PEACEFUL);
}
private void moveMonster(TARDISTeleportLocation tpl, TARDISMonster m, Entity e, boolean guardian) {
Location loc = null;
if (guardian) {
// check for pool
HashMap<String, Object> wherea = new HashMap<String, Object>();
wherea.put("tardis_id", tpl.getTardisId());
ResultSetARS rsa = new ResultSetARS(plugin, wherea);
if (rsa.resultSet()) {
int l = 0, r = 0, c = 0;
// check there is a pool
int[][][] json = TARDISARSMethods.getGridFromJSON(rsa.getJson());
for (int[][] level : json) {
for (int[] row : level) {
for (int col : row) {
if (col == 80) {
// need to get the console location - will be different for non-TIPS TARDISes
HashMap<String, Object> wheret = new HashMap<String, Object>();
wheret.put("tardis_id", tpl.getTardisId());
ResultSetTardis rs = new ResultSetTardis(plugin, wheret, "", false, 2);
if (rs.resultSet()) {
int pos = rs.getTardis().getTIPS();
int tx = 0, tz = 0;
if (pos != -1) {
// tips slot
TARDISInteriorPostioning tips = new TARDISInteriorPostioning(plugin);
TARDISTIPSData coords = tips.getTIPSData(pos);
tx = coords.getCentreX();
tz = coords.getCentreZ();
}
int x = tx + ((r - 4) * 16) + 8;
int y = 51 + (l * 16);
int z = tz + ((c - 4) * 16) + 8;
loc = new Location(tpl.getLocation().getWorld(), x, y, z);
break;
}
}
c++;
}
c = 0;
r++;
}
r = 0;
l++;
}
}
} else {
loc = tpl.getLocation();
}
if (loc != null) {
// remove the entity
if (e != null) {
e.remove();
}
// if there are players in the TARDIS sound the cloister bell
HashMap<String, Object> where = new HashMap<String, Object>();
where.put("tardis_id", tpl.getTardisId());
ResultSetTravellers rs = new ResultSetTravellers(plugin, where, false);
if (rs.resultSet()) {
TARDISSounds.playTARDISSound(loc, "tardis_cloister_bell");
} else {
// else message the Time Lord
HashMap<String, Object> wheret = new HashMap<String, Object>();
wheret.put("tardis_id", tpl.getTardisId());
ResultSetTardis rst = new ResultSetTardis(plugin, wheret, "", false, 2);
if (rst.resultSet()) {
Player p = plugin.getServer().getPlayer(rst.getTardis().getUuid());
if (p != null) {
TARDISMessage.send(p, "MONSTER", m.getDisplayName());
}
}
HashMap<String, Object> wherer = new HashMap<String, Object>();
wherer.put("tardis_id", rst.getTardis().getTardis_id());
wherer.put("type", 5);
wherer.put("secondary", 0);
ResultSetControls rsc = new ResultSetControls(plugin, wherer, false);
if (rsc.resultSet()) {
// move the location to the y-repeater
loc = TARDISLocationGetters.getLocationFromDB(rsc.getLocation(), 0.0f, 0.0f);
loc.add(0.5d, 0.125d, 0.5d);
}
}
// load the chunk
while (!loc.getChunk().isLoaded()) {
loc.getChunk().load();
}
// spawn a monster in the TARDIS
plugin.setTardisSpawn(true);
Entity ent = loc.getWorld().spawnEntity(loc, m.getType());
switch (m.getType()) {
case CREEPER:
Creeper creeper = (Creeper) ent;
creeper.setPowered(m.isCharged());
break;
case ENDERMAN:
Enderman enderman = (Enderman) ent;
if (m.getCarried() != null) {
enderman.setCarriedMaterial(m.getCarried());
}
break;
case PIG_ZOMBIE:
PigZombie pigzombie = (PigZombie) ent;
pigzombie.setAngry(m.isAggressive());
pigzombie.setAnger(m.getAnger());
EntityEquipment ep = pigzombie.getEquipment();
if (m.getEquipment() != null) {
ep.setArmorContents(m.getEquipment().getArmorContents());
ep.setItemInMainHand(m.getEquipment().getItemInMainHand());
}
break;
case SKELETON:
Skeleton skeleton = (Skeleton) ent;
EntityEquipment es = skeleton.getEquipment();
if (m.getEquipment() != null) {
es.setArmorContents(m.getEquipment().getArmorContents());
es.setItemInMainHand(m.getEquipment().getItemInMainHand());
if (m.getEquipment().getHelmet().getType().equals(Material.VINE) && plugin.getPM().isPluginEnabled("LibsDisguises")) {
TARDISDalekDisguiser.dalekanium(skeleton);
}
}
skeleton.setSkeletonType(m.getSkeletonType());
break;
case SLIME:
Slime slime = (Slime) ent;
if (m.getSize() > 0) {
slime.setSize(m.getSize());
}
break;
case ZOMBIE:
Zombie zombie = (Zombie) ent;
if (m.getProfession() != null) {
zombie.setVillagerProfession(m.getProfession());
}
zombie.setBaby(m.isBaby());
EntityEquipment ez = zombie.getEquipment();
if (m.getEquipment() != null) {
ez.setArmorContents(m.getEquipment().getArmorContents());
ez.setItemInMainHand(m.getEquipment().getItemInMainHand());
}
break;
}
if (m.getAge() > 0) {
((LivingEntity) ent).setTicksLived(m.getAge());
}
if (m.getHealth() > 0 && m.getHealth() <= 20.0d) {
((LivingEntity) ent).setHealth(m.getHealth());
}
if (m.getName() != null && !m.getName().isEmpty()) {
((LivingEntity) ent).setCustomName(m.getName());
}
if (m.getPassenger() != null) {
if (plugin.getPM().isPluginEnabled("TARDISWeepingAngels") && m.getPassenger().equals(EntityType.GUARDIAN)) {
TARDISAngelsAPI.getAPI(plugin).setSilentEquipment((LivingEntity) ent);
} else {
Entity passenger = loc.getWorld().spawnEntity(loc, m.getPassenger());
ent.setPassenger(passenger);
}
}
}
}
private boolean isTimelord(TARDISTeleportLocation tpl, Entity e) {
ResultSetCompanions rsc = new ResultSetCompanions(plugin, tpl.getTardisId());
return (rsc.getCompanions().contains(((Player) e).getUniqueId()));
}
}