[ci skip] Add ClientTooltipComponentRegistry for custom tooltips (#475)

* Add ClientTooltipComponentRegistry for custom tooltips (#463)

Signed-off-by: Sergey Shatunov <me@aur.rocks>
Signed-off-by: shedaniel <daniel@shedaniel.me>

* Fix testmod for client tooltip components

Signed-off-by: shedaniel <daniel@shedaniel.me>

---------

Signed-off-by: Sergey Shatunov <me@aur.rocks>
Signed-off-by: shedaniel <daniel@shedaniel.me>
Co-authored-by: Sergey Shatunov <me@aur.rocks>
This commit is contained in:
shedaniel
2024-02-06 17:32:25 +09:00
committed by GitHub
parent 9851188174
commit b26347a026
6 changed files with 237 additions and 0 deletions

View File

@@ -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 <T> the type of {@link TooltipComponent} factory
*/
@ExpectPlatform
public static <T extends TooltipComponent> void register(Class<T> clazz, Function<? super T, ? extends ClientTooltipComponent> factory) {
throw new AssertionError();
}
}

View File

@@ -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 <T extends TooltipComponent> void register(Class<T> clazz, Function<? super T, ? extends ClientTooltipComponent> factory) {
TooltipComponentCallback.EVENT.register((tooltipComponent) -> {
if (clazz.isInstance(tooltipComponent)) {
return factory.apply(clazz.cast(tooltipComponent));
}
return null;
});
}
}

View File

@@ -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<Entry<?>> entries = new ArrayList<>();
static {
EventBuses.onRegistered("architectury", bus -> {
bus.<RegisterClientTooltipComponentFactoriesEvent>addListener(EventPriority.HIGH, event -> {
if (entries != null) {
for (Entry<?> entry : entries) {
Entry<TooltipComponent> casted = (Entry<TooltipComponent>) entry;
event.register(casted.clazz(), casted.factory());
}
entries = null;
}
});
});
}
public static <T extends TooltipComponent> void register(Class<T> clazz, Function<? super T, ? extends ClientTooltipComponent> 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<T extends TooltipComponent>(
Class<T> clazz, Function<? super T, ? extends ClientTooltipComponent> factory
) {
}
}

View File

@@ -20,6 +20,7 @@
package dev.architectury.test; package dev.architectury.test;
import dev.architectury.event.events.client.ClientLifecycleEvent; 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.registry.client.level.entity.EntityRendererRegistry;
import dev.architectury.test.debug.ConsoleMessageSink; import dev.architectury.test.debug.ConsoleMessageSink;
import dev.architectury.test.debug.MessageSink; 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.particle.TestParticles;
import dev.architectury.test.registry.TestRegistries; import dev.architectury.test.registry.TestRegistries;
import dev.architectury.test.registry.client.TestKeybinds; import dev.architectury.test.registry.client.TestKeybinds;
import dev.architectury.test.registry.objects.ItemWithTooltip;
import dev.architectury.test.tags.TestTags; import dev.architectury.test.tags.TestTags;
import dev.architectury.test.trade.TestTrades; import dev.architectury.test.trade.TestTrades;
import dev.architectury.test.worldgen.TestWorldGeneration; import dev.architectury.test.worldgen.TestWorldGeneration;
@@ -72,6 +74,7 @@ public class TestMod {
TestModNet.initializeClient(); TestModNet.initializeClient();
EntityRendererRegistry.register(TestRegistries.TEST_ENTITY, CowRenderer::new); EntityRendererRegistry.register(TestRegistries.TEST_ENTITY, CowRenderer::new);
EntityRendererRegistry.register(TestRegistries.TEST_ENTITY_2, CowRenderer::new); EntityRendererRegistry.register(TestRegistries.TEST_ENTITY_2, CowRenderer::new);
ClientTooltipComponentRegistry.register(ItemWithTooltip.MyTooltipComponent.class, ItemWithTooltip.MyClientTooltipComponent::new);
} }
} }
} }

View File

@@ -34,6 +34,7 @@ import dev.architectury.test.TestMod;
import dev.architectury.test.entity.TestEntity; import dev.architectury.test.entity.TestEntity;
import dev.architectury.test.recipes.TestRecipeSerializer; import dev.architectury.test.recipes.TestRecipeSerializer;
import dev.architectury.test.registry.objects.EquippableTickingItem; import dev.architectury.test.registry.objects.EquippableTickingItem;
import dev.architectury.test.registry.objects.ItemWithTooltip;
import dev.architectury.test.tab.TestCreativeTabs; import dev.architectury.test.tab.TestCreativeTabs;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
@@ -127,6 +128,9 @@ public class TestRegistries {
} }
}); });
public static final RegistrySupplier<ItemWithTooltip> TEST_TOOLTIP = ITEMS.register("test_tooltip",
() -> new ItemWithTooltip(new Item.Properties().tab(TestCreativeTabs.TEST_TAB)));
public static final RegistrySupplier<Block> TEST_BLOCK = BLOCKS.register("test_block", () -> public static final RegistrySupplier<Block> TEST_BLOCK = BLOCKS.register("test_block", () ->
new Block(BlockBehaviour.Properties.copy(Blocks.STONE))); new Block(BlockBehaviour.Properties.copy(Blocks.STONE)));
public static final RegistrySupplier<Block> COLLISION_BLOCK = BLOCKS.register("collision_block", () -> public static final RegistrySupplier<Block> COLLISION_BLOCK = BLOCKS.register("collision_block", () ->

View File

@@ -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<TooltipComponent> 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();
}
}
}