Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Co-authored-by: MiniDigger | Martin <admin@minidigger.dev>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Co-authored-by: Shane Freeder <theboyetronic@gmail.com>
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com>
Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
Nassim Jahnke
2025-04-12 17:26:44 +02:00
parent 0767902699
commit f00727c57e
2092 changed files with 50551 additions and 48729 deletions

View File

@@ -7,7 +7,6 @@ import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.JavaOps;
import com.mojang.serialization.JsonOps;
import io.papermc.paper.util.MethodParameterSource;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -35,11 +34,9 @@ import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.apache.commons.lang3.RandomStringUtils;
import org.bukkit.support.RegistryHelper;
import org.bukkit.support.environment.VanillaFeature;
import org.junit.jupiter.api.Test;
@@ -85,7 +82,7 @@ class AdventureCodecsTest {
void testTextColor() {
final TextColor color = color(0x1d38df);
final Tag result = TEXT_COLOR_CODEC.encodeStart(NbtOps.INSTANCE, color).result().orElseThrow();
assertEquals(color.asHexString(), result.getAsString());
assertEquals("\"" + color.asHexString() + "\"", result.toString());
final net.minecraft.network.chat.TextColor nms = net.minecraft.network.chat.TextColor.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
assertEquals(color.value(), nms.getValue());
}
@@ -94,7 +91,7 @@ class AdventureCodecsTest {
void testNamedTextColor() {
final NamedTextColor color = NamedTextColor.BLUE;
final Tag result = TEXT_COLOR_CODEC.encodeStart(NbtOps.INSTANCE, color).result().orElseThrow();
assertEquals(NamedTextColor.NAMES.keyOrThrow(color), result.getAsString());
assertEquals("\"" + NamedTextColor.NAMES.keyOrThrow(color) + "\"", result.toString());
final net.minecraft.network.chat.TextColor nms = net.minecraft.network.chat.TextColor.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
assertEquals(color.value(), nms.getValue());
}
@@ -103,7 +100,7 @@ class AdventureCodecsTest {
void testKey() {
final Key key = key("hello", "there");
final Tag result = KEY_CODEC.encodeStart(NbtOps.INSTANCE, key).result().orElseThrow();
assertEquals(key.asString(), result.getAsString());
assertEquals("\"" + key.asString() + "\"", result.toString());
final ResourceLocation location = ResourceLocation.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
assertEquals(key.asString(), location.toString());
}
@@ -111,37 +108,49 @@ class AdventureCodecsTest {
@ParameterizedTest(name = PARAMETERIZED_NAME)
@EnumSource(value = ClickEvent.Action.class, mode = EnumSource.Mode.EXCLUDE, names = {"OPEN_FILE"})
void testClickEvent(final ClickEvent.Action action) {
final ClickEvent event = ClickEvent.clickEvent(action, RandomStringUtils.randomAlphanumeric(20));
final ClickEvent event = ClickEvent.clickEvent(action, action.name().equals("OPEN_URL") ? "https://google.com" : "1337");
final Tag result = CLICK_EVENT_CODEC.encodeStart(NbtOps.INSTANCE, event).result().orElseThrow();
final net.minecraft.network.chat.ClickEvent nms = net.minecraft.network.chat.ClickEvent.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
assertEquals(event.action().toString(), nms.getAction().getSerializedName());
assertEquals(event.value(), nms.getValue());
assertEquals(event.action().toString(), nms.action().getSerializedName());
switch (nms) {
case net.minecraft.network.chat.ClickEvent.OpenUrl(java.net.URI uri) ->
assertEquals(event.value(), uri.toString());
case net.minecraft.network.chat.ClickEvent.SuggestCommand(String command) ->
assertEquals(event.value(), command);
case net.minecraft.network.chat.ClickEvent.RunCommand(String command) ->
assertEquals(event.value(), command);
case net.minecraft.network.chat.ClickEvent.CopyToClipboard(String value) ->
assertEquals(event.value(), value);
case net.minecraft.network.chat.ClickEvent.ChangePage(int page) ->
assertEquals(event.value(), String.valueOf(page));
default -> throw new AssertionError("Unexpected ClickEvent type: " + nms.getClass());
}
}
@Test
void testShowTextHoverEvent() {
final HoverEvent<Component> hoverEvent = HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, text("hello"));
final Tag result = HOVER_EVENT_CODEC.encodeStart(NbtOps.INSTANCE, hoverEvent).result().orElseThrow();
final net.minecraft.network.chat.HoverEvent nms = net.minecraft.network.chat.HoverEvent.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
assertEquals(hoverEvent.action().toString(), nms.getAction().getSerializedName());
assertNotNull(nms.getValue(net.minecraft.network.chat.HoverEvent.Action.SHOW_TEXT));
final net.minecraft.network.chat.HoverEvent.ShowText nms = (net.minecraft.network.chat.HoverEvent.ShowText) net.minecraft.network.chat.HoverEvent.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
assertEquals(hoverEvent.action().toString(), nms.action().getSerializedName());
assertEquals("hello", nms.value().getString());
}
@Test
void testShowItemHoverEvent() throws IOException {
void testShowItemHoverEvent() {
final ItemStack stack = new ItemStack(Items.PUMPKIN, 3);
stack.set(DataComponents.CUSTOM_NAME, net.minecraft.network.chat.Component.literal("NAME"));
final HoverEvent<HoverEvent.ShowItem> hoverEvent = HoverEvent.showItem(key("minecraft:pumpkin"), 3, PaperAdventure.asAdventure(stack.getComponentsPatch()));
final Tag result = HOVER_EVENT_CODEC.encodeStart(NbtOps.INSTANCE, hoverEvent).result().orElseThrow();
final DataResult<Pair<net.minecraft.network.chat.HoverEvent, Tag>> dataResult = net.minecraft.network.chat.HoverEvent.CODEC.decode(NbtOps.INSTANCE, result);
assertTrue(dataResult.result().isPresent(), () -> dataResult + " result is not present");
final net.minecraft.network.chat.HoverEvent nms = dataResult.result().orElseThrow().getFirst();
assertEquals(hoverEvent.action().toString(), nms.getAction().getSerializedName());
final net.minecraft.network.chat.HoverEvent.ItemStackInfo value = nms.getValue(net.minecraft.network.chat.HoverEvent.Action.SHOW_ITEM);
assertNotNull(value);
assertEquals(hoverEvent.value().count(), value.count);
assertEquals(hoverEvent.value().item().asString(), value.item.unwrapKey().orElseThrow().location().toString());
assertEquals(stack.getComponentsPatch(), value.components);
final net.minecraft.network.chat.HoverEvent.ShowItem nms = (net.minecraft.network.chat.HoverEvent.ShowItem) dataResult.result().orElseThrow().getFirst();
assertEquals(hoverEvent.action().toString(), nms.action().getSerializedName());
final ItemStack item = nms.item();
assertNotNull(item);
assertEquals(hoverEvent.value().count(), item.getCount());
assertEquals(hoverEvent.value().item().asString(), item.getItem().toString());
assertEquals(stack.getComponentsPatch(), item.getComponentsPatch());
}
@Test
@@ -151,12 +160,12 @@ class AdventureCodecsTest {
final Tag result = HOVER_EVENT_CODEC.encodeStart(NbtOps.INSTANCE, hoverEvent).result().orElseThrow();
final DataResult<Pair<net.minecraft.network.chat.HoverEvent, Tag>> dataResult = net.minecraft.network.chat.HoverEvent.CODEC.decode(NbtOps.INSTANCE, result);
assertTrue(dataResult.result().isPresent(), () -> dataResult + " result is not present");
final net.minecraft.network.chat.HoverEvent nms = dataResult.result().orElseThrow().getFirst();
assertEquals(hoverEvent.action().toString(), nms.getAction().getSerializedName());
final net.minecraft.network.chat.HoverEvent.EntityTooltipInfo value = nms.getValue(net.minecraft.network.chat.HoverEvent.Action.SHOW_ENTITY);
final net.minecraft.network.chat.HoverEvent.ShowEntity nms = (net.minecraft.network.chat.HoverEvent.ShowEntity) dataResult.result().orElseThrow().getFirst();
assertEquals(hoverEvent.action().toString(), nms.action().getSerializedName());
final net.minecraft.network.chat.HoverEvent.EntityTooltipInfo value = nms.entity();
assertNotNull(value);
assertEquals(hoverEvent.value().type().asString(), BuiltInRegistries.ENTITY_TYPE.getKey(value.type).toString());
assertEquals(hoverEvent.value().id(), value.id);
assertEquals(hoverEvent.value().id(), value.uuid);
assertEquals("NAME", value.name.orElseThrow().getString());
}

View File

@@ -1,9 +1,10 @@
package io.papermc.paper.command.brigadier;
import ca.spottedleaf.dataconverter.util.CommandArgumentUpgrader;
//import ca.spottedleaf.dataconverter.util.CommandArgumentUpgrader;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
// TODO
@Normal
public class DFUCommandArgumentUpgraderCompatTest {
@@ -11,7 +12,7 @@ public class DFUCommandArgumentUpgraderCompatTest {
public void testCompatibilityWithCommandArgumentUpgrader() {
// The Command argument upgrader has some specific assumptions about the tree, specifically around
// Attempt to construct it and to that degree its tree of commands.
CommandArgumentUpgrader.upgrader_1_20_4_to_1_20_5(999);
//CommandArgumentUpgrader.upgrader_1_20_4_to_1_20_5(999);
}
}

View File

@@ -9,6 +9,7 @@ import io.github.classgraph.ScanResult;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import net.minecraft.world.entity.LivingEntity;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@@ -26,7 +27,7 @@ public class EntitySetItemSlotSilentOverrideTest {
.whitelistPackages("net.minecraft")
.scan()
) {
for (final ClassInfo subclass : scanResult.getSubclasses("net.minecraft.world.entity.LivingEntity")) {
for (final ClassInfo subclass : scanResult.getSubclasses(LivingEntity.class.getName())) {
final MethodInfoList setItemSlot = subclass.getDeclaredMethodInfo("setItemSlot");
if (!setItemSlot.isEmpty()) {
classInfo.add(subclass);

View File

@@ -46,7 +46,7 @@ class EquipmentSlotGroupTest {
@ParameterizedTest
@EnumSource(net.minecraft.world.entity.EquipmentSlotGroup.class)
void testNmsToBukkit(final net.minecraft.world.entity.EquipmentSlotGroup slotGroup) {
final EquipmentSlotGroup apiGroup = CraftEquipmentSlot.getSlot(slotGroup);
final EquipmentSlotGroup apiGroup = CraftEquipmentSlot.getSlotGroup(slotGroup);
assertNotNull(apiGroup, "No api slot group found for " + slotGroup);
assertEquals(apiGroup.toString(), slotGroup.getSerializedName(), "slot group name mismatch");
}

View File

@@ -2,6 +2,7 @@ package io.papermc.paper.item;
import io.papermc.paper.datacomponent.DataComponentTypes;
import java.util.Set;
import io.papermc.paper.datacomponent.item.TooltipDisplay;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@@ -82,11 +83,11 @@ class ItemStackDataComponentEqualsTest {
@Test
public void testAdvancedExample() {
ItemStack oakLeaves = ItemStack.of(Material.OAK_LEAVES, 1);
oakLeaves.setData(DataComponentTypes.HIDE_TOOLTIP);
oakLeaves.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().hideTooltip(true).build());
oakLeaves.setData(DataComponentTypes.MAX_STACK_SIZE, 1);
ItemStack otherOakLeavesItem = ItemStack.of(Material.OAK_LEAVES, 2);
Assertions.assertTrue(oakLeaves.matchesWithoutData(otherOakLeavesItem, Set.of(DataComponentTypes.HIDE_TOOLTIP, DataComponentTypes.MAX_STACK_SIZE), true));
Assertions.assertTrue(oakLeaves.matchesWithoutData(otherOakLeavesItem, Set.of(DataComponentTypes.TOOLTIP_DISPLAY, DataComponentTypes.MAX_STACK_SIZE), true));
}
}

View File

@@ -16,7 +16,7 @@ import io.papermc.paper.datacomponent.item.MapId;
import io.papermc.paper.datacomponent.item.MapItemColor;
import io.papermc.paper.datacomponent.item.PotDecorations;
import io.papermc.paper.datacomponent.item.Tool;
import io.papermc.paper.datacomponent.item.Unbreakable;
import io.papermc.paper.datacomponent.item.TooltipDisplay;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.set.RegistrySet;
@@ -93,38 +93,39 @@ class ItemStackDataComponentTest {
@Test
void testUnbreakable() {
final ItemStack stack = new ItemStack(Material.STONE);
stack.setData(DataComponentTypes.UNBREAKABLE, Unbreakable.unbreakable().showInTooltip(false).build());
stack.setData(DataComponentTypes.UNBREAKABLE);
stack.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().addHiddenComponents(DataComponentTypes.UNBREAKABLE).build());
Assertions.assertTrue(stack.getItemMeta().isUnbreakable());
Assertions.assertTrue(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_UNBREAKABLE));
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_UNBREAKABLE));
stack.unsetData(DataComponentTypes.UNBREAKABLE);
Assertions.assertFalse(stack.getItemMeta().isUnbreakable());
}
@Test
void testHideAdditionalTooltip() {
final ItemStack stack = new ItemStack(Material.STONE);
stack.setData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
Assertions.assertTrue(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
stack.unsetData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
Assertions.assertFalse(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
}
// @Test
// void testHideAdditionalTooltip() {
// final ItemStack stack = new ItemStack(Material.STONE);
// stack.setData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
//
// Assertions.assertTrue(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
// stack.unsetData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP);
// Assertions.assertFalse(stack.getItemMeta().getItemFlags().contains(ItemFlag.HIDE_ADDITIONAL_TOOLTIP));
// }
@Test
void testHideTooltip() {
ItemStack stack = new ItemStack(Material.STONE);
stack.setData(DataComponentTypes.HIDE_TOOLTIP);
stack.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().hideTooltip(true).build());
Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.HIDE_TOOLTIP));
Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.TOOLTIP_DISPLAY) && stack.getData(DataComponentTypes.TOOLTIP_DISPLAY).hideTooltip());
Assertions.assertTrue(stack.getItemMeta().isHideTooltip());
stack.unsetData(DataComponentTypes.HIDE_TOOLTIP);
stack.unsetData(DataComponentTypes.TOOLTIP_DISPLAY);
Assertions.assertFalse(stack.getItemMeta().isHideTooltip());
stack = new ItemStack(Material.STONE);
stack.unsetData(DataComponentTypes.HIDE_TOOLTIP);
stack.unsetData(DataComponentTypes.TOOLTIP_DISPLAY);
Assertions.assertFalse(stack.getItemMeta().isHideTooltip());
Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.HIDE_TOOLTIP));
Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.TOOLTIP_DISPLAY));
}
@Test
@@ -158,7 +159,8 @@ class ItemStackDataComponentTest {
void testItemEnchantments() {
final ItemStack stack = new ItemStack(Material.STONE);
Map<Enchantment, Integer> enchantmentIntegerMap = Map.of(Enchantment.SOUL_SPEED, 1);
stack.setData(DataComponentTypes.ENCHANTMENTS, ItemEnchantments.itemEnchantments(enchantmentIntegerMap, false));
stack.setData(DataComponentTypes.ENCHANTMENTS, ItemEnchantments.itemEnchantments(enchantmentIntegerMap));
stack.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().addHiddenComponents(DataComponentTypes.ENCHANTMENTS).build());
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_ENCHANTS));
Assertions.assertEquals(1, stack.getItemMeta().getEnchantLevel(Enchantment.SOUL_SPEED));
@@ -171,7 +173,8 @@ class ItemStackDataComponentTest {
void testItemAttributes() {
final ItemStack stack = new ItemStack(Material.STONE);
AttributeModifier modifier = new AttributeModifier(NamespacedKey.minecraft("test"), 5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.ANY);
stack.setData(DataComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.itemAttributes().showInTooltip(false).addModifier(Attribute.ATTACK_DAMAGE, modifier).build());
stack.setData(DataComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.itemAttributes().addModifier(Attribute.ATTACK_DAMAGE, modifier).build());
stack.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().addHiddenComponents(DataComponentTypes.ATTRIBUTE_MODIFIERS).build());
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_ATTRIBUTES));
Assertions.assertEquals(modifier, ((List<AttributeModifier>) stack.getItemMeta().getAttributeModifiers(Attribute.ATTACK_DAMAGE)).getFirst());
@@ -271,7 +274,8 @@ class ItemStackDataComponentTest {
void testDyedColor() {
final ItemStack stack = new ItemStack(Material.LEATHER_CHESTPLATE);
Color color = Color.BLUE;
stack.setData(DataComponentTypes.DYED_COLOR, DyedItemColor.dyedItemColor(color, false));
stack.setData(DataComponentTypes.DYED_COLOR, DyedItemColor.dyedItemColor(color));
stack.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().addHiddenComponents(DataComponentTypes.DYED_COLOR).build());
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_DYE));
Assertions.assertEquals(color, ((LeatherArmorMeta) stack.getItemMeta()).getColor());
@@ -302,13 +306,13 @@ class ItemStackDataComponentTest {
@Test
void testTrim() {
final ItemStack stack = new ItemStack(Material.LEATHER_CHESTPLATE);
ItemArmorTrim armorTrim = ItemArmorTrim.itemArmorTrim(new ArmorTrim(TrimMaterial.AMETHYST, TrimPattern.BOLT), false);
ItemArmorTrim armorTrim = ItemArmorTrim.itemArmorTrim(new ArmorTrim(TrimMaterial.AMETHYST, TrimPattern.BOLT)).build();
stack.setData(DataComponentTypes.TRIM, armorTrim);
stack.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().addHiddenComponents(DataComponentTypes.TRIM).build());
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_ARMOR_TRIM));
Assertions.assertEquals(armorTrim.armorTrim(), ((ArmorMeta) stack.getItemMeta()).getTrim());
stack.unsetData(DataComponentTypes.TRIM);
Assertions.assertFalse(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_ARMOR_TRIM));
Assertions.assertFalse(((ArmorMeta) stack.getItemMeta()).hasTrim());
}
@@ -365,8 +369,7 @@ class ItemStackDataComponentTest {
void testJukeboxWithEitherHolder() {
final net.minecraft.world.item.ItemStack internalStack = new net.minecraft.world.item.ItemStack(Items.STONE);
internalStack.set(DataComponents.JUKEBOX_PLAYABLE, new net.minecraft.world.item.JukeboxPlayable(
new EitherHolder<>(RegistryHelper.getRegistry().lookupOrThrow(Registries.JUKEBOX_SONG).getOrThrow(JukeboxSongs.FIVE)),
true
new EitherHolder<>(RegistryHelper.getRegistry().lookupOrThrow(Registries.JUKEBOX_SONG).getOrThrow(JukeboxSongs.FIVE))
));
final ItemStack apiStack = CraftItemStack.asBukkitCopy(internalStack);

View File

@@ -1,26 +0,0 @@
package io.papermc.paper.scoreboard;
import org.bukkit.craftbukkit.scoreboard.CraftScoreboardTranslations;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@Normal
public class DisplaySlotTest {
@Test
public void testBukkitToMinecraftDisplaySlots() {
for (DisplaySlot bukkitSlot : DisplaySlot.values()) {
assertNotNull(CraftScoreboardTranslations.fromBukkitSlot(bukkitSlot));
}
}
@Test
public void testMinecraftToBukkitDisplaySlots() {
for (net.minecraft.world.scores.DisplaySlot nmsSlot : net.minecraft.world.scores.DisplaySlot.values()) {
assertNotNull(CraftScoreboardTranslations.toBukkitSlot(nmsSlot));
}
}
}

View File

@@ -9,6 +9,7 @@ import io.github.classgraph.ScanResult;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import net.minecraft.world.level.block.Block;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@@ -26,7 +27,7 @@ public class BlockPlayerDestroyOverrideTest {
.whitelistPackages("net.minecraft")
.scan()
) {
for (final ClassInfo subclass : scanResult.getSubclasses("net.minecraft.world.level.block.Block")) {
for (final ClassInfo subclass : scanResult.getSubclasses(Block.class.getName())) {
final MethodInfoList playerDestroy = subclass.getDeclaredMethodInfo("playerDestroy");
if (!playerDestroy.isEmpty()) {
classInfo.add(subclass);

View File

@@ -1,56 +0,0 @@
package org.bukkit;
import static org.junit.jupiter.api.Assertions.*;
import java.util.stream.Stream;
import org.bukkit.support.environment.VanillaFeature;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@VanillaFeature
public class ArtTest {
public static Stream<Arguments> widthData() {
return Stream.of(Arguments.of(Art.KEBAB, 1),
Arguments.of(Art.WANDERER, 1),
Arguments.of(Art.POOL, 2),
Arguments.of(Art.MATCH, 2),
Arguments.of(Art.BOUQUET, 3),
Arguments.of(Art.BACKYARD, 3),
Arguments.of(Art.FIGHTERS, 4),
Arguments.of(Art.SKELETON, 4),
Arguments.of(Art.POINTER, 4));
}
public static Stream<Arguments> heightData() {
return Stream.of(Arguments.of(Art.KEBAB, 1),
Arguments.of(Art.WANDERER, 2),
Arguments.of(Art.POOL, 1),
Arguments.of(Art.MATCH, 2),
Arguments.of(Art.BOUQUET, 3),
Arguments.of(Art.BACKYARD, 4),
Arguments.of(Art.FIGHTERS, 2),
Arguments.of(Art.SKELETON, 3),
Arguments.of(Art.POINTER, 4));
}
@ParameterizedTest
@MethodSource("widthData")
public void testWidth(Art art, int expected) {
assertEquals(expected, art.getBlockWidth(), """
Art '%s' does not have the correct width.
This can be caused by either a change in the Implementation.
Or the width for this specific art was changed in which case the test needs to be updated.
""".formatted(art.getKey()));
}
@ParameterizedTest
@MethodSource("heightData")
public void testHeight(Art art, int expected) {
assertEquals(expected, art.getBlockHeight(), """
Art '%s' does not have the correct height.
This can be caused by either a change in the Implementation.
Or the height for this specific art was changed in which case the test needs to be updated.
""".formatted(art.getKey()));
}
}

View File

@@ -1,32 +0,0 @@
package org.bukkit;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.core.registries.Registries;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.block.CraftBiome;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class BiomeTest {
@Test
public void testBukkitToMinecraft() {
for (Biome biome : Biome.values()) {
if (biome == Biome.CUSTOM) {
continue;
}
assertNotNull(CraftBiome.bukkitToMinecraftHolder(biome), "No NMS mapping for " + biome);
}
}
@Test
public void testMinecraftToBukkit() {
for (net.minecraft.world.level.biome.Biome biomeBase : CraftRegistry.getMinecraftRegistry(Registries.BIOME)) {
Biome biome = CraftBiome.minecraftToBukkit(biomeBase);
assertTrue(biome != null && biome != Biome.CUSTOM, "No Bukkit mapping for " + biomeBase);
}
}
}

View File

@@ -24,8 +24,8 @@ public class BlockDataConversionTest {
@ParameterizedTest
@MethodSource("data")
public void testNotNull(BlockState data) {
assertNotNull(data);
assertNotNull(CraftBlockData.fromData(data));
public void testNotNull(BlockState state) {
assertNotNull(state);
assertNotNull(CraftBlockData.fromData(state));
}
}

View File

@@ -28,15 +28,15 @@ public class ChatTest {
public void testURLJsonConversion() {
Component[] components;
components = CraftChatMessage.fromString("https://spigotmc.org/test Test Message");
assertEquals("{\"text\":\"\",\"extra\":[{\"text\":\"https://spigotmc.org/test\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://spigotmc.org/test\"}},\" Test Message\"]}",
assertEquals("{\"text\":\"\",\"extra\":[{\"text\":\"https://spigotmc.org/test\",\"click_event\":{\"url\":\"https://spigotmc.org/test\",\"action\":\"open_url\"}},\" Test Message\"]}",
CraftChatMessage.toJSON(components[0]));
components = CraftChatMessage.fromString("123 " + ChatColor.GOLD + "https://spigotmc.org " + ChatColor.BOLD + "test");
assertEquals("{\"text\":\"\",\"extra\":[\"123 \",{\"text\":\"https://spigotmc.org\",\"strikethrough\":false,\"obfuscated\":false,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://spigotmc.org\"},\"bold\":false,\"italic\":false,\"underlined\":false,\"color\":\"gold\"},{\"text\":\" \",\"strikethrough\":false,\"obfuscated\":false,\"bold\":false,\"italic\":false,\"underlined\":false,\"color\":\"gold\"},{\"text\":\"test\",\"strikethrough\":false,\"obfuscated\":false,\"bold\":true,\"italic\":false,\"underlined\":false,\"color\":\"gold\"}]}",
assertEquals("{\"text\":\"\",\"extra\":[\"123 \",{\"text\":\"https://spigotmc.org\",\"strikethrough\":false,\"obfuscated\":false,\"click_event\":{\"url\":\"https://spigotmc.org\",\"action\":\"open_url\"},\"bold\":false,\"italic\":false,\"underlined\":false,\"color\":\"gold\"},{\"text\":\" \",\"strikethrough\":false,\"obfuscated\":false,\"bold\":false,\"italic\":false,\"underlined\":false,\"color\":\"gold\"},{\"text\":\"test\",\"strikethrough\":false,\"obfuscated\":false,\"bold\":true,\"italic\":false,\"underlined\":false,\"color\":\"gold\"}]}",
CraftChatMessage.toJSON(components[0]));
components = CraftChatMessage.fromString("multiCase http://SpigotMC.ORg/SpOngeBobMeEMeGoESHeRE");
assertEquals("{\"text\":\"\",\"extra\":[\"multiCase \",{\"text\":\"http://SpigotMC.ORg/SpOngeBobMeEMeGoESHeRE\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"http://SpigotMC.ORg/SpOngeBobMeEMeGoESHeRE\"}}]}",
assertEquals("{\"text\":\"\",\"extra\":[\"multiCase \",{\"text\":\"http://SpigotMC.ORg/SpOngeBobMeEMeGoESHeRE\",\"click_event\":{\"url\":\"http://SpigotMC.ORg/SpOngeBobMeEMeGoESHeRE\",\"action\":\"open_url\"}}]}",
CraftChatMessage.toJSON(components[0]));
}
}

View File

@@ -12,9 +12,7 @@ import java.util.Set;
import net.minecraft.world.level.block.LevelEvent;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class EffectTest {

View File

@@ -1,25 +0,0 @@
package org.bukkit;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class EnchantmentTest {
@Test
public void verifyMapping() {
for (ResourceLocation key : CraftRegistry.getMinecraftRegistry(Registries.ENCHANTMENT).keySet()) {
net.minecraft.world.item.enchantment.Enchantment nms = CraftRegistry.getMinecraftRegistry(Registries.ENCHANTMENT).getValue(key);
Enchantment bukkitById = Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(key));
assertFalse(bukkitById.getName().startsWith("UNKNOWN"), "Unknown enchant name for " + key);
}
}
}

View File

@@ -18,7 +18,7 @@ public class ExplosionResultTest {
@Test
public void testToBukkit() {
for (Explosion.BlockInteraction effect : Explosion.BlockInteraction.values()) {
assertNotNull(CraftExplosionResult.toBukkit(effect), "No Bukkit enum for NMS explosion effect " + effect);
assertNotNull(CraftExplosionResult.toExplosionResult(effect), "No Bukkit enum for NMS explosion effect " + effect);
}
}
}

View File

@@ -1,20 +0,0 @@
package org.bukkit;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.core.registries.BuiltInRegistries;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class GameEventTest {
@Test
public void toBukkit() {
for (net.minecraft.world.level.gameevent.GameEvent nms : BuiltInRegistries.GAME_EVENT) {
GameEvent bukkit = GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(nms)));
assertNotNull(bukkit, "Bukkit should not be null " + nms);
}
}
}

View File

@@ -4,18 +4,14 @@ import static org.bukkit.support.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.StreamSupport;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.LegacyHelper;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@@ -31,7 +27,7 @@ public class MaterialTest {
continue;
}
materials.put(CraftMagicNumbers.key(material), material);
materials.put(CraftNamespacedKey.toMinecraft(material.getKey()), material);
}
Iterator<Item> items = BuiltInRegistries.ITEM.iterator();
@@ -51,28 +47,4 @@ public class MaterialTest {
assertThat(materials, is(Collections.EMPTY_MAP));
}
@Test
public void verifyMaterialOrder() {
List<Material> expectedOrder = new ArrayList<>(Material.values().length);
// Start with items in the same order as BuiltInRegistries.ITEM
StreamSupport.stream(BuiltInRegistries.ITEM.spliterator(), false)
.map(CraftMagicNumbers::getMaterial)
.forEach(expectedOrder::add);
// Then non-item blocks in the same order as BuiltInRegistries.BLOCK
StreamSupport.stream(BuiltInRegistries.BLOCK.spliterator(), false)
.map(CraftMagicNumbers::getMaterial)
.filter(block -> !block.isItem())
.forEach(expectedOrder::add);
// Then legacy materials in order of ID
Arrays.stream(Material.values())
.filter(Material::isLegacy)
.sorted(Comparator.comparingInt(Material::getId))
.forEach(expectedOrder::add);
assertArrayEquals(expectedOrder.toArray(), Material.values());
}
}

View File

@@ -3,115 +3,23 @@ package org.bukkit;
import static org.bukkit.support.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Map;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.equipment.Equippable;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.Fallable;
import net.minecraft.world.level.block.FireBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.support.LegacyHelper;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
@AllFeatures
public class PerMaterialTest {
private static Map<Block, Integer> fireValues;
@BeforeAll
public static void getFireValues() {
PerMaterialTest.fireValues = ((FireBlock) Blocks.FIRE).igniteOdds;
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void isBlock(Material material) {
if (material != Material.AIR && material != Material.CAVE_AIR && material != Material.VOID_AIR) {
assertThat(material.isBlock(), is(not(CraftMagicNumbers.getBlock(material) == null)));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void isSolid(Material material) {
if (material == Material.AIR) {
assertFalse(material.isSolid());
} else if (material.isBlock()) {
assertThat(material.isSolid(), is(CraftMagicNumbers.getBlock(material).defaultBlockState().blocksMotion()));
} else {
assertFalse(material.isSolid());
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void isEdible(Material material) {
if (material.isBlock()) {
assertFalse(material.isEdible());
} else {
assertThat(material.isEdible(), is(CraftMagicNumbers.getItem(material).components().has(DataComponents.FOOD)));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void isRecord(Material material) {
if (material.isBlock()) {
assertFalse(material.isRecord());
} else {
assertThat(material.isRecord(), is(CraftMagicNumbers.getItem(material).components().has(DataComponents.JUKEBOX_PLAYABLE)));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void maxDurability(Material material) {
if (LegacyHelper.getInvalidatedMaterials().contains(material)) return;
if (material == Material.AIR) {
assertThat((int) material.getMaxDurability(), is(0));
} else if (material.isBlock()) {
Item item = CraftMagicNumbers.getItem(material);
assertThat((int) material.getMaxDurability(), is(item.components().getOrDefault(DataComponents.MAX_DAMAGE, 0)));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void maxStackSize(Material material) {
if (LegacyHelper.getInvalidatedMaterials().contains(material)) return;
final ItemStack bukkit = new ItemStack(material);
final CraftItemStack craft = CraftItemStack.asCraftCopy(bukkit);
// Paper - remove air exception
int max = CraftMagicNumbers.getItem(material).components().getOrDefault(DataComponents.MAX_STACK_SIZE, 64);
assertThat(material.getMaxStackSize(), is(max));
assertThat(bukkit.getMaxStackSize(), is(max));
assertThat(craft.getMaxStackSize(), is(max));
// Paper - remove air exception
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
@Disabled
public void isTransparent(Material material) {
if (material == Material.AIR) {
assertTrue(material.isTransparent());
@@ -122,47 +30,6 @@ public class PerMaterialTest {
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void isFlammable(Material material) {
if (material != Material.AIR && material.isBlock()) {
assertThat(material.isFlammable(), is(CraftMagicNumbers.getBlock(material).defaultBlockState().ignitedByLava()));
} else {
assertFalse(material.isFlammable());
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void isBurnable(Material material) {
if (material.isBlock()) {
Block block = CraftMagicNumbers.getBlock(material);
assertThat(material.isBurnable(), is(PerMaterialTest.fireValues.containsKey(block) && PerMaterialTest.fireValues.get(block) > 0));
} else {
assertFalse(material.isBurnable());
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void isOccluding(Material material) {
if (material.isBlock()) {
assertThat(material.isOccluding(), is(CraftMagicNumbers.getBlock(material).defaultBlockState().isRedstoneConductor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)));
} else {
assertFalse(material.isOccluding());
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void hasGravity(Material material) {
if (material.isBlock()) {
assertThat(material.hasGravity(), is(CraftMagicNumbers.getBlock(material) instanceof Fallable));
} else {
assertFalse(material.hasGravity());
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void usesDurability(Material material) {
@@ -173,104 +40,6 @@ public class PerMaterialTest {
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testDurability(Material material) {
if (!material.isBlock()) {
assertThat(material.getMaxDurability(), is((short) (int) CraftMagicNumbers.getItem(material).components().getOrDefault(DataComponents.MAX_DAMAGE, 0)));
} else {
assertThat(material.getMaxDurability(), is((short) 0));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testBlock(Material material) {
if (material == Material.AIR) {
assertTrue(material.isBlock());
} else {
assertThat(material.isBlock(), is(equalTo(CraftMagicNumbers.getBlock(material) != null)));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testAir(Material material) {
if (material.isBlock()) {
assertThat(material.isAir(), is(equalTo(CraftMagicNumbers.getBlock(material).defaultBlockState().isAir())));
} else {
assertThat(material.isAir(), is(equalTo(false)));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testItem(Material material) {
if (material == Material.AIR) {
assertTrue(material.isItem());
} else {
assertThat(material.isItem(), is(equalTo(CraftMagicNumbers.getItem(material) != null)));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testInteractable(Material material) throws ReflectiveOperationException {
if (material.isBlock()) {
Class<?> clazz = CraftMagicNumbers.getBlock(material).getClass();
boolean hasMethod = this.hasMethod(clazz, "useWithoutItem", BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, BlockHitResult.class)
|| this.hasMethod(clazz, "useItemOn", net.minecraft.world.item.ItemStack.class, BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, InteractionHand.class, BlockHitResult.class);
if (!hasMethod && clazz.getSuperclass() != BlockBehaviour.class) {
clazz = clazz.getSuperclass();
hasMethod = this.hasMethod(clazz, "useWithoutItem", BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, BlockHitResult.class)
|| this.hasMethod(clazz, "useItemOn", net.minecraft.world.item.ItemStack.class, BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, InteractionHand.class, BlockHitResult.class);
}
assertThat(material.isInteractable(),
is(hasMethod));
} else {
assertFalse(material.isInteractable());
}
}
private boolean hasMethod(Class<?> clazz, String methodName, Class<?>... params) {
boolean hasMethod;
try {
hasMethod = clazz.getDeclaredMethod(methodName, params) != null;
} catch (NoSuchMethodException ex) {
hasMethod = false;
}
return hasMethod;
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testBlockHardness(Material material) {
if (material.isBlock()) {
assertThat(material.getHardness(), is(CraftMagicNumbers.getBlock(material).defaultBlockState().destroySpeed));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testBlastResistance(Material material) {
if (material.isBlock()) {
assertThat(material.getBlastResistance(), is(CraftMagicNumbers.getBlock(material).getExplosionResistance()));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testSlipperiness(Material material) {
if (material.isBlock()) {
assertThat(material.getSlipperiness(), is(CraftMagicNumbers.getBlock(material).getFriction()));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testBlockDataCreation(Material material) {
@@ -279,27 +48,6 @@ public class PerMaterialTest {
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testCraftingRemainingItem(Material material) {
if (material.isItem()) {
net.minecraft.world.item.ItemStack expectedItem = CraftMagicNumbers.getItem(material).getCraftingRemainder();
Material expected = expectedItem.isEmpty() ? null : CraftMagicNumbers.getMaterial(expectedItem.getItem());
assertThat(material.getCraftingRemainingItem(), is(expected));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testEquipmentSlot(Material material) {
if (material.isItem()) {
Equippable equipable = CraftItemStack.asNMSCopy(new ItemStack(material)).get(DataComponents.EQUIPPABLE);
EquipmentSlot expected = CraftEquipmentSlot.getSlot(equipable != null ? equipable.slot() : net.minecraft.world.entity.EquipmentSlot.MAINHAND);
assertThat(material.getEquipmentSlot(), is(expected));
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testBlockDataClass(Material material) {
@@ -311,12 +59,4 @@ public class PerMaterialTest {
}
}
}
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void testCreativeCategory(Material material) {
if (material.isItem()) {
material.getCreativeCategory();
}
}
}

View File

@@ -33,7 +33,7 @@ public class PotionEffectTypeTest {
effects.remove(effect);
}
assertThat(effects, is(Collections.EMPTY_LIST), "org.bukkit.PotionEffectType has too many effects");
assertThat(effects, is(Collections.emptyList()), "org.bukkit.PotionEffectType has too many effects");
}
@Test

View File

@@ -1,32 +1,13 @@
package org.bukkit;
import static org.bukkit.support.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Locale;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import org.bukkit.craftbukkit.CraftSound;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class SoundTest {
@Test
public void testGetSound() {
for (Sound sound : Sound.values()) {
assertThat(CraftSound.bukkitToMinecraft(sound), is(not(nullValue())), sound.name());
}
}
@Test
public void testReverse() {
for (ResourceLocation effect : BuiltInRegistries.SOUND_EVENT.keySet()) {
assertNotNull(Sound.valueOf(effect.getPath().replace('.', '_').toUpperCase(Locale.ROOT)), effect + "");
}
}
@Test
public void testCategory() {
for (SoundCategory category : SoundCategory.values()) {

View File

@@ -15,8 +15,7 @@ import org.junit.jupiter.api.Test;
public class StatisticsAndAchievementsTest {
@Test
@SuppressWarnings("unchecked")
public void verifyEntityMapping() throws Throwable {
public void verifyEntityMapping() {
for (Statistic statistic : Statistic.values()) {
if (statistic.getType() == Statistic.Type.ENTITY) {
for (EntityType entity : EntityType.values()) {
@@ -30,7 +29,7 @@ public class StatisticsAndAchievementsTest {
@Test
@SuppressWarnings("unchecked")
public void verifyStatisticMapping() throws Throwable {
public void verifyStatisticMapping() {
HashMultiset<Statistic> statistics = HashMultiset.create();
for (StatType wrapper : BuiltInRegistries.STAT_TYPE) {
for (Object child : wrapper.getRegistry()) {

View File

@@ -1,42 +0,0 @@
package org.bukkit.block.banner;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.block.entity.BannerPattern;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class PatternTypeTest {
@Test
public void testToBukkit() {
for (BannerPattern nms : MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.BANNER_PATTERN)) {
PatternType bukkit = Registry.BANNER_PATTERN.get(CraftNamespacedKey.fromMinecraft(nms.assetId()));
assertNotNull(bukkit, "No Bukkit banner pattern for " + nms + " " + nms);
}
}
@Test
public void testToNMS() {
net.minecraft.core.Registry<BannerPattern> registry = MinecraftServer.getDefaultRegistryAccess().lookupOrThrow(Registries.BANNER_PATTERN);
for (PatternType bukkit : PatternType.values()) {
BannerPattern found = null;
for (BannerPattern nms : registry) {
NamespacedKey nmsKey = CraftNamespacedKey.fromMinecraft(registry.getKey(nms));
if (bukkit.getKey().equals(nmsKey)) {
found = nms;
break;
}
}
assertNotNull(found, "No NMS banner pattern for " + bukkit + " " + bukkit.getKey());
}
}
}

View File

@@ -7,7 +7,6 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import org.bukkit.Material;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@@ -27,10 +26,10 @@ public class BlockStateTest {
// check tile entity type
BlockEntity tileEntity = ((EntityBlock) block).newBlockEntity(BlockPos.ZERO, block.defaultBlockState());
BlockEntity materialTileEntity = CraftBlockStates.createNewTileEntity(material);
BlockEntity materialTileEntity = CraftBlockStates.createNewBlockEntity(material);
if (tileEntity == null) {
if (CraftBlockStates.isTileEntityOptional(material)) {
if (CraftBlockStates.isBlockEntityOptional(material)) {
continue;
}
fail(material + " has no tile entity, it be added to CraftBlockStates#isTileEntityOptional");

View File

@@ -11,6 +11,7 @@ import java.util.jar.JarFile;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.AbstractCow;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.AbstractSkeleton;
import org.bukkit.entity.AbstractVillager;
@@ -56,6 +57,7 @@ import org.bukkit.entity.SplashPotion;
import org.bukkit.entity.Steerable;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.ThrowableProjectile;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.TippedArrow;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.WaterMob;
@@ -74,6 +76,7 @@ public class EntityTypesTest {
// Entity classes, which do not have any entity type / entity type data
private static final List<Class<? extends Entity>> EXCLUDE = Arrays.asList(
AbstractArrow.class,
AbstractCow.class,
AbstractHorse.class,
AbstractSkeleton.class,
AbstractVillager.class,
@@ -102,7 +105,6 @@ public class EntityTypesTest {
Hanging.class,
HumanEntity.class,
Illager.class,
LingeringPotion.class,
LivingEntity.class,
Minecart.class,
Mob.class,
@@ -114,10 +116,10 @@ public class EntityTypesTest {
Sittable.class,
SizedFireball.class,
Spellcaster.class,
SplashPotion.class,
Steerable.class,
Tameable.class,
ThrowableProjectile.class,
ThrownPotion.class,
TippedArrow.class,
Vehicle.class,
WaterMob.class

View File

@@ -12,11 +12,11 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.support.environment.Normal;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@Normal
public class CompositeSerialization {
@AllFeatures
public class CompositeSerializationTest {
public YamlConfiguration getConfig() {
return new YamlConfiguration();

View File

@@ -0,0 +1,33 @@
package org.bukkit.craftbukkit.inventory;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@AllFeatures
public class ItemFlagsTest {
@Test
void testItemFlags() {
final ItemStack item = ItemStack.of(Material.DIAMOND_HOE);
for (final ItemFlag value : ItemFlag.values()) {
assertFalse(item.hasItemFlag(value));
}
item.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
assertTrue(item.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES));
assertTrue(item.getItemFlags().contains(ItemFlag.HIDE_ATTRIBUTES));
item.removeItemFlags(ItemFlag.HIDE_ATTRIBUTES);
assertFalse(item.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES));
assertFalse(item.getItemFlags().contains(ItemFlag.HIDE_ATTRIBUTES));
}
}

View File

@@ -56,7 +56,7 @@ public class ItemTypeTest {
@Test
public void testStaticItemTypeUsageBuilder() {
final ItemStack armor = ItemType.DIAMOND_LEGGINGS.createItemStack(a ->
a.setTrim(new ArmorTrim(TrimMaterial.EMERALD, TrimPattern.COAST))
((ArmorMeta) a).setTrim(new ArmorTrim(TrimMaterial.EMERALD, TrimPattern.COAST))
);
final ItemMeta itemMeta = armor.getItemMeta();

View File

@@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.inventory;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.PlayerEquipment;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.bukkit.support.environment.Normal;
@@ -20,8 +21,8 @@ public class PlayerInventoryTest {
ItemStack itemStack64Coal = new ItemStack(Items.COAL, 64);
// keep one slot empty
Inventory inventory = new Inventory(null);
for (int i = 0; i < inventory.items.size() - 1; i++) {
Inventory inventory = new Inventory(null, new PlayerEquipment(null));
for (int i = 0; i < inventory.getNonEquipmentItems().size() - 1; i++) {
inventory.setItem(i, itemStackApple);
}
@@ -31,46 +32,46 @@ public class PlayerInventoryTest {
assertEquals(64, inventory.canHold(itemStack64Coal));
// no free space with a stack of the item to check in the inventory
inventory.setItem(inventory.items.size() - 1, itemStack64Coal);
inventory.setItem(inventory.getNonEquipmentItems().size() - 1, itemStack64Coal);
assertEquals(0, inventory.canHold(itemStack1Coal));
assertEquals(0, inventory.canHold(itemStack32Coal));
assertEquals(0, inventory.canHold(itemStack64Coal));
// no free space without a stack of the item to check in the inventory
inventory.setItem(inventory.items.size() - 1, itemStackApple);
inventory.setItem(inventory.getNonEquipmentItems().size() - 1, itemStackApple);
assertEquals(0, inventory.canHold(itemStack1Coal));
assertEquals(0, inventory.canHold(itemStack32Coal));
assertEquals(0, inventory.canHold(itemStack64Coal));
// free space for 32 items in one slot
inventory.setItem(inventory.items.size() - 1, itemStack32Coal);
inventory.setItem(inventory.getNonEquipmentItems().size() - 1, itemStack32Coal);
assertEquals(1, inventory.canHold(itemStack1Coal));
assertEquals(32, inventory.canHold(itemStack32Coal));
assertEquals(32, inventory.canHold(itemStack64Coal));
// free space for 1 item in two slots
inventory.setItem(inventory.items.size() - 1, itemStack63Coal);
inventory.setItem(inventory.items.size() - 2, itemStack63Coal);
inventory.setItem(inventory.getNonEquipmentItems().size() - 1, itemStack63Coal);
inventory.setItem(inventory.getNonEquipmentItems().size() - 2, itemStack63Coal);
assertEquals(1, inventory.canHold(itemStack1Coal));
assertEquals(2, inventory.canHold(itemStack32Coal));
assertEquals(2, inventory.canHold(itemStack64Coal));
// free space for 32 items in non-empty off-hand slot
inventory.setItem(inventory.items.size() - 1, itemStackApple);
inventory.setItem(inventory.items.size() - 2, itemStackApple);
inventory.setItem(inventory.items.size() + inventory.armor.size(), itemStack32Coal);
inventory.setItem(inventory.getNonEquipmentItems().size() - 1, itemStackApple);
inventory.setItem(inventory.getNonEquipmentItems().size() - 2, itemStackApple);
inventory.setItem(inventory.getNonEquipmentItems().size() + inventory.getArmorContents().size(), itemStack32Coal);
assertEquals(1, inventory.canHold(itemStack1Coal));
assertEquals(32, inventory.canHold(itemStack32Coal));
assertEquals(32, inventory.canHold(itemStack64Coal));
// free space for 1 item in non-empty off-hand slot and another slot
inventory.setItem(inventory.items.size() - 1, itemStack63Coal);
inventory.setItem(inventory.items.size() + inventory.armor.size(), itemStack63Coal);
inventory.setItem(inventory.getNonEquipmentItems().size() - 1, itemStack63Coal);
inventory.setItem(inventory.getNonEquipmentItems().size() + inventory.getArmorContents().size(), itemStack63Coal);
assertEquals(1, inventory.canHold(itemStack1Coal));
assertEquals(2, inventory.canHold(itemStack32Coal));

View File

@@ -0,0 +1,130 @@
package org.bukkit.craftbukkit.inventory;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.ItemEnchantments;
import io.papermc.paper.datacomponent.item.Tool;
import io.papermc.paper.datacomponent.item.WrittenBookContent;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.keys.BlockTypeKeys;
import io.papermc.paper.registry.set.RegistrySet;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.util.TriState;
import net.minecraft.world.level.storage.DataVersion;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@AllFeatures
public class YamlSerializationTest {
@Test
void testDataComponents() {
final ItemStack item = ItemStack.of(Material.WRITTEN_BOOK);
item.setData(DataComponentTypes.WRITTEN_BOOK_CONTENT, WrittenBookContent.writtenBookContent("Jon", "The Destroyer").addPage(Component.text("hi")).build());
item.setData(DataComponentTypes.ENCHANTMENTS, ItemEnchantments.itemEnchantments().add(Enchantment.AQUA_AFFINITY, 1).add(Enchantment.DENSITY, 2).build());
item.setData(DataComponentTypes.GLIDER);
item.setData(DataComponentTypes.TOOL, Tool.tool().addRule(Tool.rule(RegistrySet.keySet(RegistryKey.BLOCK, BlockTypeKeys.ACACIA_DOOR), 1f, TriState.TRUE)));
testYamlRoundTrip(item, """
item:
==: org.bukkit.inventory.ItemStack
DataVersion: %s
id: minecraft:written_book
count: 1
components:
minecraft:written_book_content: '{author:"The Destroyer",pages:[{raw:"hi"}],title:{raw:"Jon"}}'
minecraft:glider: '{}'
minecraft:enchantments: '{"minecraft:aqua_affinity":1,"minecraft:density":2}'
minecraft:tool: '{rules:[{blocks:"minecraft:acacia_door",correct_for_drops:1b,speed:1.0f}]}'
schema_version: 1
""".formatted(Bukkit.getUnsafe().getDataVersion()));
}
@Test
void testItemMeta() {
final ItemStack item = ItemStack.of(Material.WRITTEN_BOOK);
item.editMeta(BookMeta.class, (meta) -> {
meta.setAuthor("The Destroyer");
meta.setTitle("Jon");
meta.addPages(Component.text("hi"));
meta.addEnchant(Enchantment.AQUA_AFFINITY, 1, false);
meta.addEnchant(Enchantment.DENSITY, 2, false);
});
testYamlRoundTrip(item, """
item:
==: org.bukkit.inventory.ItemStack
DataVersion: %s
id: minecraft:written_book
count: 1
components:
minecraft:written_book_content: '{author:"The Destroyer",pages:[{raw:"hi"}],title:{raw:"Jon"}}'
minecraft:enchantments: '{"minecraft:aqua_affinity":1,"minecraft:density":2}'
schema_version: 1
""".formatted(Bukkit.getUnsafe().getDataVersion()));
}
@Test
void testUpgrading() {
// 4189 = 1.21.4
testYamlUpgrade("""
item:
==: org.bukkit.inventory.ItemStack
DataVersion: 4189
id: minecraft:diamond_hoe
count: 1
components:
minecraft:unbreakable: '{show_in_tooltip:false}'
minecraft:enchantments: '{levels:{"minecraft:sharpness":2},show_in_tooltip:false}'
schema_version: 1
""", """
item:
==: org.bukkit.inventory.ItemStack
DataVersion: %s
id: minecraft:diamond_hoe
count: 1
components:
minecraft:unbreakable: '{}'
minecraft:enchantments: '{"minecraft:sharpness":2}'
minecraft:tooltip_display: '{hidden_components:["minecraft:enchantments","minecraft:unbreakable"]}'
schema_version: 1
""".formatted(Bukkit.getUnsafe().getDataVersion()));
}
private void testYamlRoundTrip(ItemStack itemStack, String expectedYamlString) {
final YamlConfiguration out = new YamlConfiguration();
out.set("item", itemStack);
final String yamlString = out.saveToString();
assertEquals(expectedYamlString, yamlString);
final YamlConfiguration in = new YamlConfiguration();
try {
in.loadFromString(yamlString);
} catch (final InvalidConfigurationException e) {
throw new RuntimeException(e);
}
assertEquals(itemStack, in.getItemStack("item"));
}
private void testYamlUpgrade(String oldYamlString, String expectedYamlString) {
final YamlConfiguration config = new YamlConfiguration();
try {
config.loadFromString(oldYamlString);
} catch (final InvalidConfigurationException e) {
throw new RuntimeException(e);
}
assertEquals(expectedYamlString, config.saveToString());
}
}

View File

@@ -135,6 +135,8 @@ public class LegacyTest {
// 1.21.4
Material.OPEN_EYEBLOSSOM, Material.CLOSED_EYEBLOSSOM, Material.RESIN_CLUMP, Material.RESIN_BLOCK, Material.RESIN_BRICKS, Material.RESIN_BRICK_STAIRS, Material.RESIN_BRICK_SLAB, Material.RESIN_BRICK_WALL, Material.CHISELED_RESIN_BRICKS,
Material.RESIN_BRICK, Material.POTTED_OPEN_EYEBLOSSOM, Material.POTTED_CLOSED_EYEBLOSSOM,
// 1.21.5
Material.WILDFLOWERS, Material.LEAF_LITTER, Material.TEST_BLOCK, Material.TEST_INSTANCE_BLOCK, Material.BUSH, Material.FIREFLY_BUSH, Material.SHORT_DRY_GRASS, Material.TALL_DRY_GRASS, Material.CACTUS_FLOWER, Material.BLUE_EGG, Material.BROWN_EGG,
//
Material.LEGACY_AIR, Material.LEGACY_DEAD_BUSH, Material.LEGACY_BURNING_FURNACE, Material.LEGACY_WALL_SIGN, Material.LEGACY_REDSTONE_TORCH_OFF, Material.LEGACY_SKULL, Material.LEGACY_REDSTONE_COMPARATOR_ON, Material.LEGACY_WALL_BANNER, Material.LEGACY_MONSTER_EGG));

View File

@@ -98,7 +98,7 @@ public class MaterialReroutingTest {
}
// Paper start - filter out more methods from rerouting test
if (methodNode.name.startsWith("lambda$")) continue;
if (isInternal(methodNode.invisibleAnnotations)) continue;
if ((methodNode.access & Opcodes.ACC_PRIVATE) != 0 || isInternal(methodNode.invisibleAnnotations)) continue;
// Paper end - filter out more methods from rerouting test
if (!Commodore.rerouteMethods(ApiVersion.CURRENT, MaterialReroutingTest.MATERIAL_METHOD_REROUTE, (methodNode.access & Opcodes.ACC_STATIC) != 0, classNode.name, methodNode.name, methodNode.desc, a -> { })) {

View File

@@ -1,11 +1,11 @@
package org.bukkit.craftbukkit.legacy;
import static org.junit.jupiter.api.Assertions.*;
import com.google.common.base.Charsets;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.craftbukkit.inventory.CraftItemFactory;
@@ -27,7 +27,7 @@ public class PersistentDataContainerLegacyTest {
try (final InputStream input = this.getClass().getClassLoader().getResourceAsStream("pdc/legacy_pdc.yml")) {
assertNotNull(input, "Legacy pdc yaml was null");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, Charsets.UTF_8))) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
legacyConfig = YamlConfiguration.loadConfiguration(reader);
}
} catch (IOException e) {

View File

@@ -1,33 +1,13 @@
package org.bukkit.entity;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class EntityTypesTest {
@Test
public void testMaps() {
Set<EntityType> allBukkit = Arrays.stream(EntityType.values()).filter((b) -> b.getName() != null).collect(Collectors.toSet());
for (net.minecraft.world.entity.EntityType<?> nms : BuiltInRegistries.ENTITY_TYPE) { // Paper - remap fix
ResourceLocation key = net.minecraft.world.entity.EntityType.getKey(nms); // Paper - remap fix
org.bukkit.entity.EntityType bukkit = org.bukkit.entity.EntityType.fromName(key.getPath());
assertNotNull(bukkit, "Missing nms->bukkit " + key);
assertTrue(allBukkit.remove(bukkit), "Duplicate entity nms->" + bukkit);
}
assertTrue(allBukkit.isEmpty(), "Unmapped bukkit entities " + allBukkit);
}
@Test
public void testTranslationKey() {
for (org.bukkit.entity.EntityType entityType : org.bukkit.entity.EntityType.values()) {

View File

@@ -1,33 +0,0 @@
package org.bukkit.entity;
import static org.junit.jupiter.api.Assertions.*;
import org.bukkit.craftbukkit.entity.CraftPanda;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class PandaGeneTest {
@Test
public void testBukkit() {
for (Panda.Gene gene : Panda.Gene.values()) { // Paper - remap fix
net.minecraft.world.entity.animal.Panda.Gene nms = CraftPanda.toNms(gene); // Paper - remap fix
assertNotNull(nms, "NMS gene null for " + gene);
assertEquals(gene.isRecessive(), nms.isRecessive(), "Recessive status did not match " + gene);
assertEquals(gene, CraftPanda.fromNms(nms), "Gene did not convert back " + gene);
}
}
@Test
public void testNMS() {
for (net.minecraft.world.entity.animal.Panda.Gene gene : net.minecraft.world.entity.animal.Panda.Gene.values()) { // Paper - remap fix
org.bukkit.entity.Panda.Gene bukkit = CraftPanda.fromNms(gene);
assertNotNull(bukkit, "Bukkit gene null for " + gene);
assertEquals(gene.isRecessive(), bukkit.isRecessive(), "Recessive status did not match " + gene);
assertEquals(gene, CraftPanda.toNms(bukkit), "Gene did not convert back " + gene);
}
}
}

View File

@@ -1,78 +0,0 @@
package org.bukkit.entity.memory;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@AllFeatures
public class CraftMemoryKeyTest {
@Test
public void shouldConvertBukkitHomeKeyToNMSRepresentation() {
MemoryModuleType<GlobalPos> nmsHomeKey = CraftMemoryKey.bukkitToMinecraft(MemoryKey.HOME);
assertEquals(MemoryModuleType.HOME, nmsHomeKey, "MemoryModuleType should be HOME");
}
@Test
public void shouldConvertBukkitJobSiteKeyToNMSRepresentation() {
MemoryModuleType<GlobalPos> nmsHomeKey = CraftMemoryKey.bukkitToMinecraft(MemoryKey.JOB_SITE);
assertEquals(MemoryModuleType.JOB_SITE, nmsHomeKey, "MemoryModuleType should be JOB_SITE");
}
@Test
public void shouldConvertBukkitMeetingPointKeyToNMSRepresentation() {
MemoryModuleType<GlobalPos> nmsHomeKey = CraftMemoryKey.bukkitToMinecraft(MemoryKey.MEETING_POINT);
assertEquals(MemoryModuleType.MEETING_POINT, nmsHomeKey, "MemoryModuleType should be MEETING_POINT");
}
@Test
public void shouldConvertNMSHomeKeyToBukkitRepresentation() {
MemoryKey<Location> bukkitHomeKey = CraftMemoryKey.minecraftToBukkit(MemoryModuleType.HOME);
assertEquals(MemoryKey.HOME, bukkitHomeKey, "MemoryModuleType should be HOME");
}
@Test
public void shouldConvertNMSJobSiteKeyToBukkitRepresentation() {
MemoryKey<Location> bukkitJobSiteKey = CraftMemoryKey.minecraftToBukkit(MemoryModuleType.JOB_SITE);
assertEquals(MemoryKey.JOB_SITE, bukkitJobSiteKey, "MemoryKey should be JOB_SITE");
}
@Test
public void shouldConvertNMSMeetingPointKeyToBukkitRepresentation() {
MemoryKey<Location> bukkitHomeKey = CraftMemoryKey.minecraftToBukkit(MemoryModuleType.MEETING_POINT);
assertEquals(MemoryKey.MEETING_POINT, bukkitHomeKey, "MemoryKey should be MEETING_POINT");
}
@Test
public void shouldReturnNullWhenBukkitRepresentationOfKeyisNotAvailable() {
MemoryKey bukkitNoKey = CraftMemoryKey.minecraftToBukkit(MemoryModuleType.NEAREST_LIVING_ENTITIES);
assertNull(bukkitNoKey, "MemoryModuleType should be null");
}
@Test
public void shouldReturnNullWhenBukkitRepresentationOfKeyisNotAvailableAndSerializerIsNotPresent() {
for (MemoryModuleType<?> memoryModuleType : BuiltInRegistries.MEMORY_MODULE_TYPE) {
if (!memoryModuleType.getCodec().isPresent()) {
MemoryKey bukkitNoKey = CraftMemoryKey.minecraftToBukkit(memoryModuleType);
assertNull(bukkitNoKey, "MemoryModuleType should be null");
}
}
}
@Test
@Disabled("Unit type not yet implemented")
public void shouldReturnAnInstanceOfMemoryKeyWhenBukkitRepresentationOfKeyisAvailableAndSerializerIsPresent() {
for (MemoryModuleType<?> memoryModuleType : BuiltInRegistries.MEMORY_MODULE_TYPE) {
if (memoryModuleType.getCodec().isPresent()) {
MemoryKey bukkitNoKey = CraftMemoryKey.minecraftToBukkit(memoryModuleType);
assertNotNull(bukkitNoKey, "MemoryModuleType should not be null " + BuiltInRegistries.MEMORY_MODULE_TYPE.getKey(memoryModuleType));
}
}
}
}

View File

@@ -7,6 +7,7 @@ import java.util.List;
import net.minecraft.world.level.entity.EntityAccess;
import org.bukkit.support.environment.Normal;
import org.bukkit.support.test.ClassNodeTest;
import org.junit.jupiter.api.Disabled;
import org.objectweb.asm.Handle;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
@@ -16,12 +17,13 @@ import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
@Normal
@Disabled // TODO Delete this test or re-enable it with changes
public class EntityRemoveEventTest {
@ClassNodeTest(value = ClassNodeTest.ClassType.CRAFT_BUKKIT,
excludedClasses = EntityAccess.class,
excludedPackages = "net/minecraft/gametest/framework")
public void testForMissing(ClassNode classNode) throws ClassNotFoundException {
public void testForMissing(ClassNode classNode, String name) throws ClassNotFoundException {
List<String> missingReason = new ArrayList<>();
boolean minecraftCause = false;

View File

@@ -1,53 +0,0 @@
package org.bukkit.generator.structure;
import static org.junit.jupiter.api.Assertions.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Locale;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class StructureTest {
@Test
public void testBukkitToMinecraftFieldName() {
for (Field field : Structure.class.getFields()) {
if (field.getType() != Structure.class) {
continue;
}
if (!Modifier.isStatic(field.getModifiers())) {
continue;
}
String name = field.getName();
assertNotNull(Registry.STRUCTURE.get(NamespacedKey.fromString(name.toLowerCase(Locale.ROOT))), "No structure for field name " + name);
}
}
@Test
public void testMinecraftToBukkitFieldName() {
net.minecraft.core.Registry<net.minecraft.world.level.levelgen.structure.Structure> structureBuiltInRegistries = CraftRegistry.getMinecraftRegistry(Registries.STRUCTURE);
for (net.minecraft.world.level.levelgen.structure.Structure structure : structureBuiltInRegistries) {
ResourceLocation minecraftKey = structureBuiltInRegistries.getKey(structure);
try {
Structure bukkit = (Structure) Structure.class.getField(minecraftKey.getPath().toUpperCase(Locale.ROOT)).get(null);
assertEquals(minecraftKey, CraftNamespacedKey.toMinecraft(bukkit.getKey()), "Keys are not the same for " + minecraftKey);
} catch (NoSuchFieldException e) {
fail("No Bukkit default structure for " + minecraftKey);
} catch (IllegalAccessException e) {
fail("Bukkit field is not access able for " + minecraftKey);
} catch (ClassCastException e) {
fail("Bukkit field is not of type structure for" + minecraftKey);
}
}
}
}

View File

@@ -1,53 +0,0 @@
package org.bukkit.generator.structure;
import static org.junit.jupiter.api.Assertions.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Locale;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class StructureTypeTest {
@Test
public void testBukkitToMinecraftFieldName() {
for (Field field : StructureType.class.getFields()) {
if (field.getType() != StructureType.class) {
continue;
}
if (!Modifier.isStatic(field.getModifiers())) {
continue;
}
String name = field.getName();
assertNotNull(Registry.STRUCTURE_TYPE.get(NamespacedKey.fromString(name.toLowerCase(Locale.ROOT))), "No enchantment for field name " + name);
}
}
@Test
public void testMinecraftToBukkitFieldName() {
for (net.minecraft.world.level.levelgen.structure.StructureType<?> structureType : CraftRegistry.getMinecraftRegistry(Registries.STRUCTURE_TYPE)) {
ResourceLocation minecraftKey = BuiltInRegistries.STRUCTURE_TYPE.getKey(structureType);
try {
StructureType bukkit = (StructureType) StructureType.class.getField(minecraftKey.getPath().toUpperCase(Locale.ROOT)).get(null);
assertEquals(minecraftKey, CraftNamespacedKey.toMinecraft(bukkit.getKey()), "Keys are not the same for " + minecraftKey);
} catch (NoSuchFieldException e) {
fail("No Bukkit default enchantment for " + minecraftKey);
} catch (IllegalAccessException e) {
fail("Bukkit field is not access able for " + minecraftKey);
} catch (ClassCastException e) {
fail("Bukkit field is not of type enchantment for" + minecraftKey);
}
}
}
}

View File

@@ -3,11 +3,8 @@ package org.bukkit.map;
import static org.junit.jupiter.api.Assertions.*;
import java.awt.Color;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.world.level.material.MapColor;
import org.bukkit.craftbukkit.map.CraftMapColorCache;
import org.bukkit.support.environment.Normal;
import org.bukkit.support.environment.Slow;
import org.junit.jupiter.api.Test;
@@ -15,55 +12,6 @@ public class MapTest {
private static final Logger logger = Logger.getLogger("MapTest");
private static final int[] modifiers = {180, 220, 255, 135};
@Test
@Normal
public void testColors() {
MapColor[] nmsColors = MapColor.MATERIAL_COLORS;
Color[] bukkitColors = MapPalette.colors;
boolean fail = false;
for (int i = 0; i < nmsColors.length; i++) {
if (nmsColors[i] == null) {
break;
}
int rgb = nmsColors[i].col;
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
if (i + 1 > bukkitColors.length / 4) {
for (int modi : MapTest.modifiers) {
int mr = (r * modi) / 255;
int mg = (g * modi) / 255;
int mb = (b * modi) / 255;
MapTest.logger.log(Level.WARNING, "Missing color (check CraftMapView#render and update md5 hash in CraftMapColorCache): c({0}, {1}, {2})", new Object[]{mr, mg, mb});
}
fail = true;
} else {
for (int j = 0; j < MapTest.modifiers.length; j++) {
int modi = MapTest.modifiers[j];
Color bukkit = bukkitColors[i * 4 + j];
int mr = (r * modi) / 255;
int mg = (g * modi) / 255;
int mb = (b * modi) / 255;
if (bukkit.getRed() != mr || bukkit.getGreen() != mg || bukkit.getBlue() != mb) {
MapTest.logger.log(Level.WARNING, "Incorrect color: {6} {7} c({0}, {1}, {2}) != c({3}, {4}, {5})", new Object[]{
bukkit.getRed(), bukkit.getGreen(), bukkit.getBlue(),
mr, mg, mb,
i, j
});
fail = true;
}
}
}
}
assertFalse(fail);
}
@Test
@Slow("Test takes around 25 seconds, should be run by changes to the map color conversion")
public void testMapColorCacheBuilding() throws ExecutionException, InterruptedException {

View File

@@ -16,23 +16,6 @@ import org.junit.jupiter.api.Test;
@AllFeatures
public class PotionTest {
@Test
public void testEffectCompleteness() throws Throwable {
Map<PotionType, String> effects = new EnumMap(PotionType.class);
for (Potion reg : BuiltInRegistries.POTION) {
List<MobEffectInstance> eff = reg.getEffects();
if (eff.size() != 1) continue;
PotionEffectType type = CraftPotionEffectType.minecraftHolderToBukkit(eff.get(0).getEffect());
assertNotNull(type, String.valueOf(reg));
PotionType enumType = PotionType.getByEffect(type);
assertNotNull(enumType, type.getName());
effects.put(enumType, enumType.name());
}
assertEquals(PotionType.values().length - /* PotionTypes with no/shared Effects */ (5 + 22 /* There are 22 new strong / long potion types */), effects.entrySet().size());
}
@Test
public void testEffectType() {
@@ -42,7 +25,6 @@ public class PotionTest {
PotionEffectType bukkit = CraftPotionEffectType.minecraftToBukkit(nms);
assertNotNull(bukkit, "No Bukkit type for " + key);
assertFalse(bukkit.getName().contains("UNKNOWN"), "No name for " + key);
PotionEffectType byName = FieldRename.getByName_PotionEffectType(bukkit.getName());
assertEquals(bukkit, byName, "Same type not returned by name " + key);

View File

@@ -17,6 +17,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemFactory;
import org.bukkit.craftbukkit.tag.CraftBlockTag;
import org.bukkit.craftbukkit.tag.CraftEntityTag;
import org.bukkit.craftbukkit.tag.CraftFluidTag;
import org.bukkit.craftbukkit.tag.CraftGameEventTag;
import org.bukkit.craftbukkit.tag.CraftItemTag;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
@@ -78,6 +79,13 @@ public final class DummyServerHelper {
return new CraftEntityTag(BuiltInRegistries.ENTITY_TYPE, entityTagKey);
}
}
case org.bukkit.Tag.REGISTRY_GAME_EVENTS -> {
Preconditions.checkArgument(clazz == org.bukkit.GameEvent.class, "Game event namespace must have game event");
TagKey<net.minecraft.world.level.gameevent.GameEvent> gameEventKey = TagKey.create(Registries.GAME_EVENT, key); // Paper - address remapping issues
if (BuiltInRegistries.GAME_EVENT.get(gameEventKey).isPresent()) {
return new CraftGameEventTag(BuiltInRegistries.GAME_EVENT, gameEventKey);
}
}
default -> new io.papermc.paper.util.EmptyTag(); // Paper - testing additions
}

View File

@@ -1,7 +1,5 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
@@ -17,7 +15,6 @@ import org.junit.jupiter.api.extension.ExtensionContext;
public class AllFeaturesExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> realRegistries = new HashMap<>();
private static final Map<Class<? extends Keyed>, Registry<?>> spyRegistries = new HashMap<>();
public AllFeaturesExtension() {
super("AllFeatures");

View File

@@ -1,13 +1,7 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
@@ -16,8 +10,6 @@ import org.junit.jupiter.api.extension.ExtensionContext;
public class LegacyExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> registries = new HashMap<>();
public LegacyExtension() {
super("Legacy");
}

View File

@@ -1,13 +1,7 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
@@ -16,8 +10,6 @@ import org.junit.jupiter.api.extension.ExtensionContext;
public class SlowExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> registries = new HashMap<>();
public SlowExtension() {
super("Slow");
}

View File

@@ -1,13 +1,7 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
@@ -16,8 +10,6 @@ import org.junit.jupiter.api.extension.ExtensionContext;
public class VanillaFeatureExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> registries = new HashMap<>();
public VanillaFeatureExtension() {
super("VanillaFeature");
}

View File

@@ -34,7 +34,7 @@ public class ClassNodeArgumentProvider implements ArgumentsProvider, AnnotationC
ClassReaderArgumentProvider classReaderArgumentProvider = new ClassReaderArgumentProvider();
classReaderArgumentProvider.accept(new ClassReaderArguments(this.classReaderClassType(), this.excludedClasses, this.excludedPackages));
return classReaderArgumentProvider.getClassReaders().map(this::toClassNode).map(Arguments::of);
return classReaderArgumentProvider.getClassReaders().map(this::toClassNode).map(cn -> Arguments.of(cn, cn.name));
}
private ClassReaderTest.ClassType[] classReaderClassType() {

View File

@@ -9,8 +9,12 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.animal.CatVariant;
import net.minecraft.world.entity.animal.FrogVariant;
import net.minecraft.world.entity.animal.WolfVariant;
import net.minecraft.world.entity.animal.ChickenVariant;
import net.minecraft.world.entity.animal.CowVariant;
import net.minecraft.world.entity.animal.PigVariant;
import net.minecraft.world.entity.animal.frog.FrogVariant;
import net.minecraft.world.entity.animal.wolf.WolfSoundVariant;
import net.minecraft.world.entity.animal.wolf.WolfVariant;
import net.minecraft.world.entity.decoration.PaintingVariant;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.VillagerType;
@@ -40,7 +44,10 @@ import org.bukkit.craftbukkit.block.banner.CraftPatternType;
import org.bukkit.craftbukkit.damage.CraftDamageType;
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
import org.bukkit.craftbukkit.entity.CraftCat;
import org.bukkit.craftbukkit.entity.CraftChicken;
import org.bukkit.craftbukkit.entity.CraftCow;
import org.bukkit.craftbukkit.entity.CraftFrog;
import org.bukkit.craftbukkit.entity.CraftPig;
import org.bukkit.craftbukkit.entity.CraftVillager;
import org.bukkit.craftbukkit.entity.CraftWolf;
import org.bukkit.craftbukkit.generator.structure.CraftStructure;
@@ -54,7 +61,10 @@ import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.damage.DamageType;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Frog;
import org.bukkit.entity.Pig;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
import org.bukkit.generator.structure.Structure;
@@ -93,6 +103,7 @@ public class RegistriesArgumentProvider implements ArgumentsProvider {
register(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class);
register(RegistryKey.JUKEBOX_SONG, JukeboxSong.class, Registries.JUKEBOX_SONG, CraftJukeboxSong.class, net.minecraft.world.item.JukeboxSong.class);
register(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class);
register(RegistryKey.WOLF_SOUND_VARIANT, Wolf.SoundVariant.class, Registries.WOLF_SOUND_VARIANT, CraftWolf.CraftSoundVariant.class, WolfSoundVariant.class);
register(RegistryKey.ITEM, ItemType.class, Registries.ITEM, CraftItemType.class, net.minecraft.world.item.Item.class, true);
register(RegistryKey.BLOCK, BlockType.class, Registries.BLOCK, CraftBlockType.class, net.minecraft.world.level.block.Block.class, true);
register(RegistryKey.FROG_VARIANT, Frog.Variant.class, Registries.FROG_VARIANT, CraftFrog.CraftVariant.class, FrogVariant.class);
@@ -101,6 +112,9 @@ public class RegistriesArgumentProvider implements ArgumentsProvider {
register(RegistryKey.BANNER_PATTERN, PatternType.class, Registries.BANNER_PATTERN, CraftPatternType.class, BannerPattern.class);
register(RegistryKey.MENU, MenuType.class, Registries.MENU, CraftMenuType.class, net.minecraft.world.inventory.MenuType.class);
register(RegistryKey.DATA_COMPONENT_TYPE, io.papermc.paper.datacomponent.DataComponentType.class, Registries.DATA_COMPONENT_TYPE, io.papermc.paper.datacomponent.PaperDataComponentType.class, net.minecraft.core.component.DataComponentType.class);
register(RegistryKey.CHICKEN_VARIANT, Chicken.Variant.class, Registries.CHICKEN_VARIANT, CraftChicken.CraftVariant.class, ChickenVariant.class);
register(RegistryKey.COW_VARIANT, Cow.Variant.class, Registries.COW_VARIANT, CraftCow.CraftVariant.class, CowVariant.class);
register(RegistryKey.PIG_VARIANT, Pig.Variant.class, Registries.PIG_VARIANT, CraftPig.CraftVariant.class, PigVariant.class);
}
private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft) { // Paper

View File

@@ -1,15 +0,0 @@
package org.bukkit.support.suite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite(failIfNoTests = false)
@SuiteDisplayName("Test suite for test which need registry values present, with the bundle feature flag set")
@IncludeTags("BundleFeature")
@SelectPackages({"org.bukkit", "io.papermc"})
@ConfigurationParameter(key = "TestSuite", value = "BundleFeature")
public class BundleFeatureTestSuite {
}

View File

@@ -11,7 +11,7 @@ import org.junit.jupiter.params.provider.ArgumentsSource;
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ArgumentsSource(ClassNodeArgumentProvider.class)
@ParameterizedTest
@ParameterizedTest(name = "[{index}] - {1}")
public @interface ClassNodeTest {
ClassType[] value() default {ClassType.BUKKIT, ClassType.CRAFT_BUKKIT};