reskate.world.physics lets a plugin make rigid bodies of its own in the local physics world: a ball, a cart, a crate, a vehicle. Each body is a compound of capsules. The plugin reads where the body is, asks for a force, torque or impulse on the next physics step, and reads what happened. What a body is for, and how it is steered, is up to your plugin.
Every function needs the world.physics permission. probe_batch needs world.raycast as well, and three of its options need world.physics.observe. create’s reuse option needs world.physics.reuse. Calling a function without its permission raises an error.
How a body moves
The physics world steps 60 times a second. Eachread gives a sample of the body at one step, with an epoch: an opaque token for that step of that body. You compute a command from the sample and submit it with the epoch. The command is applied on the very next step and on no other: if that step is missed, or 100 ms pass, it expires.
Every command gets a receipt. The receipt says whether the command was applied, and later carries the first sample taken after it (its successor), so your plugin reads what actually happened. Acknowledge each receipt once you are done with it. A body keeps at most four receipts; while all four wait, submit is refused.
read, and still takes its place among the eight.
Preparing
reskate.world.physics.prepare()
Asks for the game’s one-time setup for bodies, so that create is not the call that finds it pending. Call it, and after true, make your first create.
Takes no arguments; passing any raises an error.
True when the setup is done and the local skater’s physics step can be read now. It reserves nothing: the room for bodies can still run out before
create.create answers a pending setup and a skater, world or step it cannot read now alike, with body_preallocation_unavailable. prepare tells them apart.
Needs the
world.physics permission. Once a tick.Making and reading
reskate.world.physics.create(definition, options)
Makes a body, or with reuse brings back one of your own parked bodies.
nil with a body. Otherwise why not. These are fixed codes, to compare against (see refusal codes):The other refusals are sentences meant for your log, such as
"owned bodies require the current local client phase outside multiplayer", "the eight retained body slots are exhausted; native destruction is unproven" or "a previous partial allocation in this world prohibits another native allocation".Only when you pass
options, with a body: "reused" (a parked body came back) or "allocated" (a new body).Only for a
reuse that made a new body: why none of your parked bodies came back. See bringing a parked body back.options, or with nil in their place, create returns the body alone, or nil and why. With options it returns body, nil, origin, and miss after them for a reuse that made a new body.
The capsules collide with the world only. A plugin cannot choose what a body collides with. A failed create is not tried again for you.
Needs the
world.physics permission, and world.physics.reuse for reuse = true. A definition out of these ranges raises invalid native body: mass 1..1000, inertia .01..10000, unit XYZW rotation, capsule endpoints +/-10m and radius .01..2m.reskate.world.physics.read(body)
The body at its latest physics step.
nil and why when the body cannot be read now, such as "body owner or generation unavailable" for a released body, or "body snapshot or native epoch changed; no sample published".Needs the
world.physics permission.Pushing
reskate.world.physics.submit(body, epoch, command)
Asks for a force, torque or impulse on the body for the step after epoch.
nil when it waits. Otherwise why not. These two are fixed codes, to compare against (see refusal codes):The other refusals are sentences meant for your log:
"body owner or generation changed", "body commands require the current local client phase" or "body command invalid, repeated, stopped, pending or receipt ring full".receipt, acknowledge and release still answer for it.
Needs the
world.physics permission. A command out of these bounds, or an epoch of another body, raises an error.reskate.world.physics.receipt(body, sequence)
What became of a command.
"applied" says the game took the force and torque. It does not say how the body moved: read the successor.
Needs the
world.physics permission. A sequence that is not a decimal string raises an error.reskate.world.physics.acknowledge(body, sequence)
Frees the oldest receipt, so another command can be submitted.
"receipt unavailable, already acknowledged or awaiting a measured successor": receipts are freed oldest first, a queued one cannot be, and an applied one waits for its successor.Needs the
world.physics permission.reskate.world.physics.release(body)
Stops the body: its waiting command is cancelled, its force and velocity are cleared, it stops colliding, and it is parked. It still takes one of the eight places. With world.physics.reuse, your plugin can bring it back later.
The receipts of a released body can still be read and acknowledged.
Needs the
world.physics permission.Bringing a parked body back
A released body keeps one of the eight places until the game restarts, so a plugin that makes and releases the same body again and again, such as a bike made on each mount and released on each return, would run out.create(definition, {reuse = true}) brings back one of its own parked bodies in place of a new one, at the definition’s position and rotation.
reuse looks only among the bodies this copy of your plugin parked itself: never another plugin’s, and not those from before your plugin reloaded. A body can come back when:
- your plugin released it with
release, in the same world it was made or brought back in; - it never failed and was never quarantined;
- its capsules, mass and inertia are exactly those of the new definition, to the last bit. Its position and rotation may differ: it comes back at the new ones.
release left it. Then it places the body, lets it collide with the world again and sets it moving, as at the end of a creation. It comes back with a new handle: the old handle, its epochs and its receipts are gone.
When no body can come back, create makes a new one, as without reuse, and its fourth result, miss, says why, from your own bodies only:
Two refusals come only from
reuse:
create without reuse never brings a body back, so it is how a plugin asks for a new one.
Needs
world.physics.reuse as well as world.physics; a manifest with the first and not the second fails to load. A plugin may ask to reuse once a tick. A second request that tick, after a refused one too, returns nil, "asked to reuse a native body more than once in one tick" without reaching the game.Refusal codes
Five refusals are fixed codes rather than sentences, so a plugin can comparewhy with them and decide whether to try again. Every other refusal on this page is a sentence meant for your log, whose words can change. probe_batch has its own reasons, in batch.reason.
Ray batches
reskate.world.physics.probe_batch(body, epoch, rays, options)
Casts up to 32 rays at the moment of one sample of a body: what is under a wheel, what a bumper is about to meet. A batch is all or nothing. When anything about the body or the world changed between the first ray and the last, every ray is discarded and the batch is "unavailable".
1 to 32 rays, each exactly
{from = vector, to = vector}, in a list with no gaps. Each end within 100 km; each ray at least 10 micrometres and at most 1000 m long.require_contact, a hit’s normal and surface velocity are left out. A hit never names the body, object or face it met.
Needs the
world.physics and world.raycast permissions, and world.physics.observe for query_preset = "all", include_shape_categories and include_hit_owner. Each ray is one of the plugin’s 64 raycasts a tick, shared with reskate.world.raycast, pick, probe and reskate.session.raycast; past them the call raises an error. Batch rays and reskate.world.probe also share 64 casts in the game a tick, each ray using at most two; when they run out the batch is "unavailable" with budget_exhausted.