summer-match-results is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. End a Summer match: report each player’s win, loss or draw, show results on clients, then close the World.
When your agent uses it
- A multiplayer Summer game needs a winner, a game-over screen or a match that ends
- Reporting match outcomes, abandons or rating changes from the authority
- Players disconnect, reconnect or leave mid-match and the authority must handle it
- The World should shut down after a match, or a persistent World runs several matches
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
Overview
A match ends when the authority says so. It decides the outcome for every player, then:- Concludes the match:
Summer.authority.match.conclude(outcomes, reason). Summer settles it once and returns a settlement, including each player’s rating change on a rated queue. - Summer delivers each player their own result on the client
(
Summer.client.ratings.match_result), and later their committed rating (rating_committed). The authority never relays results or ratings. - Completes the World:
Summer.authority.world.complete()for a match-scoped World. Clients are disconnected and go back to your menu.
multiplayer-project and
multiplayer-state): the first player to collect WIN_COINS coins wins.
With a team queue (summer-matchmaking), their whole team wins.
Steps
1. Track who is in the match
Inauthority/main.gd, keep every Session the engine admitted, and the
players who left. Add these variables:
_ready(), next to the other World signals (skip this line if
summer-player-data already connected it):
_on_session_joined (summer-player-data
adds one), put the line at its start instead of defining it twice.
At the top of _on_session_left:
sessions after it leaves: it stays on the match roster
until the match is delivered, and it still needs an outcome.
Presence signals on the authority’s SummerNetworkWorld:
Hosted, a seat waits
lifecycle.reconnect_seconds (world.json) before
Summer ends the Session. Under Local Play a quitting player only
disconnects; session_left arrives when the World ends.
2. Decide the outcome and conclude
At the end of_collect, after request.accept(...):
match_doc a "winner": "" entry so clients can show the winner’s name.
The rules conclude enforces:
- One outcome for every outcome-eligible player admitted into the match,
including players who already left (
MATCH_OUTCOME_ABANDON). A missing or extra player fails withinvalid_roster; spectators are skipped. - Keys must be the exact
SummerSessionobjects the engine delivered (session_joined, orrequest.get_session()in a Command). Copies, such as the Sessions inSummer.authority.context.participants, fail withinvalid_roster. - Outcomes are
MATCH_OUTCOME_WIN,MATCH_OUTCOME_LOSS,MATCH_OUTCOME_DRAWandMATCH_OUTCOME_ABANDON. On a team queue give every member of a team the same outcome; Summer scores the sides it formed. - It settles once. Retrying with identical arguments replays the same
settlement (
concluding.replayedis true); different arguments are refused. A rejected conclusion (invalid_request) commits nothing, so you may conclude again with corrected arguments. rating_deltas, the third argument, is only forauthority_v1queues (summer-leaderboards).
3. Show the result on each client
Inclient/main.gd’s _ready(), connect the result signals right after
Summer.initialize succeeds and before joining (Summer.client is null
until then), and handle the end of the World:
show_status and the Hud/Status label come from summer-matchmaking.
match_resultarrives when the authority concludes. Itsrating_stateisRATING_STATE_PENDINGon a rated queue, orRATING_STATE_NONE.rating_committedfollows when Summer committed the rating, withresult.rating.before,afteranddelta. Hosted only.Summer.client.ratings.last_resultandresultskeep recent results, so a results screen opened later can read them.- Drive the results screen from
match_result, not from a disconnect. Give it a “Back to menu” button that awaitsSummer.client.leave(), then offers “Play again” (find_matchagain). - Hosted, completing the World ends every Session and Summer stops the server,
so clients get
server_disconnected. Under Local Play the World completes but clients stay connected until they leave or Local Play stops.
4. Close the World
- Match-scoped World (
"lifetime": "match_scoped", the project skill’s default): conclude, thenSummer.authority.world.complete(reason). This permanently ends the World; Summer stops the server. Completing before a successful conclusion fails withsettlement_required. - Persistent or multi-match World: conclude, then
Summer.authority.match.complete_delivery(). Match-bound Sessions end, World-bound Sessions stay, and the World keeps serving. Never callworld.complete()on a World that should keep running. draining(deadline_unix)on the World means Summer is shutting the server down (maintenance). Conclude or save before the deadline (summer-world-saves).
5. Test it with Local Play
deterministic-v1);
every client receives match_result with its own outcome and rating_state
RATING_STATE_PENDING on a rated queue; about 3 seconds later the authority
logs session_left with reason match_complete for each player and
world.complete() succeeds. rating_committed does not fire locally, and
clients stay connected until they leave.
Checklist
- There is exactly one place that ends the match, guarded so it runs once.
- Outcomes cover every outcome-eligible participant, including those who left (
MATCH_OUTCOME_ABANDON). - Team queues give a whole team the same outcome.
- A retryable conclusion failure is retried with identical arguments.
- Clients show
match_result, andrating_committedwhen it arrives. - Match-scoped Worlds call
world.complete()after concluding; persistent Worlds callmatch.complete_delivery(). - Local Play shows the result on every client, and “Back to menu” leaves cleanly.
Common mistakes
See also
summer-matchmaking— queues and teams that the outcome refers tosummer-leaderboards— ratings andauthority_v1rating movessummer-world-saves— persistent Worlds that outlive a matchmultiplayer-testing— running bots through a whole match
From a shell
No Summer MCP tools in this session? Run each one as a command; whensummer --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.
Related skills
multiplayer: Start here for Summer multiplayer: how authority, clients, Worlds and Sessions fit, and what comes next.multiplayer-state: Authority-owned state in Summer multiplayer: shared and private State groups, Commands, Events.summer-matchmaking: Get players into matches with Summer matchmaking: queues, teams, accept prompts, join progress and failures.summer-leaderboards: Leaderboards in a Summer game: queue ratings from matches, and Game rankings your authority scores.summer-world-saves: Keep a persistent Summer World between restarts: checkpoint saves, restore before join, the final save.multiplayer-testing: Test a Summer multiplayer game with Local Play: several players, bad network, bots, a passing run.summer-analytics: Send game events to Summer analytics from the authority or client: fire-and-forget, never blocking gameplay.
Source:
library/skills/summer-match-results/SKILL.md, rendered from summer-engine@4.3.0 on npm.
