Fix ItemStack in RenderTooltipEvent always EMPTY, merges RenderTooltipEvent.Background into .Pre (#10655) (#10702)

This commit is contained in:
Matt 2025-11-14 10:42:03 -05:00 committed by GitHub
parent f3d16621c0
commit 7ea0a41fe2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 125 additions and 43 deletions

View file

@ -82,11 +82,31 @@
}
public void setComponentTooltipForNextFrame(Font p_408650_, List<Component> p_407512_, int p_406019_, int p_408123_, @Nullable ResourceLocation p_409993_) {
@@ -1069,11 +_,13 @@
ClientTooltipPositioner p_409451_,
@Nullable ResourceLocation p_409298_
@@ -1056,9 +_,14 @@
) {
+ var preEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipPre(this.tooltipStack, this, p_283678_, p_281696_, guiWidth(), guiHeight(), p_282716_, p_283128_, p_409451_);
if (!p_409928_.isEmpty()) {
if (this.deferredTooltip == null || p_410618_) {
- this.deferredTooltip = () -> this.renderTooltip(p_406605_, p_409928_, p_407794_, p_408784_, p_408798_, p_407676_);
+ final var stackContext = this.tooltipStack;
+ this.deferredTooltip = () -> this.renderTooltip(p_406605_, p_409928_, p_407794_, p_408784_, p_408798_, p_407676_, stackContext);
}
}
+ }
+
+ public void renderTooltip(Font p_283128_, List<ClientTooltipComponent> p_282716_, int p_283678_, int p_281696_, ClientTooltipPositioner p_409451_, @Nullable ResourceLocation p_409298_) {
+ renderTooltip(p_283128_, p_282716_, p_283678_, p_281696_, p_409451_, p_409298_, ItemStack.EMPTY);
}
public void renderTooltip(
@@ -1067,13 +_,16 @@
int p_283678_,
int p_281696_,
ClientTooltipPositioner p_409451_,
- @Nullable ResourceLocation p_409298_
+ @Nullable ResourceLocation p_409298_,
+ ItemStack itemstack
) {
+ var preEvent = net.minecraftforge.client.ForgeHooksClient.onRenderTooltipPre(itemstack, this, p_283678_, p_281696_, guiWidth(), guiHeight(), p_282716_, p_283128_, p_409451_, p_409298_);
+ if (preEvent == null) return;
int i = 0;
int j = p_282716_.size() == 1 ? -2 : 0;
@ -97,7 +117,7 @@
if (k > i) {
i = k;
}
@@ -1083,16 +_,17 @@
@@ -1083,16 +_,16 @@
int l1 = i;
int i2 = j;
@ -107,8 +127,7 @@
int i1 = vector2ic.y();
this.pose.pushMatrix();
- TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, p_409298_);
+ var background_event = net.minecraftforge.client.event.ForgeEventFactoryClient.onRenderTooltipBackground(this.tooltipStack, this, l, i1, preEvent.getFont(), p_282716_, p_409298_);
+ TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, background_event.getBackground());
+ TooltipRenderUtil.renderTooltipBackground(this, l, i1, i, j, preEvent.getBackground());
int j1 = i1;
for (int k1 = 0; k1 < p_282716_.size(); k1++) {

View file

@ -658,8 +658,8 @@ public class ForgeHooksClient {
return stackFont == null ? fallbackFont : stackFont;
}
public static @Nullable RenderTooltipEvent.Pre onRenderTooltipPre(@NotNull ItemStack stack, GuiGraphics graphics, int x, int y, int screenWidth, int screenHeight, @NotNull List<ClientTooltipComponent> components, @NotNull Font fallbackFont, @NotNull ClientTooltipPositioner positioner) {
var preEvent = new RenderTooltipEvent.Pre(stack, graphics, x, y, screenWidth, screenHeight, getTooltipFont(stack, fallbackFont), components, positioner);
public static @Nullable RenderTooltipEvent.Pre onRenderTooltipPre(@NotNull ItemStack stack, GuiGraphics graphics, int x, int y, int screenWidth, int screenHeight, @NotNull List<ClientTooltipComponent> components, @NotNull Font fallbackFont, @NotNull ClientTooltipPositioner positioner, @Nullable ResourceLocation background) {
var preEvent = new RenderTooltipEvent.Pre(stack, graphics, x, y, screenWidth, screenHeight, getTooltipFont(stack, fallbackFont), components, positioner, background);
return RenderTooltipEvent.Pre.BUS.post(preEvent) ? null : preEvent;
}

View file

@ -244,10 +244,6 @@ public final class ForgeEventFactoryClient {
TickEvent.RenderTickEvent.Post.BUS.post(new TickEvent.RenderTickEvent.Post(timer));
}
public static RenderTooltipEvent.Background onRenderTooltipBackground(@NotNull ItemStack stack, GuiGraphics graphics, int x, int y, @NotNull Font font, @NotNull List<ClientTooltipComponent> components, @Nullable ResourceLocation backgroundPrefix) {
return RenderTooltipEvent.Background.BUS.fire(new RenderTooltipEvent.Background(stack, graphics, x, y, font, components, backgroundPrefix));
}
public static boolean onToastAdd(Toast toast) {
return ToastAddEvent.BUS.post(new ToastAddEvent(toast));
}

View file

@ -35,7 +35,6 @@ import java.util.List;
*
* @see RenderTooltipEvent.GatherComponents
* @see RenderTooltipEvent.Pre
* @see RenderTooltipEvent.Background
*/
@NullMarked
public abstract sealed class RenderTooltipEvent extends MutableEvent implements InheritableEvent {
@ -117,7 +116,7 @@ public abstract sealed class RenderTooltipEvent extends MutableEvent implements
*
* <p>This event is {@linkplain Cancellable cancellable}.
* If this event is cancelled, then the list of components will be empty, causing the tooltip to not be rendered and
* the corresponding {@link RenderTooltipEvent.Pre} and {@link RenderTooltipEvent.Background} to not be fired.</p>
* the corresponding {@link RenderTooltipEvent.Pre} to not be fired.</p>
*
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
@ -195,11 +194,10 @@ public abstract sealed class RenderTooltipEvent extends MutableEvent implements
/**
* Fired <b>before</b> the tooltip is rendered.
* This can be used to modify the positioning and font of the tooltip.
* This can be used to modify the positioning, font, and background of the tooltip.
*
* <p>This event is {@linkplain Cancellable cancellable}.
* If this event is cancelled, then the tooltip will not be rendered and the corresponding
* {@link RenderTooltipEvent.Background} will not be fired.</p>
* If this event is cancelled, then the tooltip will not be rendered
*
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
@ -210,13 +208,19 @@ public abstract sealed class RenderTooltipEvent extends MutableEvent implements
private final int screenWidth;
private final int screenHeight;
private final ClientTooltipPositioner positioner;
@Nullable
private ResourceLocation background;
@Nullable
private ResourceLocation originalBackground;
@ApiStatus.Internal
public Pre(ItemStack stack, GuiGraphics graphics, int x, int y, int screenWidth, int screenHeight, Font font, List<ClientTooltipComponent> components, ClientTooltipPositioner positioner) {
public Pre(ItemStack stack, GuiGraphics graphics, int x, int y, int screenWidth, int screenHeight, Font font, List<ClientTooltipComponent> components, ClientTooltipPositioner positioner, @Nullable ResourceLocation background) {
super(stack, graphics, x, y, font, components);
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.positioner = positioner;
this.background = background;
this.originalBackground = background;
}
/**
@ -266,27 +270,6 @@ public abstract sealed class RenderTooltipEvent extends MutableEvent implements
public void setY(int y) {
this.y = y;
}
}
/**
* Fired when the tooltip background prefix is determined.
* This can be used to modify the textures to be used for the tooltip background.
*
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
*/
public static final class Background extends RenderTooltipEvent {
public static final EventBus<Background> BUS = EventBus.create(Background.class);
private final @Nullable ResourceLocation originalBackground;
private @Nullable ResourceLocation background;
@ApiStatus.Internal
public Background(ItemStack stack, GuiGraphics graphics, int x, int y, Font fr, List<ClientTooltipComponent> components, @Nullable ResourceLocation background) {
super(stack, graphics, x, y, fr, components);
this.originalBackground = background;
this.background = background;
}
/**
* Sets the new prefix for the background texture

View file

@ -0,0 +1,7 @@
{
"type": "minecraft:function",
"environment": "minecraft:default",
"function": "forge:render_tooltip_test/stack_present_in_pre",
"max_ticks": 100,
"structure": "forge:empty3x3x3"
}

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.debug.client;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.event.AddGuiOverlayLayersEvent;
import net.minecraftforge.client.event.RenderTooltipEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.gametest.GameTest;
import net.minecraftforge.gametest.GameTestNamespace;
import net.minecraftforge.test.BaseTestMod;
import java.util.Random;
@GameTestNamespace("forge")
@Mod(RenderTooltipTest.MODID)
public class RenderTooltipTest extends BaseTestMod {
public static final String MODID = "render_tooltip_test";
private static boolean testMode = false;
private static int shouldOpen = 0;
// Need some randomness so this test isn't asinine.
private static Object[] possibleChoices = BuiltInRegistries.ITEM.listElements().map(Holder::get).map(Item::getDefaultInstance).toArray();
private static int itemStack = 0;
private static ItemStack lastItemstackSeenInEvent = null;
public RenderTooltipTest(FMLJavaModLoadingContext context) {
super(context, false, false);
AddGuiOverlayLayersEvent.BUS.addListener(event -> {
event.getLayeredDraw().addWithCondition(rl("render_tooltip_test"), (gg, dt) -> {
gg.setTooltipForNextFrame(Minecraft.getInstance().font, (ItemStack) possibleChoices[itemStack], 50, 50);
}, () -> testMode) ;
});
}
@SuppressWarnings("all")
@GameTest
public static void stack_present_in_pre(GameTestHelper helper) {
testMode = true;
shouldOpen = 1;
helper.addEventListener(RenderTooltipEvent.Pre.BUS, event -> {
lastItemstackSeenInEvent = event.getItemStack();
});
helper.addRecordListener(TickEvent.RenderTickEvent.Pre.BUS, (event) -> {
if (shouldOpen == 1) {
Minecraft.getInstance().setScreen(new InventoryScreen(Minecraft.getInstance().player));
shouldOpen = 2;
} else if (shouldOpen == 2) {
Minecraft.getInstance().setScreen(null);
shouldOpen = 0;
}
});
itemStack = new Random().nextInt(possibleChoices.length);
helper.runAfterDelay(10, () -> {
testMode = false;
var copyOfLastSeen = lastItemstackSeenInEvent;
boolean testPassed = lastItemstackSeenInEvent == possibleChoices[itemStack];
lastItemstackSeenInEvent = null;
helper.assertTrue(testPassed, "Itemstack from last tooltip was not correct. Was " + copyOfLastSeen + " expected " + possibleChoices[itemStack]);
helper.succeed();
});
}
}

View file

@ -34,8 +34,11 @@ public class GatherComponentsEventTest extends BaseTestMod {
@GameTest
public static void is_food(GameTestHelper helper) {
helper.assertTrue(Items.IRON_NUGGET.components().has(DataComponents.FOOD), "Iron Nugget is not edible, failed to apply DataComponents.FOOD to it.");
helper.assertFalse(Items.IRON_INGOT.components().has(DataComponents.FOOD), "Iron Ingot is edible, should not have DataComponents.FOOD");
helper.succeed();
helper.runAfterDelay(5, () -> {
helper.assertTrue(Items.IRON_NUGGET.components().has(DataComponents.FOOD), "Iron Nugget is not edible, failed to apply DataComponents.FOOD to it.");
helper.assertFalse(Items.IRON_INGOT.components().has(DataComponents.FOOD), "Iron Ingot is edible, should not have DataComponents.FOOD");
helper.succeed();
});
}
}

View file

@ -0,0 +1 @@
clientSideOnly=true