predictaddon
A scene run ahead of its server on the page, so a press is drawn on the next frame.
Using it
A page across a network from its server is sent each step's rows a down leg late, and its presses reach the server an up leg late, so a page that only draws the packets draws its own press a whole round trip after the key went down. A page that runs ahead holds a copy of the scene its seat is on, steps it on its own clock, answers its own presses on it and draws it. A press is then drawn on the next frame, at any lag.
The page's own code makes the page with predict in place of the scenemanager's view, and runs the loop it returns:
import { predict } from '#addons/predict/predict.addon.ts'
const page = predict(link(dial(url)), file, import.meta.url, mount)
const loop = async (now: number) => { page.input(); await page.frame(now); requestAnimationFrame(loop) }
requestAnimationFrame(loop)
A page that shares a tab with its truth, where nothing is across a network, has nothing to run ahead and does not use it. Only scenes whose world.predict is set are run ahead (see rewind). Any other scene passes through: every packet goes to the view as it came, every message goes up as it is, and the page steps nothing.
The copy takes every seat's presses on the steps the server took them, so it comes to the same rows as the server. Where a late press of another seat moves something, that jumps and the jump is eased. The page is corrected only where a browser rounds a last bit otherwise than node, and when a press of its own reaches the server so late that the copy no longer keeps the step it took it on. For the copy to match the server to the last bit, every rule, every plugin's server half and every mod it runs calls math in place of Math.sin, exp, pow, ** and the rest, which a browser and node do not compute to the same bit.
Properties
Read from world.predict of the child scene. All five numbers are required; cutoff is described on rewind.
"predict": { "epsilon": 0.01, "cutoff": 12, "halflife": 100, "snap": 2, "below": 0.001 }
.epsilon : number
How far apart a number of the page's and the server's may be and still count as the same, in the units of the rows' numbers. 0 or more. A packet whose numbers all fall within it is a drift: the copy plays on and nothing is loaded. A packet past it is a correction: the page asks the server for the whole truth and runs again from it.
.halflife : number
Milliseconds, of the steps' time, in which the smoothing of a jump halves. Above 0. When the copy goes back for a late press or loads the server's truth over a copy already running, each thing that moved is drawn where it was, and its distance from where it now is halves every halflife.
.snap : number
The furthest, in the units of the rows' numbers, that a jump is smoothed. 0 or more. A number that moved further is drawn where it now is at once. A number that is a whole number on both sides of the jump, such as a sprite's frame, a count or an id, has no place between and is drawn where it now is.
.below : number
A distance above 0 under which a smoothing offset is dropped and the thing is drawn exactly where the copy has it.
Methods
predict( wire, file, base, mount ) : Page
Makes the page. wire is the page's link to its server. file is the manager scene file, which must give the scenemanager prefab a scenes table and a dt above 0, and the engine prefab a dt above 0. base is import.meta.url of the page's module, and mount is the same argument the scenemanager's view takes. It makes the view itself on a link of its own.
The page
input( )
The view's input. Call it before the steps, each frame.
frame( now ) : Promise<void>
Runs this frame's steps of the copy, then the view's frame. now is the time that requestAnimationFrame handed the loop.
close( )
Closes the page and its wire.
client, name
The view's client and name.
How the copy runs
Starting
The first packet of a visit names the scene. Once the scene's files are fetched and its rows' kinds prepared, the page asks for the whole truth, and the server sends it with its next packet. A request no snapshot answers within a second is sent again. The page loads the snapshot, hands each row's kind what it held beside the rows (see Memory on rewind), and runs the copy from the next frame. Until then every packet goes to the view as it came, and a message the client sends waits.
The clock
The copy steps once for every dt of the engine prefab that the page's clock passes, each step handed the manager's scenemanager dt as the server's children are, and at most a quarter of a second of steps in one frame. Every packet carries the server's clock, and the copy runs up to 10% faster or slower than real time until it stands on it. Every page therefore stands one down leg behind the server's clock, whenever it joined. A copy that falls more than cutoff steps behind the newest packet, such as a tab whose frames stopped, asks for the whole truth again and starts over from it.
A message
The client's message is stamped with the step the copy is about to run and answered there at once. It is sent up on every frame until a packet's acknowledgement covers it, so one lost on the way is sent again, and the server takes each message once.
What is drawn
The view is handed the copy's packet after each step it runs, every row the seat may see. The seat's own row answers its press on the next frame, as does every row that press makes or moves, such as a shot it fires or a crate it knocks over. Every other seat's row runs on from its last press, carried by the copy's rules.
Properties of the module
stats : Stats
On the page predict returns. Numbers to read while the copy runs, such as in a test.
| Field | Meaning |
|---|---|
predicting | Whether this visit runs ahead. |
corrections, drifts | How many packets differed from the copy by more than epsilon, and by no more. |
checked | How many packets were held against the copy. |
behind | How many steps the copy stands behind the newest packet. |
n | The copy's step. |
taken | How many journal entries of other seats were put into the copy. |
missed | How many of those were stamped before the oldest step the copy keeps, and were answered on its next step instead. |
back | How many steps the copy went back for them. |
loads | The step of each snapshot the copy loaded, oldest first. |
differed, first | The last and the first packet that differed: its step n and each row that differed, with the copy's data and the packet's. |
drifted | The last packet that drifted, the same, with by, the most any one number of it was apart. |
Used by
- simulatorRuns pages with it against a server.