From 8e6232496b09b73b6e2f63aec7727f547bdd8eb9 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Sat, 13 Mar 2021 13:13:08 +0000 Subject: [PATCH] Added top damager tracking --- .../com/willfp/ecobosses/EcoBossesPlugin.java | 4 +- .../com/willfp/ecobosses/bosses/EcoBoss.java | 51 +++++++++- .../bosses/listeners/AttackListeners.java | 92 +++++++++++++++++-- .../bosses/listeners/DeathListeners.java | 78 +++++++++++++++- .../ecobosses/bosses/util/BossUtils.java | 32 +++++++ .../bosses/util/obj/DamagerProperty.java | 17 ++++ .../src/main/resources/bosses/illusioner.yml | 27 ++++++ .../core-plugin/src/main/resources/lang.yml | 4 +- 8 files changed, 290 insertions(+), 15 deletions(-) create mode 100644 eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/obj/DamagerProperty.java diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/EcoBossesPlugin.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/EcoBossesPlugin.java index 412d080..2b82a00 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/EcoBossesPlugin.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/EcoBossesPlugin.java @@ -119,8 +119,8 @@ public class EcoBossesPlugin extends AbstractEcoPlugin { @Override public List getListeners() { return Arrays.asList( - new AttackListeners(), - new DeathListeners(), + new AttackListeners(this), + new DeathListeners(this), new SpawnListeners(this) ); } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java index 09b99bf..9dda990 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java @@ -2,6 +2,7 @@ package com.willfp.ecobosses.bosses; import com.willfp.eco.internal.config.AbstractUndefinedConfig; import com.willfp.eco.util.NumberUtils; +import com.willfp.eco.util.StringUtils; import com.willfp.eco.util.internal.PluginDependent; import com.willfp.eco.util.plugin.AbstractEcoPlugin; import com.willfp.ecobosses.bosses.util.bosstype.BossEntityUtils; @@ -36,14 +37,17 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.StringUtil; import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.ArrayList; import java.util.Base64; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -117,7 +121,7 @@ public class EcoBoss extends PluginDependent { * The drops. */ @Getter - private final List drops; + private final Map drops; /** * The exp to drop. @@ -185,6 +189,18 @@ public class EcoBoss extends PluginDependent { @Getter private final TeleportOptions teleportOptions; + /** + * Spawn messages. + */ + @Getter + private final List spawnMessages; + + /** + * Death messages. + */ + @Getter + private final List deathMessages; + /** * Create a new Boss. * @@ -224,9 +240,15 @@ public class EcoBoss extends PluginDependent { ); // Rewards - this.drops = new ArrayList<>(); + this.drops = new HashMap<>(); for (String string : this.getConfig().getStrings("rewards.drops")) { YamlConfiguration tempConfig = new YamlConfiguration(); + double chance = 100; + if (string.contains("::")) { + String[] split = string.split("::"); + chance = Double.parseDouble(split[0]); + string = split[1]; + } String tempConfigString = new String(Base64.getDecoder().decode(string)); try { tempConfig.load(tempConfigString); @@ -234,7 +256,7 @@ public class EcoBoss extends PluginDependent { e.printStackTrace(); } ItemStack itemStack = tempConfig.getItemStack("drop-key"); - this.drops.add(itemStack); + this.drops.put(chance, itemStack); } this.experienceOptions = new ExperienceOptions( this.getConfig().getInt("rewards.xp.minimum"), @@ -339,6 +361,16 @@ public class EcoBoss extends PluginDependent { */ + // Messages + this.spawnMessages = new ArrayList<>(); + for (String string : this.getConfig().getStrings("broadcast.spawn")) { + this.spawnMessages.add(StringUtils.translate(string)); + } + this.deathMessages = new ArrayList<>(); + for (String string : this.getConfig().getStrings("broadcast.death")) { + this.deathMessages.add(StringUtils.translate(string)); + } + // Teleportation this.teleportationEnabled = this.getConfig().getBool("defence.teleport.enabled"); this.teleportOptions = new TeleportOptions( @@ -361,6 +393,9 @@ public class EcoBoss extends PluginDependent { entity.getPersistentDataContainer().set(this.getPlugin().getNamespacedKeyFactory().create("boss"), PersistentDataType.STRING, name); entity.setPersistent(true); + entity.setCustomName(this.getDisplayName()); + entity.setCustomNameVisible(true); + AttributeInstance maxHealth = entity.getAttribute(Attribute.GENERIC_MAX_HEALTH); assert maxHealth != null; maxHealth.setBaseValue(this.getMaxHealth()); @@ -375,6 +410,14 @@ public class EcoBoss extends PluginDependent { location.getWorld().playSound(location, sound.getSound(), sound.getVolume(), sound.getPitch()); } + for (String spawnMessage : this.getSpawnMessages()) { + Bukkit.broadcastMessage(spawnMessage + .replace("%x%", StringUtils.internalToString(location.getBlockX())) + .replace("%y%", StringUtils.internalToString(location.getBlockY())) + .replace("%z%", StringUtils.internalToString(location.getBlockZ())) + ); + } + if (this.isBossbarEnabled()) { createBossBar(entity); } @@ -382,7 +425,7 @@ public class EcoBoss extends PluginDependent { private void createBossBar(@NotNull final LivingEntity entity) { BossBar bossBar = Bukkit.getServer().createBossBar( - this.getDisplayName(), + entity.getCustomName(), this.getBossbarProperties().getColor(), this.getBossbarProperties().getStyle(), (BarFlag) null diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/AttackListeners.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/AttackListeners.java index dd69dee..2e1c36e 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/AttackListeners.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/AttackListeners.java @@ -1,8 +1,12 @@ package com.willfp.ecobosses.bosses.listeners; import com.willfp.eco.util.NumberUtils; +import com.willfp.eco.util.internal.PluginDependent; +import com.willfp.eco.util.plugin.AbstractEcoPlugin; +import com.willfp.ecobosses.EcoBossesPlugin; import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.util.BossUtils; +import com.willfp.ecobosses.bosses.util.obj.DamagerProperty; import com.willfp.ecobosses.bosses.util.obj.ImmunityOptions; import org.bukkit.Location; import org.bukkit.Material; @@ -10,17 +14,35 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.jetbrains.annotations.NotNull; +import javax.swing.tree.TreeNode; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.UUID; + +public class AttackListeners extends PluginDependent implements Listener { + /** + * Create new attack listeners. + * + * @param plugin Instance of EcoBosses. + */ + public AttackListeners(@NotNull final AbstractEcoPlugin plugin) { + super(plugin); + } -public class AttackListeners implements Listener { /** * Called when a player attacks a boss. * @@ -28,17 +50,25 @@ public class AttackListeners implements Listener { */ @EventHandler(ignoreCancelled = true) public void onAttackBoss(@NotNull final EntityDamageByEntityEvent event) { - if (!(event.getDamager() instanceof Player)) { - return; - } - if (!(event.getEntity() instanceof LivingEntity)) { return; } LivingEntity entity = (LivingEntity) event.getEntity(); - Player player = (Player) event.getDamager(); + Player player = null; + + if (event.getDamager() instanceof Player) { + player = (Player) event.getDamager(); + } else if (event.getDamager() instanceof Projectile) { + if (((Projectile) event.getDamager()).getShooter() instanceof Player) { + player = (Player) ((Projectile) event.getDamager()).getShooter(); + } + } + + if (player == null) { + return; + } EcoBoss boss = BossUtils.getBoss(entity); @@ -51,6 +81,56 @@ public class AttackListeners implements Listener { } } + /** + * Track top damage players. + * + * @param event The event to listen for. + */ + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void topDamageTracker(@NotNull final EntityDamageByEntityEvent event) { + if (!(event.getEntity() instanceof LivingEntity)) { + return; + } + + LivingEntity entity = (LivingEntity) event.getEntity(); + + Player temp = null; + + if (event.getDamager() instanceof Player) { + temp = (Player) event.getDamager(); + } else if (event.getDamager() instanceof Projectile) { + if (((Projectile) event.getDamager()).getShooter() instanceof Player) { + temp = (Player) ((Projectile) event.getDamager()).getShooter(); + } + } + + if (temp == null) { + return; + } + + Player player = temp; + + EcoBoss boss = BossUtils.getBoss(entity); + + if (boss == null) { + return; + } + + List topDamagers = BossUtils.getTopDamagers(entity); + + double playerDamage; + + Optional damager = topDamagers.stream().filter(damagerProperty -> damagerProperty.getPlayer().equals(player)).findFirst(); + playerDamage = damager.map(DamagerProperty::getDamage).orElse(0.0); + + playerDamage += event.getFinalDamage(); + topDamagers.removeIf(damagerProperty -> damagerProperty.getPlayer().equals(player)); + topDamagers.add(new DamagerProperty(player, playerDamage)); + + entity.removeMetadata("ecobosses-top-damagers", this.getPlugin()); + entity.setMetadata("ecobosses-top-damagers", this.getPlugin().getMetadataValueFactory().create(topDamagers)); + } + /** * Called when a boss attacks a player. * diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/DeathListeners.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/DeathListeners.java index 610f459..5819f2c 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/DeathListeners.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/DeathListeners.java @@ -1,18 +1,47 @@ package com.willfp.ecobosses.bosses.listeners; +import com.willfp.eco.util.NumberUtils; +import com.willfp.eco.util.StringUtils; import com.willfp.eco.util.events.entitydeathbyentity.EntityDeathByEntityEvent; +import com.willfp.eco.util.internal.PluginDependent; +import com.willfp.eco.util.plugin.AbstractEcoPlugin; import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.util.BossUtils; +import com.willfp.ecobosses.bosses.util.obj.DamagerProperty; import com.willfp.ecobosses.bosses.util.obj.OptionedSound; +import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import sun.reflect.generics.tree.Tree; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.UUID; +import java.util.stream.Collectors; + +public class DeathListeners extends PluginDependent implements Listener { + /** + * Create new death listeners. + * + * @param plugin Instance of EcoBosses. + */ + public DeathListeners(@NotNull final AbstractEcoPlugin plugin) { + super(plugin); + } -public class DeathListeners implements Listener { /** * Called when a boss dies. * @@ -48,7 +77,52 @@ public class DeathListeners implements Listener { return; } - event.getDrops().addAll(boss.getDrops()); + List topDamagers = BossUtils.getTopDamagers(entity); + + DamagerProperty top = null; + DamagerProperty second = null; + DamagerProperty third = null; + + if (topDamagers.size() >= 1) { + top = topDamagers.get(0); + } + if (topDamagers.size() >= 2) { + second = topDamagers.get(1); + } + if (topDamagers.size() >= 3) { + third = topDamagers.get(2); + } + + String na = this.getPlugin().getLangYml().getString("na"); + + String topDamager = top == null ? na : top.getPlayer().getDisplayName(); + String topDamage = top == null ? na : StringUtils.internalToString(top.getDamage()); + + String secondDamager = second == null ? na : second.getPlayer().getDisplayName(); + String secondDamage = second == null ? na : StringUtils.internalToString(second.getDamage()); + + String thirdDamager = third == null ? na : third.getPlayer().getDisplayName(); + String thirdDamage = third == null ? na : StringUtils.internalToString(third.getDamage()); + + for (String spawnMessage : boss.getDeathMessages()) { + Bukkit.broadcastMessage(spawnMessage + .replace("%top%", topDamager) + .replace("%top_damage%", topDamage) + .replace("%second%", secondDamager) + .replace("%second_damage%", secondDamage) + .replace("%third%", thirdDamager) + .replace("%third_damage%", thirdDamage) + ); + } + + List drops = new ArrayList<>(); + boss.getDrops().forEach((aDouble, itemStack) -> { + if (NumberUtils.randFloat(0, 100) < aDouble) { + drops.add(itemStack); + } + }); + + event.getDrops().addAll(drops); event.setDroppedExp(boss.getExperienceOptions().generateXp()); } } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/BossUtils.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/BossUtils.java index 92e45d7..729e840 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/BossUtils.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/BossUtils.java @@ -3,13 +3,20 @@ package com.willfp.ecobosses.bosses.util; import com.willfp.ecobosses.EcoBossesPlugin; import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.EcoBosses; +import com.willfp.ecobosses.bosses.util.obj.DamagerProperty; import lombok.experimental.UtilityClass; import org.bukkit.entity.LivingEntity; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + @UtilityClass +@SuppressWarnings("unchecked") public class BossUtils { /** * Instance of EcoBosses. @@ -36,4 +43,29 @@ public class BossUtils { return EcoBosses.getByName(bossName); } + + /** + * Get top damagers for a boss. + * + * @param entity The boss entity. + * @return A list of the top damagers, sorted. + */ + public List getTopDamagers(@NotNull final LivingEntity entity) { + if (getBoss(entity) == null) { + return new ArrayList<>(); + } + + List topDamagers; + if (entity.hasMetadata("ecobosses-top-damagers")) { + topDamagers = (List) entity.getMetadata("ecobosses-top-damagers").get(0).value(); + } else { + topDamagers = new ArrayList<>(); + } + assert topDamagers != null; + + topDamagers.sort(Comparator.comparingDouble(DamagerProperty::getDamage)); + Collections.reverse(topDamagers); + + return topDamagers; + } } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/obj/DamagerProperty.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/obj/DamagerProperty.java new file mode 100644 index 0000000..3b47070 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/obj/DamagerProperty.java @@ -0,0 +1,17 @@ +package com.willfp.ecobosses.bosses.util.obj; + +import lombok.Data; +import org.bukkit.entity.Player; + +@Data +public class DamagerProperty { + /** + * The player. + */ + private final Player player; + + /** + * The damage. + */ + private final double damage; +} diff --git a/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml b/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml index 53c026a..a9998e3 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml @@ -21,8 +21,35 @@ rewards: xp: minimum: 20000 maximum: 25000 + top-damager-commands: + 1: + - "40::give %player% diamond_block" + 2: + - "25::give %player% emerald_block" + 3: + - "10::give %player% iron_block" + nearby-player-commands: + radius: 10 + commands: [] drops: # Get items to add here by copying the console output for /ebdrop + # To set the chance for a drop, put :: + +broadcast: + spawn: + - "" + - "&9The &9&lIllusioner&r&9 has been spawned!" + - "&9Come fight it at &b%x%&9, &b%y%&9, &b%z%&9!" + - "" + death: + - "" + - "&9The &9&lIllusioner&r&9 has been killed!" + - "&9Most Damage:" + - "&9 - &b%top%&9: &b%top_damage% &9Damage" + - "&9 - &b%second%&9: &b%second_damage% &9Damage" + - "&9 - &b%third%&9: &b%third_damage% &9Damage" + - "" + defence: immunities: diff --git a/eco-core/core-plugin/src/main/resources/lang.yml b/eco-core/core-plugin/src/main/resources/lang.yml index 9efb0f9..b5e7269 100644 --- a/eco-core/core-plugin/src/main/resources/lang.yml +++ b/eco-core/core-plugin/src/main/resources/lang.yml @@ -6,4 +6,6 @@ messages: sent-drop: "Check console for the drop!" specify-boss: "&cYou must specify a valid boss!" invalid-location: "&cInvalid location!" - spawned: "Spawned a boss!" \ No newline at end of file + spawned: "Spawned a boss!" + +na: "N/A" \ No newline at end of file