Skip to content
Back to skills

Multiplayer

ASecurity

Start here for Summer multiplayer: how authority, clients, Worlds and Sessions fit, and what comes next.

  • 77 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 16, 2026
ai-agentsgoshellnodeawstestingapi

Works with

  • claude code
  • cursor
  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 16, 2026

npx -y skills add SummerEngine/summer --skill multiplayer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Multiplayer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Multiplayer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/summerengine-multiplayer/badge)](https://www.skillsdirectory.com/skills/summerengine-multiplayer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: multiplayer
description: "Start here for Summer multiplayer: how authority, clients, Worlds and Sessions fit, and what comes next."
license: MIT
compatibility: [Cursor, Claude Code, Windsurf, Codex]
category: multiplayer-and-networking
user-invocable: true
allowed-tools: Read Grep Glob summer_get_scene_tree summer_get_script_errors summer_project_setting
paths: ["**/*.gd", "**/*.tscn", "project.godot", "summer.build.json", "world.json"]
---

# /multiplayer — how Summer multiplayer works

Read this first, whatever the user asked for: "multiplayer", "co-op", "PvP",
"online", "play with friends", "lobby", "peer-to-peer", "host a game",
"netcode", "sync players". It explains the model in one page and sends you to
the skill that builds the next piece.

## The picture

A Summer multiplayer game is **one project with two entry scenes**:

- the **client** scene, which every player runs: input, camera, visuals, UI;
- the **authority** scene, which runs headless as the match server and owns
  the rules.

```text
   each player's device                   Summer hosting (or Local Play)
  ┌──────────────────────┐  my pose       ┌──────────────────────────────┐
  │ client scene         │ ─────────────► │ authority scene = one World  │
  │ moves its own player │  "collect"     │ checks every pose and request│
  │ draws everyone else  │ ─────────────► │ owns score, doors, items...  │
  │                      │ ◄───────────── │                              │
  └──────────────────────┘  state, events └──────────────────────────────┘
```

- A running match is a **World**. Summer starts one authority for it; the game
  declares what a World is in `world.json` (a **WorldDefinition**).
- A player joins with `Summer.client.join(...)` and gets a verified
  **Session**: their seat in that World, with a verified player identity.
- Players find a World through a **queue** in `summer.build.json`. Hosted,
  Summer's matchmaking fills it; locally, **Local Play** starts the authority
  and N clients on your machine.
- The same code runs locally and hosted. No `if server`, no local-only
  branches, no IP addresses.

There is no player-hosted server, so there is no host migration, and a player
quitting never ends the match for the others.

## How data moves

Both sides load one **network composition** (`network/composition.tres`). It
declares every stream the game uses, and a **Spawner** node attaches it to the
World:

| You want | Use | Who writes it | Skill |
|---|---|---|---|
| My character moves | Owner-written State group, one per player | that player's client; the authority checks each pose | `multiplayer-movement` |
| Everyone sees the score, a door, the round timer | Authority-written State group, World audience | the authority | `multiplayer-state` |
| Only I see my wallet, hand, inventory | Authority-written State group, target-Session audience | the authority | `multiplayer-state` |
| A player wants to buy, open, collect, ready up | Command | client asks, authority accepts or refuses | `multiplayer-state` |
| A one-off effect (sparkle, sound, hit flash) | Event | the authority | `multiplayer-state` |

State is retained, so a late joiner gets the current value. Commands carry
the sender's verified Session. Events are fire-and-forget.

## The rules

1. **Each client moves its own character.** Movement feels instant on every
   connection. The authority accepts or refuses each pose, and a refused pose
   snaps the player back.
2. **The authority owns every other fact.** Clients never change shared
   state; they send a Command and show the result.
3. **Identity comes from the Session**, never from a field a client sent.
4. **Never use the stock high-level multiplayer API in a Summer game:** no
   `@rpc`, `MultiplayerSynchronizer`, `MultiplayerSpawner`,
   `ENetMultiplayerPeer`, `multiplayer.is_server()` or peer-ID branches. Their
   sender ids are transport peers, not verified players. Late joiners miss
   state, and the game cannot use Summer hosting, matchmaking or identity.
5. **Test under a bad network before calling anything done:** Local Play
   with latency, jitter and loss (`multiplayer-testing`).

## Words

| Word | Meaning |
|---|---|
| Game | Your game on Summer; its id is `gameId` in `summer.build.json`. `Summer.initialize()` takes no ID: Summer knows which game is running |
| World | One running match or shared place, simulated by one authority |
| WorldDefinition | `world.json`: which scenes run the client and the authority, lifetime, persistence |
| Queue | How players find a World; declared in `summer.build.json` |
| Session | One player's verified seat in a World |
| Composition | The network contract both sides load: State streams, Command and Event streams |
| State group | One retained value (a pose, a scoreboard); one writer, an audience |
| Command | A request from a client, answered by the authority |
| Event | A one-off message from the authority |
| Local Play | Runs the authority and N clients locally, with optional network emulation |

## Build it in this order

Each skill continues the same small game, so their code fits together:

1. **`multiplayer-project`**: the files, both entry scenes, joining, and a
   first Local Play run.
2. **`multiplayer-movement`**: each player moves their own character; others
   see it smoothly; the authority checks every pose.
3. **`multiplayer-state`**: score, doors, private inventories, Commands and
   Events.
4. **`multiplayer-testing`**: Local Play under latency and loss, bots, and
   what a passing run must show.
5. **`multiplayer-publish`**: export the summer.games bundle and upload it as
   a Build.
6. **`release-readiness`**: before players get a version, prove the server
   starts its authority scene and a real online join works.

## Add Summer services

| Skill | What it adds | Works in Local Play? |
|---|---|---|
| `summer-matchmaking` | Queues, match sizes, teams, the accept prompt, join failures | Yes, without the accept prompt |
| `summer-match-results` | Ending a match: winners, losers, rating changes | Yes |
| `summer-leaderboards` | Ratings and Game-wide leaderboards | Partly; reading boards needs hosting |
| `summer-parties` | Friends queue together as a party | No, hosted only |
| `summer-friends` | The player's Summer friends and direct messages | No, hosted only |
| `summer-player-data` | Progress that follows the player to any World | Yes, stored on disk |
| `summer-world-saves` | Worlds that persist between sessions | Yes, in memory |
| `summer-world-chat` | Text chat inside a World | No, hosted only |
| `summer-store` | Selling items for Sparks, owned items | Items yes; the store is hosted only |
| `summer-analytics` | Game events for your analytics dashboard | No, hosted only |

## What people ask for, and what Summer does

| They ask for | On Summer |
|---|---|
| "One player hosts", peer-to-peer | A headless authority per match, started by Summer or by Local Play |
| Host migration | Not needed: no player is the authority |
| Join by IP, invite code, server browser | Not available. Players join a queue; friends join as a party (`summer-parties`) |
| A lobby | A queue with `minPlayers`/`maxPlayers` and an accept prompt (`summer-matchmaking`) |
| "Sync the player's position" | An owner-written pose group (`multiplayer-movement`) |
| "Tell everyone the door opened" | An authority-written State group (`multiplayer-state`) |
| "The client asks the host to buy something" | A Command validated with the verified Session (`multiplayer-state`) |
| Save progress | Player data for the player, World saves for the place (`summer-player-data`, `summer-world-saves`) |

## Start

Check what exists: `summer.build.json`, `world.json`, `network/`,
`authority/`, `client/`.

- **None of them:** start with `multiplayer-project`.
- **They exist:** pick the skill for the piece you need from the tables above.
- **The game already uses `@rpc` or `MultiplayerSynchronizer`:** tell the user
  it needs moving to Summer's networking. Then follow `multiplayer-project`
  and port one system at a time: movement first, then state.

<!-- shell-commands: generated from the operation catalog by npm run generate:registry; do not edit by hand -->
## From a shell

No Summer MCP tools in this session? Run each one as a command; when `summer --version` is missing or below 4.0, use `npx -y summer-engine@latest` in place of `summer`. Fields are flags in kebab-case (`--scene-path res://main.tscn`) or one `--input '<json>'`, and `summer ops describe <op>` prints the exact input. The `summer-cli` skill has the rest.

| In this skill | Command |
|---|---|
| `summer_get_scene_tree` | `summer engine get-scene-tree` |
| `summer_get_script_errors` | `summer engine get-script-errors` |
| `summer_project_setting` | `summer engine project-setting` |
<!-- /shell-commands -->

Files in this skill

  • SKILL.md9 KB
  • resource.yaml1.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.