diff --git a/patches/api/0497-WIP-DataComponent-API.patch b/patches/api/0497-WIP-DataComponent-API.patch index 98ddaef26f..f7b16e5cee 100644 --- a/patches/api/0497-WIP-DataComponent-API.patch +++ b/patches/api/0497-WIP-DataComponent-API.patch @@ -4018,7 +4018,7 @@ index b4ef3133fdd9d79a3381cf8f659ff561ab2b4fad..d3c9fb2fd625ed6ae4882c3b16b86f32 * Get the object by its key. * diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index b59222b8c262545d100a9fd28b3bf1d2a4cf4eb0..aafbf87d21b4d40c3635f7e9323a92ce61fbc45b 100644 +index b59222b8c262545d100a9fd28b3bf1d2a4cf4eb0..8071624df30b36e2f96dcf7a0b2ada20179b1641 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -1,10 +1,11 @@ @@ -4187,11 +4187,11 @@ index b59222b8c262545d100a9fd28b3bf1d2a4cf4eb0..aafbf87d21b4d40c3635f7e9323a92ce + * This is useful if you are wanting to ignore certain properties of itemstacks, such as durability. + * + * @param item the item to compare -+ * @param exclude the data component types to ignore ++ * @param excludeTypes the data component types to ignore + * @return {@code true} if the provided item is equal, ignoring the provided components + */ -+ public boolean matchesWithoutData(final @NotNull ItemStack item, final @NotNull io.papermc.paper.registry.set.RegistrySet exclude) { -+ return this.matchesWithoutData(item, exclude, false); ++ public boolean matchesWithoutData(final @NotNull ItemStack item, final @NotNull io.papermc.paper.registry.set.RegistrySet excludeTypes) { ++ return this.matchesWithoutData(item, excludeTypes, false); + } + + /** @@ -4199,12 +4199,12 @@ index b59222b8c262545d100a9fd28b3bf1d2a4cf4eb0..aafbf87d21b4d40c3635f7e9323a92ce + * This is useful if you are wanting to ignore certain properties of itemstacks, such as durability. + * + * @param item the item to compare -+ * @param exclude the data component types to ignore ++ * @param excludeTypes the data component types to ignore + * @param ignoreCount ignore the count of the item + * @return {@code true} if the provided item is equal, ignoring the provided components + */ -+ public boolean matchesWithoutData(final @NotNull ItemStack item, final @NotNull io.papermc.paper.registry.set.RegistrySet exclude, final boolean ignoreCount) { -+ return this.craftDelegate.matchesWithoutData(item, exclude, ignoreCount); ++ public boolean matchesWithoutData(final @NotNull ItemStack item, final @NotNull io.papermc.paper.registry.set.RegistrySet excludeTypes, final boolean ignoreCount) { ++ return this.craftDelegate.matchesWithoutData(item, excludeTypes, ignoreCount); + } + // Paper end - data component API } diff --git a/patches/server/1058-WIP-DataComponent-API.patch b/patches/server/1058-WIP-DataComponent-API.patch index cca3c8117b..74f390591b 100644 --- a/patches/server/1058-WIP-DataComponent-API.patch +++ b/patches/server/1058-WIP-DataComponent-API.patch @@ -3854,7 +3854,7 @@ index 12220f78ffaf06433ada72fd0c7f22b97d55287d..e1c6f514f45a02d7401b5390aefd0a49 // data-drivens entry(Registries.STRUCTURE, RegistryKey.STRUCTURE, Structure.class, CraftStructure::new).delayed(), diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 756c73a401437566258813946fa10c7caa8f2469..528b6705b714376766bcab507781323a7a3e90b9 100644 +index 756c73a401437566258813946fa10c7caa8f2469..4fe0543754ba644a7ce2231ec267007215f823c4 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java @@ -206,7 +206,7 @@ public final class CraftItemStack extends ItemStack { @@ -3948,7 +3948,7 @@ index 756c73a401437566258813946fa10c7caa8f2469..528b6705b714376766bcab507781323a } static Map getEnchantments(net.minecraft.world.item.ItemStack item) { -@@ -526,4 +545,140 @@ public final class CraftItemStack extends ItemStack { +@@ -526,4 +545,129 @@ public final class CraftItemStack extends ItemStack { return this.pdcView; } // Paper end - pdc @@ -4033,58 +4033,47 @@ index 756c73a401437566258813946fa10c7caa8f2469..528b6705b714376766bcab507781323a + } + + @Override -+ public boolean matchesWithoutData(final ItemStack item, final io.papermc.paper.registry.set.RegistrySet exclude, final boolean ignoreCount) { ++ public boolean matchesWithoutData(final ItemStack item, final io.papermc.paper.registry.set.RegistrySet excludeTypes, final boolean ignoreCount) { + // Extracted from base equals -+ if (!(item instanceof final org.bukkit.inventory.ItemStack bukkit)) return false; -+ final CraftItemStack craftStack = getCraftStack(bukkit); ++ final CraftItemStack craftStack = getCraftStack(item); + if (this.handle == craftStack.handle) return true; -+ else if (this.handle == null || craftStack.handle == null) return false; -+ else if (this.handle.isEmpty() && craftStack.handle.isEmpty()) return true; -+ else { -+ net.minecraft.world.item.ItemStack left = this.handle; -+ net.minecraft.world.item.ItemStack right = craftStack.handle; -+ if (!ignoreCount && left.getCount() != right.getCount()) { -+ return false; -+ } -+ if (!left.is(right.getItem())) { -+ return false; -+ } ++ if (this.handle == null || craftStack.handle == null) return false; ++ if (this.handle.isEmpty() && craftStack.handle.isEmpty()) return true; + -+ // It can be assumed that the prototype is equal since the type is the same. This way all we need to check is the patch -+ -+ // Flatten registry set into registry elements -+ java.util.Collection excludeTypes; -+ if (exclude instanceof io.papermc.paper.registry.set.RegistryKeySet keySet) { -+ excludeTypes = keySet.resolve(org.bukkit.Registry.DATA_COMPONENT_TYPE); -+ } else if (exclude instanceof io.papermc.paper.registry.set.RegistryValueSet valueSet) { -+ excludeTypes = valueSet.values(); -+ } else { -+ throw new UnsupportedOperationException(); -+ } -+ -+ // Collect all the NMS types into a set -+ java.util.Set> skippingTypes = exclude.isEmpty() ? java.util.Set.of() : new java.util.HashSet<>(exclude.size()); // micro op -+ for (io.papermc.paper.datacomponent.DataComponentType api : excludeTypes) { -+ net.minecraft.core.component.DataComponentType type = io.papermc.paper.datacomponent.PaperComponentType.bukkitToMinecraft(api); -+ skippingTypes.add(type); -+ } -+ -+ // Iterate over the entries in the left item, where we will then check to make sure the right entry has the same value. -+ // But, ignore if in our special set -+ java.util.Set, java.util.Optional>> rightEntries = right.getComponentsPatch().entrySet(); -+ for (java.util.Map.Entry, java.util.Optional> leftEntry : left.getComponentsPatch().entrySet()) { -+ // This type should be skipped! -+ if (skippingTypes.contains(leftEntry.getKey())) { -+ continue; -+ } -+ // This will check if the right value contains the KEY & VALUE of leftEntry -+ if (!rightEntries.contains(leftEntry)) { -+ return false; -+ } -+ } -+ -+ return true; ++ net.minecraft.world.item.ItemStack left = this.handle; ++ net.minecraft.world.item.ItemStack right = craftStack.handle; ++ if (!ignoreCount && left.getCount() != right.getCount()) { ++ return false; + } ++ if (!left.is(right.getItem())) { ++ return false; ++ } ++ ++ // It can be assumed that the prototype is equal since the type is the same. This way all we need to check is the patch ++ ++ // Fast path when excluded types is empty to not flatten the set ++ if (excludeTypes.isEmpty()) { ++ return left.getComponentsPatch().equals(right.getComponentsPatch()); ++ } ++ ++ // Flatten registry set into registry elements ++ java.util.Collection exclude; ++ if (excludeTypes instanceof io.papermc.paper.registry.set.RegistryKeySet keySet) { ++ exclude = keySet.resolve(org.bukkit.Registry.DATA_COMPONENT_TYPE); ++ } else if (excludeTypes instanceof io.papermc.paper.registry.set.RegistryValueSet valueSet) { ++ exclude = valueSet.values(); ++ } else { ++ throw new UnsupportedOperationException(); ++ } ++ ++ // Collect all the NMS types into a set ++ java.util.Set> skippingTypes = new java.util.HashSet<>(exclude.size()); ++ for (io.papermc.paper.datacomponent.DataComponentType api : exclude) { ++ skippingTypes.add(io.papermc.paper.datacomponent.PaperComponentType.bukkitToMinecraft(api)); ++ } ++ ++ // Check the patch by first stripping excluded types and then compare the trimmed patches ++ return left.getComponentsPatch().forget(skippingTypes::contains).equals(right.getComponentsPatch().forget(skippingTypes::contains)); + } + + // Paper end - data component API @@ -4173,10 +4162,10 @@ index 0000000000000000000000000000000000000000..852ab097181491735fb9ee5ee4f70e4c +io.papermc.paper.datacomponent.item.consumable.ConsumableTypesBridgeImpl diff --git a/src/test/java/io/papermc/paper/item/ItemStackDataComponentEqualsTest.java b/src/test/java/io/papermc/paper/item/ItemStackDataComponentEqualsTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..451ebde6856d2f128c623c42bf8f88d31683f407 +index 0000000000000000000000000000000000000000..6a287dcd4b42fa494117ae3f07def596c69d29da --- /dev/null +++ b/src/test/java/io/papermc/paper/item/ItemStackDataComponentEqualsTest.java -@@ -0,0 +1,85 @@ +@@ -0,0 +1,94 @@ +package io.papermc.paper.item; + +import io.papermc.paper.datacomponent.DataComponentTypes; @@ -4188,7 +4177,6 @@ index 0000000000000000000000000000000000000000..451ebde6856d2f128c623c42bf8f88d3 +import org.bukkit.inventory.ItemStack; +import org.bukkit.support.environment.AllFeatures; +import org.junit.jupiter.api.Assertions; -+import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +@AllFeatures @@ -4230,7 +4218,6 @@ index 0000000000000000000000000000000000000000..451ebde6856d2f128c623c42bf8f88d3 + } + + @Test -+ @Disabled // todo look into that + public void testEqualWithoutComponent() { + ItemStack item1 = ItemStack.of(Material.STONE, 1); + @@ -4241,6 +4228,17 @@ index 0000000000000000000000000000000000000000..451ebde6856d2f128c623c42bf8f88d3 + } + + @Test ++ public void testEqualRemoveComponent() { ++ ItemStack item1 = ItemStack.of(Material.STONE, 1); ++ item1.unsetData(DataComponentTypes.MAX_STACK_SIZE); ++ ++ ItemStack item2 = ItemStack.of(Material.STONE, 1); ++ item2.unsetData(DataComponentTypes.MAX_STACK_SIZE); ++ ++ Assertions.assertTrue(item1.matchesWithoutData(item2, RegistrySet.keySet(RegistryKey.DATA_COMPONENT_TYPE))); ++ } ++ ++ @Test + public void testEqualIncludeComponentIgnoreSize() { + ItemStack item1 = ItemStack.of(Material.STONE, 2); + item1.setData(DataComponentTypes.MAX_STACK_SIZE, 1);