Files
CustomNPC-Plus/src/main/java/noppes/npcs/attribute/ItemAttributeHelper.java
T

335 lines
14 KiB
Java
Raw Normal View History

2025-02-24 16:08:22 -05:00
package noppes.npcs.attribute;
2025-02-26 22:49:26 -05:00
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
2025-02-24 16:08:22 -05:00
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
2025-02-26 22:49:26 -05:00
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import noppes.npcs.client.ClientProxy;
2025-02-27 00:30:39 -05:00
import noppes.npcs.controllers.MagicController;
import noppes.npcs.controllers.data.Magic;
2025-02-26 22:49:26 -05:00
import org.lwjgl.input.Keyboard;
import java.util.*;
import static noppes.npcs.attribute.AttributeDefinition.AttributeSection.INFO;
import static noppes.npcs.attribute.AttributeDefinition.AttributeSection.MODIFIER;
2025-02-24 16:08:22 -05:00
/**
2025-02-24 20:07:32 -05:00
* Provides helper functions to write/read item attributes to/from NBT.
* Non–magic attributes are stored under a compound tag (TAG_ROOT),
* and magic attributes are stored as a compound mapping (by magic ID) under specific keys.
2025-02-24 16:08:22 -05:00
*/
public class ItemAttributeHelper {
2025-02-26 22:49:26 -05:00
public static final String RPGItemAttributes = "RPGCoreAttributes";
2025-02-24 16:08:22 -05:00
/**
* Applies a non–magic attribute to an item.
*/
2025-02-24 16:08:22 -05:00
public static void applyAttribute(ItemStack item, String attributeKey, double value) {
2025-02-24 20:07:32 -05:00
if (item == null) return;
if (item.stackTagCompound == null) {
2025-02-24 16:08:22 -05:00
item.stackTagCompound = new NBTTagCompound();
}
NBTTagCompound root = item.stackTagCompound;
NBTTagCompound attrTag;
2025-02-26 22:49:26 -05:00
if (root.hasKey(RPGItemAttributes)) {
attrTag = root.getCompoundTag(RPGItemAttributes);
2025-02-24 16:08:22 -05:00
} else {
attrTag = new NBTTagCompound();
}
attrTag.setDouble(attributeKey, value);
2025-02-26 22:49:26 -05:00
root.setTag(RPGItemAttributes, attrTag);
2025-02-24 16:08:22 -05:00
}
/**
* Removes a non–magic attribute from an item.
*/
public static void removeAttribute(ItemStack item, String attributeKey) {
if (item == null || item.stackTagCompound == null) return;
NBTTagCompound root = item.stackTagCompound;
2025-02-26 22:49:26 -05:00
if (root.hasKey(RPGItemAttributes)) {
NBTTagCompound attrTag = root.getCompoundTag(RPGItemAttributes);
attrTag.removeTag(attributeKey);
// If no attributes remain, remove the root tag.
if (attrTag.func_150296_c().isEmpty()) {
2025-02-26 22:49:26 -05:00
root.removeTag(RPGItemAttributes);
}
}
}
/**
* Reads non–magic attributes from an item.
*/
2025-02-24 16:08:22 -05:00
public static Map<String, Double> readAttributes(ItemStack item) {
Map<String, Double> map = new HashMap<>();
2025-02-24 20:07:32 -05:00
if (item == null || item.stackTagCompound == null) return map;
2025-02-24 16:08:22 -05:00
NBTTagCompound root = item.stackTagCompound;
2025-02-26 22:49:26 -05:00
if (root.hasKey(RPGItemAttributes)) {
NBTTagCompound attrTag = root.getCompoundTag(RPGItemAttributes);
2025-02-24 16:08:22 -05:00
Set<String> keys = attrTag.func_150296_c();
2025-02-24 20:07:32 -05:00
for (String key : keys) {
2025-02-24 16:08:22 -05:00
map.put(key, attrTag.getDouble(key));
}
}
return map;
}
/**
* Reads a magic attribute map from an item.
* The given attributeTag is the key under which the compound is stored (e.g., MAGIC_DAMAGE_FLAT).
*/
2025-02-24 16:08:22 -05:00
public static Map<Integer, Double> readMagicAttributeMap(ItemStack item, String attributeTag) {
Map<Integer, Double> map = new HashMap<>();
2025-02-24 20:07:32 -05:00
if (item == null || item.stackTagCompound == null) return map;
if (item.stackTagCompound.hasKey(attributeTag)) {
2025-02-24 16:08:22 -05:00
NBTTagCompound magicMap = item.stackTagCompound.getCompoundTag(attributeTag);
Set<String> keys = magicMap.func_150296_c();
2025-02-24 20:07:32 -05:00
for (String key : keys) {
2025-02-24 16:08:22 -05:00
try {
int magicId = Integer.parseInt(key);
map.put(magicId, magicMap.getDouble(key));
2025-02-24 20:07:32 -05:00
} catch (NumberFormatException e) {
2025-02-24 16:08:22 -05:00
// Skip invalid key.
}
}
}
return map;
}
/**
* Applies (writes) a magic attribute to an item.
* This is essentially the same as writeMagicAttribute.
*/
public static void applyMagicAttribute(ItemStack item, String attributeTag, int magicId, double value) {
writeMagicAttribute(item, attributeTag, magicId, value);
}
/**
* Writes a magic attribute value to the given attributeTag.
*/
2025-02-24 16:08:22 -05:00
public static void writeMagicAttribute(ItemStack item, String attributeTag, int magicId, double value) {
2025-02-24 20:07:32 -05:00
if (item == null) return;
if (item.stackTagCompound == null)
2025-02-24 16:08:22 -05:00
item.stackTagCompound = new NBTTagCompound();
NBTTagCompound magicMap;
2025-02-24 20:07:32 -05:00
if (item.stackTagCompound.hasKey(attributeTag)) {
2025-02-24 16:08:22 -05:00
magicMap = item.stackTagCompound.getCompoundTag(attributeTag);
} else {
magicMap = new NBTTagCompound();
}
magicMap.setDouble(String.valueOf(magicId), value);
item.stackTagCompound.setTag(attributeTag, magicMap);
}
/**
* Removes a magic attribute value from the given attributeTag.
*/
public static void removeMagicAttribute(ItemStack item, String attributeTag, int magicId) {
if (item == null || item.stackTagCompound == null)
return;
NBTTagCompound root = item.stackTagCompound;
if (root.hasKey(attributeTag)) {
NBTTagCompound magicMap = root.getCompoundTag(attributeTag);
magicMap.removeTag(String.valueOf(magicId));
// If the magic map is empty, remove the tag.
if (magicMap.func_150296_c().isEmpty())
root.removeTag(attributeTag);
}
}
2025-02-26 22:49:26 -05:00
@SideOnly(Side.CLIENT)
public static List<String> getToolTip(List<String> original, NBTTagCompound compound) {
2025-02-27 00:30:39 -05:00
List<String> tooltip = new ArrayList<>(original);
2025-02-26 22:49:26 -05:00
NBTTagCompound attrTag = compound.getCompoundTag(RPGItemAttributes);
if (Keyboard.isKeyDown(ClientProxy.NPCButton.getKeyCode())) {
List<String> newTooltips = new ArrayList<>();
if (!tooltip.isEmpty()) {
2025-02-27 00:30:39 -05:00
newTooltips.add(tooltip.get(0));
2025-02-26 22:49:26 -05:00
}
2025-02-27 00:30:39 -05:00
// Lists for non–magic attributes
2025-02-26 22:49:26 -05:00
List<String> baseList = new ArrayList<>();
List<String> modifierList = new ArrayList<>();
List<String> infoList = new ArrayList<>();
List<String> extraList = new ArrayList<>();
2025-02-27 00:30:39 -05:00
// Process non–magic attributes (order maintained)
Iterator<String> 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;
}
2025-02-26 22:49:26 -05:00
double value = attrTag.getDouble(key);
AttributeDefinition def = AttributeController.getAttribute(key);
AttributeDefinition.AttributeSection section = def != null ? def.getSection() : AttributeDefinition.AttributeSection.EXTRA;
2025-02-27 00:30:39 -05:00
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;
2025-02-26 22:49:26 -05:00
}
}
2025-02-27 00:30:39 -05:00
// 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));
2025-02-26 22:49:26 -05:00
tooltip = newTooltips;
} else {
String keyName = Keyboard.getKeyName(ClientProxy.NPCButton.getKeyCode());
tooltip.add(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.ITALIC +
StatCollector.translateToLocal("rpgcore:tooltip").replace("%key%", keyName));
}
return tooltip;
}
2025-02-27 00:30:39 -05:00
/**
* 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<String> baseList, List<String> modifierList,
List<String> infoList, List<String> 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<String> 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) {
2025-02-27 09:27:34 -05:00
String magicDisplayName = magic.getDisplayName() + " " + EnumChatFormatting.GRAY + getMagicAppendix(magicKey);
2025-02-27 00:30:39 -05:00
// 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.
}
}
}
}
}
2025-02-27 09:27:34 -05:00
@SideOnly(Side.CLIENT)
private static String getMagicAppendix(String type){
switch(type){
case ModAttributes.MAGIC_DEFENSE_KEY:
return StatCollector.translateToLocal("rpgcore:attribute.defense");
case ModAttributes.MAGIC_RESISTANCE_KEY:
return StatCollector.translateToLocal("rpgcore:attribute.resistance");
default:
return StatCollector.translateToLocal("rpgcore:attribute.damage");
}
}
2025-02-27 00:30:39 -05:00
/**
* Returns a translated attribute name.
*/
2025-02-27 09:27:34 -05:00
@SideOnly(Side.CLIENT)
2025-02-27 00:30:39 -05:00
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();
2025-02-27 00:48:10 -05:00
String valueString = color + sign + formattedValue;
2025-02-27 00:30:39 -05:00
if (def != null && def.getValueType() == AttributeValueType.PERCENT)
valueString += "%";
2025-02-27 00:48:10 -05:00
valueString += EnumChatFormatting.GRAY;
2025-02-27 00:30:39 -05:00
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<String> buildSection(List<String> lines) {
List<String> section = new ArrayList<>();
if (!lines.isEmpty()) {
section.add("");
section.addAll(lines);
}
return section;
}
2025-02-26 22:49:26 -05:00
/**
* Helper to format a double by removing trailing zeros.
*/
private static String formatDouble(double value) {
return new java.math.BigDecimal(Double.toString(value)).stripTrailingZeros().toPlainString();
}
2025-02-24 16:08:22 -05:00
}