From b0df4fc813b747ab4df6f928e93ecb6a280103ae Mon Sep 17 00:00:00 2001 From: Bukkit/Spigot Date: Mon, 3 Jun 2024 07:15:10 +1000 Subject: [PATCH] #1020: Cast instead of using #typed when getting BlockType and ItemType to better work with testing / mocks By: DerFrZocker --- .../src/main/java/org/bukkit/block/BlockType.java | 7 ++++--- .../main/java/org/bukkit/inventory/ItemType.java | 7 ++++--- .../test/java/org/bukkit/support/TestServer.java | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/block/BlockType.java b/paper-api/src/main/java/org/bukkit/block/BlockType.java index 95cedd536f..2fd6f52ad6 100644 --- a/paper-api/src/main/java/org/bukkit/block/BlockType.java +++ b/paper-api/src/main/java/org/bukkit/block/BlockType.java @@ -3409,11 +3409,12 @@ public interface BlockType extends Keyed, Translatable { // @NotNull - private static BlockType.Typed getBlockType(@NotNull String key) { + private static B getBlockType(@NotNull String key) { NamespacedKey namespacedKey = NamespacedKey.minecraft(key); - BlockType.Typed blockType = Registry.BLOCK.get(namespacedKey).typed(); + BlockType blockType = Registry.BLOCK.get(namespacedKey); Preconditions.checkNotNull(blockType, "No BlockType found for %s. This is a bug.", namespacedKey); - return (BlockType.Typed) blockType; + // Cast instead of using BlockType#typed, since block type can be a mock during testing and would return null + return (B) blockType; } /** diff --git a/paper-api/src/main/java/org/bukkit/inventory/ItemType.java b/paper-api/src/main/java/org/bukkit/inventory/ItemType.java index 8dc744f253..2dec823442 100644 --- a/paper-api/src/main/java/org/bukkit/inventory/ItemType.java +++ b/paper-api/src/main/java/org/bukkit/inventory/ItemType.java @@ -2257,11 +2257,12 @@ public interface ItemType extends Keyed, Translatable { // @NotNull - private static Typed getItemType(@NotNull String key) { + private static M getItemType(@NotNull String key) { NamespacedKey namespacedKey = NamespacedKey.minecraft(key); - Typed itemType = Registry.ITEM.get(namespacedKey).typed(); + ItemType itemType = Registry.ITEM.get(namespacedKey); Preconditions.checkNotNull(itemType, "No ItemType found for %s. This is a bug.", namespacedKey); - return (Typed) itemType; + // Cast instead of using ItemType#typed, since item type can be a mock during testing and would return null + return (M) itemType; } /** diff --git a/paper-api/src/test/java/org/bukkit/support/TestServer.java b/paper-api/src/test/java/org/bukkit/support/TestServer.java index 79173d6ed8..5709d52ed4 100644 --- a/paper-api/src/test/java/org/bukkit/support/TestServer.java +++ b/paper-api/src/test/java/org/bukkit/support/TestServer.java @@ -3,6 +3,7 @@ package org.bukkit.support; import static org.mockito.Mockito.*; import java.util.HashMap; import java.util.Iterator; +import java.util.Locale; import java.util.Map; import java.util.logging.Logger; import java.util.stream.Stream; @@ -38,12 +39,22 @@ public final class TestServer { when(instance.getBukkitVersion()).thenReturn("BukkitVersion_" + TestServer.class.getPackage().getImplementationVersion()); Map, Registry> registers = new HashMap<>(); - when(instance.getRegistry(any())).then(invocationOnMock -> registers.computeIfAbsent(invocationOnMock.getArgument(0), aClass -> new Registry() { + when(instance.getRegistry(any())).then(invocationOnMock -> registers.computeIfAbsent(invocationOnMock.getArgument(0), aClass -> new Registry<>() { private final Map cache = new HashMap<>(); @Override public Keyed get(NamespacedKey key) { - return cache.computeIfAbsent(key, key2 -> mock(aClass, withSettings().stubOnly())); + Class theClass; + // Some registries have extra Typed classes such as BlockType and ItemType. + // To avoid class cast exceptions during init mock the Typed class. + // To get the correct class, we just use the field type. + try { + theClass = (Class) aClass.getField(key.getKey().toUpperCase(Locale.ROOT).replace('.', '_')).getType(); + } catch (ClassCastException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + + return cache.computeIfAbsent(key, key2 -> mock(theClass, withSettings().stubOnly())); } @NotNull