From b26347a026f4b9fc8712bc3f75df957f5199a4ce Mon Sep 17 00:00:00 2001 From: shedaniel Date: Tue, 6 Feb 2024 17:32:25 +0900 Subject: [PATCH] [ci skip] Add ClientTooltipComponentRegistry for custom tooltips (#475) * Add ClientTooltipComponentRegistry for custom tooltips (#463) Signed-off-by: Sergey Shatunov Signed-off-by: shedaniel * Fix testmod for client tooltip components Signed-off-by: shedaniel --------- Signed-off-by: Sergey Shatunov Signed-off-by: shedaniel Co-authored-by: Sergey Shatunov --- .../gui/ClientTooltipComponentRegistry.java | 50 ++++++++++++++ .../ClientTooltipComponentRegistryImpl.java | 42 +++++++++++ .../ClientTooltipComponentRegistryImpl.java | 69 +++++++++++++++++++ .../java/dev/architectury/test/TestMod.java | 3 + .../test/registry/TestRegistries.java | 4 ++ .../registry/objects/ItemWithTooltip.java | 69 +++++++++++++++++++ 6 files changed, 237 insertions(+) create mode 100644 common/src/main/java/dev/architectury/registry/client/gui/ClientTooltipComponentRegistry.java create mode 100644 fabric/src/main/java/dev/architectury/registry/client/gui/fabric/ClientTooltipComponentRegistryImpl.java create mode 100644 forge/src/main/java/dev/architectury/registry/client/gui/forge/ClientTooltipComponentRegistryImpl.java create mode 100644 testmod-common/src/main/java/dev/architectury/test/registry/objects/ItemWithTooltip.java diff --git a/common/src/main/java/dev/architectury/registry/client/gui/ClientTooltipComponentRegistry.java b/common/src/main/java/dev/architectury/registry/client/gui/ClientTooltipComponentRegistry.java new file mode 100644 index 000000000..b7e9a798b --- /dev/null +++ b/common/src/main/java/dev/architectury/registry/client/gui/ClientTooltipComponentRegistry.java @@ -0,0 +1,50 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.registry.client.gui; + +import dev.architectury.injectables.annotations.ExpectPlatform; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.world.inventory.tooltip.TooltipComponent; + +import java.util.function.Function; + +/** + * Registry for {@link ClientTooltipComponent} factories + */ +@Environment(EnvType.CLIENT) +public final class ClientTooltipComponentRegistry { + private ClientTooltipComponentRegistry() { + } + + /** + * Allows users to register custom {@link ClientTooltipComponent} + * factories for their {@link TooltipComponent} types. + * + * @param clazz class of {@link T} + * @param factory factory to create instances of {@link ClientTooltipComponent} from {@link T} + * @param the type of {@link TooltipComponent} factory + */ + @ExpectPlatform + public static void register(Class clazz, Function factory) { + throw new AssertionError(); + } +} diff --git a/fabric/src/main/java/dev/architectury/registry/client/gui/fabric/ClientTooltipComponentRegistryImpl.java b/fabric/src/main/java/dev/architectury/registry/client/gui/fabric/ClientTooltipComponentRegistryImpl.java new file mode 100644 index 000000000..f74c8447d --- /dev/null +++ b/fabric/src/main/java/dev/architectury/registry/client/gui/fabric/ClientTooltipComponentRegistryImpl.java @@ -0,0 +1,42 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.registry.client.gui.fabric; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.rendering.v1.TooltipComponentCallback; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import org.jetbrains.annotations.ApiStatus; + +import java.util.function.Function; + +@Environment(EnvType.CLIENT) +@ApiStatus.Internal +public class ClientTooltipComponentRegistryImpl { + public static void register(Class clazz, Function factory) { + TooltipComponentCallback.EVENT.register((tooltipComponent) -> { + if (clazz.isInstance(tooltipComponent)) { + return factory.apply(clazz.cast(tooltipComponent)); + } + return null; + }); + } +} diff --git a/forge/src/main/java/dev/architectury/registry/client/gui/forge/ClientTooltipComponentRegistryImpl.java b/forge/src/main/java/dev/architectury/registry/client/gui/forge/ClientTooltipComponentRegistryImpl.java new file mode 100644 index 000000000..932ed66f7 --- /dev/null +++ b/forge/src/main/java/dev/architectury/registry/client/gui/forge/ClientTooltipComponentRegistryImpl.java @@ -0,0 +1,69 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.registry.client.gui.forge; + +import dev.architectury.platform.forge.EventBuses; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.RegisterClientTooltipComponentFactoriesEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +@OnlyIn(Dist.CLIENT) +@ApiStatus.Internal +public class ClientTooltipComponentRegistryImpl { + @Nullable + private static List> entries = new ArrayList<>(); + + static { + EventBuses.onRegistered("architectury", bus -> { + bus.addListener(EventPriority.HIGH, event -> { + if (entries != null) { + for (Entry entry : entries) { + Entry casted = (Entry) entry; + event.register(casted.clazz(), casted.factory()); + } + + entries = null; + } + }); + }); + } + + public static void register(Class clazz, Function factory) { + if (entries == null) { + throw new IllegalStateException("Cannot register ClientTooltipComponent factory when factories are already aggregated!"); + } + entries.add(new Entry<>(clazz, factory)); + } + + public record Entry( + Class clazz, Function factory + ) { + } +} diff --git a/testmod-common/src/main/java/dev/architectury/test/TestMod.java b/testmod-common/src/main/java/dev/architectury/test/TestMod.java index 009bcf22b..5829979b1 100644 --- a/testmod-common/src/main/java/dev/architectury/test/TestMod.java +++ b/testmod-common/src/main/java/dev/architectury/test/TestMod.java @@ -20,6 +20,7 @@ package dev.architectury.test; import dev.architectury.event.events.client.ClientLifecycleEvent; +import dev.architectury.registry.client.gui.ClientTooltipComponentRegistry; import dev.architectury.registry.client.level.entity.EntityRendererRegistry; import dev.architectury.test.debug.ConsoleMessageSink; import dev.architectury.test.debug.MessageSink; @@ -33,6 +34,7 @@ import dev.architectury.test.particle.TestParticles; import dev.architectury.test.registry.TestRegistries; import dev.architectury.test.registry.client.TestKeybinds; +import dev.architectury.test.registry.objects.ItemWithTooltip; import dev.architectury.test.tags.TestTags; import dev.architectury.test.trade.TestTrades; import dev.architectury.test.worldgen.TestWorldGeneration; @@ -72,6 +74,7 @@ public static void initializeClient() { TestModNet.initializeClient(); EntityRendererRegistry.register(TestRegistries.TEST_ENTITY, CowRenderer::new); EntityRendererRegistry.register(TestRegistries.TEST_ENTITY_2, CowRenderer::new); + ClientTooltipComponentRegistry.register(ItemWithTooltip.MyTooltipComponent.class, ItemWithTooltip.MyClientTooltipComponent::new); } } } diff --git a/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java b/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java index b8e1ff73e..1cbcfe832 100644 --- a/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java +++ b/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java @@ -34,6 +34,7 @@ import dev.architectury.test.entity.TestEntity; import dev.architectury.test.recipes.TestRecipeSerializer; import dev.architectury.test.registry.objects.EquippableTickingItem; +import dev.architectury.test.registry.objects.ItemWithTooltip; import dev.architectury.test.tab.TestCreativeTabs; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; @@ -127,6 +128,9 @@ public TestInt(int value) { } }); + public static final RegistrySupplier TEST_TOOLTIP = ITEMS.register("test_tooltip", + () -> new ItemWithTooltip(new Item.Properties().tab(TestCreativeTabs.TEST_TAB))); + public static final RegistrySupplier TEST_BLOCK = BLOCKS.register("test_block", () -> new Block(BlockBehaviour.Properties.copy(Blocks.STONE))); public static final RegistrySupplier COLLISION_BLOCK = BLOCKS.register("collision_block", () -> diff --git a/testmod-common/src/main/java/dev/architectury/test/registry/objects/ItemWithTooltip.java b/testmod-common/src/main/java/dev/architectury/test/registry/objects/ItemWithTooltip.java new file mode 100644 index 000000000..b826f8dc2 --- /dev/null +++ b/testmod-common/src/main/java/dev/architectury/test/registry/objects/ItemWithTooltip.java @@ -0,0 +1,69 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.test.registry.objects; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class ItemWithTooltip extends Item { + public ItemWithTooltip(Properties properties) { + super(properties); + } + + @Override + public @NotNull Optional getTooltipImage(ItemStack itemStack) { + return Optional.of(new MyTooltipComponent(itemStack.getCount())); + } + + public record MyTooltipComponent(int count) implements TooltipComponent { + + } + + @Environment(EnvType.CLIENT) + public record MyClientTooltipComponent(MyTooltipComponent component) implements ClientTooltipComponent { + @Override + public int getHeight() { + return 100; + } + + @Override + public int getWidth(Font font) { + return 100; + } + + @Override + public void renderImage(Font font, int x, int y, PoseStack poseStack, ItemRenderer itemRenderer, int blitOffset) { + poseStack.pushPose(); + poseStack.translate(0, 0, blitOffset); + font.draw(poseStack, "Count: " + component.count, x + getWidth(font) / 2, y + (getHeight() - font.lineHeight) / 2, 0xFF00FF00); + poseStack.popPose(); + } + } +}