Client Entity and Static Object API

Methods available on the entity or static object passed to client-side Lua hooks — animations, lights, and visual state.

Client-side hooks receive the object they belong to: mob hooks (a mob’s scripts.client-update / client-on-create / client-on-death / client-on-interact) and mount hooks receive a client entity, and interactable hooks (client-on-interact, client-update, client-on-create) receive a client static object. See lua-modding-overview.md for the full hook tables and signatures.

The two share almost the same API, listed together below. Everything here is visual and local — it changes what this player sees and hears, not the authoritative game state. Gameplay changes (health, blocks, spawning) belong in server-side hooks.


Persistent Script State: lua_data

Both object kinds carry a lua_data table that persists across hook calls for as long as the object exists on this client. Use it for animation timers, sound handles, and other presentation state.

lua_data returns the live table — field changes stick immediately; assigning a whole new table replaces it.

Sound cleanup: store sound objects returned by play_sound as top-level values of an entity’s lua_data (e.g. entity.lua_data.hum = play_sound(...)). When the entity disappears (walks out of range, dies, despawns), the engine automatically stops any sound stored that way. Sounds nested deeper in the table — or stored on a static object’s lua_data — are not auto-stopped and will keep playing; stop those yourself. See lua-client-sounds.md.


Animations

Animation names come from the object’s texture config (see mob-texture-config.md and interactable-texture-config.md). Playing an unknown animation name logs a client warning.

MethodDescription
play_animation(name)Play the named animation from its first frame. If that animation is already the current one, this does nothing (it will not restart it).
play_animation_if_not_playing(name)Play the named animation only if no animation is currently mid-play — use this for idle/looping states so they don’t cut off one-shot animations.
set_texture_variation_number(n)Directly select a texture variation row (number). Normally you don’t need this — play_animation selects the right variation — but it’s useful for permanent visual variants.
flip_horizontal_facing()Mirror the sprite horizontally (turn left/right).

Lights

MethodDescription
add_light(offset_x, offset_y, light)Attach a light to the object at a pixel offset from its origin. light is a light table (see lua-client-lights.md). Adding a light whose id is already attached updates that light in place instead of adding a second one — so calling this every frame with the same id is safe.
get_lights()Returns a list (1-indexed) of the attached lights as tables — each light’s fields plus its x_offset and y_offset. Empty list if none.

Info

MethodReturnsDescription
get_id()numberThis object’s ID — pair with the inventory-opening globals in lua-client-globals.md.
get_location()locationPosition snapshot with read-only .x, .y, .world fields.
get_hitbox()table{ width = number, height = number } — the object’s hitbox size in pixels.
set_display_name(name)Change the displayed name. Entities only — not available on static objects (and only changes it on this client).

Example — Torch-Like Interactable

-- client-on-create: attach a flickering light and a loop sound.
return function(static_object)
    local light = create_new_light()
    light.magnitude = 8.0
    light.dropoff_distance = 4.0
    light.intensity = 1.0
    light.color = { 1.0, 0.75, 0.4, 1.0 }
    static_object:add_light(0.0, -6.0, light)
    static_object.lua_data.light_id = light.id

    static_object:play_animation("burn")

    local crackle = play_sound("Creation:torch_crackle", 40)
    if crackle ~= nil then
        crackle:set_looping(true)
        static_object.lua_data.crackle = crackle
    end
end

See Also