• v3.0.1 b35455068d

    Ember's Text API 3.0.1
    All checks were successful
    Publish / Build Fabric 26.1 (push) Successful in 12m3s
    Publish / Build Fabric 1.21.1 (push) Successful in 13m50s
    Publish / Build Fabric 1.20.1 (push) Successful in 15m4s
    Publish / Build Fabric 26.2 (push) Successful in 13m33s
    Publish / Build NeoForge 1.21.1 (push) Successful in 16m10s
    Publish / Build NeoForge 26.2 (push) Successful in 14m18s
    Publish / Build NeoForge 26.1 (push) Successful in 16m17s
    Publish / Build Forge 1.20.1 (push) Successful in 6m48s
    Publish / Publish Fabric 1.21.1 (push) Successful in 32s
    Publish / Publish Fabric 26.2 (push) Successful in 32s
    Publish / Publish Fabric 26.1 (push) Successful in 32s
    Publish / Publish Fabric 1.20.1 (push) Successful in 33s
    Publish / Publish Forge 1.20.1 (push) Successful in 8s
    Publish / Publish NeoForge 26.2 (push) Successful in 9s
    Publish / Publish NeoForge 26.1 (push) Successful in 10s
    Publish / Publish NeoForge 1.21.1 (push) Successful in 8s
    Publish / Create Forgejo release (push) Successful in 9s
    Publish / Publish to Maven (Forgejo registry) (push) Successful in 15m42s
    Publish / Announce release in Discord (push) Successful in 4s
    Stable

    TysonTheEmber released this 2026-07-04 22:59:56 -06:00 | 1 commits to master since this release

    Downloads

    Pick the jar that matches your loader and Minecraft version. The same files are also on:

    Changelog

    • Fixed a dedicated-server crash when a command built an immersive message,
      such as an FTB Quests command reward running /eta queue. ImmersiveMessage
      carried its client-only rendering, so loading the class on a server threw
      NoClassDefFoundError: MultiBufferSource. The rendering now lives in a
      client-only holder, leaving the message data safe to load server-side. This
      affected every loader and version; single-player was unaffected because the
      client classes are present there.
    • Unwrapped text now honors hard line breaks. Without wrap set, a \n in the
      message rendered as a missing-glyph box instead of starting a new line; it now
      breaks correctly whether or not wrapping is enabled.
    Downloads
  • v3.0.0 35daec4922

    Ember's Text API 3.0.0
    All checks were successful
    Publish / Build Fabric 1.20.1 (push) Successful in 3m26s
    Publish / Build Fabric 1.21.1 (push) Successful in 4m11s
    Publish / Build Fabric 26.1 (push) Successful in 3m49s
    Publish / Build Fabric 26.2 (push) Successful in 3m19s
    Publish / Build NeoForge 1.21.1 (push) Successful in 5m38s
    Publish / Build NeoForge 26.1 (push) Successful in 4m9s
    Publish / Build NeoForge 26.2 (push) Successful in 4m5s
    Publish / Build Forge 1.20.1 (push) Successful in 3m15s
    Publish / Publish Fabric 1.20.1 (push) Successful in 9s
    Publish / Publish Fabric 1.21.1 (push) Successful in 6s
    Publish / Publish Fabric 26.1 (push) Successful in 7s
    Publish / Publish Fabric 26.2 (push) Successful in 7s
    Publish / Publish Forge 1.20.1 (push) Successful in 8s
    Publish / Publish NeoForge 1.21.1 (push) Successful in 7s
    Publish / Publish NeoForge 26.1 (push) Successful in 7s
    Publish / Publish NeoForge 26.2 (push) Successful in 6s
    Publish / Create Forgejo release (push) Successful in 8s
    Publish / Publish to Maven (Forgejo registry) (push) Successful in 15m5s
    Publish / Announce release in Discord (push) Successful in 4s
    Stable

    TysonTheEmber released this 2026-06-21 22:45:37 -06:00 | 5 commits to master since this release

    Downloads

    Pick the jar that matches your loader and Minecraft version. The same files are also on:

    Changelog

    • NeoForge and Fabric support for MC 26.1.x and 26.2, including the neon glow
      and SDF text pipeline ported to 26.2's new bind-group render API. The FTB
      Quests and Emojiful integrations are not present on 26.2.
    • FTB Quests composer: an ETA button on the quest text editor opens a composer
      with effect and preset pickers, a font picker, per-parameter controls, and a
      live preview that writes the composed markup back into the editor. Available
      on 1.20.1, 1.21.1, and 26.1.
    • Effect parameters reworked for consistent naming with multiple accepted
      aliases per parameter. Gradient and rainbow gained an angle; rainbow gained
      length, saturation, and brightness; neon gained flicker controls.
    • <shadow> is now independent of the host text's drop shadow, so it renders
      even where the host draws without one (such as FTB Quests titles), and an
      explicit shadow color is no longer dimmed.
    • Twemoji coexistence: Twemoji's emoji render alongside ETA markup.
    • Lang tag args now supports escaping commas with a backslash so a single
      argument can contain commas: <lang key='commands.give.success.single' args='$9\,000'> passes $9,000 as one argument. A literal backslash is
      written \\.
    • Emojiful compat: text effects now apply to chat messages on Forge 1.20.1.
      The render hook targeted the dev-mapped method name, which silently no-ops
      against the SRG-named build that ships in production. The integration also
      reads Emojiful's renderer state through accessor mixins instead of
      reflection.
    Downloads
  • v3.0.0-beta.2 39b1b1a9b1

    Ember's Text API 3.0.0-beta.2
    Some checks failed
    Publish / Build Fabric 1.20.1 (push) Has been cancelled
    Publish / Build Fabric 1.21.1 (push) Has been cancelled
    Publish / Build Fabric 26.1 (push) Has been cancelled
    Publish / Build NeoForge 1.21.1 (push) Has been cancelled
    Publish / Build NeoForge 26.1 (push) Has been cancelled
    Publish / Build Forge 1.20.1 (push) Has been cancelled
    Publish / Publish Fabric 1.20.1 (push) Has been cancelled
    Publish / Publish Fabric 1.21.1 (push) Has been cancelled
    Publish / Publish Fabric 26.1 (push) Has been cancelled
    Publish / Publish Forge 1.20.1 (push) Has been cancelled
    Publish / Publish NeoForge 1.21.1 (push) Has been cancelled
    Publish / Publish NeoForge 26.1 (push) Has been cancelled
    Publish / Publish to Maven (Forgejo registry) (push) Has been cancelled
    Publish / Create Forgejo release (push) Has been cancelled
    Publish / Announce release in Discord (push) Has been cancelled
    Pre-release

    TysonTheEmber released this 2026-06-11 22:08:41 -06:00 | 50 commits to master since this release

    Downloads

    Pick the jar that matches your loader and Minecraft version. The same files are also on:

    Changelog

    Neon glow

    • New glow effect (alias neon) 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, freq for 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
      neon markup 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 -all jar and fails the
      binding probe cleanly on servers without them.

    KubeJS integration (NeoForge 1.21.1)

    • New EmbersText binding for scripts: send/queue immersive messages, manage
      HUD elements, and style item names and tooltips.
    • New EmbersTextEvents.itemTooltip client event for per-stack tooltip
      styling from scripts.

    Version parity

    • Item-name styling and the EmbersTextFacade entry 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.applyEffects no longer recursively applies sibling-spawning
      effects onto siblings they just created — those level-2 grandchildren never
      render. New Effect#spawnsSiblings() opt-out lets sibling-spawning effects
      skip the redundant pass.
    • ImmersiveMessage.buildComponentFromSpans caches its output keyed on the
      typewriter index snapshot.
    • Per-codepoint glyph width and FormattedCharSequence now cached per
      (font, codepoint, bold) on each message.
    • Effects can opt out of per-char dispatch via Effect#requiresPerChar().
      TypewriterEffect opts out when cursor=false — its cropping is already
      handled at the component layer.
    • GuiGraphics.drawManaged wraps 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 fill loops with single rotated
      fillGradient calls 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 MessageEffect under the hood. fadeInTicks / fadeOutTicks builders
      construct and add FadeInMessageEffect / FadeOutMessageEffect to the message's
      effect list. The parallel field-based fade state on ImmersiveMessage is gone.
    • New effect names available in markup and MessageEffectRegistry: fadein, fadeout.
    • MessageEffect#target() (default EffectTarget.TEXT) controls whether the effect's
      pose transform scopes to text, background, or both.
    • New AlphaContributor sub-interface lets effects contribute to a per-frame alpha
      multiplier shared by text and background. FadeInMessageEffect and
      FadeOutMessageEffect implement it.

    Slide effect background option

    • <slide> now accepts a target param (text, background, all). Default is
      all, which slides text and background together. The previous beta.1 behavior of
      sliding text only matches target=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

    • ImmersiveMessage constructor, builder, fromMarkup, fromSpans, getDuration,
      and setDuration now take/return int ticks instead of float. The internal field
      remains float for 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
      via TextSpan.typewriter(float) / .typewriterCentered(float) / .obfuscate(...).
    • TextSpan.typewriter(float speed, boolean center) is removed. Use
      TextSpan.typewriter(float speed) or TextSpan.typewriterCentered(float speed).
    • ImmersiveMessage no longer exposes public fadeInTicks / fadeOutTicks /
      typewriter* / obfuscate* fields. fadeInTicks / fadeOutTicks builders still
      work and now construct effects; reflection-based consumers must read from
      getMessageEffects().
    • NBT key "Duration" is now stored as IntTag (previously FloatTag). NBT saved by
      3.0.0-beta.1 will not load.
    • NBT: legacy fadeIn, fadeOut, Typewriter, TypewriterSpeed, TypewriterCenter,
      ObfuscateMode, ObfuscateSpeed keys are no longer read or written. Fade state
      lives in the existing MessageEffects list (e.g. "fadein t=20"); typewriter and
      obfuscate live on TextSpan or come from markup.
    • S2C message wire format encodes duration as VarInt (previously Float), 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.1 clients/servers are incompatible.
    • NBT gained an optional BorderGradient list. Saves without the key load
      unchanged.
    • Default <slide> behavior changed from text-only to text+background. Pass
      target=text in markup, or construct SlideMessageEffect with that param, to
      restore the old shape.
    Downloads
  • v3.0.0-beta.1 0c79817755

    Ember's Text API 3.0.0-beta.1
    Some checks failed
    Publish / Publish Fabric 1.20.1 (push) Has been cancelled
    Publish / Publish Fabric 1.21.1 (push) Has been cancelled
    Publish / Publish Fabric 26.1 (push) Has been cancelled
    Publish / Publish NeoForge 1.21.1 (push) Has been cancelled
    Publish / Publish NeoForge 26.1 (push) Has been cancelled
    Publish / Publish Forge 1.20.1 (push) Has been cancelled
    Publish / Publish to Maven (Forgejo registry) (push) Has been cancelled
    Publish / Announce release in Discord (push) Has been cancelled
    Pre-release

    TysonTheEmber released this 2026-05-23 00:33:06 -06:00 | 153 commits to master since this release

    Downloads

    Pick the jar that matches your loader and Minecraft version. The same files are also on:

    Changelog

    Changed

    • Replaced the config system. Options are now defined by a single schema split
      into two files: emberstextapi-client.toml/.json (per-client: which effects
      render, performance) and emberstextapi-server.toml/.json (authoritative:
      player markup permissions, message limits, anvil rename length). The old
      emberstextapi-common.toml, emberstextapi-client.toml (old layout) and
      emberstextapi.json are no longer read — settings must be re-applied in the
      new files, which generate with defaults on first run.
    • Player markup access is now permission-gated. playerMarkup.mode is ALL,
      PERMISSION (nodes emberstextapi.markup.use, .effect.<name>,
      .category.<cat>, .bypass, with an OP-level fallback), or NONE. Effects
      can be allowed/denied per-effect or per-category for both the client render
      gate and the server markup gate. LuckPerms and FTB Ranks back the permission
      nodes automatically.
    • Unified effect parameter naming across visual, message, and animation effects.
      Every public param now has a canonical fully-spelled name and a short alias
      (e.g., amplitude/amp, frequency/freq, duration/dur). Old ad-hoc
      shorts (a/f/w, etc.) no longer work — see
      docs/superpowers/specs/2026-05-18-effect-parameter-refinement-design.md
      for the full rename table.
    • Effects now declare params via ParamSchema; unknown params log a warning
      instead of being silently ignored.
    • obfuscate's speed is renamed to interval (ms per step).
    • shatter's speed is renamed to duration (animation length in seconds).
    • matrix's resolve is renamed to duration.
    • vibrate's intensity is renamed to amplitude; speed to frequency.
    • breathe's amount is renamed to amplitude; speed to frequency.
    • circle's a is renamed to radius (the param was always a radius, not an
      amplitude).
    • drift's rx/ry are renamed to amplitudeX/amplitudeY.
    • gradient's span is renamed to length; speed to frequency.
    • fade's a is renamed to minAlpha.
    • neon's p/f are renamed to frequency/falloff; c to color.
    • RainbowEffect.getName() now returns "rainbow" (was "rainb").
    • GradientEffect.getName() now returns "gradient" (was "grad").
    • TurbulenceEffect.getName() now returns "turbulence" (was "turb").
    • PendulumEffect.getName() now returns "pendulum" (was "pend").
    • typewriter's cursor param is now boolean-only; use cursorChar to set
      the glyph. The cursor=<char> overload is dropped.

    Added

    • Seven new immersive-message motion effects: grow (continuous scale
      oscillation), slam (one-shot drop-in with damped bounces), float
      (slow sinusoidal drift), drift (independent X/Y wander), vibrate
      (high-frequency jitter), spin (full Z-axis rotation), and slide
      (one-shot slide-in or slide-out from any screen edge). All compose with
      the existing rock/breathe effects and with each other.
    • slide accepts an easing param: linear, easeInCubic, easeOutCubic,
      easeInOutCubic. Defaults match prior behavior (easeOutCubic for
      mode=in, easeInCubic for mode=out).
    • Three per-character message effects: drip (characters fall and trail
      downward in staggered order), shatter (characters fragment outward at a
      configurable trigger time), and matrix (characters scramble via random
      glyph cycling then resolve in stagger order).
    • outline span effect: renders a stroked outline around glyphs using a
      second SDF draw pass with a configurable color (c) and width (w).
      Requires an SDF font; logs a warning and skips the outline draw on vanilla
      fonts.
    • Per-character effect dispatch: MessageEffect implementations can opt in
      via perCharacter() to receive an applyToChar call for each rendered
      glyph, enabling effects that vary per character. Existing whole-message
      effects are unaffected.
    • [sound ...] message effect plays a Minecraft sound at a configurable time
      offset (at), volume, and pitch. Built-in presets (click, whoosh,
      static, magic, pop, thud, shatter) map to vanilla sound ids;
      any resource location works as well. drip, shatter, matrix, and
      slam each accept an inline sound param that fires on their respective
      key moment (first drip, shatter trigger, matrix resolve, slam land).
    • ETA markup inside Component.translatable string arguments now renders.
      <...> tags in arguments passed to translatable(key, args...) are
      parsed by the existing markup pipeline instead of being forwarded as
      literal strings.
    • EffectRegistry.getSchema(name) and MessageEffectRegistry.getSchema(name)
      return the ParamSchema for an effect, enabling introspection and doc
      tooling.
    • The server syncs each player's effective markup policy on join; the client
      caches it for accurate previews and feedback.
    • /emberstextapi reload reloads config from disk and re-syncs policy to
      online players; /emberstextapi policy [player] prints a player's resolved
      markup policy.
    • MSDF font rendering now works on MC 26.1 (NeoForge and Fabric); pipelines
      are registered against the 26.1 RenderPipelines API.
    Downloads