# `tecs.physics.contract`
The batched crossing between Tecs entities and a native rigid-body solver.
One fixed step is one crossing. A frame's systems queue commands through the
`queue*` functions, `step` applies every queued command and advances the
solver once, and the results are read back from buffers the simulation
already holds. Nothing here calls a solver once per body, and nothing a
solver owns ever calls back into Nupp: a Nupp function reached through a
foreign function pointer cannot be entered from a compiled trace or from a
thread the Nupp VM never created, so contacts, poses and assigned handles
leave through buffers instead.
`tecs.physics.rapier` implements this over the `tecs_physics` Rust library.
A test supplies its own implementation, which is what lets the entity-facing
half of `tecs.physics` be exercised with no native library present.
Every length here is in solver meters and every angle is in radians.
`tecs.physics` owns the pixel conversion and does not push it across this
boundary.
A handle is a one-based `index1` plus a `generation`. Zero `index1` names
nothing, which is what a snapshot load leaves behind and what a failed
creation reports.
## Types
### `BodyCreate` _record_
```nupp
record BodyCreate
entity: integer
collider: ColliderDef
kind: integer
fixedRotation: boolean
isBullet: boolean
sleepEnabled: boolean
gravityScale: number
linearDamping: number
angularDamping: number
x: number
y: number
angle: number
vx: number
vy: number
omega: number
end
```
One body creation, together with the primary collider it always carries.
#### Fields
##### `entity`
```nupp
entity: integer
```
Caller-writable. Names the entity the body belongs to.
##### `collider`
```nupp
collider: ColliderDef
```
Caller-writable. Describes the shape created with the body.
##### `kind`
```nupp
kind: integer
```
Caller-writable. Selects one of the body-kind constants.
##### `fixedRotation`
```nupp
fixedRotation: boolean
```
Caller-writable. Locks the body's angle.
##### `isBullet`
```nupp
isBullet: boolean
```
Caller-writable. Sweeps the body's motion for continuous collision.
##### `sleepEnabled`
```nupp
sleepEnabled: boolean
```
Caller-writable. Permits the body to sleep when it comes to rest.
##### `gravityScale`
```nupp
gravityScale: number
```
Caller-writable. Scales gravity for this body alone.
##### `linearDamping`
```nupp
linearDamping: number
```
Caller-writable. Damps linear velocity.
##### `angularDamping`
```nupp
angularDamping: number
```
Caller-writable. Damps angular velocity.
##### `x`
```nupp
x: number
```
Caller-writable. Places the body's origin along x, in meters.
##### `y`
```nupp
y: number
```
Caller-writable. Places the body's origin along y with `x`.
##### `angle`
```nupp
angle: number
```
Caller-writable. Sets the body's initial angle, in radians.
##### `vx`
```nupp
vx: number
```
Caller-writable. Sets initial linear velocity along x, in meters per
second.
##### `vy`
```nupp
vy: number
```
Caller-writable. Sets initial linear velocity along y with `vx`.
##### `omega`
```nupp
omega: number
```
Caller-writable. Sets initial angular velocity, in radians per second.
### `ColliderCreate` _record_
```nupp
record ColliderCreate
def: ColliderDef
bodyIndex1: integer
bodyGeneration: integer
bodyOrder: integer
end
```
One secondary collider added to an existing or same-batch body.
#### Fields
##### `def`
```nupp
def: ColliderDef
```
Caller-writable. Describes the shape to add.
##### `bodyIndex1`
```nupp
bodyIndex1: integer
```
Caller-writable. Names the owning body slot, one-based, when
`bodyOrder` is zero.
##### `bodyGeneration`
```nupp
bodyGeneration: integer
```
Caller-writable. Rejects a stale owning body with `bodyIndex1`.
##### `bodyOrder`
```nupp
bodyOrder: integer
```
Caller-writable. Names the one-based order of the `queueCreateBody`
call in this same batch that owns the shape, or zero when
`bodyIndex1` is authoritative. Queueing a shape onto a body the same
batch creates is what keeps a compound body one crossing.
### `ColliderDef` _record_
```nupp
record ColliderDef
entity: integer
shape: integer
sensor: boolean
halfWidth: number
halfHeight: number
radius: number
length: number
offsetX: number
offsetY: number
density: number
friction: number
restitution: number
categoryBits: integer
maskBits: integer
end
```
One collider's geometry, material and collision filtering.
#### Fields
##### `entity`
```nupp
entity: integer
```
Caller-writable. Names the entity that owns this shape, which is what
a contact event and an entity-addressed replacement both report.
##### `shape`
```nupp
shape: integer
```
Caller-writable. Selects one of the shape constants.
##### `sensor`
```nupp
sensor: boolean
```
Caller-writable. Reports overlap without a collision response.
##### `halfWidth`
```nupp
halfWidth: number
```
Caller-writable. Sets the box half extent along x, in meters.
##### `halfHeight`
```nupp
halfHeight: number
```
Caller-writable. Sets the box half extent along y, in meters.
##### `radius`
```nupp
radius: number
```
Caller-writable. Sets the circle or capsule radius, in meters.
##### `length`
```nupp
length: number
```
Caller-writable. Sets the distance between capsule end centers, in
meters, excluding the caps.
##### `offsetX`
```nupp
offsetX: number
```
Caller-writable. Offsets the shape along x in the body frame, in
meters.
##### `offsetY`
```nupp
offsetY: number
```
Caller-writable. Offsets the shape along y with `offsetX`.
##### `density`
```nupp
density: number
```
Caller-writable. Sets mass per unit area.
##### `friction`
```nupp
friction: number
```
Caller-writable. Sets Coulomb friction.
##### `restitution`
```nupp
restitution: number
```
Caller-writable. Sets the bounce coefficient.
##### `categoryBits`
```nupp
categoryBits: integer
```
Caller-writable. Sets the low 32 collision-group category bits.
##### `maskBits`
```nupp
maskBits: integer
```
Caller-writable. Sets the categories this shape may contact.
### `ColliderUpdate` _record_
```nupp
record ColliderUpdate
def: ColliderDef
index1: integer
generation: integer
bodyIndex1: integer
bodyGeneration: integer
end
```
One in-place collider replacement, addressed by handle or by entity.
#### Fields
##### `def`
```nupp
def: ColliderDef
```
Caller-writable. Describes the replacement shape.
##### `index1`
```nupp
index1: integer
```
Caller-writable. Names the collider slot to replace, one-based, or
zero to find the shape under `bodyIndex1` whose entity is `def.entity`.
##### `generation`
```nupp
generation: integer
```
Caller-writable. Rejects a stale collider slot with `index1`.
##### `bodyIndex1`
```nupp
bodyIndex1: integer
```
Caller-writable. Names the owning body slot, one-based, used when
`index1` is zero.
##### `bodyGeneration`
```nupp
bodyGeneration: integer
```
Caller-writable. Rejects a stale owning body with `bodyIndex1`.
### `EntityHandles` _record_
```nupp
record EntityHandles
bodyIndex1: {integer}
bodyGeneration: {integer}
colliderIndex1: {integer}
colliderGeneration: {integer}
jointIndex1: {integer}
jointGeneration: {integer}
end
```
The body and collider handle owned by each entity a lookup asked about.
Each array holds one entry per requested entity, in the requested order,
and a zero `index1` means the simulation has nothing for that entity.
#### Fields
##### `bodyIndex1`
```nupp
bodyIndex1: {integer}
```
Read-only. Holds each entity's body slot, one-based.
##### `bodyGeneration`
```nupp
bodyGeneration: {integer}
```
Read-only. Holds each entity's body generation.
##### `colliderIndex1`
```nupp
colliderIndex1: {integer}
```
Read-only. Holds each entity's collider slot, one-based.
##### `colliderGeneration`
```nupp
colliderGeneration: {integer}
```
Read-only. Holds each entity's collider generation.
##### `jointIndex1`
```nupp
jointIndex1: {integer}
```
Read-only. Holds each entity's joint slot, one-based.
##### `jointGeneration`
```nupp
jointGeneration: {integer}
```
Read-only. Holds each entity's joint generation.
### `JointCreate` _record_
```nupp
record JointCreate
entity: integer
kind: integer
bodyAIndex1: integer
bodyAGeneration: integer
bodyAOrder: integer
bodyBIndex1: integer
bodyBGeneration: integer
bodyBOrder: integer
anchorAX: number
anchorAY: number
anchorBX: number
anchorBY: number
axisX: number
axisY: number
limitsEnabled: boolean
limitMin: number
limitMax: number
motorEnabled: boolean
motorTargetVelocity: number
motorMaxForce: number
contactsEnabled: boolean
end
```
One joint creation between two existing or same-batch bodies.
#### Fields
##### `entity`
```nupp
entity: integer
```
Caller-writable. Names the entity that owns the joint.
##### `kind`
```nupp
kind: integer
```
Caller-writable. Selects one of the joint-kind constants.
##### `bodyAIndex1`
```nupp
bodyAIndex1: integer
```
Caller-writable. Names the first body slot, one-based, when
`bodyAOrder` is zero.
##### `bodyAGeneration`
```nupp
bodyAGeneration: integer
```
Caller-writable. Rejects a stale first body with `bodyAIndex1`.
##### `bodyAOrder`
```nupp
bodyAOrder: integer
```
Caller-writable. Names the one-based `queueCreateBody` order in this
batch that supplies the first body, or zero.
##### `bodyBIndex1`
```nupp
bodyBIndex1: integer
```
Caller-writable. Names the second body slot, one-based, when
`bodyBOrder` is zero.
##### `bodyBGeneration`
```nupp
bodyBGeneration: integer
```
Caller-writable. Rejects a stale second body with `bodyBIndex1`.
##### `bodyBOrder`
```nupp
bodyBOrder: integer
```
Caller-writable. Names the one-based `queueCreateBody` order in this
batch that supplies the second body, or zero.
##### `anchorAX`
```nupp
anchorAX: number
```
Caller-writable. Anchors the joint in the first body's frame along x,
in meters.
##### `anchorAY`
```nupp
anchorAY: number
```
Caller-writable. Anchors the joint in the first body's frame along y.
##### `anchorBX`
```nupp
anchorBX: number
```
Caller-writable. Anchors the joint in the second body's frame along x.
##### `anchorBY`
```nupp
anchorBY: number
```
Caller-writable. Anchors the joint in the second body's frame along y.
##### `axisX`
```nupp
axisX: number
```
Caller-writable. Sets the prismatic sliding axis along x. The solver
normalizes it, and the other joint kinds ignore it.
##### `axisY`
```nupp
axisY: number
```
Caller-writable. Sets the prismatic sliding axis along y.
##### `limitsEnabled`
```nupp
limitsEnabled: boolean
```
Caller-writable. Enforces `limitMin` and `limitMax`.
##### `limitMin`
```nupp
limitMin: number
```
Caller-writable. Sets the lower limit, in radians for a revolute joint
and meters for a prismatic one.
##### `limitMax`
```nupp
limitMax: number
```
Caller-writable. Sets the upper limit with `limitMin`.
##### `motorEnabled`
```nupp
motorEnabled: boolean
```
Caller-writable. Drives the joint's free degree of freedom.
##### `motorTargetVelocity`
```nupp
motorTargetVelocity: number
```
Caller-writable. Sets the motor's target velocity, in radians or
meters per second.
##### `motorMaxForce`
```nupp
motorMaxForce: number
```
Caller-writable. Bounds the force or torque the motor may apply.
##### `contactsEnabled`
```nupp
contactsEnabled: boolean
```
Caller-writable. Lets the two joined bodies still collide.
### `Options` _type_
```nupp
type Options = {
gravityX: number?,
gravityY: number?,
subStepCount: integer?,
workerCount: integer?
}
```
Options accepted when a simulation is created.
### `Simulation` _record_
```nupp
record Simulation
id: integer
subStepCount: integer
workerCount: integer
queueCreateBody: function(command: BodyCreate): integer
queueCreateCollider: function(command: ColliderCreate): integer
queueCreateJoint: function(command: JointCreate): integer
queueUpdateBody: function(
index1: integer,
generation: integer,
kind: integer,
fixedRotation: boolean,
isBullet: boolean,
sleepEnabled: boolean,
gravityScale: number,
linearDamping: number,
angularDamping: number
): nil
queueUpdateCollider: function(command: ColliderUpdate): integer
queueAction: function(
index1: integer,
generation: integer,
action: integer,
a: number,
b: number,
c: number,
d: number
): nil
queueDestroyBody: function(index1: integer, generation: integer): nil
queueDestroyCollider: function(index1: integer, generation: integer): nil
queueDestroyJoint: function(index1: integer, generation: integer): nil
step: function(dt: number): nil
createdBody: function(order: integer): (integer, integer, integer, integer)
createdCollider: function(order: integer): (integer, integer)
createdJoint: function(order: integer): (integer, integer)
updatedCollider: function(order: integer): (integer, integer)
isLive: function(index1: integer, generation: integer): boolean
isAwake: function(index1: integer, generation: integer): boolean
poseOf: function(index1: integer, generation: integer): (number?, number, number, number)
velocityOf: function(index1: integer, generation: integer): (number, number, number)
eventCount: function(): integer
eventAt: function(index: integer): (integer, integer, boolean, boolean)
raycast: function(
x1: number,
y1: number,
x2: number,
y2: number,
categoryBits: integer,
maskBits: integer
): (integer?, number, number, number, number, number)
resolveEntities: function(entities: {integer}): EntityHandles
save: function(): (string?, string?)
load: function(bytes: string): (boolean, string?)
destroy: function(): nil
end
```
One live simulation, driven entirely through batched commands.
Every field is a closure over one simulation's private state, so an
implementation is a value rather than a subclass and a test may supply
its own without a native library.
#### Methods
##### `queueCreateBody`
```nupp
queueCreateBody: function(command: BodyCreate): integer
```
Queues one body creation and returns its one-based order in this
batch, which `createdBody` and a same-batch `bodyOrder` both use.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `command` | `BodyCreate` | |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | |
##### `queueCreateCollider`
```nupp
queueCreateCollider: function(command: ColliderCreate): integer
```
Queues one secondary collider and returns its one-based order.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `command` | `ColliderCreate` | |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | |
##### `queueCreateJoint`
```nupp
queueCreateJoint: function(command: JointCreate): integer
```
Queues one joint and returns its one-based order.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `command` | `JointCreate` | |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | |
##### `queueUpdateBody`
```nupp
queueUpdateBody: function(
index1: integer,
generation: integer,
kind: integer,
fixedRotation: boolean,
isBullet: boolean,
sleepEnabled: boolean,
gravityScale: number,
linearDamping: number,
angularDamping: number
): nil
```
Queues one body redeclaration, which never moves the body and never
changes its owning entity.
The arguments are positional because a redeclaration runs once per
dirty body row, and a record per row is an allocation in a loop whose
length is the game's business.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | the one-based target body slot |
| `generation` | `integer` | the generation that must match |
| `kind` | `integer` | one of the body-kind constants |
| `fixedRotation` | `boolean` | whether the body's angle is locked |
| `isBullet` | `boolean` | whether the body sweeps its motion |
| `sleepEnabled` | `boolean` | whether the body may sleep at rest |
| `gravityScale` | `number` | the body's own gravity multiplier |
| `linearDamping` | `number` | the linear velocity damping term |
| `angularDamping` | `number` | the angular velocity damping term |
###### Returns
| Type | Description |
| --- | --- |
| `nil` | |
##### `queueUpdateCollider`
```nupp
queueUpdateCollider: function(command: ColliderUpdate): integer
```
Queues one collider replacement and returns its one-based order,
which `updatedCollider` uses to read the replacement's handle.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `command` | `ColliderUpdate` | |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | |
##### `queueAction`
```nupp
queueAction: function(
index1: integer,
generation: integer,
action: integer,
a: number,
b: number,
c: number,
d: number
): nil
```
Queues one mutation of a live body.
Actions apply at the start of the step that follows them, in the order
they were queued, and reads report the state after the last completed
step. A queued impulse is therefore not visible until that step runs.
The arguments are positional because a game applies actions in its own
loops.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | the one-based target body slot |
| `generation` | `integer` | the generation that must match |
| `action` | `integer` | one of the action constants |
| `a` | `number` | the action's first operand |
| `b` | `number` | the action's second operand |
| `c` | `number` | the action's third operand |
| `d` | `number` | the action's fourth operand |
###### Returns
| Type | Description |
| --- | --- |
| `nil` | |
##### `queueDestroyBody`
```nupp
queueDestroyBody: function(index1: integer, generation: integer): nil
```
Queues one body destruction, which also removes its colliders and
joints. A slot the simulation no longer holds is ignored.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | |
| `generation` | `integer` | |
###### Returns
| Type | Description |
| --- | --- |
| `nil` | |
##### `queueDestroyCollider`
```nupp
queueDestroyCollider: function(index1: integer, generation: integer): nil
```
Queues one collider destruction, ignoring a slot already gone.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | |
| `generation` | `integer` | |
###### Returns
| Type | Description |
| --- | --- |
| `nil` | |
##### `queueDestroyJoint`
```nupp
queueDestroyJoint: function(index1: integer, generation: integer): nil
```
Queues one joint destruction, ignoring a slot already gone.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | |
| `generation` | `integer` | |
###### Returns
| Type | Description |
| --- | --- |
| `nil` | |
##### `step`
```nupp
step: function(dt: number): nil
```
Applies every queued command and advances the simulation once.
Commands apply in a fixed order that does not depend on the order
systems discovered them: joint, collider and body destruction, then
body, collider and joint creation, then body redeclaration, collider
replacement, and queued actions. The queues are empty afterwards.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `dt` | `number` | the interval to advance, in seconds |
###### Returns
| Type | Description |
| --- | --- |
| `nil` | |
###### Raises
- when the simulation cannot apply the batch
##### `createdBody`
```nupp
createdBody: function(order: integer): (integer, integer, integer, integer)
```
Returns the body and collider assigned to one queued creation.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `order` | `integer` | the one-based order `queueCreateBody` returned |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | the body slot, one-based and zero when creation failed, the body generation, the primary collider slot, and its generation |
| `integer` | |
| `integer` | |
| `integer` | |
##### `createdCollider`
```nupp
createdCollider: function(order: integer): (integer, integer)
```
Returns the collider assigned to one queued secondary creation.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `order` | `integer` | the one-based order `queueCreateCollider` returned |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | the collider slot, one-based and zero on failure, and its generation |
| `integer` | |
##### `createdJoint`
```nupp
createdJoint: function(order: integer): (integer, integer)
```
Returns the joint assigned to one queued creation.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `order` | `integer` | the one-based order `queueCreateJoint` returned |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | the joint slot, one-based and zero on failure, and its generation |
| `integer` | |
##### `updatedCollider`
```nupp
updatedCollider: function(order: integer): (integer, integer)
```
Returns the collider a queued replacement produced.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `order` | `integer` | the one-based order `queueUpdateCollider` returned |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | the collider slot, one-based and zero on failure, and its generation |
| `integer` | |
##### `isLive`
```nupp
isLive: function(index1: integer, generation: integer): boolean
```
Reports whether the simulation still holds this body.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | |
| `generation` | `integer` | |
###### Returns
| Type | Description |
| --- | --- |
| `boolean` | |
##### `isAwake`
```nupp
isAwake: function(index1: integer, generation: integer): boolean
```
Reports whether the solver is still integrating this body.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | |
| `generation` | `integer` | |
###### Returns
| Type | Description |
| --- | --- |
| `boolean` | |
##### `poseOf`
```nupp
poseOf: function(index1: integer, generation: integer): (number?, number, number, number)
```
Returns a body's pose only when the last step moved it.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | the one-based body slot |
| `generation` | `integer` | the generation that must match |
###### Returns
| Type | Description |
| --- | --- |
| `number?` | nil when the body is gone or did not move, otherwise x in meters, y in meters, the cosine of its angle, and the sine |
| `number` | |
| `number` | |
| `number` | |
##### `velocityOf`
```nupp
velocityOf: function(index1: integer, generation: integer): (number, number, number)
```
Returns a body's velocity after the last completed step.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index1` | `integer` | the one-based body slot |
| `generation` | `integer` | the generation that must match |
###### Returns
| Type | Description |
| --- | --- |
| `number` | linear velocity along x and y in meters per second, and angular velocity in radians per second, all zero when the body is gone |
| `number` | |
| `number` | |
##### `eventCount`
```nupp
eventCount: function(): integer
```
Reports how many contact and sensor transitions the last step queued.
###### Returns
| Type | Description |
| --- | --- |
| `integer` | |
##### `eventAt`
```nupp
eventAt: function(index: integer): (integer, integer, boolean, boolean)
```
Returns one queued transition.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `index` | `integer` | the one-based position within the last step's events |
###### Returns
| Type | Description |
| --- | --- |
| `integer` | the first entity, the second entity, whether the pair began touching rather than stopped, and whether the pair involved a sensor. A sensor transition names the sensor first. |
| `integer` | |
| `boolean` | |
| `boolean` | |
##### `raycast`
```nupp
raycast: function(
x1: number,
y1: number,
x2: number,
y2: number,
categoryBits: integer,
maskBits: integer
): (integer?, number, number, number, number, number)
```
Casts a finite segment and returns its nearest hit.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `x1` | `number` | the segment start along x, in meters |
| `y1` | `number` | the segment start along y, in meters |
| `x2` | `number` | the segment end along x, in meters |
| `y2` | `number` | the segment end along y, in meters |
| `categoryBits` | `integer` | the ray's collision categories |
| `maskBits` | `integer` | the categories the ray may hit |
###### Returns
| Type | Description |
| --- | --- |
| `integer?` | nil on a miss, otherwise the owning entity, the contact point x and y in meters, the outward unit normal x and y, and the fraction along the segment |
| `number` | |
| `number` | |
| `number` | |
| `number` | |
| `number` | |
##### `resolveEntities`
```nupp
resolveEntities: function(entities: {integer}): EntityHandles
```
Answers the handles the simulation holds for a list of entities.
A snapshot load asks about every restored entity at once, so the cost
stays linear in the simulation rather than quadratic.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `entities` | `{integer}` | the entity ids to look up |
###### Returns
| Type | Description |
| --- | --- |
| `EntityHandles` | one caller-owned record of parallel result arrays |
##### `save`
```nupp
save: function(): (string?, string?)
```
Serializes the complete simulation state.
###### Returns
| Type | Description |
| --- | --- |
| `string?` | the bytes, or nil and a reason when the state cannot be saved |
| `string?` | |
##### `load`
```nupp
load: function(bytes: string): (boolean, string?)
```
Replaces the simulation state with previously saved bytes.
Slots and generations survive, so a handle a save recorded still
addresses the same body afterwards.
###### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `bytes` | `string` | the value a previous `save` returned |
###### Returns
| Type | Description |
| --- | --- |
| `boolean` | whether the state was restored, and a reason when it was not |
| `string?` | |
##### `destroy`
```nupp
destroy: function(): nil
```
Releases the simulation and everything it owns.
Calling it twice is harmless. Every other function is undefined
afterwards.
###### Returns
| Type | Description |
| --- | --- |
| `nil` | |
#### Fields
##### `id`
```nupp
id: integer
```
Read-only. Identifies this simulation among the process's live ones,
which is what a stored handle carries so a row left over from another
simulation is rejected rather than resolved against whatever took its
place.
##### `subStepCount`
```nupp
subStepCount: integer
```
Read-only. Reports how many substeps each `step` divides its interval
into.
##### `workerCount`
```nupp
workerCount: integer
```
Read-only. Reports the solver width the process settled on.
## Values
### `ACTION_FORCE` _variable_
```nupp
const ACTION_FORCE: integer
```
Adds a center-of-mass force from `a` and `b`.
### `ACTION_FORCE_AT` _variable_
```nupp
const ACTION_FORCE_AT: integer
```
Adds the force `a`, `b` at the world point `c`, `d`.
### `ACTION_IMPULSE` _variable_
```nupp
const ACTION_IMPULSE: integer
```
Adds a center-of-mass impulse from `a` and `b`.
### `ACTION_IMPULSE_AT` _variable_
```nupp
const ACTION_IMPULSE_AT: integer
```
Adds the impulse `a`, `b` at the world point `c`, `d`.
### `ACTION_SET_ANGULAR_VELOCITY` _variable_
```nupp
const ACTION_SET_ANGULAR_VELOCITY: integer
```
Replaces angular velocity with `a`.
### `ACTION_SET_AWAKE` _variable_
```nupp
const ACTION_SET_AWAKE: integer
```
Wakes the body when `a` is nonzero and sleeps it otherwise.
### `ACTION_SET_BODY_TYPE` _variable_
```nupp
const ACTION_SET_BODY_TYPE: integer
```
Replaces the body kind with `a`, one of the body-kind constants.
### `ACTION_SET_ENABLED` _variable_
```nupp
const ACTION_SET_ENABLED: integer
```
Enables the body when `a` is nonzero and disables it otherwise.
### `ACTION_SET_TRANSFORM` _variable_
```nupp
const ACTION_SET_TRANSFORM: integer
```
Teleports the body to `a`, `b` at angle `c`, leaving velocity alone.
### `ACTION_SET_VELOCITY` _variable_
```nupp
const ACTION_SET_VELOCITY: integer
```
Replaces linear velocity with `a`, `b`.
### `ACTION_TORQUE` _variable_
```nupp
const ACTION_TORQUE: integer
```
Adds the torque `a`.
### `BODY_DYNAMIC` _variable_
```nupp
const BODY_DYNAMIC: integer
```
A body the solver moves.
### `BODY_KINEMATIC` _variable_
```nupp
const BODY_KINEMATIC: integer
```
A body the game moves through velocity, which pushes dynamic bodies.
### `BODY_STATIC` _variable_
```nupp
const BODY_STATIC: integer
```
A body the solver never moves.
### `JOINT_FIXED` _variable_
```nupp
const JOINT_FIXED: integer
```
A joint holding one relative pose between two bodies.
### `JOINT_PRISMATIC` _variable_
```nupp
const JOINT_PRISMATIC: integer
```
A joint sharing one sliding axis, leaving translation along it free.
### `JOINT_REVOLUTE` _variable_
```nupp
const JOINT_REVOLUTE: integer
```
A joint sharing one anchor point, leaving rotation about it free.
### `SHAPE_BOX` _variable_
```nupp
const SHAPE_BOX: integer
```
An axis-aligned box in the body frame.
### `SHAPE_CAPSULE` _variable_
```nupp
const SHAPE_CAPSULE: integer
```
A vertical capsule.
### `SHAPE_CIRCLE` _variable_
```nupp
const SHAPE_CIRCLE: integer
```
A circle.
### `SHAPE_SEGMENT` _variable_
```nupp
const SHAPE_SEGMENT: integer
```
A centered segment from negative to positive half extents.