Start here

Where things go

The frozen engine, the wire, and the one home every new thing has.

The engine, rows and kinds, prefabs and scene files, and the wire between the engine and a game are finished. Everything a game adds goes into one of the homes below and changes none of them.

The engine is frozen

Nothing in engine/ is edited, for a feature, a game or a test. The engine names nothing outside itself: no game, kind, field, plugin or addon. A feature that was fully built as a plugin or an addon and could not work there, because every way left would send a seat data it must not have, goes to Patchwork as an issue on its GitHub repo.

The wire

  • scenemanager is in every game: many truths, a seat on one of them at a time, and the seat moved between them. Its plugin is the one plugin that connects a page to its scene.
  • A transport carries packets and messages between two ends and knows nothing about scenes or seats. loopback joins a page and its server in one process, with a simulated bad network when given one; socket is a WebSocket between two processes. A new way to travel, WebRTC for example, is a new transport addon.
  • Nothing else carries a packet.

Row or local

For anything a game holds, ask whether every seat has to agree on it or only this page feels it.

  • A row holds what every seat must agree on and the server decides: positions, health, ammo, score, who hit whom. The thing a seat plays as is that seat's own player row. Every seat is sent every player row; a field only its own seat may read is listed in security.
  • Local state is what only this page needs: the camera, screen shake, a menu cursor, a HUD flash, the volume or rebound keys. It never goes up the wire and no rule reads it. It lives in the actor or plugin that draws it, or in the store when it must outlive a scene. The feedback for the seat's own press is read off its own player row.
  • What another seat does is read off rows, since only the server knows it happened.

The pages

PageWhat it runs
index.htmlThe truth in this tab over a loopback, stepped by the page's clock, with no prediction and no lag.
client.htmlOne seat on <game>.server.ts over a socket. Every scene a seat plays in sets world.predict, so the page runs it ahead of the server.
dev.htmlThe game's own testbed: any readout, any number of seats, any scene entered and any value overridden in its own copy before the boot.

index.html and client.html are the same in every game except the files they import. A cpu driver, a network panel or a readout goes in dev.html.

Every new thing has one home

Ask in this order. The first yes is the home.

  1. A value (a number, colour, size, rate, list or starting setting). If it changes while the game runs, its starting value is a field of its kind's prefab in the scene file. If it never changes, it is the kind's definition, its entry in a data file the scene names. A scene's own few numbers are fields of its world. A level or other large data is a file of its own in the game's assets/. A plugin's fixed numbers are world.<plugin>. Where a seat starts is a start actor, one actors entry per slot.
  2. A value only the page uses (volume, brightness, a theme, rebound keys): a key of the store.
  3. One game's rule, or how one of its things is drawn: an actor in that game's folder, <kind>.sim.ts for the rule and <kind>.client.ts for the drawing. Something used by one game only, shared by several of its kinds, or a system of that game's (its level, its HUD): a plugin or addon of the game's own, in games/<game>/plugins/<name>/ or games/<game>/addons/<name>/.
  4. Used by a second game, and living in the world or the browser (rows, the step, drawing, input, camera, sound, UI): a top-level plugin in plugins/, moved up from the game that had it.
  5. Used by a second game, and holding a truth (seats, connections, sockets, files, timers, more than one truth, what a packet carries): a top-level addon in addons/.

Who uses a thing decides whether it is top-level, not whether it could be described without naming a game.

What each home may do

HomeMay do
Scene fileHolds data. Every number a game has is in it or in a data file it names.
FilesEvery file a game uses is an entry in its scene's asset catalogue, or named by one, and is read through the loader only.
StoreBelongs to the page. The server never reads it, writes it or is sent it.
ActorReads changing values off its row and fixed ones off its definition and world, and writes no number of its own. Anything it remembers between steps is a field on its row. Its rules run in before, tick, after and its acts. It uses plugins and never imports another actor. A new system is a new kind.
PluginNames no game or game kind (a game's own plugin may name that game's kinds). Has a row only when its server half has changing state. A plugin it is built on is handed to it, never imported. It never imports from games/.
ModHow one plugin gives another what it knows: plugin a writes <a>.<p>.ts, and a scene switches it on with world.<p>.mods.
Inputplayer binds a seat with bind, straight to keys, or control, to named actions a player may rebind.
LedgerA row that only appends events for the page to play or draw once.
AddonTakes a truth, runs where the truth is, and knows no game or kind (a game's own addon may know that game's). It never imports from games/.
PageMounts things. No rule, number, readout, listener or scene name. dev.html is the exception.

Names

  • A file in a game folder is named after a kind, a scene or the game. The browser loads a row's actor by its kind's name, so a file with any other name is never loaded.
  • assets/ holds the game's data files and art, and beside them the scripts they are made from.
  • A kind is never named after its game, a scene or a plugin.
  • A test sits beside the file it tests and is named after it.

When something is missing

Build it in its home: in the game that needs it, set from the scene file and tested. It moves to plugins/ or addons/ when a second game needs it. A plugin does not get a setting only one game would set; that setting is the game's actor.

The work, page by page

PageThe work
Starting a gameA new game, from yarn new-game to the first thing of its own playing.
Designing a kindA thing with rules, and things acting on each other.
Designing a seatThe player row is the thing the seat plays as, never a row it spawns.
Input and seatsHow a player controls the game: seats, starts, presses and ledgers.
Building a controls screenThe screen where a player sees and rebinds the controls.
Building a levelThe place a game is played in.
Bringing in artPictures, sheets, models and files into a game and drawn.
Writing the lookHow a game looks, in 2D or 3D.
Scene flowMore than one scene: titles, menus, levels and game over.
Building a cutscene introAn intro that films the entry scene's own kinds, then lands on the title.
Session flowThe loop around play: a menu, a choice, joining, respawn, results and a fresh round.
Building the HUDWhat is drawn over the game.
SoundSound and music.
Tuning feelMovement, physics, cameras, and the numbers that make them feel right.
3D physicsbox3d, box3dvehicle, walker, hitscan3d, volley3d, flight3d, ragdoll3d, interact and cover3d, and which mods make a thing solid, stood on or hit in each.
Smooth gameplayDrawing between steps, a teleport, and anything that slides, streaks, judders or pops on screen.
Building a pluginA plugin, an addon or a mod, top-level or a game's own.
Proving a gameTests, bots, the simulator, replay, and playing it.
Porting a gameA game that exists elsewhere, brought into Patchwork.
Auditing a gameA game checked against every rule on this page and moved into its homes.
Going multiplayerPlaying with other people over a network.
Persisting playersWho a player is, and what is kept for them.
Shipping a gameGetting a game to people, and keeping its repo alongside Patchwork.