From bb9546544d8667794677b09e06eacd601b92622f Mon Sep 17 00:00:00 2001 From: Jikoo Date: Thu, 13 Jun 2024 21:35:47 -0400 Subject: [PATCH] Update dependencies, require 1.20.6 --- pom.xml | 4 +- src/main/resources/plugin.yml | 2 +- .../enchantableblocks/mock/ServerMocks.java | 62 +++++++++++++------ .../mock/inventory/ItemFactoryMocks.java | 1 - 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 422207d..a6815b0 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ org.spigotmc spigot-api - 1.20.6-R0.1-SNAPSHOT + 1.21-R0.1-SNAPSHOT provided @@ -99,7 +99,7 @@ com.github.jikoo planarwrappers - 3.2.2 + 3.2.3 compile diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index d6d4991..5edbafa 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,7 +3,7 @@ name: EnchantableBlocks main: com.github.jikoo.enchantableblocks.EnchantableBlocksPlugin version: ${project.version} author: Jikoo -api-version: "1.18" +api-version: "1.20.6" libraries: - it.unimi.dsi:fastutil:${versions.fastutil} diff --git a/src/test/java/com/github/jikoo/enchantableblocks/mock/ServerMocks.java b/src/test/java/com/github/jikoo/enchantableblocks/mock/ServerMocks.java index 2deb1d1..ee9ebc5 100644 --- a/src/test/java/com/github/jikoo/enchantableblocks/mock/ServerMocks.java +++ b/src/test/java/com/github/jikoo/enchantableblocks/mock/ServerMocks.java @@ -5,9 +5,11 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.logging.Logger; import org.bukkit.Bukkit; @@ -17,7 +19,6 @@ import org.bukkit.Server; import org.bukkit.Tag; import org.jetbrains.annotations.NotNull; -import org.mockito.Answers; public final class ServerMocks { @@ -26,28 +27,44 @@ public final class ServerMocks { Logger noOp = mock(Logger.class); when(mock.getLogger()).thenReturn(noOp); + when(mock.isPrimaryThread()).thenReturn(true); // Server must be available before tags can be mocked. Bukkit.setServer(mock); // Bukkit has a lot of static constants referencing registry values. To initialize those, the // registries must be able to be fetched before the classes are touched. - // The mock registry can later be more specifically modified as necessary. - doAnswer(invocationGetRegistry -> { - // This must be mocked here or else Registry will be initialized when mocking it. - Registry registry = mock(); - doAnswer(invocationGetEntry -> { - NamespacedKey key = invocationGetEntry.getArgument(0); - // Set registries to always return a new value so that any constants are initialized. - Class arg = invocationGetRegistry.getArgument(0); - // Deep stubs aren't great, but Bukkit has a lot of nullity checks on new constants. - Keyed keyed = mock(arg, withSettings().defaultAnswer(Answers.RETURNS_DEEP_STUBS)); - doReturn(key).when(keyed).getKey(); - // It may eventually be necessary to stub BlockType#typed() here, but deep stubs work for now. - return keyed; - }).when(registry).get(notNull()); - return registry; - }).when(mock).getRegistry(notNull()); + Map, Object> registers = new HashMap<>(); + + doAnswer(invocationGetRegistry -> + registers.computeIfAbsent(invocationGetRegistry.getArgument(0), clazz -> { + Registry registry = mock(); + Map cache = new HashMap<>(); + doAnswer(invocationGetEntry -> { + NamespacedKey key = invocationGetEntry.getArgument(0); + // Some classes (like BlockType and ItemType) have extra generics that will be + // erased during runtime calls. To ensure accurate typing, grab the constant's field. + // This approach also allows us to return null for unsupported keys. + Class constantClazz; + try { + //noinspection unchecked + constantClazz = (Class) clazz.getField(key.getKey().toUpperCase( + Locale.ROOT).replace('.', '_')).getType(); + } catch (ClassCastException e) { + throw new RuntimeException(e); + } catch (NoSuchFieldException e) { + return null; + } + + return cache.computeIfAbsent(key, key1 -> { + Keyed keyed = mock(constantClazz); + doReturn(key).when(keyed).getKey(); + return keyed; + }); + }).when(registry).get(notNull()); + return registry; + })) + .when(mock).getRegistry(notNull()); // Tags are dependent on registries, but use a different method. // This will set up blank tags for each constant; all that needs to be done to render them @@ -68,6 +85,15 @@ public final class ServerMocks { return tag; }).when(mock).getTag(notNull(), notNull(), notNull()); + // Once the server is all set up, touch BlockType and ItemType to initialize. + // This prevents issues when trying to access dependent methods from a Material constant. + try { + Class.forName("org.bukkit.inventory.ItemType"); + Class.forName("org.bukkit.block.BlockType"); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + return mock; } diff --git a/src/test/java/com/github/jikoo/enchantableblocks/mock/inventory/ItemFactoryMocks.java b/src/test/java/com/github/jikoo/enchantableblocks/mock/inventory/ItemFactoryMocks.java index bbdd73b..06e3276 100644 --- a/src/test/java/com/github/jikoo/enchantableblocks/mock/inventory/ItemFactoryMocks.java +++ b/src/test/java/com/github/jikoo/enchantableblocks/mock/inventory/ItemFactoryMocks.java @@ -81,7 +81,6 @@ public final class ItemFactoryMocks { when(factory.isApplicable(any(ItemMeta.class), any(Material.class))).thenReturn(true); when(factory.isApplicable(any(ItemMeta.class), any(ItemStack.class))) .thenAnswer(invocation -> factory.isApplicable(invocation.getArgument(0), invocation.getArgument(1, ItemStack.class).getType())); - when(factory.updateMaterial(any(ItemMeta.class), any(Material.class))).thenAnswer(invocation -> invocation.getArgument(1)); return factory; }