# @tiptap/platform@0.1.0

<!-- Generated by scripts/gen-package-reference.mts from the package source.
     Do not edit: §15.4 — package docs are generated, nobody writes them. -->

**Spec §7.1: `@tiptap/platform`** — moving platforms, and the arithmetic that
makes them agree on every client.

Extracted from `platformer2d/src/platform.rs`. §7.1's entry reads "gravity,
ground detection, coyote time, jump buffering, variable jump height,
one-ways, **moving-platform parenting**" — this is the last of those and the
part that is hardest to get right, so it comes out first. The rest is still
inside `platformer2d/src/step.rs`, tangled with the orchestration, and
separating it is the same cut phase 4 makes anyway.

## Why the motion is a pure function of the tick

A platform's position is **derived, never stored**. That is the decision the
original file was built around and it survives the move unchanged, because
under rollback it is worth more than it was: a client that rewinds forty ticks
does not have to rewind the platforms, it just asks where they were. No state,
no snapshot, nothing on the wire, and nothing to get out of step.

## The shift, and why it is a parameter

Positions are snapped to the owning module's lattice, and the modules do not
agree on it — `racer` uses 10 where the others use 9 (see
[`sim_core::quantise`]). So every entry point here takes the shift rather than
choosing one.

It is worth saying what that parameter is *for*, because it is on its way out.
The lattice exists so positions fit the wire's 16 bits — and §22 took module
state off the wire entirely. Once phase 4 lands, nothing here needs to snap at
all. It stays for now because removing it would change what the four games
compute, and `sim-wasm/tests/golden.rs` is watching.

## Types

```rust
pub struct Platform
```

A kinematic moving platform — spec §3.3's **"the hard part"**.

> A player standing on one must inherit its motion inside *prediction*, which
> means platform motion has to be deterministic and evaluated before player
> integration every tick. Get the order wrong and players jitter or fall
> through.

The motion is a **closed form in the tick number**: a platform ping-pongs
between `from` and `to` on a triangle wave of `period_ticks`, offset by
`phase_ticks`. See [`crate::platform`] for why that is a closed form rather
than an integration, which is the decision the whole module hangs on.

# There is deliberately no looping or teleporting kind

A platform that wraps from its end back to its start moves an entire path
length in one tick, and everything riding it either teleports with it or is
left behind. Both answers are deterministic and both are wrong on screen. A
creator who wants a circuit builds it from two ping-pongs.

```rust
pub struct Frame
```

Every platform's box and per-tick delta, on the stack.

`step` needs both for every platform on every tick, and spec §3.2 requires
`step` not to allocate. [`MAX_PLATFORMS`] is 16, so this is 16 boxes and 16
vectors — 384 bytes of stack, computed once a tick and read by every seat.

The array is full length rather than a slice of the live prefix because a
fixed-size array is a `Copy` value with no length to get wrong; `count` says
how much of it means anything.

## Functions

```rust
pub fn Platform::is_moving(&self) -> bool
```

Whether this platform actually moves.

```rust
pub fn step_of(platform: &Platform, shift: u32) -> Vec2
```

How far a platform moves in one tick, **rounded to a whole number of position
quanta**.

The number the whole file is built on — see the module header. `Vec2::ZERO`
for a platform that does not move, including one whose declared path is
shorter than half a quantum, which rounds to standing still rather than to
creeping in a way no client can represent identically.

```rust
pub fn effective_to(platform: &Platform, shift: u32) -> Vec2
```

The far end of the path a platform **actually** travels.

`from + step × half`, which is the declared `to` rounded to a whole number of
steps. `Platformer2d::validate_config` checks the level against this rather
than against the declared endpoint: a platform validated against a path it
does not take is a platform that can poke through a wall.

```rust
pub fn center(platform: &Platform, tick: u32, shift: u32) -> Vec2
```

Where a platform's centre is at `tick`.

Pure and total. A platform that does not move — zero-length path, a period
under two ticks, or a path too short to cover one quantum per tick — sits at
`from` forever, which is how a creator parks one and is also what a malformed
config degrades to.

```rust
pub fn aabb(platform: &Platform, tick: u32, shift: u32) -> Aabb
```

A platform's box at `tick`.

```rust
pub fn delta(platform: &Platform, tick: u32, shift: u32) -> Vec2
```

How far a platform moved between `tick - 1` and `tick`.

**This is the value a rider is carried by**, and it is a difference of two
lattice-aligned positions, so it is itself an exact multiple of the position
quantum. See the module header for why that is the property the whole
no-jitter claim rests on.

```rust
pub fn velocity(platform: &Platform, tick: u32, shift: u32) -> Vec2
```

A platform's speed at `tick`, in **units per second**.

`delta × 60`, and the point of the function is that this is *exact* — a
consequence of [`step_of`] quantizing the step rather than the position, and
the reason [`crate::step`] can hand a jumping rider a velocity that keeps it
in lockstep with the platform for the whole flight. See the module header.

It is also exactly representable on the **velocity** lattice, which is the
second half of that claim: a whole number of position quanta per tick is a
whole number of velocity quanta per second, so `snap_velocity` is the identity
on this value and nothing is lost storing it in a body.

```rust
pub fn Frame::evaluate(platforms: &[Platform], tick: u32, shift: u32) -> Frame
```

Evaluate every platform for `tick`. **This runs before any player moves**
— see `platformer2d::step`'s header for the ordering argument.

```rust
pub fn max_step(platform: &Platform, shift: u32) -> Fixed
```

The largest distance a platform covers in one tick.

Used by `validate_config`. Not a tunnelling bound — nothing tunnels here (see
`crate::geom`) — but a **playability** bound: a platform that moves further
than a body is wide in one tick teleports its riders past anything between,
and a rider whose carry is blocked by a wall is left behind in a single frame
rather than sliding off.
