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"
]
}
}