From 58cd2bc535d87c1674d0eff860629e7a4a808d45 Mon Sep 17 00:00:00 2001 From: Kam Date: Thu, 27 Feb 2025 00:30:39 -0500 Subject: [PATCH] Tooltip Helper for RPG Items --- .../npcs/attribute/AttributeController.java | 4 +- .../npcs/attribute/AttributeDefinition.java | 8 +- .../npcs/attribute/ItemAttributeHelper.java | 220 ++++++++++++------ .../noppes/npcs/attribute/ModAttributes.java | 22 +- .../noppes/npcs/controllers/data/Magic.java | 12 + 5 files changed, 178 insertions(+), 88 deletions(-) diff --git a/src/main/java/noppes/npcs/attribute/AttributeController.java b/src/main/java/noppes/npcs/attribute/AttributeController.java index cdd00e1b4..70bd56ba1 100644 --- a/src/main/java/noppes/npcs/attribute/AttributeController.java +++ b/src/main/java/noppes/npcs/attribute/AttributeController.java @@ -29,11 +29,11 @@ public class AttributeController { } - public static AttributeDefinition registerAttribute(String key, String displayName, AttributeValueType valueType, AttributeDefinition.AttributeSection section) { + public static AttributeDefinition registerAttribute(String key, String displayName, char colorCode, AttributeValueType valueType, AttributeDefinition.AttributeSection section) { if (definitions.containsKey(key)) { throw new IllegalArgumentException("Attribute already registered with key: " + key); } - AttributeDefinition def = new AttributeDefinition(key, displayName, valueType, section); + AttributeDefinition def = new AttributeDefinition(key, displayName, colorCode, valueType, section); definitions.put(key, def); return def; } diff --git a/src/main/java/noppes/npcs/attribute/AttributeDefinition.java b/src/main/java/noppes/npcs/attribute/AttributeDefinition.java index 45a2a54c2..16875e489 100644 --- a/src/main/java/noppes/npcs/attribute/AttributeDefinition.java +++ b/src/main/java/noppes/npcs/attribute/AttributeDefinition.java @@ -3,14 +3,16 @@ package noppes.npcs.attribute; public class AttributeDefinition { private final String key; // e.g., "main_attack_flat" private final String displayName; // Human‑readable name + private final char colorCode; private final AttributeValueType attributeValueType; private final AttributeSection section; - public AttributeDefinition(String key, String displayName, AttributeValueType attributeValueType, AttributeSection section) { + public AttributeDefinition(String key, String displayName, char colorCode, AttributeValueType attributeValueType, AttributeSection section) { this.key = key; this.displayName = displayName; this.attributeValueType = attributeValueType; this.section = section; + this.colorCode = colorCode; } public String getKey() { @@ -29,6 +31,10 @@ public class AttributeDefinition { return section; } + public char getColorCode() { + return colorCode; + } + public enum AttributeSection { BASE, MODIFIER, diff --git a/src/main/java/noppes/npcs/attribute/ItemAttributeHelper.java b/src/main/java/noppes/npcs/attribute/ItemAttributeHelper.java index 8c9927bb8..c8f495b64 100644 --- a/src/main/java/noppes/npcs/attribute/ItemAttributeHelper.java +++ b/src/main/java/noppes/npcs/attribute/ItemAttributeHelper.java @@ -8,6 +8,8 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.StatCollector; import noppes.npcs.client.ClientProxy; +import noppes.npcs.controllers.MagicController; +import noppes.npcs.controllers.data.Magic; import org.lwjgl.input.Keyboard; import java.util.*; @@ -140,100 +142,62 @@ public class ItemAttributeHelper { @SideOnly(Side.CLIENT) public static List getToolTip(List original, NBTTagCompound compound) { - List tooltip = original; + List tooltip = new ArrayList<>(original); NBTTagCompound attrTag = compound.getCompoundTag(RPGItemAttributes); if (Keyboard.isKeyDown(ClientProxy.NPCButton.getKeyCode())) { List newTooltips = new ArrayList<>(); if (!tooltip.isEmpty()) { - newTooltips.add((String) tooltip.get(0)); + newTooltips.add(tooltip.get(0)); newTooltips.add(""); } - // Create lists for each section + // Lists for non–magic attributes List baseList = new ArrayList<>(); List modifierList = new ArrayList<>(); List infoList = new ArrayList<>(); List extraList = new ArrayList<>(); - Iterator iterator = attrTag.func_150296_c().iterator(); - while (iterator.hasNext()) { - String key = (String) iterator.next(); + // Process non–magic attributes (order maintained) + Iterator iter = attrTag.func_150296_c().iterator(); + while (iter.hasNext()) { + String key = iter.next(); + // Skip magic attribute keys; they are handled separately. + if(key.equals(ModAttributes.MAGIC_DAMAGE_KEY) || key.equals(ModAttributes.MAGIC_BOOST_KEY) + || key.equals(ModAttributes.MAGIC_DEFENSE_KEY) || key.equals(ModAttributes.MAGIC_RESISTANCE_KEY)) { + continue; + } double value = attrTag.getDouble(key); AttributeDefinition def = AttributeController.getAttribute(key); - // Default section is EXTRA if not defined AttributeDefinition.AttributeSection section = def != null ? def.getSection() : AttributeDefinition.AttributeSection.EXTRA; - String line; - String translation = null; - if (key.contains(":")) { - if (StatCollector.canTranslate(key)) { - translation = StatCollector.translateToLocal(key); - } - } else { - if (StatCollector.canTranslate("rpgcore:attribute." + key)) { - translation = StatCollector.translateToLocal("rpgcore:attribute." + key); - } - } - if (translation == null && def != null) { - translation = def.getDisplayName(); - } else if (translation == null) { - translation = key; - } - translation = EnumChatFormatting.AQUA + translation; - String formattedValue = formatDouble(value); - if (section == MODIFIER || section == INFO) { - String sign = (value >= 0) ? "+" : ""; - String valueColor = (value >= 0) ? EnumChatFormatting.GREEN + "" : EnumChatFormatting.RED + ""; - String valueString = valueColor + sign + formattedValue + EnumChatFormatting.GRAY; - switch (section) { - case MODIFIER: - line = valueString + " " + translation; - modifierList.add(line); - break; - case INFO: - line = valueString + " " + translation; - infoList.add(line); - break; - default: - line = translation + ": " + formattedValue; - break; - } - } else { - formattedValue = EnumChatFormatting.GRAY + formattedValue; - switch (section) { - case BASE: - line = translation + ": " + formattedValue; - baseList.add(line); - break; - case EXTRA: - line = translation + ": " + formattedValue; - extraList.add(line); - break; - default: - line = translation + ": " + formattedValue; - break; - } + String displayName = getTranslatedAttributeName(key, def); + String line = formatAttributeLine(def, section, value, displayName); + switch (section) { + case BASE: + baseList.add(line); + break; + case MODIFIER: + modifierList.add(line); + break; + case INFO: + infoList.add(line); + break; + default: + extraList.add(line); + break; } } - if (!baseList.isEmpty()) { - newTooltips.add(""); - newTooltips.addAll(baseList); - } - if (!modifierList.isEmpty()) { - newTooltips.add(""); - newTooltips.addAll(modifierList); - } - if (!infoList.isEmpty()) { - newTooltips.add(""); - newTooltips.addAll(infoList); - } - if (!extraList.isEmpty()) { - newTooltips.add(""); - newTooltips.addAll(extraList); - } + // Process magic attributes and merge them into the proper lists. + processMagicAttributes(compound, baseList, modifierList, infoList, extraList); + + // Append sections (adds an empty line before each if not empty) + newTooltips.addAll(buildSection(baseList)); + newTooltips.addAll(buildSection(modifierList)); + newTooltips.addAll(buildSection(infoList)); + newTooltips.addAll(buildSection(extraList)); + tooltip = newTooltips; } else { - // Inform the user to hold the NPCButton key for attribute details String keyName = Keyboard.getKeyName(ClientProxy.NPCButton.getKeyCode()); tooltip.add(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.ITALIC + StatCollector.translateToLocal("rpgcore:tooltip").replace("%key%", keyName)); @@ -241,6 +205,114 @@ public class ItemAttributeHelper { return tooltip; } + /** + * Processes magic attributes from the compound. + * For each magic key (from ModAttributes), it retrieves the stored magic attributes, + * formats each line (using the magic's display name) and adds it to the proper section list. + */ + private static void processMagicAttributes(NBTTagCompound compound, List baseList, List modifierList, + List infoList, List extraList) { + String[] magicKeys = { + ModAttributes.MAGIC_DAMAGE_KEY, + ModAttributes.MAGIC_BOOST_KEY, + ModAttributes.MAGIC_DEFENSE_KEY, + ModAttributes.MAGIC_RESISTANCE_KEY + }; + for (String magicKey : magicKeys) { + if (compound.hasKey(magicKey)) { + NBTTagCompound magicTag = compound.getCompoundTag(magicKey); + // Use the attribute definition for this magic key to determine its section. + AttributeDefinition def = AttributeController.getAttribute(magicKey); + AttributeDefinition.AttributeSection section = def != null ? def.getSection() : AttributeDefinition.AttributeSection.EXTRA; + Iterator magicIter = magicTag.func_150296_c().iterator(); + while (magicIter.hasNext()) { + String key = magicIter.next(); + try { + int magicId = Integer.parseInt(key); + double value = magicTag.getDouble(key); + Magic magic = MagicController.getInstance().getMagic(magicId); + if (magic != null) { + String magicDisplayName = magic.getDisplayName(); + // Format using the magic attribute's definition and the magic's display name. + String line = formatAttributeLine(def, section, value, magicDisplayName); + switch (section) { + case BASE: + baseList.add(line); + break; + case MODIFIER: + modifierList.add(line); + break; + case INFO: + infoList.add(line); + break; + default: + extraList.add(line); + break; + } + } + } catch (NumberFormatException e) { + // Skip invalid key. + } + } + } + } + } + + /** + * Returns a translated attribute name. + */ + private static String getTranslatedAttributeName(String key, AttributeDefinition def) { + String translation = null; + if (key.contains(":")) { + if (StatCollector.canTranslate(key)) + translation = StatCollector.translateToLocal(key); + } else { + if (StatCollector.canTranslate("rpgcore:attribute." + key)) + translation = StatCollector.translateToLocal("rpgcore:attribute." + key); + } + if (translation == null && def != null) + translation = def.getDisplayName(); + else if (translation == null) + translation = key; + return translation; + } + + /** + * Formats the attribute line based on its section and value type. + */ + private static String formatAttributeLine(AttributeDefinition def, AttributeDefinition.AttributeSection section, + double value, String displayName) { + String formattedValue = formatDouble(value); + if (section == AttributeDefinition.AttributeSection.MODIFIER || section == AttributeDefinition.AttributeSection.INFO) { + String sign = value >= 0 ? "+" : ""; + String color = value >= 0 ? EnumChatFormatting.GREEN.toString() : EnumChatFormatting.RED.toString(); + String valueString = color + sign + formattedValue + EnumChatFormatting.GRAY; + if (def != null && def.getValueType() == AttributeValueType.PERCENT) + valueString += "%"; + return valueString + " " + displayName; + } else { + if (def != null) + displayName = "\u00A7" + def.getColorCode() + displayName; + else + displayName = EnumChatFormatting.AQUA + displayName; + formattedValue = EnumChatFormatting.GRAY + formattedValue; + return displayName + "\u00A77: " + formattedValue; + } + } + + /** + * Builds a section from a list of tooltip lines. + * Adds an empty line before the section if it contains lines. + */ + private static List buildSection(List lines) { + List section = new ArrayList<>(); + if (!lines.isEmpty()) { + section.add(""); + section.addAll(lines); + } + return section; + } + /** * Helper to format a double by removing trailing zeros. */ diff --git a/src/main/java/noppes/npcs/attribute/ModAttributes.java b/src/main/java/noppes/npcs/attribute/ModAttributes.java index 9f62aec15..52fabffca 100644 --- a/src/main/java/noppes/npcs/attribute/ModAttributes.java +++ b/src/main/java/noppes/npcs/attribute/ModAttributes.java @@ -32,21 +32,21 @@ public class ModAttributes { public static AttributeDefinition MAGIC_RESISTANCE; public ModAttributes(){ - HEALTH = AttributeController.registerAttribute(HEALTH_KEY, "Health", AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); + HEALTH = AttributeController.registerAttribute(HEALTH_KEY, "Health", 'c', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); - MAIN_ATTACK = AttributeController.registerAttribute(MAIN_ATTACK_KEY, "Main Attack Damage", AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); - MAIN_BOOST = AttributeController.registerAttribute(MAIN_ATTACK_BOOST_KEY, "Main Attack Damage (%)", AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.MODIFIER); + MAIN_ATTACK = AttributeController.registerAttribute(MAIN_ATTACK_KEY, "Main Attack Damage", '4', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); + MAIN_BOOST = AttributeController.registerAttribute(MAIN_ATTACK_BOOST_KEY, "Main Attack Damage", '4', AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.MODIFIER); - NEUTRAL_ATTACK = AttributeController.registerAttribute(NEUTRAL_KEY, "Neutral Damage", AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); - NEUTRAL_BOOST = AttributeController.registerAttribute(NEUTRAL_BOOST_KEY, "Neutral Damage (%)", AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.MODIFIER); + NEUTRAL_ATTACK = AttributeController.registerAttribute(NEUTRAL_KEY, "Neutral Damage", '6', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.BASE); + NEUTRAL_BOOST = AttributeController.registerAttribute(NEUTRAL_BOOST_KEY, "Neutral Damage", '6', AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.MODIFIER); - CRITICAL_CHANCE = AttributeController.registerAttribute(CRITICAL_CHANCE_KEY, "Critical Chance (%)", AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.INFO); - CRITICAL_DAMAGE = AttributeController.registerAttribute(CRITICAL_DAMAGE_KEY, "Critical Damage Bonus", AttributeValueType.FLAT, AttributeDefinition.AttributeSection.INFO); + CRITICAL_CHANCE = AttributeController.registerAttribute(CRITICAL_CHANCE_KEY, "Critical Chance", '6', AttributeValueType.PERCENT, AttributeDefinition.AttributeSection.INFO); + CRITICAL_DAMAGE = AttributeController.registerAttribute(CRITICAL_DAMAGE_KEY, "Critical Damage", '6', AttributeValueType.FLAT, AttributeDefinition.AttributeSection.INFO); - MAGIC_DAMAGE = AttributeController.registerAttribute(MAGIC_DAMAGE_KEY, "Magic Damage", AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.BASE); - MAGIC_BOOST = AttributeController.registerAttribute(MAGIC_BOOST_KEY, "Magic Damage (%)", AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.MODIFIER); + MAGIC_DAMAGE = AttributeController.registerAttribute(MAGIC_DAMAGE_KEY, "Magic Damage", '3', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.BASE); + MAGIC_BOOST = AttributeController.registerAttribute(MAGIC_BOOST_KEY, "Magic Damage", '3', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.MODIFIER); - MAGIC_DEFENSE = AttributeController.registerAttribute(MAGIC_DEFENSE_KEY, "Magic Defense", AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.BASE); - MAGIC_RESISTANCE = AttributeController.registerAttribute(MAGIC_RESISTANCE_KEY, "Magic Resistance (%)", AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.MODIFIER); + MAGIC_DEFENSE = AttributeController.registerAttribute(MAGIC_DEFENSE_KEY, "Magic Defense", 'b', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.BASE); + MAGIC_RESISTANCE = AttributeController.registerAttribute(MAGIC_RESISTANCE_KEY, "Magic Resistance", 'b', AttributeValueType.MAGIC, AttributeDefinition.AttributeSection.MODIFIER); } } diff --git a/src/main/java/noppes/npcs/controllers/data/Magic.java b/src/main/java/noppes/npcs/controllers/data/Magic.java index 25b5b1474..ba6b608b2 100644 --- a/src/main/java/noppes/npcs/controllers/data/Magic.java +++ b/src/main/java/noppes/npcs/controllers/data/Magic.java @@ -10,6 +10,7 @@ import java.util.Map; public class Magic implements IMagic { public String name = ""; + public String displayName = ""; public int color = Integer.parseInt("FF00", 16); public int id = -1; @@ -21,6 +22,7 @@ public class Magic implements IMagic { public Magic(int id, String name, int color) { this.name = name; + this.displayName = name; this.color = color; this.id = id; } @@ -32,6 +34,7 @@ public class Magic implements IMagic { public void readNBT(NBTTagCompound compound) { name = compound.getString("Name"); + displayName = compound.getString("DisplayName"); color = compound.getInteger("Color"); id = compound.getInteger("Slot"); // No longer reading index/priority here. @@ -55,6 +58,7 @@ public class Magic implements IMagic { public void writeNBT(NBTTagCompound compound) { compound.setInteger("Slot", id); compound.setString("Name", name); + compound.setString("DisplayName", displayName); compound.setInteger("Color", color); // No longer writing index/priority here. if(iconItem != null) { @@ -96,6 +100,14 @@ public class Magic implements IMagic { return this.color; } + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + public void save() { MagicController.getInstance().saveMagic(this); }