From a956ecd524ff611a2425bff75c287f019d2fd55d Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Sun, 23 Feb 2025 20:51:21 +0100 Subject: [PATCH] More data components - moved component-related helper methods to their own class, DataComponentHelper - ItemNBTHelper is now deprecated --- .../BindableSpecialFlowerBlockEntity.java | 22 +-- .../functional/HopperhockBlockEntity.java | 7 +- .../component/BotaniaDataComponents.java | 18 ++- .../component/HaloRecipeStorageComponent.java | 98 ------------ .../botania/common/component/StoredIds.java | 146 ++++++++++++++++++ .../common/helper/DataComponentHelper.java | 133 ++++++++++++++++ .../botania/common/helper/ItemNBTHelper.java | 85 +--------- .../corporea/CorporeaItemStackMatcher.java | 4 +- .../common/impl/mana/DefaultManaItemImpl.java | 4 +- .../botania/common/item/AssemblyHaloItem.java | 46 ++---- .../common/item/BlackHoleTalismanItem.java | 8 +- .../botania/common/item/CacophoniumItem.java | 29 ++-- .../common/item/ItemBackedInventory.java | 25 ++- .../common/item/LifeAggregatorItem.java | 78 ++++------ .../botania/common/item/ManaTabletItem.java | 4 +- .../common/item/ManufactoryHaloItem.java | 4 +- .../common/item/SlimeInABottleItem.java | 4 +- .../common/item/StoneOfTemperanceItem.java | 4 +- .../common/item/WandOfTheForestItem.java | 6 +- .../item/block/TinyPotatoBlockItem.java | 16 +- .../common/item/brew/BaseBrewItem.java | 4 +- .../common/item/brew/IncenseStickItem.java | 19 ++- .../armor/manasteel/ManasteelArmorItem.java | 4 +- .../item/equipment/bauble/BandOfManaItem.java | 4 +- .../item/equipment/bauble/BaubleItem.java | 4 +- .../equipment/bauble/CloakOfVirtueItem.java | 4 +- .../item/equipment/bauble/SpectatorItem.java | 6 +- .../bauble/TaintedBloodPendantItem.java | 16 +- .../tool/terrasteel/TerraShattererItem.java | 4 +- .../common/item/lens/CelebratoryLens.java | 49 ++---- .../botania/common/item/lens/LensItem.java | 4 +- .../botania/common/lib/LibComponentNames.java | 6 +- doc/1.21-data-components.md | 3 +- 33 files changed, 454 insertions(+), 414 deletions(-) delete mode 100644 Xplat/src/main/java/vazkii/botania/common/component/HaloRecipeStorageComponent.java create mode 100644 Xplat/src/main/java/vazkii/botania/common/component/StoredIds.java create mode 100644 Xplat/src/main/java/vazkii/botania/common/helper/DataComponentHelper.java diff --git a/Xplat/src/main/java/vazkii/botania/api/block_entity/BindableSpecialFlowerBlockEntity.java b/Xplat/src/main/java/vazkii/botania/api/block_entity/BindableSpecialFlowerBlockEntity.java index c12a53124c..cce66bd195 100644 --- a/Xplat/src/main/java/vazkii/botania/api/block_entity/BindableSpecialFlowerBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/api/block_entity/BindableSpecialFlowerBlockEntity.java @@ -41,7 +41,7 @@ * such as generating flowers to mana collectors, or functional flowers to pools. * Implements the bindability logic common to both types of flower. * - * @param Type of block entity this special flower cna bind to. + * @param Type of block entity this special flower can bind to. */ public abstract class BindableSpecialFlowerBlockEntity extends SpecialFlowerBlockEntity implements WandBindable { /** @@ -107,7 +107,7 @@ public void setBindingPos(@Nullable BlockPos bindingPos) { } } - public @Nullable T findBindCandidateAt(BlockPos pos) { + public @Nullable T findBindCandidateAt(@Nullable BlockPos pos) { if (level == null || pos == null) { return null; } @@ -132,6 +132,7 @@ public boolean isValidBinding() { return wouldBeValidBinding(bindingPos); } + @Nullable @Override public BlockPos getBinding() { //Used for Wand of the Forest overlays; only return the binding if it's valid. @@ -166,22 +167,7 @@ public void writeToPacketNBT(CompoundTag cmp, HolderLookup.Provider registries) public void readFromPacketNBT(CompoundTag cmp, HolderLookup.Provider registries) { super.readFromPacketNBT(cmp, registries); - if (cmp.contains(TAG_BINDING)) { - //todo bindingPos = NbtUtils.readBlockPos(cmp.getCompound(TAG_BINDING)); - } else { - //In older versions of the mod (1.16, early 1.17), GeneratingFlowerBlockEntity and SpecialFlowerBlockEntity - //implemented their own copies of the binding logic. Read data from the old locations. - if (cmp.contains("collectorX")) { - bindingPos = new BlockPos(cmp.getInt("collectorX"), cmp.getInt("collectorY"), cmp.getInt("collectorZ")); - } else if (cmp.contains("poolX")) { - bindingPos = new BlockPos(cmp.getInt("poolX"), cmp.getInt("poolY"), cmp.getInt("poolZ")); - } - //These versions of the mod also sometimes used a binding with a Y of -1 to signify an unbound flower. - //Currently, `null` is always used for unbound flowers. Coerce these positions to `null`. - if (bindingPos != null && bindingPos.getY() == -1) { - bindingPos = null; - } - } + NbtUtils.readBlockPos(cmp, TAG_BINDING).ifPresent(this::setBindingPos); } public abstract int getMana(); diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/HopperhockBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/HopperhockBlockEntity.java index b93197fa43..9a4eca6ceb 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/HopperhockBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/HopperhockBlockEntity.java @@ -32,10 +32,7 @@ import vazkii.botania.api.block_entity.FunctionalFlowerBlockEntity; import vazkii.botania.api.block_entity.RadiusDescriptor; import vazkii.botania.common.block.BotaniaFlowerBlocks; -import vazkii.botania.common.helper.DelayHelper; -import vazkii.botania.common.helper.EntityHelper; -import vazkii.botania.common.helper.InventoryHelper; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.*; import vazkii.botania.common.internal_caps.ItemFlagsComponent; import vazkii.botania.xplat.XplatAbstractions; @@ -156,7 +153,7 @@ public static boolean canAcceptItem(ItemStack stack, List filter, int } anyFilter = true; - if (ItemNBTHelper.matchTagAndManaFullness(stack, filterEntry)) { + if (DataComponentHelper.matchTagAndManaFullness(stack, filterEntry)) { return true; } } diff --git a/Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java b/Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java index aa2610a808..2775b28035 100644 --- a/Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java +++ b/Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java @@ -106,18 +106,15 @@ public class BotaniaDataComponents { public static final DataComponentType MANA_POOL_POS = make(LibComponentNames.MANA_POOL_POS, builder -> builder.persistent(GlobalPos.CODEC).networkSynchronized(GlobalPos.STREAM_CODEC)); - public static final DataComponentType RANGE = make(LibComponentNames.RANGE, - builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); - // crafting halo data public static final DataComponentType HALO_ROTATION_BASE = make(LibComponentNames.HALO_ROTATION_BASE, builder -> builder.networkSynchronized(ByteBufCodecs.FLOAT)); public static final DataComponentType LAST_RECIPE_ID = make(LibComponentNames.LAST_RECIPE_ID, builder -> builder.persistent(ResourceLocation.CODEC).networkSynchronized(ResourceLocation.STREAM_CODEC) ); - public static final DataComponentType STORED_RECIPES = make(LibComponentNames.STORED_RECIPES, - builder -> builder.persistent(HaloRecipeStorageComponent.CODEC) - .networkSynchronized(HaloRecipeStorageComponent.STREAM_CODEC).cacheEncoding()); + public static final DataComponentType STORED_RECIPES = make(LibComponentNames.STORED_RECIPES, + builder -> builder.persistent(StoredIds.CODEC).cacheEncoding() + .networkSynchronized(StoredIds.STREAM_CODEC)); public static final DataComponentType LAST_TRIGGER_TIME = make(LibComponentNames.LAST_TRIGGER_TIME, builder -> builder.persistent(Codec.LONG).networkSynchronized(ByteBufCodecs.VAR_LONG)); @@ -132,7 +129,7 @@ public class BotaniaDataComponents { */ public static final DataComponentType LENS_RAINBOW_TINT = makeUnit(LibComponentNames.LENS_RAINBOW_TINT); public static final DataComponentType ATTACHED_LENS = make(LibComponentNames.ATTACHED_LENS, - builder -> builder.persistent(ItemStack.CODEC).networkSynchronized(ItemStack.STREAM_CODEC).cacheEncoding()); + builder -> builder.persistent(ItemStack.CODEC).cacheEncoding().networkSynchronized(ItemStack.STREAM_CODEC)); // brews and similar consumables public static final DataComponentType BREW = make(LibComponentNames.BREW, @@ -166,6 +163,13 @@ public void encode(RegistryFriendlyByteBuf buffer, Long value) { public static final DataComponentType BLOCK_COUNT = make(LibComponentNames.BLOCK_COUNT, builder -> builder.persistent(ExtraCodecs.NON_NEGATIVE_INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static final DataComponentType RANGE = make(LibComponentNames.RANGE, + builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static final DataComponentType MOB_TYPE = make(LibComponentNames.MOB_TYPE, + builder -> builder.persistent(ResourceLocation.CODEC).networkSynchronized(ResourceLocation.STREAM_CODEC)); + public static final DataComponentType NOT_MY_NAME_STEP = make(LibComponentNames.NOT_MY_NAME_STEP, + builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static void registerComponents(BiConsumer, ResourceLocation> biConsumer) { for (Map.Entry> entry : ALL.entrySet()) { biConsumer.accept(entry.getValue(), botaniaRL(entry.getKey())); diff --git a/Xplat/src/main/java/vazkii/botania/common/component/HaloRecipeStorageComponent.java b/Xplat/src/main/java/vazkii/botania/common/component/HaloRecipeStorageComponent.java deleted file mode 100644 index 3f5c15d668..0000000000 --- a/Xplat/src/main/java/vazkii/botania/common/component/HaloRecipeStorageComponent.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This class is distributed as part of the Botania Mod. - * Get the Source Code in github: - * https://github.com/Vazkii/Botania - * - * Botania is Open Source and distributed under the - * Botania License: http://botaniamod.net/license.php - * - */ - -package vazkii.botania.common.component; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; - -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.resources.ResourceLocation; - -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.Map; - -import io.netty.buffer.ByteBuf; - -public class HaloRecipeStorageComponent { - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - Codec.INT.fieldOf("slots").forGetter(HaloRecipeStorageComponent::getNumSlots), - Codec.unboundedMap(Codec.INT, ResourceLocation.CODEC).fieldOf("recipes").forGetter(HaloRecipeStorageComponent::getPopulatedSlots) - ).apply(instance, HaloRecipeStorageComponent::create)); - - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.VAR_INT, HaloRecipeStorageComponent::getNumSlots, - ByteBufCodecs.map(Int2ObjectArrayMap::new, ByteBufCodecs.VAR_INT, ResourceLocation.STREAM_CODEC), HaloRecipeStorageComponent::getPopulatedSlots, - HaloRecipeStorageComponent::create - ); - - private static HaloRecipeStorageComponent create(Integer numSlots, Map recipesMap) { - var component = new HaloRecipeStorageComponent(numSlots); - recipesMap.forEach((slot, id) -> { - if (slot >= 0 && slot < numSlots) { - component.setSlot(slot, id); - } - }); - return component; - } - - private static Int2ObjectMap getPopulatedSlots(HaloRecipeStorageComponent component) { - var map = new Int2ObjectArrayMap(component.getNumSlots()); - for (int slot = 0; slot < component.getNumSlots(); slot++) { - var id = component.getSlot(slot); - if (id != null) { - map.put(slot, id); - } - } - return map; - } - - @Nullable - private final ResourceLocation[] recipeIds; - - public HaloRecipeStorageComponent(int slots) { - this.recipeIds = new ResourceLocation[slots]; - } - - public int getNumSlots() { - return recipeIds.length; - } - - public void setSlot(int slot, @Nullable ResourceLocation recipeId) { - recipeIds[slot] = recipeId; - } - - @Nullable - public ResourceLocation getSlot(int slot) { - return recipeIds[slot]; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof HaloRecipeStorageComponent that)) { - return false; - } - return Arrays.equals(recipeIds, that.recipeIds); - } - - @Override - public int hashCode() { - return Arrays.hashCode(recipeIds); - } -} diff --git a/Xplat/src/main/java/vazkii/botania/common/component/StoredIds.java b/Xplat/src/main/java/vazkii/botania/common/component/StoredIds.java new file mode 100644 index 0000000000..1f1a12282d --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/component/StoredIds.java @@ -0,0 +1,146 @@ +/* + * This class is distributed as part of the Botania Mod. + * Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under the + * Botania License: http://botaniamod.net/license.php + * + */ + +package vazkii.botania.common.component; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; + +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +import io.netty.buffer.ByteBuf; + +public class StoredIds { + public static final StoredIds EMPTY = new StoredIds(new ResourceLocation[0]); + public static final int MAX_SLOTS = 128; // happens to be a single byte if written as VAR_INT + + public static final Codec CODEC = Slot.CODEC.sizeLimitedListOf(MAX_SLOTS) + .xmap(StoredIds::fromSlots, StoredIds::getPopulatedSlots); + public static final StreamCodec STREAM_CODEC = Slot.STREAM_CODEC + .apply(ByteBufCodecs.list(MAX_SLOTS)) + .map(StoredIds::fromSlots, StoredIds::getPopulatedSlots); + + private static StoredIds fromSlots(List slots) { + OptionalInt lastSlotIndex = slots.stream().mapToInt(Slot::index).max(); + if (lastSlotIndex.isEmpty()) { + return EMPTY; + } + + var ids = new ResourceLocation[lastSlotIndex.getAsInt() + 1]; + for (Slot slot : slots) { + ids[slot.index] = slot.value; + } + + return new StoredIds(ids); + } + + private static List getPopulatedSlots(StoredIds storedIds) { + var ids = storedIds.ids; + List slots = new ArrayList<>(ids.length); + for (int i = 0; i < ids.length; i++) { + if (ids[i] != null) { + slots.add(new Slot(i, ids[i])); + } + } + return slots; + } + + @Nullable + private final ResourceLocation[] ids; + private final int cachedHashCode; + + private StoredIds(ResourceLocation[] idsToStore) { + ids = idsToStore; + cachedHashCode = Arrays.hashCode(idsToStore); + } + + public StoredIds store(int slot, @Nullable ResourceLocation newId) { + if (slot < 0 || slot >= MAX_SLOTS) { + throw new IndexOutOfBoundsException("Slot index must be positive and less than " + MAX_SLOTS + ", but was " + slot); + } + + if (slot < ids.length && Objects.equals(ids[slot], newId)) { + return this; + } + + int newLength = getNewLength(slot, newId); + + if (newLength == 0) { + return EMPTY; + } + + var idsCopy = Arrays.copyOf(ids, newLength); + if (slot < newLength) { + idsCopy[slot] = newId; + } + + return new StoredIds(idsCopy); + } + + private int getNewLength(int slot, @Nullable ResourceLocation newId) { + if (newId != null) { + // setting a slot, array might need to grow + return Math.max(ids.length, slot + 1); + + } + + if (slot == ids.length - 1) { + // clearing last entry, trim array to have no empty slots at the end + int newLastSlot = slot; + //noinspection StatementWithEmptyBody + while (--newLastSlot >= 0 && ids[newLastSlot] == null) {} + return newLastSlot + 1; + + } + + // clearing a slot that is not the last one, array will keep its length + return ids.length; + } + + @Nullable + public ResourceLocation getSlot(int slot) { + return slot >= 0 && slot < ids.length ? ids[slot] : null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof StoredIds that)) { + return false; + } + return Arrays.equals(ids, that.ids); + } + + @Override + public int hashCode() { + return cachedHashCode; + } + + public record Slot(int index, ResourceLocation value) { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.intRange(0, MAX_SLOTS).fieldOf("index").forGetter(Slot::index), + ResourceLocation.CODEC.fieldOf("value").forGetter(Slot::value) + ).apply(instance, Slot::new)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.VAR_INT, Slot::index, + ResourceLocation.STREAM_CODEC, Slot::value, + Slot::new + ); + } +} diff --git a/Xplat/src/main/java/vazkii/botania/common/helper/DataComponentHelper.java b/Xplat/src/main/java/vazkii/botania/common/helper/DataComponentHelper.java new file mode 100644 index 0000000000..84dab718ac --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/helper/DataComponentHelper.java @@ -0,0 +1,133 @@ +/* + * This class is distributed as part of the Botania Mod. + * Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under the + * Botania License: http://botaniamod.net/license.php + * + */ + +package vazkii.botania.common.helper; + +import net.minecraft.core.component.DataComponentType; +import net.minecraft.util.Unit; +import net.minecraft.world.item.ItemStack; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; + +import vazkii.botania.api.mana.ManaItem; +import vazkii.botania.xplat.XplatAbstractions; + +import java.util.Collection; + +public final class DataComponentHelper { + /** + * Sets an Integer component of the ItemStack to the specified value. + * If the value is zero, that component is removed instead. + */ + @Contract(mutates = "param1") + public static void setIntNonZero(ItemStack stack, DataComponentType component, int value) { + if (value == 0) { + stack.remove(component); + } else { + stack.set(component, value); + } + } + + /** + * Ensures a {@link Unit} component is present on the ItemStack if the value is true, + * otherwise ensures that component is not present. + */ + @Contract(mutates = "param1") + public static void setFlag(ItemStack stack, DataComponentType component, boolean value) { + if (value) { + stack.set(component, Unit.INSTANCE); + } else { + stack.remove(component); + } + } + + /** + * Sets a component of the ItemStack to a value. If that value is null, the component is removed instead. + */ + @Contract(mutates = "param1") + public static void setOptional(ItemStack stack, DataComponentType component, @Nullable T value) { + if (value == null) { + stack.remove(component); + } else { + stack.set(component, value); + } + } + + /** + * Sets a component of the ItemStack to a non-default value. + * If the value is null or equal to the specified default value, the component is removed instead. + */ + @Contract(mutates = "param1") + public static void setUnlessDefault(ItemStack stack, DataComponentType component, @Nullable T value, T defaultValue) { + if (value == null || value.equals(defaultValue)) { + stack.remove(component); + } else { + stack.set(component, value); + } + } + + /** + * Sets a collection component of the ItemStack to the specified collection. + * If that collection is null or empty, the component is removed instead. + */ + @Contract(mutates = "param1") + public static > void setNonEmpty(ItemStack stack, DataComponentType component, @Nullable C collection) { + if (collection == null || collection.isEmpty()) { + stack.remove(component); + } else { + stack.set(component, collection); + } + } + + /** + * Returns the fullness of the mana item: + * 0 if empty, 1 if partially full, 2 if full. + */ + public static int getFullness(ManaItem item) { + int mana = item.getMana(); + if (mana == 0) { + return 0; + } else if (mana == item.getMaxMana()) { + return 2; + } else { + return 1; + } + } + + public static ItemStack duplicateAndClearMana(ItemStack stack) { + ItemStack copy = stack.copy(); + ManaItem manaItem = XplatAbstractions.INSTANCE.findManaItem(copy); + if (manaItem != null) { + manaItem.addMana(-manaItem.getMana()); + } + return copy; + } + + /** + * Checks if two items are the same and have the same NBT. If they are `IManaItems`, their mana property is matched + * on whether they are empty, partially full, or full. + */ + public static boolean matchTagAndManaFullness(ItemStack stack1, ItemStack stack2) { + if (!ItemStack.isSameItem(stack1, stack2)) { + return false; + } + ManaItem manaItem1 = XplatAbstractions.INSTANCE.findManaItem(stack1); + ManaItem manaItem2 = XplatAbstractions.INSTANCE.findManaItem(stack2); + if (manaItem1 != null && manaItem2 != null) { + if (getFullness(manaItem1) != getFullness(manaItem2)) { + return false; + } else { + return ItemStack.matches(duplicateAndClearMana(stack1), duplicateAndClearMana(stack2)); + } + } + return ItemStack.isSameItemSameComponents(stack1, stack2); + } +} diff --git a/Xplat/src/main/java/vazkii/botania/common/helper/ItemNBTHelper.java b/Xplat/src/main/java/vazkii/botania/common/helper/ItemNBTHelper.java index 3817b03ea8..5700ae84e7 100644 --- a/Xplat/src/main/java/vazkii/botania/common/helper/ItemNBTHelper.java +++ b/Xplat/src/main/java/vazkii/botania/common/helper/ItemNBTHelper.java @@ -12,57 +12,18 @@ import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; -import net.minecraft.core.component.DataComponentType; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; -import net.minecraft.util.Unit; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nullable; -import vazkii.botania.api.mana.ManaItem; -import vazkii.botania.xplat.XplatAbstractions; - -import java.util.Collection; - -// TODO clean out all NBT methods, none of them should be used +@Deprecated(forRemoval = true) public final class ItemNBTHelper { - public static void setIntNonZero(ItemStack stack, DataComponentType component, int value) { - if (value == 0) { - stack.remove(component); - } else { - stack.set(component, value); - } - } - - public static void setFlag(ItemStack stack, DataComponentType component, boolean value) { - if (value) { - stack.set(component, Unit.INSTANCE); - } else { - stack.remove(component); - } - } - - public static void setOptional(ItemStack stack, DataComponentType component, @Nullable T value) { - if (value == null) { - stack.remove(component); - } else { - stack.set(component, value); - } - } - - public static > void setNonEmpty(ItemStack stack, DataComponentType component, @Nullable C collection) { - if (collection == null || collection.isEmpty()) { - stack.remove(component); - } else { - stack.set(component, collection); - } - } - private static final int[] EMPTY_INT_ARRAY = new int[0]; private static final long[] EMPTY_LONG_ARRAY = new long[0]; @@ -231,50 +192,6 @@ public static ListTag getList(ItemStack stack, String tag, int objtype, boolean // OTHER /////////////////////////////////////////////////////////////////// - /** - * Returns the fullness of the mana item: - * 0 if empty, 1 if partially full, 2 if full. - */ - public static int getFullness(ManaItem item) { - int mana = item.getMana(); - if (mana == 0) { - return 0; - } else if (mana == item.getMaxMana()) { - return 2; - } else { - return 1; - } - } - - public static ItemStack duplicateAndClearMana(ItemStack stack) { - ItemStack copy = stack.copy(); - ManaItem manaItem = XplatAbstractions.INSTANCE.findManaItem(copy); - if (manaItem != null) { - manaItem.addMana(-manaItem.getMana()); - } - return copy; - } - - /** - * Checks if two items are the same and have the same NBT. If they are `IManaItems`, their mana property is matched - * on whether they are empty, partially full, or full. - */ - public static boolean matchTagAndManaFullness(ItemStack stack1, ItemStack stack2) { - if (!ItemStack.isSameItem(stack1, stack2)) { - return false; - } - ManaItem manaItem1 = XplatAbstractions.INSTANCE.findManaItem(stack1); - ManaItem manaItem2 = XplatAbstractions.INSTANCE.findManaItem(stack2); - if (manaItem1 != null && manaItem2 != null) { - if (getFullness(manaItem1) != getFullness(manaItem2)) { - return false; - } else { - return ItemStack.matches(duplicateAndClearMana(stack1), duplicateAndClearMana(stack2)); - } - } - return ItemStack.isSameItemSameComponents(stack1, stack2); - } - /** * Serializes the given stack such that {@link net.minecraft.world.item.crafting.ShapedRecipe#CODEC} * would be able to read the result back diff --git a/Xplat/src/main/java/vazkii/botania/common/impl/corporea/CorporeaItemStackMatcher.java b/Xplat/src/main/java/vazkii/botania/common/impl/corporea/CorporeaItemStackMatcher.java index 249d358a9a..9a623ee103 100644 --- a/Xplat/src/main/java/vazkii/botania/common/impl/corporea/CorporeaItemStackMatcher.java +++ b/Xplat/src/main/java/vazkii/botania/common/impl/corporea/CorporeaItemStackMatcher.java @@ -13,7 +13,7 @@ import net.minecraft.world.item.ItemStack; import vazkii.botania.api.corporea.CorporeaRequestMatcher; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; public class CorporeaItemStackMatcher implements CorporeaRequestMatcher { private static final String TAG_REQUEST_STACK = "requestStack"; @@ -29,7 +29,7 @@ public CorporeaItemStackMatcher(ItemStack match, boolean checkNBT) { @Override public boolean test(ItemStack stack) { - return !stack.isEmpty() && !match.isEmpty() && ItemStack.isSameItem(stack, match) && (!checkNBT || ItemNBTHelper.matchTagAndManaFullness(stack, match)); + return !stack.isEmpty() && !match.isEmpty() && ItemStack.isSameItem(stack, match) && (!checkNBT || DataComponentHelper.matchTagAndManaFullness(stack, match)); } public static CorporeaItemStackMatcher createFromNBT(CompoundTag tag) { diff --git a/Xplat/src/main/java/vazkii/botania/common/impl/mana/DefaultManaItemImpl.java b/Xplat/src/main/java/vazkii/botania/common/impl/mana/DefaultManaItemImpl.java index 3c692e6527..fe829cee51 100644 --- a/Xplat/src/main/java/vazkii/botania/common/impl/mana/DefaultManaItemImpl.java +++ b/Xplat/src/main/java/vazkii/botania/common/impl/mana/DefaultManaItemImpl.java @@ -15,7 +15,7 @@ import vazkii.botania.api.mana.ManaItem; import vazkii.botania.common.component.BotaniaDataComponents; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; /** * Default implementation for the {@link ManaItem} interface. This implementation covers all of Botania's own mana @@ -44,7 +44,7 @@ public void addMana(int mana) { return; } - ItemNBTHelper.setIntNonZero(stack, BotaniaDataComponents.MANA, Math.min(getMana() + mana, getMaxMana())); + DataComponentHelper.setIntNonZero(stack, BotaniaDataComponents.MANA, Math.min(getMana() + mana, getMaxMana())); Integer manaBacklog = stack.get(BotaniaDataComponents.MANA_BACKLOG); if (manaBacklog != null) { stack.set(BotaniaDataComponents.MANA_BACKLOG, manaBacklog + mana); diff --git a/Xplat/src/main/java/vazkii/botania/common/item/AssemblyHaloItem.java b/Xplat/src/main/java/vazkii/botania/common/item/AssemblyHaloItem.java index e70c2d2887..b63f4493c9 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/AssemblyHaloItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/AssemblyHaloItem.java @@ -57,8 +57,8 @@ import vazkii.botania.client.lib.ResourcesLib; import vazkii.botania.common.annotations.SoftImplement; import vazkii.botania.common.component.BotaniaDataComponents; -import vazkii.botania.common.component.HaloRecipeStorageComponent; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.component.StoredIds; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.helper.PlayerHelper; import vazkii.botania.common.helper.VecHelper; import vazkii.botania.network.EffectType; @@ -76,11 +76,7 @@ public class AssemblyHaloItem extends Item { public static final int SEGMENTS = 12; public AssemblyHaloItem(Properties props) { - super(props.component(BotaniaDataComponents.STORED_RECIPES, createRecipeStorage())); - } - - private static HaloRecipeStorageComponent createRecipeStorage() { - return new HaloRecipeStorageComponent(SEGMENTS - 1); + super(props.component(BotaniaDataComponents.STORED_RECIPES, StoredIds.EMPTY)); } @Override @@ -255,40 +251,32 @@ private static float getCheckingAngle(LivingEntity living, float base) { } @Nullable - private static RecipeHolder getSavedRecipe(Level world, ItemStack halo, int position) { - if (position <= 0 || position >= SEGMENTS) { - return null; - } - var storedRecipes = halo.get(BotaniaDataComponents.STORED_RECIPES); - if (storedRecipes == null) { + private static RecipeHolder getSavedRecipe(Level world, ItemStack halo, int segment) { + if (segment <= 0 || segment >= SEGMENTS) { return null; } - ResourceLocation id = storedRecipes.getSlot(position - 1); + var storedRecipes = halo.getOrDefault(BotaniaDataComponents.STORED_RECIPES, StoredIds.EMPTY); + ResourceLocation id = storedRecipes.getSlot(segment - 1); return id != null ? getRecipeHolder(world, id) : null; } - private static void saveRecipe(ItemStack halo, @Nullable ResourceLocation id, int position) { - if (position <= 0 || position >= SEGMENTS) { + private static void saveRecipe(ItemStack halo, @Nullable ResourceLocation id, int segment) { + if (segment <= 0 || segment >= SEGMENTS) { return; } - var storedRecipes = halo.get(BotaniaDataComponents.STORED_RECIPES); - if (storedRecipes == null) { - storedRecipes = createRecipeStorage(); - halo.set(BotaniaDataComponents.STORED_RECIPES, storedRecipes); - } - - storedRecipes.setSlot(position - 1, id); + var storedRecipes = halo.getOrDefault(BotaniaDataComponents.STORED_RECIPES, StoredIds.EMPTY); + halo.set(BotaniaDataComponents.STORED_RECIPES, storedRecipes.store(segment - 1, id)); } - private static ItemStack getDisplayItem(Level world, ItemStack stack, int position) { - if (position == 0) { + private static ItemStack getDisplayItem(Level world, ItemStack stack, int segment) { + if (segment == 0) { return craftingTable; - } else if (position >= SEGMENTS) { + } else if (segment >= SEGMENTS) { return ItemStack.EMPTY; } else { - RecipeHolder> recipeHolder = getSavedRecipe(world, stack, position); + RecipeHolder> recipeHolder = getSavedRecipe(world, stack, segment); if (recipeHolder != null) { return recipeHolder.value().getResultItem(world.registryAccess()); } else { @@ -317,7 +305,7 @@ public static void onItemCrafted(Player player, Container inv) { } private static void rememberLastRecipe(ResourceLocation recipeId, ItemStack halo) { - ItemNBTHelper.setOptional(halo, BotaniaDataComponents.LAST_RECIPE_ID, recipeId); + DataComponentHelper.setOptional(halo, BotaniaDataComponents.LAST_RECIPE_ID, recipeId); } @Nullable @@ -339,7 +327,7 @@ private static boolean wasEquipped(ItemStack stack) { } private static void setEquipped(ItemStack stack, boolean equipped) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.ACTIVE_TRANSIENT, equipped); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.ACTIVE_TRANSIENT, equipped); } private static float getRotationBase(ItemStack stack) { diff --git a/Xplat/src/main/java/vazkii/botania/common/item/BlackHoleTalismanItem.java b/Xplat/src/main/java/vazkii/botania/common/item/BlackHoleTalismanItem.java index d0f65d7c7a..0980d4f553 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/BlackHoleTalismanItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/BlackHoleTalismanItem.java @@ -42,7 +42,7 @@ import vazkii.botania.client.gui.ItemsRemainingRenderHandler; import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.BotaniaSounds; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.helper.PlayerHelper; import java.util.List; @@ -57,7 +57,7 @@ public BlackHoleTalismanItem(Properties props) { public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); if (getBlock(stack) != null && player.isSecondaryUseActive()) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, !stack.has(BotaniaDataComponents.ACTIVE)); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, !stack.has(BotaniaDataComponents.ACTIVE)); player.playSound(BotaniaSounds.blackHoleTalismanConfigure, 1F, 1F); return InteractionResultHolder.sidedSuccess(stack, world.isClientSide()); } @@ -173,7 +173,7 @@ public Component getName(ItemStack stack) { public static boolean setBlock(ItemStack stack, Block block) { if (block.asItem() != Items.AIR && (getBlock(stack) == null || getBlockCount(stack) == 0)) { - ItemNBTHelper.setOptional(stack, BotaniaDataComponents.BLOCK_TYPE, BuiltInRegistries.BLOCK.getKey(block)); + DataComponentHelper.setOptional(stack, BotaniaDataComponents.BLOCK_TYPE, BuiltInRegistries.BLOCK.getKey(block)); return true; } return false; @@ -198,7 +198,7 @@ public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag flags) { + public void appendHoverText(ItemStack stack, TooltipContext context, List infoList, TooltipFlag flags) { if (isDOIT(stack)) { - list.add(Component.translatable("botaniamisc.justDoIt").withStyle(ChatFormatting.GRAY)); + infoList.add(Component.translatable("botaniamisc.justDoIt").withStyle(ChatFormatting.GRAY)); } else if (getSound(stack) != null) { - list.add(Component.translatable(ItemNBTHelper.getString(stack, TAG_SOUND_NAME, "")).withStyle(ChatFormatting.GRAY)); + ResourceLocation id = stack.get(BotaniaDataComponents.MOB_TYPE); + if (id != null) { + BuiltInRegistries.ENTITY_TYPE.getOptional(id).ifPresent( + type -> infoList.add(type.getDescription().copy().withStyle(ChatFormatting.GRAY))); + } } } @@ -153,11 +154,7 @@ public static SoundEvent getSound(ItemStack stack) { if (isDOIT(stack)) { return BotaniaSounds.doit; } else { - try { - return BuiltInRegistries.SOUND_EVENT.get(ResourceLocation.parse(ItemNBTHelper.getString(stack, TAG_SOUND, ""))); - } catch (ResourceLocationException ex) { - return null; - } + return BuiltInRegistries.SOUND_EVENT.get(stack.get(DataComponents.NOTE_BLOCK_SOUND)); } } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/ItemBackedInventory.java b/Xplat/src/main/java/vazkii/botania/common/item/ItemBackedInventory.java index 97da0f18bc..d995112c18 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/ItemBackedInventory.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/ItemBackedInventory.java @@ -8,30 +8,27 @@ */ package vazkii.botania.common.item; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ItemContainerContents; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; /** - * An inventory that writes into the provided stack's NBT on save + * An inventory that writes into the provided stack's {@link net.minecraft.core.component.DataComponents#CONTAINER} on + * save */ public class ItemBackedInventory extends SimpleContainer { - private static final String TAG_ITEMS = "Items"; private final ItemStack stack; public ItemBackedInventory(ItemStack stack, int expectedSize) { super(expectedSize); this.stack = stack; - ListTag lst = ItemNBTHelper.getList(stack, TAG_ITEMS, Tag.TAG_COMPOUND, false); - int i = 0; - for (; i < expectedSize && i < lst.size(); i++) { - setItem(i, /*ItemStack.of(lst.getCompound(i))*/ ItemStack.EMPTY); - } + var contents = stack.getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY); + contents.copyInto(getItems()); } @Override @@ -42,10 +39,8 @@ public boolean stillValid(Player player) { @Override public void setChanged() { super.setChanged(); - ListTag list = new ListTag(); - for (int i = 0; i < getContainerSize(); i++) { - //todo list.add(getItem(i).save(new CompoundTag())); - } - ItemNBTHelper.setList(stack, TAG_ITEMS, list); + + ItemContainerContents contents = ItemContainerContents.fromItems(getItems()); + DataComponentHelper.setUnlessDefault(stack, DataComponents.CONTAINER, contents, ItemContainerContents.EMPTY); } } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/LifeAggregatorItem.java b/Xplat/src/main/java/vazkii/botania/common/item/LifeAggregatorItem.java index e171037e7a..1b8582aaf4 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/LifeAggregatorItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/LifeAggregatorItem.java @@ -10,81 +10,65 @@ import com.mojang.datafixers.util.Pair; +import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; -import net.minecraft.world.level.SpawnData; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.SpawnerBlockEntity; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import vazkii.botania.client.fx.SparkleParticleData; import vazkii.botania.client.fx.WispParticleData; import vazkii.botania.common.advancements.UseItemSuccessTrigger; +import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.helper.PlayerHelper; import java.util.List; public class LifeAggregatorItem extends Item { - private static final String TAG_SPAWNER = "spawner"; - private static final String TAG_SPAWN_DATA = "SpawnData"; - private static final String TAG_ID = "id"; - public LifeAggregatorItem(Properties props) { super(props); } - @Nullable - private static ResourceLocation getEntityId(ItemStack stack) { - CompoundTag tag = /*todo stack.getTagElement(TAG_SPAWNER)*/ null; - if (tag != null && tag.contains(TAG_SPAWN_DATA)) { - tag = tag.getCompound(TAG_SPAWN_DATA); - var spawnData = SpawnData.CODEC.parse(NbtOps.INSTANCE, tag); - return spawnData.result() - .filter(sd -> sd.getEntityToSpawn().contains(TAG_ID)) - .map(sd -> ResourceLocation.tryParse(sd.getEntityToSpawn().getString(TAG_ID))) - .orElse(null); - } - - return null; - } - public static boolean hasData(ItemStack stack) { - return getEntityId(stack) != null; + return stack.has(DataComponents.BLOCK_ENTITY_DATA); } @Override public void appendHoverText(ItemStack stack, TooltipContext context, List infoList, TooltipFlag flags) { - ResourceLocation id = getEntityId(stack); + ResourceLocation id = stack.get(BotaniaDataComponents.MOB_TYPE); if (id != null) { - BuiltInRegistries.ENTITY_TYPE.getOptional(id).ifPresent(type -> infoList.add(type.getDescription())); + BuiltInRegistries.ENTITY_TYPE.getOptional(id).ifPresent( + type -> infoList.add(type.getDescription().copy().withStyle(ChatFormatting.GRAY))); } } @NotNull @Override public InteractionResult useOn(UseOnContext ctx) { - if (getEntityId(ctx.getItemInHand()) == null) { + if (hasData(ctx.getItemInHand())) { + return placeSpawner(ctx); + } else { return captureSpawner(ctx) ? InteractionResult.sidedSuccess(ctx.getLevel().isClientSide()) : InteractionResult.PASS; - } else { - return placeSpawner(ctx); } } @@ -98,22 +82,18 @@ private InteractionResult placeSpawner(UseOnContext ctx) { ItemStack mover = ctx.getItemInHand(); if (!world.isClientSide) { - if (ctx.getPlayer() != null) { - //todo ctx.getPlayer().broadcastBreakEvent(ctx.getHand()); + Player player = ctx.getPlayer(); + if (player != null) { + player.onEquippedItemBroken(this, LivingEntity.getSlotForHand(ctx.getHand())); } - mover.shrink(1); - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof SpawnerBlockEntity) { - /*todo - CompoundTag spawnerTag = ctx.getItemInHand().getTagElement(TAG_SPAWNER).copy(); - spawnerTag.putInt("x", pos.getX()); - spawnerTag.putInt("y", pos.getY()); - spawnerTag.putInt("z", pos.getZ()); - te.load(spawnerTag); - - */ + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof SpawnerBlockEntity) { + blockEntity.loadWithComponents(mover.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(), + world.registryAccess()); } + // must empty stack last, as otherwise components become inaccessible + mover.shrink(1); } else { for (int i = 0; i < 100; i++) { SparkleParticleData data = SparkleParticleData.sparkle(0.45F + 0.2F * (float) Math.random(), (float) Math.random(), (float) Math.random(), (float) Math.random(), 6); @@ -131,10 +111,18 @@ private boolean captureSpawner(UseOnContext ctx) { ItemStack stack = ctx.getItemInHand(); Player player = ctx.getPlayer(); + // TODO: support trial spawners if (world.getBlockState(pos).is(Blocks.SPAWNER)) { if (!world.isClientSide) { - BlockEntity te = world.getBlockEntity(pos); - //todo stack.getOrCreateTag().put(TAG_SPAWNER, te.saveWithFullMetadata()); + SpawnerBlockEntity spawnerBlockEntity = (SpawnerBlockEntity) world.getBlockEntity(pos); + Entity displayEntity = spawnerBlockEntity.getSpawner().getOrCreateDisplayEntity(world, pos); + if (displayEntity != null) { + // TODO: does this make sense or is it better to navigate the NBT data for the entity ID? + stack.set(BotaniaDataComponents.MOB_TYPE, BuiltInRegistries.ENTITY_TYPE.getKey(displayEntity.getType())); + } + stack.set(DataComponents.BLOCK_ENTITY_DATA, + // black-box serialized data; no need for metadata, or component transfer to this item + CustomData.of(spawnerBlockEntity.saveWithoutMetadata(world.registryAccess()))); world.destroyBlock(pos, false); if (player != null) { player.getCooldowns().addCooldown(this, 20); @@ -142,7 +130,7 @@ private boolean captureSpawner(UseOnContext ctx) { UseItemSuccessTrigger.INSTANCE.trigger(serverPlayer, stack, serverPlayer.serverLevel(), pos.getX(), pos.getY(), pos.getZ()); } - //todo player.broadcastBreakEvent(ctx.getHand()); + player.onEquippedItemBroken(this, LivingEntity.getSlotForHand(ctx.getHand())); } } else { for (int i = 0; i < 50; i++) { diff --git a/Xplat/src/main/java/vazkii/botania/common/item/ManaTabletItem.java b/Xplat/src/main/java/vazkii/botania/common/item/ManaTabletItem.java index d4d90159ec..47c792d44a 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/ManaTabletItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/ManaTabletItem.java @@ -17,7 +17,7 @@ import vazkii.botania.api.mana.ManaBarTooltip; import vazkii.botania.common.component.BotaniaDataComponents; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.xplat.XplatAbstractions; import java.util.List; @@ -68,7 +68,7 @@ public Optional getTooltipImage(ItemStack stack) { } protected static void setMana(ItemStack stack, int mana) { - ItemNBTHelper.setIntNonZero(stack, BotaniaDataComponents.MANA, mana); + DataComponentHelper.setIntNonZero(stack, BotaniaDataComponents.MANA, mana); } public static void setStackCreative(ItemStack stack) { diff --git a/Xplat/src/main/java/vazkii/botania/common/item/ManufactoryHaloItem.java b/Xplat/src/main/java/vazkii/botania/common/item/ManufactoryHaloItem.java index 63c9eba47f..0f00443f84 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/ManufactoryHaloItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/ManufactoryHaloItem.java @@ -27,7 +27,7 @@ import vazkii.botania.client.lib.ResourcesLib; import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.BotaniaSounds; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import java.util.List; @@ -89,7 +89,7 @@ public boolean overrideOtherStackedOnMe(ItemStack stack, ItemStack cursor, Slot } private void togglePassive(ItemStack stack, LivingEntity living, Level world) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, !isActive(stack)); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, !isActive(stack)); if (living instanceof Player player) { world.playSound(player, player.getX(), player.getY(), player.getZ(), BotaniaSounds.manufactoryHaloConfigure, SoundSource.NEUTRAL, 1F, 1F); } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/SlimeInABottleItem.java b/Xplat/src/main/java/vazkii/botania/common/item/SlimeInABottleItem.java index a7fe789279..c4c7a5fdbf 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/SlimeInABottleItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/SlimeInABottleItem.java @@ -15,7 +15,7 @@ import vazkii.botania.common.block.flower.generating.NarslimmusBlockEntity; import vazkii.botania.common.component.BotaniaDataComponents; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; public class SlimeInABottleItem extends Item { @@ -27,7 +27,7 @@ public SlimeInABottleItem(Properties builder) { public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { if (!level.isClientSide) { boolean slime = NarslimmusBlockEntity.isSlimeChunk(level, entity.blockPosition()); - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.ACTIVE_TRANSIENT, slime); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.ACTIVE_TRANSIENT, slime); } } } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/StoneOfTemperanceItem.java b/Xplat/src/main/java/vazkii/botania/common/item/StoneOfTemperanceItem.java index 07c0fa8af0..3cb1de44ec 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/StoneOfTemperanceItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/StoneOfTemperanceItem.java @@ -24,7 +24,7 @@ import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.BotaniaSounds; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import java.util.List; @@ -71,7 +71,7 @@ public boolean overrideOtherStackedOnMe(ItemStack stack, ItemStack cursor, Slot } private void toggleActive(ItemStack stack, Player player, Level world) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, !stack.has(BotaniaDataComponents.ACTIVE)); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, !stack.has(BotaniaDataComponents.ACTIVE)); world.playSound(player, player.getX(), player.getY(), player.getZ(), BotaniaSounds.temperanceStoneConfigure, SoundSource.NEUTRAL, 1F, 1F); } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/WandOfTheForestItem.java b/Xplat/src/main/java/vazkii/botania/common/item/WandOfTheForestItem.java index e93241c2c1..7d19169845 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/WandOfTheForestItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/WandOfTheForestItem.java @@ -52,7 +52,7 @@ import vazkii.botania.common.block.block_entity.ManaEnchanterBlockEntity; import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.BotaniaSounds; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.helper.PlayerHelper; import vazkii.botania.common.lib.BotaniaTags; import vazkii.botania.common.proxy.Proxy; @@ -503,7 +503,7 @@ public static DyeColor getColor2(ItemStack stack) { } public static void setBindingAttempt(ItemStack stack, @Nullable GlobalPos pos) { - ItemNBTHelper.setOptional(stack, BotaniaDataComponents.BINDING_POS, pos); + DataComponentHelper.setOptional(stack, BotaniaDataComponents.BINDING_POS, pos); } public static Optional getBindingAttempt(ItemStack stack) { @@ -515,7 +515,7 @@ public static boolean getBindMode(ItemStack stack) { } public static void setBindMode(ItemStack stack, boolean bindMode) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.WAND_BIND_MODE, bindMode); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.WAND_BIND_MODE, bindMode); } public static String getModeString(ItemStack stack) { diff --git a/Xplat/src/main/java/vazkii/botania/common/item/block/TinyPotatoBlockItem.java b/Xplat/src/main/java/vazkii/botania/common/item/block/TinyPotatoBlockItem.java index 22fb341a1b..a3f8b64ed4 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/block/TinyPotatoBlockItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/block/TinyPotatoBlockItem.java @@ -24,8 +24,8 @@ import org.jetbrains.annotations.Nullable; import vazkii.botania.common.annotations.SoftImplement; +import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.ContributorList; -import vazkii.botania.common.helper.ItemNBTHelper; import vazkii.botania.common.item.ItemWithBannerPattern; import vazkii.botania.common.lib.BotaniaTags; @@ -36,16 +36,14 @@ public class TinyPotatoBlockItem extends BlockItem implements ItemWithBannerPattern { private static final Pattern TYPOS = Pattern.compile( - "(?!^vazkii$)" // Do not match the properly spelled version - + "^v[ao]{1,2}[sz]{0,2}[ak]{1,2}(i){1,2}l{0,2}$", + "^(?!vazkii$)" // Do not match the properly spelled version + + "v[ao]{1,2}[sz]{0,2}[ak]{1,2}(i){1,2}l{0,2}$", Pattern.CASE_INSENSITIVE ); private static final List ENCHANTMENT_NAMES = List.of("enchanted", "glowy", "shiny", "gay"); private static final int NOT_MY_NAME = 17; - private static final String TAG_TICKS = "notMyNameTicks"; - public TinyPotatoBlockItem(Block block, Properties props) { super(block, props); } @@ -56,15 +54,15 @@ public TagKey getBannerPattern() { } @Override - public void inventoryTick(ItemStack stack, Level world, Entity e, int t, boolean idunno) { - if (!world.isClientSide && e instanceof Player player && e.tickCount % 30 == 0 + public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { + if (!level.isClientSide && entity instanceof Player player && entity.tickCount % 30 == 0 && TYPOS.matcher(stack.getHoverName().getString()).matches()) { - int ticks = ItemNBTHelper.getInt(stack, TAG_TICKS, 0); + int ticks = stack.getOrDefault(BotaniaDataComponents.NOT_MY_NAME_STEP, 0); if (ticks < NOT_MY_NAME) { player.sendSystemMessage(Component .translatable("botania.tater.you_came_to_the_wrong_neighborhood." + ticks) .withStyle(ChatFormatting.RED)); - ItemNBTHelper.setInt(stack, TAG_TICKS, ticks + 1); + stack.set(BotaniaDataComponents.NOT_MY_NAME_STEP, ticks + 1); } } } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/brew/BaseBrewItem.java b/Xplat/src/main/java/vazkii/botania/common/item/brew/BaseBrewItem.java index 55b57e28e6..8b3f815920 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/brew/BaseBrewItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/brew/BaseBrewItem.java @@ -30,7 +30,7 @@ import vazkii.botania.api.brew.BrewItem; import vazkii.botania.common.brew.BotaniaBrews; import vazkii.botania.common.component.BotaniaDataComponents; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.item.CustomCreativeTabContents; import java.util.List; @@ -147,7 +147,7 @@ public static void setBrew(ItemStack stack, @Nullable Brew brew) { } public static void setBrew(ItemStack stack, @Nullable ResourceLocation brew) { - ItemNBTHelper.setOptional(stack, BotaniaDataComponents.BREW, brew); + DataComponentHelper.setOptional(stack, BotaniaDataComponents.BREW, brew); } @NotNull diff --git a/Xplat/src/main/java/vazkii/botania/common/item/brew/IncenseStickItem.java b/Xplat/src/main/java/vazkii/botania/common/item/brew/IncenseStickItem.java index 29480b5a12..19ba1fa345 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/brew/IncenseStickItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/brew/IncenseStickItem.java @@ -22,14 +22,15 @@ import vazkii.botania.api.brew.BrewContainer; import vazkii.botania.api.brew.BrewItem; import vazkii.botania.common.brew.BotaniaBrews; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.component.BotaniaDataComponents; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.item.CustomCreativeTabContents; import java.util.List; +import java.util.Objects; public class IncenseStickItem extends Item implements BrewItem, BrewContainer, CustomCreativeTabContents { - private static final String TAG_BREW_KEY = "brewKey"; public static final int TIME_MULTIPLIER = 60; public IncenseStickItem(Properties builder) { @@ -55,27 +56,29 @@ public void appendHoverText(ItemStack stack, TooltipContext context, List getTooltipImage(ItemStack stack) { } protected static void setMana(ItemStack stack, int mana) { - ItemNBTHelper.setIntNonZero(stack, BotaniaDataComponents.MANA, mana); + DataComponentHelper.setIntNonZero(stack, BotaniaDataComponents.MANA, mana); } @Override diff --git a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/BaubleItem.java b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/BaubleItem.java index abf3ec2afa..3c4efd53c9 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/BaubleItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/BaubleItem.java @@ -26,7 +26,7 @@ import vazkii.botania.api.item.PhantomInkable; import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.EquipmentHandler; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.helper.PlayerHelper; import vazkii.botania.xplat.BotaniaConfig; @@ -109,7 +109,7 @@ public boolean hasPhantomInk(ItemStack stack) { @Override public void setPhantomInk(ItemStack stack, boolean ink) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.PHANTOM_INKED, ink); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.PHANTOM_INKED, ink); } public void onWornTick(ItemStack stack, LivingEntity entity) {} diff --git a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/CloakOfVirtueItem.java b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/CloakOfVirtueItem.java index 61c0f920db..4c2e3a67a5 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/CloakOfVirtueItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/CloakOfVirtueItem.java @@ -36,7 +36,7 @@ import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.BotaniaSounds; import vazkii.botania.common.handler.EquipmentHandler; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.proxy.Proxy; public class CloakOfVirtueItem extends BaubleItem { @@ -122,7 +122,7 @@ public static boolean isInEffect(ItemStack stack) { } public static void setInEffect(ItemStack stack, boolean effect) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.ACTIVE_TRANSIENT, effect); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.ACTIVE_TRANSIENT, effect); } ResourceLocation getCloakTexture() { diff --git a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/SpectatorItem.java b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/SpectatorItem.java index e5037fa145..e6fb6a20f5 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/SpectatorItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/SpectatorItem.java @@ -45,7 +45,7 @@ import vazkii.botania.client.render.AccessoryRenderRegistry; import vazkii.botania.client.render.AccessoryRenderer; import vazkii.botania.common.component.BotaniaDataComponents; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.proxy.Proxy; import vazkii.botania.mixin.AbstractHorseAccessor; import vazkii.botania.mixin.RandomizableContainerBlockEntityAccessor; @@ -126,10 +126,10 @@ public void scanForItems(ItemStack stack, Player player) { ItemStack offHandStack = player.getOffhandItem(); IntList entityIds = scanEntities(player, mainHandStack, offHandStack); - ItemNBTHelper.setNonEmpty(stack, BotaniaDataComponents.SPECTATOR_HIGHLIGHT_ENTITIES, entityIds); + DataComponentHelper.setNonEmpty(stack, BotaniaDataComponents.SPECTATOR_HIGHLIGHT_ENTITIES, entityIds); List blockPositions = scanBlockContainers(player, mainHandStack, offHandStack); - ItemNBTHelper.setNonEmpty(stack, BotaniaDataComponents.SPECTATOR_HIGHLIGHT_BLOCKS, blockPositions); + DataComponentHelper.setNonEmpty(stack, BotaniaDataComponents.SPECTATOR_HIGHLIGHT_BLOCKS, blockPositions); } private IntList scanEntities(Player player, ItemStack mainHandStack, ItemStack offHandStack) { diff --git a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/TaintedBloodPendantItem.java b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/TaintedBloodPendantItem.java index 92609aac5a..12f1c0fb2b 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/TaintedBloodPendantItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/equipment/bauble/TaintedBloodPendantItem.java @@ -41,17 +41,16 @@ import vazkii.botania.client.render.AccessoryRenderRegistry; import vazkii.botania.client.render.AccessoryRenderer; import vazkii.botania.common.brew.BotaniaBrews; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.item.CustomCreativeTabContents; import vazkii.botania.common.proxy.Proxy; import vazkii.botania.mixin.client.MinecraftAccessor; import java.util.List; +import java.util.Objects; public class TaintedBloodPendantItem extends BaubleItem implements BrewContainer, BrewItem, CustomCreativeTabContents { - private static final String TAG_BREW_KEY = "brewKey"; - public TaintedBloodPendantItem(Properties props) { super(props); Proxy.INSTANCE.runOnClient(() -> () -> AccessoryRenderRegistry.register(this, new Renderer())); @@ -94,7 +93,7 @@ public void appendHoverText(ItemStack stack, TooltipContext context, List bipedModel, ItemStack stack, LivingEntity @Override public Brew getBrew(ItemStack stack) { - String key = ItemNBTHelper.getString(stack, TAG_BREW_KEY, ""); - return BotaniaAPI.instance().getBrewRegistry().get(ResourceLocation.tryParse(key)); + return Objects.requireNonNull(BotaniaAPI.instance().getBrewRegistry().get(stack.get(BotaniaDataComponents.BREW))); } public static void setBrew(ItemStack stack, Brew brew) { - setBrew(stack, BotaniaAPI.instance().getBrewRegistry().getKey(brew)); + setBrew(stack, Objects.requireNonNull(BotaniaAPI.instance().getBrewRegistry().getKey(brew))); } public static void setBrew(ItemStack stack, ResourceLocation brew) { - ItemNBTHelper.setString(stack, TAG_BREW_KEY, brew.toString()); + stack.set(BotaniaDataComponents.BREW, brew); } @Override public ItemStack getItemForBrew(Brew brew, ItemStack stack) { - if (!brew.canInfuseBloodPendant() || brew.getPotionEffects(stack).size() != 1 || brew.getPotionEffects(stack).get(0).getEffect().value().isInstantenous()) { + if (!brew.canInfuseBloodPendant() || brew.getPotionEffects(stack).size() != 1 || brew.getPotionEffects(stack).getFirst().getEffect().value().isInstantenous()) { return ItemStack.EMPTY; } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/equipment/tool/terrasteel/TerraShattererItem.java b/Xplat/src/main/java/vazkii/botania/common/item/equipment/tool/terrasteel/TerraShattererItem.java index c718eae0f7..a2f739b5a3 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/equipment/tool/terrasteel/TerraShattererItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/equipment/tool/terrasteel/TerraShattererItem.java @@ -35,7 +35,7 @@ import vazkii.botania.common.annotations.SoftImplement; import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.handler.BotaniaSounds; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.helper.PlayerHelper; import vazkii.botania.common.item.CustomCreativeTabContents; import vazkii.botania.common.item.StoneOfTemperanceItem; @@ -218,7 +218,7 @@ public static boolean isEnabled(ItemStack stack) { } void setEnabled(ItemStack stack, boolean enabled) { - ItemNBTHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, enabled); + DataComponentHelper.setFlag(stack, BotaniaDataComponents.ACTIVE, enabled); } protected static void setMana(ItemStack stack, int mana) { diff --git a/Xplat/src/main/java/vazkii/botania/common/item/lens/CelebratoryLens.java b/Xplat/src/main/java/vazkii/botania/common/item/lens/CelebratoryLens.java index dbb2288390..936be569bd 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/lens/CelebratoryLens.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/lens/CelebratoryLens.java @@ -8,16 +8,20 @@ */ package vazkii.botania.common.item.lens; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; +import it.unimi.dsi.fastutil.ints.IntList; + +import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.FireworkExplosion; +import net.minecraft.world.item.component.Fireworks; import net.minecraft.world.phys.HitResult; import vazkii.botania.api.internal.ManaBurst; -import vazkii.botania.common.helper.ItemNBTHelper; + +import java.util.List; public class CelebratoryLens extends Lens { @@ -39,39 +43,20 @@ public boolean collideBurst(ManaBurst burst, HitResult pos, boolean isManaBlock, private ItemStack generateFirework(int color) { ItemStack stack = new ItemStack(Items.FIREWORK_ROCKET); - CompoundTag explosion = new CompoundTag(); - explosion.putIntArray("Colors", new int[] { color }); - int type = 1; + FireworkExplosion.Shape shape; double rand = Math.random(); - if (rand > 0.25) { - if (rand > 0.9) { - type = 2; - } else { - type = 0; - } - } - - explosion.putInt("Type", type); - - if (Math.random() < 0.05) { - if (Math.random() < 0.5) { - explosion.putBoolean("Flicker", true); - } else { - explosion.putBoolean("Trail", true); - } + if (rand > 0.9) { + shape = FireworkExplosion.Shape.STAR; + } else if (rand > 0.25) { + shape = FireworkExplosion.Shape.SMALL_BALL; + } else { + shape = FireworkExplosion.Shape.LARGE_BALL; } - ItemNBTHelper.setCompound(stack, "Explosion", explosion); - - CompoundTag fireworks = new CompoundTag(); - fireworks.putInt("Flight", (int) (Math.random() * 3 + 2)); - - ListTag explosions = new ListTag(); - explosions.add(explosion); - fireworks.put("Explosions", explosions); - - ItemNBTHelper.setCompound(stack, "Fireworks", fireworks); + FireworkExplosion explosion = new FireworkExplosion(shape, IntList.of(color), IntList.of(), + Math.random() < 0.05, Math.random() < 0.05); + stack.set(DataComponents.FIREWORKS, new Fireworks((int) (Math.random() * 3 + 2), List.of(explosion))); return stack; } diff --git a/Xplat/src/main/java/vazkii/botania/common/item/lens/LensItem.java b/Xplat/src/main/java/vazkii/botania/common/item/lens/LensItem.java index 8726de3a8e..618e8933f6 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/lens/LensItem.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/lens/LensItem.java @@ -28,7 +28,7 @@ import vazkii.botania.api.mana.*; import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.helper.ColorHelper; -import vazkii.botania.common.helper.ItemNBTHelper; +import vazkii.botania.common.helper.DataComponentHelper; import vazkii.botania.common.item.BotaniaItems; import java.util.List; @@ -205,7 +205,7 @@ public ItemStack getCompositeLens(ItemStack stack) { @Override public ItemStack setCompositeLens(ItemStack sourceLens, ItemStack compositeLens) { - ItemNBTHelper.setOptional(sourceLens, BotaniaDataComponents.ATTACHED_LENS, compositeLens); + DataComponentHelper.setOptional(sourceLens, BotaniaDataComponents.ATTACHED_LENS, compositeLens); return sourceLens; } diff --git a/Xplat/src/main/java/vazkii/botania/common/lib/LibComponentNames.java b/Xplat/src/main/java/vazkii/botania/common/lib/LibComponentNames.java index 5782107d71..98cd5aac74 100644 --- a/Xplat/src/main/java/vazkii/botania/common/lib/LibComponentNames.java +++ b/Xplat/src/main/java/vazkii/botania/common/lib/LibComponentNames.java @@ -35,8 +35,6 @@ public final class LibComponentNames { public static final String MANA_BACKLOG = "mana_backlog"; public static final String MANA_POOL_POS = "mana_pool_pos"; - public static final String RANGE = "range"; - public static final String HALO_ROTATION_BASE = "halo_rotation_base"; public static final String LAST_RECIPE_ID = "last_recipe_id"; public static final String STORED_RECIPES = "stored_recipes"; @@ -57,4 +55,8 @@ public final class LibComponentNames { public static final String BLOCK_TYPE = "block_type"; public static final String BLOCK_COUNT = "block_count"; + + public static final String RANGE = "range"; + public static final String MOB_TYPE = "mob_type"; + public static final String NOT_MY_NAME_STEP = "not_my_name_step"; } diff --git a/doc/1.21-data-components.md b/doc/1.21-data-components.md index cde52d23a3..7c3595ef27 100644 --- a/doc/1.21-data-components.md +++ b/doc/1.21-data-components.md @@ -37,13 +37,14 @@ Also see [NBT documentation for 1.20.1](nbt-reference-1.20.1.md), which lists th - `botania:lens_clip` (…) - Mana blaster lens clip data, i.e. clip position and up to six lens ItemStacks. - `botania:cooldown` (int) - Remaining cooldown ticks of the item. - `botania:stored_recipes` (list of potentially empty recipe IDs) - Stored recipes of an Assembly/Manufactory Halo. + NOTE: This uses zero-based indices for recipe IDs, while the old halo NBT started at 1, as segment 0 is the crafting table. - `botania:last_recipe` (recipe ID) - Last recipe manually crafted with this Assembly/Manufactory Halo. - `botania:rotation_base` (float) - Player's horizontal view direction at the time they selected the halo item. - `botania:inventory` (list of potentially empty ItemStacks) - Content of a flower/petal pouch or bauble box. TODO: is there a generic way that items like backpacks represent their content? - `botania:block` (Block) - Block type assigned to Black Hole Talisman or selected for Astrolabe. - `botania:block_count` (int) - Number of blocks stored in Black Hole Talisman. -- `botania:mob_name` (translation key string) - Name of an entity. (used by Cacophonium and Life Aggregator) +- `botania:mob_type` (entity ID) - ID of an entity type. (used by Cacophonium and Life Aggregator tooltips) - `botania:center_pos` (GlobalPos) - Center of the shape being created with the Sextant. - `botania:sextant_mode` (?) - Active mode of the Sextant. - `botania:size` (int) - Size of Astrolabe placement. (Any other uses?)