Sending Messages
ImmersiveMessage is the main class for creating on-screen text displays. This page covers creating messages, configuring them, and sending them to players.
Package: net.tysontheember.emberstextapi.immersivemessages.api
For a list of all available effects and their parameters, see the Effects Reference.
The Simplest Message
import net.tysontheember.emberstextapi.EmbersTextAPI;
import net.tysontheember.emberstextapi.immersivemessages.api.ImmersiveMessage;
import net.minecraft.network.chat.Component;
ImmersiveMessage msg = new ImmersiveMessage(Component.literal("Hello, World!"), 100f);
EmbersTextAPI.sendMessage(serverPlayer, msg);
The duration is in ticks (20 ticks = 1 second). 100f = 5 seconds.
On Fabric, use EmbersTextAPIFabric.sendMessage() instead.
Creating Messages
From a Component
ImmersiveMessage msg = new ImmersiveMessage(Component.literal("Hello!"), 100f);
From Markup
ImmersiveMessage msg = ImmersiveMessage.fromMarkup(150f,
"<neon r=2><rainbow><bold>Welcome!</bold></rainbow></neon>"
);
From a Plain String
ImmersiveMessage msg = ImmersiveMessage.builder(100f, "Simple message");
From Pre-Built TextSpans
List<TextSpan> spans = MarkupParser.parse("<rainbow>Hello!</rainbow> normal text");
ImmersiveMessage msg = ImmersiveMessage.fromSpans(200f, spans);
Configuration Methods
All configuration methods return this for fluent chaining.
Positioning
msg.anchor(TextAnchor.MIDDLE) // Default: TOP_CENTER
msg.align(TextAlign.CENTER) // Default: LEFT
msg.offset(0f, -30f) // Pixel offset from anchor (x, y)
msg.scale(1.5f) // Default: 1.0
Fade Animations
msg.fadeInTicks(20) // Fade in over 1 second
msg.fadeOutTicks(30) // Fade out over 1.5 seconds
Fade ticks are included in the total duration. For a 5-second message with 1-second fades: duration=100, fadeInTicks(20), fadeOutTicks(20).
Shadow
msg.shadow(true) // Default: true
msg.shadow(false) // Disable shadow
Background
// Simple on/off
msg.background(true)
// With colors (ImmersiveColor uses 0xAARRGGBB format)
msg.backgroundColors(
new ImmersiveColor(0x60000000), // bg: 37% opaque black
new ImmersiveColor(0x80FFFFFF), // border start: 50% opaque white
new ImmersiveColor(0x80FFFFFF) // border end
)
// Background gradient
msg.backgroundGradient("60000040", "60400000") // Hex strings
Text Color Gradient
Use the <grad> markup tag on your spans instead:
List<TextSpan> spans = MarkupParser.parse("<grad from=FF0000 to=0000FF>Hello!</grad>");
// Multi-stop:
List<TextSpan> spans = MarkupParser.parse("<grad from=FF0000 via=FFFF00 to=00FF00>Hello!</grad>");
Typewriter
msg.typewriter(0.5f) // 0.5 characters per tick
msg.typewriter(0.5f, true) // With center-aligned reveal
Wrapping
msg.wrap(200) // Max 200 pixels wide before wrapping
Texture Backgrounds
Use a custom texture as the message background instead of a solid color. Texture backgrounds are Java API-only — there is no markup tag equivalent.
import net.minecraft.resources.ResourceLocation;
// Simple — uses a 256x256 texture at full size
msg.textureBackground(ResourceLocation.parse("mymod:textures/gui/panel.png"));
// Specify texture dimensions
msg.textureBackground(ResourceLocation.parse("mymod:textures/gui/panel.png"), 128, 64);
// Full atlas control — UV offset, region size, atlas size
msg.textureBackground(
ResourceLocation.parse("mymod:textures/gui/atlas.png"),
0, 0, // u, v offset
64, 32, // region width, height
256, 256 // atlas width, height
);
Configuration methods (all return this for chaining):
// Scale the texture (uniform or per-axis)
msg.textureBackgroundScale(2.0f);
msg.textureBackgroundScale(1.5f, 2.0f); // scaleX, scaleY
// Add padding around the text area
msg.textureBackgroundPadding(8.0f);
msg.textureBackgroundPadding(10.0f, 5.0f); // paddingX, paddingY
// Override the rendered size (ignores scale)
msg.textureBackgroundSize(200f, 100f);
msg.textureBackgroundWidth(200f);
msg.textureBackgroundHeight(100f);
// Sizing mode: how the texture fills the background area
msg.textureBackgroundMode(ImmersiveMessage.TextureSizingMode.STRETCH); // Default
msg.textureBackgroundMode(ImmersiveMessage.TextureSizingMode.CROP);
| Method | Description |
|---|---|
textureBackground(ResourceLocation) | Set texture (assumes 256x256 atlas) |
textureBackground(ResourceLocation, width, height) | Set texture with dimensions |
textureBackground(ResourceLocation, u, v, regionW, regionH, atlasW, atlasH) | Full atlas UV control |
textureBackgroundScale(float) | Uniform scale multiplier |
textureBackgroundScale(float, float) | Per-axis scale (X, Y) |
textureBackgroundPadding(float) | Uniform padding around text |
textureBackgroundPadding(float, float) | Per-axis padding (X, Y) |
textureBackgroundSize(float, float) | Override rendered width and height |
textureBackgroundWidth(float) | Override rendered width only |
textureBackgroundHeight(float) | Override rendered height only |
textureBackgroundMode(TextureSizingMode) | STRETCH (default) or CROP |
See TextureSizingMode for sizing mode details.
Full Example
import net.tysontheember.emberstextapi.EmbersTextAPI;
import net.tysontheember.emberstextapi.immersivemessages.api.*;
import net.tysontheember.emberstextapi.immersivemessages.util.ImmersiveColor;
// Build spans from markup
List<TextSpan> spans = MarkupParser.parse(
"<neon r=2><rainbow><bold>Welcome!</bold></rainbow></neon> " +
"<color value=#AAAAAA>Enjoy your stay.</color>"
);
// Create and configure the message
ImmersiveMessage msg = new ImmersiveMessage(spans, 200f)
.anchor(TextAnchor.MIDDLE)
.scale(1.3f)
.background(true)
.backgroundColors(
new ImmersiveColor(0x60000020),
new ImmersiveColor(0xAAFFFFFF),
new ImmersiveColor(0xAA000000)
)
.fadeInTicks(30)
.fadeOutTicks(30);
// Send (must be called on server thread)
EmbersTextAPI.sendMessage(player, msg);
Sending Methods
- Forge / NeoForge
- Fabric
import net.tysontheember.emberstextapi.EmbersTextAPI;
// Simple send (generates UUID automatically)
EmbersTextAPI.sendMessage(serverPlayer, message);
import net.tysontheember.emberstextapi.fabric.EmbersTextAPIFabric;
// Simple send
EmbersTextAPIFabric.sendMessage(serverPlayer, message);
For advanced control (update or close messages by ID), see Networking.
Open / Update / Close Pattern
For messages that persist and need to be updated or closed programmatically (e.g., a progress bar, a running timer), use the explicit Open/Update/Close API via NetworkHelper.
import net.tysontheember.emberstextapi.platform.NetworkHelper;
NetworkHelper net = NetworkHelper.getInstance();
String messageId = "my-progress-bar";
// Open a message with an explicit ID
net.sendOpenMessage(player, message); // generates UUID internally
// Later: update it before it expires
net.sendUpdateMessage(player, messageId, updatedMessage);
// Later: close it explicitly
net.sendCloseMessage(player, messageId);
// Emergency: close everything
net.sendCloseAllMessages(player);
See the full Networking page for all available methods.
Sending Message Queues from Java
import net.tysontheember.emberstextapi.platform.NetworkHelper;
import java.util.List;
NetworkHelper net = NetworkHelper.getInstance();
// Build steps: each step is a list of simultaneous messages
ImmersiveMessage step1a = ImmersiveMessage.fromMarkup(100f, "<rainbow>Step 1 message A</rainbow>");
ImmersiveMessage step1b = ImmersiveMessage.fromMarkup(100f, "<wave>Step 1 message B</wave>");
ImmersiveMessage step2 = ImmersiveMessage.fromMarkup(80f, "Step 2");
List<List<ImmersiveMessage>> steps = List.of(
List.of(step1a, step1b), // Step 1: both show simultaneously
List.of(step2) // Step 2: plays after step 1 finishes
);
net.sendQueue(player, "my-channel", steps);
Important Notes
- Always send messages from the server thread. Never construct or send messages from the client side.
- Duration is in ticks:
20f= 1 second,200f= 10 seconds. - Messages are automatically removed when their duration expires. To remove early, use
sendCloseMessage(). - Do not send a new message every tick for updates — use
sendUpdateMessage()instead.