Builda Online
Updated 2026-10-23 中文
Contents

Builda Online

Builda Online provides hosted multiplayer for Builda games. Your game keeps its own client presentation and gameplay rules, while the platform handles player identity, matchmaking, room scheduling, and multiplayer transport. Room rules are defined by your TypeScript or Rust Room source code.

Copy for AI

Please integrate Builda Online into the current project: read https://ai.builda.game/online/setup.md and strictly follow the installation and workflow instructions in it.

Choose the Player Experience

First decide how players enter the game, start a match, and what happens when it ends. A game can offer several entry points at once, but each entry point should belong to one clearly defined mode.

What players experience Good for Multiplayer mode
Gather a fixed number of players for one match, then return to the lobby to find new players 1v1, multiplayer battles, co-op levels Single-match matchmaking
Players stay in the same room and play match after match; others can join while waiting CF/CS-style rooms, board game rooms Recurring room
Players enter a world that is already running; newcomers can join at any time MMORPG channels, shadow worlds, long-running servers Persistent room
Players open a room directly and invite friends through the Builda App or share the Room ID Matches with friends, private co-op Private room

Each gameplay mode is identified by a matchKey, which maps to a Room program, player count, teams, and runtime configuration. The same gameplay mode can offer two independent entry points:

The two entry points can be enabled individually, both enabled, or both disabled. Private rooms have no host: the creator and members have equal rights, and the room is still subject to team capacity and room lifecycle limits. Public Pool/RankPool matches already have a fixed participant list, so knowing the Room ID does not let anyone join. The AI will go on to confirm, for each entry point, the player count, when joining is allowed, how disconnects are recovered, and where players go after a match ends.

Ranked scores: when the public mode is RankPool, the platform pairs players by scores the game submits. Each entry passes rankScore (rank_score in Godot, MatchJoinOptions.RankScore in Unity). Scores must be integers from 0 to 9007199254740991. The platform only validates the range, not whether a score is genuine; if wins, rewards or rankings depend on it, the game must design its own anti-tampering approach.

Supported Scope

Each project installs only one client SDK, one Room language, and the local Mock for that language.

Component Currently supported
Game client Godot, H5, Cocos Creator 3.8 Web, Unity
Room language TypeScript, Rust
Gameplay data plane WebRTC DataChannel
Room entry Public automatic matchmaking, private room creation and joining by Room ID
Player data and purchase delivery Read and write cross-room player data in the Room; in-app purchase orders with grantBy "room" are delivered by the Room
Builda App multiplayer social features Room chat group, room invitations that launch the game (provided by the Builda App; the game does not need to build them)
Local integration testing TypeScript or Rust source Mock

The client handles input, UI, and presentation; the Room validates player actions, advances authoritative state, broadcasts results, handles disconnects, and settles results. Do not leave outcomes, damage, resources, or rankings that must be tamper-proof to the client alone.

Player Data

Player Data is stored per game + player, persists across rooms, and can only be read and written in the Room. The client has no API for it (privateKV is a separate private save store). TypeScript Rooms use cloudEnqueue / cloudRead* / cloudFlush / cloudLoadSnapshot; Rust Rooms use the corresponding cloud_state_api.

Report semantic issues or failures to the Player Data maintainers; do not treat them as client SDK problems.

Purchase delivery

Each in-app purchase point in payPoints of builda.publish.json declares who delivers it with grantBy:

Room delivery flow:

  1. On receiving an orderId, call doOrder / do_order; the result arrives in the callback on a later tick. Do not block waiting for it.
  2. Only when the result is allowed, use fulfill in the same callback to write that player's data (for example, add coins). Take the item from the payId in the callback result, never from an item ID uploaded by the client; the recipient is always the authenticated player who sent the message.
  3. Do not call cloudEnqueue / cloudFlush inside the payment callback; the platform waits for the fulfill writes to take effect before completing the order.
  4. already_delivered means it was already delivered; do not treat it as a rejection. An incomplete order can be retried with doOrder on the same orderId.

Chat and Invitations Built into the Builda App

You do not need to build your own server or UI for in-room chat and friend invitations. The Builda App already provides them, and the SDK connects your game to them at the right moments.

Room Chat

Room Invitations and Joining

Chat and invitations work exactly the same for public and private rooms. During integration, the AI will decide, based on your gameplay, where to place the chat entry point, how to divide team_id, and how to handle invitations at startup.

From Integration to Launch

  1. Confirm the project. The project should already be integrated with Builda and have a single identifiable client engine.
  2. Hand it to the AI. Click "Copy for AI" in the top-right corner of the page and send the full integration instructions to the AI in your project. The AI will install the Skill, SDK, and Mock that match your project.
  3. Confirm the plan. Confirm, in player terms, the matchmaking entry points, room size, room lifecycle, Bots, and disconnect and settlement rules.
  4. Test locally. Use two different local identities to verify joining, state, messages, disconnects, and leaving.
  5. Deploy the Room. The AI uploads the Room source and activates the online version only when you explicitly ask it to deploy or go live.
  6. Verify for real. Use two real identities to verify matchmaking, entering the Room, and gameplay messages before deciding whether to release the client publicly.

A Room deployment may immediately affect newly created real rooms under the same compatible revision. Client-only updates, compatible Room updates, and incompatible protocol updates each have a different release order. Let the installed Skill decide, and do not use repeated uploads as trial and error.

Local vs. Online

Local Online
Identity Synthetic local identity Real Builda App identity
Room Runs the source in the current language directly Rebuilt and hosted by the platform
Transport Local loopback WebSocket WebRTC DataChannel
Chat and invitations Not available; the SDK returns an unavailable status Provided by the Builda App
Player data and purchase delivery The Mock simulates player data and fake-order delivery Real player data and Builda payments
Can verify Room rules, messages, state, and basic lifecycle Real authentication, matchmaking, WebRTC, chat and invitations, hosted runtime
Does not represent Production capacity, security isolation, TURN, distributed recovery A fast local iteration environment

The TypeScript / Rust local Mocks can simulate player data and doOrder / fulfill for fake orders, so you can run the full delivery loop without going online; they do not stand in for production storage or real payments, so full acceptance must still happen online.

The page address, localhost, or 127.0.0.1 cannot be used to tell whether the game is connected to the local Mock. The Builda App may also load a real game Bundle from a local address on the device; the client only uses the install record and the explicit configuration provided by the Builda local development shell.

Usage Limits

The following are the current hard limits per Room and per deployment, not targets to fill up. Requests that exceed structural or runtime limits may be rejected, and Rooms that far exceed them may be shut down for protection. Exceeding log limits only drops logs and does not block gameplay logic.

Room runtime resource Current limit
Players per Room 50 players
Memory per Room 64 MiB
Single complete gameplay message frame 65535 bytes
Single recovery checkpoint 4 MiB
Commands submitted to the platform per lifecycle callback 256
Output per callback / per Room per second 1 MiB / 4 MiB

Game Data Bandwidth

All online Rooms enforce bandwidth limits at both the user level and the room level at the same time. Upstream means client to Room, downstream means Room to client, and 1 KB = 1024 bytes. The quota covers complete gameplay message frames plus protocol overhead, not just the business payload.

Scope Upstream base rate Downstream base rate
Per user 10 KB/s 30 KB/s
Per Room 10 × effective player count KB/s 30 × effective player count KB/s

The effective player count is min(currently connected unique users + 1, room max players). For example, in a room with a maximum of 5 players, when 1 player is online the room gets a 2-player quota, and when full it gets a 5-player quota; each user is still subject to the per-user quota. Multiple connections from the same user share the per-user quota, and switching online transport or reconnecting does not reset the quota immediately. Broadcasts count toward the quota per receiving connection; targeted sends count only the target connections.

Each scope and each direction must satisfy both conditions: the total over the past 5 seconds must not exceed base rate × 5 seconds, and the total over the past 1 second must not exceed base rate × 2 seconds. For example, a single user's upstream can send a burst of 20 KB when quota is available, but no more than 50 KB in total over any 5 seconds, so it cannot sustain 20 KB per second. Accounting uses 100ms buckets, and window boundaries may be conservatively delayed by up to 100ms. Recovery depends on when past usage expires; waiting one second does not guarantee recovery.

When a limit is exceeded, the affected gameplay messages are rejected and ROOM_BANDWIDTH_LIMIT_EXCEEDED is reported. Exceeding bandwidth does not by itself close the Room; new messages can be processed once the quota recovers, but rejected messages are not resent automatically. The reliable channel also cannot guarantee that over-quota messages are accepted. Critical actions need business-level acknowledgment and bounded, idempotent retries, not immediate repeated resends. Limit-exceeded notifications, join/leave acknowledgments, and migration notifications do not count toward the gameplay quota.

In the table above, 1 MiB / 4 MiB is the runtime budget for output that Room callbacks submit to the platform, not network bandwidth available to players. At runtime, one broadcast counts as a single output, but when actually sent, its bytes are counted per receiving connection and must also satisfy the network limits. A single frame under 65535 bytes does not mean the current bandwidth will allow it to be sent, and splitting into chunks cannot bypass the cumulative limits.

When designing synchronization, estimate worst-case output as "encoded message size × sends per second × actual receiving connections". Prefer compact binary encoding, delta sync, merging and rate limiting, and sending targeted by team or visibility range; include full snapshots and reconnection resends in the budget too.

Source, Configuration, and Logs

Source and configuration Current limit
matchKeys 64 entries
TypeScript single file / source archive 16 MiB
Workspace file count / total unpacked size 2048 files / 64 MiB
Match confirmation timeout 1..60 seconds
Snapshot schema version 1..65535
Room logs Current limit
Single entry body 2048 bytes
Per Room per second 20 entries, 16 KiB of body
Memory buffer / single query 256 KiB / 200 entries
Maximum retention 7 days

Split large state into summaries, deltas, or pages. Do not keep unbounded collections, call platform capabilities once per object, or broadcast the full world state every tick. Business state, retries, and settlement must not depend on logs being written successfully. The local Mock enforces only some message and log limits; it does not simulate online WASM memory, checkpoints, output budgets, online dual-window bandwidth limits, or real capacity, so passing locally does not prove that online capacity requirements are met.

Current Delivery Information

This document was updated on 2026-10-23. The page, Skills, SDKs, and Mocks are accepted and switched together as part of the same CDN snapshot.

Component Version
Multiplayer development Skill 0.36.0
Log diagnostics Skill 0.5.0
Godot / H5 / Cocos / Unity client SDK 0.20.0 / 0.18.0 / 0.11.0 / 0.19.0
TypeScript / Rust Room SDK 0.14.11 / 0.14.11
TypeScript / Rust local Mock 0.6.18 / 0.5.19
Room public contract 0.12.0

Multiplayer deliverables are released with the same version as the Builda SDK. Each project pins a single version in .builda-agent/sdk-version and is not upgraded automatically just because you start a new multiplayer feature. Only after you have the AI run builda sdk upgrade to advance the version does builda-online upgrade update the multiplayer Skill, client SDK, Room SDK, and local Mock together to the same version, rather than replacing individual files.

FAQ

Do I need to learn the entire API myself?

No. First confirm the player experience and rules, then hand the installation entry point to your project's AI. The AI should read only the public materials relevant to your current engine and Room language, and complete the full loop of client, Room, configuration, and local verification.

Can I go live once local tests pass?

No. The local Mock is good for verifying business rules, but it does not simulate real authentication, the matchmaking algorithm, WebRTC/TURN, capacity, or security isolation. Before going live, you still need to create a new Ticket and Room with real identities to verify the current online Artifact.

Can I use both TypeScript and Rust Rooms?

Each project should choose one Room language. If source code already exists, follow what the project already uses; for a new project where this cannot be determined, the author chooses. The client engine and Room language are independent of each other; for example, a Unity client can be paired with a TypeScript Room.

Do I need to build chat and friend invitations myself?

No. The room chat group and room invitations are provided by the Builda App, and the SDK connects to them automatically on entering the room, leaving the room, and at startup. The game only needs to decide where to place the chat entry point and how to divide teams, and handle the invitation once at startup. The local Mock does not simulate either feature, so verify them in the Builda App with real identities.

How do I investigate online Room issues?

The install package includes a separate log diagnostics Skill. When you ask your project's AI to query Room logs, drop statistics, or exit reasons, it uses a read-only diagnostics flow and avoids outputting player private data, credentials, or complete sensitive payloads.