From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Sat, 6 Jan 2024 14:31:00 +0100
Subject: [PATCH] Fixup NamespacedKey handling


diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
@@ -0,0 +0,0 @@ public class LoomMenu extends AbstractContainerMenu {
         return stillValid(this.access, player, Blocks.LOOM);
     }
 
+    private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper - handle custom banner pattern, skip the event
+    private static boolean PRINTED_PATTERN_TYPE_NAG = false; // Paper - handle custom banner pattern, skip the event
+
     @Override
     public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) {
         if (id >= 0 && id < this.selectablePatterns.size()) {
+            // Paper start - handle custom banner pattern, skip the event (todo remove once this is supported)
+            java.util.Optional<org.bukkit.block.banner.PatternType> patternType = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.BANNER_PATTERN, this.selectablePatterns.get(id));
+            if (patternType.isEmpty()) {
+                if (!PRINTED_PATTERN_TYPE_NAG) {
+                    LOGGER.warn("A datapack added a custom banner pattern, those are not supported yet in the API, skipping the PlayerLoomPatternSelectEvent for {}.", player.getScoreboardName());
+                    PRINTED_PATTERN_TYPE_NAG = true;
+                }
+                this.selectedBannerPatternIndex.set(id);
+                this.setupResultSlot((Holder) this.selectablePatterns.get(id));
+                return true;
+            }
+            // Paper end - handle custom banner pattern
+
             // Paper start - Add PlayerLoomPatternSelectEvent
             int selectablePatternIndex = id;
-            io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.craftbukkit.block.banner.CraftPatternType.minecraftHolderToBukkit((this.selectablePatterns.get(selectablePatternIndex))));
+            io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), patternType.get());
             if (!event.callEvent()) {
                 player.containerMenu.sendAllDataToRemote();
                 return false;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java b/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java
@@ -0,0 +0,0 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
     }
 
     public static org.bukkit.loot.LootTable minecraftToBukkit(ResourceKey<LootTable> minecraft) {
-        return (minecraft == null) ? null : Bukkit.getLootTable(CraftLootTable.minecraftToBukkitKey(minecraft));
+        return (minecraft == null || minecraft.location().getPath().isEmpty()) ? null : Bukkit.getLootTable(CraftLootTable.minecraftToBukkitKey(minecraft)); // Paper - fix some NamespacedKey parsing
     }
 
     public static NamespacedKey minecraftToBukkitKey(ResourceKey<LootTable> minecraft) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -0,0 +0,0 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
                 + ", this can happen if a plugin creates its own registry entry with out properly registering it.");
     }
 
+    // Paper start - fixup upstream being dum
+    public static <T extends org.bukkit.Keyed, M> java.util.Optional<T> unwrapAndConvertHolder(final io.papermc.paper.registry.RegistryKey<T> registryKey, final Holder<M> value) {
+        return unwrapAndConvertHolder(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(registryKey), value);
+    }
+
+    public static <T extends org.bukkit.Keyed, M> java.util.Optional<T> unwrapAndConvertHolder(final Registry<T> registry, final Holder<M> value) {
+        return value.unwrapKey().map(key -> registry.get(CraftNamespacedKey.fromMinecraft(key.location())));
+    }
+    // Paper end - fixup upstream being dum
+
     // Paper - move to PaperRegistries
 
     // Paper - NOTE: As long as all uses of the method below relate to *serialization* via ConfigurationSerializable, it's fine
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java
@@ -0,0 +0,0 @@ public class CraftAttribute {
         string = FieldRename.convertAttributeName(ApiVersion.CURRENT, string);
         string = string.toLowerCase(Locale.ROOT);
         NamespacedKey key = NamespacedKey.fromString(string);
+        if (key == null) return null; // Paper - Fixup NamespacedKey handling
 
         // Now also convert from when keys where saved
         return CraftRegistry.get(Registry.ATTRIBUTE, key, ApiVersion.CURRENT);
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java
@@ -0,0 +0,0 @@ public class CraftBanner extends CraftBlockEntityState<BannerBlockEntity> implem
         if (banner.getPatterns() != null) {
             for (int i = 0; i < banner.getPatterns().layers().size(); i++) {
                 BannerPatternLayers.Layer p = banner.getPatterns().layers().get(i);
-                this.patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.color().getId()), CraftPatternType.minecraftHolderToBukkit(p.pattern())));
+                // Paper start - fix upstream not handling custom banner pattern
+                java.util.Optional<org.bukkit.block.banner.PatternType> type = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.BANNER_PATTERN, p.pattern());
+                if (type.isEmpty()) continue;
+                this.patterns.add(new Pattern(DyeColor.getByWoolData((byte) p.color().getId()), type.get()));
+                // Paper end
             }
         }
     }
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
@@ -0,0 +0,0 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
         super(tag);
 
         getOrEmpty(tag, CraftMetaArmor.TRIM).ifPresent((trimCompound) -> {
-            TrimMaterial trimMaterial = CraftTrimMaterial.minecraftHolderToBukkit(trimCompound.material());
-            TrimPattern trimPattern = CraftTrimPattern.minecraftHolderToBukkit(trimCompound.pattern());
+            TrimMaterial trimMaterial = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_MATERIAL, trimCompound.material()).orElse(null); // Paper - fix upstream not being correct
+            TrimPattern trimPattern = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_PATTERN, trimCompound.pattern()).orElse(null); // Paper - fix upstream not being correct
+            if (trimMaterial == null || trimPattern == null) return; // Paper - just delete the trim because upstream is not doing this right
 
             this.trim = new ArmorTrim(trimMaterial, trimPattern);
 
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
@@ -0,0 +0,0 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
             for (int i = 0; i < Math.min(patterns.size(), 20); i++) {
                 BannerPatternLayers.Layer p = patterns.get(i);
                 DyeColor color = DyeColor.getByWoolData((byte) p.color().getId());
-                PatternType pattern = CraftPatternType.minecraftHolderToBukkit(p.pattern());
+                PatternType pattern = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.BANNER_PATTERN, p.pattern()).orElse(null); // Paper - fix upstream not handling custom banner pattern
 
                 if (color != null && pattern != null) {
                     this.patterns.add(new Pattern(color, pattern));
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
@@ -0,0 +0,0 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst
         super(tag);
 
         getOrEmpty(tag, CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT).ifPresent((instrument) -> {
-            this.instrument = CraftMusicInstrument.minecraftHolderToBukkit(instrument);
+            this.instrument = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.INSTRUMENT, instrument).orElse(null); // Paper - fix upstream not handling custom instruments
         });
     }
 
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java
@@ -0,0 +0,0 @@ public class CraftPotionType implements PotionType.InternalPotionData {
         string = FieldRename.convertPotionTypeName(ApiVersion.CURRENT, string);
         string = string.toLowerCase(Locale.ROOT);
         NamespacedKey key = NamespacedKey.fromString(string);
+        if (key == null) return null; // Paper - Fixup NamespacedKey handling
 
         // Now also convert from when keys where saved
         return CraftRegistry.get(Registry.POTION, key, ApiVersion.CURRENT);
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java
@@ -0,0 +0,0 @@ public final class CraftNamespacedKey {
             return null;
         }
         ResourceLocation minecraft = ResourceLocation.tryParse(string);
-        return (minecraft == null) ? null : CraftNamespacedKey.fromMinecraft(minecraft);
+        return (minecraft == null || minecraft.getPath().isEmpty()) ? null : CraftNamespacedKey.fromMinecraft(minecraft); // Paper - Bukkit's parser does not match Vanilla for empty paths
     }
 
     public static NamespacedKey fromString(String string) {
