177 lines
6.6 KiB
Java
177 lines
6.6 KiB
Java
package eu.m724.giants;
|
|
|
|
import org.bukkit.Location;
|
|
import org.bukkit.NamespacedKey;
|
|
import org.bukkit.entity.*;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.entity.EntityDeathEvent;
|
|
import org.bukkit.event.entity.EntitySpawnEvent;
|
|
import org.bukkit.event.world.ChunkLoadEvent;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.persistence.PersistentDataType;
|
|
import org.bukkit.plugin.java.JavaPlugin;
|
|
import org.bukkit.potion.PotionEffect;
|
|
import org.bukkit.potion.PotionEffectType;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
|
|
import java.util.*;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
import java.util.logging.Logger;
|
|
|
|
// TODO move ai stuff to another class
|
|
/**
|
|
* A processor class that processes giants
|
|
*/
|
|
public class GiantProcessor implements Listener {
|
|
private static final int VERSION = 1;
|
|
|
|
private final JavaPlugin plugin;
|
|
private final Configuration configuration;
|
|
private final Logger logger;
|
|
|
|
// private final Set<Giant> trackedGiants = new HashSet<>();
|
|
private final Set<Husk> trackedHusks = new HashSet<>();
|
|
|
|
private final ThreadLocalRandom random = ThreadLocalRandom.current();
|
|
private final NamespacedKey huskKey;
|
|
|
|
public GiantProcessor(JavaPlugin plugin, Configuration configuration) {
|
|
this.plugin = plugin;
|
|
this.configuration = configuration;
|
|
this.logger = Logger.getLogger(plugin.getLogger().getName() + ".GiantProcessor");
|
|
this.huskKey = new NamespacedKey(plugin, "husk");
|
|
}
|
|
|
|
void start() {
|
|
if (configuration.ai) {
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
for (Husk husk : Set.copyOf(trackedHusks)) {
|
|
if (husk.isValid()) {
|
|
Location location = husk.getLocation();
|
|
Entity giant = husk.getVehicle();
|
|
|
|
if (giant instanceof Giant) {
|
|
if (giant.isValid()) { // TODO reconsider
|
|
giant.getWorld().getNearbyEntities(
|
|
giant.getBoundingBox().expand(configuration.attackReach),
|
|
e -> (e instanceof Player && !e.isInvulnerable())
|
|
).forEach(p -> ((Player) p).damage(configuration.attackDamage, giant));
|
|
giant.setRotation(location.getYaw(), location.getPitch());
|
|
}
|
|
} else {
|
|
// no vehicle means the giant doesn't exist anymore and the husk should also not exist
|
|
husk.setHealth(0);
|
|
|
|
trackedHusks.remove(husk);
|
|
logger.fine("Husk killed because Giant died at " + husk.getLocation());
|
|
}
|
|
} else {
|
|
trackedHusks.remove(husk);
|
|
logger.fine("Husk unloaded at " + husk.getLocation());
|
|
}
|
|
}
|
|
}
|
|
}.runTaskTimer(plugin, configuration.attackDelay, 0L);
|
|
}
|
|
|
|
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
|
}
|
|
|
|
public LivingEntity spawnGiant(Location pos) {
|
|
LivingEntity entity = (LivingEntity) pos.getWorld().spawnEntity(pos, EntityType.GIANT);
|
|
|
|
if (configuration.ai) {
|
|
// the husk basically moves the giant
|
|
LivingEntity passenger = (LivingEntity) pos.getWorld().spawnEntity(pos, EntityType.HUSK);
|
|
new PotionEffect(PotionEffectType.INVISIBILITY, Integer.MAX_VALUE, 1).apply(passenger);
|
|
passenger.setInvulnerable(true);
|
|
passenger.setPersistent(true);
|
|
passenger.getPersistentDataContainer().set(huskKey, PersistentDataType.INTEGER, VERSION);
|
|
|
|
entity.addPassenger(passenger);
|
|
trackedHusks.add((Husk) passenger);
|
|
}
|
|
|
|
configuration.effects.forEach(entity::addPotionEffect);
|
|
//trackedGiants.add((Giant) entity);
|
|
|
|
logger.fine("Spawned a Giant at " + pos);
|
|
|
|
return entity;
|
|
}
|
|
|
|
@EventHandler
|
|
public void onChunkLoad(ChunkLoadEvent event) {
|
|
Entity[] entities = event.getChunk().getEntities();
|
|
logger.fine("Chunk loaded: " + event.getChunk().getX() + " " + event.getChunk().getZ());
|
|
|
|
Husk[] husks = Arrays.stream(entities)
|
|
.filter(entity -> entity instanceof Husk && entity.getPersistentDataContainer().has(huskKey))
|
|
.map(Husk.class::cast)
|
|
.toArray(Husk[]::new);
|
|
|
|
for (Husk husk : husks) {
|
|
logger.fine("Husk found at " + husk.getLocation());
|
|
|
|
Entity giant = husk.getVehicle();
|
|
|
|
if (giant instanceof Giant) {
|
|
trackedHusks.add(husk);
|
|
//trackedGiants.add((Giant) giant);
|
|
|
|
logger.fine("Tracking a loaded Giant at " + giant.getLocation());
|
|
} else {
|
|
// kill stray husks, that is those without a giant
|
|
husk.setHealth(0);
|
|
|
|
logger.fine("Stray Husk killed at " + husk.getLocation());
|
|
}
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void entitySpawn(EntitySpawnEvent e) {
|
|
if (configuration.worldBlacklist.contains(e.getLocation().getWorld().getName()))
|
|
return;
|
|
|
|
if (e.getEntityType() == EntityType.ZOMBIE) {
|
|
if (configuration.chance > random.nextDouble()) {
|
|
e.setCancelled(true);
|
|
spawnGiant(e.getLocation());
|
|
|
|
logger.fine("Spawned a Giant by chance at " + e.getLocation());
|
|
}
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void entityDeath(EntityDeathEvent e) {
|
|
LivingEntity entity = e.getEntity();
|
|
|
|
if (entity.getType() == EntityType.GIANT) {
|
|
Location location = entity.getLocation();
|
|
logger.fine("A Giant died at " + location);
|
|
|
|
for (Drop drop : configuration.drops) {
|
|
logger.fine("Rolling a drop");
|
|
|
|
if (drop.chance > random.nextDouble()) {
|
|
ItemStack is = drop.generateItemStack();
|
|
entity.getWorld().dropItemNaturally(location, is);
|
|
|
|
logger.fine("Dropped " + is);
|
|
}
|
|
}
|
|
|
|
for (Entity passenger : entity.getPassengers()) {
|
|
if (passenger.getPersistentDataContainer().has(huskKey)) {
|
|
((LivingEntity) passenger).setHealth(0);
|
|
logger.fine("Killed a Husk");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|