Documentation
¶
Index ¶
- type ConfigComponent
- type LobbyComponent
- func (l *LobbyComponent) AddPlayerToTeam(playerID, teamID string) bool
- func (l *LobbyComponent) AddTeam(team Team)
- func (c LobbyComponent) FromProto(p *component.LobbyComponent) LobbyComponent
- func (l *LobbyComponent) GetAllPlayerIDs() []string
- func (l *LobbyComponent) GetPlayerTeam(playerID string) *Team
- func (l *LobbyComponent) GetTeam(teamID string) *Team
- func (l *LobbyComponent) HasPlayer(playerID string) bool
- func (l *LobbyComponent) IsLeader(playerID string) bool
- func (c LobbyComponent) MarshalWire() ([]byte, error)
- func (l *LobbyComponent) MovePlayerToTeam(playerID, newTeamID string) bool
- func (LobbyComponent) Name() string
- func (l *LobbyComponent) PlayerCount() int
- func (l *LobbyComponent) RemovePlayer(playerID string)
- func (l *LobbyComponent) RemovePlayerFromTeam(playerID, teamID string) bool
- func (c LobbyComponent) ToProto() *component.LobbyComponent
- func (c LobbyComponent) UnmarshalWire(data []byte) (any, error)
- type LobbyIndexComponent
- func (idx *LobbyIndexComponent) AddLobby(lobbyID string, entityID uint32, inviteCode string)
- func (idx *LobbyIndexComponent) AddPlayerToLobby(playerID, lobbyID, teamID string, entityID uint32, deadline int64)
- func (c LobbyIndexComponent) FromProto(p *component.LobbyIndexComponent) LobbyIndexComponent
- func (idx *LobbyIndexComponent) GetEntityID(lobbyID string) (uint32, bool)
- func (idx *LobbyIndexComponent) GetLobbyByInviteCode(inviteCode string) (string, bool)
- func (idx *LobbyIndexComponent) GetLobbyPlayerCount(lobbyID string) int
- func (idx *LobbyIndexComponent) GetPlayerDeadline(playerID string) (int64, bool)
- func (idx *LobbyIndexComponent) GetPlayerEntityID(playerID string) (uint32, bool)
- func (idx *LobbyIndexComponent) GetPlayerLobby(playerID string) (string, bool)
- func (idx *LobbyIndexComponent) GetPlayerTeam(playerID string) (string, bool)
- func (idx *LobbyIndexComponent) HasPlayer(playerID string) bool
- func (idx *LobbyIndexComponent) Init()
- func (c LobbyIndexComponent) MarshalWire() ([]byte, error)
- func (LobbyIndexComponent) Name() string
- func (idx *LobbyIndexComponent) RemoveLobby(lobbyID string, inviteCode string)
- func (idx *LobbyIndexComponent) RemovePlayerFromLobby(playerID string)
- func (c LobbyIndexComponent) ToProto() *component.LobbyIndexComponent
- func (c LobbyIndexComponent) UnmarshalWire(data []byte) (any, error)
- func (idx *LobbyIndexComponent) UpdateInviteCode(lobbyID, oldCode, newCode string)
- func (idx *LobbyIndexComponent) UpdatePlayerDeadline(playerID string, deadline int64)
- func (idx *LobbyIndexComponent) UpdatePlayerTeam(playerID, teamID string)
- type PlayerComponent
- type Session
- type SessionState
- type ShardAddress
- type Team
- type TeamConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ConfigComponent ¶
type ConfigComponent struct {
// LobbyWorld is this lobby shard's address (for game shard to send NotifySessionEndCommand back).
LobbyWorld ShardAddress `json:"lobby_world"`
// HeartbeatTimeout is how long (in seconds) before a player is removed for not sending heartbeats.
// Clients should send heartbeats more frequently than this (e.g., every timeout/3 seconds).
// Default: 30 seconds.
HeartbeatTimeout int64 `json:"heartbeat_timeout"`
// AssignmentAuthority is an accident-prevention filter, NOT an
// authentication boundary. The plugin compares it against cmd.Persona
// and drops mismatches. This prevents an unrelated system that
// happens to send AssignShardCommand from accidentally completing the
// wrong lobby's session start. It does NOT defend against a client
// that forges Persona, because cmd.Persona is not signature-verified
// at this layer. Real authentication must live above the plugin
// (NATS ACLs, gateway auth, signed commands). Empty = no filter.
AssignmentAuthority string `json:"assignment_authority,omitempty"`
// MaxAllocationTimeout bounds how long (in seconds) a lobby may remain
// in SessionStateAwaitingAllocation before the lobby shard fails the
// start itself and returns to Idle. Values <= 0 disable timeout
// enforcement entirely.
MaxAllocationTimeout int64 `json:"max_allocation_timeout,omitempty"`
// LobbyPresets is the server-owned registry of team configurations
// that clients can reference by label in CreateLobbyCommand.Preset.
// Server is the source of truth for team caps; clients cannot supply
// arbitrary TeamConfig values.
LobbyPresets map[string][]TeamConfig `json:"lobby_presets,omitempty"`
}
ConfigComponent stores lobby configuration.
func (ConfigComponent) FromProto ¶ added in v0.15.0
func (c ConfigComponent) FromProto(p *component.ConfigComponent) ConfigComponent
func (ConfigComponent) MarshalWire ¶ added in v0.15.0
func (c ConfigComponent) MarshalWire() ([]byte, error)
func (ConfigComponent) Name ¶
func (ConfigComponent) Name() string
Name returns the component name for ECS registration.
func (ConfigComponent) ToProto ¶ added in v0.15.0
func (c ConfigComponent) ToProto() *component.ConfigComponent
func (ConfigComponent) UnmarshalWire ¶ added in v0.15.0
func (c ConfigComponent) UnmarshalWire(data []byte) (any, error)
type LobbyComponent ¶
type LobbyComponent struct {
// ID is the unique identifier for the lobby.
ID string `json:"id"`
// LeaderID is the player who controls the lobby.
LeaderID string `json:"leader_id"`
// Teams is the list of teams in the lobby.
Teams []Team `json:"teams"`
// InviteCode is the code for others to join.
InviteCode string `json:"invite_code"`
// GameWorld is the target game shard address.
GameWorld ShardAddress `json:"game_world"`
// Session is the current session state.
Session Session `json:"session"`
// CreatedAt is the Unix timestamp when the lobby was created.
CreatedAt int64 `json:"created_at"`
}
LobbyComponent represents a lobby where players gather. Following rampage-backend pattern: Name() uses value receiver for ecs.Component interface, helper methods use pointer receivers. This may change based on best practices.
func (*LobbyComponent) AddPlayerToTeam ¶
func (l *LobbyComponent) AddPlayerToTeam(playerID, teamID string) bool
AddPlayerToTeam adds a player ID to a specific team. Returns false if player already in lobby, team doesn't exist, or team is full. Note: This only updates the lobby's team membership. PlayerComponent entity must be created separately.
func (*LobbyComponent) AddTeam ¶
func (l *LobbyComponent) AddTeam(team Team)
AddTeam adds a new team to the lobby.
func (LobbyComponent) FromProto ¶ added in v0.15.0
func (c LobbyComponent) FromProto(p *component.LobbyComponent) LobbyComponent
func (*LobbyComponent) GetAllPlayerIDs ¶
func (l *LobbyComponent) GetAllPlayerIDs() []string
GetAllPlayerIDs returns all player IDs across all teams.
func (*LobbyComponent) GetPlayerTeam ¶
func (l *LobbyComponent) GetPlayerTeam(playerID string) *Team
GetPlayerTeam returns the team that contains the player.
func (*LobbyComponent) GetTeam ¶
func (l *LobbyComponent) GetTeam(teamID string) *Team
GetTeam returns a team by ID.
func (*LobbyComponent) HasPlayer ¶
func (l *LobbyComponent) HasPlayer(playerID string) bool
HasPlayer returns true if the player is in any team.
func (*LobbyComponent) IsLeader ¶
func (l *LobbyComponent) IsLeader(playerID string) bool
IsLeader returns true if the player is the lobby leader.
func (LobbyComponent) MarshalWire ¶ added in v0.15.0
func (c LobbyComponent) MarshalWire() ([]byte, error)
func (*LobbyComponent) MovePlayerToTeam ¶
func (l *LobbyComponent) MovePlayerToTeam(playerID, newTeamID string) bool
MovePlayerToTeam moves a player from their current team to a new team. Returns false if player not in lobby, new team doesn't exist, or new team is full. Note: PlayerComponent.TeamID must be updated separately.
func (LobbyComponent) Name ¶
func (LobbyComponent) Name() string
Name returns the component name for ECS registration.
func (*LobbyComponent) PlayerCount ¶
func (l *LobbyComponent) PlayerCount() int
PlayerCount returns the total number of players across all teams.
func (*LobbyComponent) RemovePlayer ¶
func (l *LobbyComponent) RemovePlayer(playerID string)
RemovePlayer removes a player ID from their team. Note: This only updates the lobby's team membership. PlayerComponent entity must be deleted separately.
func (*LobbyComponent) RemovePlayerFromTeam ¶
func (l *LobbyComponent) RemovePlayerFromTeam(playerID, teamID string) bool
RemovePlayerFromTeam removes a player ID from a specific team. O(players in team). Note: This only updates the lobby's team membership. PlayerComponent entity must be deleted separately.
func (LobbyComponent) ToProto ¶ added in v0.15.0
func (c LobbyComponent) ToProto() *component.LobbyComponent
func (LobbyComponent) UnmarshalWire ¶ added in v0.15.0
func (c LobbyComponent) UnmarshalWire(data []byte) (any, error)
type LobbyIndexComponent ¶
type LobbyIndexComponent struct {
// LobbyIDToEntity maps LobbyID -> EntityID for O(1) lookup
LobbyIDToEntity map[string]uint32 `json:"lobby_id_to_entity"`
// InviteCodeToLobby maps InviteCode -> LobbyID for join lookups
InviteCodeToLobby map[string]string `json:"invite_code_to_lobby"`
// PlayerToLobby maps PlayerID -> LobbyID for "my lobby" lookups
PlayerToLobby map[string]string `json:"player_to_lobby"`
// PlayerToTeam maps PlayerID -> TeamID for O(1) team lookup
PlayerToTeam map[string]string `json:"player_to_team"`
// PlayerToEntity maps PlayerID -> EntityID for O(1) player entity lookup
PlayerToEntity map[string]uint32 `json:"player_to_entity"`
// PlayerDeadline maps PlayerID -> Unix timestamp when player will be kicked if no heartbeat
// This enables O(1) heartbeat updates instead of O(teams × players) lookups
PlayerDeadline map[string]int64 `json:"player_deadline"`
// LobbyPlayerCount maps LobbyID -> player count for O(1) count lookup
LobbyPlayerCount map[string]int `json:"lobby_player_count"`
}
LobbyIndexComponent provides O(1) lookups for lobbies and players. This is a singleton component - only one entity should have it. Following rampage-backend pattern: Name() uses value receiver for ecs.Component interface, helper methods use pointer receivers. This may change based on best practices.
func (*LobbyIndexComponent) AddLobby ¶
func (idx *LobbyIndexComponent) AddLobby(lobbyID string, entityID uint32, inviteCode string)
AddLobby adds a lobby to the index.
func (*LobbyIndexComponent) AddPlayerToLobby ¶
func (idx *LobbyIndexComponent) AddPlayerToLobby(playerID, lobbyID, teamID string, entityID uint32, deadline int64)
AddPlayerToLobby maps a player to a lobby, team, entity ID, and sets their deadline.
func (LobbyIndexComponent) FromProto ¶ added in v0.15.0
func (c LobbyIndexComponent) FromProto(p *component.LobbyIndexComponent) LobbyIndexComponent
func (*LobbyIndexComponent) GetEntityID ¶
func (idx *LobbyIndexComponent) GetEntityID(lobbyID string) (uint32, bool)
GetEntityID returns the entity ID for a lobby.
func (*LobbyIndexComponent) GetLobbyByInviteCode ¶
func (idx *LobbyIndexComponent) GetLobbyByInviteCode(inviteCode string) (string, bool)
GetLobbyByInviteCode returns the lobby ID for an invite code.
func (*LobbyIndexComponent) GetLobbyPlayerCount ¶
func (idx *LobbyIndexComponent) GetLobbyPlayerCount(lobbyID string) int
GetLobbyPlayerCount returns the player count for a lobby.
func (*LobbyIndexComponent) GetPlayerDeadline ¶
func (idx *LobbyIndexComponent) GetPlayerDeadline(playerID string) (int64, bool)
GetPlayerDeadline returns the deadline for a player.
func (*LobbyIndexComponent) GetPlayerEntityID ¶
func (idx *LobbyIndexComponent) GetPlayerEntityID(playerID string) (uint32, bool)
GetPlayerEntityID returns the entity ID for a player.
func (*LobbyIndexComponent) GetPlayerLobby ¶
func (idx *LobbyIndexComponent) GetPlayerLobby(playerID string) (string, bool)
GetPlayerLobby returns the lobby ID for a player.
func (*LobbyIndexComponent) GetPlayerTeam ¶
func (idx *LobbyIndexComponent) GetPlayerTeam(playerID string) (string, bool)
GetPlayerTeam returns the team ID for a player.
func (*LobbyIndexComponent) HasPlayer ¶
func (idx *LobbyIndexComponent) HasPlayer(playerID string) bool
HasPlayer returns true if player exists in the index (O(1)).
func (*LobbyIndexComponent) Init ¶
func (idx *LobbyIndexComponent) Init()
Init initializes the maps if nil.
func (LobbyIndexComponent) MarshalWire ¶ added in v0.15.0
func (c LobbyIndexComponent) MarshalWire() ([]byte, error)
func (LobbyIndexComponent) Name ¶
func (LobbyIndexComponent) Name() string
Name returns the component name for ECS registration.
func (*LobbyIndexComponent) RemoveLobby ¶
func (idx *LobbyIndexComponent) RemoveLobby(lobbyID string, inviteCode string)
RemoveLobby removes a lobby from the index.
func (*LobbyIndexComponent) RemovePlayerFromLobby ¶
func (idx *LobbyIndexComponent) RemovePlayerFromLobby(playerID string)
RemovePlayerFromLobby removes a player's lobby mapping, team mapping, entity mapping, and deadline.
func (LobbyIndexComponent) ToProto ¶ added in v0.15.0
func (c LobbyIndexComponent) ToProto() *component.LobbyIndexComponent
func (LobbyIndexComponent) UnmarshalWire ¶ added in v0.15.0
func (c LobbyIndexComponent) UnmarshalWire(data []byte) (any, error)
func (*LobbyIndexComponent) UpdateInviteCode ¶
func (idx *LobbyIndexComponent) UpdateInviteCode(lobbyID, oldCode, newCode string)
UpdateInviteCode updates the invite code for a lobby.
func (*LobbyIndexComponent) UpdatePlayerDeadline ¶
func (idx *LobbyIndexComponent) UpdatePlayerDeadline(playerID string, deadline int64)
UpdatePlayerDeadline updates the deadline for a player.
func (*LobbyIndexComponent) UpdatePlayerTeam ¶
func (idx *LobbyIndexComponent) UpdatePlayerTeam(playerID, teamID string)
UpdatePlayerTeam updates the team ID for a player.
type PlayerComponent ¶
type PlayerComponent struct {
PlayerID string `json:"player_id"`
LobbyID string `json:"lobby_id"`
TeamID string `json:"team_id"`
IsReady bool `json:"is_ready"`
PassthroughData map[string]any `json:"passthrough_data,omitempty"`
JoinedAt int64 `json:"joined_at"` // Unix timestamp when player joined
}
PlayerComponent represents a player entity in a lobby. Players are created when joining a lobby and deleted when leaving.
func (PlayerComponent) FromProto ¶ added in v0.15.0
func (c PlayerComponent) FromProto(p *component.PlayerComponent) PlayerComponent
func (PlayerComponent) MarshalWire ¶ added in v0.15.0
func (c PlayerComponent) MarshalWire() ([]byte, error)
func (PlayerComponent) Name ¶
func (PlayerComponent) Name() string
Name returns the component name for ECS registration.
func (PlayerComponent) ToProto ¶ added in v0.15.0
func (c PlayerComponent) ToProto() *component.PlayerComponent
func (PlayerComponent) UnmarshalWire ¶ added in v0.15.0
func (c PlayerComponent) UnmarshalWire(data []byte) (any, error)
type Session ¶
type Session struct {
State SessionState `json:"state"`
PassthroughData map[string]any `json:"passthrough_data,omitempty"`
// PendingRequestID holds the StartSessionCommand RequestID while the
// lobby waits in SessionStateAwaitingAllocation for an external shard
// assignment. Empty in other states.
PendingRequestID string `json:"pending_request_id,omitempty"`
// PendingStartedAt records the unix timestamp (seconds) at which the
// lobby entered SessionStateAwaitingAllocation. Used by timeout
// enforcement. Zero in other states.
PendingStartedAt int64 `json:"pending_started_at,omitempty"`
}
Session represents the current session state of a lobby.
type SessionState ¶
type SessionState string
SessionState represents the current state of a lobby session.
const ( SessionStateIdle SessionState = "idle" // Lobby is waiting, not in a session SessionStateAwaitingAllocation SessionState = "awaiting_allocation" // Lobby is awaiting external shard assignment SessionStateInSession SessionState = "in_session" // Lobby is currently in a game session )
type ShardAddress ¶ added in v0.15.0
ShardAddress mirrors cardinal.OtherWorld for wire types (commands, events, components). A wire type can't carry cardinal.OtherWorld directly — it's cross-module to the generator, which would block. The fields are identical, so the two convert with a plain Go struct cast: cardinal.OtherWorld(a) and back.
TODO(cross-module): this mirror duplicates cardinal.OtherWorld. Since the wire is proto, the cleaner long-term fix is to import world-engine's committed other_world.proto instead of mirroring — deferred, the import path (per-module type→proto manifest + buf staging) is high effort. See sdkgen.go.
func (ShardAddress) FromProto ¶ added in v0.15.0
func (c ShardAddress) FromProto(p *component.ShardAddress) ShardAddress
func (ShardAddress) ToProto ¶ added in v0.15.0
func (c ShardAddress) ToProto() *component.ShardAddress
type Team ¶
type Team struct {
// TeamID is the stable identifier used to reference this team in all
// commands and events. Server-assigned at lobby creation from the
// preset registry and immutable afterward.
TeamID string `json:"team_id"`
PlayerIDs []string `json:"player_ids"` // References to player IDs (source of truth)
MaxPlayers int `json:"max_players"`
}
Team represents a team within a lobby.
type TeamConfig ¶
TeamConfig is a creation-time team specification used inside a lobby preset. Server operators declare presets in lobby.Config.LobbyPresets; clients choose a preset by name on CreateLobbyCommand. MaxPlayers <= 0 means unlimited.