Giants/src/main/java/eu/m724/giants/GiantProcessor.java
2024-09-21 10:11:49 +02:00

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");
}
}
}
}
}