diff --git a/build.gradle.kts b/build.gradle.kts index 98b7c2b..a59ff6e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,18 +1,19 @@ import net.minecrell.pluginyml.bukkit.BukkitPluginDescription plugins { - id("com.playmonumenta.gradle-config") version "1.+" + id("com.playmonumenta.gradle-config") version "2.2+" } dependencies { compileOnly(libs.commandapi) compileOnly(libs.nbtapi) - compileOnly(libs.redissync) { + compileOnly(libs.mixinapi) + compileOnly(libs.nbteditor) { artifact { classifier = "all" } } - compileOnly(libs.nbteditor) { + compileOnly(libs.redissync) { artifact { classifier = "all" } @@ -20,6 +21,10 @@ dependencies { compileOnly(libs.gson) } +tasks.javadoc { + (options as StandardJavadocDocletOptions).addBooleanOption("Xdoclint:none", true) +} + monumenta { name("LibraryOfSouls") paper( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6b53af4..fb9a58c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,6 +4,7 @@ nbtapi = "2.12.0-SNAPSHOT" redissync = "4.1" nbteditor = "4.1" gson = "2.8.5" +mixinapi = "1.0.4" [libraries] commandapi = { module = "dev.jorel:commandapi-bukkit-core", version.ref = "commandapi" } @@ -11,3 +12,4 @@ nbtapi = { module = "de.tr7zw:item-nbt-api-plugin", version.ref = "nbtapi" } redissync = { module = "com.playmonumenta:redissync", version.ref = "redissync" } nbteditor = { module = "com.playmonumenta:nbteditor", version.ref = "nbteditor" } gson = { module = "com.google.code.gson:gson", version.ref = "gson" } +mixinapi = { module = "com.playmonumenta.papermixins:plugin-api", version.ref = "mixinapi" } diff --git a/src/main/java/com/playmonumenta/libraryofsouls/LibraryOfSouls.java b/src/main/java/com/playmonumenta/libraryofsouls/LibraryOfSouls.java index ca361a3..13d5ec9 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/LibraryOfSouls.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/LibraryOfSouls.java @@ -95,7 +95,7 @@ public void onEnable() { /* Don't load the bestiary config initially - this will happen when the souls database loads */ Config.load(getLogger(), getDataFolder(), false); - getLogger().info("Library of Souls read only: " + Boolean.toString(Config.isReadOnly())); + getLogger().info("Library of Souls read only: " + Config.isReadOnly()); if (!Config.isReadOnly()) { LibraryOfSoulsCommand.registerWriteAccessCommands(); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulEntry.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulEntry.java index de1de01..eea1e3c 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulEntry.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulEntry.java @@ -14,9 +14,9 @@ import com.playmonumenta.libraryofsouls.bestiary.BestiarySoulInventory; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Random; import java.util.Set; import net.kyori.adventure.text.Component; @@ -51,7 +51,7 @@ public SoulEntry(List history, Set locationNames, List mHistory = history; if (locationNames == null) { - mLocs = new HashSet(); + mLocs = new HashSet<>(); } else { mLocs = locationNames; } @@ -62,18 +62,13 @@ public SoulEntry(List history, Set locationNames, List mLore = lore; } - if (description == null) { - mDescription = new ArrayList<>(); - } else { - mDescription = description; - } + mDescription = Objects.requireNonNullElseGet(description, ArrayList::new); String refLabel = history.get(0).getLabel(); - Component refName = history.get(0).getName(); for (SoulHistoryEntry entry : history) { if (!entry.getLabel().equals(refLabel)) { - throw new Exception("Soul history has mismatching names! '" + refName + "' != '" + entry.getName()); + throw new Exception("Soul history has mismatching labels! '" + refLabel + "' != '" + entry.getLabel()); } } } @@ -82,8 +77,8 @@ public SoulEntry(List history, Set locationNames, List public SoulEntry(Player player, NBTTagCompound nbt) throws Exception { SoulHistoryEntry newHist = new SoulHistoryEntry(player, nbt); - mLocs = new HashSet(); - mHistory = new ArrayList(1); + mLocs = new HashSet<>(); + mHistory = new ArrayList<>(1); mHistory.add(newHist); mLore = new ArrayList<>(); mDescription = new ArrayList<>(); @@ -281,7 +276,7 @@ public ItemStack getBestiaryItem(Player player) { // Hide weapon damage, book enchants, and potion effects: meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); meta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); + meta.addItemFlags(ItemFlag.HIDE_ITEM_SPECIFICS); item.setItemMeta(meta); return item; @@ -346,15 +341,11 @@ public InfoTier getInfoTier(Player player) { return InfoTier.EVERYTHING; } - Integer kills = BestiaryManager.getKillsForMob(player, this); - if (kills != null && kills >= 1) { - if (kills >= 60 - || (isElite() && kills >= 10) - || (isBoss() && kills >= 2)) { + int kills = BestiaryManager.getKillsForMob(player, this); + if (kills >= 1) { + if (kills >= 60 || (isElite() && kills >= 10) || (isBoss() && kills >= 2)) { return InfoTier.EVERYTHING; - } else if (kills >= 30 - || (isElite() && kills >= 5) - || (isBoss() && kills >= 1)) { + } else if (kills >= 30 || (isElite() && kills >= 5) || isBoss()) { return InfoTier.STATS; } else { return InfoTier.MINIMAL; @@ -366,11 +357,11 @@ public InfoTier getInfoTier(Player player) { //Checks if the mob is invlunerable, for bestiary purposes public boolean isInvulnerable() { EntityNBT entityNBT = EntityNBT.fromEntityData(this.getNBT()); - EffectsVariable effectVar = new EffectsVariable("ActiveEffects"); + EffectsVariable effectVar = new EffectsVariable("active_effects"); BooleanVariable booVar = new BooleanVariable("Invulnerable"); - String ret = ((BooleanVariable)booVar.bind(entityNBT.getData())).get(); - boolean override = (ret != null && ret.toLowerCase().equals("true")); + String ret = booVar.bind(entityNBT.getData()).get(); + boolean override = (ret != null && ret.equalsIgnoreCase("true")); ItemStack effectItem = ((EffectsVariable)effectVar.bind(entityNBT.getData())).getItem(); if (effectItem != null && effectItem.hasItemMeta()) { @@ -396,7 +387,7 @@ public MobType getMobType() { } public List getHistory() { - return new ArrayList(mHistory); + return new ArrayList<>(mHistory); } public Set getLocationNames() { @@ -404,7 +395,7 @@ public Set getLocationNames() { } public static SoulEntry fromJson(JsonObject obj, boolean loadHistory) throws Exception { - Set locs = new HashSet(); + Set locs = new HashSet<>(); JsonElement elem = obj.get("location_names"); if (elem != null) { JsonArray array = elem.getAsJsonArray(); @@ -412,11 +403,9 @@ public static SoulEntry fromJson(JsonObject obj, boolean loadHistory) throws Exc throw new Exception("Failed to parse location_names as JSON array"); } - Iterator iter = array.iterator(); - while (iter.hasNext()) { - JsonElement tagElement = iter.next(); + for (JsonElement tagElement : array) { if (!tagElement.isJsonPrimitive()) { - throw new Exception("location_names entry for '" + elem.toString() + "' is not a string!"); + throw new Exception("location_names entry for '" + elem + "' is not a string!"); } locs.add(tagElement.getAsString()); } @@ -430,11 +419,9 @@ public static SoulEntry fromJson(JsonObject obj, boolean loadHistory) throws Exc throw new Exception("Failed to parse lore as JSON array"); } - Iterator iter = array.iterator(); - while (iter.hasNext()) { - JsonElement loreElement = iter.next(); + for (JsonElement loreElement : array) { if (!loreElement.isJsonPrimitive()) { - throw new Exception("location_names entry for '" + elem.toString() + "' is not a string!"); + throw new Exception("location_names entry for '" + elem + "' is not a string!"); } Component comp = GSON_SERIALIZER.deserialize(loreElement.getAsString()); lore.add(comp); @@ -451,9 +438,7 @@ public static SoulEntry fromJson(JsonObject obj, boolean loadHistory) throws Exc throw new Exception("Failed to parse description as JSON array"); } - Iterator iter = array.iterator(); - while (iter.hasNext()) { - JsonElement descriptionElement = iter.next(); + for (JsonElement descriptionElement : array) { if (!descriptionElement.isJsonPrimitive()) { throw new Exception("description entry for '" + elem + "' is not a string!"); } @@ -464,7 +449,7 @@ public static SoulEntry fromJson(JsonObject obj, boolean loadHistory) throws Exc description.add(Component.text(elem.getAsString())); } - List history = new ArrayList(); + List history = new ArrayList<>(); elem = obj.get("history"); if (elem != null) { JsonArray array = elem.getAsJsonArray(); @@ -475,16 +460,16 @@ public static SoulEntry fromJson(JsonObject obj, boolean loadHistory) throws Exc if (loadHistory) { for (JsonElement historyElement : array) { if (!historyElement.isJsonObject()) { - throw new Exception("history entry for '" + elem.toString() + "' is not a string!"); + throw new Exception("history entry for '" + elem + "' is not a string!"); } history.add(SoulHistoryEntry.fromJson(historyElement.getAsJsonObject(), locs, lore, description)); } } else { - if (array.size() >= 1) { + if (!array.isEmpty()) { JsonElement historyElement = array.get(0); if (!historyElement.isJsonObject()) { - throw new Exception("history entry for '" + elem.toString() + "' is not a string!"); + throw new Exception("history entry for '" + elem + "' is not a string!"); } history.add(SoulHistoryEntry.fromJson(historyElement.getAsJsonObject(), locs, lore, description)); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulHistoryEntry.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulHistoryEntry.java index 3044311..ccac88f 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulHistoryEntry.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulHistoryEntry.java @@ -4,8 +4,7 @@ import com.goncalomb.bukkit.mylib.reflect.NBTTagList; import com.goncalomb.bukkit.nbteditor.bos.BookOfSouls; import com.goncalomb.bukkit.nbteditor.nbt.EntityNBT; -import com.goncalomb.bukkit.nbteditor.nbt.ItemStackNBTWrapper; -import com.goncalomb.bukkit.nbteditor.nbt.variables.ListVariable; +import com.google.common.collect.Lists; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.playmonumenta.libraryofsouls.utils.Utils; @@ -14,6 +13,7 @@ import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -22,10 +22,10 @@ import java.util.Set; import java.util.logging.Logger; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -34,14 +34,13 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.util.BoundingBox; import org.jetbrains.annotations.Nullable; public class SoulHistoryEntry implements Soul { private static class HitboxSize { - private double mWidth; - private double mHeight; + private final double mWidth; + private final double mHeight; public HitboxSize(Location origin, NBTTagCompound nbt) { Entity entity = EntityNBT.fromEntityData(nbt).spawn(origin); @@ -49,9 +48,9 @@ public HitboxSize(Location origin, NBTTagCompound nbt) { // TODO get width and height of bounding box relative to origin (ignore height below origin, because boats are whack) mWidth = Math.max(Math.max(bb.getMaxX() - origin.getX(), - bb.getMaxZ() - origin.getZ()), - Math.max(origin.getX() - bb.getMinX(), - origin.getZ() - bb.getMinZ())); + bb.getMaxZ() - origin.getZ()), + Math.max(origin.getX() - bb.getMinX(), + origin.getZ() - bb.getMinZ())); mHeight = bb.getMaxY() - origin.getY(); } @@ -115,7 +114,7 @@ public SoulHistoryEntry(Player player, NBTTagCompound nbt) throws Exception { mNBT = nbt; mModifiedOn = Instant.now().getEpochSecond(); mModifiedBy = player.getName(); - mLocs = new HashSet(); + mLocs = new HashSet<>(); mId = EntityNBT.fromEntityData(mNBT).getEntityType().getKey(); mLore = new ArrayList<>(); mDescription = new ArrayList<>(); @@ -285,30 +284,36 @@ public Component getDisplayName() { @Override public boolean isBoss() { - boolean isBoss = false; NBTTagList tags = mNBT.getList("Tags"); - if (tags != null && tags.size() > 0) { - for (Object obj : tags.getAsArray()) { - if (obj.equals("Boss")) { - isBoss = true; - } + + if (tags == null || tags.size() <= 0) { + return false; + } + + for (Object obj : tags.getAsArray()) { + if (obj.equals("Boss")) { + return true; } } - return isBoss; + + return false; } @Override public boolean isElite() { - boolean isElite = false; NBTTagList tags = mNBT.getList("Tags"); - if (tags != null && tags.size() > 0) { - for (Object obj : tags.getAsArray()) { - if (obj.equals("Elite")) { - isElite = true; - } + + if (tags == null || tags.size() <= 0) { + return false; + } + + for (Object obj : tags.getAsArray()) { + if (obj.equals("Elite")) { + return true; } } - return isElite; + + return false; } @Override @@ -320,33 +325,57 @@ public Entity summon(Location loc) { * Soul Interface *--------------------------------------------------------------------------------*/ - private List stringifyWrapList(String prefix, int maxLen, Object[] elements) { - List ret = new ArrayList(); + private List stringifyWrapList(String prefix, int maxLen, int minLen, Object[] elements) { + final var text = Arrays.stream(elements) + .map(element -> Component.text((String) element, Utils.colorFromInt(element.hashCode()))) + .collect(Component.toComponent(Component.space())); - String cur = "" + prefix; - boolean first = true; - for (Object element : elements) { - String entry = (String)element; + return Utils.wrapComponent((TextComponent) text, maxLen - prefix.length(), minLen - prefix.length(), true) + .stream() + .map(x -> Component.text(prefix).append(x)) + .toList(); + } - String temp; - if (first) { - temp = cur + Utils.hashColor(entry); - } else { - temp = cur + " " + Utils.hashColor(entry); - } - first = false; + private List renderItemLore(boolean isPlaceholder) { + List lore = new ArrayList<>(); - if (ChatColor.stripColor(temp).length() <= maxLen) { - cur = temp; - } else { - ret.add(cur); - cur = prefix + Utils.hashColor(entry); - } + final var id = mNBT.getString("id"); + lore.add(Component.text("Type: " + (id.startsWith("minecraft:") ? id.substring(10) : id)).color(NamedTextColor.WHITE)); + lore.add(Component.text("Health: " + mNBT.getDouble("Health")).color(NamedTextColor.WHITE)); + + NBTTagList tags = mNBT.getList("Tags"); + if (tags != null && tags.size() > 0) { + lore.add(Component.text("Tags:").color(NamedTextColor.WHITE)); + lore.addAll(stringifyWrapList(" ", 50, 30, tags.getAsArray())); + } + + if (mLocs != null && !mLocs.isEmpty()) { + lore.add(Component.text("Locations:").color(NamedTextColor.WHITE)); + lore.addAll(stringifyWrapList(" ", 50, 30, mLocs.toArray())); } - ret.add(cur); + if (mLore != null && !mLore.isEmpty()) { + lore.add(Component.text("Lore:").color(NamedTextColor.WHITE)); + lore.add(Component.text("It exists.")); + } - return ret; + if (mDescription != null && !mDescription.isEmpty()) { + lore.add(Component.text("Description:").color(NamedTextColor.WHITE)); + lore.add(Component.text("It exists.")); + } + + /* If the item has been modified, list when */ + if (mModifiedBy != null && !mModifiedBy.isEmpty()) { + if (isPlaceholder) { + lore.add(Component.text("Modified " + getTimeDeltaStr()).color(NamedTextColor.AQUA)); + } + /* Actual time on the picked-up item */ + LocalDateTime modTime = LocalDateTime.ofEpochSecond(mModifiedOn, 0, ZoneOffset.UTC); + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + lore.add(Component.text("Modified " + modTime.format(fmt) + " by " + mModifiedBy).color(NamedTextColor.AQUA)); + } + + return Lists.transform(lore, x -> x.decoration(TextDecoration.ITALIC, false)); } private void regenerateItems() { @@ -360,11 +389,7 @@ private void regenerateItems() { ex.printStackTrace(); mPlaceholder = new ItemStack(Material.BARRIER); - mPlaceholder = mPlaceholder.ensureServerConversions(); - ItemStackNBTWrapper placeholderWrap = new ItemStackNBTWrapper(mPlaceholder); - placeholderWrap.getVariable("Name").set("FAILED TO LOAD: " + getDisplayName(), null); - placeholderWrap.save(); - + mPlaceholder.editMeta(itemMeta -> itemMeta.displayName(Component.text("FAILED TO LOAD: ").append(getDisplayName()))); mBoS = mPlaceholder.clone(); return; } @@ -379,10 +404,9 @@ private void regenerateItems() { case CAMEL -> Material.SANDSTONE; case CAVE_SPIDER -> Material.FERMENTED_SPIDER_EYE; case CHICKEN -> Material.CHICKEN; - case COD -> Material.COD; + case COD, DOLPHIN -> Material.COD; case COW -> Material.BEEF; case CREEPER -> Material.CREEPER_HEAD; - case DOLPHIN -> Material.COD; case DROWNED -> Material.TRIDENT; case ELDER_GUARDIAN -> Material.SPONGE; case ENDERMAN -> Material.ENDER_PEARL; @@ -402,7 +426,7 @@ private void regenerateItems() { case ZOGLIN -> Material.CRIMSON_FUNGUS; case HORSE -> Material.SADDLE; case HUSK -> Material.ROTTEN_FLESH; - case ILLUSIONER -> Material.BOW; + case ILLUSIONER, STRAY -> Material.BOW; case IRON_GOLEM -> Material.IRON_BLOCK; case MAGMA_CUBE -> Material.MAGMA_CREAM; case MUSHROOM_COW -> Material.RED_MUSHROOM; @@ -430,7 +454,6 @@ private void regenerateItems() { case SNIFFER -> Material.TORCHFLOWER; case SNOWMAN -> Material.CARVED_PUMPKIN; case SPIDER -> Material.SPIDER_EYE; - case STRAY -> Material.BOW; case STRIDER -> Material.WARPED_FUNGUS_ON_A_STICK; case SQUID -> Material.INK_SAC; case TADPOLE -> Material.FROGSPAWN; @@ -456,102 +479,19 @@ private void regenerateItems() { mPlaceholder = new ItemStack(material); } - mPlaceholder = mPlaceholder.ensureServerConversions(); - ItemMeta placeholderMeta = mPlaceholder.getItemMeta(); - placeholderMeta.displayName(Component.text("")); - placeholderMeta.lore(List.of()); - mPlaceholder.setItemMeta(placeholderMeta); - mPlaceholder.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_ENCHANTS); - - mBoS = mBoS.ensureServerConversions(); - ItemMeta bosMeta = mBoS.getItemMeta(); - bosMeta.displayName(Component.text("")); - bosMeta.lore(List.of()); - mBoS.setItemMeta(bosMeta); - - ItemStackNBTWrapper placeholderWrap = new ItemStackNBTWrapper(mPlaceholder); - ItemStackNBTWrapper bosWrap = new ItemStackNBTWrapper(mBoS); - - /* Set the item's display name (recolored, does not exactly match actual mob name) */ - String serializedDisplayName = GsonComponentSerializer.gson().serialize(getDisplayName()); - placeholderWrap.getVariable("Name").set(serializedDisplayName, null); - bosWrap.getVariable("Name").set(serializedDisplayName, null); - - /* Set hide flags to hide the BoS author info */ - placeholderWrap.getVariable("HideFlags").set("32", null); - bosWrap.getVariable("HideFlags").set("32", null); - - String idStr = ChatColor.WHITE + "Type: "; - if (mNBT.getString("id").startsWith("minecraft:")) { - idStr += mNBT.getString("id").substring(10); - } else { - idStr += mNBT.getString("id"); - } - ((ListVariable)placeholderWrap.getVariable("Lore")).add(idStr, null); - ((ListVariable)bosWrap.getVariable("Lore")).add(idStr, null); - - if (mNBT.hasKey("Health")) { - String healthStr = ChatColor.WHITE + "Health: " + Double.toString(mNBT.getDouble("Health")); - ((ListVariable)placeholderWrap.getVariable("Lore")).add(healthStr, null); - ((ListVariable)bosWrap.getVariable("Lore")).add(healthStr, null); - } - - NBTTagList tags = mNBT.getList("Tags"); - if (tags != null && tags.size() > 0) { - ((ListVariable)placeholderWrap.getVariable("Lore")).add(ChatColor.WHITE + "Tags:", null); - ((ListVariable)bosWrap.getVariable("Lore")).add(ChatColor.WHITE + "Tags:", null); - - int index = 0; - for (String str : stringifyWrapList(" ", 50, tags.getAsArray())) { - index = 0; - while (str.length() - index >= 40) { - ((ListVariable)placeholderWrap.getVariable("Lore")).add(str.substring(index, index + 40), null); - ((ListVariable)bosWrap.getVariable("Lore")).add(str.substring(index, index + 40), null); - index += 40; - } - - ((ListVariable)placeholderWrap.getVariable("Lore")).add(str.substring(index), null); - ((ListVariable)bosWrap.getVariable("Lore")).add(str.substring(index), null); - } - } - - if (mLocs != null && mLocs.size() > 0) { - ((ListVariable)placeholderWrap.getVariable("Lore")).add(ChatColor.WHITE + "Locations:", null); - ((ListVariable)bosWrap.getVariable("Lore")).add(ChatColor.WHITE + "Locations:", null); + mPlaceholder.editMeta(itemMeta -> { + itemMeta.displayName(getDisplayName()); + itemMeta.lore(renderItemLore(true)); + }); - for (String str : stringifyWrapList(" ", 45, mLocs.toArray())) { - ((ListVariable)placeholderWrap.getVariable("Lore")).add(str, null); - ((ListVariable)bosWrap.getVariable("Lore")).add(str, null); - } - } - - if (mLore != null && !mLore.isEmpty()) { - ((ListVariable)placeholderWrap.getVariable("Lore")).add(ChatColor.WHITE + "Lore:", null); - ((ListVariable)bosWrap.getVariable("Lore")).add(ChatColor.WHITE + "Lore:", null); - //Rather than a giant block of text, two words suffice. - ((ListVariable)placeholderWrap.getVariable("Lore")).add("It exists.", null); - } - - if (mDescription != null && !mDescription.isEmpty()) { - ((ListVariable)placeholderWrap.getVariable("Lore")).add(ChatColor.WHITE + "Description:", null); - ((ListVariable)bosWrap.getVariable("Lore")).add(ChatColor.WHITE + "Description:", null); - // Rather than a giant block of text, two words suffice. - ((ListVariable)placeholderWrap.getVariable("Lore")).add("It exists.", null); - } + mPlaceholder.addItemFlags(ItemFlag.HIDE_ITEM_SPECIFICS); - /* If the item has been modified, list when */ - if (mModifiedBy != null && !mModifiedBy.isEmpty()) { - /* Relative time on the placeholder item */ - ((ListVariable)placeholderWrap.getVariable("Lore")).add(ChatColor.AQUA + "Modified " + getTimeDeltaStr() + " by " + mModifiedBy, null); - - /* Actual time on the picked-up item */ - LocalDateTime modTime = LocalDateTime.ofEpochSecond(mModifiedOn, 0, ZoneOffset.UTC); - DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - ((ListVariable)bosWrap.getVariable("Lore")).add(ChatColor.AQUA + "Modified " + modTime.format(fmt) + " by " + mModifiedBy, null); - } + mBoS.editMeta(itemMeta -> { + itemMeta.displayName(getDisplayName()); + itemMeta.lore(renderItemLore(false)); + }); - placeholderWrap.save(); - bosWrap.save(); + mBoS.addItemFlags(ItemFlag.HIDE_ITEM_SPECIFICS); } private String getTimeDeltaStr() { @@ -559,25 +499,25 @@ private String getTimeDeltaStr() { if (deltaSeconds > 60 * 24 * 60 * 60) { /* More than 2 months - just print months */ - return Long.toString(deltaSeconds / (60 * 24 * 60 * 60)) + " months ago"; + return deltaSeconds / (60 * 24 * 60 * 60) + " months ago"; } else { String retStr = ""; long days = deltaSeconds / (24 * 60 * 60); if (days >= 1) { - retStr += Long.toString(days) + "d "; + retStr += days + "d "; } if (days < 7) { long hours = (deltaSeconds % (24 * 60 * 60)) / (60 * 60); if (hours >= 1) { - retStr += Long.toString(hours) + "h "; + retStr += hours + "h "; } if (days == 0) { long minutes = (deltaSeconds % (60 * 60)) / 60; if (minutes >= 1) { - retStr += Long.toString(minutes) + "m "; + retStr += minutes + "m "; } } } diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyEntry.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyEntry.java index 5355b5e..b467217 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyEntry.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyEntry.java @@ -35,7 +35,7 @@ public SoulPartyEntry(List history) throws Exception { public SoulPartyEntry(Player player, String label) { SoulPartyHistoryEntry newHist = new SoulPartyHistoryEntry(player, label); - mHistory = new ArrayList(1); + mHistory = new ArrayList<>(1); mHistory.add(newHist); } @@ -117,11 +117,11 @@ public List summonGroup(Random random, World world, BoundingBox spawnBb) *--------------------------------------------------------------------------------*/ public List getHistory() { - return new ArrayList(mHistory); + return new ArrayList<>(mHistory); } public static SoulPartyEntry fromJson(JsonObject obj, boolean loadHistory) throws Exception { - List history = new ArrayList(); + List history = new ArrayList<>(); JsonArray array = obj.getAsJsonArray("history"); if (array == null) { throw new Exception("Failed to parse history as JSON array"); @@ -130,16 +130,16 @@ public static SoulPartyEntry fromJson(JsonObject obj, boolean loadHistory) throw if (loadHistory) { for (JsonElement historyElement : array) { if (!historyElement.isJsonObject()) { - throw new Exception("history entry for '" + history.toString() + "' is not an object!"); + throw new Exception("history entry for '" + history + "' is not an object!"); } history.add(SoulPartyHistoryEntry.fromJson(historyElement.getAsJsonObject())); } } else { - if (array.size() >= 1) { + if (!array.isEmpty()) { JsonElement historyElement = array.get(0); if (!historyElement.isJsonObject()) { - throw new Exception("history entry for '" + history.toString() + "' is not an object!"); + throw new Exception("history entry for '" + history + "' is not an object!"); } history.add(SoulPartyHistoryEntry.fromJson(historyElement.getAsJsonObject())); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyHistoryEntry.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyHistoryEntry.java index 99d0eaf..ece40ac 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyHistoryEntry.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulPartyHistoryEntry.java @@ -37,7 +37,7 @@ public SoulPartyHistoryEntry(String label, long modifiedOn, String modifiedBy, M /* Create a new SoulPartyHistoryEntry object with a label */ public SoulPartyHistoryEntry(Player player, String label) { - this(label, Instant.now().getEpochSecond(), player.getName(), new HashMap()); + this(label, Instant.now().getEpochSecond(), player.getName(), new HashMap<>()); } /* Create a new SoulPartyHistoryEntry object with modified counts */ @@ -62,7 +62,7 @@ public SoulPartyHistoryEntry changeCount(Player player, String entryLabel, int c } public Map getEntryCounts() { - return new HashMap(mEntryCounts); + return new HashMap<>(mEntryCounts); } /*-------------------------------------------------------------------------------- diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolEntry.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolEntry.java index 4369481..6fd20c6 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolEntry.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolEntry.java @@ -35,7 +35,7 @@ public SoulPoolEntry(List history) throws Exception { public SoulPoolEntry(Player player, String label) { SoulPoolHistoryEntry newHist = new SoulPoolHistoryEntry(player, label); - mHistory = new ArrayList(1); + mHistory = new ArrayList<>(1); mHistory.add(newHist); } @@ -117,11 +117,11 @@ public List summonGroup(Random random, World world, BoundingBox spawnBb) *--------------------------------------------------------------------------------*/ public List getHistory() { - return new ArrayList(mHistory); + return new ArrayList<>(mHistory); } public static SoulPoolEntry fromJson(JsonObject obj, boolean loadHistory) throws Exception { - List history = new ArrayList(); + List history = new ArrayList<>(); JsonArray array = obj.getAsJsonArray("history"); if (array == null) { throw new Exception("Failed to parse history as JSON array"); @@ -130,16 +130,16 @@ public static SoulPoolEntry fromJson(JsonObject obj, boolean loadHistory) throws if (loadHistory) { for (JsonElement historyElement : array) { if (!historyElement.isJsonObject()) { - throw new Exception("history entry for '" + history.toString() + "' is not an object!"); + throw new Exception("history entry for '" + history + "' is not an object!"); } history.add(SoulPoolHistoryEntry.fromJson(historyElement.getAsJsonObject())); } } else { - if (array.size() >= 1) { + if (!array.isEmpty()) { JsonElement historyElement = array.get(0); if (!historyElement.isJsonObject()) { - throw new Exception("history entry for '" + history.toString() + "' is not an object!"); + throw new Exception("history entry for '" + history + "' is not an object!"); } history.add(SoulPoolHistoryEntry.fromJson(historyElement.getAsJsonObject())); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolHistoryEntry.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolHistoryEntry.java index 582580b..eea344e 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolHistoryEntry.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulPoolHistoryEntry.java @@ -52,7 +52,7 @@ public SoulPoolHistoryEntry(String label, long modifiedOn, String modifiedBy, Ma /* Create a new SoulPoolHistoryEntry object with a label */ public SoulPoolHistoryEntry(Player player, String label) { - this(label, Instant.now().getEpochSecond(), player.getName(), new HashMap()); + this(label, Instant.now().getEpochSecond(), player.getName(), new HashMap<>()); } /* Create a new SoulPoolHistoryEntry object with modified weights */ @@ -77,7 +77,7 @@ public SoulPoolHistoryEntry changeWeight(Player player, String entryLabel, int w } public Map getEntryWeights() { - return new HashMap(mEntryWeights); + return new HashMap<>(mEntryWeights); } /*-------------------------------------------------------------------------------- @@ -132,7 +132,7 @@ public Set getPossibleSoulGroupLabels() { @Override public Map getRandomEntries(Random random) { if (mTotalWeight == 0) { - return new HashMap(); + return new HashMap<>(); } int randomValue = random.nextInt(mTotalWeight); String selectedLabel = mNavigableMap.higherEntry(randomValue).getValue(); @@ -162,7 +162,7 @@ public Map getAverageEntries() { @Override public Map getRandomSouls(Random random) { if (mTotalWeight == 0) { - return new HashMap(); + return new HashMap<>(); } int randomValue = random.nextInt(mTotalWeight); String selectedLabel = mNavigableMap.higherEntry(randomValue).getValue(); @@ -170,7 +170,7 @@ public Map getRandomSouls(Random random) { if (selected != null) { return selected.getRandomSouls(random); } else { - return new HashMap(); + return new HashMap<>(); } } diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulsDatabase.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulsDatabase.java index 645b6d5..e5588e3 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulsDatabase.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulsDatabase.java @@ -9,6 +9,8 @@ import com.google.gson.JsonObject; import com.playmonumenta.libraryofsouls.utils.FileUtils; import com.playmonumenta.libraryofsouls.utils.Utils; +import com.playmonumenta.mixinapi.v1.DataFix; +import de.tr7zw.nbtapi.NBTContainer; import dev.jorel.commandapi.CommandAPI; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import java.nio.file.Files; @@ -20,13 +22,14 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -34,6 +37,10 @@ import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.Nullable; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; + public class SoulsDatabase { private static final String SOULS_DATABASE_FILE = "souls_database.json"; private static final String SOUL_PARTIES_DATABASE_FILE = "soul_parties_database.json"; @@ -41,12 +48,7 @@ public class SoulsDatabase { private static @Nullable SoulsDatabase INSTANCE = null; - private static final Comparator COMPARATOR = new Comparator() { - @Override - public int compare(String e1, String e2) { - return e1.toLowerCase().compareTo(e2.toLowerCase()); - } - }; + private static final Comparator COMPARATOR = String::compareToIgnoreCase; private final Plugin mPlugin; private final boolean mLoadHistory; @@ -57,7 +59,7 @@ public int compare(String e1, String e2) { private boolean mIgnoreNextChange = false; /* This is the primary database. One name, one SoulEntry per mob */ - private Map mSouls = new TreeMap(COMPARATOR); + private Map mSouls = new TreeMap<>(COMPARATOR); /* These are secondary databases for pools/parties of mobs */ private Map mSoulParties = new TreeMap<>(COMPARATOR); @@ -120,10 +122,10 @@ public void run() { try { soulEntry.autoUpdate(loc); } catch (Exception ex) { - sender.sendMessage(ChatColor.RED + "Failed to auto-update " + name + ": " + ex.getMessage()); + sender.sendMessage(text("Failed to auto-update " + name + ": " + ex.getMessage(), RED)); } } else { - sender.sendMessage(ChatColor.GRAY + "Auto-update done."); + sender.sendMessage(text("Auto-update done.", NamedTextColor.GRAY)); cancel(); } } @@ -143,7 +145,7 @@ public void run() { } public List getSouls() { - List souls = new ArrayList(mSouls.size()); + List souls = new ArrayList<>(mSouls.size()); souls.addAll(mSouls.values()); return souls; } @@ -153,7 +155,7 @@ public List getSouls() { return null; } - return (SoulEntry)mSouls.values().toArray()[index]; + return (SoulEntry) mSouls.values().toArray()[index]; } public @Nullable SoulEntry getSoul(String name) { @@ -161,7 +163,7 @@ public List getSouls() { } public List getSoulParties() { - List soulParties = new ArrayList(mSoulParties.size()); + List soulParties = new ArrayList<>(mSoulParties.size()); soulParties.addAll(mSoulParties.values()); return soulParties; } @@ -171,7 +173,7 @@ public List getSoulParties() { return null; } - return (SoulPartyEntry)mSoulParties.values().toArray()[index]; + return (SoulPartyEntry) mSoulParties.values().toArray()[index]; } public @Nullable SoulPartyEntry getSoulParty(String label) { @@ -179,7 +181,7 @@ public List getSoulParties() { } public List getSoulPools() { - List soulPools = new ArrayList(mSoulPools.size()); + List soulPools = new ArrayList<>(mSoulPools.size()); soulPools.addAll(mSoulPools.values()); return soulPools; } @@ -189,7 +191,7 @@ public List getSoulPools() { return null; } - return (SoulPoolEntry)mSoulPools.values().toArray()[index]; + return (SoulPoolEntry) mSoulPools.values().toArray()[index]; } public @Nullable SoulPoolEntry getSoulPool(String label) { @@ -219,18 +221,18 @@ public void add(Player sender, BookOfSouls bos) { String label = Utils.getLabelFromName(name); if (mSouls.containsKey(label)) { - sender.sendMessage(ChatColor.RED + "Mob '" + label + "' already exists!"); + sender.sendMessage(text("Mob '" + label + "' already exists!", RED)); return; } soul = new SoulEntry(sender, nbt); } catch (Exception ex) { - sender.sendMessage(ChatColor.RED + "Error parsing BoS: " + ex.getMessage()); + sender.sendMessage(text("Error parsing BoS: " + ex.getMessage(), RED)); return; } mSouls.put(soul.getLabel(), soul); - sender.sendMessage(ChatColor.GREEN + "Added " + soul.getLabel()); + sender.sendMessage(text("Added " + soul.getLabel(), GREEN)); updateIndex(); save(); } @@ -245,22 +247,23 @@ public void update(Player sender, BookOfSouls bos) { soul = mSouls.get(label); if (soul == null) { - sender.sendMessage(ChatColor.RED + "Mob '" + label + "' does not exist!"); + sender.sendMessage(text("Mob '" + label + "' does not exist!", RED)); return; } soul.update(sender, nbt); } catch (Exception ex) { - sender.sendMessage(ChatColor.RED + "Error parsing BoS: " + ex.getMessage()); + sender.sendMessage(text("Error parsing BoS: " + ex.getMessage(), RED)); return; } - sender.sendMessage(ChatColor.GREEN + "Updated " + soul.getLabel()); + sender.sendMessage(text("Updated " + soul.getLabel(), GREEN)); updateIndex(); save(); } - // This function is only called in updateLore, where by definition the soul exists - also the bos doesnt change internally, only on the outside but maybe that needs to happen? + // This function is only called in updateLore, where by definition the soul exists - also the bos doesnt change + // internally, only on the outside but maybe that needs to happen? public void updateLore(SoulEntry soul, Player sender) { try { soul.update(sender, soul.getNBT()); @@ -272,10 +275,10 @@ public void updateLore(SoulEntry soul, Player sender) { public void del(CommandSender sender, String name) { if (!mSouls.containsKey(name)) { - sender.sendMessage(ChatColor.RED + "Mob '" + name + "' does not exist!"); + sender.sendMessage(text("Mob '" + name + "' does not exist!", RED)); } else { mSouls.remove(name); - sender.sendMessage(ChatColor.GREEN + "Removed " + name); + sender.sendMessage(text("Removed " + name, GREEN)); updateIndex(); save(); } @@ -285,7 +288,7 @@ public void addParty(Player player, String label) { SoulPartyEntry soulParty = new SoulPartyEntry(player, label); mSoulParties.put(soulParty.getLabel(), soulParty); - player.sendMessage(ChatColor.GREEN + "Added " + soulParty.getLabel()); + player.sendMessage(text("Added " + soulParty.getLabel(), GREEN)); save(); } @@ -301,16 +304,16 @@ public void updateParty(Player player, String label, String entryLabel, int coun } soulParty.update(player, entryLabel, count); - player.sendMessage(ChatColor.GREEN + "Updated " + soulParty.getLabel()); + player.sendMessage(text("Updated " + soulParty.getLabel(), GREEN)); save(); } public void delParty(CommandSender player, String label) { if (!mSoulParties.containsKey(label)) { - player.sendMessage(ChatColor.RED + "Soul party '" + label + "' does not exist!"); + player.sendMessage(text("Soul party '" + label + "' does not exist!", RED)); } else { mSoulParties.remove(label); - player.sendMessage(ChatColor.GREEN + "Removed " + label); + player.sendMessage(text("Removed " + label, GREEN)); save(); } } @@ -319,7 +322,7 @@ public void addPool(Player player, String label) { SoulPoolEntry soulPool = new SoulPoolEntry(player, label); mSoulPools.put(soulPool.getLabel(), soulPool); - player.sendMessage(ChatColor.GREEN + "Added " + soulPool.getLabel()); + player.sendMessage(text("Added " + soulPool.getLabel(), GREEN)); save(); } @@ -335,20 +338,78 @@ public void updatePool(Player player, String label, String entryLabel, int weigh } soulPool.update(player, entryLabel, weight); - player.sendMessage(ChatColor.GREEN + "Updated " + soulPool.getLabel()); + player.sendMessage(text("Updated " + soulPool.getLabel(), GREEN)); save(); } public void delPool(CommandSender player, String label) { if (!mSoulPools.containsKey(label)) { - player.sendMessage(ChatColor.RED + "Soul Pool '" + label + "' does not exist!"); + player.sendMessage(text("Soul Pool '" + label + "' does not exist!", GREEN)); } else { mSoulPools.remove(label); - player.sendMessage(ChatColor.GREEN + "Removed " + label); + player.sendMessage(text("Removed " + label, GREEN)); save(); } } + private JsonArray readSouls(Gson gson, String content) { + JsonElement soulsArray = gson.fromJson(content, JsonElement.class); + + final JsonArray souls; + int dataVersion = 3337; + if (soulsArray instanceof JsonObject object) { + if (object.has("data_version")) { + dataVersion = object.get("data_version").getAsInt(); + } + + souls = object.getAsJsonArray("souls"); + } else { + mPlugin.getLogger().info("Database is in legacy format, assuming data version: " + dataVersion); + souls = (JsonArray) soulsArray; + } + + try { + Class.forName("com.playmonumenta.mixinapi.v1.DataFix"); + final var latestVersion = DataFix.getInstance().currentDataVersion(); + if (dataVersion < latestVersion) { + mPlugin.getLogger().info("Performing datafix..."); + int entries = 0; + for (JsonElement soul : souls) { + for (JsonElement h : soul.getAsJsonObject().get("history").getAsJsonArray()) { + entries++; + final var history = h.getAsJsonObject(); + final var result = DataFix.getInstance().dataFix( + new NBTContainer(history.get("mojangson").getAsString()), + DataFix.Types.ENTITY, dataVersion, latestVersion + ); + history.addProperty("mojangson", result.toString()); + } + } + mPlugin.getLogger().info("Datafixed " + entries + " entries"); + } + } catch (ClassNotFoundException e) { + mPlugin.getLogger().info("Monumenta mixin DFU api not found, skipping auto upgrade!"); + } + + return souls; + } + + private String writeSouls(JsonArray soulArray, Gson gson) { + final var object = new JsonObject(); + object.add("souls", soulArray); + + try { + Class.forName("com.playmonumenta.mixinapi.v1.DataFix"); + final var dfuVersion = DataFix.getInstance().currentDataVersion(); + mPlugin.getLogger().info("Writing souls with DFU version: " + dfuVersion); + object.addProperty("data_version", dfuVersion); + } catch (ClassNotFoundException e) { + mPlugin.getLogger().info("Monumenta mixin DFU api not found, skipping auto upgrade!"); + } + + return gson.toJson(object); + } + public void reloadAsync() throws Exception { mPlugin.getLogger().info("Reloading souls library..."); Map newSouls = new TreeMap<>(COMPARATOR); @@ -356,18 +417,18 @@ public void reloadAsync() throws Exception { Map newSoulPools = new TreeMap<>(COMPARATOR); String content = FileUtils.readFile(mSoulsDatabasePath.toString()); - if (content == null || content.isEmpty()) { + if (content.isEmpty()) { throw new Exception("Failed to read souls database"); } Gson gson = new Gson(); - JsonArray soulsArray = gson.fromJson(content, JsonArray.class); + JsonArray soulsArray = readSouls(gson, content); if (soulsArray == null) { throw new Exception("Failed to parse souls database as JSON array"); } content = FileUtils.readFile(mSoulPartiesDatabasePath.toString()); - if (content == null || content.isEmpty()) { + if (content.isEmpty()) { throw new Exception("Failed to read soul parties database"); } @@ -377,7 +438,7 @@ public void reloadAsync() throws Exception { } content = FileUtils.readFile(mSoulPoolsDatabasePath.toString()); - if (content == null || content.isEmpty()) { + if (content.isEmpty()) { throw new Exception("Failed to read soul parties database"); } @@ -459,9 +520,9 @@ public void reloadAsync() throws Exception { LibraryOfSouls.Config.load(mPlugin.getLogger(), mPlugin.getDataFolder(), true); mPlugin.getLogger().info("Finished parsing souls library"); - mPlugin.getLogger().info("Loaded " + Integer.toString(finalSoulCount) + " mob souls"); - mPlugin.getLogger().info("Loaded " + Integer.toString(finalSoulPartyCount) + " mob soul parties"); - mPlugin.getLogger().info("Loaded " + Integer.toString(finalSoulPoolCount) + " mob soul pools"); + mPlugin.getLogger().info("Loaded " + finalSoulCount + " mob souls"); + mPlugin.getLogger().info("Loaded " + finalSoulPartyCount + " mob soul parties"); + mPlugin.getLogger().info("Loaded " + finalSoulPoolCount + " mob soul pools"); }); } @@ -480,22 +541,14 @@ private void updateIndex() { mNoLocMobs.add(soul); } else { for (String tag : locs) { - List lst = mLocsIndex.get(tag); - if (lst == null) { - lst = new ArrayList(); - mLocsIndex.put(tag, lst); - } + List lst = mLocsIndex.computeIfAbsent(tag, k -> new ArrayList<>()); lst.add(soul); } } /* Update type index */ - String id = soul.getId().getKey().toLowerCase(); - List lst = mTypesIndex.get(id); - if (lst == null) { - lst = new ArrayList(); - mTypesIndex.put(id, lst); - } + String id = soul.getId().getKey().toLowerCase(Locale.ROOT); + List lst = mTypesIndex.computeIfAbsent(id, k -> new ArrayList<>()); lst.add(soul); } } @@ -524,7 +577,7 @@ private void save() { String soulPoolsDatabasePath = mSoulPoolsDatabasePath.toString(); try { - FileUtils.writeFile(soulsDatabasePath, gson.toJson(soulArray)); + FileUtils.writeFile(soulsDatabasePath, writeSouls(soulArray, gson)); } catch (Exception ex) { mPlugin.getLogger().severe("Failed to save souls database to '" + soulsDatabasePath + "': " + ex.getMessage()); } @@ -562,7 +615,7 @@ public Set listSoulPoolNames() { } public Set listSoulGroupNames() { - Set result = new HashSet(mSouls.keySet()); + Set result = new HashSet<>(mSouls.keySet()); result.addAll(mSoulParties.keySet()); result.addAll(mSoulPools.keySet()); return result; diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SoulsInventory.java b/src/main/java/com/playmonumenta/libraryofsouls/SoulsInventory.java index 3433d55..ce049bb 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SoulsInventory.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SoulsInventory.java @@ -48,7 +48,7 @@ private void loadWindow() { } if (mOffset > 0) { - _inventory.setItem(45, UtilsMc.newSingleItemStack(Material.ARROW, "[" + Integer.toString(mOffset / 36) + "] Previous Page")); + _inventory.setItem(45, UtilsMc.newSingleItemStack(Material.ARROW, "[" + mOffset / 36 + "] Previous Page")); mHasPrevPage = true; } else { mHasPrevPage = false; @@ -56,7 +56,7 @@ private void loadWindow() { } if (mCurrentSlots.size() >= 36) { - _inventory.setItem(53, UtilsMc.newSingleItemStack(Material.ARROW, "[" + Integer.toString(mOffset / 36) + "] Next Page")); + _inventory.setItem(53, UtilsMc.newSingleItemStack(Material.ARROW, "[" + mOffset / 36 + "] Next Page")); mHasNextPage = true; } else { mHasNextPage = false; @@ -67,9 +67,10 @@ private void loadWindow() { @Override protected void inventoryClick(final InventoryClickEvent event) { if (event.getClickedInventory() == null) { - // Player clicked off the screen return; - } else if ((event.getCursor().getType() != Material.AIR && event.getClickedInventory().equals(getInventory())) + } + // Player clicked off the screen + if ((event.getCursor().getType() != Material.AIR && event.getClickedInventory().equals(getInventory())) || (event.isShiftClick() && !event.getClickedInventory().equals(getInventory()))) { // Attempted to place something in the souls inventory event.setCancelled(true); @@ -79,12 +80,7 @@ protected void inventoryClick(final InventoryClickEvent event) { if (slot >= 0 && slot < 36 && mCurrentSlots.size() > slot) { if (event.isShiftClick()) { event.setCurrentItem(mCurrentSlots.get(slot).getBoS()); - Bukkit.getScheduler().runTask(getPlugin(), new Runnable() { - @Override - public void run() { - event.setCurrentItem(mCurrentSlots.get(slot).getPlaceholder()); - } - }); + Bukkit.getScheduler().runTask(getPlugin(), () -> event.setCurrentItem(mCurrentSlots.get(slot).getPlaceholder())); } else if (event.isRightClick()) { event.setCancelled(true); SpawnerInventory.openSpawnerInventory(mCurrentSlots.get(slot), (Player)event.getWhoClicked(), this); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/SpawnerInventory.java b/src/main/java/com/playmonumenta/libraryofsouls/SpawnerInventory.java index c8f4d17..e1e84a0 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/SpawnerInventory.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/SpawnerInventory.java @@ -6,12 +6,12 @@ import com.goncalomb.bukkit.nbteditor.nbt.SpawnerNBTWrapper; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; @@ -75,9 +75,11 @@ private ItemStack changeActivationRange(ItemStack spawnerItem, int range) { @Override protected void inventoryClick(InventoryClickEvent event) { if (event.getClickedInventory() == null) { - // Player clicked off the screen return; - } else if (event.getClickedInventory().equals(getInventory()) && event.getSlot() == 0 && mGoBackInventory != null) { + // Player clicked off the screen + } + + if (event.getClickedInventory().equals(getInventory()) && event.getSlot() == 0 && mGoBackInventory != null) { event.setCancelled(true); Player player = (Player)event.getWhoClicked(); new SoulsInventory(mGoBackInventory, player).openInventory(player, LibraryOfSouls.getInstance()); @@ -94,7 +96,7 @@ public static void openSpawnerInventory(Soul soul, Player player, @Nullable Soul Block block = findSafeAirBlock(player.getLocation()); if (block == null) { - player.sendMessage(ChatColor.RED + "There is no nearby air block to construct the spawner"); + player.sendMessage(Component.text("There is no nearby air block to construct the spawner").color(NamedTextColor.RED)); player.playSound(player.getLocation(), Sound.ENTITY_SHULKER_HURT, 1, 1); return; } @@ -135,7 +137,7 @@ public static void openSpawnerInventory(Soul soul, Player player, @Nullable Soul ItemStack item = new ItemStack(Material.SPAWNER); BlockStateMeta meta = (BlockStateMeta)item.getItemMeta(); meta.setBlockState(spawnerBlock); - meta.displayName(soul.getDisplayName().append(Component.text(" " + nbt.getEntityType().toString().toLowerCase(), NamedTextColor.YELLOW).decoration(TextDecoration.ITALIC, false))); + meta.displayName(soul.getDisplayName().append(Component.text(" " + nbt.getEntityType().toString().toLowerCase(Locale.ROOT), NamedTextColor.YELLOW).decoration(TextDecoration.ITALIC, false))); item.setItemMeta(meta); // Update the item's lore/name @@ -160,7 +162,7 @@ public static void updateSpawnerItemDisplay(ItemStack item, CreatureSpawner spaw // Append the radius to the item name Component name = meta.displayName(); name = name.replaceText(TextReplacementConfig.builder().match(" r=").replacement(Component.empty()).build()); - name = name.append(Component.text(" r=" + Integer.toString(spawner.getRequiredPlayerRange())).color(NamedTextColor.GREEN)); + name = name.append(Component.text(" r=" + spawner.getRequiredPlayerRange()).color(NamedTextColor.GREEN)); meta.displayName(name); meta.lore(loreString); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryArea.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryArea.java index 62fa6c3..b615e00 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryArea.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryArea.java @@ -6,10 +6,7 @@ import com.playmonumenta.libraryofsouls.SoulEntry; import com.playmonumenta.libraryofsouls.SoulsDatabase; import com.playmonumenta.libraryofsouls.utils.Utils; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; +import java.util.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; @@ -51,7 +48,7 @@ public BestiaryArea(@Nullable BestiaryArea parent, String name, ConfigurationSec if (souls == null || souls.isEmpty()) { throw new Exception("Bestiary entry " + Utils.plainText(mName) + " specifies nonexistent location " + mLocation); } - mChildren = new ArrayList(souls); + mChildren = new ArrayList<>(souls); } else if (config.contains("children")) { mLocation = null; @@ -86,7 +83,7 @@ public BestiaryArea(@Nullable BestiaryArea parent, String name, ConfigurationSec if (config.contains("item")) { NBTTagCompound compound = NBTTagCompound.fromString(config.getString("item")); - compound.setByte("Count", (byte)1); + compound.setByte("Count", (byte) 1); mItem = NBTUtils.itemStackFromNBTData(compound); if (mItem == null || mItem.getType().isAir()) { throw new Exception("Item for " + Utils.plainText(mName) + " failed to parse, was: " + config.getString("item")); @@ -100,13 +97,13 @@ public BestiaryArea(@Nullable BestiaryArea parent, String name, ConfigurationSec if (config.contains("subtitle")) { Component subtitle = Utils.parseMiniMessage(config.getString("subtitle")); - meta.lore(Arrays.asList(subtitle)); + meta.lore(List.of(subtitle)); } // Hide weapon damage, book enchants, and potion effects: meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); meta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); + meta.addItemFlags(ItemFlag.HIDE_ITEM_SPECIFICS); mItem.setItemMeta(meta); } diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryAreaInventory.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryAreaInventory.java index 329bd28..7ab495c 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryAreaInventory.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryAreaInventory.java @@ -50,6 +50,7 @@ public class BestiaryAreaInventory extends CustomInventory { private final BestiaryArea mArea; private final List mChildren; + @SuppressWarnings("deprecation") public BestiaryAreaInventory(Player player, BestiaryArea area, int offset) { super(player, 54, ChatColor.BLACK + "Bestiary: " + Utils.plainText(area.getName())); mOffset = offset; @@ -70,8 +71,7 @@ public BestiaryAreaInventory(Player player, BestiaryArea area, int offset) { if (i < mChildren.size() + offsetOffset) { BestiaryEntryInterface entry = mChildren.get(i - offsetOffset); ItemStack item = entry.getBestiaryItem(player).clone(); - if (entry instanceof BestiaryArea) { - BestiaryArea progressArea = (BestiaryArea)entry; + if (entry instanceof BestiaryArea progressArea) { double total = getTotal(progressArea); double discovered = totalDiscovered(progressArea, player, progressArea); int bars = (int)Math.floor((discovered / total) * 20); @@ -182,16 +182,10 @@ public int accountForOffset(int slot) { //Workaround because it needs what the previous entry was to smash a bug public double totalDiscovered(BestiaryEntryInterface entry, Player player, BestiaryEntryInterface lastChecked) { - if (entry instanceof SoulEntry) { - SoulEntry soul = (SoulEntry)entry; + if (entry instanceof SoulEntry soul) { double kills = BestiaryManager.getKillsForMob(player, soul); - if ((kills >= 1 || soul.isInvulnerable()) && lastChecked.canOpenBestiary(player)) { - return 1; - } else { - return 0; - } - } else if (entry instanceof BestiaryArea) { - BestiaryArea area = (BestiaryArea)entry; + return (kills >= 1 || soul.isInvulnerable()) && lastChecked.canOpenBestiary(player) ? 1 : 0; + } else if (entry instanceof BestiaryArea area) { double discovered = 0; List children = area.getBestiaryChildren(); for (BestiaryEntryInterface face : children) { diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryCommand.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryCommand.java index b73b81f..055a5b5 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryCommand.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryCommand.java @@ -38,7 +38,7 @@ public static void register() { .withArguments(playerArg) .withArguments(LibraryOfSoulsCommand.mobLabelArg) .executes((sender, args) -> { - int kills = 0; + int kills; SoulEntry soul = LibraryOfSoulsCommand.getSoul(args.getByArgument(LibraryOfSoulsCommand.mobLabelArg)); Player player = args.getByArgument(playerArg); try { @@ -66,7 +66,7 @@ public static void register() { .withArguments(LibraryOfSoulsCommand.mobLabelArg) .withArguments(amountArg) .executes((sender, args) -> { - int kills = 0; + int kills; try { kills = BestiaryManager.addKillsToMob(args.getByArgument(playerArg), LibraryOfSoulsCommand.getSoul(args.getByArgument(LibraryOfSoulsCommand.mobLabelArg)), args.getByArgument(amountArg)); } catch (Exception ex) { @@ -213,7 +213,7 @@ public static void registerWriteAccessCommands() { .withPermission(CommandPermission.fromString("los.bestiary.lore")) .executesPlayer((sender, args) -> { ItemStack item = sender.getInventory().getItemInMainHand(); - if (item == null || !item.getItemMeta().hasLore()) { + if (!item.getItemMeta().hasLore()) { throw CommandAPI.failWithString("You need a valid item with lore text!"); } List lore = item.lore(); @@ -270,7 +270,7 @@ public static void registerWriteAccessCommands() { .withPermission(CommandPermission.fromString("los.bestiary.description")) .executesPlayer((sender, args) -> { ItemStack item = sender.getInventory().getItemInMainHand(); - if (item == null || !item.getItemMeta().hasLore()) { + if (!item.getItemMeta().hasLore()) { throw CommandAPI.failWithString("You need a valid item with lore text!"); } List lore = item.lore(); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryManager.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryManager.java index beaa13e..57c0206 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryManager.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiaryManager.java @@ -6,14 +6,7 @@ import com.playmonumenta.libraryofsouls.bestiary.storage.BestiaryScoreboardStorage; import com.playmonumenta.libraryofsouls.bestiary.storage.BestiaryStorage; import com.playmonumenta.libraryofsouls.utils.Utils; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.logging.Logger; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; @@ -41,7 +34,8 @@ public class BestiaryManager implements Listener { * Entity UUID key, Player UUID Set * The size here is automatically managed by removing the oldest entries as the map fills up */ - private final Map> mDamageTracker = new LinkedHashMap>(MAX_BOSS_TRACK_ENTRIES + 1, .75F, true) { + private final Map> mDamageTracker = new LinkedHashMap<>(MAX_BOSS_TRACK_ENTRIES + 1, + .75F, true) { // This method is called just after a new entry has been added @Override public boolean removeEldestEntry(Map.Entry> eldest) { @@ -108,7 +102,7 @@ public static int addKillsToMob(Player player, SoulEntry soul, int amount) { public static void deleteAll(Player player) { List souls = SoulsDatabase.getInstance().getSouls(); for (SoulEntry soul : souls) { - BestiaryManager.setKillsForMob(player, soul, 0); + setKillsForMob(player, soul, 0); } } @@ -117,14 +111,14 @@ public void entityDamageByEntityEvent(EntityDamageByEntityEvent event) { Entity entity = event.getEntity(); Entity damager = event.getDamager(); if (entity instanceof LivingEntity && - !(entity instanceof Player) && damager instanceof Player) { + !(entity instanceof Player) && damager instanceof Player) { // Non-player living entity was damaged by player if (entity.customName() != null) { // Damaged entity had a non-empty name Set tags = entity.getScoreboardTags(); - if (tags != null && !tags.isEmpty() && tags.contains("Boss")) { + if (!tags.isEmpty() && tags.contains("Boss")) { // Damaged entity has the Boss tag // Keep track of all players that damage this mob @@ -145,63 +139,68 @@ public void entityDamageByEntityEvent(EntityDamageByEntityEvent event) { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void entityDeathEvent(EntityDeathEvent event) { - Entity entity = event.getEntity(); - if (entity instanceof LivingEntity) { - Component name = entity.customName(); - if (name != null) { - LivingEntity livingEntity = (LivingEntity)entity; - Player player = livingEntity.getKiller(); - if (player != null) { - // Player kills a mob - SoulsDatabase database = SoulsDatabase.getInstance(); - if (database != null) { + LivingEntity entity = event.getEntity(); + + Component name = entity.customName(); + if (name == null) { + return; + } + + Player player = entity.getKiller(); + if (player == null) { + return; + } + + // Player kills a mob + SoulsDatabase database = SoulsDatabase.getInstance(); + if (database == null) { + return; + } + + try { + String label = Utils.getLabelFromName(name); + SoulEntry soul = database.getSoul(label); + if (soul != null) { + // A soul entry exists for this mob + + // Check if this was a boss with multiple tracked damagers + Set damagers = mDamageTracker.remove(entity.getUniqueId()); + if (damagers != null) { + // A boss, record kill for everyone who damaged the mob (including the killer) + damagers.add(player.getUniqueId()); + damagers.stream().map(Bukkit::getPlayer).filter(Objects::nonNull).forEach((damager) -> { + try { + mStorage.recordKill(damager, soul); + } catch (Exception ex) { + mLogger.warning(ex.getMessage()); + } + }); + } else { + // Not a boss, record kill for the killer + try { + mStorage.recordKill(player, soul); + } catch (Exception ex) { + mLogger.warning(ex.getMessage()); + } + + // also check if any nearby player has not killed that mob before, and give them the kill + // good for both unlocking the entry in group play, and also to stop descriptions from showing up + // too many times + List otherPlayers = player.getWorld().getPlayers(); + otherPlayers.remove(player); + otherPlayers.removeIf(p -> p.getLocation().distanceSquared(player.getLocation()) > 20 * 20); + otherPlayers.removeIf(p -> getKillsForMob(p, soul) > 0); + for (Player p : otherPlayers) { try { - String label = Utils.getLabelFromName(name); - SoulEntry soul = database.getSoul(label); - if (soul != null) { - // A soul entry exists for this mob - - // Check if this was a boss with multiple tracked damagers - Set damagers = mDamageTracker.remove(entity.getUniqueId()); - if (damagers != null) { - // A boss, record kill for everyone who damaged the mob (including the killer) - damagers.add(player.getUniqueId()); - damagers.stream().map((damagerUUID) -> Bukkit.getPlayer(damagerUUID)).filter(Objects::nonNull).forEach((damager) -> { - try { - mStorage.recordKill(damager, soul); - } catch (Exception ex) { - mLogger.warning(ex.getMessage()); - } - }); - } else { - // Not a boss, record kill for the killer - try { - mStorage.recordKill(player, soul); - } catch (Exception ex) { - mLogger.warning(ex.getMessage()); - } - - // also check if any nearby player has not killed that mob before, and give them the kill - // good for both unlocking the entry in group play, and also to stop descriptions from showing up too many times - List otherPlayers = player.getWorld().getPlayers(); - otherPlayers.remove(player); - otherPlayers.removeIf(p -> p.getLocation().distanceSquared(player.getLocation()) > 20 * 20); - otherPlayers.removeIf(p -> getKillsForMob(p, soul) > 0); - for (Player p : otherPlayers) { - try { - mStorage.recordKill(p, soul); - } catch (Exception ex) { - mLogger.warning(ex.getMessage()); - } - } - } - } + mStorage.recordKill(p, soul); } catch (Exception ex) { mLogger.warning(ex.getMessage()); } } } } + } catch (Exception ex) { + mLogger.warning(ex.getMessage()); } } } diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulEquipmentInventory.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulEquipmentInventory.java index 61c8592..a3696d2 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulEquipmentInventory.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulEquipmentInventory.java @@ -71,7 +71,7 @@ public BestiarySoulEquipmentInventory(Player player, SoulEntry soul, BestiaryAre } for (int i = mSoulPeerIndex - 1; i >= 0; i--) { - if (mSoulPeers.get(i).canOpenBestiary(player) && ((SoulEntry)mSoulPeers.get(i)).getInfoTier(player) == SoulEntry.InfoTier.EVERYTHING && i >= 0) { + if (mSoulPeers.get(i).canOpenBestiary(player) && ((SoulEntry) mSoulPeers.get(i)).getInfoTier(player) == SoulEntry.InfoTier.EVERYTHING) { mPrevEntry = i; break; } diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulInventory.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulInventory.java index d2b370b..d85d29a 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulInventory.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/BestiarySoulInventory.java @@ -11,10 +11,7 @@ import com.goncalomb.bukkit.nbteditor.nbt.variables.NBTVariable; import com.playmonumenta.libraryofsouls.LibraryOfSouls; import com.playmonumenta.libraryofsouls.SoulEntry; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.Iterator; -import java.util.List; +import java.util.*; import java.util.logging.Level; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -42,11 +39,11 @@ import org.jetbrains.annotations.Nullable; public class BestiarySoulInventory extends CustomInventory { - private static EnumMap mDefaultArmor = new EnumMap<>(Material.class); - private static EnumMap mDefaultDamage = new EnumMap<>(EntityType.class); - private static EnumMap mDefaultSpeed = new EnumMap<>(EntityType.class); - private static EnumMap mDefaultItemDamage = new EnumMap<>(Material.class); - private static EnumMap mDefaultHealth = new EnumMap<>(EntityType.class); + private static final EnumMap DEFAULT_ARMOR = new EnumMap<>(Material.class); + private static final EnumMap DEFAULT_DAMAGE = new EnumMap<>(EntityType.class); + private static final EnumMap DEFAULT_SPEED = new EnumMap<>(EntityType.class); + private static final EnumMap DEFAULT_ITEM_DAMAGE = new EnumMap<>(Material.class); + private static final EnumMap DEFAULT_HEALTH = new EnumMap<>(EntityType.class); private static final AttributeModifier.Operation ADD = AttributeModifier.Operation.ADD_NUMBER; private static final AttributeModifier.Operation SCALAR = AttributeModifier.Operation.ADD_SCALAR; @@ -62,189 +59,196 @@ enum DamageType { } static { - mDefaultArmor.put(Material.LEATHER_HELMET, 1.0); - mDefaultArmor.put(Material.LEATHER_CHESTPLATE, 3.0); - mDefaultArmor.put(Material.LEATHER_LEGGINGS, 2.0); - mDefaultArmor.put(Material.LEATHER_BOOTS, 1.0); - mDefaultArmor.put(Material.GOLDEN_HELMET, 2.0); - mDefaultArmor.put(Material.GOLDEN_CHESTPLATE, 5.0); - mDefaultArmor.put(Material.GOLDEN_LEGGINGS, 3.0); - mDefaultArmor.put(Material.GOLDEN_BOOTS, 1.0); - mDefaultArmor.put(Material.CHAINMAIL_HELMET, 2.0); - mDefaultArmor.put(Material.CHAINMAIL_CHESTPLATE, 5.0); - mDefaultArmor.put(Material.CHAINMAIL_LEGGINGS, 4.0); - mDefaultArmor.put(Material.CHAINMAIL_BOOTS, 1.0); - mDefaultArmor.put(Material.IRON_HELMET, 2.0); - mDefaultArmor.put(Material.IRON_CHESTPLATE, 6.0); - mDefaultArmor.put(Material.IRON_LEGGINGS, 5.0); - mDefaultArmor.put(Material.IRON_BOOTS, 2.0); - mDefaultArmor.put(Material.DIAMOND_HELMET, 3.0); - mDefaultArmor.put(Material.DIAMOND_CHESTPLATE, 8.0); - mDefaultArmor.put(Material.DIAMOND_LEGGINGS, 6.0); - mDefaultArmor.put(Material.DIAMOND_BOOTS, 3.0); - mDefaultArmor.put(Material.TURTLE_HELMET, 2.0); - - mDefaultDamage.put(EntityType.BLAZE, 6.0); - mDefaultDamage.put(EntityType.CAVE_SPIDER, 2.0); - mDefaultDamage.put(EntityType.CREEPER, 49.0); - mDefaultDamage.put(EntityType.DOLPHIN, 3.0); + DEFAULT_ARMOR.put(Material.LEATHER_HELMET, 1.0); + DEFAULT_ARMOR.put(Material.LEATHER_CHESTPLATE, 3.0); + DEFAULT_ARMOR.put(Material.LEATHER_LEGGINGS, 2.0); + DEFAULT_ARMOR.put(Material.LEATHER_BOOTS, 1.0); + DEFAULT_ARMOR.put(Material.GOLDEN_HELMET, 2.0); + DEFAULT_ARMOR.put(Material.GOLDEN_CHESTPLATE, 5.0); + DEFAULT_ARMOR.put(Material.GOLDEN_LEGGINGS, 3.0); + DEFAULT_ARMOR.put(Material.GOLDEN_BOOTS, 1.0); + DEFAULT_ARMOR.put(Material.CHAINMAIL_HELMET, 2.0); + DEFAULT_ARMOR.put(Material.CHAINMAIL_CHESTPLATE, 5.0); + DEFAULT_ARMOR.put(Material.CHAINMAIL_LEGGINGS, 4.0); + DEFAULT_ARMOR.put(Material.CHAINMAIL_BOOTS, 1.0); + DEFAULT_ARMOR.put(Material.IRON_HELMET, 2.0); + DEFAULT_ARMOR.put(Material.IRON_CHESTPLATE, 6.0); + DEFAULT_ARMOR.put(Material.IRON_LEGGINGS, 5.0); + DEFAULT_ARMOR.put(Material.IRON_BOOTS, 2.0); + DEFAULT_ARMOR.put(Material.DIAMOND_HELMET, 3.0); + DEFAULT_ARMOR.put(Material.DIAMOND_CHESTPLATE, 8.0); + DEFAULT_ARMOR.put(Material.DIAMOND_LEGGINGS, 6.0); + DEFAULT_ARMOR.put(Material.DIAMOND_BOOTS, 3.0); + DEFAULT_ARMOR.put(Material.TURTLE_HELMET, 2.0); + + DEFAULT_DAMAGE.put(EntityType.BLAZE, 6.0); + DEFAULT_DAMAGE.put(EntityType.CAVE_SPIDER, 2.0); + DEFAULT_DAMAGE.put(EntityType.CREEPER, 49.0); + DEFAULT_DAMAGE.put(EntityType.DOLPHIN, 3.0); //?? - mDefaultDamage.put(EntityType.DROWNED, 3.0); - mDefaultDamage.put(EntityType.ELDER_GUARDIAN, 8.0); - mDefaultDamage.put(EntityType.ENDERMAN, 7.0); - mDefaultDamage.put(EntityType.ENDERMITE, 2.0); - mDefaultDamage.put(EntityType.EVOKER, 6.0); - mDefaultDamage.put(EntityType.GHAST, 23.0); - mDefaultDamage.put(EntityType.GUARDIAN, 6.0); - mDefaultDamage.put(EntityType.HUSK, 3.0); + DEFAULT_DAMAGE.put(EntityType.DROWNED, 3.0); + DEFAULT_DAMAGE.put(EntityType.ELDER_GUARDIAN, 8.0); + DEFAULT_DAMAGE.put(EntityType.ENDERMAN, 7.0); + DEFAULT_DAMAGE.put(EntityType.ENDERMITE, 2.0); + DEFAULT_DAMAGE.put(EntityType.EVOKER, 6.0); + DEFAULT_DAMAGE.put(EntityType.GHAST, 23.0); + DEFAULT_DAMAGE.put(EntityType.GUARDIAN, 6.0); + DEFAULT_DAMAGE.put(EntityType.HUSK, 3.0); //?? - mDefaultDamage.put(EntityType.ILLUSIONER, 4.0); - mDefaultDamage.put(EntityType.IRON_GOLEM, 21.0); - mDefaultDamage.put(EntityType.MAGMA_CUBE, 6.0); - mDefaultDamage.put(EntityType.PHANTOM, 6.0); - mDefaultDamage.put(EntityType.ZOMBIFIED_PIGLIN, 4.0); + DEFAULT_DAMAGE.put(EntityType.ILLUSIONER, 4.0); + DEFAULT_DAMAGE.put(EntityType.IRON_GOLEM, 21.0); + DEFAULT_DAMAGE.put(EntityType.MAGMA_CUBE, 6.0); + DEFAULT_DAMAGE.put(EntityType.PHANTOM, 6.0); + DEFAULT_DAMAGE.put(EntityType.ZOMBIFIED_PIGLIN, 4.0); //?? - mDefaultDamage.put(EntityType.PILLAGER, 4.0); - mDefaultDamage.put(EntityType.POLAR_BEAR, 6.0); - mDefaultDamage.put(EntityType.RAVAGER, 12.0); - mDefaultDamage.put(EntityType.SHULKER, 4.0); - mDefaultDamage.put(EntityType.SILVERFISH, 1.0); + DEFAULT_DAMAGE.put(EntityType.PILLAGER, 4.0); + DEFAULT_DAMAGE.put(EntityType.POLAR_BEAR, 6.0); + DEFAULT_DAMAGE.put(EntityType.RAVAGER, 12.0); + DEFAULT_DAMAGE.put(EntityType.SHULKER, 4.0); + DEFAULT_DAMAGE.put(EntityType.SILVERFISH, 1.0); //?? - mDefaultDamage.put(EntityType.SKELETON, 2.5); - mDefaultDamage.put(EntityType.SLIME, 2.0); - mDefaultDamage.put(EntityType.SPIDER, 2.0); + DEFAULT_DAMAGE.put(EntityType.SKELETON, 2.5); + DEFAULT_DAMAGE.put(EntityType.SLIME, 2.0); + DEFAULT_DAMAGE.put(EntityType.SPIDER, 2.0); //?? - mDefaultDamage.put(EntityType.STRAY, 2.0); - mDefaultDamage.put(EntityType.VEX, 3.0); - mDefaultDamage.put(EntityType.VINDICATOR, 5.0); - mDefaultDamage.put(EntityType.WITHER_SKELETON, 3.0); + DEFAULT_DAMAGE.put(EntityType.STRAY, 2.0); + DEFAULT_DAMAGE.put(EntityType.VEX, 3.0); + DEFAULT_DAMAGE.put(EntityType.VINDICATOR, 5.0); + DEFAULT_DAMAGE.put(EntityType.WITHER_SKELETON, 3.0); //?? - mDefaultDamage.put(EntityType.WITHER, 8.0); - mDefaultDamage.put(EntityType.WOLF, 2.0); - mDefaultDamage.put(EntityType.ZOMBIE, 3.0); - mDefaultDamage.put(EntityType.ZOMBIE_VILLAGER, 3.0); + DEFAULT_DAMAGE.put(EntityType.WITHER, 8.0); + DEFAULT_DAMAGE.put(EntityType.WOLF, 2.0); + DEFAULT_DAMAGE.put(EntityType.ZOMBIE, 3.0); + DEFAULT_DAMAGE.put(EntityType.ZOMBIE_VILLAGER, 3.0); //Health - mDefaultHealth.put(EntityType.SNOWMAN, 4.0); - mDefaultHealth.put(EntityType.BLAZE, 20.0); - mDefaultHealth.put(EntityType.DROWNED, 20.0); - mDefaultHealth.put(EntityType.HUSK, 20.0); - mDefaultHealth.put(EntityType.ZOMBIE, 20.0); - mDefaultHealth.put(EntityType.ZOMBIE_VILLAGER, 20.0); - mDefaultHealth.put(EntityType.ZOMBIFIED_PIGLIN, 20.0); - mDefaultHealth.put(EntityType.CREEPER, 20.0); - mDefaultHealth.put(EntityType.ENDERMITE, 8.0); - mDefaultHealth.put(EntityType.IRON_GOLEM, 100.0); - mDefaultHealth.put(EntityType.POLAR_BEAR, 30.0); - mDefaultHealth.put(EntityType.SILVERFISH, 8.0); - mDefaultHealth.put(EntityType.SKELETON, 20.0); - mDefaultHealth.put(EntityType.STRAY, 20.0); - mDefaultHealth.put(EntityType.WITCH, 26.0); - mDefaultHealth.put(EntityType.WITHER_SKELETON, 20.0); - mDefaultHealth.put(EntityType.CAT, 10.0); - mDefaultHealth.put(EntityType.CAVE_SPIDER, 12.0); - mDefaultHealth.put(EntityType.ELDER_GUARDIAN, 80.0); - mDefaultHealth.put(EntityType.ENDERMAN, 40.0); - mDefaultHealth.put(EntityType.FOX, 10.0); - mDefaultHealth.put(EntityType.OCELOT, 10.0); - mDefaultHealth.put(EntityType.RAVAGER, 1000.0); - mDefaultHealth.put(EntityType.SPIDER, 16.0); - mDefaultHealth.put(EntityType.WOLF, 8.0); - mDefaultHealth.put(EntityType.PILLAGER, 24.0); - mDefaultHealth.put(EntityType.VINDICATOR, 24.0); - mDefaultHealth.put(EntityType.EVOKER, 24.0); - mDefaultHealth.put(EntityType.GUARDIAN, 30.0); - mDefaultHealth.put(EntityType.ILLUSIONER, 32.0); - mDefaultHealth.put(EntityType.WITHER, 300.0); - mDefaultHealth.put(EntityType.GHAST, 10.0); - mDefaultHealth.put(EntityType.PUFFERFISH, 30.0); - mDefaultHealth.put(EntityType.SHULKER, 30.0); - mDefaultHealth.put(EntityType.DOLPHIN, 19.0); - mDefaultHealth.put(EntityType.SQUID, 10.0); - mDefaultHealth.put(EntityType.VEX, 14.0); + DEFAULT_HEALTH.put(EntityType.SNOWMAN, 4.0); + DEFAULT_HEALTH.put(EntityType.BLAZE, 20.0); + DEFAULT_HEALTH.put(EntityType.DROWNED, 20.0); + DEFAULT_HEALTH.put(EntityType.HUSK, 20.0); + DEFAULT_HEALTH.put(EntityType.ZOMBIE, 20.0); + DEFAULT_HEALTH.put(EntityType.ZOMBIE_VILLAGER, 20.0); + DEFAULT_HEALTH.put(EntityType.ZOMBIFIED_PIGLIN, 20.0); + DEFAULT_HEALTH.put(EntityType.CREEPER, 20.0); + DEFAULT_HEALTH.put(EntityType.ENDERMITE, 8.0); + DEFAULT_HEALTH.put(EntityType.IRON_GOLEM, 100.0); + DEFAULT_HEALTH.put(EntityType.POLAR_BEAR, 30.0); + DEFAULT_HEALTH.put(EntityType.SILVERFISH, 8.0); + DEFAULT_HEALTH.put(EntityType.SKELETON, 20.0); + DEFAULT_HEALTH.put(EntityType.STRAY, 20.0); + DEFAULT_HEALTH.put(EntityType.WITCH, 26.0); + DEFAULT_HEALTH.put(EntityType.WITHER_SKELETON, 20.0); + DEFAULT_HEALTH.put(EntityType.CAT, 10.0); + DEFAULT_HEALTH.put(EntityType.CAVE_SPIDER, 12.0); + DEFAULT_HEALTH.put(EntityType.ELDER_GUARDIAN, 80.0); + DEFAULT_HEALTH.put(EntityType.ENDERMAN, 40.0); + DEFAULT_HEALTH.put(EntityType.FOX, 10.0); + DEFAULT_HEALTH.put(EntityType.OCELOT, 10.0); + DEFAULT_HEALTH.put(EntityType.RAVAGER, 1000.0); + DEFAULT_HEALTH.put(EntityType.SPIDER, 16.0); + DEFAULT_HEALTH.put(EntityType.WOLF, 8.0); + DEFAULT_HEALTH.put(EntityType.PILLAGER, 24.0); + DEFAULT_HEALTH.put(EntityType.VINDICATOR, 24.0); + DEFAULT_HEALTH.put(EntityType.EVOKER, 24.0); + DEFAULT_HEALTH.put(EntityType.GUARDIAN, 30.0); + DEFAULT_HEALTH.put(EntityType.ILLUSIONER, 32.0); + DEFAULT_HEALTH.put(EntityType.WITHER, 300.0); + DEFAULT_HEALTH.put(EntityType.GHAST, 10.0); + DEFAULT_HEALTH.put(EntityType.PUFFERFISH, 30.0); + DEFAULT_HEALTH.put(EntityType.SHULKER, 30.0); + DEFAULT_HEALTH.put(EntityType.DOLPHIN, 19.0); + DEFAULT_HEALTH.put(EntityType.SQUID, 10.0); + DEFAULT_HEALTH.put(EntityType.VEX, 14.0); //I'll just assume it works the same for each mob-it should really only be on select zombies anyway - mDefaultItemDamage.put(Material.WOODEN_SWORD, 4.0); - mDefaultItemDamage.put(Material.GOLDEN_SWORD, 4.0); - mDefaultItemDamage.put(Material.STONE_SWORD, 5.0); - mDefaultItemDamage.put(Material.IRON_SWORD, 6.0); - mDefaultItemDamage.put(Material.DIAMOND_SWORD, 7.0); - mDefaultItemDamage.put(Material.NETHERITE_SWORD, 8.0); - mDefaultItemDamage.put(Material.WOODEN_AXE, 7.0); - mDefaultItemDamage.put(Material.GOLDEN_AXE, 7.0); - mDefaultItemDamage.put(Material.STONE_AXE, 9.0); - mDefaultItemDamage.put(Material.IRON_AXE, 9.0); - mDefaultItemDamage.put(Material.DIAMOND_AXE, 9.0); - mDefaultItemDamage.put(Material.NETHERITE_AXE, 10.0); - - mDefaultSpeed.put(EntityType.STRIDER, 0.125); - mDefaultSpeed.put(EntityType.SNOWMAN, 0.2); - mDefaultSpeed.put(EntityType.BLAZE, 0.23); - mDefaultSpeed.put(EntityType.DROWNED, 0.23); - mDefaultSpeed.put(EntityType.HUSK, 0.23); - mDefaultSpeed.put(EntityType.ZOMBIE, 0.23); - mDefaultSpeed.put(EntityType.ZOMBIE_VILLAGER, 0.23); - mDefaultSpeed.put(EntityType.ZOMBIFIED_PIGLIN, 0.23); - mDefaultSpeed.put(EntityType.CREEPER, 0.25); - mDefaultSpeed.put(EntityType.ENDERMITE, 0.25); - mDefaultSpeed.put(EntityType.IRON_GOLEM, 0.25); - mDefaultSpeed.put(EntityType.POLAR_BEAR, 0.25); - mDefaultSpeed.put(EntityType.SILVERFISH, 0.25); - mDefaultSpeed.put(EntityType.SKELETON, 0.25); - mDefaultSpeed.put(EntityType.STRAY, 0.25); - mDefaultSpeed.put(EntityType.WITCH, 0.25); - mDefaultSpeed.put(EntityType.WITHER_SKELETON, 0.25); - mDefaultSpeed.put(EntityType.BEE, 0.3); - mDefaultSpeed.put(EntityType.CAT, 0.3); - mDefaultSpeed.put(EntityType.CAVE_SPIDER, 0.3); - mDefaultSpeed.put(EntityType.ELDER_GUARDIAN, 0.3); - mDefaultSpeed.put(EntityType.ENDERMAN, 0.3); - mDefaultSpeed.put(EntityType.FOX, 0.3); - mDefaultSpeed.put(EntityType.OCELOT, 0.3); - mDefaultSpeed.put(EntityType.RAVAGER, 0.3); - mDefaultSpeed.put(EntityType.SPIDER, 0.3); - mDefaultSpeed.put(EntityType.WOLF, 0.3); - mDefaultSpeed.put(EntityType.PILLAGER, 0.35); - mDefaultSpeed.put(EntityType.VINDICATOR, 0.35); - mDefaultSpeed.put(EntityType.EVOKER, 0.5); - mDefaultSpeed.put(EntityType.GUARDIAN, 0.5); - mDefaultSpeed.put(EntityType.ILLUSIONER, 0.5); - mDefaultSpeed.put(EntityType.PIGLIN, 0.5); - mDefaultSpeed.put(EntityType.WITHER, 0.6); - mDefaultSpeed.put(EntityType.GHAST, 0.7); - mDefaultSpeed.put(EntityType.PUFFERFISH, 0.7); - mDefaultSpeed.put(EntityType.SHULKER, 0.0); - mDefaultSpeed.put(EntityType.DOLPHIN, 1.2); - mDefaultSpeed.put(EntityType.SQUID, 0.7); - mDefaultSpeed.put(EntityType.VEX, 0.7); + DEFAULT_ITEM_DAMAGE.put(Material.WOODEN_SWORD, 4.0); + DEFAULT_ITEM_DAMAGE.put(Material.GOLDEN_SWORD, 4.0); + DEFAULT_ITEM_DAMAGE.put(Material.STONE_SWORD, 5.0); + DEFAULT_ITEM_DAMAGE.put(Material.IRON_SWORD, 6.0); + DEFAULT_ITEM_DAMAGE.put(Material.DIAMOND_SWORD, 7.0); + DEFAULT_ITEM_DAMAGE.put(Material.NETHERITE_SWORD, 8.0); + DEFAULT_ITEM_DAMAGE.put(Material.WOODEN_AXE, 7.0); + DEFAULT_ITEM_DAMAGE.put(Material.GOLDEN_AXE, 7.0); + DEFAULT_ITEM_DAMAGE.put(Material.STONE_AXE, 9.0); + DEFAULT_ITEM_DAMAGE.put(Material.IRON_AXE, 9.0); + DEFAULT_ITEM_DAMAGE.put(Material.DIAMOND_AXE, 9.0); + DEFAULT_ITEM_DAMAGE.put(Material.NETHERITE_AXE, 10.0); + + DEFAULT_SPEED.put(EntityType.STRIDER, 0.125); + DEFAULT_SPEED.put(EntityType.SNOWMAN, 0.2); + DEFAULT_SPEED.put(EntityType.BLAZE, 0.23); + DEFAULT_SPEED.put(EntityType.DROWNED, 0.23); + DEFAULT_SPEED.put(EntityType.HUSK, 0.23); + DEFAULT_SPEED.put(EntityType.ZOMBIE, 0.23); + DEFAULT_SPEED.put(EntityType.ZOMBIE_VILLAGER, 0.23); + DEFAULT_SPEED.put(EntityType.ZOMBIFIED_PIGLIN, 0.23); + DEFAULT_SPEED.put(EntityType.CREEPER, 0.25); + DEFAULT_SPEED.put(EntityType.ENDERMITE, 0.25); + DEFAULT_SPEED.put(EntityType.IRON_GOLEM, 0.25); + DEFAULT_SPEED.put(EntityType.POLAR_BEAR, 0.25); + DEFAULT_SPEED.put(EntityType.SILVERFISH, 0.25); + DEFAULT_SPEED.put(EntityType.SKELETON, 0.25); + DEFAULT_SPEED.put(EntityType.STRAY, 0.25); + DEFAULT_SPEED.put(EntityType.WITCH, 0.25); + DEFAULT_SPEED.put(EntityType.WITHER_SKELETON, 0.25); + DEFAULT_SPEED.put(EntityType.BEE, 0.3); + DEFAULT_SPEED.put(EntityType.CAT, 0.3); + DEFAULT_SPEED.put(EntityType.CAVE_SPIDER, 0.3); + DEFAULT_SPEED.put(EntityType.ELDER_GUARDIAN, 0.3); + DEFAULT_SPEED.put(EntityType.ENDERMAN, 0.3); + DEFAULT_SPEED.put(EntityType.FOX, 0.3); + DEFAULT_SPEED.put(EntityType.OCELOT, 0.3); + DEFAULT_SPEED.put(EntityType.RAVAGER, 0.3); + DEFAULT_SPEED.put(EntityType.SPIDER, 0.3); + DEFAULT_SPEED.put(EntityType.WOLF, 0.3); + DEFAULT_SPEED.put(EntityType.PILLAGER, 0.35); + DEFAULT_SPEED.put(EntityType.VINDICATOR, 0.35); + DEFAULT_SPEED.put(EntityType.EVOKER, 0.5); + DEFAULT_SPEED.put(EntityType.GUARDIAN, 0.5); + DEFAULT_SPEED.put(EntityType.ILLUSIONER, 0.5); + DEFAULT_SPEED.put(EntityType.PIGLIN, 0.5); + DEFAULT_SPEED.put(EntityType.WITHER, 0.6); + DEFAULT_SPEED.put(EntityType.GHAST, 0.7); + DEFAULT_SPEED.put(EntityType.PUFFERFISH, 0.7); + DEFAULT_SPEED.put(EntityType.SHULKER, 0.0); + DEFAULT_SPEED.put(EntityType.DOLPHIN, 1.2); + DEFAULT_SPEED.put(EntityType.SQUID, 0.7); + DEFAULT_SPEED.put(EntityType.VEX, 0.7); } public static String formatWell(String in) { in = in.replaceAll("\"", ""); - String sub = ""; + StringBuilder sub = new StringBuilder(); if (in.contains("_")) { String[] cuts = in.split("_"); for (String cut : cuts) { - if (cut.length() == 0) { + if (cut.isEmpty()) { continue; } String subCut = cut.substring(0, 1); - subCut = subCut.toUpperCase(); + subCut = subCut.toUpperCase(Locale.ROOT); subCut += cut.substring(1); - sub += subCut + " "; + sub.append(subCut).append(" "); } } else { - sub = in.substring(0, 1); - sub = sub.toUpperCase(); - sub += in.substring(1); + sub = new StringBuilder(in.substring(0, 1)); + sub = new StringBuilder(sub.toString().toUpperCase(Locale.ROOT)); + sub.append(in.substring(1)); } - return sub; + return sub.toString(); } private static Component blackIfWhite(Component comp) { - if (comp.color().asHexString().equals("#ffffff")) { - comp = comp.color(TextColor.color(0, 0, 0)); + final var color = comp.color(); + + if (color == null) { + return comp.color(TextColor.color(0, 0, 0)); + } + + if (color.value() == 0xffffff) { + return comp.color(TextColor.color(0, 0, 0)); } + return comp; } @@ -253,7 +257,7 @@ private static Component blackIfWhite(Component comp) { private final List mPeers; private final int mPeerIndex; private int mPrevEntry = -1; - private int mNextEntry = 40000; + private int mNextEntry; public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, boolean lowerInfoTier, List peers, int peerIndex) { super(player, 54, LegacyComponentSerializer.legacySection().serialize(blackIfWhite(soul.getDisplayName()))); @@ -270,8 +274,8 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, double armor = 0; double armorToughness = 0; - double health = vars.hasKey("Health") ? 0.0 + Float.valueOf(vars.getFloat("Health")) : 0.0; - double speed = vars.hasKey("MovementSpeed") ? 0.0 + Float.valueOf(vars.getFloat("MovementSpeed")) : 0; + double health = vars.hasKey("Health") ? 0.0 + vars.getFloat("Health") : 0.0; + double speed = vars.hasKey("MovementSpeed") ? 0.0 + vars.getFloat("MovementSpeed") : 0; double damage = attr.getAttribute(AttributeType.ATTACK_DAMAGE) != null ? Math.max(attr.getAttribute(AttributeType.ATTACK_DAMAGE).getBase(), 0.0) : 0.0; double speedScalar = 0; double speedPercent = 1; @@ -282,8 +286,8 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, EntityType entType = entityNBT.getEntityType(); DamageType type = null; - Double defHealth = mDefaultHealth.get(entType); - Double defDamage = mDefaultDamage.get(entType); + Double defHealth = DEFAULT_HEALTH.get(entType); + Double defDamage = DEFAULT_DAMAGE.get(entType); //Stuff to throw errors before everything if (defHealth != null && health == 0.0) { @@ -299,7 +303,7 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, } // Only need to create one of these - EffectsVariable effectVar = new EffectsVariable("ActiveEffects"); + EffectsVariable effectVar = new EffectsVariable("active_effects"); ItemsVariable itemsVar = new ItemsVariable("ArmorItems", new String[] {"Feet Equipment", "Legs Equipment", "Chest Equipment", "Head Equipment"}); ItemsVariable handVar = new ItemsVariable("HandItems", new String[] {"Offhand", "Mainhand"}); // For each mob you want to work with: @@ -310,8 +314,8 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, if (item != null && item.hasItemMeta()) { armor += getAttributeNumber(item, Attribute.GENERIC_ARMOR, ADD); - if (mDefaultArmor.containsKey(item.getType()) && item.getItemMeta().getAttributeModifiers(Attribute.GENERIC_ARMOR) == null) { - armor += mDefaultArmor.get(item.getType()); + if (DEFAULT_ARMOR.containsKey(item.getType()) && item.getItemMeta().getAttributeModifiers(Attribute.GENERIC_ARMOR) == null) { + armor += DEFAULT_ARMOR.get(item.getType()); } armorToughness += getAttributeNumber(item, Attribute.GENERIC_ARMOR_TOUGHNESS, ADD); @@ -347,8 +351,8 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, type = DamageType.TRIDENT; } - if (getAttributeNumber(item, Attribute.GENERIC_ATTACK_DAMAGE, ADD, slot) == 0 && mDefaultItemDamage.containsKey(item.getType()) && slot == EquipmentSlot.HAND) { - damage += mDefaultItemDamage.get(item.getType()); + if (getAttributeNumber(item, Attribute.GENERIC_ATTACK_DAMAGE, ADD, slot) == 0 && DEFAULT_ITEM_DAMAGE.containsKey(item.getType()) && slot == EquipmentSlot.HAND) { + damage += DEFAULT_ITEM_DAMAGE.get(item.getType()); } if (slot == EquipmentSlot.HAND && item.containsEnchantment(Enchantment.DAMAGE_ALL)) { @@ -379,7 +383,7 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, String get = nbtVar.get(); if (get != null && !get.isEmpty()) { type = DamageType.GHAST; - explodePower = Float.valueOf(nbtVar.get()); + explodePower = Float.parseFloat(nbtVar.get()); } else { type = DamageType.GHAST; explodePower = 1; @@ -395,7 +399,7 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, } else { String get = nbtVar.get(); if (get != null) { - explodePower = Double.valueOf(get); + explodePower = Double.parseDouble(get); } else { explodePower = 3; } @@ -435,7 +439,7 @@ public BestiarySoulInventory(Player player, SoulEntry soul, BestiaryArea parent, // Outside of the checking for tier since if you can see the entry, you can hopefully move between them (If there are mobs there) for (int i = mPeerIndex - 1; i >= 0; i--) { - if (mPeers.get(i).canOpenBestiary(player) && i >= 0) { + if (mPeers.get(i).canOpenBestiary(player)) { mPrevEntry = i; break; } @@ -537,9 +541,7 @@ public static double getAttributeNumber(ItemStack item, Attribute attribute, Att ItemMeta meta = item.getItemMeta(); double attributeNum = 0; if (meta.getAttributeModifiers(attribute) != null) { - Iterator iterator = meta.getAttributeModifiers(attribute).iterator(); - while (iterator.hasNext()) { - AttributeModifier mod = iterator.next(); + for (AttributeModifier mod : meta.getAttributeModifiers(attribute)) { if (mod.getOperation().equals(operation)) { if (slot == null) { attributeNum += mod.getAmount(); @@ -659,7 +661,7 @@ private static ItemStack getDamageItem(@Nullable ItemStack item, double damage, damageMeta.addEnchant(Enchantment.ARROW_INFINITE, 1, true); damageMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - damageMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); + damageMeta.addItemFlags(ItemFlag.HIDE_ITEM_SPECIFICS); damageItem.setItemMeta(damageMeta); @@ -672,10 +674,10 @@ private static ItemStack getEffectItem(ItemStack effectItem) { PotionMeta potionMeta = (PotionMeta)effectItem.getItemMeta(); for (PotionEffect effect : potionMeta.getCustomEffects()) { - lore.add(Component.text(formatWell(effect.toString().substring(0, effect.toString().indexOf(":")).toLowerCase()) + " (∞)", NamedTextColor.DARK_BLUE).decoration(TextDecoration.ITALIC, false)); + lore.add(Component.text(formatWell(effect.toString().substring(0, effect.toString().indexOf(":")).toLowerCase(Locale.ROOT)) + " (∞)", NamedTextColor.DARK_BLUE).decoration(TextDecoration.ITALIC, false)); } - potionMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); + potionMeta.addItemFlags(ItemFlag.HIDE_ITEM_SPECIFICS); potionMeta.lore(lore); potionMeta.displayName(Component.text("Effects", NamedTextColor.WHITE).decoration(TextDecoration.ITALIC, false)); potionMeta.addEnchant(Enchantment.ARROW_INFINITE, 1, true); @@ -701,10 +703,10 @@ private static ItemStack getSpeedItem(EntityNBT entityNBT, double speed, double ItemMeta speedMeta = speedItem.getItemMeta(); List lore = new ArrayList<>(); - if (mDefaultSpeed.containsKey(entityNBT.getEntityType()) && speed == 0) { + if (DEFAULT_SPEED.containsKey(entityNBT.getEntityType()) && speed == 0) { - if (mDefaultSpeed.get(entityNBT.getEntityType()) != null) { - speedScalar += mDefaultSpeed.get(entityNBT.getEntityType()); + if (DEFAULT_SPEED.get(entityNBT.getEntityType()) != null) { + speedScalar += DEFAULT_SPEED.get(entityNBT.getEntityType()); } else { LibraryOfSouls.getInstance().getLogger().log(Level.INFO, "This mob type is not contained in the speed map: " + entityNBT.getEntityType()); } @@ -712,7 +714,7 @@ private static ItemStack getSpeedItem(EntityNBT entityNBT, double speed, double speed += speedScalar; speed *= speedPercent; } else if (entityNBT.getEntityType().equals(EntityType.SLIME)) { - int size = Integer.valueOf(entityNBT.getVariable("Size").get()); + int size = Integer.parseInt(entityNBT.getVariable("Size").get()); speed = 0.2 + (0.1 * size); speed += speedScalar; speed *= speedPercent; @@ -750,11 +752,7 @@ public ItemStack getLoreItem(SoulEntry soul) { return loreItem; } - List itemLore = new ArrayList<>(); - - for (Component comp : lore) { - itemLore.add(comp); - } + List itemLore = new ArrayList<>(lore); meta.lore(itemLore); loreItem.setItemMeta(meta); @@ -795,7 +793,7 @@ public static List formatTags(String tag) { for (String iterTag : tags) { iterTag = iterTag.replaceAll("\"", ""); iterTag = iterTag.replaceAll("\\[", ""); - iterTag = iterTag.replaceAll("\\]", ""); + iterTag = iterTag.replaceAll("]", ""); iterTag = formatWell(iterTag); iterTag = iterTag.replaceAll("Boss ", ""); ret.add(iterTag); @@ -803,7 +801,7 @@ public static List formatTags(String tag) { } else { tag = tag.replaceAll("\"", ""); tag = tag.replaceAll("\\[", ""); - tag = tag.replaceAll("\\]", ""); + tag = tag.replaceAll("]", ""); tag = formatWell(tag); tag = tag.replaceAll("Boss ", ""); ret.add(tag); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryRedisStorage.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryRedisStorage.java index 3ca410a..824e7ed 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryRedisStorage.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryRedisStorage.java @@ -85,7 +85,7 @@ public void playerJoinEvent(final PlayerJoinEvent event) { new BukkitRunnable() { @Override public void run() { - final Long runnableTime = System.currentTimeMillis(); + final long runnableTime = System.currentTimeMillis(); int stepCounter = 0; while (iter.hasNext() && player.isOnline()) { final SoulEntry soul = iter.next(); @@ -106,7 +106,7 @@ public void run() { break; } } - mLogger.fine("Main thread data loading loop took " + Long.toString(System.currentTimeMillis() - runnableTime) + " milliseconds"); + mLogger.fine("Main thread data loading loop took " + (System.currentTimeMillis() - runnableTime) + " milliseconds"); if (!player.isOnline()) { /* Player logged out before their data finished loading - abort */ @@ -115,7 +115,7 @@ public void run() { /* All done loading - make the player kills map accessible */ mPlayerKills.put(uuid, playerKills); this.cancel(); - mLogger.fine("Data load complete, total time " + Long.toString(System.currentTimeMillis() - startMainTime) + " milliseconds"); + mLogger.fine("Data load complete, total time " + (System.currentTimeMillis() - startMainTime) + " milliseconds"); } } }.runTaskTimer(mPlugin, 1, 1); @@ -141,7 +141,7 @@ public void playerSaveEvent(final PlayerSaveEvent event) { } mLogger.fine("Started saving redis player data for " + uuid); - final Long startMainTime = System.currentTimeMillis(); + final long startMainTime = System.currentTimeMillis(); if (playerKills != null) { for (final Map.Entry entry : playerKills.entrySet()) { @@ -152,7 +152,7 @@ public void playerSaveEvent(final PlayerSaveEvent event) { /* Save the data to Redis */ event.setPluginData(IDENTIFIER, originalData); - mLogger.fine("Main thread work took " + Long.toString(System.currentTimeMillis() - startMainTime) + " milliseconds"); + mLogger.fine("Main thread work took " + (System.currentTimeMillis() - startMainTime) + " milliseconds"); } /* When player leaves, remove it from the local storage a short bit later */ @@ -178,12 +178,7 @@ public void recordKill(final Player player, final SoulEntry soul) { } mLogger.fine("Recording kill for player " + player.getName() + " mob " + soul.getLabel()); - final Integer kills = playerKills.get(soul); - if (kills == null) { - playerKills.put(soul, 1); - } else { - playerKills.put(soul, kills + 1); - } + playerKills.merge(soul, 1, Integer::sum); } @Override @@ -195,11 +190,7 @@ public int getKillsForMob(final Player player, final SoulEntry soul) { return 0; } - final Integer kills = playerKills.get(soul); - if (kills == null) { - return 0; - } - return kills; + return playerKills.getOrDefault(soul, 0); } @Override @@ -242,11 +233,7 @@ public Map getAllKilledMobs(final Player player, final Colle final Map map = new HashMap<>(); for (final SoulEntry soul : searchSouls) { - if (playerKills == null) { - map.put(soul, 0); - } else { - map.put(soul, playerKills.getOrDefault(soul, 0)); - } + map.put(soul, playerKills.getOrDefault(soul, 0)); } return map; diff --git a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryScoreboardStorage.java b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryScoreboardStorage.java index 3778677..6c8db8a 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryScoreboardStorage.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/bestiary/storage/BestiaryScoreboardStorage.java @@ -14,6 +14,7 @@ import org.bukkit.scoreboard.Scoreboard; public class BestiaryScoreboardStorage implements BestiaryStorage { + @SuppressWarnings("deprecation") @Override public void recordKill(Player player, SoulEntry soul) { Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); @@ -38,13 +39,14 @@ public int getKillsForMob(Player player, SoulEntry soul) { } Score score = objective.getScore(player.getName()); - if (score == null || !score.isScoreSet()) { + if (!score.isScoreSet()) { return 0; } return score.getScore(); } + @SuppressWarnings("deprecation") @Override public void setKillsForMob(Player player, SoulEntry soul, int amount) { Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); @@ -59,6 +61,7 @@ public void setKillsForMob(Player player, SoulEntry soul, int amount) { score.setScore(amount); } + @SuppressWarnings("deprecation") @Override public int addKillsForMob(Player player, SoulEntry soul, int amount) { Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); diff --git a/src/main/java/com/playmonumenta/libraryofsouls/commands/LibraryOfSoulsCommand.java b/src/main/java/com/playmonumenta/libraryofsouls/commands/LibraryOfSoulsCommand.java index 71b4aba..f158804 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/commands/LibraryOfSoulsCommand.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/commands/LibraryOfSoulsCommand.java @@ -38,10 +38,10 @@ public class LibraryOfSoulsCommand { /* Several sub commands have this same tab completion */ - public static final ArgumentSuggestions LIST_MOBS_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listMobNames().stream().toArray(String[]::new)); - public static final ArgumentSuggestions LIST_SOUL_PARTIES_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listSoulPartyNames().stream().toArray(String[]::new)); - public static final ArgumentSuggestions LIST_SOUL_POOLS_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listSoulPoolNames().stream().toArray(String[]::new)); - public static final ArgumentSuggestions LIST_SOUL_GROUPS_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listSoulGroupNames().stream().toArray(String[]::new)); + public static final ArgumentSuggestions LIST_MOBS_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listMobNames().toArray(String[]::new)); + public static final ArgumentSuggestions LIST_SOUL_PARTIES_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listSoulPartyNames().toArray(String[]::new)); + public static final ArgumentSuggestions LIST_SOUL_POOLS_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listSoulPoolNames().toArray(String[]::new)); + public static final ArgumentSuggestions LIST_SOUL_GROUPS_FUNCTION = ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listSoulGroupNames().toArray(String[]::new)); private static final String COMMAND = "los"; private static final Pattern VALID_SOUL_GROUP_LABEL = Pattern.compile("[0-9A-Za-z_]+"); @@ -55,8 +55,8 @@ public static void register() { LocationArgument locationArg = new LocationArgument("location"); LocationArgument pos1Arg = new LocationArgument("pos1"); LocationArgument pos2Arg = new LocationArgument("pos2"); - Argument areaArg = new StringArgument("area").replaceSuggestions(ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listMobLocations().stream().toArray(String[]::new))); - Argument idArg = new StringArgument("id").replaceSuggestions(ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listMobTypes().stream().toArray(String[]::new))); + Argument areaArg = new StringArgument("area").replaceSuggestions(ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listMobLocations().toArray(String[]::new))); + Argument idArg = new StringArgument("id").replaceSuggestions(ArgumentSuggestions.strings((info) -> SoulsDatabase.getInstance().listMobTypes().toArray(String[]::new))); /* los open */ new CommandAPICommand(COMMAND) diff --git a/src/main/java/com/playmonumenta/libraryofsouls/utils/FileUtils.java b/src/main/java/com/playmonumenta/libraryofsouls/utils/FileUtils.java index 23f48b9..2bec507 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/utils/FileUtils.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/utils/FileUtils.java @@ -55,14 +55,8 @@ public static void writeFile(String fileName, String contents) throws IOExceptio file.createNewFile(); } - OutputStreamWriter writer = null; - try { - writer = new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8); + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8)) { writer.write(contents); - } finally { - if (writer != null) { - writer.close(); - } } } diff --git a/src/main/java/com/playmonumenta/libraryofsouls/utils/Utils.java b/src/main/java/com/playmonumenta/libraryofsouls/utils/Utils.java index 86f1b17..862fc11 100644 --- a/src/main/java/com/playmonumenta/libraryofsouls/utils/Utils.java +++ b/src/main/java/com/playmonumenta/libraryofsouls/utils/Utils.java @@ -1,6 +1,16 @@ package com.playmonumenta.libraryofsouls.utils; +import it.unimi.dsi.fastutil.Pair; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.function.BiConsumer; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -24,40 +34,45 @@ public static String plainFromLegacy(String legacyText) { return PLAIN_SERIALIZER.serialize(LEGACY_SERIALIZER.deserialize(legacyText)); } + public static TextColor colorFromInt(int val) { + return switch (val % 13) { + case 0 -> NamedTextColor.DARK_GREEN; + case 1 -> NamedTextColor.DARK_AQUA; + case 2 -> NamedTextColor.DARK_RED; + case 3 -> NamedTextColor.DARK_PURPLE; + case 4 -> NamedTextColor.GOLD; + case 5 -> NamedTextColor.GRAY; + case 6 -> NamedTextColor.DARK_GRAY; + case 7 -> NamedTextColor.BLUE; + case 8 -> NamedTextColor.GREEN; + case 9 -> NamedTextColor.AQUA; + case 10 -> NamedTextColor.RED; + case 11 -> NamedTextColor.LIGHT_PURPLE; + default -> NamedTextColor.YELLOW; + }; + } + + @SuppressWarnings("deprecation") public static String hashColor(String in) { - int val = in.hashCode() % 13; - switch (val) { - case 0: - return ChatColor.DARK_GREEN + in; - case 1: - return ChatColor.DARK_AQUA + in; - case 2: - return ChatColor.DARK_RED + in; - case 3: - return ChatColor.DARK_PURPLE + in; - case 4: - return ChatColor.GOLD + in; - case 5: - return ChatColor.GRAY + in; - case 6: - return ChatColor.DARK_GRAY + in; - case 7: - return ChatColor.BLUE + in; - case 8: - return ChatColor.GREEN + in; - case 9: - return ChatColor.AQUA + in; - case 10: - return ChatColor.RED + in; - case 11: - return ChatColor.LIGHT_PURPLE + in; - default: - return ChatColor.YELLOW + in; - } + return switch (in.hashCode() % 13) { + case 0 -> ChatColor.DARK_GREEN + in; + case 1 -> ChatColor.DARK_AQUA + in; + case 2 -> ChatColor.DARK_RED + in; + case 3 -> ChatColor.DARK_PURPLE + in; + case 4 -> ChatColor.GOLD + in; + case 5 -> ChatColor.GRAY + in; + case 6 -> ChatColor.DARK_GRAY + in; + case 7 -> ChatColor.BLUE + in; + case 8 -> ChatColor.GREEN + in; + case 9 -> ChatColor.AQUA + in; + case 10 -> ChatColor.RED + in; + case 11 -> ChatColor.LIGHT_PURPLE + in; + default -> ChatColor.YELLOW + in; + }; } public static String getLabelFromName(Component name) throws Exception { - String label = null; + String label; try { label = plainText(name).replaceAll("[^A-Za-z]", ""); } catch (Exception e) { @@ -68,7 +83,7 @@ public static String getLabelFromName(Component name) throws Exception { } public static String getLabelFromName(String name) throws Exception { - String label = null; + String label; try { label = plainFromLegacy(name).replaceAll("[^A-Za-z]", ""); } catch (Exception e) { @@ -109,4 +124,99 @@ public static boolean insideBlocks(Location feetLoc, double width, double height } return false; } + + private static void visitComponentDfs(Style parent, TextComponent component, BiConsumer consumer) { + final var newParent = parent.merge(component.style()); + consumer.accept(newParent, component.content()); + + for (Component child : component.children()) { + if (!(child instanceof TextComponent textComponent)) { + throw new IllegalArgumentException("Non-text component found in wrapComponent"); + } + + visitComponentDfs(newParent, textComponent, consumer); + } + } + + public static List wrapComponent(TextComponent text, int maxChars, int minChars, boolean skipSpace) { + final var styleList = new ArrayList