Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions openspec/changes/follow-leader-to-lobby/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Design

## Context

`FollowPolicy.shouldTriggerWarp` warps only when the leader connects to a non-lobby server; `FollowPolicy` then
moves local members who are in a lobby (mode `lobby`) or everyone (mode `always`). Velocity's `ServerConnectedEvent`
carries the previous server, so the proxy knows where the leader came from.

## Decisions

### 1. Rule: "were together, or idle in a lobby"

On `party.warp` with target `T` and origin `F`, a local member `M` on server `S` (not the leader, `S ≠ T`) follows if
mode is `always`, or `S = F`, or `S` is a lobby. The rule needs no notion of "game" vs "lobby" for the target, so
lobby → lobby alignment falls out of it, and a member in another game is never pulled out.

### 2. When the proxy asks for a warp

Every `ServerConnectedEvent` of a party leader that has a previous server requests a warp to the new server with
`fromServer` = previous server. The first connection after login (no previous server) requests none. Members moved by
a warp are not leaders, so warps never cascade. `/party warp` sends no origin, so it keeps today's behaviour (members
in a lobby follow).

### 3. API

`WarpRequest` gains `fromServer` (optional, at most 64 characters); the service copies it into the `party.warp`
payload as `from`. Old plugins send no origin and ignore the field in events; a new plugin talking to an old service
gets events without `from` and falls back to the lobby rule. No version negotiation is needed.

Rejected: tracking each member's "last server with the leader" in the service (more state, and the proxy already
sees the move); warping only when the leader returns to a lobby from a game (lobby → lobby alignment would still be
missing).

## Risks / Trade-offs

- A leader hopping between lobby instances drags lobby members along each time; that is the intent (the party stays
together) and costs one server switch per member.
- A member who just left the round on their own to another lobby instance is moved to the leader's lobby; acceptable,
since they are idle in a lobby.
40 changes: 40 additions & 0 deletions openspec/changes/follow-leader-to-lobby/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Proposal

**Ships as:** `feat(party)`: one code pull request `feat(party): bring the party back to the lobby with its leader`.

## Why

The first test on the team proxy showed the follow working one way only. When the leader went from `Lobby-2` to
`Bounce-1`, the member followed within a second. When the leader returned with `/lobby`, the member stayed in the
finished round and, after typing `/lobby` themselves, landed on `Lobby-1` while the leader was on `Lobby-2`. The
party falls apart exactly when players expect it to stay together: after a round, and in the lobby itself, where the
lobby's own server selection knows nothing about parties.

## What Changes

- **One follow rule for every move of the leader:** a member follows the leader to the new server if the member was
on the server the leader just left (they were together), or if the member is in a lobby. A member in another game
stays. This covers game → lobby (the round ends), lobby → game (as today) and lobby → other lobby instance.
- **The leader's lobby moves trigger a warp too** (today only moves to non-lobby servers do).
- **Warps name their origin:** `POST /v1/parties/{id}/warp` takes an optional `fromServer`; the `party.warp` event
carries it as `from`. The 0.2.0 plugin ignores it and keeps its old behaviour.
- Follow mode `always` is unchanged: every member follows every move.

## Capabilities

### New Capabilities
None.

### Modified Capabilities
- `party-follow`: when a warp is requested and who follows.

## Out of Scope

- Party-aware lobby selection in Titan (sending the whole party to one lobby instance at login). The proxy aligns the
party after the leader's first move instead.
- Moving members out of a game they are playing in follow mode `lobby`.

## Impact

- Backend: warp request and event payload (`fromServer` / `from`), OpenAPI.
- Plugin: server-connected listener, `FollowPolicy`, event handler, tests.
40 changes: 40 additions & 0 deletions openspec/changes/follow-leader-to-lobby/specs/party-follow/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Spec Delta

## Purpose
The party follows its leader onto the same server.

## MODIFIED Requirements

### Requirement: Warp on leader move
When the proxy sees a party leader connect from one server to another, the proxy SHALL request a warp of the party to the new server's name and SHALL name the server the leader left as the warp's origin.

#### Scenario: Leader joins a game from the lobby
- **GIVEN** A leads a party with B, both on `Lobby-1`
- **WHEN** A is connected to `Bounce-2`
- **THEN** B is connected to `Bounce-2`

#### Scenario: Leader returns to the lobby
- **GIVEN** A leads a party with B, both on `Bounce-2`
- **WHEN** A is connected to `Lobby-2`
- **THEN** B is connected to `Lobby-2`

#### Scenario: First server after login
- **WHEN** the leader logs in and is connected to `Lobby-1`
- **THEN** no warp is requested

### Requirement: Who follows
When a proxy receives `party.warp`, it SHALL connect each of its local members except the leader who is not already on the target server to that exact server if follow mode is `always`, or if the member is on the warp's origin server, or if the member is on a lobby server.

#### Scenario: Member in another game
- **GIVEN** follow mode `lobby` and member C is on `Tamias-1`
- **WHEN** the leader moves from `Bounce-2` to `Lobby-2`
- **THEN** C stays on `Tamias-1`

#### Scenario: Other lobby instance
- **GIVEN** member B is on `Lobby-1`
- **WHEN** the leader moves from `Bounce-2` to `Lobby-2`
- **THEN** B is connected to `Lobby-2`

#### Scenario: Target full
- **WHEN** a member's connection to the target is refused
- **THEN** the member stays where they are and is told why
24 changes: 24 additions & 0 deletions openspec/changes/follow-leader-to-lobby/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Tasks

## 1. Backend

- [ ] 1.1 `WarpRequest.fromServer` (optional, max 64); `PartyService.warp` puts it into the `party.warp` payload as
`from`; OpenAPI updated.
- [ ] 1.2 Tests: warp with and without origin.

## 2. Plugin

- [ ] 2.1 Server-connected listener: a leader's move with a previous server requests a warp with `fromServer`; no
warp without a previous server.
- [ ] 2.2 `FollowPolicy`: follow if mode `always`, member on the origin, or member on a lobby; skip the leader and
members already on the target.
- [ ] 2.3 Tests with fakes: game → lobby (co-player follows, member in another game stays, other lobby instance
aligns), lobby → game (as before), lobby → lobby, first login, event without `from`.

## 3. Documentation

- [ ] 3.1 README: the follow rule.

## 4. Pull request

- [ ] 4.1 Open the code pull request `feat(party): bring the party back to the lobby with its leader`.
Loading