Kzeroko KTM2

Emoji data

Emoji catalogues, sprite frames, motion parameters and client resource validation.

Updated Sep 18, 2026 6 min read

An emoji definition combines an image, translation keys and motion into a sticker. The server owns the catalogue and playback requests; each client resolves the image from its resource packs, so distribute the data and matching image assets together.

Where the files live

Definitions live at data/<namespace>/emojis/<path>.json, giving emoji ID <namespace>:<path>. Images live under assets/<namespace>/textures/...; texture IDs retain the textures/ prefix and extension. Resource-pack/data-pack priority selects same-ID resources; fields are not merged.

Minimal example

This retains the required fields of bundled isekaiexpansion:evelina/smile and references its existing texture:

{
  "texture": "isekaiexpansion:textures/gui/emoji/evelina/evelinasmile.png",
  "title_key": "emoji.isekaiexpansion.smile.title",
  "caption_key": "emoji.isekaiexpansion.smile.caption",
  "category_key": "emoji.isekaiexpansion.category.positive"
}

Fields

FieldTypeDefaultWhat it does
textureidentifierrequiredResource-pack texture ID including textures/ and .png. Invalid ID syntax rejects the definition; missing images are handled on the client.
title_keystringrequiredNonblank title translation key; its translation is not validated by the data loader.
caption_keystringrequiredNonblank caption translation key.
category_keystringrequiredNonblank category translation key.
orderinteger0Display sort order, ascending; ties use the emoji ID string. No explicit bounds.
duration_ticksinteger70Picker playback duration: 70 ticks (3.5 seconds). Clamped to 20–200 ticks (1–10 seconds).
frame_widthinteger0Frame width in pixels. Negative becomes 0; 0 uses texture width. Positive values cap at texture width.
frame_heightinteger0Frame height in pixels. Negative becomes 0; 0 uses texture height. Positive values cap at texture height.
frame_countinteger1At least 1; the client caps it at the complete grid cells available in the texture.
frame_time_msinteger80Milliseconds per frame, clamped to at least 1.
loopbooleantrueLoops the sprite frames. False holds the last frame.
animationobjectsway_wiggleObject or type-name string. Missing/null selects the default sway; a string uses that type’s defaults.
animation.typeenum(none, sway_wiggle, float_bob, pulse, tremble, bounce, elastic_pop, squash_stretch)sway_wiggleType name, trimmed and case-insensitive. Unknown names reject the catalogue reload.
animation.period_ticksnumbertype defaultPeriod in ticks; clamped to at least 1 tick (0.05 seconds). Defaults below include seconds.
animation.offset_pixelsnumbertype defaultMovement amplitude in pixels; minimum 0.
animation.max_scalenumbertype defaultUpper scale parameter; minimum 0.05, no enforced ordering against min_scale.
animation.min_scalenumbertype defaultLower scale parameter; minimum 0.05.
animation.rotation_degreesnumbertype defaultNonnegative rotation amplitude in degrees. Tremble additionally caps its used amplitude at 4 degrees.
animation.squashnumbertype defaultSquash/stretch parameter, clamped to 0–0.45.
animation.loopbooleantrueLoops icon motion independently of sprite looping. False restores the identity pose after its period.

Motion defaults

Every type defaults to motion looping true. Columns correspond to the animation fields above; period is ticks with seconds.

TypePeriodOffsetMax scaleMin scaleRotationSquash
none30 (1.5 s)01100
sway_wiggle30 (1.5 s)011150
float_bob60 (3 s)41100
pulse28 (1.4 s)01.2100
tremble8 (0.4 s)21130
bounce24 (1.2 s)81100
elastic_pop26 (1.3 s)01.30.8200
squash_stretch24 (1.2 s)91100.18

Dialogue playback options

The isekaiexpansion:emoji dialogue action accepts the following fields inside its action value. These are playback fields, not keys in an emoji definition.

FieldTypeDefaultWhat it does
emojiidentifierrequiredCatalogue ID. Malformed syntax rejects the action; an unknown ID produces no playback.
duration_ticksinteger70At least 1 tick (0.05 seconds) after normalisation; default 70 ticks (3.5 seconds). Independent of definition duration.
priorityinteger50Clamped to 0–1000 when playback options are built.
policystringreplacereplace, queue or force; trimmed and case-insensitive. Unknown names become replace.
targetstringdialogue_entitydialogue_entity, player or both. Unknown names become dialogue_entity. A missing/nonliving dialogue entity is skipped; both still targets the player.
interruptiblebooleantrueAllows ordinary replacement by sufficient priority; force overrides this flag.
interrupt_on_damagebooleantrueEnables server damage interruption of the latest request.

Missing optional fields use the listed defaults; missing emoji or wrong field types fail action decoding. Extra fields are ignored. See Emoji playback API for the queue and damage-interruption contract.

Full example

The bundled smile changes duration to 74 ticks (3.7 seconds), sway period to 48 ticks (2.4 seconds) and rotation amplitude to 2.5 degrees:

{
  "texture": "isekaiexpansion:textures/gui/emoji/evelina/evelinasmile.png",
  "title_key": "emoji.isekaiexpansion.smile.title",
  "caption_key": "emoji.isekaiexpansion.smile.caption",
  "category_key": "emoji.isekaiexpansion.category.positive",
  "order": 20,
  "duration_ticks": 74,
  "animation": {
    "type": "sway_wiggle",
    "period_ticks": 48,
    "rotation_degrees": 2.5
  }
}

Sprite frames advance left to right, then top to bottom. With frame sizes omitted, the entire image is one grid cell; provide dimensions matching the image layout for multiple frames. Incomplete edge cells do not contribute available frames.

Validation

Missing required keys, blank translation keys, invalid texture IDs, wrong types in consumed fields or unknown motion types accumulate into a catalogue reload error. The loader throws before replacement, retaining the previous catalogue when this definition-loading stage fails. Unknown fields are ignored; extra keys cannot change playback priority or queue policy. An empty object lacks required fields; empty text is invalid JSON.

Duration, frame dimensions/count/timing and animation parameters are corrected as listed in the field table rather than rejected for finite out-of-range values. Numeric reads do not provide exact-integer or uniform finite-number validation. Use finite JSON numbers of the stated type; do not rely on fraction truncation or oversized-exponent conversion.

The server does not verify image existence, dimensions or translations. A client with a missing or undecodable image logs a warning and creates no usable image definition for that emoji; other emojis remain available.

Reloading

/reload reloads the server catalogue. Players receive it on join and after successful data-pack reload. Receiving a catalogue rebuilds client image definitions, as does client resource reload. Image bytes are not sent in the catalogue packet; supply a resource pack separately.

Picker requests use the definition’s duration and have a server cooldown of 30 ticks (1.5 seconds). Other playback entry points can supply their own duration, so duration_ticks is not a mandatory lifetime for every playback request.

For screen-space text rendering, see Damage numbers; for entity lifecycle visuals, see Entity FX.