values
Named values an entity holds: typed numbers, vectors and booleans (throttle, rpm, gear, headlights, doorOpen) that scripts and engine systems write and read cheaply, and that materials, audio voices, the UI and replication follow without a script copying them every frame. A value stays on this engine unless it is declared to replicate, at a rate in Hz.
require("@builtin::modules.api.engine.values") -- values (also available as global 'values')
The values namespace: 47 functions.
entity/proxy/values/clear
entity(id).values.clear() -> number
Drop every named value this entity holds; answers how many it held.
Returns number
entity/proxy/values/declare
entity(id).values.declare(name: string, declaration: { type: string?, default: (number | vector | boolean)?, replicate: number? }?) -> ()
State a named value's type, the default it starts at, and the rate in Hz it replicates at; a value with no replicate rate stays on this engine.
Parameters
namestringdeclaration{ type: string?, default: (number | vector | boolean)?, replicate: number? }(optional)
Returns ()
car.values.declare("throttle", { type = "number", replicate = 10 })
entity/proxy/values/describe
entity(id).values.describe() -> { { name: string, type: string, value: number | vector | boolean, writer: string, revision: number, replicate: number?, declared: boolean } }
Every named value this entity holds with its type, last writer, revision and replication rate, sorted by name.
Returns { { name: string, type: string, value: number | vector | boolean, writer: string, revision: number, replicate: number?, declared: boolean } }
entity/proxy/values/get
entity(id).values.get(name: string) -> (number | vector | boolean)?
The named value this entity holds, or nil.
Parameters
namestring
Returns (number | vector | boolean)?
local rpm = car.values.get("rpm") or 0
entity/proxy/values/list
entity(id).values.list() -> { [string]: number | vector | boolean }
Every named value this entity holds, by name.
Returns { [string]: number | vector | boolean }
entity/proxy/values/remove
entity(id).values.remove(name: string) -> boolean
Drop a named value; answers whether this entity held it.
Parameters
namestring
Returns boolean
entity/proxy/values/set
entity(id).values.set(name: string, value: (number | vector | boolean)?) -> ()
Write a named value: a number, a vector or a boolean; nil removes it. A name keeps the kind of its first value. Nothing is replicated unless the name is declared to replicate.
Parameters
namestringvalue(number | vector | boolean)(optional)
Returns ()
car.values.set("rpm", 3200)
entity/proxy/values/subscribe
entity(id).values.subscribe(name: string?, callback: ((number | vector | boolean)?, string, string) -> ()) -> { Connected: boolean, Disconnect: (any) -> () }
Call callback(value, name, entityId) once per frame in which a named value changed, whoever changed it; nil name follows every value of this entity.
Parameters
namestring(optional)callback((number | vector | boolean)?, string, string) -> ()
Returns { Connected: boolean, Disconnect: (any) -> () }
car.values.subscribe("gear", function(gear) print(gear) end)
globals/values/bind
values.bind(target: string | entityRef, name: string, opts: { format: string?, scale: number?, offset: number?, fallback: any? }?) -> ValueBinding
A UI prop that follows a named value, with no script updating the
screen: put it where a widget takes text, value, visible,
checked or enabled, and the widget reads the value every frame.
format is a string.format pattern for text ("%d rpm"; the value
as it reads when absent); scale and offset map a number
(value * scale + offset) before it is shown. A value the entity does
not hold shows fallback (empty text, 0 or false when absent).
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.opts{ format: string?, scale: number?, offset: number?, fallback: any? }(optional) —{ format?, scale?, offset?, fallback? }.
Returns ValueBinding — A binding to place in a widget's props.
ui.registerScreen("dash", { type = "vertical", children = {
{ type = "label", props = { text = values.bind(car, "rpm", { format = "%.0f rpm" }) } },
{ type = "slider", props = { min = 0, max = 1, value = values.bind(car, "throttle") } },
} })
globals/values/clear
values.clear(target: string | entityRef) -> number
Drop every named value an entity holds. An entity's values also go when the entity leaves the world.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
Returns number — How many values it held.
values.clear(car)
globals/values/declare
values.declare(target: string | entityRef, name: string, declaration: ValueDeclaration?)
State what a named value is: its type ("number", "vector" or
"boolean"), the default it starts at, and whether it replicates. A name
the entity already holds keeps its value. replicate is a rate in Hz (up
to 60): the owner of the entity sends the value to every other peer at
most that often while it changes, and always sends the latest one, and
the other peers read it like any value. A value with no replicate is
never sent anywhere.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.declarationValueDeclaration(optional) —{ type?, default?, replicate? }; givetypeordefaultfor a name the entity does not hold yet.
values.declare(car, "throttle", { type = "number", default = 0, replicate = 10 })
values.declare(car, "brake", { default = false, replicate = 20 })
globals/values/describe
values.describe(target: string | entityRef) -> { ValueRow }
Every named value an entity holds, sorted by name, each with its
type, its value, who wrote it last (writer: "script", "engine" or
"remote"), the store revision of its last change, its replicate rate
(absent for a value kept on this engine) and whether a declaration states
it. The same rows /zero/runtime/values/<entityId> and the values
toolbox list.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
Returns { ValueRow } — The rows.
for _, row in values.describe(car) do print(row.name, row.type, row.value, row.writer) end
globals/values/entities
values.entities() -> { string }
Every entity holding at least one named value, sorted by id.
Returns { string } — Entity ids.
for _, id in values.entities() do print(id, #values.describe(id)) end
globals/values/get
values.get(target: string | entityRef, name: string) -> Value?
Read a named value an entity holds, or nil when it holds none under
that name. Engine systems write values too: a WheelCollider writes its
own state (wheel.slipRatio, wheel.angularVelocity, ...), so a script
reads it here the way it reads a value a script wrote.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.
Returns Value? — The value, or nil.
local rpm = values.get(car, "rpm") or 0
globals/values/list
values.list(target: string | entityRef) -> { [string]: Value }
Every named value an entity holds, by name.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
Returns { [string]: Value } — { [name] = value }.
for name, v in values.list(car) do print(name, v) end
globals/values/onAnyChange
values.onAnyChange(callback: (Value?, string, string) -> ()) -> ValueConnection
Call callback(value, name, entityId) for every change of every named
value on every entity, once per frame in which it changed: what a debug
view or a recorder of a session's values follows.
Parameters
callback(Value?, string, string) -> ()—function(value, name, entityId).
Returns ValueConnection — A connection; :Disconnect() ends it.
local conn = values.onAnyChange(function(v, name, id) print(id, name, v) end)
globals/values/remove
values.remove(target: string | entityRef, name: string) -> boolean
Drop a named value from an entity.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.
Returns boolean — Whether the entity held it.
values.remove(car, "rpm")
globals/values/set
values.set(target: string | entityRef, name: string, value: Value?)
Write a named value on an entity: a number, a vector or a boolean;
nil removes it. A name takes the kind of its first value and keeps it:
writing another kind raises (remove the value first to change its kind).
The write is a store, with nothing replicated and nothing copied, and
every reader sees it from the next read: values.get, a material
property bound to the name, an Audio voice following it, a UI prop
values.bind made. Only a value values.declare gives a replicate
rate is ever sent to other peers.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.valueValue(optional) — A number, a vector or a boolean;nilremoves the value.
values.set(car, "rpm", 3200)
values.set(car, "headlights", true)
values.set(car, "wheelSpin", vector.create(0, 12.5, 0))
globals/values/stats
values.stats() -> { entities: number, values: number, revision: number, replication: ValueReplicationStats }
How many entities hold values, how many values there are, the
store's revision (which advances on every change), and what replication
has carried: a value with no replicate rate adds nothing to it.
Returns { entities: number, values: number, revision: number, replication: ValueReplicationStats } — { entities, values, revision, replication }.
print(values.stats().values, values.stats().replication.sentBytes)
globals/values/subscribe
values.subscribe(target: string | entityRef, name: string?, callback: (Value?, string, string) -> ()) -> ValueConnection
Call callback(value, name, entityId) when a named value of an entity
changes, whoever changed it: a script, an engine system or another peer.
Give name to follow one value, or nil to follow every value of the
entity. The callback runs once for the writes a frame made, on the
engine's next pass over its tasks, with the value as it stands then:
three writes in one frame are one call with the last of them. A value
that went (values.remove, its entity left the world) arrives as nil.
A subscription made by a component ends with the component.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring(optional) — The value's name, or nil for every value of the entity.callback(Value?, string, string) -> ()—function(value, name, entityId).
Returns ValueConnection — A connection; :Disconnect() ends it.
local conn = values.subscribe(car, "gear", function(gear) print("now in gear", gear) end)
conn:Disconnect()
modules/values/bind
bind(
A UI prop that follows a named value, with no script updating the
screen: put it where a widget takes text, value, visible,
checked or enabled, and the widget reads the value every frame.
format is a string.format pattern for text ("%d rpm"; the value
as it reads when absent); scale and offset map a number
(value * scale + offset) before it is shown. A value the entity does
not hold shows fallback (empty text, 0 or false when absent).
ui.registerScreen("dash", { type = "vertical", children = {
{ type = "label", props = { text = values.bind(car, "rpm", { format = "%.0f rpm" }) } },
{ type = "slider", props = { min = 0, max = 1, value = values.bind(car, "throttle") } },
} })
modules/values/clear
clear(target: string | entityRef): number
Drop every named value an entity holds. An entity's values also go when the entity leaves the world.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
values.clear(car)
modules/values/declare
declare(target: string | entityRef, name: string, declaration: ValueDeclaration?)
State what a named value is: its type ("number", "vector" or
"boolean"), the default it starts at, and whether it replicates. A name
the entity already holds keeps its value. replicate is a rate in Hz (up
to 60): the owner of the entity sends the value to every other peer at
most that often while it changes, and always sends the latest one, and
the other peers read it like any value. A value with no replicate is
never sent anywhere.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.declarationValueDeclaration?(optional) —{ type?, default?, replicate? }; givetypeordefaultfor a name the entity does not hold yet.
values.declare(car, "throttle", { type = "number", default = 0, replicate = 10 })
values.declare(car, "brake", { default = false, replicate = 20 })
modules/values/describe
describe(target: string | entityRef): { ValueRow }
Every named value an entity holds, sorted by name, each with its
type, its value, who wrote it last (writer: "script", "engine" or
"remote"), the store revision of its last change, its replicate rate
(absent for a value kept on this engine) and whether a declaration states
it. The same rows /zero/runtime/values/<entityId> and the values
toolbox list.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
for _, row in values.describe(car) do print(row.name, row.type, row.value, row.writer) end
modules/values/entities
entities(): { string }
Every entity holding at least one named value, sorted by id.
for _, id in values.entities() do print(id, #values.describe(id)) end
modules/values/get
get(target: string | entityRef, name: string): Value?
Read a named value an entity holds, or nil when it holds none under
that name. Engine systems write values too: a WheelCollider writes its
own state (wheel.slipRatio, wheel.angularVelocity, ...), so a script
reads it here the way it reads a value a script wrote.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.
local rpm = values.get(car, "rpm") or 0
modules/values/list
list(target: string | entityRef): { [string]: Value }
Every named value an entity holds, by name.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
for name, v in values.list(car) do print(name, v) end
modules/values/onAnyChange
onAnyChange(callback: (Value?, string, string) -> ()): ValueConnection
Call callback(value, name, entityId) for every change of every named
value on every entity, once per frame in which it changed: what a debug
view or a recorder of a session's values follows.
Parameters
callback(Value?, string, string) -> ()—function(value, name, entityId).
local conn = values.onAnyChange(function(v, name, id) print(id, name, v) end)
modules/values/remove
remove(target: string | entityRef, name: string): boolean
Drop a named value from an entity.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.
values.remove(car, "rpm")
modules/values/set
set(target: string | entityRef, name: string, value: Value?)
Write a named value on an entity: a number, a vector or a boolean;
nil removes it. A name takes the kind of its first value and keeps it:
writing another kind raises (remove the value first to change its kind).
The write is a store, with nothing replicated and nothing copied, and
every reader sees it from the next read: values.get, a material
property bound to the name, an Audio voice following it, a UI prop
values.bind made. Only a value values.declare gives a replicate
rate is ever sent to other peers.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.valueValue?(optional) — A number, a vector or a boolean;nilremoves the value.
values.set(car, "rpm", 3200)
values.set(car, "headlights", true)
values.set(car, "wheelSpin", vector.create(0, 12.5, 0))
modules/values/stats
stats(): { entities: number, values: number, revision: number, replication: ValueReplicationStats }
How many entities hold values, how many values there are, the
store's revision (which advances on every change), and what replication
has carried: a value with no replicate rate adds nothing to it.
print(values.stats().values, values.stats().replication.sentBytes)
modules/values/subscribe
subscribe(
Call callback(value, name, entityId) when a named value of an entity
changes, whoever changed it: a script, an engine system or another peer.
Give name to follow one value, or nil to follow every value of the
entity. The callback runs once for the writes a frame made, on the
engine's next pass over its tasks, with the value as it stands then:
three writes in one frame are one call with the last of them. A value
that went (values.remove, its entity left the world) arrives as nil.
A subscription made by a component ends with the component.
local conn = values.subscribe(car, "gear", function(gear) print("now in gear", gear) end)
conn:Disconnect()
tools/values/describe
values.describe(target: string) -> ValueDescription
One entity's named values as they stand now, sorted by name: each with its type, value (a vector as [x, y, z]), last writer ("script", "engine" or "remote"), the store revision of its last change, its replication rate when it replicates, and whether a declaration states it.
Parameters
targetstring
Returns ValueDescription
"car"
tools/values/list
values.list() -> ValueListing
Every entity holding at least one named value, sorted by id, each with its name and how many values it holds; and the total values and the store's revision, which advances on every change.
Returns ValueListing
tools/values/set
values.set(target: string, name: string, value: any) -> SetResult
Write one named value on an entity: a number, a boolean, or a list of three numbers for a vector; nil removes it. Answers the value the entity holds after the write, a vector as [x, y, z].
Parameters
targetstringnamestringvalueany(optional)
Returns SetResult
"car", "brake", true
typed/builtin//modules/api/engine/values/values/bind
values.bind(target: string | entityRef, name: string, opts: { format: string?, scale: number?, offset: number?, fallback: any? }?) -> ValueBinding
A UI prop that follows a named value, with no script updating the
screen: put it where a widget takes text, value, visible,
checked or enabled, and the widget reads the value every frame.
format is a string.format pattern for text ("%d rpm"; the value
as it reads when absent); scale and offset map a number
(value * scale + offset) before it is shown. A value the entity does
not hold shows fallback (empty text, 0 or false when absent).
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.opts{ format: string?, scale: number?, offset: number?, fallback: any? }(optional) —{ format?, scale?, offset?, fallback? }.
Returns ValueBinding — A binding to place in a widget's props.
ui.registerScreen("dash", { type = "vertical", children = {
{ type = "label", props = { text = values.bind(car, "rpm", { format = "%.0f rpm" }) } },
{ type = "slider", props = { min = 0, max = 1, value = values.bind(car, "throttle") } },
} })
typed/builtin//modules/api/engine/values/values/clear
values.clear(target: string | entityRef) -> number
Drop every named value an entity holds. An entity's values also go when the entity leaves the world.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
Returns number — How many values it held.
values.clear(car)
typed/builtin//modules/api/engine/values/values/declare
values.declare(target: string | entityRef, name: string, declaration: ValueDeclaration?)
State what a named value is: its type ("number", "vector" or
"boolean"), the default it starts at, and whether it replicates. A name
the entity already holds keeps its value. replicate is a rate in Hz (up
to 60): the owner of the entity sends the value to every other peer at
most that often while it changes, and always sends the latest one, and
the other peers read it like any value. A value with no replicate is
never sent anywhere.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.declarationValueDeclaration(optional) —{ type?, default?, replicate? }; givetypeordefaultfor a name the entity does not hold yet.
values.declare(car, "throttle", { type = "number", default = 0, replicate = 10 })
values.declare(car, "brake", { default = false, replicate = 20 })
typed/builtin//modules/api/engine/values/values/describe
values.describe(target: string | entityRef) -> { ValueRow }
Every named value an entity holds, sorted by name, each with its
type, its value, who wrote it last (writer: "script", "engine" or
"remote"), the store revision of its last change, its replicate rate
(absent for a value kept on this engine) and whether a declaration states
it. The same rows /zero/runtime/values/<entityId> and the values
toolbox list.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
Returns { ValueRow } — The rows.
for _, row in values.describe(car) do print(row.name, row.type, row.value, row.writer) end
typed/builtin//modules/api/engine/values/values/entities
values.entities() -> { string }
Every entity holding at least one named value, sorted by id.
Returns { string } — Entity ids.
for _, id in values.entities() do print(id, #values.describe(id)) end
typed/builtin//modules/api/engine/values/values/get
values.get(target: string | entityRef, name: string) -> Value?
Read a named value an entity holds, or nil when it holds none under
that name. Engine systems write values too: a WheelCollider writes its
own state (wheel.slipRatio, wheel.angularVelocity, ...), so a script
reads it here the way it reads a value a script wrote.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.
Returns Value? — The value, or nil.
local rpm = values.get(car, "rpm") or 0
typed/builtin//modules/api/engine/values/values/list
values.list(target: string | entityRef) -> { [string]: Value }
Every named value an entity holds, by name.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.
Returns { [string]: Value } — { [name] = value }.
for name, v in values.list(car) do print(name, v) end
typed/builtin//modules/api/engine/values/values/onAnyChange
values.onAnyChange(callback: (Value?, string, string) -> ()) -> ValueConnection
Call callback(value, name, entityId) for every change of every named
value on every entity, once per frame in which it changed: what a debug
view or a recorder of a session's values follows.
Parameters
callback(Value?, string, string) -> ()—function(value, name, entityId).
Returns ValueConnection — A connection; :Disconnect() ends it.
local conn = values.onAnyChange(function(v, name, id) print(id, name, v) end)
typed/builtin//modules/api/engine/values/values/remove
values.remove(target: string | entityRef, name: string) -> boolean
Drop a named value from an entity.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.
Returns boolean — Whether the entity held it.
values.remove(car, "rpm")
typed/builtin//modules/api/engine/values/values/set
values.set(target: string | entityRef, name: string, value: Value?)
Write a named value on an entity: a number, a vector or a boolean;
nil removes it. A name takes the kind of its first value and keeps it:
writing another kind raises (remove the value first to change its kind).
The write is a store, with nothing replicated and nothing copied, and
every reader sees it from the next read: values.get, a material
property bound to the name, an Audio voice following it, a UI prop
values.bind made. Only a value values.declare gives a replicate
rate is ever sent to other peers.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring— The value's name.valueValue(optional) — A number, a vector or a boolean;nilremoves the value.
values.set(car, "rpm", 3200)
values.set(car, "headlights", true)
values.set(car, "wheelSpin", vector.create(0, 12.5, 0))
typed/builtin//modules/api/engine/values/values/stats
values.stats() -> { entities: number, values: number, revision: number, replication: ValueReplicationStats }
How many entities hold values, how many values there are, the
store's revision (which advances on every change), and what replication
has carried: a value with no replicate rate adds nothing to it.
Returns { entities: number, values: number, revision: number, replication: ValueReplicationStats } — { entities, values, revision, replication }.
print(values.stats().values, values.stats().replication.sentBytes)
typed/builtin//modules/api/engine/values/values/subscribe
values.subscribe(target: string | entityRef, name: string?, callback: (Value?, string, string) -> ()) -> ValueConnection
Call callback(value, name, entityId) when a named value of an entity
changes, whoever changed it: a script, an engine system or another peer.
Give name to follow one value, or nil to follow every value of the
entity. The callback runs once for the writes a frame made, on the
engine's next pass over its tasks, with the value as it stands then:
three writes in one frame are one call with the last of them. A value
that went (values.remove, its entity left the world) arrives as nil.
A subscription made by a component ends with the component.
Parameters
targetstring | entityRef— The entity: a proxy fromentity(...), or its id.namestring(optional) — The value's name, or nil for every value of the entity.callback(Value?, string, string) -> ()—function(value, name, entityId).
Returns ValueConnection — A connection; :Disconnect() ends it.
local conn = values.subscribe(car, "gear", function(gear) print("now in gear", gear) end)
conn:Disconnect()