🇬🇧 English
🇬🇧 English
Appearance
🇬🇧 English
🇬🇧 English
Appearance
This page is written for version:
1.21.10
We already briefly touched on rendering things to the HUD in the Basic Rendering Concepts page and Using The Drawing Context, so on this page we'll stick to the Hud API and the RenderTickCounter parameter.
HudRenderCallback WARNING
Previously, Fabric provided HudRenderCallback to render to the HUD. Due to changes to HUD rendering, this event became extremely limited and is deprecated since Fabric API 0.116. Usage is strongly discouraged.
HudElementRegistry Fabric provides the Hud API to render and layer elements on the HUD.
To start, we need to register a listener to HudElementRegistry which registers your elements. Each element is an HudElement. A HudElement instance is usually a lambda that takes a DrawContext and a RenderTickCounter instance as parameters. See HudElementRegistry and related Javadocs for more details on how to use the API.
The draw context can be used to access the various rendering utilities provided by the game, and access the raw matrix stack. You should check out the Draw Context page to learn more about the draw context.
The RenderTickCounter class allows you to retrieve the current tickProgress value. tickProgress is the "progress" between the last game tick and the next game tick.
For example, if we assume a 200 FPS scenario, the game runs a new tick roughly every 10 frames. Each frame, tickProgress represents how far we are between the last tick and the next. Over 11 frames, you might see:
| Frame | tickProgress |
|---|---|
1 | 1: New tick |
2 | 1/10 = 0.1 |
3 | 2/10 = 0.2 |
4 | 3/10 = 0.3 |
5 | 4/10 = 0.4 |
6 | 5/10 = 0.5 |
7 | 6/10 = 0.6 |
8 | 7/10 = 0.7 |
9 | 8/10 = 0.8 |
10 | 9/10 = 0.9 |
11 | 1: New tick |
In practice, you should only use tickProgress when your animations depend on Minecraft's ticks. For time-based animations, use Util.getMeasuringTimeMs(), which measures real-world time.
You can retrieve tickProgress by calling renderTickCounter.getTickProgress(false), where the boolean parameter is ignoreFreeze, which essentially just allows you to ignore whenever players use the /tick freeze command.
In this example, we'll use Util.getMeasuringTimeMs() to linearly interpolate the color of a square that is being rendered to the HUD.
public class HudRenderingEntrypoint implements ClientModInitializer {
@Override
public void onInitializeClient() {
// Attach our rendering code to before the chat hud layer. Our layer will render right before the chat. The API will take care of z spacing.
HudElementRegistry.attachElementBefore(VanillaHudElements.CHAT, Identifier.of(ExampleMod.MOD_ID, "before_chat"), HudRenderingEntrypoint::render);
}
private static void render(DrawContext context, RenderTickCounter tickCounter) {
int color = 0xFFFF0000; // Red
int targetColor = 0xFF00FF00; // Green
// You can use the Util.getMeasuringTimeMs() function to get the current time in milliseconds.
// Divide by 1000 to get seconds.
double currentTime = Util.getMeasuringTimeMs() / 1000.0;
// "lerp" simply means "linear interpolation", which is a fancy way of saying "blend".
float lerpedAmount = MathHelper.abs(MathHelper.sin((float) currentTime));
int lerpedColor = ColorHelper.lerp(lerpedAmount, color, targetColor);
// Draw a square with the lerped color.
// x1, x2, y1, y2, color
context.fill(0, 0, 10, 10, lerpedColor);
}
}
Why don't you try use tickProgress and see what happens to the animation when you run the /tick freeze command? You should see the animation freeze in place as tickProgress becomes constant (assuming you have passed false as the parameter to RenderTickCounter#getTickProgress)