Entities

Your game is made up of entities each of which have an associated UUID, position, type and data. These fields can be edited and used alongside Entity Functions to create gameplay.

Types & Behaviour Scripting

Entities are divided into types, each of which have their own behaviour. This behaviour is determined by a script in the entity folder. To create a new entity type, simply create a new file in this folder, call the file entity_type_name.lua and add the stub code shown below:

-- entity_type_name.lua file
local function init(self)
end

local function update(self, dt)
end

local function message(self, msg)
end

return {init=init,update=update, message=message}

There must always be an Entity Type called player which acts as the abstraction for both the player client and other players within the simulation.

These three functions init(), update(), and message() govern the behaviour of all entities of this type. Each must be referenced and returned in a table at the end of the file.

Init

The init() function is called when the entity is created and should be used to set initial state (for example, setting the Chunkloader or Data fields).

local function init(self)
end

Update

The update() function is called each tick to update the entity, for movement and repeating processes. The parameter dt is the time since the last update in seconds.

local function update(self, dt)
end

Message

The message() function receives messages sent to this entity and processes them. Messages can come from other entities or the game client.

All messages sent from the game client are sent to the player entity, and received by the message() function in player.lua. If a message is sent from the client, its message's Client field will be true.

local function message(self, msg)
end

The msg argument supplied to this function is defined as follows:

Field
Type
Description

Data

table

Contains the content of the message.

Client

bool

True, if the message was sent from a game client.

False, if sent from another entity on the server.

Entity Messaging

Messages between entities are sent using api.entity.Message(). They are received by an entity's message function.

For example, sending a message to a particular entity each tick would look like:

local function update(self, dt)
  api.entity.Message(receiverid, {message="hello there", from=self.ID})
end

And be received like this:

local function message(self, msg)
  print("The id of the sender is: ", msg.Data.from) -- prints self.ID
  print("The message is: ", msg.Data.message) -- print "hello there"
end

Client Messaging

Messages can be sent manually from the game engine Client to the game server, using a message function in the SDK. By default the player entity on the server will receive all client messages. The message function of the player.lua file handles these messages.

Messages can be sent from a game engine to a specific entity on the server using the direct message function in the SDK. (Direct Messaging is in Beta and not available for all SDKs).

Client to Server Messaging

Messages are sent to every client automatically every tick, syncing the clientside entities' Data fields with those of the serverside Entity. These updates are typically accessible from the clientside entity itself or the script maintaining the connection to the server.

Automatic Server to Client Updates

Messages can be manually sent to a specific player's game engine client using api.client.Message(). These messages are received by the SDK's server-to-client messaging function.

Manual Server to Client Messages

Entities and Chunks

Entities won't load game world chunks, by default. If an entity tries to move into an unloaded chunk, it will delay processing until the chunk is loaded. Players and Chunkloader entities are not required to wait and will automatically load the required chunk.

Entities can access the data for the chunk they are in, using the chunk variable.

Example Cat Entity

Below is the example cat.lua script which exists in the default template repository. The comments provide further information on what each line is doing.

-- cat.lua
-- init called on creation of entity
local function init(self)
    -- set self.Chunkloader = true means this entity's chunk will always remain loaded
    self.Chunkloader = true
    -- self.Data is an arbitrary table, this is persisted, populated here with target coordinates
    self.Data.target = { x = math.random(-64, 64), y = math.random(-64, 64) }
end

-- update called each simulation step, with dt being the number of seconds since last step (float)
local function update(self, dt)
    -- position must be fetched using self:GetPosition method
    x, y, _ = self:GetPosition()
    -- calculate distance from target on x and y axis
    local dx = self.Data.target.x - x
    local dy = self.Data.target.y - y
    -- if we're close enough then consider ourselves successful
    if dx * dx < 4 and dy * dy < 4 then
        self.Data.target = { x = math.random(-chunk.Size+1, chunk.Size*2-1), y = math.random(-chunk.Size, chunk.Size*2-1) }
    else
        -- determine largest direction of motion
        if dx * dx > dy * dy then
            dx = dx < 0 and -1 or 1
            dy = 0
        elseif dy * dy > dx * dx then
            dy = dy < 0 and -1 or 1
            dx = 0
        else
            dx = dx < 0 and -1 or 1
            dy = dy < 0 and -1 or 1
        end
        -- self:Move(dx, dy, dz) moves relative to current position
        -- by multiplying by dt we move at a constant speed regardless of performance
        -- we also have self:MoveTo(x, y, z) which moves to an absolute position
        -- note that z is left as 0 as this is a 2D game
        self:Move(dx * dt, dy * dt, 0)
    end
end

-- called when this entity receives a message
local function message(self, msg)
end

-- entity file must return table of this format
return { init = init, update = update, message = message }

Entity API

A number of API calls are available for certain entity-related actions such as spawning entities, they are accessed by interfacing with the api.entity object in the global scope within all server-side scripts.

Method
Parameters
Returns
Description

type: string x: float y: float z: float data: table

Entity

Creates a new entity in the current dimension and returns a data copy of it.

entityid: string message: table

None

Sends a message to the entity with UUID entityid.


Entity

Fields

Field
Type
Description

string

UUID of the entity. Read-only.

string

Type of the entity. Read-only.

table

Custom lua table which can be used to store any data about the entity.

Chunkloader (Premium Only)

bool

If true, the chunk containing this entity will remain loaded even if no players are present.

bool

If true, when the chunk containing this entity is unloaded, it will not be persisted.

Methods

Each of these methods takes the entity object self as its first parameter. Hence you may use self:Move(dx, dy, dz) instead of self.Move(self, dx, dy, dz).

Method
Parameters
Returns
Description

dx: float dy: float dz: float

None

Move the entity relative to its current position.

x: float y: float z: float

None

Move the entity relative to the origin (teleport).

None

x: float y: float z: float

Get the current position of the entity. Returns individual coordinates x, y, z.

None

None

Delete this entity.

dist: float

Entity[]

Get entities within the specified distance. Within a 3x3 grid of chunks around the entity.

dimension: string x: float y: float z: float

None

Transport this entity to coordinates (x,y,z) in the dimension specified.

The x, y, and z fields are optional and default to 0.


Init

Method
Parameters
Return Value
Description

self: Entity

None

A necessary function, to initialise an entity in its default state.


Update

Method
Parameters
Return Value
Description

self: Entity dt: float

None

A necessary function, to process an entity's behaviour each tick.


Message

Method
Parameters
Return Value
Description

self: Entity

msg: table({ Data: table Client: bool )}

None

A necessary function, to receive messages to an entity.

Last updated