component

package
v0.16.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: LGPL-3.0 Imports: 4 Imported by: 0

Documentation

Index

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 (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) ProtoDescriptor added in v0.16.4

func (c ConfigComponent) ProtoDescriptor() protoreflect.MessageDescriptor

func (ConfigComponent) ToProto added in v0.15.0

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 (*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) ProtoDescriptor added in v0.16.4

func (c LobbyComponent) ProtoDescriptor() protoreflect.MessageDescriptor

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 (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 (*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) InviteCodeCount added in v0.16.2

func (idx *LobbyIndexComponent) InviteCodeCount() int

InviteCodeCount returns how many invite codes the index currently knows. Logged on a rejected join to separate "this one code is missing" from "the index is empty", which look identical to the player.

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) ProtoDescriptor added in v0.16.4

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 (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 (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) ProtoDescriptor added in v0.16.4

func (c PlayerComponent) ProtoDescriptor() protoreflect.MessageDescriptor

func (PlayerComponent) ToProto added in v0.15.0

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.

func (Session) FromProto added in v0.15.0

func (c Session) FromProto(p *component.Session) Session

func (Session) ToProto added in v0.15.0

func (c Session) ToProto() *component.Session

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

type ShardAddress struct {
	Region       string
	Organization string
	Project      string
	ShardID      string
}

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 (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.

func (Team) FromProto added in v0.15.0

func (c Team) FromProto(p *component.Team) Team

func (Team) IsFull

func (t Team) IsFull() bool

IsTeamFull returns true if the team is at max capacity.

func (Team) ToProto added in v0.15.0

func (c Team) ToProto() *component.Team

type TeamConfig

type TeamConfig struct {
	TeamID     string `json:"team_id"`
	MaxPlayers int    `json:"max_players"`
}

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL