Table of Contents
Installation
Requirements
Defold 1.12.4 or newer. 1.12.4 is where zlib.inflate learned to read a gzip
wrapper, which is what decodes the compressed frames the server sends above
1KiB. CI runs 1.13.0. The SDK itself is pure Lua and runs on both native and
HTML5 targets.
Install
Add both of these to your game.project dependencies:
https://git.nokopia.com/yuris/spacetimedb-defold/archive/v4.0.2.zip
https://github.com/defold/extension-websocket/archive/refs/tags/4.2.4.zip
Then Project ▸ Fetch Libraries. That is the whole installation, on every
target including HTML5. The archive also carries README.md and
game.project, but include_dirs = stdb is what Defold mounts, so
require("stdb.init") is the only thing it puts on your require path.
Three things worth knowing, each learned by actually building a separate consumer project against the release:
-
Pin a tag, not
main. Defold's own guidance, and it means a library change cannot break your build without you choosing it. -
extension-websocket is not optional and not automatic. Defold does not resolve dependencies transitively, so a project that lists only this SDK compiles fine and then fails at
connectwithextension-websocket missing: add it to game.project dependencies. -
Private repo on Forgejo? Append the token as a query parameter, the same shape Defold documents for GitLab. Basic auth in the URL (
https://user:token@…) is not a reliable substitute. Forgejo's archive endpoint validates the query token, and a bad one gets a plain401, while URL credentials are handled inconsistently.https://git.nokopia.com/yuris/spacetimedb-defold/archive/v4.0.2.zip?token=<access-token>
Use at least 4.2.4 of extension-websocket. Earlier releases dropped the
Sec-WebSocket-Protocol header on HTML5, and SpacetimeDB answers
400 no valid protocol selected without it
(#67, fixed by
#68).
The one HTML5 difference
Headers do not exist on HTML5, so the token goes in the URL. A browser's
WebSocket cannot send an Authorization header, and extension-websocket
drops params.headers silently. The connection then succeeds as a brand new
anonymous identity, so nothing fails loudly and the player's identity is
quietly gone. Verified against 2.8.2, ?token=<jwt> authenticates to the same
identity as the header, so connect switches to the query parameter on HTML5
and keeps the header everywhere else (a token in a URL can land in access
logs). This one is permanent. Emscripten's WebSocket API has no way to set
request headers.
Nothing about it needs your attention. The SDK picks the right route per target.
HTML5 is tested
The full smoke client passes in headless Chromium. It connects, subscribes and
calls a reducer, restarts the server and replays the subscription, drops one
query set while a second still holds the row, calls procedures and a one-off
query, reads an identity-keyed table and an event table, and finishes with a
bulk apply, which is the phase that prints the run's single SMOKE: PASS. The subprotocol the handshake offers
is asserted, not merely printed, since it is the only place the wire is
observable from outside the page. The row id below is a server autoinc, so it
differs from run to run:
[handshake] -> subprotocol=v2.bsatn.spacetimedb
[handshake] <- 101 Switching Protocols
[html5] SMOKE: PHASE2 OK survived restart; row id=… restored
[html5] SMOKE: PHASE4 OK procedure round trip; failure surfaced as an error; per-table API: 1 insert(s), 1 update; one-off query returned … encoded BSATN row(s)
Installed? Quickstart goes from here to a connected game.
spacetimedb-defold
Using the SDK
Working on the SDK