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
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,22 @@ func (PlayerComponent) Name() string { return "player" }

// Team represents a team within a lobby.
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"`
Name string `json:"name"`
PlayerIDs []string `json:"player_ids"` // References to player IDs (source of truth)
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.
type TeamConfig struct {
TeamID string `json:"team_id"`
MaxPlayers int `json:"max_players"`
}

// Session represents the current session state of a lobby.
type Session struct {
State SessionState `json:"state"`
Expand Down Expand Up @@ -97,16 +107,6 @@ func (l *LobbyComponent) GetTeam(teamID string) *Team {
return nil
}

// GetTeamByName returns a team by its name.
func (l *LobbyComponent) GetTeamByName(name string) *Team {
for i := range l.Teams {
if l.Teams[i].Name == name {
return &l.Teams[i]
}
}
return nil
}

// HasPlayer returns true if the player is in any team.
func (l *LobbyComponent) HasPlayer(playerID string) bool {
for _, team := range l.Teams {
Expand Down Expand Up @@ -428,6 +428,12 @@ type ConfigComponent struct {
// 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"`
}

// Name returns the component name for ECS registration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ func TestLobbyComponent_GetTeam(t *testing.T) {

lobby := &LobbyComponent{
Teams: []Team{
{TeamID: "team1", Name: "Team One"},
{TeamID: "team2", Name: "Team Two"},
{TeamID: "team1"},
{TeamID: "team2"},
},
}

team := lobby.GetTeam("team1")
require.NotNil(t, team)
assert.Equal(t, "Team One", team.Name)
assert.Equal(t, "team1", team.TeamID)

assert.Nil(t, lobby.GetTeam("unknown"))
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/lobby/lobby_test.go → pkg/plugin/lobby/lobby_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (

"github.com/argus-labs/world-engine/pkg/cardinal"
"github.com/argus-labs/world-engine/pkg/cardinal/snapshot"
"github.com/argus-labs/world-engine/pkg/lobby"
"github.com/argus-labs/world-engine/pkg/plugin/lobby"
"github.com/stretchr/testify/require"
)

Expand Down
15 changes: 13 additions & 2 deletions pkg/lobby/plugin.go → pkg/plugin/lobby/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ package lobby

import (
"github.com/argus-labs/world-engine/pkg/cardinal"
"github.com/argus-labs/world-engine/pkg/lobby/component"
"github.com/argus-labs/world-engine/pkg/lobby/system"
"github.com/argus-labs/world-engine/pkg/plugin/lobby/component"
"github.com/argus-labs/world-engine/pkg/plugin/lobby/system"
)

// Re-export types for easier user access.
Expand Down Expand Up @@ -63,6 +63,7 @@ type (
UpdatePlayerPassthroughCommand = system.UpdatePlayerPassthroughCommand
GetPlayerCommand = system.GetPlayerCommand
GetAllPlayersCommand = system.GetAllPlayersCommand
GetLobbyCommand = system.GetLobbyCommand

// Events (Broadcast).
CreatedEvent = system.LobbyCreatedEvent
Expand Down Expand Up @@ -95,6 +96,7 @@ type (
UpdatePlayerPassthroughResult = system.UpdatePlayerPassthroughResult
GetPlayerResult = system.GetPlayerResult
GetAllPlayersResult = system.GetAllPlayersResult
GetLobbyResult = system.GetLobbyResult

// Cross-Shard Commands.
NotifySessionStartCommand = system.NotifySessionStartCommand
Expand Down Expand Up @@ -139,6 +141,14 @@ type Config struct {
// Clients should send heartbeats more frequently than this (e.g., every timeout/3 seconds).
// Default: 30 seconds.
HeartbeatTimeout int64

// LobbyPresets is the server-owned registry of team configurations
// that clients can reference by label in CreateLobbyCommand.Preset.
// The map key is the preset label; the value is the ordered list of
// teams that a lobby created with that preset will contain. Server
// operators are the source of truth for team caps; clients cannot
// supply arbitrary team configurations.
LobbyPresets map[string][]TeamConfig
}

// Plugin implements cardinal.Plugin for the lobby system.
Expand All @@ -160,6 +170,7 @@ func (p *Plugin) Register(world *cardinal.World) {
HeartbeatTimeout: p.config.HeartbeatTimeout,
AssignmentAuthority: p.config.AssignmentAuthority,
MaxAllocationTimeout: p.config.MaxAllocationTimeout,
LobbyPresets: p.config.LobbyPresets,
})

// Store provider
Expand Down
Loading
Loading