MobHealthbarUtils.java 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package com.gmail.nossr50.util;
  2. import com.gmail.nossr50.config.Config;
  3. import com.gmail.nossr50.datatypes.MobHealthbarType;
  4. import com.gmail.nossr50.datatypes.meta.OldName;
  5. import com.gmail.nossr50.mcMMO;
  6. import com.gmail.nossr50.runnables.MobHealthDisplayUpdaterTask;
  7. import com.gmail.nossr50.util.text.StringUtils;
  8. import org.bukkit.ChatColor;
  9. import org.bukkit.entity.LivingEntity;
  10. import org.bukkit.entity.Player;
  11. import org.bukkit.event.entity.EntityDamageByEntityEvent;
  12. import org.bukkit.event.entity.EntityDamageEvent;
  13. import org.bukkit.metadata.FixedMetadataValue;
  14. public final class MobHealthbarUtils {
  15. private MobHealthbarUtils() {}
  16. /**
  17. * Fix issues with death messages caused by the mob healthbars.
  18. *
  19. * @param deathMessage The original death message
  20. * @param player The player who died
  21. * @return the fixed death message
  22. */
  23. public static String fixDeathMessage(String deathMessage, Player player) {
  24. EntityDamageEvent lastDamageCause = player.getLastDamageCause();
  25. String replaceString = lastDamageCause instanceof EntityDamageByEntityEvent ? StringUtils.getPrettyEntityTypeString(((EntityDamageByEntityEvent) lastDamageCause).getDamager().getType()) : "a mob";
  26. return deathMessage.replaceAll("(?:(\u00A7(?:[0-9A-FK-ORa-fk-or]))*(?:[\u2764\u25A0]{1,10})){1,2}", replaceString);
  27. }
  28. /**
  29. * Handle the creation of mob healthbars.
  30. * @param target the targetted entity
  31. * @param damage damage done by the attack triggering this
  32. */
  33. public static void handleMobHealthbars(LivingEntity target, double damage, mcMMO plugin) {
  34. if (mcMMO.isHealthBarPluginEnabled() || !Config.getInstance().getMobHealthbarEnabled()) {
  35. return;
  36. }
  37. if (isBoss(target)) {
  38. return;
  39. }
  40. // Don't mangle invalid entities, they're not going to be rendered anyways
  41. if (!target.isValid()) {
  42. return;
  43. }
  44. String originalName = target.getName();
  45. String oldName = target.getCustomName();
  46. /*
  47. * Store the name in metadata
  48. */
  49. if(target.getMetadata(TransientMetadataTools.OLD_NAME_METAKEY).size() <= 0 && originalName != null)
  50. target.setMetadata(TransientMetadataTools.OLD_NAME_METAKEY, new OldName(originalName, plugin));
  51. if (oldName == null) {
  52. oldName = "";
  53. }
  54. boolean oldNameVisible = target.isCustomNameVisible();
  55. String newName = createHealthDisplay(Config.getInstance().getMobHealthbarDefault(), target, damage);
  56. target.setCustomName(newName);
  57. target.setCustomNameVisible(true);
  58. int displayTime = Config.getInstance().getMobHealthbarTime();
  59. if (displayTime != -1) {
  60. boolean updateName = !ChatColor.stripColor(oldName).equalsIgnoreCase(ChatColor.stripColor(newName));
  61. if (updateName) {
  62. target.setMetadata(mcMMO.customNameKey, new FixedMetadataValue(mcMMO.p, oldName));
  63. target.setMetadata(mcMMO.customVisibleKey, new FixedMetadataValue(mcMMO.p, oldNameVisible));
  64. }
  65. else if (!target.hasMetadata(mcMMO.customNameKey)) {
  66. target.setMetadata(mcMMO.customNameKey, new FixedMetadataValue(mcMMO.p, ""));
  67. target.setMetadata(mcMMO.customVisibleKey, new FixedMetadataValue(mcMMO.p, false));
  68. }
  69. new MobHealthDisplayUpdaterTask(target).runTaskLater(mcMMO.p, displayTime * Misc.TICK_CONVERSION_FACTOR); // Clear health display after 3 seconds
  70. }
  71. }
  72. private static String createHealthDisplay(MobHealthbarType mobHealthbarType, LivingEntity entity, double damage) {
  73. double maxHealth = entity.getMaxHealth();
  74. double currentHealth = Math.max(entity.getHealth() - damage, 0);
  75. double healthPercentage = (currentHealth / maxHealth) * 100.0D;
  76. int fullDisplay;
  77. ChatColor color = ChatColor.BLACK;
  78. String symbol;
  79. switch (mobHealthbarType) {
  80. case HEARTS:
  81. fullDisplay = Math.min((int) (maxHealth / 2), 10);
  82. color = ChatColor.DARK_RED;
  83. symbol = "❤";
  84. break;
  85. case BAR:
  86. fullDisplay = 10;
  87. if (healthPercentage >= 85) {
  88. color = ChatColor.DARK_GREEN;
  89. }
  90. else if (healthPercentage >= 70) {
  91. color = ChatColor.GREEN;
  92. }
  93. else if (healthPercentage >= 55) {
  94. color = ChatColor.GOLD;
  95. }
  96. else if (healthPercentage >= 40) {
  97. color = ChatColor.YELLOW;
  98. }
  99. else if (healthPercentage >= 25) {
  100. color = ChatColor.RED;
  101. }
  102. else if (healthPercentage >= 0) {
  103. color = ChatColor.DARK_RED;
  104. }
  105. symbol = "■";
  106. break;
  107. default:
  108. return null;
  109. }
  110. int coloredDisplay = (int) Math.ceil(fullDisplay * (healthPercentage / 100.0D));
  111. int grayDisplay = fullDisplay - coloredDisplay;
  112. StringBuilder healthbar = new StringBuilder(color + "");
  113. for (int i = 0; i < coloredDisplay; i++) {
  114. healthbar.append(symbol);
  115. }
  116. healthbar.append(ChatColor.GRAY);
  117. for (int i = 0; i < grayDisplay; i++) {
  118. healthbar.append(symbol);
  119. }
  120. return healthbar.toString();
  121. }
  122. /**
  123. * Check if a given LivingEntity is a boss.
  124. *
  125. * @param livingEntity The {@link LivingEntity} of the livingEntity to check
  126. * @return true if the livingEntity is a boss, false otherwise
  127. */
  128. private static boolean isBoss(LivingEntity livingEntity) {
  129. switch (livingEntity.getType()) {
  130. case ENDER_DRAGON:
  131. case WITHER:
  132. return true;
  133. default:
  134. return false;
  135. }
  136. }
  137. }