Skip to content

API Living Entities and AI

Piggo41 edited this page Sep 28, 2026 · 1 revision

Living entities and AI

Lua API / Entities / Living entities and AI

Living entities can participate in natural spawning and use native, manually controlled, or composed AI behavior.

Natural spawning

A living entity can add spawning to participate in the normal hostile or passive world spawn pass. BetaMoon checks only already-loaded chunks near players and never loads terrain for a spawn attempt.

spawning = {
    category = "passive",
    weight = 10,
    group = { min = 2, max = 4 },
    cap = 24,
    light = { min = 9, max = 15 },
    height = { min = 50, max = 100 },
    dimensions = { 0 },
    biomes = { "Forest", "Seasonal Forest" },
    substrates = { grassBlock },
    despawn = "persistent"
}
Field Default Meaning
category "passive" "hostile" or "passive"; the corresponding vanilla spawn pass must be enabled.
weight 10 Relative selection weight among matching custom types, 1-10000.
group { min = 1, max = 1 } Attempted group size; both values are 1-16.
cap 32 Maximum loaded instances of this type in the world, 1-1024.
light 0-15 Accepted combined light range.
height 1-126 Accepted block Y range.
dimensions Any Up to 64 dimension IDs in -128-127.
biomes Any Up to 64 biome display names; matching is case-insensitive.
substrates Any solid block Up to 64 registered block references or IDs directly beneath the entity.
despawn living.despawn "native" uses vanilla distance despawning; "persistent" prevents it.

The position also needs solid support, clear body space, and no water or lava in the spawn block. The per-type cap counts loaded parent entities, including instances created explicitly. onSpawn receives reason = "natural" for a natural spawn and "script" for spawnEntity or an item-launched custom projectile. Native despawning requires lifecycle = "native".

Living entity settings and AI

Use kind = "living" with optional living settings. The living simulation handles health, collision, gravity, water, and ground movement. maxHealth defaults to 20 (1–32767), movementSpeed to 0.7 (0–4), and despawn to false. attackDamage defaults to 2, attackCooldownTicks to 20, and targetRange to 16 (greater than zero, at most 32). aggression can be "none" (default), "retaliate", or "players"; the latter two require native wander or directed AI.

living.ai accepts a simple native preset string ("idle", "wander", or "directed") or { mode = "native" | "manual", preset, routine, intervalTicks, stages }. A table defaults to native mode with the directed preset. intervalTicks defaults to 1. The routine receives entity, world, and age before movement each time it runs. The preset field is only for native mode.

Native preset Behavior
idle No autonomous movement.
wander Ground path selection and movement.
directed Target/path following without random wandering; Lua can choose targets or destinations.
living = {
    ai = {
        mode = "native",
        preset = "directed",
        intervalTicks = 20,
        routine = function(ctx)
            local player = ctx.world:getClosestPlayer(12)
            ctx.entity:setTarget(player)
        end
    },
    attackDamage = 3
}

Compose AI decisions

For a creature that needs only some decisions in Lua, use living.ai.stages with native AI mode. Its optional target, path, attack, and movement entries each default to { mode = "native" }; set one to { mode = "manual", routine = function(ctx) ... end } to replace that decision. Manual stages accept intervalTicks from 1 to 1200 (default 1) and require their own routine. living.ai.routine runs before these stages, so it can maintain shared state. living.ai.mode = "manual" remains the whole-AI option and cannot be combined with stages.

living = {
    ai = {
        preset = "directed",
        stages = {
            target = {
                mode = "manual",
                intervalTicks = 10,
                routine = function(ctx)
                    return ctx.world:getClosestPlayer(12)
                end
            }
        }
    }
}

This creature chooses a player in Lua and lets BetaMoon plan and follow a native ground path, time melee attacks, and move. Stage callbacks receive entity, world, age, optional current target, and navigationStatus.

Manual stage Return value
target Entity handle selects a live target in the same world; false clears it; nil keeps it.
path { x, y, z, range? } requests a ground route; false cancels; nil keeps the current route. Coordinates are integers, Y is 0–127, and range defaults to 16 with a maximum of 32.
attack Integer 1–32767 requests a melee hit against the current target when in reach and visible, respecting attackCooldownTicks; 0, false, or nil skips. Lua can instead call entity:attack(target, damage) for its own attack rules.
movement { forward, strafe, jump } supplies movement inputs (forward and strafe in -1–1; jump boolean); false stops; nil uses the latest entity:setMovement(...) inputs.

Native target acquisition uses aggression and retains targets set by Lua. Native path choice follows a target with directed or wander; wander also chooses short roaming routes. idle does not choose paths on its own. A Lua path decision can still request one. Native movement follows the selected route. The composed controller is a ground controller; flying and swimming navigation are not provided by these stages. Composed stages require lifecycle = "native"; the wholly manual lifecycle skips this controller.

entity:getNavigationStatus() returns "idle", "moving", "reached", "blocked", "unavailable", or "cancelled" for composed AI. The current status is also in each stage context. entity:getNavigationWaypoint() returns a detached position or nil; entity:cancelNavigation() stops the current route. These methods return nil or false for the simple presets and whole-manual AI. Paths are bounded by range, checked against loaded chunks, and retried at most once every 20 ticks for a persistent blocked destination; no path request loads a chunk. A route becomes blocked when no path is found or progress stalls, unavailable when the required chunks are absent, and reached at its last waypoint. Changing or removing a target clears its route.

For full AI decision control, choose mode = "manual" and use the routine's entity handle to read position, rotation, health, environment, nearby entities, visibility, and persistent or transient data. Lua can select targets with setTarget, request detached native route waypoints with getPathTo, or choose its own route; it then uses setMovement(forward, strafe, jump), facePosition(x, y, z), and attack(target, amount) to act. Store selected routes in entity.memory between ticks. Native collision and living physics remain active unless lifecycle = "manual" takes over the entire tick. ctx.world exposes time, weather, biome, light, terrain, and nearby-player queries. See entity access and movement for signatures.

Clone this wiki locally