diff --git a/changelog.md b/changelog.md index dc2e6df..6821b98 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,7 @@ These changes will (most likely) be included in the next version. ## [Unreleased] - Extended and upgraded potions are now supported in the item syntax by prepending `long_` or `strong_` to the data portion of a potion item (e.g. `potion:strong_instant_heal:1` will yield a Potion of Healing II). Check the wiki for details. - MobArena now has basic tab completion support for most of the commands that take arguments. +- The `pet-items` node in `global-settings` now supports any living entity as a pet (but only tameable entities will _behave_ as pets). This should allow 1.14 servers to replace `ocelot` with `cat` in their `pet-items` node to get cat pets working again. - Tridents and crossbows are now considered weapons with regards to the `unbreakable-weapons` flag. All class items that have durability now have their unbreakable flag set to true unless the `unbreakable-weapons` and/or `unbreakable-armor` flags are set to `false`. - Leaderboards now work again on servers running Minecraft 1.14+. - Class chests (non-linked) now work again on servers running Minecraft 1.14+. diff --git a/src/main/java/com/garbagemule/MobArena/ArenaListener.java b/src/main/java/com/garbagemule/MobArena/ArenaListener.java index 59c3b49..24f1aff 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaListener.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaListener.java @@ -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) diff --git a/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java b/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java index 93e5600..e4dba2f 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java @@ -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); } /** diff --git a/src/main/java/com/garbagemule/MobArena/MonsterManager.java b/src/main/java/com/garbagemule/MobArena/MonsterManager.java index f9ab87e..98b2ac6 100644 --- a/src/main/java/com/garbagemule/MobArena/MonsterManager.java +++ b/src/main/java/com/garbagemule/MobArena/MonsterManager.java @@ -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 monsters, sheep, golems; - private Set petWolves; - private Set petOcelots; private Map bosses; private Map> suppliers; private Set mounts; + private Map petToPlayer; + private Map> 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 collection) { - for (LivingEntity e : collection) { + private void removeAll(Collection 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 getPets(Player owner) { + Set 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 pets = playerToPets.remove(p); + if (pets != null) { + pets.forEach(Entity::remove); + pets.clear(); } } diff --git a/src/main/java/com/garbagemule/MobArena/SpawnsPets.java b/src/main/java/com/garbagemule/MobArena/SpawnsPets.java index 720ca42..7e943a1 100644 --- a/src/main/java/com/garbagemule/MobArena/SpawnsPets.java +++ b/src/main/java/com/garbagemule/MobArena/SpawnsPets.java @@ -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 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 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); diff --git a/src/main/resources/res/global-settings.yml b/src/main/resources/res/global-settings.yml index eb382ca..b0c0fdf 100644 --- a/src/main/resources/res/global-settings.yml +++ b/src/main/resources/res/global-settings.yml @@ -4,4 +4,3 @@ update-notification: true prefix: '&a[MobArena] ' pet-items: wolf: bone - ocelot: salmon