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 00000000..b7e9a798 --- /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 00000000..f74c8447 --- /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 00000000..932ed66f --- /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 009bcf22..5829979b 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.networking.TestModNet; 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 class TestMod { 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 b8e1ff73..1cbcfe83 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.TestMod; 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 class TestRegistries { } }); + 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 00000000..b826f8dc --- /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(); + } + } +}