This is documentation for EmbersTextAPI 2.9.4. View the latest version

Effect Registry

EffectRegistry is the central factory for all effects. Built-in effects are registered and locked during client setup. Third-party mods can register custom effects with unique names.

Package: net.tysontheember.emberstextapi.immersivemessages.effects


Every effect implements this interface:

public interface Effect {
/** Apply this effect to a character's rendering state. Called once per character per frame. */
void apply(@NotNull EffectSettings settings);
/** The canonical name of this effect. Used for serialization and registry lookup. */
@NotNull String getName();
/** Serialize to string: "effectName key1=value1 key2=value2". Default returns just the name. */
@NotNull default String serialize() { return getName(); }
}

Abstract base class that most effects extend. Provides parameter handling and color parsing utilities.

public abstract class BaseEffect implements Effect {
public BaseEffect(Params params) { ... }
/** Get the raw parameters passed to this effect. */
public Params getParams() { ... }
/** Parse a hex color string to RGB float array [r, g, b]. Accepts "FF0000" or "#FF0000". */
protected static Optional<float[]> parseColor(String hex) { ... }
/** Parse a color from a named parameter with a default fallback. */
protected static float[] parseColor(Params params, String key, float[] defaultColor) { ... }
/** Convert packed RGB integer to float array [r, g, b]. */
protected static float[] intToRGB(int packed) { ... }
/** Convert RGB float values to packed integer. */
protected static int rgbToInt(float r, float g, float b) { ... }
}

/**
* Register an effect factory.
* Names are case-insensitive (normalized to lowercase).
* After the registry is locked, built-in names cannot be overwritten.
*/
public static synchronized void register(String name, Function<Params, Effect> factory)

Example:

EffectRegistry.register("fan", FanEffect::new);
/** Create an effect by name with the given parameters. */
public static Effect create(String name, Params params)
/** Parse and create an effect from a tag content string: "effectName key1=value1" */
public static Effect parseTag(String tagContent)

Example:

Effect wave = EffectRegistry.create("wave", TypedParams.of("a", 2.0, "f", 1.5));
Effect neon = EffectRegistry.parseTag("neon r=3 i=2.0");
public static boolean isRegistered(String name) // Check if registered
public static Set<String> getRegisteredEffects() // All registered names
public static boolean isBuiltIn(String name) // Is it a locked built-in?
public static boolean isLocked() // Is registry locked?
/**
* Initialize all built-in effects and lock the registry.
* Called automatically during mod client setup.
* Safe to call multiple times (subsequent calls are no-ops).
*/
public static synchronized void initializeDefaultEffects()

This is called by ETA during its client setup. You don’t need to call it yourself.


These names are locked after initialization and cannot be overwritten:

NameAliasesCategory
rainbow, rainbColor
grad, gradientColor
colorColor
pulseColor
fadeColor / Global
waveMotion
shakeMotion
bounceMotion
circleMotion
wiggleMotion
pend, pendulumMotion
swingMotion
scrollMotion
turb, turbulenceMotion
glitchSpecial
neon, glowSpecial
shadowSpecial
typewriter, typeAnimation
obfuscateAnimation

The Params interface provides typed access to effect parameters:

public interface Params {
OptionalDouble getDouble(String key);
OptionalBoolean getBoolean(String key);
Optional<String> getString(String key);
}

Implementations:

  • EmptyParams — no parameters (singleton, use Params.EMPTY)
  • TypedParams — wraps an immutable map of parsed key-value pairs

Creating TypedParams programmatically:

Params params = TypedParams.of("a", 2.0, "f", 1.5);

Utility for clamping parameter values to safe ranges:

/**
* Clamp a float value, logging a warning if it was out of range.
*
* @param effectName Name of the effect (for log messages)
* @param paramName Name of the parameter (for log messages)
* @param value The value to clamp
* @param min Minimum allowed value
* @param max Maximum allowed value
* @return Clamped value
*/
public static float clamp(String effectName, String paramName, float value, float min, float max)

For the full guide — JSON format, built-in presets, creating presets via resource packs — see the Preset System guide.

A preset is a reusable bundle of effects and style overrides defined in a JSON file. Presets are used as markup tags (e.g., <epic>, <legendary>).

public record PresetDefinition(
String name,
int formatVersion,
List<EffectEntry> effects,
StyleOverrides styles
)
public record EffectEntry(
String type, // Effect name
Map<String, Object> params // Effect parameters
)
public record StyleOverrides(
Boolean bold,
Boolean italic,
Boolean underline,
Boolean strikethrough,
Boolean obfuscated,
String color, // Hex color string
String font // ResourceLocation string
)

Presets live in assets/emberstextapi/presets/ — the filename (without .json) is the tag name.

assets/emberstextapi/presets/fire.json
{
"format_version": 1,
"effects": [
{ "type": "grad", "params": { "from": "FF4400", "to": "FFAA00", "f": 1.5 } },
{ "type": "neon", "params": { "r": 2.0, "c": "FF3300", "p": 1.5 } }
],
"styles": {
"bold": true,
"color": "FF6600"
}
}

Used as: <fire>FIRE SALE!</fire>

FileTagEffectsStyle
epic.json<epic>Pulse (f=2.0) + WaveBold italic purple (#AA00FF)
legendary.json<legendary>Rainbow (f=1.5, w=0.8) + NeonBold gold (#FFD700)
spooky.json<spooky>Shake (a=0.5, f=3.0) + Fade (a=0.4, f=1.5)Italic dark purple (#2D1B4E)
arcane.json<arcane>Neon (c=9944FF) + Turbulence (a=0.6, f=0.8)Purple (#BB88FF), Cinzel font
chaotic.json<chaotic>Rainbow (f=3.0, w=0.4) + Glitch (f=2.0) + Bounce (a=1.5, f=2.0)Bold
divine.json<divine>Neon (c=FFFFAA) + Wave (a=0.5, f=0.6) + Pulse (f=0.8, a=0.3)Bold gold (#FFD700), Almendra font
frozen.json<frozen>Gradient (88CCFF→FFFFFF) + Pendulum (a=0.4, f=0.5) + Neon (c=44AAFF)Italic, Cardo font
infernal.json<infernal>Gradient (FF4400→FFD700) + Shake (a=0.8, f=4.0) + Neon (c=FF2200)Bold, Norse font
public static PresetDefinition get(String name) // Get by name; null if not found
public static boolean has(String name) // Check existence
public static void register(PresetDefinition preset) // Register programmatically

In a mod: Place JSON files at src/main/resources/assets/emberstextapi/presets/

In a resource pack: Place at assets/emberstextapi/presets/ within the pack.

PresetLoader automatically loads all JSON files from this path at mod initialization. Third-party presets load alongside built-in ones.