From bb9710acfc4cce82d464c7657881dcb364dd4b03 Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Mon, 20 Mar 2023 12:25:52 +0100 Subject: [PATCH] Stores original metadata to all armored elytras --- .../container/EnchantmentContainer.java | 13 +- .../armoredelytra/metadata/NBTEditor.java | 2 +- .../metadata/OriginalMetadata.java | 63 +++------ .../builder/ArmoredElytraBuilder.java | 23 +++- .../builder/OriginalMetadataBuilder.java | 125 ++++++++++++++++++ .../armoredelytra/update/UpdateManager.java | 2 +- .../armoredelytra/util/GenericUtilTest.java | 2 +- 7 files changed, 176 insertions(+), 54 deletions(-) create mode 100644 src/main/java/net/knarcraft/armoredelytra/metadata/builder/OriginalMetadataBuilder.java diff --git a/src/main/java/net/knarcraft/armoredelytra/container/EnchantmentContainer.java b/src/main/java/net/knarcraft/armoredelytra/container/EnchantmentContainer.java index a83a21b..41e36b7 100644 --- a/src/main/java/net/knarcraft/armoredelytra/container/EnchantmentContainer.java +++ b/src/main/java/net/knarcraft/armoredelytra/container/EnchantmentContainer.java @@ -7,6 +7,7 @@ import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -15,7 +16,11 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -public class EnchantmentContainer implements Iterable> { +/** + * A container for keeping track of enchantments, with additional filtering capabilities. + */ +public class EnchantmentContainer implements Iterable>, Serializable { + private Map enchantments; /** @@ -219,9 +224,8 @@ public class EnchantmentContainer implements Iterable blackList = - second.keySet().stream() - .flatMap(enchantment -> getMutuallyExclusiveEnchantments(enchantment).stream()) - .toList(); + second.keySet().stream().flatMap(enchantment -> + getMutuallyExclusiveEnchantments(enchantment).stream()).toList(); blackList.forEach(first.keySet()::remove); final Map combined = new HashMap<>(first); @@ -260,4 +264,5 @@ public class EnchantmentContainer implements Iterable> iterator() { return enchantments.entrySet().iterator(); } + } diff --git a/src/main/java/net/knarcraft/armoredelytra/metadata/NBTEditor.java b/src/main/java/net/knarcraft/armoredelytra/metadata/NBTEditor.java index a2b757d..88dd1bc 100644 --- a/src/main/java/net/knarcraft/armoredelytra/metadata/NBTEditor.java +++ b/src/main/java/net/knarcraft/armoredelytra/metadata/NBTEditor.java @@ -260,7 +260,7 @@ public class NBTEditor { * @param item

The item to get item meta for

* @return

The existing or new item meta

*/ - private static ItemMeta getOrCreateItemMeta(ItemStack item) { + public static ItemMeta getOrCreateItemMeta(ItemStack item) { final ItemMeta meta = item.hasItemMeta() ? item.getItemMeta() : Bukkit.getItemFactory().getItemMeta(item.getType()); if (meta == null) { diff --git a/src/main/java/net/knarcraft/armoredelytra/metadata/OriginalMetadata.java b/src/main/java/net/knarcraft/armoredelytra/metadata/OriginalMetadata.java index a458550..8b65d36 100644 --- a/src/main/java/net/knarcraft/armoredelytra/metadata/OriginalMetadata.java +++ b/src/main/java/net/knarcraft/armoredelytra/metadata/OriginalMetadata.java @@ -1,12 +1,11 @@ package net.knarcraft.armoredelytra.metadata; -import org.bukkit.enchantments.Enchantment; +import net.knarcraft.armoredelytra.container.EnchantmentContainer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; +import java.util.List; /** * An object for storing the original metadata for an armored elytra. @@ -18,11 +17,11 @@ import java.util.Set; */ public class OriginalMetadata implements Serializable { - private Set armorEnchantments = new HashSet<>(); - private Set elytraEnchantments = new HashSet<>(); - private String elytraLore; + private EnchantmentContainer armorEnchantments = new EnchantmentContainer(); + private EnchantmentContainer elytraEnchantments = new EnchantmentContainer(); + private List elytraLore; private String elytraName; - private String armorLore; + private List armorLore; private String armorName; public OriginalMetadata() { @@ -34,8 +33,8 @@ public class OriginalMetadata implements Serializable { * * @return

The stored armor enchantments.

*/ - public @NotNull Set getArmorEnchantments() { - return new HashSet<>(armorEnchantments); + public @NotNull EnchantmentContainer getArmorEnchantments() { + return armorEnchantments; } /** @@ -43,8 +42,8 @@ public class OriginalMetadata implements Serializable { * * @return

The stored elytra enchantments.

*/ - public @NotNull Set getElytraEnchantments() { - return new HashSet<>(elytraEnchantments); + public @NotNull EnchantmentContainer getElytraEnchantments() { + return elytraEnchantments; } /** @@ -52,7 +51,7 @@ public class OriginalMetadata implements Serializable { * * @return

The original elytra lore.

*/ - public @Nullable String getElytraLore() { + public @Nullable List getElytraLore() { return this.elytraLore; } @@ -70,7 +69,7 @@ public class OriginalMetadata implements Serializable { * * @return

The original armor lore.

*/ - public @Nullable String getArmorLore() { + public @Nullable List getArmorLore() { return this.armorLore; } @@ -87,80 +86,54 @@ public class OriginalMetadata implements Serializable { * Sets the stored lore of this armored elytra's armor. * * @param armorLore

The armor lore to store.

- * @return

This original metadata.

*/ - public OriginalMetadata setArmorLore(@NotNull String armorLore) { + public void setArmorLore(@NotNull List armorLore) { this.armorLore = armorLore; - return this; } /** * Sets the stored elytra lore of this armored elytra's elytra. * * @param elytraLore

The elytra lore to store.

- * @return

This original metadata.

*/ - public OriginalMetadata setElytraLore(@NotNull String elytraLore) { + public void setElytraLore(@NotNull List elytraLore) { this.elytraLore = elytraLore; - return this; } /** * Sets the stored elytra name of this armored elytra's elytra. * * @param elytraName

The elytra name to store.

- * @return

This original metadata.

*/ - public OriginalMetadata setElytraName(@NotNull String elytraName) { + public void setElytraName(@NotNull String elytraName) { this.elytraName = elytraName; - return this; } /** * Sets the stored armor name of this armored elytra's armor. * * @param armorName

The armor name to store.

- * @return

This original metadata.

*/ - public OriginalMetadata setArmorName(@NotNull String armorName) { + public void setArmorName(@NotNull String armorName) { this.armorName = armorName; - return this; } /** * Sets the stored enchantments for this armored elytra's armor. * * @param armorEnchantments

The armor enchantments to store.

- * @return

This original metadata.

*/ - public OriginalMetadata setArmorEnchantments(@NotNull Set armorEnchantments) { + public void setArmorEnchantments(@NotNull EnchantmentContainer armorEnchantments) { this.armorEnchantments = armorEnchantments; - return this; } /** * Sets the stored enchantments for this armored elytra's elytra. * * @param elytraEnchantments

The elytra enchantments to store.

- * @return

This original metadata.

*/ - public OriginalMetadata setElytraEnchantments(@NotNull Set elytraEnchantments) { + public void setElytraEnchantments(@NotNull EnchantmentContainer elytraEnchantments) { this.elytraEnchantments = elytraEnchantments; - return this; - } - - /** - * Adds the given enchantments to armor enchantments. - * - *

The purpose of this method is to combine enchantments for the original chestplate, and any chest-plates used - * to upgrade the armored elytra.

- * - * @param enchantments

The enchantments to add

- * @return

This original metadata.

- */ - public OriginalMetadata addArmorEnchantments(@NotNull Set enchantments) { - this.armorEnchantments.addAll(enchantments); - return this; } } diff --git a/src/main/java/net/knarcraft/armoredelytra/metadata/builder/ArmoredElytraBuilder.java b/src/main/java/net/knarcraft/armoredelytra/metadata/builder/ArmoredElytraBuilder.java index 4c8f391..d11f183 100644 --- a/src/main/java/net/knarcraft/armoredelytra/metadata/builder/ArmoredElytraBuilder.java +++ b/src/main/java/net/knarcraft/armoredelytra/metadata/builder/ArmoredElytraBuilder.java @@ -5,6 +5,7 @@ import net.knarcraft.armoredelytra.config.ConfigLoader; import net.knarcraft.armoredelytra.container.EnchantmentContainer; import net.knarcraft.armoredelytra.metadata.DurabilityManager; import net.knarcraft.armoredelytra.metadata.NBTEditor; +import net.knarcraft.armoredelytra.metadata.OriginalMetadata; import net.knarcraft.armoredelytra.property.ArmorTier; import org.bukkit.inventory.ItemStack; @@ -16,6 +17,7 @@ public class ArmoredElytraBuilder { private final DurabilityManager durabilityManager; private final ConfigLoader config; private final ArmoredElytra plugin; + private final OriginalMetadataBuilder metadataBuilder; public ArmoredElytraBuilder(NBTEditor nbtEditor, DurabilityManager durabilityManager, ConfigLoader config, ArmoredElytra plugin) { @@ -24,6 +26,7 @@ public class ArmoredElytraBuilder { this.durabilityManager = durabilityManager; this.config = config; this.plugin = plugin; + this.metadataBuilder = new OriginalMetadataBuilder(plugin, nbtEditor); } /** @@ -79,14 +82,16 @@ public class ArmoredElytraBuilder { * @return The new armored elytra. */ public ItemStack combine(ItemStack elytra, ItemStack combiner, ArmorTier armorTier, @Nullable String name) { - return newBuilder().ofElytra(elytra).combineWith(combiner, armorTier).withName(name).build(); + return getArmoredElytraWithOriginalMetadata(elytra, combiner, + newBuilder().ofElytra(elytra).combineWith(combiner, armorTier).withName(name).build()); } /** * See {@link #combine(ItemStack, ItemStack, ArmorTier, String)} for unknown armor tiers. */ public ItemStack combine(ItemStack elytra, ItemStack combiner, @Nullable String name) { - return newBuilder().ofElytra(elytra).combineWith(combiner).withName(name).build(); + return getArmoredElytraWithOriginalMetadata(elytra, combiner, + newBuilder().ofElytra(elytra).combineWith(combiner).withName(name).build()); } /** @@ -99,4 +104,18 @@ public class ArmoredElytraBuilder { return newBuilder().newItem(armorTier).build(); } + /** + * Adds/Updates the original metadata for an armored elytra, and returns the armored elytra. + * + * @param elytra

The base elytra.

+ * @param armor

The armor/armored elytra combined with the elytra.

+ * @param armoredElytra

The combined armored elytra.

+ * @return

The armored elytra with updated original metadata.

+ */ + private ItemStack getArmoredElytraWithOriginalMetadata(ItemStack elytra, ItemStack armor, ItemStack armoredElytra) { + OriginalMetadata originalMetadata = metadataBuilder.getMergedOriginalMetaData(elytra, armor); + nbtEditor.updateOriginalMetadata(armoredElytra, originalMetadata); + return armoredElytra; + } + } diff --git a/src/main/java/net/knarcraft/armoredelytra/metadata/builder/OriginalMetadataBuilder.java b/src/main/java/net/knarcraft/armoredelytra/metadata/builder/OriginalMetadataBuilder.java new file mode 100644 index 0000000..b445f02 --- /dev/null +++ b/src/main/java/net/knarcraft/armoredelytra/metadata/builder/OriginalMetadataBuilder.java @@ -0,0 +1,125 @@ +package net.knarcraft.armoredelytra.metadata.builder; + +import net.knarcraft.armoredelytra.ArmoredElytra; +import net.knarcraft.armoredelytra.container.EnchantmentContainer; +import net.knarcraft.armoredelytra.metadata.NBTEditor; +import net.knarcraft.armoredelytra.metadata.OriginalMetadata; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Objects; +import java.util.function.Predicate; + +/** + * A class for building the combined original metadata for the given items. + */ +public class OriginalMetadataBuilder { + + private final ArmoredElytra plugin; + private final NBTEditor nbtEditor; + + /** + * Instantiates a new original metadata builder + * + * @param plugin

A reference to the plugin class.

+ * @param nbtEditor

A reference to the NBT editor

+ */ + public OriginalMetadataBuilder(ArmoredElytra plugin, NBTEditor nbtEditor) { + this.plugin = plugin; + this.nbtEditor = nbtEditor; + } + + /** + * Gets the merged original metadata for two items. + * + * @param elytra

The input (armored) elytra.

+ * @param armor

The armored elytra or chestplate to be combined with the elytra.

+ * @return

The combined original metadata for the two items.

+ */ + public OriginalMetadata getMergedOriginalMetaData(ItemStack elytra, ItemStack armor) { + OriginalMetadata elytraMetadata = nbtEditor.getOriginalMetadata(elytra); + OriginalMetadata armorMetadata = nbtEditor.getOriginalMetadata(armor); + + // If metadata is missing from one of the items, create new metadata + if (elytraMetadata == null) { + elytraMetadata = createElytraMetadata(elytra); + } + if (armorMetadata == null) { + armorMetadata = createArmorMetadata(armor); + } + + // Merge elytra and armor enchantments + elytraMetadata.getElytraEnchantments().merge(armorMetadata.getElytraEnchantments()); + elytraMetadata.getArmorEnchantments().merge(armorMetadata.getArmorEnchantments()); + + // Use the elytra name from the armor if not set for the elytra + if (useSecondValue(elytraMetadata.getElytraName(), armorMetadata.getElytraName(), (item) -> !item.isBlank())) { + elytraMetadata.setElytraName(Objects.requireNonNull(armorMetadata.getElytraName())); + } + + // Use the armor name from the armor if not set for the elytra + if (useSecondValue(elytraMetadata.getArmorName(), armorMetadata.getArmorName(), (item) -> !item.isBlank())) { + elytraMetadata.setArmorName(Objects.requireNonNull(armorMetadata.getArmorName())); + } + + // Use the elytra lore from the armor if not set for the elytra + if (useSecondValue(elytraMetadata.getElytraLore(), armorMetadata.getElytraLore(), (item) -> !item.isEmpty())) { + elytraMetadata.setElytraLore(Objects.requireNonNull(armorMetadata.getElytraLore())); + } + + // Use the armor lore from the armor if not set for the elytra + if (useSecondValue(elytraMetadata.getArmorLore(), armorMetadata.getArmorLore(), (item) -> !item.isEmpty())) { + elytraMetadata.setArmorLore(Objects.requireNonNull(armorMetadata.getArmorLore())); + } + + return elytraMetadata; + } + + /** + * A test to see if the second value given matches the predicate, and the first one does not. + * + * @param value1

The first value to test.

+ * @param value2

The second value to test.

+ * @param predicate

The predicate to run.

+ * @param

The type of the values.

+ * @return

True if the second value matches the predicate, but the first value does not.

+ */ + private boolean useSecondValue(T value1, T value2, Predicate predicate) { + return (value1 == null || !predicate.test(value1)) && (value2 != null && predicate.test(value2)); + } + + /** + * Creates metadata for the given elytra item. + * + * @param elytra

The elytra to create original metadata for.

+ * @return

The generated metadata.

+ */ + private OriginalMetadata createElytraMetadata(ItemStack elytra) { + OriginalMetadata newMetadata = new OriginalMetadata(); + newMetadata.setElytraEnchantments(new EnchantmentContainer(elytra.getEnchantments(), plugin)); + ItemMeta meta = NBTEditor.getOrCreateItemMeta(elytra); + if (meta.getLore() != null) { + newMetadata.setElytraLore(meta.getLore()); + } + newMetadata.setElytraName(meta.getDisplayName()); + return newMetadata; + } + + /** + * Creates metadata for the given armor item. + * + * @param armor

The armor to create original metadata for.

+ * @return

The generated metadata.

+ */ + private OriginalMetadata createArmorMetadata(ItemStack armor) { + OriginalMetadata newMetadata = new OriginalMetadata(); + newMetadata.setArmorEnchantments(new EnchantmentContainer(armor.getEnchantments(), plugin)); + ItemMeta meta = NBTEditor.getOrCreateItemMeta(armor); + if (meta.getLore() != null) { + newMetadata.setArmorLore(meta.getLore()); + } + newMetadata.setArmorName(meta.getDisplayName()); + return newMetadata; + } + +} diff --git a/src/main/java/net/knarcraft/armoredelytra/update/UpdateManager.java b/src/main/java/net/knarcraft/armoredelytra/update/UpdateManager.java index 489ae81..d1919fb 100644 --- a/src/main/java/net/knarcraft/armoredelytra/update/UpdateManager.java +++ b/src/main/java/net/knarcraft/armoredelytra/update/UpdateManager.java @@ -76,5 +76,5 @@ public final class UpdateManager { } } } - + } diff --git a/src/test/java/net/knarcraft/armoredelytra/util/GenericUtilTest.java b/src/test/java/net/knarcraft/armoredelytra/util/GenericUtilTest.java index bd83c17..866e265 100644 --- a/src/test/java/net/knarcraft/armoredelytra/util/GenericUtilTest.java +++ b/src/test/java/net/knarcraft/armoredelytra/util/GenericUtilTest.java @@ -14,5 +14,5 @@ public class GenericUtilTest { Assertions.assertEquals("t", GenericUtil.snakeToCamelCase("_T_")); Assertions.assertEquals("testcase", GenericUtil.snakeToCamelCase("TeStCase")); } - + }