-
Ember's Text API 3.0.0-beta.2
Pre-releaseSome checks failedPublish / Build Fabric 1.20.1 (push) Has been cancelledPublish / Build Fabric 1.21.1 (push) Has been cancelledPublish / Build Fabric 26.1 (push) Has been cancelledPublish / Build NeoForge 1.21.1 (push) Has been cancelledPublish / Build NeoForge 26.1 (push) Has been cancelledPublish / Build Forge 1.20.1 (push) Has been cancelledPublish / Publish Fabric 1.20.1 (push) Has been cancelledPublish / Publish Fabric 1.21.1 (push) Has been cancelledPublish / Publish Fabric 26.1 (push) Has been cancelledPublish / Publish Forge 1.20.1 (push) Has been cancelledPublish / Publish NeoForge 1.21.1 (push) Has been cancelledPublish / Publish NeoForge 26.1 (push) Has been cancelledPublish / Publish to Maven (Forgejo registry) (push) Has been cancelledPublish / Create Forgejo release (push) Has been cancelledPublish / Announce release in Discord (push) Has been cancelledreleased this
2026-06-11 22:08:41 -06:00 | 50 commits to master since this releaseDownloads
Pick the jar that matches your loader and Minecraft version. The same files are also on:
- Modrinth
- CurseForge
- Forgejo Maven (
net.tysontheember.emberstextapi:emberstextapi-<loader>-<mc>:3.0.0-beta.2)
Changelog
Neon glow
- New
gloweffect (aliasneon) renders an SDF-based halo around glyphs:
<glow>,<glow radius=4 intensity=1.5 color=#00ffcc>,
<glow softness=0 core=0.6>for a sharp neon-tube look,freqfor pulsing.
When no color is given the halo picks up each glyph's final color, so
<glow><rainbow>animates the halo with the text. - Glow color resolves per glyph at emit time. Replaces
NeonEffect— the
neonmarkup name still works and now maps to the new effect. - Per-version render paths: core shaders on 1.21.1, the new render-pipeline
API on 26.1, and a bitmap-only runtime SDF path on 1.20.1 (no FreeType
required at runtime). - Glow distance fields bake off the render thread with a per-frame budget;
the atlas uploads only changed slots. Drop shadows are suppressed on
glowing glyphs so halos don't double-darken.
MSDF font pipeline
- Pre-baked MSDF glyphs now persist to disk on all versions — fonts skip the
bake cost on every launch after the first. - SDF providers attach once per resource reload; fixed the glyph baseline on
1.20.1. - Forge 1.20.1 embeds the FreeType natives in the
-alljar and fails the
binding probe cleanly on servers without them.
KubeJS integration (NeoForge 1.21.1)
- New
EmbersTextbinding for scripts: send/queue immersive messages, manage
HUD elements, and style item names and tooltips. - New
EmbersTextEvents.itemTooltipclient event for per-stack tooltip
styling from scripts.
Version parity
- Item-name styling and the
EmbersTextFacadeentry point now ship on every
loader/version target, and the item-name mixin is correctly registered on
NeoForge 26.1. - FTB Quests view tracking ported to 26.1.
- Emojiful compat (1.20.1/1.21.1): effect shadows are dimmed and glow emits
in the Emojiful render path. Not yet available on 26.1. - Obfuscate reveal/hide order is now computed relative to the span start on
1.20.1/1.21.1, matching 26.1 — spans that start mid-text reveal correctly. - Immersive overlay messages now attach span effect data (effect list,
typewriter track, obfuscate keys) to their component styles, so typewriter,
obfuscate reveal/random, scroll, and shadow animate in overlays the same way
they do in chat. The per-char render tier is gated against re-applying
style-carried effects (26.1 covers this with its existing render bypass).
Performance
- Eliminated multiple per-frame allocation and draw-call hot spots in the message
renderer. Stress-test FPS at 50 concurrent messages on NeoForge 26.1 improved
from ~70 to ~1500+ against a ~2000 FPS baseline. EffectApplicator.applyEffectsno longer recursively applies sibling-spawning
effects onto siblings they just created — those level-2 grandchildren never
render. NewEffect#spawnsSiblings()opt-out lets sibling-spawning effects
skip the redundant pass.ImmersiveMessage.buildComponentFromSpanscaches its output keyed on the
typewriter index snapshot.- Per-codepoint glyph width and
FormattedCharSequencenow cached per
(font, codepoint, bold)on each message. - Effects can opt out of per-char dispatch via
Effect#requiresPerChar().
TypewriterEffectopts out whencursor=false— its cropping is already
handled at the component layer. GuiGraphics.drawManagedwraps message rendering on 1.21.1/1.20.1 to collapse
per-text-call buffer flushes (not applicable on 26.1's queued render model).- Background border drawing replaced per-pixel
fillloops with single rotated
fillGradientcalls per strip. Top/bottom borders use a 90° pose rotation so
vanilla's vertical gradient becomes a smooth GPU-interpolated horizontal one. fillHorizontalGradient(multi-stop background fill) uses the same rotation
trick — N-stop gradient renders as N-1 rotated calls per strip instead of one
fill per pixel.
Background gradient extensions
[bg gradient=a,b,c,...]markup now accepts any number of stops (previously
capped at 2).[bg border=a,b,c,...]markup adds N-stop border gradient support. Side
borders use the first and last stops so corners blend cleanly with the N-stop
top/bottom edges.- New
ImmersiveMessage.borderGradient(ImmersiveColor... stops)varargs API.
The existing 2-arg overload continues to work unchanged.
Effect system unification
- Fade is now a
MessageEffectunder the hood.fadeInTicks/fadeOutTicksbuilders
construct and addFadeInMessageEffect/FadeOutMessageEffectto the message's
effect list. The parallel field-based fade state onImmersiveMessageis gone. - New effect names available in markup and
MessageEffectRegistry:fadein,fadeout. MessageEffect#target()(defaultEffectTarget.TEXT) controls whether the effect's
pose transform scopes to text, background, or both.- New
AlphaContributorsub-interface lets effects contribute to a per-frame alpha
multiplier shared by text and background.FadeInMessageEffectand
FadeOutMessageEffectimplement it.
Slide effect background option
<slide>now accepts atargetparam (text,background,all). Default is
all, which slides text and background together. The previous beta.1 behavior of
sliding text only matchestarget=text.
Metadata
- Loader metadata now declares the EML licence (was incorrectly GPL-3.0) and
the licence text is embedded in every jar.
Breaking changes from 3.0.0-beta.1
ImmersiveMessageconstructor,builder,fromMarkup,fromSpans,getDuration,
andsetDurationnow take/returnintticks instead offloat. The internal field
remainsfloatfor partial-tick interpolation.ImmersiveMessage.typewriter(float, boolean),.typewriter(float),
.typewriterCentered(float), and.obfuscate(ObfuscateMode, float)are removed.
Use<type>/<obfuscate>markup, or set typewriter/obfuscate at the span level
viaTextSpan.typewriter(float)/.typewriterCentered(float)/.obfuscate(...).TextSpan.typewriter(float speed, boolean center)is removed. Use
TextSpan.typewriter(float speed)orTextSpan.typewriterCentered(float speed).ImmersiveMessageno longer exposes publicfadeInTicks/fadeOutTicks/
typewriter*/obfuscate*fields.fadeInTicks/fadeOutTicksbuilders still
work and now construct effects; reflection-based consumers must read from
getMessageEffects().- NBT key
"Duration"is now stored asIntTag(previouslyFloatTag). NBT saved by
3.0.0-beta.1will not load. - NBT: legacy
fadeIn,fadeOut,Typewriter,TypewriterSpeed,TypewriterCenter,
ObfuscateMode,ObfuscateSpeedkeys are no longer read or written. Fade state
lives in the existingMessageEffectslist (e.g."fadein t=20"); typewriter and
obfuscate live onTextSpanor come from markup. - S2C message wire format encodes duration as
VarInt(previouslyFloat), the
legacy fade/typewriter/obfuscate per-feature fields are gone from the payload, and
the payload gained a trailing(boolean, VarInt, int[])block for
borderGradientStops. The effects list is the sole carrier for fade.
3.0.0-beta.1clients/servers are incompatible. - NBT gained an optional
BorderGradientlist. Saves without the key load
unchanged. - Default
<slide>behavior changed from text-only to text+background. Pass
target=textin markup, or constructSlideMessageEffectwith that param, to
restore the old shape.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download