Rework class pet parsing and handling.

This commit changes the pet parsing and handling such that it is a lot more dynamic. Rather than limiting pets to wolves and ocelots, any living entity is now a potential pet. This means that we can do away with the logic that specifically targets the Wolf and Ocelot interfaces and instead work with the more general Tameable interface. As a result, the discrepancies between Minecraft 1.13 and 1.14 in this regard are largely irrelevant, because server owners can just specify which entity they want to spawn given which item in their config-files.

MonsterManager's two Wolf- and Ocelot-specific addPet() methods are replaced with a generic addPet() method that takes an owner (Player) and a pet (Entity). This is technically a breaking API change, but MonsterManager is an internal component that is very unlikely to be used outside of MobArena.

The `global-settings` node in the config-file can no longer be forced into strict compliance via ConfigUtils, because the `pet-items` node is now dynamic rather than static.

The default `pet-items` node in the config-file no longer has `ocelot` in there to avoid confusion on 1.14. It now only contains `wolf` and people will have to add their own ocelot/cat in if they haven't added it already.

Fixes #563
This commit is contained in:
Andreas Troelsen
2019-08-05 14:32:23 +02:00
parent 9129a1d360
commit c6a695e2c3
6 changed files with 108 additions and 117 deletions
@@ -32,7 +32,6 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Horse;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Slime;
@@ -40,7 +39,6 @@ import org.bukkit.entity.Snowman;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.Wolf;
import org.bukkit.event.Event.Result;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
@@ -561,12 +559,11 @@ public class ArenaListener
if (shooter instanceof Entity) {
damager = (Entity) shooter;
}
}
else if (damager instanceof Wolf && arena.hasPet(damager)) {
damager = (Player) ((Wolf) damager).getOwner();
}
else if (damager instanceof Ocelot && arena.hasPet(damager)) {
damager = (Player) ((Ocelot) damager).getOwner();
} else {
Player owner = arena.getMonsterManager().getOwner(damager);
if (owner != null) {
damager = owner;
}
}
// If the damager was a player, add to kills.
@@ -656,12 +653,9 @@ public class ArenaListener
? monsters.getBoss((LivingEntity) damagee)
: null;
// Pet wolf
if (damagee instanceof Wolf && arena.hasPet(damagee)) {
onPetDamage(event, (Wolf) damagee, damager);
}
else if (damagee instanceof Ocelot && arena.hasPet(damagee)) {
onPetDamage(event, (Ocelot) damagee, damager);
// Pets
if (arena.hasPet(damagee)) {
onPetDamage(event, damagee, damager);
}
else if (damagee instanceof ArmorStand) {
onArmorStandDamage(event);
@@ -712,11 +706,7 @@ public class ArenaListener
}
}
private void onPetDamage(EntityDamageEvent event, Wolf pet, Entity damager) {
event.setCancelled(true);
}
private void onPetDamage(EntityDamageEvent event, Ocelot pet, Entity damager) {
private void onPetDamage(EntityDamageEvent event, Entity pet, Entity damager) {
event.setCancelled(true);
}
@@ -752,16 +742,12 @@ public class ArenaListener
aps.add("dmgDone", event.getDamage());
aps.inc("hits");
}
else if (damager instanceof Wolf && arena.hasPet(damager)) {
//event.setDamage(1);
Player p = (Player) ((Wolf) damager).getOwner();
ArenaPlayerStatistics aps = arena.getArenaPlayer(p).getStats();
aps.add("dmgDone", event.getDamage());
}
else if (damager instanceof Ocelot && arena.hasPet(damager)) {
Player p = (Player) ((Ocelot) damager).getOwner();
ArenaPlayerStatistics aps = arena.getArenaPlayer(p).getStats();
aps.add("dmgDone", event.getDamage());
else if (arena.hasPet(damager)) {
Player owner = arena.getMonsterManager().getOwner(damager);
if (owner != null) {
ArenaPlayerStatistics aps = arena.getArenaPlayer(owner).getStats();
aps.add("dmgDone", event.getDamage());
}
}
else if (monsters.getMonsters().contains(damager)) {
if (!monsterInfight)
@@ -16,6 +16,7 @@ import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import java.util.ArrayList;
@@ -57,7 +58,7 @@ public class ArenaMasterImpl implements ArenaMaster
this.classes = new HashMap<>();
this.allowedCommands = new HashSet<>();
this.spawnsPets = new SpawnsPets(Material.BONE, Material.SALMON);
this.spawnsPets = new SpawnsPets();
this.joinInterruptTimer = new JoinInterruptTimer();
}
@@ -254,7 +255,7 @@ public class ArenaMasterImpl implements ArenaMaster
*/
public void loadSettings() {
ConfigurationSection section = plugin.getConfig().getConfigurationSection("global-settings");
ConfigUtils.addMissingRemoveObsolete(plugin, "global-settings.yml", section);
ConfigUtils.addIfEmpty(plugin, "global-settings.yml", section);
enabled = section.getBoolean("enabled", true);
@@ -276,20 +277,35 @@ public class ArenaMasterImpl implements ArenaMaster
}
private void loadPetItems(ConfigurationSection settings) {
String wolf = settings.getString("pet-items.wolf", "");
String ocelot = settings.getString("pet-items.ocelot", "");
spawnsPets.clear();
Material wolfMaterial = Material.getMaterial(wolf.toUpperCase());
Material ocelotMaterial = Material.getMaterial(ocelot.toUpperCase());
ConfigurationSection items = settings.getConfigurationSection("pet-items");
if (wolfMaterial == null && !wolf.isEmpty()) {
throw new ConfigError("Failed to parse item type for wolf pet item: " + wolf);
for (String key : items.getKeys(false)) {
EntityType entity;
try {
entity = EntityType.valueOf(key.toUpperCase());
} catch (IllegalArgumentException e) {
throw new ConfigError("Failed to parse entity type for pet item: " + key);
}
if (!entity.isAlive()) {
throw new ConfigError("Invalid entity type for pet item: " + key);
}
Material material;
try {
material = Material.getMaterial(items.getString(key, "").toUpperCase());
} catch (Exception e) {
throw new ConfigError("Failed to parse material type for pet item: " + key);
}
if (material == null) {
throw new ConfigError("Failed to parse material type for pet item: " + key);
}
spawnsPets.register(material, entity);
}
if (ocelotMaterial == null && !ocelot.isEmpty()) {
throw new ConfigError("Failed to parse item type for ocelot pet item: " + ocelot);
}
spawnsPets = new SpawnsPets(wolfMaterial, ocelotMaterial);
}
/**
@@ -4,12 +4,11 @@ import com.garbagemule.MobArena.healthbar.HealthBar;
import com.garbagemule.MobArena.waves.MABoss;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Player;
import org.bukkit.entity.Wolf;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -20,32 +19,32 @@ import java.util.Set;
public class MonsterManager
{
private Set<LivingEntity> monsters, sheep, golems;
private Set<Wolf> petWolves;
private Set<Ocelot> petOcelots;
private Map<LivingEntity,MABoss> bosses;
private Map<LivingEntity,List<ItemStack>> suppliers;
private Set<LivingEntity> mounts;
private Map<Entity, Player> petToPlayer;
private Map<Player, Set<Entity>> playerToPets;
public MonsterManager() {
this.monsters = new HashSet<>();
this.sheep = new HashSet<>();
this.golems = new HashSet<>();
this.petWolves = new HashSet<>();
this.petOcelots = new HashSet<>();
this.bosses = new HashMap<>();
this.suppliers = new HashMap<>();
this.mounts = new HashSet<>();
this.petToPlayer = new HashMap<>();
this.playerToPets = new HashMap<>();
}
public void reset() {
monsters.clear();
sheep.clear();
golems.clear();
petWolves.clear();
petOcelots.clear();
bosses.clear();
suppliers.clear();
mounts.clear();
petToPlayer.clear();
playerToPets.clear();
}
public void clear() {
@@ -57,17 +56,16 @@ public class MonsterManager
removeAll(monsters);
removeAll(sheep);
removeAll(golems);
removeAll(petWolves);
removeAll(petOcelots);
removeAll(bosses.keySet());
removeAll(suppliers.keySet());
removeAll(mounts);
removeAll(petToPlayer.keySet());
reset();
}
private void removeAll(Collection<? extends LivingEntity> collection) {
for (LivingEntity e : collection) {
private void removeAll(Collection<? extends Entity> collection) {
for (Entity e : collection) {
if (e != null) {
e.remove();
}
@@ -78,8 +76,6 @@ public class MonsterManager
if (monsters.remove(e)) {
sheep.remove(e);
golems.remove(e);
petWolves.remove(e);
petOcelots.remove(e);
suppliers.remove(e);
MABoss boss = bosses.remove(e);
if (boss != null) {
@@ -124,32 +120,34 @@ public class MonsterManager
return golems.remove(e);
}
public void addPet(Wolf w) {
petWolves.add(w);
}
public void addPet(Ocelot o) {
petOcelots.add(o);
public void addPet(Player player, Entity pet) {
petToPlayer.put(pet, player);
playerToPets
.computeIfAbsent(player, (key) -> new HashSet<>())
.add(pet);
}
public boolean hasPet(Entity e) {
return petWolves.contains(e) || petOcelots.contains(e);
return petToPlayer.containsKey(e);
}
public Player getOwner(Entity pet) {
return petToPlayer.get(pet);
}
public Collection<Entity> getPets(Player owner) {
Set<Entity> pets = playerToPets.get(owner);
if (pets != null) {
return pets;
}
return Collections.emptySet();
}
public void removePets(Player p) {
for (Wolf w : petWolves) {
if (w == null || !(w.getOwner() instanceof Player) || !w.getOwner().getName().equals(p.getName()))
continue;
w.setOwner(null);
w.remove();
}
for (Ocelot o : petOcelots) {
if (o == null || !(o.getOwner() instanceof Player) || !o.getOwner().getName().equals(p.getName()))
continue;
o.setOwner(null);
o.remove();
Set<Entity> pets = playerToPets.remove(p);
if (pets != null) {
pets.forEach(Entity::remove);
pets.clear();
}
}
@@ -2,20 +2,29 @@ package com.garbagemule.MobArena;
import com.garbagemule.MobArena.framework.Arena;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Player;
import org.bukkit.entity.Wolf;
import org.bukkit.entity.Tameable;
import org.bukkit.inventory.PlayerInventory;
import java.util.HashMap;
import java.util.Map;
public class SpawnsPets {
private final Material wolfMaterial;
private final Material ocelotMaterial;
private final Map<Material, EntityType> materialToEntity;
SpawnsPets(Material wolfMaterial, Material ocelotMaterial) {
this.wolfMaterial = wolfMaterial;
this.ocelotMaterial = ocelotMaterial;
SpawnsPets() {
this.materialToEntity = new HashMap<>();
}
void register(Material material, EntityType entity) {
materialToEntity.put(material, entity);
}
void clear() {
materialToEntity.clear();
}
void spawn(Arena arena) {
@@ -31,47 +40,29 @@ public class SpawnsPets {
if (ac == null || ac.getConfigName().equals("My Items")) {
return;
}
spawnWolfPets(player, arena);
spawnOcelotPets(player, arena);
for (Map.Entry<Material, EntityType> entry : materialToEntity.entrySet()) {
spawnPetsFor(player, arena, entry.getKey(), entry.getValue());
}
}
private void spawnWolfPets(Player player, Arena arena) {
if (wolfMaterial == null) {
return;
}
private void spawnPetsFor(Player player, Arena arena, Material material, EntityType entity) {
PlayerInventory inv = player.getInventory();
int index = inv.first(wolfMaterial);
if (index == -1) {
int index = inv.first(material);
if (index < 0) {
return;
}
int amount = inv.getItem(index).getAmount();
for (int i = 0; i < amount; i++) {
Wolf wolf = (Wolf) arena.getWorld().spawnEntity(player.getLocation(), EntityType.WOLF);
wolf.setTamed(true);
wolf.setOwner(player);
arena.getMonsterManager().addPet(wolf);
}
inv.setItem(index, null);
}
private void spawnOcelotPets(Player player, Arena arena) {
if (ocelotMaterial == null) {
return;
}
PlayerInventory inv = player.getInventory();
int index = inv.first(ocelotMaterial);
if (index == -1) {
return;
}
int amount = inv.getItem(index).getAmount();
for (int i = 0; i < amount; i++) {
Ocelot ocelot = (Ocelot) arena.getWorld().spawnEntity(player.getLocation(), EntityType.OCELOT);
ocelot.setTamed(true);
ocelot.setOwner(player);
arena.getMonsterManager().addPet(ocelot);
Entity pet = arena.getWorld().spawn(player.getLocation(), entity.getEntityClass());
if (pet instanceof Tameable) {
Tameable tameable = (Tameable) pet;
tameable.setTamed(true);
tameable.setOwner(player);
}
arena.getMonsterManager().addPet(player, pet);
}
inv.setItem(index, null);
@@ -4,4 +4,3 @@ update-notification: true
prefix: '&a[MobArena] '
pet-items:
wolf: bone
ocelot: salmon