> ## Documentation Index
> Fetch the complete documentation index at: https://summer-18f03259-codex-native-multiplayer-entry.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Build Your First Summer Game

> Build a multiplayer-native Summer game in GDScript with the Summer SDK, then continue to local testing and review.

## Multiplayer by default

The Summer SDK contract is multiplayer-native. The default example is host-authoritative:
the server runs the rules, clients render synced state, and a
`min_players` of 1 means the same build is also a solo game. You write `SummerGame` hooks
and synced state in GDScript; the Summer SDK defines the creator-facing contract.
The SDK/runtime surfaces on this page are scaffolded, not a deployed hosted gameplay path.
Check [platform capability status](/knowledge-base/source-status#platform-capability-status)
before making production promises.

What you build here:

* extends `SummerGame`,
* server-authoritative gameplay updates (`Summer.is_server()`),
* player-visible state via `set_synced`,
* 1–8 players from the same code path,
* passes local testing and the submission pipeline.

<Note>
  Want an AI agent to run this whole page for you? Point it at [/agent-setup](/agent-setup) — the prompt there contains a complete verified template (project files, local SDK stubs, export preset) and the publish calls.
</Note>

## Step 1: Create `manifest.json`

```json theme={null}
{
  "id": "first-summer-game",
  "name": "First Summer Game",
  "version": "1.0.0",
  "summer_sdk": "1.0",
  "entry_scene": "main.tscn",
  "player_scene": "player.tscn",
  "min_players": 1,
  "max_players": 8
}
```

`min_players: 1, max_players: 8` is the multiplayer-native default — ship it unless your design demands otherwise. Paths are relative to the manifest at the pack root.

## Step 2: Choose Your Player Path

### 3D Action Template (fastest start)

* set `player.tscn` root script to `res://sdk/summer_character_3d.gd`
* use `apply_default_movement(...)` from `SummerGame`.

### Custom Genre Path (2D/card/RTS/puzzle)

* make your own script extending `SummerPlayer`
* sync your own state model (`set_synced("hand_count", ...)`, etc.).

Either way the authority rule is identical: the server writes synced state, clients read it.

## Step 3: Build `main.gd`

```gdscript theme={null}
extends SummerGame

const ROUND_SECONDS := 120.0
const MOVE_SPEED := 7.0
const GRAVITY := 20.0

func get_prediction_params() -> Dictionary:
    return {"move_speed": MOVE_SPEED, "gravity": GRAVITY}

func _game_init() -> void:
    var spawn_root := get_node_or_null("SpawnPoints")
    if spawn_root:
        for child in spawn_root.get_children():
            if child is Node3D:
                spawn_points.append(child.global_position)

func _game_start() -> void:
    Summer.set_time_limit(ROUND_SECONDS)
    Summer.send_announcement("Round started")

func _game_end() -> void:
    Summer.send_announcement("Game over")

func _player_joined(player) -> void:
    if player.has_method("respawn"):
        player.respawn(get_random_spawn_point())
    player.set_synced("score", 0)

func _player_left(_player) -> void:
    pass

func _process(delta: float) -> void:
    super._process(delta)
    if not Summer.is_server():
        return
    for p in get_players():
        if p.has_method("respawn"):
            apply_default_movement(p, delta, MOVE_SPEED, GRAVITY)
```

Give `main.tscn` a `SpawnPoints` node with at least 4 child `Node3D` spawn markers and a `Players` node — the multiplayer defaults assume them.

## Step 4: Add One Multiplayer Rule

Example scoring rule — note it runs only on the server path, and clients see it through `set_synced`:

```gdscript theme={null}
func score_point(player) -> void:
    var current := int(player.get_synced("score") if player.get_synced("score") != null else 0)
    current += 1
    player.set_synced("score", current)
    Summer.send_announcement("%s scored (%d)" % [str(player.get("display_name")), current])
```

## Step 5: Local Test

Start with the canonical one-process Summer Engine smoke checks. If your starter project
includes the optional loopback runner, also use it to exercise a local server/client path:

* the canonical agent prompt validates import, parsing, smoke execution, banned patterns,
  and pack contents with local SDK stubs;
* the optional loopback runner starts a local headless server and connects a client to
  localhost;
* neither path validates production platform services, ticket redemption, or hosted
  matchmaking.

Guide: [Testing Your Game Locally](/api-reference/summer-sdk/testing-your-game-locally). Building outside Summer Engine (agent/CLI workflow)? The same page covers stub-based validation, and the [/agent-setup](/agent-setup) prompt automates it.

## Step 6: Export and Publish

Export a game-only `.pck`, then publish it through the live release API (create game → presigned upload → server-verified finalize → manual review):

* [Exporting and Uploading Your Game](/api-reference/summer-sdk/exporting-and-uploading-your-game)
* [Submission Guide](/api-reference/summer-sdk/submission-guide)

A human reviews every release. Approval assigns `published` catalog status and makes the
release available under the documented authenticated download rules. Browser and
desktop-shell play of uploaded Summer games are not live yet.

## What "Done" Looks Like

* [ ] All lifecycle hooks implemented.
* [ ] Server authority enforced (`Summer.is_server()`).
* [ ] Player-visible state comes from `set_synced`.
* [ ] Works with 1 player and with several (`min_players: 1`).
* [ ] Canonical Summer Engine smoke checks pass.
* [ ] Optional local loopback runner passes when present.
* [ ] Export contains only game files; release enters `pending_review`.

<CardGroup cols={2}>
  <Card title="Previous: Create a Summer game" icon="arrow-left" href="/quickstarts/fresh-project">
    Return to project creation and the GDScript starting point.
  </Card>

  <Card title="Next: Choose Summer SDK capabilities" icon="arrow-right" href="/api-reference/summer-sdk">
    Use the lifecycle hub to select the SDK systems your game needs.
  </Card>
</CardGroup>
