Migrate portal, entity and worldpurger to new wm

This commit is contained in:
Ben Woo 2023-09-04 23:30:13 +08:00
parent 0a62081d03
commit 32fb25854f
No known key found for this signature in database
GPG Key ID: FB2A3645536E12C8
3 changed files with 218 additions and 70 deletions

View File

@ -7,21 +7,15 @@
package com.onarandombox.MultiverseCore.listeners;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
import com.onarandombox.MultiverseCore.worldnew.WorldPurger;
import jakarta.inject.Inject;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.entity.FoodLevelChangeEvent;
@ -33,17 +27,14 @@ import org.jvnet.hk2.annotations.Service;
*/
@Service
public class MVEntityListener implements InjectableListener {
private final MVCoreConfig config;
private final MVWorldManager worldManager;
private final WorldManager worldManager;
private final WorldPurger worldPurger;
@Inject
public MVEntityListener(
@NotNull MVCoreConfig config,
@NotNull MVWorldManager worldManager,
@NotNull WorldManager worldManager,
@NotNull WorldPurger worldPurger
) {
this.config = config;
this.worldManager = worldManager;
this.worldPurger = worldPurger;
}
@ -57,16 +48,15 @@ public class MVEntityListener implements InjectableListener {
if (event.isCancelled()) {
return;
}
if (event.getEntity() instanceof Player) {
Player p = (Player) event.getEntity();
MVWorld w = this.worldManager.getMVWorld(p.getWorld().getName());
if (w != null && !w.getHunger()) {
// If the world has hunger set to false, do not let the level go down
if (event.getFoodLevel() < ((Player) event.getEntity()).getFoodLevel()) {
event.setCancelled(true);
}
}
if (!(event.getEntity() instanceof Player player)) {
return;
}
worldManager.getMVWorld(player.getWorld())
.peek((world) -> {
if (!world.getHunger() && event.getFoodLevel() < player.getFoodLevel()) {
event.setCancelled(true);
}
});
}
/**
@ -75,14 +65,15 @@ public class MVEntityListener implements InjectableListener {
*/
@EventHandler
public void entityRegainHealth(EntityRegainHealthEvent event) {
if (event.isCancelled()) {
if (event.isCancelled() || event.getRegainReason() != RegainReason.REGEN) {
return;
}
RegainReason reason = event.getRegainReason();
MVWorld world = this.worldManager.getMVWorld(event.getEntity().getLocation().getWorld());
if (world != null && reason == RegainReason.REGEN && !world.getAutoHeal()) {
event.setCancelled(true);
}
worldManager.getMVWorld(event.getEntity().getWorld())
.peek((world) -> {
if (!world.getAutoHeal()) {
event.setCancelled(true);
}
});
}
/**
@ -91,45 +82,21 @@ public class MVEntityListener implements InjectableListener {
*/
@EventHandler
public void creatureSpawn(CreatureSpawnEvent event) {
if (event.isCancelled()) {
return;
}
// Check to see if the Creature is spawned by a plugin, we don't want to prevent this behaviour.
// TODO: Allow the egg thing to be a config param. Doubt this will be per world; seems silly.
if (event.getSpawnReason() == SpawnReason.CUSTOM || event.getSpawnReason() == SpawnReason.SPAWNER_EGG
if (event.getSpawnReason() == SpawnReason.CUSTOM
|| event.getSpawnReason() == SpawnReason.SPAWNER_EGG
|| event.getSpawnReason() == SpawnReason.BREEDING) {
return;
}
World world = event.getEntity().getWorld();
if (event.isCancelled())
return;
// Check if it's a world which we are meant to be managing.
if (!(this.worldManager.isMVWorld(world.getName())))
return;
EntityType type = event.getEntityType();
/**
* Handle people with non-standard animals: ie a patched craftbukkit.
*/
if (type == null || type.getName() == null) {
Logging.finer("Found a null typed creature.");
return;
}
MVWorld mvworld = this.worldManager.getMVWorld(world.getName());
event.setCancelled(this.worldPurger.shouldWeKillThisCreature(mvworld, event.getEntity()));
}
/**
* Handles portal search radius adjustment.
* @param event The Event that was fired.
*/
@EventHandler
public void entityPortal(EntityPortalEvent event) {
if (event.isCancelled() || event.getTo() == null) {
return;
}
if (!config.isUsingCustomPortalSearch()) {
event.setSearchRadius(config.getCustomPortalSearchRadius());
}
worldManager.getMVWorld(event.getEntity().getWorld())
.peek((world) -> {
event.setCancelled(this.worldPurger.shouldWeKillThisCreature(world, event.getEntity()));
});
}
}

View File

@ -8,17 +8,20 @@
package com.onarandombox.MultiverseCore.listeners;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import com.onarandombox.MultiverseCore.worldnew.MVWorld;
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
import jakarta.inject.Inject;
import org.bukkit.Material;
import org.bukkit.PortalType;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.PortalCreateEvent;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
/**
@ -27,10 +30,12 @@ import org.jvnet.hk2.annotations.Service;
@Service
public class MVPortalListener implements InjectableListener {
private MVWorldManager worldManager;
private final MVCoreConfig config;
private final WorldManager worldManager;
@Inject
public MVPortalListener(MVWorldManager worldManager) {
public MVPortalListener(@NotNull MVCoreConfig config, @NotNull WorldManager worldManager) {
this.config = config;
this.worldManager = worldManager;
}
@ -42,7 +47,7 @@ public class MVPortalListener implements InjectableListener {
public void portalForm(PortalCreateEvent event) {
Logging.fine("Attempting to create portal at '%s' with reason: %s", event.getWorld().getName(), event.getReason());
MVWorld world = this.worldManager.getMVWorld(event.getWorld());
MVWorld world = this.worldManager.getMVWorld(event.getWorld()).getOrNull();
if (world == null) {
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PortalCreateEvent.", event.getWorld().getName());
return;
@ -75,7 +80,7 @@ public class MVPortalListener implements InjectableListener {
return;
}
if (!world.getAllowedPortals().isPortalAllowed(targetType)) {
if (!world.getPortalForm().isPortalAllowed(targetType)) {
Logging.fine("Cancelling creation of %s portal because portalForm disallows.", targetType);
event.setCancelled(true);
}
@ -98,16 +103,30 @@ public class MVPortalListener implements InjectableListener {
return;
}
MVWorld world = this.worldManager.getMVWorld(event.getPlayer().getWorld());
MVWorld world = this.worldManager.getMVWorld(event.getPlayer().getWorld()).getOrNull();
if (world == null) {
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PlayerInteractEvent.",
event.getPlayer().getWorld().getName());
return;
}
if (!world.getAllowedPortals().isPortalAllowed(PortalType.ENDER)) {
if (!world.getPortalForm().isPortalAllowed(PortalType.ENDER)) {
Logging.fine("Cancelling creation of ENDER portal because portalForm disallows.");
event.setCancelled(true);
}
}
/**
* Handles portal search radius adjustment.
* @param event The Event that was fired.
*/
@EventHandler
public void entityPortal(EntityPortalEvent event) {
if (event.isCancelled() || event.getTo() == null) {
return;
}
if (!config.isUsingCustomPortalSearch()) {
event.setSearchRadius(config.getCustomPortalSearchRadius());
}
}
}

View File

@ -0,0 +1,162 @@
package com.onarandombox.MultiverseCore.worldnew;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Ghast;
import org.bukkit.entity.Golem;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Phantom;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Squid;
import org.jvnet.hk2.annotations.Service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// TODO: This entire class is a mess.
@Service
public class WorldPurger {
private Class<Entity> ambientClass = null;
public WorldPurger() {
try {
Class entityClass = Class.forName("org.bukkit.entity.Ambient");
if (Entity.class.isAssignableFrom(entityClass)) {
ambientClass = entityClass;
}
} catch (ClassNotFoundException ignore) { }
}
public void purgeWorlds(List<MVWorld> worlds) {
if (worlds == null || worlds.isEmpty()) {
return;
}
for (MVWorld world : worlds) {
this.purgeWorld(world);
}
}
public void purgeWorld(MVWorld world) {
if (world == null) {
return;
}
ArrayList<String> allMobs = new ArrayList<String>(world.getSpawningAnimalsExceptions());
allMobs.addAll(world.getSpawningMonstersExceptions());
purgeWorld(world, allMobs, !world.getSpawningAnimals(), !world.getSpawningMonsters());
}
public boolean shouldWeKillThisCreature(MVWorld world, Entity e) {
ArrayList<String> allMobs = new ArrayList<String>(world.getSpawningAnimalsExceptions());
allMobs.addAll(world.getSpawningMonstersExceptions());
return this.shouldWeKillThisCreature(e, allMobs, !world.getSpawningAnimals(), !world.getSpawningMonsters());
}
public void purgeWorld(MVWorld mvworld, List<String> thingsToKill,
boolean negateAnimals, boolean negateMonsters, CommandSender sender) {
if (mvworld == null) {
return;
}
World world = mvworld.getBukkitWorld().getOrNull();
if (world == null) {
return;
}
int projectilesKilled = 0;
int entitiesKilled = 0;
boolean specifiedAll = thingsToKill.contains("ALL");
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
List<Entity> worldEntities = world.getEntities();
List<LivingEntity> livingEntities = new ArrayList<LivingEntity>(worldEntities.size());
List<Projectile> projectiles = new ArrayList<Projectile>(worldEntities.size());
for (final Entity e : worldEntities) {
if (e instanceof Projectile) {
final Projectile p = (Projectile) e;
if (p.getShooter() != null) {
projectiles.add((Projectile) e);
}
} else if (e instanceof LivingEntity) {
livingEntities.add((LivingEntity) e);
}
}
for (final LivingEntity e : livingEntities) {
if (killDecision(e, thingsToKill, negateAnimals, negateMonsters, specifiedAnimals, specifiedMonsters)) {
final Iterator<Projectile> it = projectiles.iterator();
while (it.hasNext()) {
final Projectile p = it.next();
if (p.getShooter().equals(e)) {
p.remove();
it.remove();
projectilesKilled++;
}
}
e.remove();
entitiesKilled++;
}
}
if (sender != null) {
sender.sendMessage(entitiesKilled + " entities purged from the world '" + world.getName() + "' along with " + projectilesKilled + " projectiles that belonged to them.");
}
}
private boolean killDecision(Entity e, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters, boolean specifiedAnimals, boolean specifiedMonsters) {
boolean negate = false;
boolean specified = false;
if (e instanceof Golem || e instanceof Squid || e instanceof Animals
|| (ambientClass != null && ambientClass.isInstance(e))) {
// it's an animal
if (specifiedAnimals && !negateAnimals) {
Logging.finest("Removing an entity because I was told to remove all animals in world %s: %s", e.getWorld().getName(), e);
return true;
}
if (specifiedAnimals)
specified = true;
negate = negateAnimals;
} else if (e instanceof Monster || e instanceof Ghast || e instanceof Slime || e instanceof Phantom) {
// it's a monster
if (specifiedMonsters && !negateMonsters) {
Logging.finest("Removing an entity because I was told to remove all monsters in world %s: %s", e.getWorld().getName(), e);
return true;
}
if (specifiedMonsters)
specified = true;
negate = negateMonsters;
}
for (String s : thingsToKill) {
EntityType type = EntityType.fromName(s);
if (type != null && type.equals(e.getType())) {
specified = true;
if (!negate) {
Logging.finest("Removing an entity because it WAS specified and we are NOT negating in world %s: %s", e.getWorld().getName(), e);
return true;
}
break;
}
}
if (!specified && negate) {
Logging.finest("Removing an entity because it was NOT specified and we ARE negating in world %s: %s", e.getWorld().getName(), e);
return true;
}
return false;
}
public boolean shouldWeKillThisCreature(Entity e, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters) {
boolean specifiedAll = thingsToKill.contains("ALL");
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
return this.killDecision(e, thingsToKill, negateAnimals, negateMonsters, specifiedAnimals, specifiedMonsters);
}
public void purgeWorld(MVWorld mvworld, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters) {
purgeWorld(mvworld, thingsToKill, negateAnimals, negateMonsters, null);
}
}