diff --git a/src/main/java/net/kalbskinder/mobHealth/MobHealth.java b/src/main/java/net/kalbskinder/mobHealth/MobHealth.java index da0a57e..2c14293 100644 --- a/src/main/java/net/kalbskinder/mobHealth/MobHealth.java +++ b/src/main/java/net/kalbskinder/mobHealth/MobHealth.java @@ -20,7 +20,7 @@ public final class MobHealth extends JavaPlugin { private final HealthColorUtil healthColorUtil = new HealthColorUtil(); private final TextUtil textUtil = new TextUtil(); - private final RenameMobService renameMobService = new RenameMobService(healthColorUtil, textUtil); + private final RenameMobService renameMobService = new RenameMobService(healthColorUtil, textUtil, this); @Getter private static MobHealth instance; diff --git a/src/main/java/net/kalbskinder/mobHealth/service/RenameMobService.java b/src/main/java/net/kalbskinder/mobHealth/service/RenameMobService.java index 69c228a..84b3667 100644 --- a/src/main/java/net/kalbskinder/mobHealth/service/RenameMobService.java +++ b/src/main/java/net/kalbskinder/mobHealth/service/RenameMobService.java @@ -1,6 +1,5 @@ package net.kalbskinder.mobHealth.service; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.kalbskinder.mobHealth.MobHealth; import net.kalbskinder.mobHealth.configuration.Config; @@ -15,11 +14,17 @@ import org.bukkit.persistence.PersistentDataType; @Slf4j -@RequiredArgsConstructor public class RenameMobService { private final HealthColorUtil healthColorUtil; private final TextUtil textUtil; + private final NamespacedKey healthDisplayKey; + + public RenameMobService(HealthColorUtil healthColorUtil, TextUtil textUtil, MobHealth instance) { + this.healthColorUtil = healthColorUtil; + this.textUtil = textUtil; + this.healthDisplayKey = new NamespacedKey(instance, "mob_health_display"); + } public double getDefaultMaxHealth(LivingEntity entity) { return entity.getAttribute(Attribute.MAX_HEALTH).getValue(); @@ -77,6 +82,8 @@ public void renameMob(Entity anyEntity, DisplaySetting activeDisplaySetting) { } private void renameMobSkyblock(LivingEntity entity, EntityProperties props) { + resetMobName(entity); + entity.setCustomNameVisible(false); String healthColor = healthColorUtil.getSkyblockHealthColor(props.health(), props.maxHealth()); String prefix = Config.HealthBars.Skyblock.PREFIX(); @@ -101,18 +108,12 @@ private void renameMobSkyblock(LivingEntity entity, EntityProperties props) { healthBarDisplay = String.format("%s%s&7/&a%s", healthColor, formatHalf(roundedHealth), formatHalf(roundedMaxHealth)); } - if (props.disableMobName()) { - String mobDisplayName = String.format("%s%s%s", prefix, healthBarDisplay, suffix); - entity.setCustomName(textUtil.parseLegacy(mobDisplayName)); - } else { - String newMobName = props.nameColor() + props.mobName(); - - String mobDisplayName = String.format("%s%s %s%s", prefix, newMobName, healthBarDisplay, suffix); - entity.setCustomName(textUtil.parseLegacy(mobDisplayName)); - } + formatMobDisplayName(entity, props, healthBarDisplay, prefix, suffix); } private void renameMobSprite(Entity entity, EntityProperties props) { + resetMobName(entity); + int totalHalfHeartsHealth = (int) Math.round(props.health()); int fullSprites = totalHalfHeartsHealth / 2; boolean isHalfHealth = totalHalfHeartsHealth % 2 != 0; @@ -154,18 +155,9 @@ private void renameMobSprite(Entity entity, EntityProperties props) { String displayName = "%s\n%s%s".formatted(convertedPrefix, heartsDisplay, convertedSuffix); World world = entity.getWorld(); - NamespacedKey healthDisplayKey = new NamespacedKey(MobHealth.getInstance(), "mob_health_display"); - NamespacedKey healthDisplayBgKey = new NamespacedKey(MobHealth.getInstance(), "mob_health_display_bg"); String entityId = entity.getUniqueId().toString(); // Remove any lingering background display from previous implementation - world.getEntities().stream() - .filter(e -> e instanceof TextDisplay) - .map(e -> (TextDisplay) e) - .filter(e -> e.getPersistentDataContainer().has(healthDisplayBgKey, PersistentDataType.STRING) - && entityId.equals(e.getPersistentDataContainer().get(healthDisplayBgKey, PersistentDataType.STRING))) - .forEach(Entity::remove); - TextDisplay textDisplay = world.getEntities().stream() .filter(e -> e instanceof TextDisplay) .map(e -> (TextDisplay) e) @@ -189,10 +181,51 @@ private void renameMobSprite(Entity entity, EntityProperties props) { } public void renameMobSymbol(Entity entity, EntityProperties props) { - // Implement the logic to rename the mob according to the Hearts Symbol display setting + resetMobName(entity); + String symbol = Config.HealthBars.Symbols.SYMBOL(); + String healthColor = healthColorUtil.getSymbolHealthColor(props.health(), props.maxHealth()); + String prefix = Config.HealthBars.Symbols.PREFIX(); + String suffix = Config.HealthBars.Symbols.SUFFIX(); + + if (props.levelPrefixEnabled()) { + prefix = "%s %s".formatted(props.levelPrefix(), prefix); + } + + // 1 symbol per 2 HP, max 20, minimum 1 + int symbolsToShow = (int) Math.ceil(props.health() / 2.0); + symbolsToShow = Math.max(1, Math.min(symbolsToShow, 20)); + String symbols = symbol.repeat(symbolsToShow); + + String healthBarDisplay = String.format("%s%s", healthColor, symbols); + + formatMobDisplayName(entity, props, healthBarDisplay, prefix, suffix); } private void renameMobHealthBar(Entity entity, EntityProperties props) { // Implement the logic to rename the mob according to the Health Bar display setting } + + private void formatMobDisplayName(Entity entity, EntityProperties props, String healthBarDisplay, String prefix, String suffix) { + if (props.disableMobName()) { + String mobDisplayName = String.format("%s%s%s", prefix, healthBarDisplay, suffix); + entity.setCustomName(textUtil.parseLegacy(mobDisplayName)); + } else { + String newMobName = props.nameColor() + props.mobName(); + + String mobDisplayName = String.format("%s%s %s%s", prefix, newMobName, healthBarDisplay, suffix); + entity.setCustomName(textUtil.parseLegacy(mobDisplayName)); + } + } + + private void resetMobName(Entity entity) { + String entityId = entity.getUniqueId().toString(); + entity.getPassengers().stream() + .filter(e -> e instanceof TextDisplay) + .map(e -> (TextDisplay) e) + .filter(e -> e.getPersistentDataContainer().has(healthDisplayKey, PersistentDataType.STRING) + && entityId.equals(e.getPersistentDataContainer().get(healthDisplayKey, PersistentDataType.STRING))) + .forEach(Entity::remove); + + entity.setCustomName(null); + } } diff --git a/src/main/java/net/kalbskinder/mobHealth/util/HealthColorUtil.java b/src/main/java/net/kalbskinder/mobHealth/util/HealthColorUtil.java index 24b52ff..7a70173 100644 --- a/src/main/java/net/kalbskinder/mobHealth/util/HealthColorUtil.java +++ b/src/main/java/net/kalbskinder/mobHealth/util/HealthColorUtil.java @@ -13,4 +13,15 @@ public String getSkyblockHealthColor(double health, double maxHealth) { return Config.HealthBars.Skyblock.COLOR_LOW(); } } + + public String getSymbolHealthColor(double health, double maxHealth) { + double percentage = (health / maxHealth) * 100.0; + if (percentage > 75.0) { + return Config.HealthBars.Symbols.COLOR_HIGH(); + } else if (percentage >= 25.0) { + return Config.HealthBars.Symbols.COLOR_MID(); + } else { + return Config.HealthBars.Symbols.COLOR_LOW(); + } + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 53ded6c..66f7967 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -4,7 +4,7 @@ # disable-mob-name: # If true, the mob will not display its name, only the health. general: - name-always-shown: true # If true, the name of the mob will always be shown, even if the player is not looking at the entity. + name-always-shown: true # If true, the name of the mob will always be shown, even if the player is not looking at the entity. Will not work with SPRITES and BARS display-skyblock-level: false # Display a prefix of a mob's level. [Lv5] Zombie disable-mob-name: false # If true, the mob will not display its name, only the health. name-color: "&c" # The color of the mob's name. Must be a valid Minecraft color code. @@ -24,7 +24,7 @@ bars: symbols: prefix: "" suffix: "" - symbol: "❤" + symbol: "■" color: high: "&a" mid: "&e"