From 2ab92e12522e135fe9675c6064dcefed59a20a7e Mon Sep 17 00:00:00 2001 From: Artemis System Date: Mon, 11 Nov 2024 15:39:06 +0100 Subject: [PATCH] Start implementing item data components Nothing is hooked up yet, the components are just registered --- .../fabric/FabricCommonInitializer.java | 2 + .../botania/forge/ForgeCommonInitializer.java | 2 + .../component/AdvancedTooltipProvider.java | 17 ++++ .../component/BotaniaDataComponents.java | 42 ++++++++++ .../common/component/TooltipVisibility.java | 33 ++++++++ .../component/WandOfTheForestComponent.java | 77 +++++++++++++++++++ 6 files changed, 173 insertions(+) create mode 100644 Xplat/src/main/java/vazkii/botania/common/component/AdvancedTooltipProvider.java create mode 100644 Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java create mode 100644 Xplat/src/main/java/vazkii/botania/common/component/TooltipVisibility.java create mode 100644 Xplat/src/main/java/vazkii/botania/common/component/WandOfTheForestComponent.java diff --git a/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java b/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java index cb08920ad2..d0d9caa0ab 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java @@ -83,6 +83,7 @@ import vazkii.botania.common.brew.BotaniaBrews; import vazkii.botania.common.brew.BotaniaMobEffects; import vazkii.botania.common.command.SkyblockCommand; +import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.config.ConfigDataManagerImpl; import vazkii.botania.common.crafting.BotaniaRecipeTypes; import vazkii.botania.common.crafting.StateIngredients; @@ -177,6 +178,7 @@ private void registryInit() { Blocks.FARMLAND.defaultBlockState()); FlattenableBlockRegistry.register(b, Blocks.DIRT_PATH.defaultBlockState()); } + BotaniaDataComponents.registerComponents(bind(BuiltInRegistries.DATA_COMPONENT_TYPE)); int blazeTime = 2400; FuelRegistry.INSTANCE.add(BotaniaBlocks.blazeBlock.asItem(), blazeTime * (XplatAbstractions.INSTANCE.gogLoaded() ? 5 : 10)); diff --git a/NeoForge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java b/NeoForge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java index df2c2808c2..73877ecbde 100644 --- a/NeoForge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java +++ b/NeoForge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java @@ -94,6 +94,7 @@ import vazkii.botania.common.brew.BotaniaMobEffects; import vazkii.botania.common.brew.effect.SoulCrossMobEffect; import vazkii.botania.common.command.SkyblockCommand; +import vazkii.botania.common.component.BotaniaDataComponents; import vazkii.botania.common.config.ConfigDataManagerImpl; import vazkii.botania.common.crafting.BotaniaRecipeTypes; import vazkii.botania.common.entity.BotaniaEntities; @@ -194,6 +195,7 @@ private void registryInit() { bind(Registries.BLOCK, BotaniaFlowerBlocks::registerBlocks); bindForItems(BotaniaFlowerBlocks::registerItemBlocks); bind(Registries.BLOCK_ENTITY_TYPE, BotaniaFlowerBlocks::registerTEs); + bind(Registries.DATA_COMPONENT_TYPE, BotaniaDataComponents::registerComponents); // GUI and Recipe bind(Registries.MENU, BotaniaItems::registerMenuTypes); diff --git a/Xplat/src/main/java/vazkii/botania/common/component/AdvancedTooltipProvider.java b/Xplat/src/main/java/vazkii/botania/common/component/AdvancedTooltipProvider.java new file mode 100644 index 0000000000..a69a8b9841 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/component/AdvancedTooltipProvider.java @@ -0,0 +1,17 @@ +package vazkii.botania.common.component; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; + +import java.util.List; +import java.util.function.Consumer; + +public interface AdvancedTooltipProvider { + void addToTooltip( + Item.TooltipContext context, + Consumer tooltipAdder, + TooltipFlag tooltipFlag, + List fullTooltip + ); +} diff --git a/Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java b/Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java new file mode 100644 index 0000000000..8aa4b4e5da --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/component/BotaniaDataComponents.java @@ -0,0 +1,42 @@ +package vazkii.botania.common.component; + +import net.minecraft.core.component.DataComponentType; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ExtraCodecs; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.UnaryOperator; + +import static vazkii.botania.api.BotaniaAPI.botaniaRL; + +public class BotaniaDataComponents { + private static final Map> toRegister = new HashMap<>(); + + public static final DataComponentType MAX_MANA = schedule( + "max_mana", + builder -> builder.persistent(ExtraCodecs.POSITIVE_INT).networkSynchronized(ByteBufCodecs.VAR_INT) + ); + public static final DataComponentType MANA = schedule( + "mana", + builder -> builder.persistent(ExtraCodecs.NON_NEGATIVE_INT).networkSynchronized(ByteBufCodecs.VAR_INT) + ); + public static final DataComponentType WAND_OF_THE_FOREST = schedule( + "wand_of_the_forest", + builder -> builder.persistent(WandOfTheForestComponent.CODEC).networkSynchronized(WandOfTheForestComponent.STREAM_CODEC) + ); + + private static DataComponentType schedule(String name, UnaryOperator> builder) { + DataComponentType type = builder.apply(DataComponentType.builder()).build(); + toRegister.put(name, type); + return type; + }; + + public static void registerComponents(BiConsumer, ResourceLocation> biConsumer) { + for (Map.Entry> entry : toRegister.entrySet()) { + biConsumer.accept(entry.getValue(), botaniaRL(entry.getKey())); + } + } +} diff --git a/Xplat/src/main/java/vazkii/botania/common/component/TooltipVisibility.java b/Xplat/src/main/java/vazkii/botania/common/component/TooltipVisibility.java new file mode 100644 index 0000000000..ffcf82afba --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/component/TooltipVisibility.java @@ -0,0 +1,33 @@ +package vazkii.botania.common.component; + +import com.mojang.serialization.Codec; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.util.ByIdMap; +import net.minecraft.util.StringRepresentable; +import org.jetbrains.annotations.NotNull; + +import java.util.function.IntFunction; + +public enum TooltipVisibility implements StringRepresentable { + HIDDEN(0, "hidden"), + IN_NAME(1, "in_name"), + IN_LIST(2, "in_list"); + + private final int id; + private final String name; + public static final Codec CODEC = StringRepresentable.fromValues(TooltipVisibility::values); + public static final IntFunction BY_ID = ByIdMap.continuous(visibility -> visibility.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO); + public static final StreamCodec STREAM_CODEC = ByteBufCodecs.idMapper(BY_ID, visibility -> visibility.id); + + TooltipVisibility(int id, String name) { + this.id = id; + this.name = name; + } + + @Override + public @NotNull String getSerializedName() { + return name; + } +} diff --git a/Xplat/src/main/java/vazkii/botania/common/component/WandOfTheForestComponent.java b/Xplat/src/main/java/vazkii/botania/common/component/WandOfTheForestComponent.java new file mode 100644 index 0000000000..f1dd352702 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/component/WandOfTheForestComponent.java @@ -0,0 +1,77 @@ +package vazkii.botania.common.component; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.netty.buffer.ByteBuf; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentUtils; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.util.ByIdMap; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.IntFunction; + +public record WandOfTheForestComponent(WandMode wandMode, TooltipVisibility tooltipVisibility) implements AdvancedTooltipProvider { + public static Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + WandMode.CODEC.optionalFieldOf("mode", WandMode.BIND).forGetter(WandOfTheForestComponent::wandMode), + TooltipVisibility.CODEC.optionalFieldOf("tooltip_visibility", TooltipVisibility.IN_NAME).forGetter(WandOfTheForestComponent::tooltipVisibility) + ).apply(instance, WandOfTheForestComponent::new) + ); + public static StreamCodec STREAM_CODEC = StreamCodec.composite( + WandMode.STREAM_CODEC, WandOfTheForestComponent::wandMode, + TooltipVisibility.STREAM_CODEC, WandOfTheForestComponent::tooltipVisibility, + WandOfTheForestComponent::new + ); + + @Override + public void addToTooltip(Item.TooltipContext context, Consumer tooltipAdder, TooltipFlag tooltipFlag, List fullTooltip) { + if (tooltipVisibility == TooltipVisibility.IN_NAME) { + MutableComponent name = fullTooltip.get(0).copy(); + Style style = name.getStyle(); + name.append(" ("); + name.append(wandMode.getDisplay()); + // TODO: 1.21 this probably has the wrong style + name.append(")"); + fullTooltip.set(0, name); + } else if (tooltipVisibility == TooltipVisibility.IN_LIST) { + tooltipAdder.accept(wandMode.getDisplay()); + } + } + + public enum WandMode implements StringRepresentable { + BIND(0, "bind", "botaniamisc.wandMode.bind"), + FUNCTION(1, "function", "botaniamisc.wandMode.function"); + + public static final Codec CODEC = StringRepresentable.fromValues(WandMode::values); + public static final IntFunction BY_ID = ByIdMap.continuous(mode -> mode.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO); + public static final StreamCodec STREAM_CODEC = ByteBufCodecs.idMapper(BY_ID, mode -> mode.id); + private final int id; + private final String name; + private final Component display; + + WandMode(int id, String name, String translationKey) { + this.id = id; + this.name = name; + this.display = Component.translatable(translationKey).withStyle(ChatFormatting.DARK_GREEN); + } + + @Override + public @NotNull String getSerializedName() { + return name; + } + + public Component getDisplay() { + return display; + } + } +}