diff --git a/src/main/java/noppes/npcs/controllers/MagicController.java b/src/main/java/noppes/npcs/controllers/MagicController.java index 881c58e44..c0a4903d1 100644 --- a/src/main/java/noppes/npcs/controllers/MagicController.java +++ b/src/main/java/noppes/npcs/controllers/MagicController.java @@ -1,48 +1,53 @@ package noppes.npcs.controllers; -import net.minecraft.init.Blocks; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; -import noppes.npcs.CustomItems; import noppes.npcs.CustomNpcs; import noppes.npcs.LogWriter; -import noppes.npcs.api.handler.data.IMagic; import noppes.npcs.controllers.data.Magic; +import noppes.npcs.controllers.data.MagicCategory; +import noppes.npcs.controllers.data.MagicAssociation; -import java.io.*; -import java.util.*; +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; import java.util.zip.GZIPInputStream; public class MagicController { - public HashMap magicSync = new HashMap(); - public HashMap magics; + public HashMap magics = new HashMap<>(); + public HashMap magicSync = new HashMap<>(); - private static MagicController instance; + public HashMap categoriesSync = new HashMap<>(); + public HashMap categories = new HashMap<>(); + public int lastUsedCategoryID = 0; private int lastUsedID = 0; + private static MagicController instance; public MagicController() { instance = this; - magics = new HashMap(); } public static MagicController getInstance() { return instance; } - public Magic getMagic(int magic) { - return magics.get(magic); + public Magic getMagic(int magicId) { + return magics.get(magicId); + } + + public MagicCategory getCategory(int categoryId) { + return categories.get(categoryId); } public void load() { - magics = new HashMap(); - lastUsedID = 0; File saveDir = CustomNpcs.getWorldSaveDirectory(); - if (saveDir == null) { - return; - } + if (saveDir == null) return; try { File file = new File(saveDir, "magic.dat"); if (file.exists()) { @@ -56,214 +61,6 @@ public class MagicController { } } catch (Exception ee) { } } - magics.clear(); -// if (false) { -// // Create default Pokémon types -// Magic normal = new Magic(0, "Normal", 0xA8A878); -// normal.setIconItem(new ItemStack(net.minecraft.init.Items.paper)); // using paper for Normal -// -// Magic fire = new Magic(1, "Fire", 0xF08030); -// fire.setIconItem(new ItemStack(net.minecraft.init.Items.flint)); // flint for Fire -// -// Magic water = new Magic(2, "Water", 0x6890F0); -// water.setIconItem(new ItemStack(net.minecraft.init.Items.water_bucket)); // water bucket -// -// Magic electric = new Magic(3, "Electric", 0xF8D030); -// electric.setIconItem(new ItemStack(net.minecraft.init.Items.redstone)); // redstone -// -// Magic grass = new Magic(4, "Grass", 0x78C850); -// grass.setIconItem(new ItemStack(net.minecraft.init.Items.wheat_seeds)); // wheat seeds -// -// Magic ice = new Magic(5, "Ice", 0x98D8D8); -// ice.setIconItem(new ItemStack(net.minecraft.init.Items.snowball)); // snowball for Ice -// -// Magic fighting = new Magic(6, "Fighting", 0xC03028); -// fighting.setIconItem(new ItemStack(net.minecraft.init.Items.iron_sword)); // sword for Fighting -// -// Magic poison = new Magic(7, "Poison", 0xA040A0); -// poison.setIconItem(new ItemStack(net.minecraft.init.Items.potionitem)); // potion item for Poison -// -// Magic ground = new Magic(8, "Ground", 0xE0C068); -// ground.setIconItem(new ItemStack(Blocks.dirt)); // dirt for Ground -// -// Magic flying = new Magic(9, "Flying", 0xA890F0); -// flying.setIconItem(new ItemStack(net.minecraft.init.Items.feather)); // feather for Flying -// -// Magic psychic = new Magic(10, "Psychic", 0xF85888); -// psychic.setIconItem(new ItemStack(net.minecraft.init.Items.ender_pearl)); // ender pearl for Psychic -// -// Magic bug = new Magic(11, "Bug", 0xA8B820); -// bug.setIconItem(new ItemStack(net.minecraft.init.Items.spider_eye)); // spider eye for Bug -// -// Magic rock = new Magic(12, "Rock", 0xB8A038); -// rock.setIconItem(new ItemStack(Blocks.cobblestone)); // cobblestone for Rock -// -// Magic ghost = new Magic(13, "Ghost", 0x705898); -// ghost.setIconItem(new ItemStack(net.minecraft.init.Items.skull)); // skull for Ghost -// -// Magic dragon = new Magic(14, "Dragon", 0x7038F8); -// dragon.setIconItem(new ItemStack(Blocks.dragon_egg)); // dragon egg -// -// Magic dark = new Magic(15, "Dark", 0x705848); -// dark.setIconItem(new ItemStack(net.minecraft.init.Items.coal)); // coal for Dark -// -// Magic steel = new Magic(16, "Steel", 0xB8B8D0); -// steel.setIconItem(new ItemStack(net.minecraft.init.Items.iron_ingot)); // iron ingot for Steel -// -// Magic fairy = new Magic(17, "Fairy", 0xEE99AC); -// fairy.setIconItem(new ItemStack(net.minecraft.init.Items.sugar)); // sugar for Fairy -// -// // Now set weaknesses (using a multiplier of 2.0f to indicate “double damage”). -// // The following is based on a common Pokémon type chart. -// normal.weaknesses.put(fighting.id, 2.0f); -// -// fire.weaknesses.put(water.id, 2.0f); -// fire.weaknesses.put(ground.id, 2.0f); -// fire.weaknesses.put(rock.id, 2.0f); -// -// water.weaknesses.put(electric.id, 2.0f); -// water.weaknesses.put(grass.id, 2.0f); -// -// electric.weaknesses.put(ground.id, 2.0f); -// -// grass.weaknesses.put(fire.id, 2.0f); -// grass.weaknesses.put(ice.id, 2.0f); -// grass.weaknesses.put(poison.id, 2.0f); -// grass.weaknesses.put(flying.id, 2.0f); -// grass.weaknesses.put(bug.id, 2.0f); -// -// ice.weaknesses.put(fire.id, 2.0f); -// ice.weaknesses.put(fighting.id, 2.0f); -// ice.weaknesses.put(rock.id, 2.0f); -// ice.weaknesses.put(steel.id, 2.0f); -// -// fighting.weaknesses.put(flying.id, 2.0f); -// fighting.weaknesses.put(psychic.id, 2.0f); -// fighting.weaknesses.put(fairy.id, 2.0f); -// -// poison.weaknesses.put(ground.id, 2.0f); -// poison.weaknesses.put(psychic.id, 2.0f); -// -// ground.weaknesses.put(water.id, 2.0f); -// ground.weaknesses.put(grass.id, 2.0f); -// ground.weaknesses.put(ice.id, 2.0f); -// -// flying.weaknesses.put(electric.id, 2.0f); -// flying.weaknesses.put(ice.id, 2.0f); -// flying.weaknesses.put(rock.id, 2.0f); -// -// psychic.weaknesses.put(bug.id, 2.0f); -// psychic.weaknesses.put(ghost.id, 2.0f); -// psychic.weaknesses.put(dark.id, 2.0f); -// -// bug.weaknesses.put(fire.id, 2.0f); -// bug.weaknesses.put(flying.id, 2.0f); -// bug.weaknesses.put(rock.id, 2.0f); -// -// rock.weaknesses.put(water.id, 2.0f); -// rock.weaknesses.put(grass.id, 2.0f); -// rock.weaknesses.put(fighting.id, 2.0f); -// rock.weaknesses.put(ground.id, 2.0f); -// rock.weaknesses.put(steel.id, 2.0f); -// -// ghost.weaknesses.put(ghost.id, 2.0f); -// ghost.weaknesses.put(dark.id, 2.0f); -// -// dragon.weaknesses.put(ice.id, 2.0f); -// dragon.weaknesses.put(dragon.id, 2.0f); -// dragon.weaknesses.put(fairy.id, 2.0f); -// -// dark.weaknesses.put(fighting.id, 2.0f); -// dark.weaknesses.put(bug.id, 2.0f); -// dark.weaknesses.put(fairy.id, 2.0f); -// -// steel.weaknesses.put(fire.id, 2.0f); -// steel.weaknesses.put(fighting.id, 2.0f); -// steel.weaknesses.put(ground.id, 2.0f); -// -// fairy.weaknesses.put(poison.id, 2.0f); -// fairy.weaknesses.put(steel.id, 2.0f); -// -// // Register the types. -// magics.put(normal.id, normal); -// magics.put(fire.id, fire); -// magics.put(water.id, water); -// magics.put(electric.id, electric); -// magics.put(grass.id, grass); -// magics.put(ice.id, ice); -// magics.put(fighting.id, fighting); -// magics.put(poison.id, poison); -// magics.put(ground.id, ground); -// magics.put(flying.id, flying); -// magics.put(psychic.id, psychic); -// magics.put(bug.id, bug); -// magics.put(rock.id, rock); -// magics.put(ghost.id, ghost); -// magics.put(dragon.id, dragon); -// magics.put(dark.id, dark); -// magics.put(steel.id, steel); -// magics.put(fairy.id, fairy); -// } -// -// if (true) { -// // Create default magics -// Magic earth = new Magic(0, "Earth", 0x00DD00, 1, 1); -// earth.setIconItem(new ItemStack(CustomItems.earthElement)); -// -// Magic water = new Magic(1, "Water", 0xF2DD00, 1, 2); -// water.setIconItem(new ItemStack(CustomItems.waterElement)); -// -// Magic fire = new Magic(2, "Fire", 0xDD0000, 1, 3); -// fire.setIconItem(new ItemStack(CustomItems.spellFire)); -// -// Magic air = new Magic(3, "Air", 0xDD0000, 1, 0); -// air.setIconItem(new ItemStack(CustomItems.airElement)); -// -// Magic dark = new Magic(4, "Dark", 0xDD0000, 0, 3); -// dark.setIconItem(new ItemStack(CustomItems.spellDark)); -// -// Magic holy = new Magic(5, "Holy", 0xDD0000, 0, 1); -// holy.setIconItem(new ItemStack(CustomItems.spellHoly)); -// -// Magic nature = new Magic(6, "Nature", 0xDD0000, 0, 0); -// nature.setIconItem(new ItemStack(CustomItems.spellNature)); -// -// Magic arcane = new Magic(7, "Arcane", 0xDD0000, 0, 2); -// arcane.setIconItem(new ItemStack(CustomItems.spellArcane)); -// -// // Insiders -// earth.weaknesses.put(air.id, 0.60f); -// water.weaknesses.put(earth.id, 0.60f); -// fire.weaknesses.put(water.id, 0.60f); -// air.weaknesses.put(fire.id, 0.60f); -// -// // Outsiders -// dark.weaknesses.put(nature.id, 0.60f); -// nature.weaknesses.put(holy.id, 0.60f); -// holy.weaknesses.put(arcane.id, 0.60f); -// arcane.weaknesses.put(dark.id, 0.60f); -// -// // Cross Interactions -// earth.weaknesses.put(nature.id, 0.30f); -// water.weaknesses.put(holy.id, 0.30f); -// fire.weaknesses.put(arcane.id, 0.30f); -// air.weaknesses.put(dark.id, 0.30f); -// dark.weaknesses.put(fire.id, 0.30f); -// nature.weaknesses.put(air.id, 0.30f); -// holy.weaknesses.put(earth.id, 0.30f); -// arcane.weaknesses.put(water.id, 0.30f); -// -// // Add them to the registry -// magics.put(earth.id, earth); -// magics.put(water.id, water); -// magics.put(fire.id, fire); -// magics.put(air.id, air); -// magics.put(dark.id, dark); -// magics.put(holy.id, holy); -// magics.put(nature.id, nature); -// magics.put(arcane.id, arcane); -// } -// printAllMagicInteractions(); } private void loadMagicFile(File file) throws IOException { @@ -275,67 +72,67 @@ public class MagicController { } public void loadMagic(DataInputStream stream) throws IOException { - HashMap magic = new HashMap(); - NBTTagCompound nbttagcompound1 = CompressedStreamTools.read(stream); - lastUsedID = nbttagcompound1.getInteger("lastID"); - NBTTagList list = nbttagcompound1.getTagList("NPCMagic", 10); // using "NPCMagic" as tag + NBTTagCompound compound = CompressedStreamTools.read(stream); + lastUsedID = compound.getInteger("lastID"); - if (list != null) { - for (int i = 0; i < list.tagCount(); i++) { - NBTTagCompound nbttagcompound = list.getCompoundTagAt(i); - Magic loadMagic = new Magic(); - loadMagic.readNBT(nbttagcompound); - magic.put(loadMagic.id, loadMagic); - } + // Load magics + magics.clear(); + NBTTagList magicList = compound.getTagList("Magics", 10); + for (int i = 0; i < magicList.tagCount(); i++) { + NBTTagCompound magCompound = magicList.getCompoundTagAt(i); + Magic mag = new Magic(); + mag.readNBT(magCompound); + magics.put(mag.id, mag); + } + + // Load categories + categories.clear(); + NBTTagList catList = compound.getTagList("Categories", 10); + for (int i = 0; i < catList.tagCount(); i++) { + NBTTagCompound catCompound = catList.getCompoundTagAt(i); + MagicCategory cat = new MagicCategory(); + cat.readNBT(catCompound); + categories.put(cat.id, cat); } - this.magics = magic; } public NBTTagCompound getNBT() { - NBTTagList list = new NBTTagList(); - for (int slot : magics.keySet()) { - Magic mag = magics.get(slot); - NBTTagCompound nbtMagic = new NBTTagCompound(); - mag.writeNBT(nbtMagic); - list.appendTag(nbtMagic); + NBTTagList magicList = new NBTTagList(); + for (Magic mag : magics.values()) { + NBTTagCompound magCompound = new NBTTagCompound(); + mag.writeNBT(magCompound); + magicList.appendTag(magCompound); } - NBTTagCompound nbttagcompound = new NBTTagCompound(); - nbttagcompound.setInteger("lastID", lastUsedID); - nbttagcompound.setTag("NPCMagic", list); // use same tag as loadMagic - return nbttagcompound; + NBTTagList catList = new NBTTagList(); + for (MagicCategory cat : categories.values()) { + NBTTagCompound catCompound = new NBTTagCompound(); + cat.writeNBT(catCompound); + catList.appendTag(catCompound); + } + NBTTagCompound compound = new NBTTagCompound(); + compound.setInteger("lastID", lastUsedID); + compound.setTag("Magics", magicList); + compound.setTag("Categories", catList); + return compound; } - public void saveFactions() { + public void saveMagicData() { try { File saveDir = CustomNpcs.getWorldSaveDirectory(); - File file = new File(saveDir, "magic.dat_new"); - File file1 = new File(saveDir, "magic.dat_old"); - File file2 = new File(saveDir, "magic.dat"); - CompressedStreamTools.writeCompressed(getNBT(), new FileOutputStream(file)); - if (file1.exists()) { - file1.delete(); - } - file2.renameTo(file1); - if (file2.exists()) { - file2.delete(); - } - file.renameTo(file2); - if (file.exists()) { - file.delete(); - } + File fileNew = new File(saveDir, "magic.dat_new"); + File fileOld = new File(saveDir, "magic.dat_old"); + File fileCurrent = new File(saveDir, "magic.dat"); + CompressedStreamTools.writeCompressed(getNBT(), new FileOutputStream(fileNew)); + if (fileOld.exists()) fileOld.delete(); + fileCurrent.renameTo(fileOld); + if (fileCurrent.exists()) fileCurrent.delete(); + fileNew.renameTo(fileCurrent); + if (fileNew.exists()) fileNew.delete(); } catch (Exception e) { LogWriter.except(e); } } - public Magic get(int magicID) { - return magics.get(magicID); - } - - public List list() { - return new ArrayList(this.magics.values()); - } - public void saveMagic(Magic mag) { if (mag.id < 0) { mag.id = getUnusedId(); @@ -347,252 +144,76 @@ public class MagicController { while (hasName(mag.name)) mag.name += "_"; } - magics.remove(mag.id); magics.put(mag.id, mag); - - NBTTagCompound facCompound = new NBTTagCompound(); - mag.writeNBT(facCompound); - // Server.sendToAll(EnumPacketClient.SYNC_UPDATE, SyncType.MAGIC, facCompound); - saveFactions(); + saveMagicData(); } public int getUnusedId() { if (lastUsedID == 0) { - for (int catid : magics.keySet()) - if (catid > lastUsedID) - lastUsedID = catid; + for (int id : magics.keySet()) + if (id > lastUsedID) + lastUsedID = id; } lastUsedID++; return lastUsedID; } public boolean hasName(String newName) { - if (newName.trim().isEmpty()) - return true; + if (newName.trim().isEmpty()) return true; for (Magic mag : magics.values()) if (mag.name.equals(newName)) return true; return false; } - public Magic getMagicFromName(String magicName) { - for (Map.Entry entryMag : MagicController.getInstance().magics.entrySet()) { - if (entryMag.getValue().name.equalsIgnoreCase(magicName)) { - return entryMag.getValue(); - } - } - return null; - } + // === Category management methods === - public String[] getNames() { - String[] names = new String[magics.size()]; - int i = 0; - for (Magic mag : magics.values()) { - names[i] = mag.name.toLowerCase(); - i++; - } - return names; - } - - // --- New functions for applying magic NBT stats and calculating damage --- - - /** - * Applies magic-type damage to an item. A weapon/item can have multiple magic damage values. - * The damage is stored under a compound tag "MagicDamage" where each key is the magic ID. - */ - public static void addMagicDamageToItem(ItemStack item, int magicId, float damage) { - if (item == null) return; - if (item.stackTagCompound == null) - item.stackTagCompound = new NBTTagCompound(); - NBTTagCompound compound = item.stackTagCompound; - NBTTagCompound magicDamage; - if (compound.hasKey("MagicDamage")) { - magicDamage = compound.getCompoundTag("MagicDamage"); + public void addCategory(MagicCategory category) { + if (category.id < 0) { + lastUsedCategoryID++; + category.id = lastUsedCategoryID; } else { - magicDamage = new NBTTagCompound(); + while (containsCategoryName(category.title)) + category.title += "_"; + } + categories.put(category.id, category); + saveMagicData(); + } + + public boolean containsCategoryName(String title) { + title = title.toLowerCase(); + for (MagicCategory cat : categories.values()) { + if (cat.title.toLowerCase().equals(title)) + return true; + } + return false; + } + + public void removeCategory(int categoryId) { + if (categories.containsKey(categoryId)) { + categories.remove(categoryId); + saveMagicData(); } - magicDamage.setFloat(String.valueOf(magicId), damage); - compound.setTag("MagicDamage", magicDamage); } /** - * Applies magic resistance to an armor piece. - * The resistance is stored under a compound tag "MagicResistances" with the magic ID as key. + * Associates a magic with a category along with its per-category ordering data. */ - public static void addMagicResistanceToArmor(ItemStack armor, int magicId, float resistance) { - if (armor == null) return; - if (armor.stackTagCompound == null) - armor.stackTagCompound = new NBTTagCompound(); - NBTTagCompound compound = armor.stackTagCompound; - NBTTagCompound magicResist; - if (compound.hasKey("MagicResistances")) { - magicResist = compound.getCompoundTag("MagicResistances"); - } else { - magicResist = new NBTTagCompound(); - } - magicResist.setFloat(String.valueOf(magicId), resistance); - compound.setTag("MagicResistances", magicResist); + public void addMagicToCategory(int magicId, int categoryId, int index, int priority) { + MagicCategory cat = categories.get(categoryId); + if (cat == null) return; + MagicAssociation assoc = new MagicAssociation(); + assoc.magicId = magicId; + assoc.index = index; + assoc.priority = priority; + cat.associations.put(magicId, assoc); + saveMagicData(); } - /** - * Given a collection of armor pieces, sums the resistance value for the specified magic ID. - */ - public static float calculateTotalMagicResistance(int magicId, Iterable armors) { - float totalResistance = 0.0F; - for (ItemStack armor : armors) { - if (armor != null && armor.hasTagCompound() && armor.stackTagCompound.hasKey("MagicResistances")) { - NBTTagCompound magicResist = armor.stackTagCompound.getCompoundTag("MagicResistances"); - if (magicResist.hasKey(String.valueOf(magicId))) { - totalResistance += magicResist.getFloat(String.valueOf(magicId)); - } - } - } - return totalResistance; - } - - /** - * Calculates the final magic damage after applying armor resistances. - * For a given magic type, the resistance is applied. - * - * @param magicId the magic type - * @param baseDamage the base damage value - * @param armors an Iterable collection of armor ItemStacks - * @return the final damage after reduction - */ - public static float calculateFinalMagicDamage(int magicId, float baseDamage, Iterable armors) { - if (getInstance().getMagic(magicId) == null) { - // If the magic type is not defined, treat it as non-magical. - return baseDamage; - } - float resistance = calculateTotalMagicResistance(magicId, armors); - // Resistance is assumed to be a fractional reduction (e.g., 0.2 = 20% reduction). - return baseDamage * (1.0F - resistance); - } - - /** - * Extracts magic damage values from a weapon ItemStack. - * It looks for a compound tag "CNPCMagic" first; if not found, it falls back to "MagicDamage". - * Returns a mapping of magic ID to its damage value. - */ - public static Map getMagicDamageFromItem(ItemStack item) { - Map damageMap = new HashMap(); - if (item == null || item.stackTagCompound == null) return damageMap; - NBTTagCompound compound = item.stackTagCompound; - NBTTagCompound damageCompound = null; - if (compound.hasKey("CNPCMagic")) { - NBTTagCompound magicCompound = compound.getCompoundTag("CNPCMagic"); - if (magicCompound.hasKey("MagicDamage")) { - damageCompound = magicCompound.getCompoundTag("MagicDamage"); - } - } else if (compound.hasKey("MagicDamage")) { - damageCompound = compound.getCompoundTag("MagicDamage"); - } - if (damageCompound != null) { - Set keys = damageCompound.func_150296_c(); - for (String key : keys) { - try { - int magicId = Integer.parseInt(key); - float dmg = damageCompound.getFloat(key); - damageMap.put(magicId, dmg); - } catch (NumberFormatException e) { - // Ignore non-integer keys. - } - } - } - return damageMap; - } - - /** - * Extracts magic resistances from an armor ItemStack. - * It checks for a "CNPCMagic" container first; if not present, it falls back to "MagicResistances". - * Returns a mapping of magic ID to its resistance value. - */ - public static Map getMagicResistancesFromItem(ItemStack item) { - Map resistMap = new HashMap(); - if (item == null || item.stackTagCompound == null) return resistMap; - NBTTagCompound compound = item.stackTagCompound; - NBTTagCompound resistCompound = null; - if (compound.hasKey("CNPCMagic")) { - NBTTagCompound magicCompound = compound.getCompoundTag("CNPCMagic"); - if (magicCompound.hasKey("MagicResistances")) { - resistCompound = magicCompound.getCompoundTag("MagicResistances"); - } - } else if (compound.hasKey("MagicResistances")) { - resistCompound = compound.getCompoundTag("MagicResistances"); - } - if (resistCompound != null) { - Set keys = resistCompound.func_150296_c(); - for (String key : keys) { - try { - int magicId = Integer.parseInt(key); - float res = resistCompound.getFloat(key); - resistMap.put(magicId, res); - } catch (NumberFormatException e) { - // Ignore non-integer keys. - } - } - } - return resistMap; - } - - /** - * Validates whether an item (weapon or armor) contains any magic-related NBT. - */ - public static boolean hasMagicStats(ItemStack item) { - if (item == null || item.stackTagCompound == null) return false; - NBTTagCompound compound = item.stackTagCompound; - return compound.hasKey("CNPCMagic") || compound.hasKey("MagicDamage") || compound.hasKey("MagicResistances"); - } - - /** - * Calculates a damage breakdown for each magic type from a weapon when applied against a set of armors. - * This function will ignore any magic with ID 0 (neutral), so only magic damage is returned. - * Returns a map where keys are magic IDs (non-zero) and values are the final damage for that type. - */ - public static Map calculateDamageBreakdown(ItemStack weapon, Iterable armors) { - Map breakdown = new HashMap(); - Map weaponDamage = getMagicDamageFromItem(weapon); - for (Map.Entry entry : weaponDamage.entrySet()) { - int magicId = entry.getKey(); - // Skip magic ID 0 (neutral) - if (magicId == 0) continue; - float dmg = entry.getValue(); - float finalDmg = calculateFinalMagicDamage(magicId, dmg, armors); - breakdown.put(magicId, finalDmg); - } - return breakdown; - } - - /** - * Calculates the total final magic damage of a weapon after applying the resistances of a set of armor pieces. - * This sums only the magic interactions (magic IDs other than 0). - */ - public static float calculateTotalDamage(ItemStack weapon, Iterable armors) { - float totalDamage = 0.0F; - Map breakdown = calculateDamageBreakdown(weapon, armors); - for (Float dmg : breakdown.values()) { - totalDamage += dmg; - } - return totalDamage; - } - - /** - * Prints all magic interactions (weaknesses) in the registry. - * For each magic (defender) that has weaknesses, prints the corresponding attacker and the extra damage percentage. - * Format: "Magic ID: [attacker id], Name: "[attacker name]" does [percentage*100]% extra damage to Magic ID: [defender id], Name: "[defender name]". - */ - public static void printAllMagicInteractions() { - MagicController mc = getInstance(); - for (Magic defender : mc.magics.values()) { - for (Map.Entry entry : defender.weaknesses.entrySet()) { - int attackerId = entry.getKey(); - float percentage = entry.getValue(); - Magic attacker = mc.getMagic(attackerId); - if (attacker != null) { - System.out.println("Magic ID: " + attacker.id + ", Name: \"" + attacker.name + "\" does " - + (percentage * 100) + "% extra damage to Magic ID: " + defender.id + ", Name: \"" + defender.name + "\""); - } - } - } + public void removeMagicFromCategory(int magicId, int categoryId) { + MagicCategory cat = categories.get(categoryId); + if (cat == null) return; + cat.associations.remove(magicId); + saveMagicData(); } } diff --git a/src/main/java/noppes/npcs/controllers/data/Magic.java b/src/main/java/noppes/npcs/controllers/data/Magic.java index 1b5636bc1..25b5b1474 100644 --- a/src/main/java/noppes/npcs/controllers/data/Magic.java +++ b/src/main/java/noppes/npcs/controllers/data/Magic.java @@ -5,7 +5,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import noppes.npcs.api.handler.data.IMagic; import noppes.npcs.controllers.MagicController; - import java.util.HashMap; import java.util.Map; @@ -14,16 +13,9 @@ public class Magic implements IMagic { public int color = Integer.parseInt("FF00", 16); public int id = -1; - public int index; - public int priority; - - // Icon as an ItemStack or as a texture file public ItemStack iconItem = null; public String iconTexture = ""; - - // Weaknesses mapping: key = magic ID this magic is weak against, - // value = extra damage percentage (as a fraction, e.g. 0.2 for 20% extra damage) - public Map weaknesses = new HashMap(); + public Map weaknesses = new HashMap<>(); public Magic() {} @@ -33,14 +25,6 @@ public class Magic implements IMagic { this.id = id; } - public Magic(int id, String name, int color, int index, int priority) { - this.name = name; - this.color = color; - this.id = id; - this.index = index; - this.priority = priority; - } - public static String formatName(String name) { name = name.toLowerCase().trim(); return name.substring(0, 1).toUpperCase() + name.substring(1); @@ -50,19 +34,15 @@ public class Magic implements IMagic { name = compound.getString("Name"); color = compound.getInteger("Color"); id = compound.getInteger("Slot"); - index = compound.getInteger("Index"); - priority = compound.getInteger("Priority"); - + // No longer reading index/priority here. if(compound.hasKey("IconItem")){ NBTTagCompound itemTag = compound.getCompoundTag("IconItem"); iconItem = ItemStack.loadItemStackFromNBT(itemTag); } iconTexture = compound.getString("IconTexture"); - - // Read the weaknesses mapping from NBT. weaknesses.clear(); if(compound.hasKey("Weaknesses")) { - NBTTagList weaknessList = compound.getTagList("Weaknesses", 10); // compound tags + NBTTagList weaknessList = compound.getTagList("Weaknesses", 10); for(int i = 0; i < weaknessList.tagCount(); i++){ NBTTagCompound weaknessTag = weaknessList.getCompoundTagAt(i); int weakMagicId = weaknessTag.getInteger("MagicID"); @@ -76,9 +56,7 @@ public class Magic implements IMagic { compound.setInteger("Slot", id); compound.setString("Name", name); compound.setInteger("Color", color); - compound.setInteger("Index", index); - compound.setInteger("Priority", priority); - + // No longer writing index/priority here. if(iconItem != null) { NBTTagCompound itemTag = new NBTTagCompound(); iconItem.writeToNBT(itemTag); @@ -87,8 +65,6 @@ public class Magic implements IMagic { if(iconTexture != null && !iconTexture.isEmpty()){ compound.setString("IconTexture", iconTexture); } - - // Write the weaknesses mapping. NBTTagList weaknessList = new NBTTagList(); for(Map.Entry entry : weaknesses.entrySet()){ NBTTagCompound weaknessTag = new NBTTagCompound(); @@ -111,26 +87,11 @@ public class Magic implements IMagic { this.name = name; } - public int getPriority() { - return priority; - } - - public void setPriority(int priority) { - this.priority = priority; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - public void setColor(int color) { - this.color = color; + public void setColor(int c) { + this.color = c; } + @Override public int getColor() { return this.color; } diff --git a/src/main/java/noppes/npcs/controllers/data/MagicAssociation.java b/src/main/java/noppes/npcs/controllers/data/MagicAssociation.java new file mode 100644 index 000000000..2589233c9 --- /dev/null +++ b/src/main/java/noppes/npcs/controllers/data/MagicAssociation.java @@ -0,0 +1,11 @@ +package noppes.npcs.controllers.data; + +/** + * A helper class that represents the relationship between a Magic and a Category. + * It holds per-category ordering data. + */ +public class MagicAssociation { + public int magicId; + public int index; + public int priority; +} diff --git a/src/main/java/noppes/npcs/controllers/data/MagicCategory.java b/src/main/java/noppes/npcs/controllers/data/MagicCategory.java new file mode 100644 index 000000000..d3a3b029e --- /dev/null +++ b/src/main/java/noppes/npcs/controllers/data/MagicCategory.java @@ -0,0 +1,46 @@ +package noppes.npcs.controllers.data; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import java.util.HashMap; + +/** + * Holds category information for magic. + * Each category can have many magic associations. + */ +public class MagicCategory { + public int id = -1; + public String title = ""; + public HashMap associations = new HashMap<>(); + + public MagicCategory() {} + + public void readNBT(NBTTagCompound compound) { + id = compound.getInteger("CategoryID"); + title = compound.getString("Title"); + associations.clear(); + NBTTagList list = compound.getTagList("Associations", 10); // compound tags + for (int i = 0; i < list.tagCount(); i++) { + NBTTagCompound assocTag = list.getCompoundTagAt(i); + MagicAssociation assoc = new MagicAssociation(); + assoc.magicId = assocTag.getInteger("MagicID"); + assoc.index = assocTag.getInteger("Index"); + assoc.priority = assocTag.getInteger("Priority"); + associations.put(assoc.magicId, assoc); + } + } + + public void writeNBT(NBTTagCompound compound) { + compound.setInteger("CategoryID", id); + compound.setString("Title", title); + NBTTagList list = new NBTTagList(); + for (MagicAssociation assoc : associations.values()) { + NBTTagCompound assocTag = new NBTTagCompound(); + assocTag.setInteger("MagicID", assoc.magicId); + assocTag.setInteger("Index", assoc.index); + assocTag.setInteger("Priority", assoc.priority); + list.appendTag(assocTag); + } + compound.setTag("Associations", list); + } +}