diff --git a/fabric-rendering-v1/src/main/java/net/fabricmc/fabric/api/client/rendering/v1/TooltipComponentCallback.java b/fabric-rendering-v1/src/main/java/net/fabricmc/fabric/api/client/rendering/v1/TooltipComponentCallback.java new file mode 100644 index 000000000..402911acd --- /dev/null +++ b/fabric-rendering-v1/src/main/java/net/fabricmc/fabric/api/client/rendering/v1/TooltipComponentCallback.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.rendering.v1; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.item.Item; +import net.minecraft.client.item.TooltipData; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +/** + * Allows registering a mapping from {@link TooltipData} to {@link TooltipComponent}. + * This allows custom tooltips for items: first, override {@link Item#getTooltipData} and return a custom {@code TooltipData}. + * Second, register a listener to this event and convert the data to your component implementation if it's an instance of your data class. + * + *

Note that failure to map some data to a component will throw an exception, + * so make sure that any data you return in {@link Item#getTooltipData} will be handled by one of the callbacks. + */ +@Environment(EnvType.CLIENT) +public interface TooltipComponentCallback { + Event EVENT = EventFactory.createArrayBacked(TooltipComponentCallback.class, listeners -> data -> { + for (TooltipComponentCallback listener : listeners) { + TooltipComponent component = listener.getComponent(data); + + if (component != null) { + return component; + } + } + + return null; + }); + + /** + * Return the tooltip component for the passed data, or null if none is available. + */ + @Nullable + TooltipComponent getComponent(TooltipData data); +} diff --git a/fabric-rendering-v1/src/main/java/net/fabricmc/fabric/mixin/client/rendering/ScreenMixin.java b/fabric-rendering-v1/src/main/java/net/fabricmc/fabric/mixin/client/rendering/ScreenMixin.java new file mode 100644 index 000000000..3666df150 --- /dev/null +++ b/fabric-rendering-v1/src/main/java/net/fabricmc/fabric/mixin/client/rendering/ScreenMixin.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.client.rendering; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.item.TooltipData; + +import net.fabricmc.fabric.api.client.rendering.v1.TooltipComponentCallback; + +@Mixin(Screen.class) +public class ScreenMixin { + // Synthetic lambda body in renderTooltip + @Inject(at = @At("HEAD"), method = "method_32635(Ljava/util/List;Lnet/minecraft/client/item/TooltipData;)V", cancellable = true) + private static void injectRenderTooltipLambda(List components, TooltipData data, CallbackInfo ci) { + TooltipComponent component = TooltipComponentCallback.EVENT.invoker().getComponent(data); + + if (component != null) { + components.add(1, component); + ci.cancel(); + } + } +} diff --git a/fabric-rendering-v1/src/main/resources/fabric-rendering-v1.mixins.json b/fabric-rendering-v1/src/main/resources/fabric-rendering-v1.mixins.json index ec5d892bf..7dfcfc084 100644 --- a/fabric-rendering-v1/src/main/resources/fabric-rendering-v1.mixins.json +++ b/fabric-rendering-v1/src/main/resources/fabric-rendering-v1.mixins.json @@ -13,7 +13,8 @@ "EntityModelsMixin", "LivingEntityRendererAccessor", "MixinBlockEntityRenderers", - "MixinEntityRenderers" + "MixinEntityRenderers", + "ScreenMixin" ], "injectors": { "defaultRequire": 1 diff --git a/fabric-rendering-v1/src/testmod/java/net/fabricmc/fabric/test/rendering/TooltipComponentTestInit.java b/fabric-rendering-v1/src/testmod/java/net/fabricmc/fabric/test/rendering/TooltipComponentTestInit.java new file mode 100644 index 000000000..1c312f155 --- /dev/null +++ b/fabric-rendering-v1/src/testmod/java/net/fabricmc/fabric/test/rendering/TooltipComponentTestInit.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.rendering; + +import java.util.Optional; + +import net.minecraft.client.item.TooltipData; +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import net.fabricmc.api.ModInitializer; + +public class TooltipComponentTestInit implements ModInitializer { + public static Item CUSTOM_TOOLTIP_ITEM = new CustomTooltipItem(); + + @Override + public void onInitialize() { + Registry.register(Registry.ITEM, new Identifier("fabric-rendering-v1-testmod", "custom_tooltip"), CUSTOM_TOOLTIP_ITEM); + } + + private static class CustomTooltipItem extends Item { + CustomTooltipItem() { + super(new Settings().group(ItemGroup.MISC)); + } + + @Override + public Optional getTooltipData(ItemStack stack) { + return Optional.of(new Data(stack.getTranslationKey())); + } + } + + public record Data(String string) implements TooltipData { } +} diff --git a/fabric-rendering-v1/src/testmod/java/net/fabricmc/fabric/test/rendering/client/TooltipComponentTests.java b/fabric-rendering-v1/src/testmod/java/net/fabricmc/fabric/test/rendering/client/TooltipComponentTests.java new file mode 100644 index 000000000..ba08cda87 --- /dev/null +++ b/fabric-rendering-v1/src/testmod/java/net/fabricmc/fabric/test/rendering/client/TooltipComponentTests.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.rendering.client; + +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Style; +import net.minecraft.util.Formatting; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.rendering.v1.TooltipComponentCallback; +import net.fabricmc.fabric.test.rendering.TooltipComponentTestInit; + +public class TooltipComponentTests implements ClientModInitializer { + @Override + public void onInitializeClient() { + TooltipComponentCallback.EVENT.register(data -> { + if (data instanceof TooltipComponentTestInit.Data d) { + return TooltipComponent.of(new LiteralText(d.string()).setStyle(Style.EMPTY.withColor(Formatting.GREEN)).asOrderedText()); + } + + return null; + }); + } +} diff --git a/fabric-rendering-v1/src/testmod/resources/fabric.mod.json b/fabric-rendering-v1/src/testmod/resources/fabric.mod.json index f7e2de62a..121a32a38 100644 --- a/fabric-rendering-v1/src/testmod/resources/fabric.mod.json +++ b/fabric-rendering-v1/src/testmod/resources/fabric.mod.json @@ -9,10 +9,14 @@ "fabric-rendering-v1": "*" }, "entrypoints": { + "main": [ + "net.fabricmc.fabric.test.rendering.TooltipComponentTestInit" + ], "client": [ "net.fabricmc.fabric.test.rendering.client.WorldRenderEventsTests", "net.fabricmc.fabric.test.rendering.client.ArmorRenderingTests", - "net.fabricmc.fabric.test.rendering.client.FeatureRendererTest" + "net.fabricmc.fabric.test.rendering.client.FeatureRendererTest", + "net.fabricmc.fabric.test.rendering.client.TooltipComponentTests" ] } }