DataComponent API
Exposes the data component logic used by vanilla ItemStack to API consumers as a version-specific API. The types and methods introduced by this patch do not follow the general API deprecation contracts and will be adapted to each new minecraft release without backwards compatibility measures. == AT == public net/minecraft/world/item/component/ItemContainerContents MAX_SIZE public net/minecraft/world/item/component/ItemContainerContents items
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package io.papermc.paper.datacomponent;
|
||||
|
||||
import com.google.common.collect.Collections2;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
import org.bukkit.support.RegistryHelper;
|
||||
import org.bukkit.support.environment.AllFeatures;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@AllFeatures
|
||||
public class DataComponentTypesTest {
|
||||
|
||||
private static final Set<ResourceLocation> NOT_IN_API = Set.of(
|
||||
ResourceLocation.parse("custom_data"),
|
||||
ResourceLocation.parse("entity_data"),
|
||||
ResourceLocation.parse("bees"),
|
||||
ResourceLocation.parse("debug_stick_state"),
|
||||
ResourceLocation.parse("block_entity_data"),
|
||||
ResourceLocation.parse("bucket_entity_data"),
|
||||
ResourceLocation.parse("lock"),
|
||||
ResourceLocation.parse("creative_slot_lock")
|
||||
);
|
||||
|
||||
@Test
|
||||
public void testAllDataComponentsAreMapped() throws IllegalAccessException {
|
||||
final Set<ResourceLocation> vanillaDataComponentTypes = new ObjectOpenHashSet<>(
|
||||
RegistryHelper.getRegistry()
|
||||
.lookupOrThrow(Registries.DATA_COMPONENT_TYPE)
|
||||
.keySet()
|
||||
);
|
||||
|
||||
for (final Field declaredField : DataComponentTypes.class.getDeclaredFields()) {
|
||||
if (!DataComponentType.class.isAssignableFrom(declaredField.getType())) continue;
|
||||
|
||||
final DataComponentType dataComponentType = (DataComponentType) declaredField.get(null);
|
||||
if (!vanillaDataComponentTypes.remove(CraftNamespacedKey.toMinecraft(dataComponentType.getKey()))) {
|
||||
Assertions.fail("API defined component type " + dataComponentType.key().asMinimalString() + " is unknown to vanilla registry");
|
||||
}
|
||||
}
|
||||
|
||||
if (!vanillaDataComponentTypes.containsAll(NOT_IN_API)) {
|
||||
Assertions.fail("API defined data components that were marked as not-yet-implemented: " + NOT_IN_API.stream().filter(Predicate.not(vanillaDataComponentTypes::contains)).map(ResourceLocation::toString).collect(Collectors.joining(", ")));
|
||||
}
|
||||
|
||||
vanillaDataComponentTypes.removeAll(NOT_IN_API);
|
||||
if (!vanillaDataComponentTypes.isEmpty()) {
|
||||
Assertions.fail("API did not define following vanilla data component types: " + String.join(", ", Collections2.transform(vanillaDataComponentTypes, ResourceLocation::toString)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package io.papermc.paper.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import java.util.Set;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.support.environment.AllFeatures;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@AllFeatures
|
||||
class ItemStackDataComponentEqualsTest {
|
||||
|
||||
@Test
|
||||
public void testEqual() {
|
||||
ItemStack item1 = ItemStack.of(Material.STONE, 1);
|
||||
item1.setData(DataComponentTypes.MAX_STACK_SIZE, 32);
|
||||
item1.setData(DataComponentTypes.ITEM_NAME, Component.text("HI"));
|
||||
|
||||
ItemStack item2 = ItemStack.of(Material.STONE, 1);
|
||||
item2.setData(DataComponentTypes.MAX_STACK_SIZE, 32);
|
||||
item2.setData(DataComponentTypes.ITEM_NAME, Component.text("HI"));
|
||||
|
||||
Assertions.assertTrue(item1.matchesWithoutData(item2, Set.of()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualIgnoreComponent() {
|
||||
ItemStack item1 = ItemStack.of(Material.STONE, 2);
|
||||
item1.setData(DataComponentTypes.MAX_STACK_SIZE, 1);
|
||||
|
||||
ItemStack item2 = ItemStack.of(Material.STONE, 1);
|
||||
item2.setData(DataComponentTypes.MAX_STACK_SIZE, 2);
|
||||
|
||||
Assertions.assertFalse(item1.matchesWithoutData(item2, Set.of(DataComponentTypes.MAX_STACK_SIZE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualIgnoreComponentAndSize() {
|
||||
ItemStack item1 = ItemStack.of(Material.STONE, 2);
|
||||
item1.setData(DataComponentTypes.MAX_STACK_SIZE, 1);
|
||||
|
||||
ItemStack item2 = ItemStack.of(Material.STONE, 1);
|
||||
item2.setData(DataComponentTypes.MAX_STACK_SIZE, 2);
|
||||
|
||||
Assertions.assertTrue(item1.matchesWithoutData(item2, Set.of(DataComponentTypes.MAX_STACK_SIZE), true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualWithoutComponent() {
|
||||
ItemStack item1 = ItemStack.of(Material.STONE, 1);
|
||||
|
||||
ItemStack item2 = ItemStack.of(Material.STONE, 1);
|
||||
item2.setData(DataComponentTypes.MAX_STACK_SIZE, 2);
|
||||
|
||||
Assertions.assertFalse(item1.matchesWithoutData(item2, Set.of(DataComponentTypes.WRITTEN_BOOK_CONTENT)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualRemoveComponent() {
|
||||
ItemStack item1 = ItemStack.of(Material.STONE, 1);
|
||||
item1.unsetData(DataComponentTypes.MAX_STACK_SIZE);
|
||||
|
||||
ItemStack item2 = ItemStack.of(Material.STONE, 1);
|
||||
item2.unsetData(DataComponentTypes.MAX_STACK_SIZE);
|
||||
|
||||
Assertions.assertTrue(item1.matchesWithoutData(item2, Set.of()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualIncludeComponentIgnoreSize() {
|
||||
ItemStack item1 = ItemStack.of(Material.STONE, 2);
|
||||
item1.setData(DataComponentTypes.MAX_STACK_SIZE, 1);
|
||||
|
||||
ItemStack item2 = ItemStack.of(Material.STONE, 1);
|
||||
item2.setData(DataComponentTypes.MAX_STACK_SIZE, 1);
|
||||
|
||||
Assertions.assertTrue(item1.matchesWithoutData(item2, Set.of(), true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvancedExample() {
|
||||
ItemStack oakLeaves = ItemStack.of(Material.OAK_LEAVES, 1);
|
||||
oakLeaves.setData(DataComponentTypes.HIDE_TOOLTIP);
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
package io.papermc.paper.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentType;
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import io.papermc.paper.datacomponent.item.ChargedProjectiles;
|
||||
import io.papermc.paper.datacomponent.item.CustomModelData;
|
||||
import io.papermc.paper.datacomponent.item.DyedItemColor;
|
||||
import io.papermc.paper.datacomponent.item.Fireworks;
|
||||
import io.papermc.paper.datacomponent.item.FoodProperties;
|
||||
import io.papermc.paper.datacomponent.item.ItemArmorTrim;
|
||||
import io.papermc.paper.datacomponent.item.ItemAttributeModifiers;
|
||||
import io.papermc.paper.datacomponent.item.ItemEnchantments;
|
||||
import io.papermc.paper.datacomponent.item.ItemLore;
|
||||
import io.papermc.paper.datacomponent.item.JukeboxPlayable;
|
||||
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.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.set.RegistrySet;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.util.TriState;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.world.item.EitherHolder;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.JukeboxSongs;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.JukeboxSong;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.BlockType;
|
||||
import org.bukkit.block.DecoratedPot;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.EquipmentSlotGroup;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemRarity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.ItemType;
|
||||
import org.bukkit.inventory.meta.ArmorMeta;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.bukkit.inventory.meta.CrossbowMeta;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.KnowledgeBookMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.MapMeta;
|
||||
import org.bukkit.inventory.meta.Repairable;
|
||||
import org.bukkit.inventory.meta.components.FoodComponent;
|
||||
import org.bukkit.inventory.meta.components.JukeboxPlayableComponent;
|
||||
import org.bukkit.inventory.meta.components.ToolComponent;
|
||||
import org.bukkit.inventory.meta.trim.ArmorTrim;
|
||||
import org.bukkit.inventory.meta.trim.TrimMaterial;
|
||||
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||
import org.bukkit.support.RegistryHelper;
|
||||
import org.bukkit.support.environment.AllFeatures;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@AllFeatures
|
||||
class ItemStackDataComponentTest {
|
||||
|
||||
@Test
|
||||
void testMaxStackSize() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.MAX_STACK_SIZE, 32, ItemMeta.class, ItemMeta::getMaxStackSize, ItemMeta::setMaxStackSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMaxDamage() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.MAX_DAMAGE, 120, Damageable.class, Damageable::getMaxDamage, Damageable::setMaxDamage);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDamage() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.DAMAGE, 120, Damageable.class, Damageable::getDamage, Damageable::setDamage);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnbreakable() {
|
||||
final ItemStack stack = new ItemStack(Material.STONE);
|
||||
stack.setData(DataComponentTypes.UNBREAKABLE, Unbreakable.unbreakable().showInTooltip(false).build());
|
||||
|
||||
Assertions.assertTrue(stack.getItemMeta().isUnbreakable());
|
||||
Assertions.assertTrue(stack.getItemMeta().getItemFlags().contains(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 testHideTooltip() {
|
||||
ItemStack stack = new ItemStack(Material.STONE);
|
||||
stack.setData(DataComponentTypes.HIDE_TOOLTIP);
|
||||
|
||||
Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.HIDE_TOOLTIP));
|
||||
Assertions.assertTrue(stack.getItemMeta().isHideTooltip());
|
||||
stack.unsetData(DataComponentTypes.HIDE_TOOLTIP);
|
||||
Assertions.assertFalse(stack.getItemMeta().isHideTooltip());
|
||||
stack = new ItemStack(Material.STONE);
|
||||
|
||||
stack.unsetData(DataComponentTypes.HIDE_TOOLTIP);
|
||||
Assertions.assertFalse(stack.getItemMeta().isHideTooltip());
|
||||
Assertions.assertEquals(stack.getItemMeta().isHideTooltip(), stack.hasData(DataComponentTypes.HIDE_TOOLTIP));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRepairCost() {
|
||||
final ItemStack stack = new ItemStack(Material.STONE);
|
||||
testWithMeta(stack, DataComponentTypes.REPAIR_COST, 120, Repairable.class, Repairable::getRepairCost, Repairable::setRepairCost);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomName() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.CUSTOM_NAME, Component.text("HELLO!!!!!!"), ItemMeta.class, ItemMeta::displayName, ItemMeta::displayName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItemName() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.ITEM_NAME, Component.text("HELLO!!!!!! ITEM NAME"), ItemMeta.class, ItemMeta::itemName, ItemMeta::itemName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItemLore() {
|
||||
List<Component> list = List.of(Component.text("1"), Component.text("2"));
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.LORE, ItemLore.lore().lines(list).build(), ItemLore::lines, ItemMeta.class, ItemMeta::lore, ItemMeta::lore);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItemRarity() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.RARITY, ItemRarity.RARE, ItemMeta.class, ItemMeta::getRarity, ItemMeta::setRarity);
|
||||
}
|
||||
|
||||
@Test
|
||||
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));
|
||||
|
||||
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_ENCHANTS));
|
||||
Assertions.assertEquals(1, stack.getItemMeta().getEnchantLevel(Enchantment.SOUL_SPEED));
|
||||
Assertions.assertEquals(stack.getItemMeta().getEnchants(), enchantmentIntegerMap);
|
||||
stack.unsetData(DataComponentTypes.ENCHANTMENTS);
|
||||
Assertions.assertTrue(stack.getItemMeta().getEnchants().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
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());
|
||||
|
||||
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_ATTRIBUTES));
|
||||
Assertions.assertEquals(modifier, ((List<AttributeModifier>) stack.getItemMeta().getAttributeModifiers(Attribute.ATTACK_DAMAGE)).getFirst());
|
||||
stack.unsetData(DataComponentTypes.ATTRIBUTE_MODIFIERS);
|
||||
Assertions.assertNull(stack.getItemMeta().getAttributeModifiers());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLegacyCustomModelData() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.CUSTOM_MODEL_DATA, CustomModelData.customModelData().addFloat(1).build(), customModelData -> customModelData.floats().get(0).intValue(), ItemMeta.class, ItemMeta::getCustomModelData, ItemMeta::setCustomModelData);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEnchantmentGlintOverride() {
|
||||
testWithMeta(new ItemStack(Material.STONE), DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true, ItemMeta.class, ItemMeta::getEnchantmentGlintOverride, ItemMeta::setEnchantmentGlintOverride);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFood() {
|
||||
FoodProperties properties = FoodProperties.food()
|
||||
.canAlwaysEat(true)
|
||||
.saturation(1.3F)
|
||||
.nutrition(1)
|
||||
.build();
|
||||
|
||||
final ItemStack stack = new ItemStack(Material.CROSSBOW);
|
||||
stack.setData(DataComponentTypes.FOOD, properties);
|
||||
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
FoodComponent component = meta.getFood();
|
||||
Assertions.assertEquals(properties.canAlwaysEat(), component.canAlwaysEat());
|
||||
Assertions.assertEquals(properties.saturation(), component.getSaturation());
|
||||
Assertions.assertEquals(properties.nutrition(), component.getNutrition());
|
||||
|
||||
stack.unsetData(DataComponentTypes.FOOD);
|
||||
meta = stack.getItemMeta();
|
||||
Assertions.assertFalse(meta.hasFood());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTool() {
|
||||
Tool properties = Tool.tool()
|
||||
.damagePerBlock(1)
|
||||
.defaultMiningSpeed(2F)
|
||||
.addRules(List.of(
|
||||
Tool.rule(
|
||||
RegistrySet.keySetFromValues(RegistryKey.BLOCK, List.of(BlockType.STONE, BlockType.GRAVEL)),
|
||||
2F,
|
||||
TriState.TRUE
|
||||
),
|
||||
Tool.rule(
|
||||
RegistryAccess.registryAccess().getRegistry(RegistryKey.BLOCK).getTag(TagKey.create(RegistryKey.BLOCK, NamespacedKey.minecraft("bamboo_blocks"))),
|
||||
2F,
|
||||
TriState.TRUE
|
||||
)
|
||||
))
|
||||
.build();
|
||||
|
||||
final ItemStack stack = new ItemStack(Material.CROSSBOW);
|
||||
stack.setData(DataComponentTypes.TOOL, properties);
|
||||
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
ToolComponent component = meta.getTool();
|
||||
Assertions.assertEquals(properties.damagePerBlock(), component.getDamagePerBlock());
|
||||
Assertions.assertEquals(properties.defaultMiningSpeed(), component.getDefaultMiningSpeed());
|
||||
|
||||
int idx = 0;
|
||||
for (ToolComponent.ToolRule effect : component.getRules()) {
|
||||
Assertions.assertEquals(properties.rules().get(idx).speed(), effect.getSpeed());
|
||||
Assertions.assertEquals(properties.rules().get(idx).correctForDrops().toBoolean(), effect.isCorrectForDrops());
|
||||
Assertions.assertEquals(properties.rules().get(idx).blocks().resolve(Registry.BLOCK), effect.getBlocks().stream().map(Material::asBlockType).toList());
|
||||
idx++;
|
||||
}
|
||||
|
||||
stack.unsetData(DataComponentTypes.TOOL);
|
||||
meta = stack.getItemMeta();
|
||||
Assertions.assertFalse(meta.hasTool());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testJukeboxPlayable() {
|
||||
JukeboxPlayable properties = JukeboxPlayable.jukeboxPlayable(JukeboxSong.MALL).build();
|
||||
|
||||
final ItemStack stack = new ItemStack(Material.BEEF);
|
||||
stack.setData(DataComponentTypes.JUKEBOX_PLAYABLE, properties);
|
||||
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
JukeboxPlayableComponent component = meta.getJukeboxPlayable();
|
||||
Assertions.assertEquals(properties.jukeboxSong(), component.getSong());
|
||||
|
||||
stack.unsetData(DataComponentTypes.JUKEBOX_PLAYABLE);
|
||||
meta = stack.getItemMeta();
|
||||
Assertions.assertFalse(meta.hasJukeboxPlayable());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDyedColor() {
|
||||
final ItemStack stack = new ItemStack(Material.LEATHER_CHESTPLATE);
|
||||
Color color = Color.BLUE;
|
||||
stack.setData(DataComponentTypes.DYED_COLOR, DyedItemColor.dyedItemColor(color, false));
|
||||
|
||||
Assertions.assertTrue(stack.getItemMeta().hasItemFlag(ItemFlag.HIDE_DYE));
|
||||
Assertions.assertEquals(color, ((LeatherArmorMeta) stack.getItemMeta()).getColor());
|
||||
stack.unsetData(DataComponentTypes.DYED_COLOR);
|
||||
Assertions.assertFalse(((LeatherArmorMeta) stack.getItemMeta()).isDyed());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMapColor() {
|
||||
testWithMeta(new ItemStack(Material.FILLED_MAP), DataComponentTypes.MAP_COLOR, MapItemColor.mapItemColor().color(Color.BLUE).build(), MapItemColor::color, MapMeta.class, MapMeta::getColor, MapMeta::setColor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMapId() {
|
||||
testWithMeta(new ItemStack(Material.FILLED_MAP), DataComponentTypes.MAP_ID, MapId.mapId(1), MapId::id, MapMeta.class, MapMeta::getMapId, MapMeta::setMapId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFireworks() {
|
||||
testWithMeta(new ItemStack(Material.FIREWORK_ROCKET), DataComponentTypes.FIREWORKS, Fireworks.fireworks(List.of(FireworkEffect.builder().build()), 1), Fireworks::effects, FireworkMeta.class, FireworkMeta::getEffects, (fireworkMeta, effects) -> {
|
||||
fireworkMeta.clearEffects();
|
||||
fireworkMeta.addEffects(effects);
|
||||
});
|
||||
|
||||
testWithMeta(new ItemStack(Material.FIREWORK_ROCKET), DataComponentTypes.FIREWORKS, Fireworks.fireworks(List.of(FireworkEffect.builder().build()), 1), Fireworks::flightDuration, FireworkMeta.class, FireworkMeta::getPower, FireworkMeta::setPower);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTrim() {
|
||||
final ItemStack stack = new ItemStack(Material.LEATHER_CHESTPLATE);
|
||||
ItemArmorTrim armorTrim = ItemArmorTrim.itemArmorTrim(new ArmorTrim(TrimMaterial.AMETHYST, TrimPattern.BOLT), false);
|
||||
stack.setData(DataComponentTypes.TRIM, armorTrim);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChargedProjectiles() {
|
||||
final ItemStack stack = new ItemStack(Material.CROSSBOW);
|
||||
ItemStack projectile = new ItemStack(Material.FIREWORK_ROCKET);
|
||||
stack.setData(DataComponentTypes.CHARGED_PROJECTILES, ChargedProjectiles.chargedProjectiles().add(projectile).build());
|
||||
|
||||
CrossbowMeta meta = (CrossbowMeta) stack.getItemMeta();
|
||||
Assertions.assertEquals(meta.getChargedProjectiles().getFirst(), projectile);
|
||||
|
||||
stack.unsetData(DataComponentTypes.CHARGED_PROJECTILES);
|
||||
meta = (CrossbowMeta) stack.getItemMeta();
|
||||
Assertions.assertTrue(meta.getChargedProjectiles().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPot() {
|
||||
final ItemStack stack = new ItemStack(Material.DECORATED_POT);
|
||||
stack.setData(DataComponentTypes.POT_DECORATIONS, PotDecorations.potDecorations().back(ItemType.DANGER_POTTERY_SHERD).build());
|
||||
|
||||
BlockState state = ((BlockStateMeta) stack.getItemMeta()).getBlockState();
|
||||
DecoratedPot decoratedPot = (DecoratedPot) state;
|
||||
|
||||
Assertions.assertEquals(decoratedPot.getSherd(DecoratedPot.Side.BACK), Material.DANGER_POTTERY_SHERD);
|
||||
stack.unsetData(DataComponentTypes.POT_DECORATIONS);
|
||||
decoratedPot = (DecoratedPot) ((BlockStateMeta) stack.getItemMeta()).getBlockState();
|
||||
Assertions.assertTrue(decoratedPot.getSherds().values().stream().allMatch((m) -> m.asItemType() == ItemType.BRICK));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecipes() {
|
||||
final ItemStack stack = new ItemStack(Material.KNOWLEDGE_BOOK);
|
||||
stack.setData(DataComponentTypes.RECIPES, List.of(Key.key("paper:fun_recipe")));
|
||||
|
||||
final ItemMeta itemMeta = stack.getItemMeta();
|
||||
Assertions.assertInstanceOf(KnowledgeBookMeta.class, itemMeta);
|
||||
|
||||
final List<NamespacedKey> recipes = ((KnowledgeBookMeta) itemMeta).getRecipes();
|
||||
Assertions.assertEquals(recipes, List.of(new NamespacedKey("paper", "fun_recipe")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testJukeboxWithEitherKey() {
|
||||
final ItemStack apiStack = CraftItemStack.asBukkitCopy(new net.minecraft.world.item.ItemStack(Items.MUSIC_DISC_5));
|
||||
final JukeboxPlayable data = apiStack.getData(DataComponentTypes.JUKEBOX_PLAYABLE);
|
||||
|
||||
Assertions.assertNotNull(data);
|
||||
Assertions.assertEquals(JukeboxSong.FIVE, data.jukeboxSong());
|
||||
}
|
||||
|
||||
@Test
|
||||
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
|
||||
));
|
||||
|
||||
final ItemStack apiStack = CraftItemStack.asBukkitCopy(internalStack);
|
||||
final JukeboxPlayable data = apiStack.getData(DataComponentTypes.JUKEBOX_PLAYABLE);
|
||||
|
||||
Assertions.assertNotNull(data);
|
||||
Assertions.assertEquals(JukeboxSong.FIVE, data.jukeboxSong());
|
||||
}
|
||||
|
||||
private static <T, M extends ItemMeta> void testWithMeta(final ItemStack stack, final DataComponentType.Valued<T> type, final T value, final Class<M> metaType, final Function<M, T> metaGetter, final BiConsumer<M, T> metaSetter) {
|
||||
testWithMeta(stack, type, value, Function.identity(), metaType, metaGetter, metaSetter);
|
||||
}
|
||||
|
||||
private static <T, M extends ItemMeta, R> void testWithMeta(final ItemStack stack, final DataComponentType.Valued<T> type, final T value, Function<T, R> mapper, final Class<M> metaType, final Function<M, R> metaGetter, final BiConsumer<M, R> metaSetter) {
|
||||
ItemStack original = stack.clone();
|
||||
stack.setData(type, value);
|
||||
|
||||
Assertions.assertEquals(value, stack.getData(type));
|
||||
|
||||
final ItemMeta meta = stack.getItemMeta();
|
||||
final M typedMeta = Assertions.assertInstanceOf(metaType, meta);
|
||||
|
||||
Assertions.assertEquals(metaGetter.apply(typedMeta), mapper.apply(value));
|
||||
|
||||
// SETTING
|
||||
metaSetter.accept(typedMeta, mapper.apply(value));
|
||||
original.setItemMeta(typedMeta);
|
||||
Assertions.assertEquals(value, original.getData(type));
|
||||
}
|
||||
|
||||
private static <M extends ItemMeta> void testWithMeta(final ItemStack stack, final DataComponentType.NonValued type, final boolean value, final Class<M> metaType, final Function<M, Boolean> metaGetter, final BiConsumer<M, Boolean> metaSetter) {
|
||||
ItemStack original = stack.clone();
|
||||
stack.setData(type);
|
||||
|
||||
Assertions.assertEquals(value, stack.hasData(type));
|
||||
|
||||
final ItemMeta meta = stack.getItemMeta();
|
||||
final M typedMeta = Assertions.assertInstanceOf(metaType, meta);
|
||||
|
||||
Assertions.assertEquals(metaGetter.apply(typedMeta), value);
|
||||
|
||||
// SETTING
|
||||
metaSetter.accept(typedMeta, value);
|
||||
original.setItemMeta(typedMeta);
|
||||
Assertions.assertEquals(value, original.hasData(type));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
package io.papermc.paper.item;
|
||||
|
||||
import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemFactory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemFactory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.support.environment.AllFeatures;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
// TODO: This should technically be used to compare legacy meta vs the newly implemented
|
||||
@AllFeatures
|
||||
public class MetaComparisonTest {
|
||||
|
||||
private static final ItemFactory FACTORY = CraftItemFactory.instance();
|
||||
|
||||
@Test
|
||||
public void testMetaApplication() {
|
||||
ItemStack itemStack = new ItemStack(Material.STONE);
|
||||
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
meta.setCustomModelData(1);
|
||||
|
||||
ItemMeta converted = FACTORY.asMetaFor(meta, Material.GOLD_INGOT);
|
||||
Assertions.assertEquals(converted.getCustomModelData(), meta.getCustomModelData());
|
||||
|
||||
ItemMeta convertedAdvanced = FACTORY.asMetaFor(meta, Material.PLAYER_HEAD);
|
||||
Assertions.assertEquals(convertedAdvanced.getCustomModelData(), meta.getCustomModelData());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaApplicationDowngrading() {
|
||||
ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD);
|
||||
PlayerProfile profile = Bukkit.createProfile("Owen1212055");
|
||||
|
||||
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
|
||||
meta.setPlayerProfile(profile);
|
||||
|
||||
SkullMeta converted = (SkullMeta) FACTORY.asMetaFor(meta, Material.PLAYER_HEAD);
|
||||
Assertions.assertEquals(converted.getPlayerProfile(), meta.getPlayerProfile());
|
||||
|
||||
SkullMeta downgraded = (SkullMeta) FACTORY.asMetaFor(FACTORY.asMetaFor(meta, Material.STONE), Material.PLAYER_HEAD);
|
||||
Assertions.assertNull(downgraded.getPlayerProfile());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaApplicationDowngradingPotion() {
|
||||
ItemStack itemStack = new ItemStack(Material.POTION);
|
||||
Color color = Color.BLUE;
|
||||
|
||||
PotionMeta meta = (PotionMeta) itemStack.getItemMeta();
|
||||
meta.setColor(color);
|
||||
|
||||
PotionMeta converted = (PotionMeta) FACTORY.asMetaFor(meta, Material.POTION);
|
||||
Assertions.assertEquals(converted.getColor(), color);
|
||||
|
||||
PotionMeta downgraded = (PotionMeta) FACTORY.asMetaFor(FACTORY.asMetaFor(meta, Material.STONE), Material.POTION);
|
||||
Assertions.assertNull(downgraded.getColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullMeta() {
|
||||
ItemStack itemStack = new ItemStack(Material.AIR);
|
||||
|
||||
Assertions.assertFalse(itemStack.hasItemMeta());
|
||||
Assertions.assertNull(itemStack.getItemMeta());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPotionMeta() {
|
||||
PotionEffect potionEffect = new PotionEffect(PotionEffectType.SPEED, 10, 10, false);
|
||||
ItemStack nmsItemStack = new ItemStack(Material.POTION, 1);
|
||||
|
||||
testSetAndGet(nmsItemStack,
|
||||
(meta) -> ((PotionMeta) meta).addCustomEffect(potionEffect, true),
|
||||
(meta) -> Assertions.assertEquals(potionEffect, ((PotionMeta) meta).getCustomEffects().getFirst())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnchantment() {
|
||||
ItemStack stack = new ItemStack(Material.STICK, 1);
|
||||
|
||||
testSetAndGet(stack,
|
||||
(meta) -> Assertions.assertTrue(meta.addEnchant(Enchantment.SHARPNESS, 1, true)),
|
||||
(meta) -> Assertions.assertEquals(1, meta.getEnchantLevel(Enchantment.SHARPNESS))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void testPlayerHead() {
|
||||
PlayerProfile profile = new CraftPlayerProfile(UUID.randomUUID(), "Owen1212055");
|
||||
ItemStack stack = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((SkullMeta) meta).setPlayerProfile(profile),
|
||||
(meta) -> {
|
||||
Assertions.assertTrue(((SkullMeta) meta).hasOwner());
|
||||
Assertions.assertEquals(profile, ((SkullMeta) meta).getPlayerProfile());
|
||||
}
|
||||
);
|
||||
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((SkullMeta) meta).setOwner("Owen1212055"),
|
||||
(meta) -> {
|
||||
Assertions.assertTrue(((SkullMeta) meta).hasOwner());
|
||||
Assertions.assertEquals("Owen1212055", ((SkullMeta) meta).getOwner());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBookMetaAuthor() {
|
||||
ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, 1);
|
||||
|
||||
// Legacy string
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).setAuthor("Owen1212055"),
|
||||
(meta) -> Assertions.assertEquals("Owen1212055", ((BookMeta) meta).getAuthor())
|
||||
);
|
||||
|
||||
// Component Colored
|
||||
Component coloredName = Component.text("Owen1212055", NamedTextColor.DARK_GRAY);
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).author(coloredName),
|
||||
(meta) -> Assertions.assertEquals(coloredName, ((BookMeta) meta).author())
|
||||
);
|
||||
|
||||
// Simple text
|
||||
Component name = Component.text("Owen1212055");
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).author(name),
|
||||
(meta) -> Assertions.assertEquals(name, ((BookMeta) meta).author())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBookMetaTitle() {
|
||||
ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, 1);
|
||||
|
||||
// Legacy string
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).setTitle("Owen1212055"),
|
||||
(meta) -> Assertions.assertEquals("Owen1212055", ((BookMeta) meta).getTitle())
|
||||
);
|
||||
|
||||
// Component Colored
|
||||
Component coloredName = Component.text("Owen1212055", NamedTextColor.DARK_GRAY);
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).title(coloredName),
|
||||
(meta) -> Assertions.assertEquals(coloredName, ((BookMeta) meta).title())
|
||||
);
|
||||
|
||||
// Simple text
|
||||
Component name = Component.text("Owen1212055");
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).title(name),
|
||||
(meta) -> Assertions.assertEquals(name, ((BookMeta) meta).title())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testWriteableBookPages() {
|
||||
ItemStack stack = new ItemStack(Material.WRITABLE_BOOK, 1);
|
||||
|
||||
// Writeable books are serialized as plain text, but has weird legacy color support.
|
||||
// So, we need to test to make sure that all works here.
|
||||
|
||||
// Legacy string
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPage("Owen1212055"),
|
||||
(meta) -> Assertions.assertEquals("Owen1212055", ((BookMeta) meta).getPage(1))
|
||||
);
|
||||
|
||||
// Legacy string colored
|
||||
String translatedLegacy = ChatColor.translateAlternateColorCodes('&', "&7Owen1212055");
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPage(translatedLegacy),
|
||||
(meta) -> Assertions.assertEquals(translatedLegacy, ((BookMeta) meta).getPage(1))
|
||||
);
|
||||
|
||||
// Component Colored
|
||||
Component coloredName = Component.text("Owen1212055", NamedTextColor.DARK_GRAY);
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPages(coloredName),
|
||||
(meta) -> Assertions.assertEquals(coloredName, ((BookMeta) meta).page(1))
|
||||
);
|
||||
|
||||
// Simple text
|
||||
Component name = Component.text("Owen1212055");
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPages(name),
|
||||
(meta) -> Assertions.assertEquals(name, ((BookMeta) meta).page(1))
|
||||
);
|
||||
|
||||
// Simple text + hover... should NOT be saved
|
||||
// As this is plain text
|
||||
Component nameWithHover = Component.text("Owen1212055")
|
||||
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("Hover")));
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPages(nameWithHover),
|
||||
(meta) -> Assertions.assertEquals(name, ((BookMeta) meta).page(1))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrittenBookPages() {
|
||||
ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, 1);
|
||||
|
||||
// Writeable books are serialized as plain text, but has weird legacy color support.
|
||||
// So, we need to test to make sure that all works here.
|
||||
|
||||
// Legacy string
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPage("Owen1212055"),
|
||||
(meta) -> Assertions.assertEquals("Owen1212055", ((BookMeta) meta).getPage(1))
|
||||
);
|
||||
|
||||
// Legacy string colored
|
||||
String translatedLegacy = ChatColor.translateAlternateColorCodes('&', "&7Owen1212055");
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPage(translatedLegacy),
|
||||
(meta) -> Assertions.assertEquals(translatedLegacy, ((BookMeta) meta).getPage(1))
|
||||
);
|
||||
|
||||
// Component Colored
|
||||
Component coloredName = Component.text("Owen1212055", NamedTextColor.DARK_GRAY);
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPages(coloredName),
|
||||
(meta) -> Assertions.assertEquals(coloredName, ((BookMeta) meta).page(1))
|
||||
);
|
||||
|
||||
// Simple text
|
||||
Component name = Component.text("Owen1212055");
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPages(name),
|
||||
(meta) -> Assertions.assertEquals(name, ((BookMeta) meta).page(1))
|
||||
);
|
||||
|
||||
// Simple text + hover... should be saved
|
||||
Component nameWithHover = Component.text("Owen1212055")
|
||||
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("Hover")));
|
||||
testSetAndGet(stack,
|
||||
(meta) -> ((BookMeta) meta).addPages(nameWithHover),
|
||||
(meta) -> Assertions.assertEquals(nameWithHover, ((BookMeta) meta).page(1))
|
||||
);
|
||||
}
|
||||
|
||||
private void testSetAndGet(ItemStack itemStack, Consumer<ItemMeta> set, Consumer<ItemMeta> get) {
|
||||
ItemMeta craftMeta = CraftItemStack.getItemMeta(CraftItemStack.asNMSCopy(itemStack)); // TODO: This should be converted to use the old meta when this is added.
|
||||
ItemMeta paperMeta = CraftItemStack.getItemMeta(CraftItemStack.asNMSCopy(itemStack));
|
||||
// Test craft meta
|
||||
set.accept(craftMeta);
|
||||
get.accept(craftMeta);
|
||||
|
||||
// Test paper meta
|
||||
set.accept(paperMeta);
|
||||
get.accept(paperMeta);
|
||||
}
|
||||
}
|
||||
@@ -101,17 +101,13 @@ public class PerMaterialTest {
|
||||
|
||||
final ItemStack bukkit = new ItemStack(material);
|
||||
final CraftItemStack craft = CraftItemStack.asCraftCopy(bukkit);
|
||||
if (material == Material.AIR) {
|
||||
final int MAX_AIR_STACK = 0 /* Why can't I hold all of these AIR? */;
|
||||
assertThat(material.getMaxStackSize(), is(MAX_AIR_STACK));
|
||||
assertThat(bukkit.getMaxStackSize(), is(MAX_AIR_STACK));
|
||||
assertThat(craft.getMaxStackSize(), is(MAX_AIR_STACK));
|
||||
} else {
|
||||
|
||||
// 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
|
||||
|
||||
@@ -100,6 +100,7 @@ public class RegistriesArgumentProvider implements ArgumentsProvider {
|
||||
register(RegistryKey.MAP_DECORATION_TYPE, MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, CraftMapCursor.CraftType.class, MapDecorationType.class);
|
||||
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);
|
||||
}
|
||||
|
||||
private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft) { // Paper
|
||||
|
||||
Reference in New Issue
Block a user