diff --git a/pom.xml b/pom.xml index 3147445..772fa0b 100644 --- a/pom.xml +++ b/pom.xml @@ -41,31 +41,27 @@ - - codemc-snapshots - https://repo.codemc.org/repository/maven-snapshots - - codemc-releases - https://repo.codemc.org/repository/maven-releases + bentoboxworld + https://repo.codemc.org/repository/bentoboxworld/ UTF-8 UTF-8 - 17 + 21 2.0.9 - 1.21.1-R0.1-SNAPSHOT - 2.5.1-SNAPSHOT + 1.21.3-R0.1-SNAPSHOT + 2.7.1-SNAPSHOT ${build.version}-SNAPSHOT -LOCAL - 2.7.3 + 2.8.0 BentoBoxWorld_Boxed bentobox-world @@ -119,6 +115,10 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots + + bentoboxworld + https://repo.codemc.org/repository/bentoboxworld/ + codemc https://repo.codemc.org/repository/maven-snapshots/ @@ -185,12 +185,6 @@ ${spigot.version} provided - - org.spigotmc..... - spigot - 1.21-R0.1-SNAPSHOT - provided - org.spigotmc...... spigot diff --git a/src/main/java/world/bentobox/boxed/generators/biomes/AbstractCopyBiomeProvider.java b/src/main/java/world/bentobox/boxed/generators/biomes/AbstractCopyBiomeProvider.java index e7a0167..2742599 100644 --- a/src/main/java/world/bentobox/boxed/generators/biomes/AbstractCopyBiomeProvider.java +++ b/src/main/java/world/bentobox/boxed/generators/biomes/AbstractCopyBiomeProvider.java @@ -1,8 +1,8 @@ package world.bentobox.boxed.generators.biomes; -import java.util.Arrays; import java.util.List; +import org.bukkit.Registry; import org.bukkit.World.Environment; import org.bukkit.block.Biome; import org.bukkit.generator.BiomeProvider; @@ -10,8 +10,6 @@ import org.bukkit.generator.WorldInfo; import org.bukkit.util.Vector; import org.eclipse.jdt.annotation.Nullable; -import com.google.common.base.Enums; - import world.bentobox.bentobox.BentoBox; import world.bentobox.boxed.Boxed; import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator; @@ -56,7 +54,7 @@ public abstract class AbstractCopyBiomeProvider extends BiomeProvider { @Override public List getBiomes(WorldInfo worldInfo) { // Return all of them for now! - return Arrays.stream(Biome.values()).filter(b -> !b.equals(Biome.CUSTOM)).filter(b -> !b.equals(Enums.getIfPresent(Biome.class, "CHERRY_GROVE").orNull())).toList(); + return Registry.BIOME.stream().filter(b -> !b.equals(Biome.CUSTOM)).toList(); } } diff --git a/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java b/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java index ac10713..36d3db9 100644 --- a/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java +++ b/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java @@ -11,6 +11,7 @@ import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; +import org.bukkit.Registry; import org.bukkit.World.Environment; import org.bukkit.block.Biome; import org.bukkit.block.BlockFace; @@ -21,8 +22,6 @@ import org.bukkit.generator.WorldInfo; import org.bukkit.util.Vector; import org.eclipse.jdt.annotation.NonNull; -import com.google.common.base.Enums; - import world.bentobox.boxed.Boxed; /** @@ -1129,7 +1128,7 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { } public static double convertToY(double x) { - x = Math.max(-1, Math.min(1, x)); // Clamp value + x = Math.clamp(x, -1, 1); if (x >= -1 && x < -0.5) { return 2 * x + 1; } else if (x >= -0.5 && x < 0) { @@ -1196,7 +1195,7 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { @Override public List getBiomes(WorldInfo worldInfo) { // Return all of them for now! - return Arrays.stream(Biome.values()).filter(b -> !b.equals(Biome.CUSTOM)).toList(); + return Registry.BIOME.stream().filter(b -> !b.equals(Biome.CUSTOM)).toList(); } /** @@ -1215,7 +1214,7 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { if (split.length == 2) { try { double d = Double.parseDouble(split[0]); - Biome biome = Enums.getIfPresent(Biome.class, split[1].toUpperCase(Locale.ENGLISH)).orNull(); + Biome biome = Biome.valueOf(split[1].toUpperCase(Locale.ENGLISH)); if (biome == null) { addon.logError(split[1].toUpperCase(Locale.ENGLISH) + " is an unknown biome on this server."); result.put(d, Biome.CUSTOM); diff --git a/src/main/java/world/bentobox/boxed/nms/v1_21_3_R0_1_SNAPSHOT/GetMetaData.java b/src/main/java/world/bentobox/boxed/nms/v1_21_3_R0_1_SNAPSHOT/GetMetaData.java new file mode 100644 index 0000000..0cf1131 --- /dev/null +++ b/src/main/java/world/bentobox/boxed/nms/v1_21_3_R0_1_SNAPSHOT/GetMetaData.java @@ -0,0 +1,5 @@ +package world.bentobox.boxed.nms.v1_21_3_R0_1_SNAPSHOT; + +public class GetMetaData extends world.bentobox.boxed.nms.v1_21_R0_1_SNAPSHOT.GetMetaData { + // Identical to 1.21 +} \ No newline at end of file diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index 3b7a42a..d048714 100755 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -1,7 +1,7 @@ name: Boxed main: world.bentobox.boxed.Boxed version: ${version}${build.number} -api-version: 2.5.1 +api-version: 2.7.1 metrics: true icon: "COMPOSTER" repository: "BentoBoxWorld/Boxed" diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index b93c28a..e609dc8 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: BentoBox-Boxed main: world.bentobox.boxed.BoxedPladdon version: ${project.version}${build.number} -api-version: "1.19" +api-version: "1.21" authors: [tastybento] contributors: ["The BentoBoxWorld Community"] diff --git a/src/test/java/world/bentobox/boxed/listeners/EnderPearlListenerTest.java b/src/test/java/world/bentobox/boxed/listeners/EnderPearlListenerTest.java index 0522a4f..228def6 100644 --- a/src/test/java/world/bentobox/boxed/listeners/EnderPearlListenerTest.java +++ b/src/test/java/world/bentobox/boxed/listeners/EnderPearlListenerTest.java @@ -35,6 +35,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.util.BoundingBox; import org.bukkit.util.Vector; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,6 +56,7 @@ import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.util.Util; import world.bentobox.boxed.Boxed; import world.bentobox.boxed.Settings; +import world.bentobox.boxed.mocks.ServerMocks; /** * @author tastybento @@ -102,7 +104,7 @@ public class EnderPearlListenerTest { */ @Before public void setUp() throws Exception { - + ServerMocks.newServer(); // Set up plugin plugin = mock(BentoBox.class); Whitebox.setInternalState(BentoBox.class, "instance", plugin); @@ -170,6 +172,13 @@ public class EnderPearlListenerTest { epl = new EnderPearlListener(addon); } + @After + public void tearDown() { + ServerMocks.unsetBukkitServer(); + User.clearUsers(); + Mockito.framework().clearInlineMocks(); + } + /** * Test method for {@link world.bentobox.boxed.listeners.EnderPearlListener#EnderPearlListener(world.bentobox.boxed.Boxed)}. */ diff --git a/src/test/java/world/bentobox/boxed/mocks/ServerMocks.java b/src/test/java/world/bentobox/boxed/mocks/ServerMocks.java new file mode 100644 index 0000000..a4f2f40 --- /dev/null +++ b/src/test/java/world/bentobox/boxed/mocks/ServerMocks.java @@ -0,0 +1,118 @@ +package world.bentobox.boxed.mocks; + +import static org.mockito.ArgumentMatchers.notNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +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; +import org.bukkit.Keyed; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; +import org.bukkit.Server; +import org.bukkit.Tag; +import org.bukkit.UnsafeValues; +import org.eclipse.jdt.annotation.NonNull; + +public final class ServerMocks { + + public static @NonNull Server newServer() { + Server mock = mock(Server.class); + + Logger noOp = mock(Logger.class); + when(mock.getLogger()).thenReturn(noOp); + when(mock.isPrimaryThread()).thenReturn(true); + + // Unsafe + UnsafeValues unsafe = mock(UnsafeValues.class); + when(mock.getUnsafe()).thenReturn(unsafe); + + // 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. + Map, Object> registers = new HashMap<>(); + + doAnswer(invocationGetRegistry -> registers.computeIfAbsent(invocationGetRegistry.getArgument(0), clazz -> { + Registry registry = mock(Registry.class); + 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 + // functional is to re-mock Tag#getValues. + doAnswer(invocationGetTag -> { + Tag tag = mock(Tag.class); + doReturn(invocationGetTag.getArgument(1)).when(tag).getKey(); + doReturn(Set.of()).when(tag).getValues(); + doAnswer(invocationIsTagged -> { + Keyed keyed = invocationIsTagged.getArgument(0); + Class type = invocationGetTag.getArgument(2); + if (!type.isAssignableFrom(keyed.getClass())) { + return null; + } + // Since these are mocks, the exact instance might not be equal. Consider equal keys equal. + return tag.getValues().contains(keyed) + || tag.getValues().stream().anyMatch(value -> value.getKey().equals(keyed.getKey())); + }).when(tag).isTagged(notNull()); + 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; + } + + public static void unsetBukkitServer() { + try { + Field server = Bukkit.class.getDeclaredField("server"); + server.setAccessible(true); + server.set(null, null); + } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private ServerMocks() { + } + +} \ No newline at end of file