Skip to main content

MagmaCore Lua Scripting Engine

MagmaCore provides a shared Lua scripting engine used by multiple Nightbreak plugins. The engine handles sandboxing, scheduling, zone management, world interaction, entity tables, and player UI -- all with a consistent API across plugins.

Currently, the following plugins use this engine:

  • EliteMobs -- Lua powers for custom bosses (hooks like on_boss_damaged_by_player, on_enter_combat, etc.)
  • FreeMinecraftModels -- Lua scripts for props and custom items (hooks like on_right_click, on_left_click, on_equip, etc.)

This page documents the shared engine features. For plugin-specific hooks, APIs, and workflows, see the plugin pages linked above.


Tiny Lua Primer

If you are completely new to Lua, here is the minimum syntax you need to write scripts for any Nightbreak plugin.

Variables

Use local to store a value:

local cooldown_key = "fire_burst"
local damage_multiplier = 1.5

local means the variable belongs only to this file or block.

Functions

Functions are reusable blocks of logic:

local function warn_player(player)
player:send_message("&cMove!")
end

Later, you can call it:

warn_player(some_player)

if checks

Use if when something should only happen sometimes:

if context.player == nil then
return
end

That means "if there is no player for this hook, stop here".

nil

nil means "no value". It is Lua's version of "nothing is here".

You will often check for nil with:

if context.event ~= nil then
-- do something with the event
end

~= means "is not equal to".

Tables

Lua uses tables for several jobs:

  • Lists
  • Objects with named keys
  • The final returned script definition

Example of a table with named keys:

local particle = {
particle = "FLAME",
amount = 1,
speed = 0.05
}

Returning the script definition

At the end of every script file, you return one table:

return {
api_version = 1,

on_spawn = function(context)
end
}

That returned table is the script file.

Comments

Use -- to write a note for humans:

-- This cooldown stops the attack from firing every hit
context.cooldowns:set_local(60, "fire_burst")

Lua Sandbox

All Lua scripts run inside a sandboxed LuaJ environment. Several globals that could access the filesystem or the Java runtime are removed. The sandbox rules are identical across all plugins using MagmaCore.

Removed Globals

The following standard Lua globals are set to nil and cannot be used:

RemovedWhy
debugExposes internal VM state
dofileFilesystem access
ioFilesystem access
loadArbitrary code loading
loadfileFilesystem access
luajavaDirect Java class access
moduleModule system (not needed)
osOperating system access
packageModule system (not needed)
requireModule system / filesystem access

Available Standard Library

Everything else from the Lua standard library works normally:

CategoryFunctions
Mathmath.abs, math.ceil, math.floor, math.max, math.min, math.random, math.sin, math.cos, math.sqrt, math.pi, and all other math.* functions
Stringstring.byte, string.char, string.find, string.format, string.gsub, string.len, string.lower, string.match, string.rep, string.sub, string.upper, and all other string.* functions
Tabletable.insert, table.remove, table.sort, table.concat, and all other table.* functions
Iteratorspairs, ipairs, next
Typetype, tostring, tonumber, select, unpack
Error handlingpcall, xpcall, error, assert
Otherprint, rawget, rawset, rawequal, rawlen, setmetatable, getmetatable
os library is not available

The os library is completely removed from the sandbox. If you need timing information, use context.world:get_time() for world time or store timestamps in context.state using tick counters with on_tick / on_game_tick.

tip

print writes to the server console, but prefer context.log:info(msg) for output. Log messages are prefixed with the script filename, making it easier to trace which script produced the message.


File Contract

Every Lua script must return a table. That table is intentionally strict.

Required and Optional Top-Level Fields

FieldRequiredTypeNotes
api_versionYesNumberCurrently must be 1
priorityNoNumberExecution priority. Lower values run first. Defaults to 0
supported hook keysNoFunctionMust use one of the exact hook names supported by the plugin

Validation Rules

  • The file must return a table.
  • api_version is required and must currently be 1.
  • priority must be numeric if present.
  • Every extra top-level key must be a supported hook name.
  • Every hook key must point to a function.
  • Unknown top-level keys are rejected.

Helper functions and local constants should live above the final return, not inside the returned table unless they are actual hooks.

local ANIMATION_NAME = "idle"

local function do_something(context)
context.log:info("Doing something!")
end

return {
api_version = 1,
priority = 0,

on_spawn = function(context)
do_something(context)
end
}

Shared Engine Hooks

The following hooks are available to all plugins using the MagmaCore scripting engine. Individual plugins add their own hooks on top of these.

HookWhen it fires
on_spawnCalled once when the script instance is created (entity spawns or prop is placed)
on_game_tickCalled every server tick while the entity is alive/active
on_zone_enterCalled when a player enters a watched zone
on_zone_leaveCalled when a player leaves a watched zone

Method Syntax: : vs .

In Lua, object:method(arg) is shorthand for object.method(object, arg). The MagmaCore API accepts both forms, so either works:

context.log:info("hello")
context.log.info("hello") -- same thing

All documentation uses : consistently.


Execution Budget

Every hook invocation and every callback invocation is timed. If a single call takes longer than 50 milliseconds, the script is disabled with a console warning:

[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.

To stay within budget:

  • Avoid unbounded loops inside hooks.
  • Keep on_game_tick / on_tick handlers lightweight -- they run every single tick.
  • Use context.scheduler:run_repeating(...) to spread work across ticks.
  • Move expensive work behind a state-based cooldown or a reasonable interval.
Script runtime errors

If a Lua script throws a runtime error in any hook or scheduled callback, the script instance is immediately and permanently disabled for that entity. Fix the error in your script file -- the script will re-initialize on the next entity spawn.


context.state

A plain Lua table that persists for the script instance's entire lifetime. Use it to store flags, counters, task IDs, toggle states, and any data you need to share between hooks.

on_spawn = function(context)
context.state.is_open = false
context.state.click_count = 0
context.state.task_id = nil
end,

on_right_click = function(context)
context.state.click_count = (context.state.click_count or 0) + 1
end
info

Only context.state persists between hook calls. All other context tables (context.prop, context.world, context.event, etc.) are rebuilt fresh each time. context.state is not rebuilt -- it survives from the moment the script instance is created until it is destroyed.


context.log

Console logging methods. Messages are prefixed with the script filename in the server console.

MethodNotes
log:info(message)Informational message
log:warn(message)Warning message
log:error(message)Warning-level message (logged at WARN level, same as log:warn)
EliteMobs variant

The EliteMobs context.log registers debug instead of error. Use log:debug(message) for debug output (appears as info-level with a debug prefix).

context.log:info("Script loaded!")
context.log:warn("Something unexpected happened")
context.log:error("Critical failure in zone setup")

context.cooldowns

The cooldowns table manages time-based cooldowns for your scripts. There are two scopes:

  • Local cooldowns are per-script-instance and identified by a string key. If no key is provided, the script's filename is used as the default key.
  • Global cooldowns are shared across all scripts on the same owner entity (e.g. all scripts on the same prop, or all Lua powers on the same boss).

cooldowns:check_local(key?, duration)

The most common method. Checks if the cooldown is ready, and if so, starts it and returns true. If not ready, returns false. This is an atomic check-and-set — no race conditions.

ParameterTypeNotes
keystring (optional)Cooldown identifier. Defaults to the script filename.
durationintCooldown duration in ticks (20 = 1 second)
on_right_click = function(context)
-- Only allow this action once every 3 seconds
if not context.cooldowns:check_local("interact", 60) then
return
end
-- ... do the action
end

cooldowns:local_ready(key?)

Returns true if the local cooldown has expired (or was never set), false if still active.

cooldowns:local_remaining(key?)

Returns the number of ticks remaining on the local cooldown, or 0 if ready.

cooldowns:set_local(duration, key?)

Sets a local cooldown without checking if one is already active. Use this for unconditional cooldown resets.

ParameterTypeNotes
durationintDuration in ticks. Pass 0 or negative to clear.
keystring (optional)Cooldown identifier. Defaults to the script filename.

cooldowns:global_ready()

Returns true if the global cooldown (shared across all scripts on the same entity) has expired.

cooldowns:set_global(duration)

Sets the global cooldown.

ParameterTypeNotes
durationintDuration in ticks
EliteMobs global cooldowns

In EliteMobs power scripts, global_ready() and set_global() use the boss's built-in power cooldown system, which is shared across all Lua powers on the same boss. Local cooldowns in EliteMobs are also shared across all powers on the same boss entity (keyed by your chosen string).


context.scheduler

The scheduler lets you run delayed and repeating tasks. All tasks are owned by the script instance and cancelled automatically when the script instance is destroyed (e.g. when a prop is removed or a boss dies).

scheduler:run_later(ticks, callback)

Runs a callback once after a delay. Returns a numeric task ID.

ParameterTypeNotes
ticksintDelay in server ticks (20 ticks = 1 second)
callbackfunctionCalled with a fresh context when the delay expires
context.scheduler:run_later(40, function(delayed_context)
delayed_context.log:info("2 seconds have passed!")
end)

scheduler:run_repeating(delay, interval, callback)

Runs a callback repeatedly at a fixed interval. Returns a numeric task ID.

ParameterTypeNotes
delayintInitial delay in ticks before the first run
intervalintTicks between each subsequent run
callbackfunctionCalled with a fresh context each interval
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
tick_context.log:info("Another second passed!")
end)

scheduler:cancel(taskId)

Cancels a scheduled task by its ID.

ParameterTypeNotes
taskIdintThe task ID returned by run_later or run_repeating
Always cancel repeating tasks

If you start a repeating task, always cancel it in your cleanup hook (on_destroy for props, on_exit_combat / on_death for bosses, on_unequip for items). Forgetting to cancel leaves a background task running until the script instance is destroyed, which wastes performance and can cause errors.

Callbacks receive fresh context

Scheduled callbacks receive a fresh context as their parameter. Always use the callback's own context argument, not the outer context from the hook that created the callback. The outer context may contain stale references.


context.world

The world table provides methods for querying and interacting with the Minecraft world. It is built from the entity's current world.

Plugin-specific extensions

EliteMobs extends context.world with additional methods for spawning bosses, reinforcements, falling blocks, fireworks, splash potions, and temporary blocks. See EliteMobs World & Environment for the full extended API. The methods documented here are available across all plugins.

world.name

A string field containing the world name.


world:get_block_at(x, y, z)

Returns the material name of the block at the given coordinates as a lowercase string (e.g. "stone", "air").

ParameterTypeNotes
xintBlock X coordinate
yintBlock Y coordinate
zintBlock Z coordinate

world:set_block_at(x, y, z, material)

Sets the block at the given coordinates. Runs on the main thread.

ParameterTypeNotes
xintBlock X coordinate
yintBlock Y coordinate
zintBlock Z coordinate
materialstringBukkit Material name, lowercase (e.g. "stone", "air", "oak_planks")

Returns true if the block was set successfully, false otherwise.


world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)

Spawns particles at a location.

ParameterTypeDefaultNotes
particlestringrequiredBukkit Particle enum name, UPPER_CASE (e.g. "FLAME", "DUST")
xnumberrequiredX coordinate
ynumberrequiredY coordinate
znumberrequiredZ coordinate
countint1Number of particles
dxnumber0X spread/offset
dynumber0Y spread/offset
dznumber0Z spread/offset
speednumber0Particle speed
Data-requiring particles

Some particle types require block or item data that is not supported by this simple API. BLOCK_CRACK, FALLING_DUST, BLOCK_DUST, and ITEM_CRACK will fail or produce no visible effect. Use data-free alternatives instead: CLOUD, SMOKE, CAMPFIRE_COSY_SMOKE, SNOWFLAKE, FLAME, DUST, etc.


world:play_sound(sound, x, y, z, volume, pitch)

Plays a sound at a location.

ParameterTypeDefaultNotes
soundstringrequiredBukkit Sound enum name, UPPER_CASE (e.g. "ENTITY_EXPERIENCE_ORB_PICKUP")
xnumberrequiredX coordinate
ynumberrequiredY coordinate
znumberrequiredZ coordinate
volumenumber1.0Volume
pitchnumber1.0Pitch

world:strike_lightning(x, y, z)

Strikes lightning at a location (visual and damaging).

ParameterTypeNotes
xnumberX coordinate
ynumberY coordinate
znumberZ coordinate

world:get_time()

Returns the current world time in ticks.


world:set_time(ticks)

Sets the world time.

ParameterTypeNotes
ticksintWorld time (0 = dawn, 6000 = noon, 13000 = night, 18000 = midnight)

world:get_nearby_entities(x, y, z, radius)

Returns an array of entity wrapper tables for all entities within a bounding box centered at the given coordinates.

ParameterTypeNotes
xnumberCenter X
ynumberCenter Y
znumberCenter Z
radiusnumberSearch radius (used as half-extent in all three axes)
caution

This returns ALL entities in range, including non-living entities (armor stands, dropped items, etc.). Always guard with if entity.damage then before calling living-entity methods.


world:get_nearby_players(x, y, z, radius)

Returns an array of player wrapper tables for all players within a bounding box centered at the given coordinates.

ParameterTypeNotes
xnumberCenter X
ynumberCenter Y
znumberCenter Z
radiusnumberSearch radius

world:spawn_entity(entity_type, x, y, z)

Spawns a vanilla Minecraft entity at the given location.

ParameterTypeNotes
entity_typestringBukkit entity type name, lowercase (e.g. "zombie", "skeleton", "pig")
xnumberX coordinate
ynumberY coordinate
znumberZ coordinate

Returns an entity table for the spawned entity (with living entity methods if applicable), or nil if the entity type is invalid.


world:get_highest_block_y(x, z)

Returns the Y coordinate of the highest non-air block at the given X/Z position.

ParameterTypeNotes
xintBlock X coordinate
zintBlock Z coordinate

world:raycast(from_x, from_y, from_z, dir_x, dir_y, dir_z, [max_distance])

Casts a ray from a point in a direction and returns information about what it hits.

ParameterTypeDefaultNotes
from_xnumberrequiredOrigin X
from_ynumberrequiredOrigin Y
from_znumberrequiredOrigin Z
dir_xnumberrequiredDirection X component
dir_ynumberrequiredDirection Y component
dir_znumberrequiredDirection Z component
max_distancenumber50Maximum ray distance

Returns a table with the following fields:

FieldTypeNotes
hit_entityentity table or nilThe first entity hit by the ray, or nil if none
hit_locationlocation table or nilThe exact point where the ray hit something
hit_blocktable or nil{x, y, z, material} of the block hit, or nil if no block was hit

world:spawn_firework(x, y, z, colors, [type], [power])

Spawns a firework rocket at the given location.

ParameterTypeDefaultNotes
xnumberrequiredX coordinate
ynumberrequiredY coordinate
znumberrequiredZ coordinate
colorstablerequiredArray of color strings, e.g. {"RED", "BLUE", "WHITE"}
typestring"BALL"Firework shape: "BALL", "BALL_LARGE", "STAR", "BURST", "CREEPER"
powerint1Flight power, 0-127
-- Example: red and gold firework burst
context.world:spawn_firework(loc.x, loc.y, loc.z, {"RED", "GOLD"}, "BURST", 2)

world:place_temporary_block(x, y, z, material, [ticks], [require_air])

Places a block that automatically reverts to its original state after a delay.

ParameterTypeDefaultNotes
xintrequiredBlock X coordinate
yintrequiredBlock Y coordinate
zintrequiredBlock Z coordinate
materialstringrequiredBukkit Material name (e.g. "stone", "ice")
ticksint0Duration in ticks before the block reverts. 0 means permanent.
require_airbooleanfalseIf true, only places the block if the target is air

Returns true if the block was placed, false if the material was invalid or the air requirement was not met.


world:drop_item(x, y, z, material, [amount])

Drops an item entity at the given location with natural scatter.

ParameterTypeDefaultNotes
xnumberrequiredX coordinate
ynumberrequiredY coordinate
znumberrequiredZ coordinate
materialstringrequiredBukkit Material name
amountint1Stack size

Returns an entity table for the dropped item, or nil if the material was invalid.


context.zones

The zones table lets you create spatial zones and watch them for player enter/leave events. Zones are tied to the script instance and cleaned up automatically when the script instance is destroyed.

zones:create_sphere(x, y, z, radius)

Creates a sphere zone centered at the given coordinates. Returns a numeric zone handle.

ParameterTypeNotes
xnumberCenter X
ynumberCenter Y
znumberCenter Z
radiusnumberSphere radius

zones:create_cylinder(x, y, z, radius, height)

Creates a cylinder zone. Returns a numeric zone handle.

ParameterTypeNotes
xnumberCenter X
ynumberCenter Y (base)
znumberCenter Z
radiusnumberCylinder radius
heightnumberCylinder height

zones:create_cuboid(x, y, z, xSize, ySize, zSize)

Creates a cuboid zone. Returns a numeric zone handle.

ParameterTypeNotes
xnumberCenter X
ynumberCenter Y
znumberCenter Z
xSizenumberHalf-extent in X
ySizenumberHalf-extent in Y
zSizenumberHalf-extent in Z

zones:watch(handle, onEnterCallback, onLeaveCallback)

Starts watching a zone for player enter/leave events. The callback parameters act as boolean signals — passing a non-nil value (e.g. a function or true) enables the corresponding hook on the script. The callbacks themselves are not invoked directly. Instead, enter/leave logic fires through the script's on_zone_enter / on_zone_leave hooks.

ParameterTypeNotes
handleintZone handle from a create_* call
onEnterCallbackany non-nil or nilNon-nil enables the on_zone_enter hook for this zone
onLeaveCallbackany non-nil or nilNon-nil enables the on_zone_leave hook for this zone

Returns true if the watch was set up successfully, nil if the zone handle was invalid.

info

Zone watches are checked every server tick against all players in the same world. Keep zone counts reasonable to avoid performance overhead.


zones:unwatch(handle)

Stops watching a zone and cleans up its resources.

ParameterTypeNotes
handleintZone handle to stop watching

Example: Proximity trigger zone

return {
api_version = 1,

on_spawn = function(context)
local loc = context.prop.current_location -- or context.boss:get_location()
if loc == nil then return end

local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)

-- Pass non-nil values to enable on_zone_enter and on_zone_leave hooks.
-- These are boolean signals, not callbacks — the actual logic goes in the hooks below.
context.zones:watch(handle, true, true)

context.state.zone_handle = handle
end,

on_zone_enter = function(context)
context.log:info("Player entered zone!")
end,

on_zone_leave = function(context)
context.log:info("Player left zone!")
end,

on_destroy = function(context)
if context.state.zone_handle then
context.zones:unwatch(context.state.zone_handle)
end
end
}

context.event

The event table is present when the current hook was triggered by a game event (e.g. on_right_click, on_zone_enter). It is not present during on_tick or scheduled callbacks.

Field / MethodTypeNotes
is_cancelledbooleanWhether the event has been cancelled
cancel()methodCancels the event (prevents default behavior)
uncancel()methodUn-cancels a previously cancelled event
playerentity tableThe player involved in the event, if any
on_right_click = function(context)
if context.event then
context.event:cancel() -- prevent the default right-click interaction
end
end
EliteMobs event table

EliteMobs power scripts have a more detailed event table with damage amounts, damage causes, damager references, and damage modification methods. See Lua API Reference for the full EliteMobs event fields.


em Helper Namespace

The em table is available at file load time (before any hook runs). It provides helper constructors for building location tables, vector tables, and zone definitions used throughout the API.

FunctionPurpose
em.create_location(x, y, z [, world, yaw, pitch])Create a location table with optional world name, yaw, and pitch. The returned table also has an .add(dx, dy, dz) method that offsets the location in-place and returns itself for chaining.
em.create_vector(x, y, z)Create a vector table
em.zone.create_sphere_zone(radius)Create a sphere zone definition
em.zone.create_dome_zone(radius)Create a dome zone definition
em.zone.create_cylinder_zone(radius, height)Create a cylinder zone definition
em.zone.create_cuboid_zone(x, y, z)Create a cuboid zone definition
em.zone.create_cone_zone(length, radius)Create a cone zone definition
em.zone.create_static_ray_zone(length, thickness)Create a static ray zone definition
em.zone.create_rotating_ray_zone(length, point_radius, animation_duration)Create a rotating ray zone definition
em.zone.create_translating_ray_zone(length, point_radius, animation_duration)Create a translating ray zone definition

Zone builders return chainable tables with :set_center(loc) (or :set_origin(loc) / :set_destination(loc) depending on zone type):

-- At file scope: create a reusable zone shape
local blast_zone = em.zone.create_sphere_zone(5)

return {
api_version = 1,

on_spawn = function(context)
-- Anchor the zone at call time
blast_zone:set_center(context.boss:get_location())
local entities = context.zones:get_entities_in_zone(blast_zone)
-- ...
end
}
info

The em namespace is particularly useful in EliteMobs where zone definitions are used with context.zones:get_entities_in_zone() and context.script. In FreeMinecraftModels, the context.zones:create_sphere(...) / create_cylinder(...) / create_cuboid(...) methods are more commonly used for simple watch-based zones.


Entity Tables

Entity tables are returned from world queries, event data, and zone callbacks. They provide a layered set of fields and methods depending on the entity type.

Entity Base Fields

FieldTypeNotes
uuidstringThe entity's UUID
entity_typestringThe entity type (e.g. "player", "zombie", "skeleton", "villager")
is_validbooleanWhether the entity reference is still valid
is_deadbooleanWhether the entity is dead
is_playerbooleanWhether the entity is a player
is_hostilebooleanWhether the entity is a hostile mob (zombie, skeleton, etc.)
is_passivebooleanWhether the entity is a passive mob (cow, pig, chicken, etc.)
current_locationlocation tableThe entity's current position (x, y, z, world, yaw, pitch)
worldstringThe world name the entity is in

Entity Base Methods

MethodReturnsNotes
teleport(location_table)voidTeleports the entity. The location table must have x, y, z, world fields; yaw and pitch are optional.
remove()voidRemoves the entity from the world. Only acts if the entity is still valid.
set_silent(flag)voidSuppresses or re-enables the entity's sounds.
set_invulnerable(flag)voidMakes the entity invulnerable or vulnerable to damage.
set_gravity(flag)voidEnables or disables gravity for the entity.
set_glowing(flag)voidToggles the glowing outline effect on the entity.

Living Entity Fields

Living entities (players, mobs, etc.) have all entity base fields plus:

FieldTypeNotes
healthnumberCurrent health
maximum_healthnumberMaximum health
namestringDisplay name
is_alivebooleanWhether the entity is alive

Living Entity Methods

MethodReturnsNotes
damage(amount)voidDeals the given amount of damage to the entity
push(x, y, z)voidApplies a velocity impulse
set_facing(x, y, z)voidSets the direction the entity faces
add_potion_effect(effect, duration, amplifier)voidAdds a potion effect. effect is a string (e.g. "speed", "slowness", "regeneration"). duration is in ticks. amplifier is the effect level minus 1 (0 = level I).
remove_potion_effect(effect)voidRemoves a potion effect by name
get_scale()numberReturns the current entity scale (defaults to 1.0 on servers without the generic.scale attribute)
set_scale(value)voidSets the entity scale via the generic.scale attribute. No-op on servers before 1.20.5.
caution

Not all entities returned by get_nearby_entities() are living entities. You can use entity.is_player, entity.is_hostile, or entity.is_passive to filter by category, or check if entity.damage then before calling living-entity methods like damage(), push(), or add_potion_effect().


Plugin Integration Fields

Entity tables automatically include fields for detecting and interacting with entities managed by other Nightbreak plugins. These fields are only populated when the relevant plugin is installed -- otherwise they default to false / nil with zero overhead.

EliteMobs Fields

Available when EliteMobs is installed.

FieldTypeNotes
is_elitebooleanWhether the entity is an EliteMobs elite
is_custom_bossbooleanWhether the entity is an EliteMobs custom boss (also available inside the elite subtable)
is_significant_bossbooleanWhether the entity is a custom boss with a health multiplier over 1 (i.e. a designed encounter, not a filler elite)
elitetable or nilElite info subtable (see below). nil if the entity is not an elite.

The elite subtable contains:

FieldTypeNotes
elite.levelintThe elite's level
elite.namestringThe elite's display name
elite.healthnumberCurrent health
elite.max_healthnumberMaximum health
elite.is_custom_bossbooleanWhether this is a custom boss (as opposed to a natural elite)
elite.health_multipliernumberConfig-defined health multiplier
elite.damage_multipliernumberConfig-defined damage multiplier
elite:remove()voidRemoves the elite through EliteMobs' proper removal pipeline (cleans up tracking, loot, etc.)
Example: Damage elites differently
local entities = context.world:get_nearby_entities(x, y, z, 5)
for _, entity in ipairs(entities) do
if entity.is_elite then
-- Deal double damage to elites
entity:damage(20)
context.log:info("Hit elite: " .. entity.elite.name .. " (level " .. entity.elite.level .. ")")
elseif entity.is_hostile then
entity:damage(10)
end
end

FreeMinecraftModels Fields

Available when FreeMinecraftModels is installed.

FieldTypeNotes
is_modeledbooleanWhether the entity has an FMM model attached (DynamicEntity or PropEntity)
is_propbooleanWhether the entity is an FMM prop (static decorative entity)
modeltable or nilModel info subtable (see below). nil if the entity is not modeled.

The model subtable contains:

FieldTypeNotes
model.model_idstringThe model blueprint ID (e.g. "torch_01")
model:play_animation(name, [blend], [loop])booleanPlays a named animation. blend defaults to false, loop defaults to false. Returns true if the animation was found.
model:stop_animations()voidStops all currently playing animations on the model.
model:remove()voidRemoves the modeled entity through FMM's proper removal pipeline.
Bridge vs Prop defaults

The model bridge (available on any entity) defaults blend and loop to false. The prop table play_animation defaults both to true because props typically want blended, looped animations.

Example: Filter entities by type
local entities = context.world:get_nearby_entities(x, y, z, 10)
for _, entity in ipairs(entities) do
if entity.is_prop then
-- Skip props
elseif entity.is_player then
entity:damage(5)
elseif entity.entity_type == "villager" then
-- Don't hurt villagers
elseif entity.is_elite then
entity:damage(20)
elseif entity.is_hostile then
entity:damage(10)
end
end

Player-Specific Fields

Player entities have all entity and living entity fields plus:

FieldTypeNotes
game_modestringThe player's game mode ("creative", "survival", "adventure", "spectator")

Player-Specific Methods

MethodReturnsNotes
send_message(msg)voidSends a chat message to the player. Supports & color codes.
get_held_item()table or nilReturns {type, amount, display_name} for the item in the player's main hand, or nil if empty
consume_held_item(amount?)voidConsumes items from the player's main hand. amount defaults to 1
has_item(material, amount?)booleanReturns true if the player has at least amount (default 1) of the given material anywhere in their inventory
get_target_entity([range])entity table or nilReturns the entity the player is looking at via raycast, or nil if none. Default range is 50.
get_eye_location()location tableReturns a location table at the player's eye height
get_look_direction()tableReturns a {x, y, z} direction vector for where the player is looking
send_block_change(x, y, z, material, [ticks])booleanSends a fake block visible only to this player. If ticks is provided, the fake block auto-resets after that duration. Returns true on success, false if the material is invalid.
reset_block(x, y, z)booleanResets a fake block back to the real block for this player. Always returns true.
sleep(x, y, z)voidMakes the player enter a bed sleep animation at the given coordinates. The block is automatically restored when the player stops sleeping.
wake_up()voidWakes up a sleeping player.

Player UI Methods

These methods are available on any player entity table and provide ways to display information to the player through Minecraft's built-in UI elements.

player:show_boss_bar(text, [color], progress, [ticks])

Shows a boss bar to the player.

ParameterTypeDefaultNotes
textstringrequiredThe text to display. Supports & color codes.
colorstring"WHITE"Bar color. One of: "RED", "BLUE", "GREEN", "YELLOW", "PURPLE", "PINK", "WHITE"
progressnumberrequiredFill amount from 0.0 (empty) to 1.0 (full)
ticksintnilOptional auto-dismiss delay in ticks. If omitted, the bar stays until manually hidden.

player:hide_boss_bar()

Removes the boss bar from the player's screen. Takes no parameters.

player:show_action_bar(text, [ticks])

Shows text in the action bar area (above the hotbar).

ParameterTypeDefaultNotes
textstringrequiredThe text to display. Supports & color codes.
ticksintnilOptional duration in ticks. If provided, the message is re-sent every 40 ticks to keep it visible for the full duration.

player:show_title(title, [subtitle], fade_in, stay, fade_out)

Shows a title screen to the player.

ParameterTypeDefaultNotes
titlestringrequiredMain title text. Supports & color codes.
subtitlestring""Subtitle text below the main title. Optional.
fade_inintrequiredFade-in duration in ticks
stayintrequiredHow long the title stays on screen in ticks
fade_outintrequiredFade-out duration in ticks

Next Steps

For plugin-specific hooks, APIs, and workflows: