import "github.com/sceredi/co-type/broker/cmd/app"
Package main is the entrypoint of the broker application.
import "github.com/sceredi/co-type/broker/internal/app"
Package app provides utilities for setting up the broker application
App represents the main application structure for the broker, containing everything needed to run the broker.
type App struct {
Server *grpc.Server
// contains filtered or unexported fields
}
func New(_ *config.Config) (*App, error)
New initializes a new instance of App.
func (a *App) Shutdown()
Shutdown gracefully shuts down the application by stopping the gRPC server.
import "github.com/sceredi/co-type/broker/internal/config"
Package config is responsible for setting up the configuration for the broker application.
Config holds the configuration settings for the broker application.
type Config struct{}
func Get() *Config
Get returns the global configuration instance, loading it if it hasn’t been loaded yet.
import "github.com/sceredi/co-type/broker/internal/repository"
Package repository defines the interfaces for the repositories used in the application. It provides an abstraction layer for data access, allowing for different implementations without affecting the business logic.
LobbyID is a type alias for string, representing the unique identifier of a lobby.
type LobbyID string
LobbyRepository defines the interface for managing lobbies in the broker.
type LobbyRepository interface {
// Create registers a new lobby in the repository with the server name managing it. It returns an error if the lobby already exists or if the operation fails.
Create(lobbyID LobbyID, serverName ServerName) error
// Upsert registers or updates a lobby in the repository with the server name managing it. It never returns ErrLobbyAlreadyExists.
Upsert(lobbyID LobbyID, serverName ServerName)
// Get retrieves a lobby by its ID from the repository. It returns the server name managing the lobby or an error if the lobby is not found or if the operation fails.
Get(id LobbyID) (ServerName, error)
// Delete removes a lobby by its ID from the repository. It returns an error if the lobby is not found or if the operation fails.
Delete(id LobbyID) error
}
PendingResumeRepository stores lobbies that are waiting to be resumed on a new server. The first player to call RequestResumeGame claims a server; subsequent callers get the same one.
type PendingResumeRepository interface {
// Set stores or overwrites the assigned server for a pending-resume lobby.
Set(lobbyID LobbyID, serverName ServerName)
// Get returns the assigned server name and true if the lobby is pending resume, or ("", false) otherwise.
Get(lobbyID LobbyID) (ServerName, bool)
// Delete removes the lobby from the pending-resume list (called after the server registers it).
Delete(lobbyID LobbyID)
}
ServerName is a type alias for string, representing the name of a server managing a lobby.
type ServerName string
ServerRepository defines the interface for managing servers in the broker.
type ServerRepository interface {
// Create adds a new server to the repository. It returns the created server or an error if the operation fails.
Create(server *domain.Server) (*domain.Server, error)
// List retrieves all servers from the repository.
List() []*domain.Server
// UpdateLastSeen records the time a server was last seen alive and updates its load.
UpdateLastSeen(name string, load int, t time.Time) error
// Upsert creates the server if it does not exist, or resets its address/port and last-seen time if it does.
Upsert(server *domain.Server) *domain.Server
// Delete removes a server by name. Returns ErrServerNotFound if no such server exists.
Delete(name string) error
// ListStale returns the names of servers whose last heartbeat is older than ttl.
ListStale(ttl time.Duration) []string
}
import "github.com/sceredi/co-type/broker/internal/service"
Package service contains the service layer of the broker service. The service layer is responsible for implementing the business logic of the broker service. It defines the interfaces that the handlers will use to interact with the domain models and repositories.
LobbyService defines the interface for managing lobbies in the broker service.
type LobbyService interface {
// Create registers a new lobby in the broker service. It takes a lobby ID and the server name managing it, and returns an error if the operation fails (e.g., if the lobby already exists).
Create(lobbyID repository.LobbyID, serverName repository.ServerName) error
// Upsert registers or updates a lobby in the broker service. It never returns ErrLobbyAlreadyExists.
Upsert(lobbyID repository.LobbyID, serverName repository.ServerName)
// Get retrieves a lobby by its ID from the broker service. It returns the server managing the lobby or an error if the lobby is not found or if the operation fails.
Get(lobbyID repository.LobbyID) (*domain.Server, error)
// Delete removes a lobby by its ID from the broker service. It returns an error if the lobby is not found or if the operation fails.
Delete(lobbyID repository.LobbyID) error
// RequestResumeGame assigns a server to host the resumed lobby. If a server has already been
// assigned for this lobby (a previous player called first), the same server is returned.
// The assignment is stored as pending until the server calls RegisterLobby.
RequestResumeGame(lobbyID repository.LobbyID) (*domain.Server, error)
// RemoveFromPending removes a lobby from the pending-resume list. Called when the server
// registers the lobby via RegisterLobby.
RemoveFromPending(lobbyID repository.LobbyID)
}
func NewLobbyService(lobbyRepo repository.LobbyRepository, pendingResumeRepo repository.PendingResumeRepository, serverSvc ServerService) LobbyService
NewLobbyService creates a new instance of LobbyService with the provided LobbyRepository and ServerService, and returns it.
ServerService defines the interface for managing servers in the broker service.
type ServerService interface {
// Create creates a new server in the broker service. It takes a CreateServerRequest and returns the created Server or an error if the operation fails.
Create(name, addr string, port int) (*domain.Server, error)
// Upsert registers or updates a server entry. It never returns ErrServerAlreadyExists.
Upsert(name, addr string, port int) *domain.Server
// LowestLoad finds the server with the lowest load. It returns it or an error if there are no available servers.
LowestLoad() (*domain.Server, error)
// LowestLoadExcluding finds the server with the lowest load, skipping the named server.
// Falls back to LowestLoad if the excluded server is the only one registered.
LowestLoadExcluding(excludeName string) (*domain.Server, error)
// GetByName retrieves a server by its name. It returns the server or an error if the server is not found or if the operation fails.
GetByName(name string) (*domain.Server, error)
// Heartbeat updates the last-seen timestamp and load for a registered server.
Heartbeat(name string, load int) error
// EvictStale removes servers that have not sent a heartbeat within ttl and returns the count of evicted servers.
EvictStale(ttl time.Duration) int
}
func NewServerService(serverRepo repository.ServerRepository) ServerService
NewServerService creates a new instance of ServerService with the provided ServerRepository and returns it.
import "github.com/sceredi/co-type/broker/internal/repository/memory"
Package memory provides an in-memory implementation of the repository interfaces defined in the repository package.
func NewLobbyRepository() repository.LobbyRepository
NewLobbyRepository creates a new instance of LobbyRepository and returns it.
func NewPendingResumeRepository() repository.PendingResumeRepository
NewPendingResumeRepository creates a new in-memory PendingResumeRepository.
func NewServerRepository() repository.ServerRepository
NewServerRepository creates a new instance of ServerRepository.
import "github.com/sceredi/co-type/broker/internal/api/grpc/handler"
Package handler provides the implementation for the gRPC handlers that manage incoming requests.
ControlHandler implements the ControlServiceServer interface and handles incoming gRPC requests for server management.
type ControlHandler struct {
control.UnimplementedControlServiceServer
// contains filtered or unexported fields
}
func NewControlHandler(serverSvc service.ServerService, lobbySvc service.LobbyService) *ControlHandler
NewControlHandler creates a new instance of ControlHandler with the provided ServerService.
func (h *ControlHandler) Heartbeat(_ context.Context, req *control.HeartbeatRequest) (*control.HeartbeatResponse, error)
Heartbeat handles incoming heartbeat requests from game servers, updating their last-seen timestamp and load.
func (h *ControlHandler) RegisterLobby(_ context.Context, req *control.RegisterLobbyRequest) (*control.RegisterLobbyResponse, error)
RegisterLobby handles incoming gRPC requests to register a new lobby. It validates the request and upserts the lobby entry — this is idempotent and also handles the resume-game path where a lobby was previously hosted by a crashed server. If the lobby was pending resume, it is removed from the pending list.
func (h *ControlHandler) RegisterServer(_ context.Context, req *control.RegisterServerRequest) (*control.RegisterServerResponse, error)
RegisterServer handles incoming gRPC requests to register a new server. It is idempotent: if the server is already known (e.g. after a broker restart) its address is updated and all supplied lobby IDs are re-registered.
func (h *ControlHandler) UnregisterLobby(_ context.Context, req *control.UnregisterLobbyRequest) (*control.UnregisterLobbyResponse, error)
UnregisterLobby handles incoming gRPC requests to unregister a lobby. It validates the request and attempts to delete the lobby entry using the LobbyService.
DiscoveryHandler implements the gRPC server for the DicoveryService.
type DiscoveryHandler struct {
discovery.UnimplementedDiscoveryServiceServer
// contains filtered or unexported fields
}
func NewDiscoveryHandler(serverSvc service.ServerService, lobbySvc service.LobbyService) *DiscoveryHandler
NewDiscoveryHandler creates a new instance of DiscoveryHandler with the provided ServerService.
func (h *DiscoveryHandler) AvailableServer(_ context.Context, _ *discovery.AvailableServerRequest) (*discovery.AvailableServerResponse, error)
AvailableServer handles incoming gRPC requests to find the server with the lowest load. It returns the server information or an error if there are no available servers.
func (h *DiscoveryHandler) RequestResumeGame(_ context.Context, req *discovery.RequestResumeGameRequest) (*discovery.RequestResumeGameResponse, error)
RequestResumeGame handles incoming gRPC requests to resume a crashed game. It assigns (or reuses) a server for the lobby and returns its address.
func (h *DiscoveryHandler) ServerHostingLobby(_ context.Context, req *discovery.ServerHostingLobbyRequest) (*discovery.ServerHostingLobbyResponse, error)
ServerHostingLobby handles incoming gRPC requests to find the server hosting a specific lobby.
import "github.com/sceredi/co-type/client/cmd/app"
Package main is the entry point of the application.
import "github.com/sceredi/co-type/client/internal/config"
Package config is responsible for setting up the client.
func CreateDiscoveryService(conn *grpc.ClientConn) service.DiscoveryService
CreateDiscoveryService creates a new DiscoveryService using the provided gRPC connection.
func CreateLobbyService() service.LobbyService
CreateLobbyService creates a new LobbyService using a new LobbyGateway.
import "github.com/sceredi/co-type/client/internal/service"
Package service contains the service layer of the client.
ErrLobbyGatewayNotSet is returned when the LobbyService is used without setting a gateway first.
var ErrLobbyGatewayNotSet = errors.New("lobby gateway not set")
DiscoveryService defines the interface for managing server discovery.
type DiscoveryService interface {
GetAvailableServer() (*domain.Server, error)
GetHostByLobby(lobbyCode string) (*domain.Server, error)
// RequestResumeGame asks the broker to assign a server for resuming the given crashed lobby.
RequestResumeGame(lobbyID string) (*domain.Server, error)
}
func NewDiscoveryService(gtw gateway.DiscoveryGateway) DiscoveryService
NewDiscoveryService creates a new instance of DiscoveryService with the provided DiscoveryGateway and returns it.
LobbyService defines the interface for managing lobbies.
type LobbyService interface {
// Create creates a new lobby with the given id and host name. It returns the created lobby or an error if something goes wrong.
Create(id, hostName string) (*domain.Lobby, error)
// Join tries to join the lobby with the given id and player name. It returns the joined lobby or an error if something goes wrong.
Join(id, playerName string) (*domain.Lobby, error)
// Leave leaves the lobby with the given id for the given player name. It returns an error if something goes wrong.
Leave(id, playerName string) error
// EditPlayer edits the settings of the player with the given name in the lobby. It returns the updated lobby or an error if something goes wrong.
EditPlayer(lobbyID, playerName string, isReady bool, allowedCharacters, blockedCharacters string, canDelete bool) (*domain.Lobby, error)
// Ready toggles the ready status of the player with the given name in the lobby. It returns the updated lobby or an error if something goes wrong.
Ready(lobbyID, playerName string) (*domain.Lobby, error)
// Connect connects to the given server. It returns an error if the connection fails.
Connect(target *domain.Server) error
// Subscribe subscribes to lobby events and returns a channel that receives updated lobby state.
Subscribe(lobbyID, playerName string) (<-chan *domain.Lobby, error)
// SendKeyPress validates and sends a key press for the given player. Returns the updated lobby.
SendKeyPress(lobbyID string, player *domain.Player, key string, isBackspace bool) (*domain.Lobby, error)
// ResumeGame connects to the given server and asks it to host the crashed lobby.
// Returns the authoritative lobby state and a subscription channel for further updates.
ResumeGame(server *domain.Server, lobby *domain.Lobby, playerName string) (*domain.Lobby, <-chan *domain.Lobby, error)
}
func NewLobbyService(gtw gateway.LobbyGateway) LobbyService
NewLobbyService creates a new instance of LobbyService.
import "github.com/sceredi/co-type/client/internal/tui"
Package tui defines the TUI model, which is the main component of the TUI. It manages the state of the TUI and the movement between pages.
Model is the main model of the TUI.
type Model struct {
// contains filtered or unexported fields
}
func New(ds service.DiscoveryService, ls service.LobbyService) Model
New creates a new TUI model.
func (m Model) Init() tea.Cmd
Init initializes the model.
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd)
Update updates the model based on the given message and returns the updated model and any commands to execute.
func (m Model) View() tea.View
View returns the view of the model.
import "github.com/sceredi/co-type/client/internal/tui/pages"
Package pages defines some constants of the TUI pages.
const (
// Width is the width of the pages.
Width = 60
// Height is the height of the pages.
Height = 30
)
import "github.com/sceredi/co-type/client/internal/tui/styles"
Package styles defines the styles for the TUI components.
var (
// ButtonDefault is a style for buttons with padding, border, and bold text.
ButtonDefault = lipgloss.NewStyle().Padding(0, 3).Border(lipgloss.RoundedBorder()).Bold(true)
// ButtonPrimary is a style for primary buttons with a green border and foreground.
ButtonPrimary = ButtonDefault.BorderForeground(Green).Foreground(Green)
// ButtonDanger is a style for danger buttons with a red border and foreground.
ButtonDanger = ButtonDefault.BorderForeground(Red).Foreground(Red)
// ButtonBlue is a style for blue buttons with a blue border and foreground.
ButtonBlue = ButtonDefault.BorderForeground(Blue).Foreground(Blue)
)
var (
// Red is a color for errors and warnings.
Red = lipgloss.Color("124")
// DarkRed is a darker Red.
DarkRed = lipgloss.Color("88")
// Green is a color for success messages and highlights.
Green = lipgloss.Color("106")
// DarkGreen is a darker Green.
DarkGreen = lipgloss.Color("100")
// Yellow is a color for highlights and accents.
Yellow = lipgloss.Color("172")
// Blue is a color for highlights and accents.
Blue = lipgloss.Color("66")
// Purple is a color for highlights and accents.
Purple = lipgloss.Color("132")
// Acqua is a color for highlights and accents.
Acqua = lipgloss.Color("72")
// Gray is a color for secondary text and accents.
Gray = lipgloss.Color("245")
)
var (
// PaddingAll is a style with padding of 1 on all sides.
PaddingAll = lipgloss.NewStyle().Padding(1)
// PaddingVertical is a style with padding of 1 on the top and bottom.
PaddingVertical = lipgloss.NewStyle().Padding(1, 0)
// PaddingHorizontal is a style with padding of 1 on the left and right.
PaddingHorizontal = lipgloss.NewStyle().Padding(0, 1)
)
Container is a style for a container with padding and a border.
var Container = lipgloss.NewStyle().Padding(1).Border(lipgloss.RoundedBorder(), true)
LabelBold is a style for labels that are bold.
var LabelBold = lipgloss.NewStyle().Bold(true)
func NewContainer(content string) string
NewContainer returns the given content styled with Container.
func NewLabelBold(content string) string
NewLabelBold returns the given content styled with LabelBold.
import "github.com/sceredi/co-type/client/internal/api/grpc/gateway"
Package gateway contains all the gateway that the client uses to connect to the broker and game servers.
Package gateway provides an implementation of the LobbyGateway interface that interacts with the game service via gRPC.
DiscoveryGateway manages the interaction with the broker service.
type DiscoveryGateway interface {
// AvailableServer returns either a server that is available to manage a lobby or an error if something goes wrong.
AvailableServer() (*domain.Server, error)
// HostByLobby returns the server that is hosting the lobby with the given code or an error if something goes wrong.
HostByLobby(lobbyCode string) (*domain.Server, error)
// RequestResumeGame asks the broker to assign a server for resuming the given crashed lobby.
// All players in the crashed game should call this; the broker returns the same server for each.
RequestResumeGame(lobbyID string) (*domain.Server, error)
}
func NewDiscoveryGateway(ctx context.Context, conn discovery.DiscoveryServiceClient) DiscoveryGateway
NewDiscoveryGateway creates a new DiscoveryGateway.
LobbyGateway defines the interface for interacting with the lobby service.
type LobbyGateway interface {
// Create creates a new lobby with the given ID and host name.
Create(id, hostName string) (*domain.Lobby, error)
Join(id, playerName string) (*domain.Lobby, error)
Leave(id, playerName string) error
EditPlayer(lobbyID, playerName string, isReady bool, allowedCharacters, blockedCharacters string, canDelete bool) (*domain.Lobby, error)
Ready(lobbyID, playerName string) (*domain.Lobby, error)
Connect(target *domain.Server) error
// Subscribe subscribes to lobby events and returns a channel that receives updated lobby state.
Subscribe(lobbyID, playerName string) (<-chan *domain.Lobby, error)
// SendKeyPress sends a validated key press to the server.
SendKeyPress(lobbyID, playerName, key string, isBackspace bool) (*domain.Lobby, error)
// ResumeGame asks the server to host the given lobby after a crash. Returns the authoritative
// lobby state. The caller must Subscribe afterwards to receive updates.
ResumeGame(lobby *domain.Lobby, playerName string) (*domain.Lobby, error)
}
func NewLobbyGateway(ctx context.Context) LobbyGateway
NewLobbyGateway creates a new LobbyGateway with the given gRPC connection.
import "github.com/sceredi/co-type/client/internal/tui/pages/common"
Package common contains reusable components and functions for the TUI pages.
func NewTextinput(placeholder string, value string) textinput.Model
NewTextinput creates a new text input with the given placeholder and value.
import "github.com/sceredi/co-type/client/internal/tui/pages/end"
Package end defines the end page of the TUI.
Model is the model for the end page.
type Model struct {
// contains filtered or unexported fields
}
func New(stats domain.GameStats) Model
New creates a new and page model.
func (m Model) Init() tea.Cmd
Init initializes the end page model.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
Update updates the end page model based on the given message.
func (m Model) View() string
View renders the end page.
import "github.com/sceredi/co-type/client/internal/tui/pages/game"
Package game defines the game page of the TUI.
Model is the model for the game page.
type Model struct {
// contains filtered or unexported fields
}
func New(lobby domain.Lobby, player *domain.Player, updates <-chan *domain.Lobby, lobbySvc service.LobbyService, discSvc service.DiscoveryService) Model
New creates a new game model.
func (m Model) Init() tea.Cmd
Init initializes the game model.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
Update updates the game model based on the given message.
func (m Model) View() string
View renders the game page.
import "github.com/sceredi/co-type/client/internal/tui/pages/lobby"
Package lobby defines the lobby page of the TUI.
The Model struct represents the state of the lobby page.
type Model struct {
// contains filtered or unexported fields
}
func New(player *domain.Player, lobby *domain.Lobby, updates <-chan *domain.Lobby, ls service.LobbyService) Model
New creates a new lobby model for the given player, lobby, and subscription channel.
func (m Model) Init() tea.Cmd
Init initializes the model. It starts listening for lobby updates if a subscription is available.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
Update updates the model based on the given message and returns the updated model and any commands to execute.
func (m Model) View() string
View renders the lobby page as a string.
import "github.com/sceredi/co-type/client/internal/tui/pages/welcome"
Package welcome defines the welcome page of the TUI.
Model is the model for the welcome page.
type Model struct {
// contains filtered or unexported fields
}
func New(ds service.DiscoveryService, ls service.LobbyService) Model
New creates a new welcome model.
func (m Model) Init() tea.Cmd
Init initializes the welcome model.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
Update updates the welcome model based on the given message.
func (m Model) View() string
View renders the welcome page.
import "github.com/sceredi/co-type/client/internal/tui/pages/game/messages"
Package game_messages defines the messages for the game page.
func NewGameEndCmd(stats domain.GameStats) tea.Cmd
NewGameEndCmd returns a command that creates a GameEndMsg.
func NewRequestResumeGameCmd(discoverySvc service.DiscoveryService, lobbyID string) tea.Cmd
NewRequestResumeGameCmd contacts the broker to get a server that will host the resumed game.
func NewResumeGameCmd(lobbySvc service.LobbyService, server *domain.Server, lobby *domain.Lobby, playerName string) tea.Cmd
NewResumeGameCmd connects to the given server, calls ResumeGame, and subscribes for updates.
func NewSendKeyPressCmd(lobbySvc service.LobbyService, lobbyID string, player *domain.Player, key string, isBackspace bool) tea.Cmd
NewSendKeyPressCmd returns a Cmd that sends a key press to the server and emits a KeyPressResultMsg.
GameEndMsg is a message that indicates that a game has ended.
type GameEndMsg struct {
Stats domain.GameStats
}
KeyPressResultMsg carries the lobby state returned after a key press, or an error.
type KeyPressResultMsg struct {
Lobby *domain.Lobby
Err error
}
RequestResumeGameResultMsg is emitted after the broker assigns a server for the crashed game.
type RequestResumeGameResultMsg struct {
Server *domain.Server
Err error
}
ResumeGameResultMsg is emitted after the client has connected to the new server and resumed the game.
type ResumeGameResultMsg struct {
Lobby *domain.Lobby
Updates <-chan *domain.Lobby
Err error
}
import "github.com/sceredi/co-type/client/internal/tui/pages/lobby/messages"
Package lobby_messages defines the messages for the lobby page.
func NewCloseSettingsCmd() tea.Cmd
NewCloseSettingsCmd returns a command that creates a CloseSettingsMsg.
func NewEditPlayerCmd(ls service.LobbyService, lobbyID, playerName string, isReady bool, allowedCharacters, blockedCharacters string, canDelete bool) tea.Cmd
NewEditPlayerCmd returns a command that calls the lobby service to edit a player’s settings.
func NewLeaveCmd() tea.Cmd
NewLeaveCmd returns a command that creates a LeaveMessage.
func NewLeaveLobbyCmd(ls service.LobbyService, lobbyID, playerName string) tea.Cmd
NewLeaveLobbyCmd returns a command that calls the lobby service to leave the lobby and then emits a LeaveMsg.
func NewPlayerReadyCmd(name string, isReady bool) tea.Cmd
NewPlayerReadyCmd returns a command that creates a PlayerReadyMsg with the given name and ready status.
func NewReadyCmd(ls service.LobbyService, lobbyID, playerName string) tea.Cmd
NewReadyCmd returns a command that calls the lobby service to toggle the ready status of the player.
func NewStartGameCmd(lobby domain.Lobby, player *domain.Player, updates <-chan *domain.Lobby) tea.Cmd
NewStartGameCmd return a command that creates a StartGameMsg.
func NewUpdatePlayerCmd(player *domain.Player, allowedCharacters, blockedCharacters string, backspaceAllowed bool) tea.Cmd
NewUpdatePlayerCmd returns a command that creates an UpdatePlayerMsg with the given player and settings.
CloseSettingsMsg is a message that indicates that the settings modal should be closed.
type CloseSettingsMsg struct{}
LeaveMsg is a message that indicates the player wants to leave the lobby and return to the main menu.
type LeaveMsg struct{}
LobbySubscriptionClosedMsg is a message that indicates the lobby subscription stream has closed.
type LobbySubscriptionClosedMsg struct{}
LobbyUpdatedMsg is a message that carries an updated lobby state from the subscription stream.
type LobbyUpdatedMsg struct {
Lobby *domain.Lobby
}
PlayerReadyMsg is a message that indicates that a player has changed their ready status.
type PlayerReadyMsg struct {
Name string
IsReady bool
}
StartGameMsg is a message that indicates that a game should be started.
type StartGameMsg struct {
Lobby domain.Lobby
Player *domain.Player
Updates <-chan *domain.Lobby
}
UpdatePlayerMsg is a message that indicates that a player’s settings have been updated.
type UpdatePlayerMsg struct {
Player *domain.Player
AllowedCharacters string
BlockedCharacters string
BackspaceAllowed bool
}
import "github.com/sceredi/co-type/client/internal/tui/pages/welcome/messages"
Package welcome_messages defines the messages for the welcome page of the TUI.
func NewCreateLobbyCmd(ds service.DiscoveryService, ls service.LobbyService, lobbyCode string, playerName string) tea.Cmd
NewCreateLobbyCmd creates a new command to create a lobby.
func NewJoinLobbyCmd(ds service.DiscoveryService, ls service.LobbyService, lobbyCode string, playerName string) tea.Cmd
NewJoinLobbyCmd creates a new command to join a lobby with the given ID.
func NewLeaveJoinLobbyCmd() tea.Cmd
NewLeaveJoinLobbyCmd creates a new command to leave the join lobby page and go back to the welcome page.
JoinLobbyErrorMsg is a message that is sent when there is an error joining a lobby.
type JoinLobbyErrorMsg struct {
Error string
}
JoinedLobbyMsg is a message that is sent when the user wants to join a lobby.
type JoinedLobbyMsg struct {
Lobby *domain.Lobby
Updates <-chan *domain.Lobby
PlayerName string
}
LeaveJoinLobbyMsg is a message that is sent when the user wants to leave the join lobby page and go back to the welcome page.
type LeaveJoinLobbyMsg struct{}
import "github.com/sceredi/co-type/client/internal/tui/pages/lobby/components/header"
Package header defines the header component of the lobby page.
func Render(player *domain.Player, lobby *domain.Lobby) string
Render renders the header component for the given player and lobby.
import "github.com/sceredi/co-type/client/internal/tui/pages/lobby/components/playerinfo"
Package playerinfo defines the component that renders the player’s information in the lobby page.
func Render(player domain.Player) string
Render renders the player information component for the given player.
import "github.com/sceredi/co-type/client/internal/tui/pages/lobby/components/playerlist"
Package playerlist defines the player list component of the lobby page.
func Render(selectedPlayer int, lobby *domain.Lobby) string
Render renders the player list component for the given selected player and lobby.
import "github.com/sceredi/co-type/client/internal/tui/pages/lobby/components/settings"
Package settings provides a bubbletea component to edit player settings
Model is the bubbletea model for the settings component.
type Model struct {
PlayerName string
// contains filtered or unexported fields
}
func New(player *domain.Player) Model
New creates a new settings model for the given player.
func (m Model) Init() tea.Cmd
Init initializes the model. It starts the blinking cursor for the text inputs.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
Update updates the model based on the given message.
func (m Model) View() string
View renders the settings editor.
import "github.com/sceredi/co-type/common/app"
Package app provides common utilities for setting up an application
func CreateListener(grpcServer *grpc.Server, serviceName string)
CreateListener sets up a gRPC server listener for the specified service, using the port defined in the environment variable.
import "github.com/sceredi/co-type/common/config"
Package config contains useful configuration utilities.
func Setup()
Setup initializes the configuration.
import "github.com/sceredi/co-type/common/domain"
Package domain contains the domain models for the co-type game.
Package domain defines the core domain entities and errors for the broker application.
var (
// ErrServerNotFound is returned when a server is not found.
ErrServerNotFound = errors.New("server not found")
// ErrServerAlreadyExists is returned when a server already exists.
ErrServerAlreadyExists = errors.New("server already exists")
// ErrServerNameInvalid is returned when a server name is invalid.
ErrServerNameInvalid = errors.New("server name is invalid")
// ErrServerAddrInvalid is returned when a server address is invalid.
ErrServerAddrInvalid = errors.New("server address is invalid")
// ErrNoAvailableServers is returned when there are no available servers.
ErrNoAvailableServers = errors.New("no available servers")
)
ErrDeleteNotAllowed is returned when a backspace is sent but the player cannot delete or there is nothing to delete.
var ErrDeleteNotAllowed = errors.New("delete not allowed")
ErrGameNotPlaying is returned when a key press is sent but the lobby is not in the Playing state.
var ErrGameNotPlaying = errors.New("game is not currently playing")
ErrKeyNotAllowed is returned when a key press does not pass the player’s allowed/blocked character filters.
var ErrKeyNotAllowed = errors.New("key not allowed for this player")
ErrLobbyAlreadyExists is returned when a lobby with the same ID already exists.
var ErrLobbyAlreadyExists = errors.New("lobby already exists")
ErrLobbyNotFound is returned when a lobby with the given ID is not found.
var ErrLobbyNotFound = errors.New("lobby not found")
ErrLobbyNotOpen is returned when a player tries to join a lobby that is not waiting for players.
var ErrLobbyNotOpen = errors.New("lobby is not open for new players")
ErrPlayerAlreadyInLobby is returned when a player with the same name is already in the lobby.
var ErrPlayerAlreadyInLobby = errors.New("player already in lobby")
ErrPlayerNotInLobby is returned when a player is not in the lobby.
var ErrPlayerNotInLobby = errors.New("player not in lobby")
func ValidateKeyPress(player *Player, key string, isBackspace bool) error
ValidateKeyPress checks whether the given key press is permitted for the player. It returns ErrDeleteNotAllowed if a backspace is sent but the player’s CanDelete is false, and ErrKeyNotAllowed if the key fails printability, AllowedCharacters, or BlockedCharacters checks. Both AllowedCharacters and BlockedCharacters are treated as optional: an empty string skips the check.
GameInfo holds the shared game state that is propagated to all clients via the lobby subscription. Revision is a monotonically increasing counter incremented on every mutation; clients can use it to reconstruct the most recent state after a disconnection. StartTimeMs is the Unix timestamp in milliseconds when the game started; it survives server crashes because it travels with the lobby state. ElapsedMs is the final game duration in milliseconds, set only when the game ends.
type GameInfo struct {
Snippet string
CorrectChars int64
WrongChars int64
Revision int64
StartTimeMs int64
ElapsedMs int64
}
func NewGameInfo(snippet string) *GameInfo
NewGameInfo creates a new GameInfo for a game starting with the given snippet. CorrectChars, WrongChars and Revision are initialised to zero.
GameStats represents the statistics of a game.
type GameStats struct {
TotalTime time.Duration
Lobby Lobby
}
Lobby represents the state of the lobby.
type Lobby struct {
ID string
Players []*Player
Game GameInfo
Status LobbyStatus
}
func NewLobby(id string, firstPlayer *Player) *Lobby
NewLobby creates a new lobby with the given ID and first player.
func NewLobbyFromGRPC(l *lobby.Lobby) *Lobby
NewLobbyFromGRPC converts a gRPC Lobby message to the Lobby struct.
func (l *Lobby) AddPlayers(players ...*Player)
AddPlayers adds the given players to the lobby.
func (l *Lobby) RemovePlayer(name string) bool
RemovePlayer removes the player with the given name from the lobby. Returns true if the player was found and removed.
func (l *Lobby) ToGRPCLobby() *lobby.Lobby
ToGRPCLobby converts the Lobby struct to its gRPC representation.
func (l *Lobby) UpdatePlayer(name string, isReady bool, allowedCharacters, blockedCharacters string, canDelete bool) bool
UpdatePlayer updates the settings of the player with the given name. Returns true if the player was found and updated.
LobbyStatus represents the current phase of a lobby.
type LobbyStatus int
const (
// LobbyWaitingForPlayers indicates the lobby is open and waiting for all players to be ready.
LobbyWaitingForPlayers LobbyStatus = iota
// LobbyPlaying indicates the game is currently in progress.
LobbyPlaying
// LobbyPaused indicates the game is temporarily paused (e.g. a player disconnected).
LobbyPaused
// LobbyGameEnded indicates the game has finished.
LobbyGameEnded
)
Player represents a player in the lobby.
type Player struct {
Name string
IsReady bool
AllowedCharacters string
BlockedCharacters string
CanDelete bool
}
func NewPlayer(name string) *Player
NewPlayer creates a new player with the given name and default values for other fields.
Server represents a server in the broker application.
type Server struct {
Name string
Addr string
Port int
Load int
}
func NewServer(name, addr string, port int) (*Server, error)
NewServer creates a new Server instance with the given address.
import "github.com/sceredi/co-type/common/grpc"
Package grpc provides helpers for gRPC communication.
func FromGRPCError(err error) error
FromGRPCError converts a gRPC error back to a standard error, extracting the message from the gRPC status.
func ToGRPCError(err error) error
ToGRPCError maps domain errors to gRPC status errors, allowing for consistent error handling in gRPC responses.
func ToGRPCMessage(err error) string
ToGRPCMessage converts an error to a string message for gRPC responses.
import "github.com/sceredi/co-type/common/proto/control"
const (
ControlService_RegisterServer_FullMethodName = "/control.ControlService/RegisterServer"
ControlService_RegisterLobby_FullMethodName = "/control.ControlService/RegisterLobby"
ControlService_UnregisterLobby_FullMethodName = "/control.ControlService/UnregisterLobby"
ControlService_Heartbeat_FullMethodName = "/control.ControlService/Heartbeat"
)
ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service. It’s only intended for direct use with grpc.RegisterService, and not to be introspected or modified (even as a copy)
var ControlService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "control.ControlService",
HandlerType: (*ControlServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "RegisterServer",
Handler: _ControlService_RegisterServer_Handler,
},
{
MethodName: "RegisterLobby",
Handler: _ControlService_RegisterLobby_Handler,
},
{
MethodName: "UnregisterLobby",
Handler: _ControlService_UnregisterLobby_Handler,
},
{
MethodName: "Heartbeat",
Handler: _ControlService_Heartbeat_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "common/proto/control/control.proto",
}
var File_common_proto_control_control_proto protoreflect.FileDescriptor
func RegisterControlServiceServer(s grpc.ServiceRegistrar, srv ControlServiceServer)
ControlServiceClient is the client API for ControlService service.
For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
The control service definition.
type ControlServiceClient interface {
RegisterServer(ctx context.Context, in *RegisterServerRequest, opts ...grpc.CallOption) (*RegisterServerResponse, error)
RegisterLobby(ctx context.Context, in *RegisterLobbyRequest, opts ...grpc.CallOption) (*RegisterLobbyResponse, error)
UnregisterLobby(ctx context.Context, in *UnregisterLobbyRequest, opts ...grpc.CallOption) (*UnregisterLobbyResponse, error)
Heartbeat(ctx context.Context, in *HeartbeatRequest, opts ...grpc.CallOption) (*HeartbeatResponse, error)
}
func NewControlServiceClient(cc grpc.ClientConnInterface) ControlServiceClient
ControlServiceServer is the server API for ControlService service. All implementations must embed UnimplementedControlServiceServer for forward compatibility.
The control service definition.
type ControlServiceServer interface {
RegisterServer(context.Context, *RegisterServerRequest) (*RegisterServerResponse, error)
RegisterLobby(context.Context, *RegisterLobbyRequest) (*RegisterLobbyResponse, error)
UnregisterLobby(context.Context, *UnregisterLobbyRequest) (*UnregisterLobbyResponse, error)
Heartbeat(context.Context, *HeartbeatRequest) (*HeartbeatResponse, error)
// contains filtered or unexported methods
}
Heartbeat request sent periodically by a server to signal it is alive and report its current load.
type HeartbeatRequest struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Load int64 `protobuf:"varint,2,opt,name=load,proto3" json:"load,omitempty"`
// contains filtered or unexported fields
}
func (*HeartbeatRequest) Descriptor() ([]byte, []int)
Deprecated: Use HeartbeatRequest.ProtoReflect.Descriptor instead.
func (x *HeartbeatRequest) GetLoad() int64
func (x *HeartbeatRequest) GetName() string
func (*HeartbeatRequest) ProtoMessage()
func (x *HeartbeatRequest) ProtoReflect() protoreflect.Message
func (x *HeartbeatRequest) Reset()
func (x *HeartbeatRequest) String() string
Acknowledgment for a heartbeat.
type HeartbeatResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
// contains filtered or unexported fields
}
func (*HeartbeatResponse) Descriptor() ([]byte, []int)
Deprecated: Use HeartbeatResponse.ProtoReflect.Descriptor instead.
func (x *HeartbeatResponse) GetSuccess() bool
func (*HeartbeatResponse) ProtoMessage()
func (x *HeartbeatResponse) ProtoReflect() protoreflect.Message
func (x *HeartbeatResponse) Reset()
func (x *HeartbeatResponse) String() string
Messages for lobby registration with the broker.
type RegisterLobbyRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
ServerName string `protobuf:"bytes,2,opt,name=server_name,json=serverName,proto3" json:"server_name,omitempty"`
// contains filtered or unexported fields
}
func (*RegisterLobbyRequest) Descriptor() ([]byte, []int)
Deprecated: Use RegisterLobbyRequest.ProtoReflect.Descriptor instead.
func (x *RegisterLobbyRequest) GetLobbyId() string
func (x *RegisterLobbyRequest) GetServerName() string
func (*RegisterLobbyRequest) ProtoMessage()
func (x *RegisterLobbyRequest) ProtoReflect() protoreflect.Message
func (x *RegisterLobbyRequest) Reset()
func (x *RegisterLobbyRequest) String() string
Response for lobby registration.
type RegisterLobbyResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// contains filtered or unexported fields
}
func (*RegisterLobbyResponse) Descriptor() ([]byte, []int)
Deprecated: Use RegisterLobbyResponse.ProtoReflect.Descriptor instead.
func (x *RegisterLobbyResponse) GetMessage() string
func (x *RegisterLobbyResponse) GetSuccess() bool
func (*RegisterLobbyResponse) ProtoMessage()
func (x *RegisterLobbyResponse) ProtoReflect() protoreflect.Message
func (x *RegisterLobbyResponse) Reset()
func (x *RegisterLobbyResponse) String() string
Messages for server registration.
type RegisterServerRequest struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Host string `protobuf:"bytes,2,opt,name=host,proto3" json:"host,omitempty"`
Port int64 `protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
LobbyIds []string `protobuf:"bytes,4,rep,name=lobby_ids,json=lobbyIds,proto3" json:"lobby_ids,omitempty"`
// contains filtered or unexported fields
}
func (*RegisterServerRequest) Descriptor() ([]byte, []int)
Deprecated: Use RegisterServerRequest.ProtoReflect.Descriptor instead.
func (x *RegisterServerRequest) GetHost() string
func (x *RegisterServerRequest) GetLobbyIds() []string
func (x *RegisterServerRequest) GetName() string
func (x *RegisterServerRequest) GetPort() int64
func (*RegisterServerRequest) ProtoMessage()
func (x *RegisterServerRequest) ProtoReflect() protoreflect.Message
func (x *RegisterServerRequest) Reset()
func (x *RegisterServerRequest) String() string
Acknowledgment for server registration.
type RegisterServerResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// contains filtered or unexported fields
}
func (*RegisterServerResponse) Descriptor() ([]byte, []int)
Deprecated: Use RegisterServerResponse.ProtoReflect.Descriptor instead.
func (x *RegisterServerResponse) GetMessage() string
func (x *RegisterServerResponse) GetSuccess() bool
func (*RegisterServerResponse) ProtoMessage()
func (x *RegisterServerResponse) ProtoReflect() protoreflect.Message
func (x *RegisterServerResponse) Reset()
func (x *RegisterServerResponse) String() string
UnimplementedControlServiceServer must be embedded to have forward compatible implementations.
NOTE: this should be embedded by value instead of pointer to avoid a nil pointer dereference when methods are called.
type UnimplementedControlServiceServer struct{}
func (UnimplementedControlServiceServer) Heartbeat(context.Context, *HeartbeatRequest) (*HeartbeatResponse, error)
func (UnimplementedControlServiceServer) RegisterLobby(context.Context, *RegisterLobbyRequest) (*RegisterLobbyResponse, error)
func (UnimplementedControlServiceServer) RegisterServer(context.Context, *RegisterServerRequest) (*RegisterServerResponse, error)
func (UnimplementedControlServiceServer) UnregisterLobby(context.Context, *UnregisterLobbyRequest) (*UnregisterLobbyResponse, error)
Request to unregister a lobby from the broker.
type UnregisterLobbyRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
// contains filtered or unexported fields
}
func (*UnregisterLobbyRequest) Descriptor() ([]byte, []int)
Deprecated: Use UnregisterLobbyRequest.ProtoReflect.Descriptor instead.
func (x *UnregisterLobbyRequest) GetLobbyId() string
func (*UnregisterLobbyRequest) ProtoMessage()
func (x *UnregisterLobbyRequest) ProtoReflect() protoreflect.Message
func (x *UnregisterLobbyRequest) Reset()
func (x *UnregisterLobbyRequest) String() string
Response for lobby unregistration.
type UnregisterLobbyResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// contains filtered or unexported fields
}
func (*UnregisterLobbyResponse) Descriptor() ([]byte, []int)
Deprecated: Use UnregisterLobbyResponse.ProtoReflect.Descriptor instead.
func (x *UnregisterLobbyResponse) GetMessage() string
func (x *UnregisterLobbyResponse) GetSuccess() bool
func (*UnregisterLobbyResponse) ProtoMessage()
func (x *UnregisterLobbyResponse) ProtoReflect() protoreflect.Message
func (x *UnregisterLobbyResponse) Reset()
func (x *UnregisterLobbyResponse) String() string
UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to ControlServiceServer will result in compilation errors.
type UnsafeControlServiceServer interface {
// contains filtered or unexported methods
}
import "github.com/sceredi/co-type/common/proto/discovery"
const (
DiscoveryService_AvailableServer_FullMethodName = "/discovery.DiscoveryService/AvailableServer"
DiscoveryService_ServerHostingLobby_FullMethodName = "/discovery.DiscoveryService/ServerHostingLobby"
DiscoveryService_RequestResumeGame_FullMethodName = "/discovery.DiscoveryService/RequestResumeGame"
)
DiscoveryService_ServiceDesc is the grpc.ServiceDesc for DiscoveryService service. It’s only intended for direct use with grpc.RegisterService, and not to be introspected or modified (even as a copy)
var DiscoveryService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "discovery.DiscoveryService",
HandlerType: (*DiscoveryServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "AvailableServer",
Handler: _DiscoveryService_AvailableServer_Handler,
},
{
MethodName: "ServerHostingLobby",
Handler: _DiscoveryService_ServerHostingLobby_Handler,
},
{
MethodName: "RequestResumeGame",
Handler: _DiscoveryService_RequestResumeGame_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "common/proto/discovery/discovery.proto",
}
var File_common_proto_discovery_discovery_proto protoreflect.FileDescriptor
func RegisterDiscoveryServiceServer(s grpc.ServiceRegistrar, srv DiscoveryServiceServer)
Request message for available server information.
type AvailableServerRequest struct {
// contains filtered or unexported fields
}
func (*AvailableServerRequest) Descriptor() ([]byte, []int)
Deprecated: Use AvailableServerRequest.ProtoReflect.Descriptor instead.
func (*AvailableServerRequest) ProtoMessage()
func (x *AvailableServerRequest) ProtoReflect() protoreflect.Message
func (x *AvailableServerRequest) Reset()
func (x *AvailableServerRequest) String() string
Response message containing available server information.
type AvailableServerResponse struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Addr string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"`
Port int64 `protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
// contains filtered or unexported fields
}
func (*AvailableServerResponse) Descriptor() ([]byte, []int)
Deprecated: Use AvailableServerResponse.ProtoReflect.Descriptor instead.
func (x *AvailableServerResponse) GetAddr() string
func (x *AvailableServerResponse) GetName() string
func (x *AvailableServerResponse) GetPort() int64
func (*AvailableServerResponse) ProtoMessage()
func (x *AvailableServerResponse) ProtoReflect() protoreflect.Message
func (x *AvailableServerResponse) Reset()
func (x *AvailableServerResponse) String() string
DiscoveryServiceClient is the client API for DiscoveryService service.
For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
The discovery service definition.
type DiscoveryServiceClient interface {
// RPC to get the available server information.
AvailableServer(ctx context.Context, in *AvailableServerRequest, opts ...grpc.CallOption) (*AvailableServerResponse, error)
// RPC to get the server hosting lobby information.
ServerHostingLobby(ctx context.Context, in *ServerHostingLobbyRequest, opts ...grpc.CallOption) (*ServerHostingLobbyResponse, error)
// RPC to request resuming a crashed game. The broker assigns (or reuses) a server for
// the lobby and returns its address. All players in the crashed game call this.
RequestResumeGame(ctx context.Context, in *RequestResumeGameRequest, opts ...grpc.CallOption) (*RequestResumeGameResponse, error)
}
func NewDiscoveryServiceClient(cc grpc.ClientConnInterface) DiscoveryServiceClient
DiscoveryServiceServer is the server API for DiscoveryService service. All implementations must embed UnimplementedDiscoveryServiceServer for forward compatibility.
The discovery service definition.
type DiscoveryServiceServer interface {
// RPC to get the available server information.
AvailableServer(context.Context, *AvailableServerRequest) (*AvailableServerResponse, error)
// RPC to get the server hosting lobby information.
ServerHostingLobby(context.Context, *ServerHostingLobbyRequest) (*ServerHostingLobbyResponse, error)
// RPC to request resuming a crashed game. The broker assigns (or reuses) a server for
// the lobby and returns its address. All players in the crashed game call this.
RequestResumeGame(context.Context, *RequestResumeGameRequest) (*RequestResumeGameResponse, error)
// contains filtered or unexported methods
}
Request message to resume a crashed game.
type RequestResumeGameRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
// contains filtered or unexported fields
}
func (*RequestResumeGameRequest) Descriptor() ([]byte, []int)
Deprecated: Use RequestResumeGameRequest.ProtoReflect.Descriptor instead.
func (x *RequestResumeGameRequest) GetLobbyId() string
func (*RequestResumeGameRequest) ProtoMessage()
func (x *RequestResumeGameRequest) ProtoReflect() protoreflect.Message
func (x *RequestResumeGameRequest) Reset()
func (x *RequestResumeGameRequest) String() string
Response message containing the server assigned to host the resumed game.
type RequestResumeGameResponse struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Addr string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"`
Port int64 `protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
// contains filtered or unexported fields
}
func (*RequestResumeGameResponse) Descriptor() ([]byte, []int)
Deprecated: Use RequestResumeGameResponse.ProtoReflect.Descriptor instead.
func (x *RequestResumeGameResponse) GetAddr() string
func (x *RequestResumeGameResponse) GetName() string
func (x *RequestResumeGameResponse) GetPort() int64
func (*RequestResumeGameResponse) ProtoMessage()
func (x *RequestResumeGameResponse) ProtoReflect() protoreflect.Message
func (x *RequestResumeGameResponse) Reset()
func (x *RequestResumeGameResponse) String() string
Request message for server hosting lobby information.
type ServerHostingLobbyRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
// contains filtered or unexported fields
}
func (*ServerHostingLobbyRequest) Descriptor() ([]byte, []int)
Deprecated: Use ServerHostingLobbyRequest.ProtoReflect.Descriptor instead.
func (x *ServerHostingLobbyRequest) GetLobbyId() string
func (*ServerHostingLobbyRequest) ProtoMessage()
func (x *ServerHostingLobbyRequest) ProtoReflect() protoreflect.Message
func (x *ServerHostingLobbyRequest) Reset()
func (x *ServerHostingLobbyRequest) String() string
Response message containing server hosting lobby information.
type ServerHostingLobbyResponse struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Addr string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"`
Port int64 `protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
// contains filtered or unexported fields
}
func (*ServerHostingLobbyResponse) Descriptor() ([]byte, []int)
Deprecated: Use ServerHostingLobbyResponse.ProtoReflect.Descriptor instead.
func (x *ServerHostingLobbyResponse) GetAddr() string
func (x *ServerHostingLobbyResponse) GetName() string
func (x *ServerHostingLobbyResponse) GetPort() int64
func (*ServerHostingLobbyResponse) ProtoMessage()
func (x *ServerHostingLobbyResponse) ProtoReflect() protoreflect.Message
func (x *ServerHostingLobbyResponse) Reset()
func (x *ServerHostingLobbyResponse) String() string
UnimplementedDiscoveryServiceServer must be embedded to have forward compatible implementations.
NOTE: this should be embedded by value instead of pointer to avoid a nil pointer dereference when methods are called.
type UnimplementedDiscoveryServiceServer struct{}
func (UnimplementedDiscoveryServiceServer) AvailableServer(context.Context, *AvailableServerRequest) (*AvailableServerResponse, error)
func (UnimplementedDiscoveryServiceServer) RequestResumeGame(context.Context, *RequestResumeGameRequest) (*RequestResumeGameResponse, error)
func (UnimplementedDiscoveryServiceServer) ServerHostingLobby(context.Context, *ServerHostingLobbyRequest) (*ServerHostingLobbyResponse, error)
UnsafeDiscoveryServiceServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to DiscoveryServiceServer will result in compilation errors.
type UnsafeDiscoveryServiceServer interface {
// contains filtered or unexported methods
}
import "github.com/sceredi/co-type/common/proto/lobby"
const (
LobbyService_CreateLobby_FullMethodName = "/lobby.LobbyService/CreateLobby"
LobbyService_JoinLobby_FullMethodName = "/lobby.LobbyService/JoinLobby"
LobbyService_LeaveLobby_FullMethodName = "/lobby.LobbyService/LeaveLobby"
LobbyService_EditPlayer_FullMethodName = "/lobby.LobbyService/EditPlayer"
LobbyService_ReadyPlayer_FullMethodName = "/lobby.LobbyService/ReadyPlayer"
LobbyService_Subscribe_FullMethodName = "/lobby.LobbyService/Subscribe"
LobbyService_SendKeyPress_FullMethodName = "/lobby.LobbyService/SendKeyPress"
LobbyService_ResumeGame_FullMethodName = "/lobby.LobbyService/ResumeGame"
)
Enum value maps for LobbyStatus.
var (
LobbyStatus_name = map[int32]string{
0: "WAITING_FOR_PLAYERS",
1: "PLAYING",
2: "PAUSED",
3: "GAME_ENDED",
}
LobbyStatus_value = map[string]int32{
"WAITING_FOR_PLAYERS": 0,
"PLAYING": 1,
"PAUSED": 2,
"GAME_ENDED": 3,
}
)
var File_common_proto_lobby_lobby_proto protoreflect.FileDescriptor
LobbyService_ServiceDesc is the grpc.ServiceDesc for LobbyService service. It’s only intended for direct use with grpc.RegisterService, and not to be introspected or modified (even as a copy)
var LobbyService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "lobby.LobbyService",
HandlerType: (*LobbyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "CreateLobby",
Handler: _LobbyService_CreateLobby_Handler,
},
{
MethodName: "JoinLobby",
Handler: _LobbyService_JoinLobby_Handler,
},
{
MethodName: "LeaveLobby",
Handler: _LobbyService_LeaveLobby_Handler,
},
{
MethodName: "EditPlayer",
Handler: _LobbyService_EditPlayer_Handler,
},
{
MethodName: "ReadyPlayer",
Handler: _LobbyService_ReadyPlayer_Handler,
},
{
MethodName: "SendKeyPress",
Handler: _LobbyService_SendKeyPress_Handler,
},
{
MethodName: "ResumeGame",
Handler: _LobbyService_ResumeGame_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "Subscribe",
Handler: _LobbyService_Subscribe_Handler,
ServerStreams: true,
},
},
Metadata: "common/proto/lobby/lobby.proto",
}
func RegisterLobbyServiceServer(s grpc.ServiceRegistrar, srv LobbyServiceServer)
Messages for lobby management.
type CreateLobbyRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
// contains filtered or unexported fields
}
func (*CreateLobbyRequest) Descriptor() ([]byte, []int)
Deprecated: Use CreateLobbyRequest.ProtoReflect.Descriptor instead.
func (x *CreateLobbyRequest) GetLobbyId() string
func (x *CreateLobbyRequest) GetPlayerName() string
func (*CreateLobbyRequest) ProtoMessage()
func (x *CreateLobbyRequest) ProtoReflect() protoreflect.Message
func (x *CreateLobbyRequest) Reset()
func (x *CreateLobbyRequest) String() string
type CreateLobbyResponse struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
// contains filtered or unexported fields
}
func (*CreateLobbyResponse) Descriptor() ([]byte, []int)
Deprecated: Use CreateLobbyResponse.ProtoReflect.Descriptor instead.
func (x *CreateLobbyResponse) GetLobby() *Lobby
func (*CreateLobbyResponse) ProtoMessage()
func (x *CreateLobbyResponse) ProtoReflect() protoreflect.Message
func (x *CreateLobbyResponse) Reset()
func (x *CreateLobbyResponse) String() string
type EditPlayerRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
IsReady bool `protobuf:"varint,3,opt,name=is_ready,json=isReady,proto3" json:"is_ready,omitempty"`
AllowedCharacters string `protobuf:"bytes,4,opt,name=allowed_characters,json=allowedCharacters,proto3" json:"allowed_characters,omitempty"`
BlockedCharacters string `protobuf:"bytes,5,opt,name=blocked_characters,json=blockedCharacters,proto3" json:"blocked_characters,omitempty"`
CanDelete bool `protobuf:"varint,6,opt,name=can_delete,json=canDelete,proto3" json:"can_delete,omitempty"`
// contains filtered or unexported fields
}
func (*EditPlayerRequest) Descriptor() ([]byte, []int)
Deprecated: Use EditPlayerRequest.ProtoReflect.Descriptor instead.
func (x *EditPlayerRequest) GetAllowedCharacters() string
func (x *EditPlayerRequest) GetBlockedCharacters() string
func (x *EditPlayerRequest) GetCanDelete() bool
func (x *EditPlayerRequest) GetIsReady() bool
func (x *EditPlayerRequest) GetLobbyId() string
func (x *EditPlayerRequest) GetPlayerName() string
func (*EditPlayerRequest) ProtoMessage()
func (x *EditPlayerRequest) ProtoReflect() protoreflect.Message
func (x *EditPlayerRequest) Reset()
func (x *EditPlayerRequest) String() string
type EditPlayerResponse struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
// contains filtered or unexported fields
}
func (*EditPlayerResponse) Descriptor() ([]byte, []int)
Deprecated: Use EditPlayerResponse.ProtoReflect.Descriptor instead.
func (x *EditPlayerResponse) GetLobby() *Lobby
func (*EditPlayerResponse) ProtoMessage()
func (x *EditPlayerResponse) ProtoReflect() protoreflect.Message
func (x *EditPlayerResponse) Reset()
func (x *EditPlayerResponse) String() string
type GameInfo struct {
Snippet string `protobuf:"bytes,1,opt,name=snippet,proto3" json:"snippet,omitempty"`
CorrectChars int64 `protobuf:"varint,2,opt,name=correct_chars,json=correctChars,proto3" json:"correct_chars,omitempty"`
WrongChars int64 `protobuf:"varint,3,opt,name=wrong_chars,json=wrongChars,proto3" json:"wrong_chars,omitempty"`
Revision int64 `protobuf:"varint,4,opt,name=revision,proto3" json:"revision,omitempty"`
// start_time_ms is the Unix timestamp in milliseconds when the game started.
StartTimeMs int64 `protobuf:"varint,5,opt,name=start_time_ms,json=startTimeMs,proto3" json:"start_time_ms,omitempty"`
// elapsed_ms is the total game duration in milliseconds, set when the game ends.
ElapsedMs int64 `protobuf:"varint,6,opt,name=elapsed_ms,json=elapsedMs,proto3" json:"elapsed_ms,omitempty"`
// contains filtered or unexported fields
}
func (*GameInfo) Descriptor() ([]byte, []int)
Deprecated: Use GameInfo.ProtoReflect.Descriptor instead.
func (x *GameInfo) GetCorrectChars() int64
func (x *GameInfo) GetElapsedMs() int64
func (x *GameInfo) GetRevision() int64
func (x *GameInfo) GetSnippet() string
func (x *GameInfo) GetStartTimeMs() int64
func (x *GameInfo) GetWrongChars() int64
func (*GameInfo) ProtoMessage()
func (x *GameInfo) ProtoReflect() protoreflect.Message
func (x *GameInfo) Reset()
func (x *GameInfo) String() string
type JoinLobbyRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
// contains filtered or unexported fields
}
func (*JoinLobbyRequest) Descriptor() ([]byte, []int)
Deprecated: Use JoinLobbyRequest.ProtoReflect.Descriptor instead.
func (x *JoinLobbyRequest) GetLobbyId() string
func (x *JoinLobbyRequest) GetPlayerName() string
func (*JoinLobbyRequest) ProtoMessage()
func (x *JoinLobbyRequest) ProtoReflect() protoreflect.Message
func (x *JoinLobbyRequest) Reset()
func (x *JoinLobbyRequest) String() string
type JoinLobbyResponse struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
// contains filtered or unexported fields
}
func (*JoinLobbyResponse) Descriptor() ([]byte, []int)
Deprecated: Use JoinLobbyResponse.ProtoReflect.Descriptor instead.
func (x *JoinLobbyResponse) GetLobby() *Lobby
func (*JoinLobbyResponse) ProtoMessage()
func (x *JoinLobbyResponse) ProtoReflect() protoreflect.Message
func (x *JoinLobbyResponse) Reset()
func (x *JoinLobbyResponse) String() string
type LeaveLobbyRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
// contains filtered or unexported fields
}
func (*LeaveLobbyRequest) Descriptor() ([]byte, []int)
Deprecated: Use LeaveLobbyRequest.ProtoReflect.Descriptor instead.
func (x *LeaveLobbyRequest) GetLobbyId() string
func (x *LeaveLobbyRequest) GetPlayerName() string
func (*LeaveLobbyRequest) ProtoMessage()
func (x *LeaveLobbyRequest) ProtoReflect() protoreflect.Message
func (x *LeaveLobbyRequest) Reset()
func (x *LeaveLobbyRequest) String() string
type LeaveLobbyResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// contains filtered or unexported fields
}
func (*LeaveLobbyResponse) Descriptor() ([]byte, []int)
Deprecated: Use LeaveLobbyResponse.ProtoReflect.Descriptor instead.
func (x *LeaveLobbyResponse) GetMessage() string
func (x *LeaveLobbyResponse) GetSuccess() bool
func (*LeaveLobbyResponse) ProtoMessage()
func (x *LeaveLobbyResponse) ProtoReflect() protoreflect.Message
func (x *LeaveLobbyResponse) Reset()
func (x *LeaveLobbyResponse) String() string
type Lobby struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Players []*Player `protobuf:"bytes,2,rep,name=players,proto3" json:"players,omitempty"`
Game *GameInfo `protobuf:"bytes,3,opt,name=game,proto3" json:"game,omitempty"`
Status LobbyStatus `protobuf:"varint,4,opt,name=status,proto3,enum=lobby.LobbyStatus" json:"status,omitempty"`
// contains filtered or unexported fields
}
func (*Lobby) Descriptor() ([]byte, []int)
Deprecated: Use Lobby.ProtoReflect.Descriptor instead.
func (x *Lobby) GetGame() *GameInfo
func (x *Lobby) GetId() string
func (x *Lobby) GetPlayers() []*Player
func (x *Lobby) GetStatus() LobbyStatus
func (*Lobby) ProtoMessage()
func (x *Lobby) ProtoReflect() protoreflect.Message
func (x *Lobby) Reset()
func (x *Lobby) String() string
type LobbyEvent struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
// contains filtered or unexported fields
}
func (*LobbyEvent) Descriptor() ([]byte, []int)
Deprecated: Use LobbyEvent.ProtoReflect.Descriptor instead.
func (x *LobbyEvent) GetLobby() *Lobby
func (*LobbyEvent) ProtoMessage()
func (x *LobbyEvent) ProtoReflect() protoreflect.Message
func (x *LobbyEvent) Reset()
func (x *LobbyEvent) String() string
LobbyServiceClient is the client API for LobbyService service.
For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
The game service definition.
type LobbyServiceClient interface {
CreateLobby(ctx context.Context, in *CreateLobbyRequest, opts ...grpc.CallOption) (*CreateLobbyResponse, error)
JoinLobby(ctx context.Context, in *JoinLobbyRequest, opts ...grpc.CallOption) (*JoinLobbyResponse, error)
LeaveLobby(ctx context.Context, in *LeaveLobbyRequest, opts ...grpc.CallOption) (*LeaveLobbyResponse, error)
EditPlayer(ctx context.Context, in *EditPlayerRequest, opts ...grpc.CallOption) (*EditPlayerResponse, error)
ReadyPlayer(ctx context.Context, in *ReadyPlayerRequest, opts ...grpc.CallOption) (*ReadyPlayerResponse, error)
Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LobbyEvent], error)
SendKeyPress(ctx context.Context, in *SendKeyPressRequest, opts ...grpc.CallOption) (*SendKeyPressResponse, error)
// RPC to resume a crashed game on a new server. The first caller creates the lobby;
// subsequent callers (reconnecting players) provide their game state so the server
// can keep the state with the highest revision.
ResumeGame(ctx context.Context, in *ResumeGameRequest, opts ...grpc.CallOption) (*ResumeGameResponse, error)
}
func NewLobbyServiceClient(cc grpc.ClientConnInterface) LobbyServiceClient
LobbyServiceServer is the server API for LobbyService service. All implementations must embed UnimplementedLobbyServiceServer for forward compatibility.
The game service definition.
type LobbyServiceServer interface {
CreateLobby(context.Context, *CreateLobbyRequest) (*CreateLobbyResponse, error)
JoinLobby(context.Context, *JoinLobbyRequest) (*JoinLobbyResponse, error)
LeaveLobby(context.Context, *LeaveLobbyRequest) (*LeaveLobbyResponse, error)
EditPlayer(context.Context, *EditPlayerRequest) (*EditPlayerResponse, error)
ReadyPlayer(context.Context, *ReadyPlayerRequest) (*ReadyPlayerResponse, error)
Subscribe(*SubscribeRequest, grpc.ServerStreamingServer[LobbyEvent]) error
SendKeyPress(context.Context, *SendKeyPressRequest) (*SendKeyPressResponse, error)
// RPC to resume a crashed game on a new server. The first caller creates the lobby;
// subsequent callers (reconnecting players) provide their game state so the server
// can keep the state with the highest revision.
ResumeGame(context.Context, *ResumeGameRequest) (*ResumeGameResponse, error)
// contains filtered or unexported methods
}
This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type LobbyService_SubscribeClient = grpc.ServerStreamingClient[LobbyEvent]
This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type LobbyService_SubscribeServer = grpc.ServerStreamingServer[LobbyEvent]
type LobbyStatus int32
const (
LobbyStatus_WAITING_FOR_PLAYERS LobbyStatus = 0
LobbyStatus_PLAYING LobbyStatus = 1
LobbyStatus_PAUSED LobbyStatus = 2
LobbyStatus_GAME_ENDED LobbyStatus = 3
)
func (LobbyStatus) Descriptor() protoreflect.EnumDescriptor
func (x LobbyStatus) Enum() *LobbyStatus
func (LobbyStatus) EnumDescriptor() ([]byte, []int)
Deprecated: Use LobbyStatus.Descriptor instead.
func (x LobbyStatus) Number() protoreflect.EnumNumber
func (x LobbyStatus) String() string
func (LobbyStatus) Type() protoreflect.EnumType
type Player struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
IsReady bool `protobuf:"varint,2,opt,name=is_ready,json=isReady,proto3" json:"is_ready,omitempty"`
AllowedCharacters string `protobuf:"bytes,3,opt,name=allowed_characters,json=allowedCharacters,proto3" json:"allowed_characters,omitempty"`
BlockedCharacters string `protobuf:"bytes,4,opt,name=blocked_characters,json=blockedCharacters,proto3" json:"blocked_characters,omitempty"`
CanDelete bool `protobuf:"varint,5,opt,name=can_delete,json=canDelete,proto3" json:"can_delete,omitempty"`
// contains filtered or unexported fields
}
func (*Player) Descriptor() ([]byte, []int)
Deprecated: Use Player.ProtoReflect.Descriptor instead.
func (x *Player) GetAllowedCharacters() string
func (x *Player) GetBlockedCharacters() string
func (x *Player) GetCanDelete() bool
func (x *Player) GetIsReady() bool
func (x *Player) GetName() string
func (*Player) ProtoMessage()
func (x *Player) ProtoReflect() protoreflect.Message
func (x *Player) Reset()
func (x *Player) String() string
type ReadyPlayerRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
// contains filtered or unexported fields
}
func (*ReadyPlayerRequest) Descriptor() ([]byte, []int)
Deprecated: Use ReadyPlayerRequest.ProtoReflect.Descriptor instead.
func (x *ReadyPlayerRequest) GetLobbyId() string
func (x *ReadyPlayerRequest) GetPlayerName() string
func (*ReadyPlayerRequest) ProtoMessage()
func (x *ReadyPlayerRequest) ProtoReflect() protoreflect.Message
func (x *ReadyPlayerRequest) Reset()
func (x *ReadyPlayerRequest) String() string
type ReadyPlayerResponse struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
// contains filtered or unexported fields
}
func (*ReadyPlayerResponse) Descriptor() ([]byte, []int)
Deprecated: Use ReadyPlayerResponse.ProtoReflect.Descriptor instead.
func (x *ReadyPlayerResponse) GetLobby() *Lobby
func (*ReadyPlayerResponse) ProtoMessage()
func (x *ReadyPlayerResponse) ProtoReflect() protoreflect.Message
func (x *ReadyPlayerResponse) Reset()
func (x *ReadyPlayerResponse) String() string
Request to resume a crashed game on a new server.
type ResumeGameRequest struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
// contains filtered or unexported fields
}
func (*ResumeGameRequest) Descriptor() ([]byte, []int)
Deprecated: Use ResumeGameRequest.ProtoReflect.Descriptor instead.
func (x *ResumeGameRequest) GetLobby() *Lobby
func (x *ResumeGameRequest) GetPlayerName() string
func (*ResumeGameRequest) ProtoMessage()
func (x *ResumeGameRequest) ProtoReflect() protoreflect.Message
func (x *ResumeGameRequest) Reset()
func (x *ResumeGameRequest) String() string
Response after resuming a game.
type ResumeGameResponse struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
// contains filtered or unexported fields
}
func (*ResumeGameResponse) Descriptor() ([]byte, []int)
Deprecated: Use ResumeGameResponse.ProtoReflect.Descriptor instead.
func (x *ResumeGameResponse) GetLobby() *Lobby
func (*ResumeGameResponse) ProtoMessage()
func (x *ResumeGameResponse) ProtoReflect() protoreflect.Message
func (x *ResumeGameResponse) Reset()
func (x *ResumeGameResponse) String() string
type SendKeyPressRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
Key string `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"`
IsBackspace bool `protobuf:"varint,4,opt,name=is_backspace,json=isBackspace,proto3" json:"is_backspace,omitempty"`
// contains filtered or unexported fields
}
func (*SendKeyPressRequest) Descriptor() ([]byte, []int)
Deprecated: Use SendKeyPressRequest.ProtoReflect.Descriptor instead.
func (x *SendKeyPressRequest) GetIsBackspace() bool
func (x *SendKeyPressRequest) GetKey() string
func (x *SendKeyPressRequest) GetLobbyId() string
func (x *SendKeyPressRequest) GetPlayerName() string
func (*SendKeyPressRequest) ProtoMessage()
func (x *SendKeyPressRequest) ProtoReflect() protoreflect.Message
func (x *SendKeyPressRequest) Reset()
func (x *SendKeyPressRequest) String() string
type SendKeyPressResponse struct {
Lobby *Lobby `protobuf:"bytes,1,opt,name=lobby,proto3" json:"lobby,omitempty"`
// contains filtered or unexported fields
}
func (*SendKeyPressResponse) Descriptor() ([]byte, []int)
Deprecated: Use SendKeyPressResponse.ProtoReflect.Descriptor instead.
func (x *SendKeyPressResponse) GetLobby() *Lobby
func (*SendKeyPressResponse) ProtoMessage()
func (x *SendKeyPressResponse) ProtoReflect() protoreflect.Message
func (x *SendKeyPressResponse) Reset()
func (x *SendKeyPressResponse) String() string
type SubscribeRequest struct {
LobbyId string `protobuf:"bytes,1,opt,name=lobby_id,json=lobbyId,proto3" json:"lobby_id,omitempty"`
PlayerName string `protobuf:"bytes,2,opt,name=player_name,json=playerName,proto3" json:"player_name,omitempty"`
// contains filtered or unexported fields
}
func (*SubscribeRequest) Descriptor() ([]byte, []int)
Deprecated: Use SubscribeRequest.ProtoReflect.Descriptor instead.
func (x *SubscribeRequest) GetLobbyId() string
func (x *SubscribeRequest) GetPlayerName() string
func (*SubscribeRequest) ProtoMessage()
func (x *SubscribeRequest) ProtoReflect() protoreflect.Message
func (x *SubscribeRequest) Reset()
func (x *SubscribeRequest) String() string
UnimplementedLobbyServiceServer must be embedded to have forward compatible implementations.
NOTE: this should be embedded by value instead of pointer to avoid a nil pointer dereference when methods are called.
type UnimplementedLobbyServiceServer struct{}
func (UnimplementedLobbyServiceServer) CreateLobby(context.Context, *CreateLobbyRequest) (*CreateLobbyResponse, error)
func (UnimplementedLobbyServiceServer) EditPlayer(context.Context, *EditPlayerRequest) (*EditPlayerResponse, error)
func (UnimplementedLobbyServiceServer) JoinLobby(context.Context, *JoinLobbyRequest) (*JoinLobbyResponse, error)
func (UnimplementedLobbyServiceServer) LeaveLobby(context.Context, *LeaveLobbyRequest) (*LeaveLobbyResponse, error)
func (UnimplementedLobbyServiceServer) ReadyPlayer(context.Context, *ReadyPlayerRequest) (*ReadyPlayerResponse, error)
func (UnimplementedLobbyServiceServer) ResumeGame(context.Context, *ResumeGameRequest) (*ResumeGameResponse, error)
func (UnimplementedLobbyServiceServer) SendKeyPress(context.Context, *SendKeyPressRequest) (*SendKeyPressResponse, error)
func (UnimplementedLobbyServiceServer) Subscribe(*SubscribeRequest, grpc.ServerStreamingServer[LobbyEvent]) error
UnsafeLobbyServiceServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to LobbyServiceServer will result in compilation errors.
type UnsafeLobbyServiceServer interface {
// contains filtered or unexported methods
}
import "github.com/sceredi/co-type/server"
Package server exposes the embedded source files of this module so that other packages (e.g. internal/snippet) can use them to generate code snippets at runtime without any external file access.
SourceFiles contains all Go source files of this module, embedded at compile time.
var SourceFiles embed.FS
import "github.com/sceredi/co-type/server/cmd/app"
Package main is the entry point of the server application.
import "github.com/sceredi/co-type/server/internal/app"
Package app provides utilities for setting up the server application
App represents the main application structure for the server, containing everything needed to run the server.
type App struct {
Server *grpc.Server
Conn *grpc.ClientConn
DiscoveryService service.DiscoveryService
// contains filtered or unexported fields
}
func New(cfg *config.Config) (*App, error)
New initializes a new instance of App.
func (a *App) Shutdown()
Shutdown gracefully shuts down the application by stopping the gRPC server and closing the connection.
import "github.com/sceredi/co-type/server/internal/config"
Package config is responsible for setting up the configuration for the server application.
Config holds the configuration settings for the server application.
type Config struct {
Name string
Addr string
Port int
ControlAddr string
ControlPort int
}
func Get() *Config
Get returns the global configuration instance, loading it if it hasn’t been loaded yet.
import "github.com/sceredi/co-type/server/internal/domain"
Package domain contains the domain of the server service.
Lobby represents a game lobby in the server service.
type Lobby struct {
Subs map[string]chan *Lobby
Base *domain.Lobby
// DisconnectedPlayers tracks players who dropped mid-game and are expected to reconnect.
DisconnectedPlayers map[string]bool
}
func NewLobby(id string, firstPlayer *domain.Player) *Lobby
NewLobby creates a new instance of Lobby with the provided ID and first player, and returns it.
import "github.com/sceredi/co-type/server/internal/repository"
Package repository contains the repository layer of the server service.
LobbyRepository defines the interface for managing lobbies.
type LobbyRepository interface {
// Create saves a new lobby to the repository and returns the created lobby or an error if the operation fails.
Create(lobby *domain.Lobby) (*domain.Lobby, error)
// Get retrieves a lobby by its ID from the repository. It returns the lobby if found, or nil if no lobby with the given ID exists.
Get(id string) *domain.Lobby
// Delete removes a lobby by its ID from the repository. It returns an error if the operation fails.
Delete(id string) error
// ListIDs returns all lobby IDs currently stored in the repository.
ListIDs() []string
}
import "github.com/sceredi/co-type/server/internal/service"
Package service contains the service layer of the server service. The service layer is responsible for implementing the business logic of the server service. It defines the interfaces that the handlers will use to interact with the domain models and repositories.
DiscoveryService defines the interface for managing service discovery in the server service.
type DiscoveryService interface {
// Register registers the server with the broker. lobbyIDs is empty on first startup and
// contains the current lobby IDs when re-registering after a broker restart.
Register(name, host string, port int, lobbyIDs []string) error
// RegisterLobby registers a lobby with the service discovery mechanism using the provided lobby ID and server name.
RegisterLobby(lobbyID, serverName string) error
// StartHeartbeat starts a background goroutine that periodically sends heartbeats to the broker.
// On any heartbeat failure it automatically re-registers the server (with current lobby IDs).
// It stops when ctx is cancelled.
StartHeartbeat(ctx context.Context, name, host string, port, load int, lobbyIDs func() []string)
}
func NewDiscoveryService(gtw gateway.ControlGateway) DiscoveryService
NewDiscoveryService creates a new instance of DiscoveryService with the provided ControlGateway and returns it.
LobbyService defines the interface for managing lobbies in the server service.
type LobbyService interface {
Create(id, userName string) (*domain.Lobby, error)
Join(id, userName string) (*domain.Lobby, error)
Leave(id, userName string) error
// PlayerDisconnected marks a player as disconnected mid-game.
PlayerDisconnected(id, userName string) error
EditPlayer(lobbyID, playerName string, isReady bool, allowedCharacters, blockedCharacters string, canDelete bool) (*domain.Lobby, error)
Ready(lobbyID, playerName string) (*domain.Lobby, error)
Get(id string) *domain.Lobby
SendKeyPress(lobbyID, playerName, key string, isBackspace bool) (*domain.Lobby, error)
// ListIDs returns the IDs of all lobbies currently managed by this server.
ListIDs() []string
// ResumeGame restores a crashed game on this server.
ResumeGame(lobby *commondomain.Lobby, playerName string) (*domain.Lobby, error)
}
func NewLobbyService(serverName string, controlGtw gateway.ControlGateway, lobbyRepo repository.LobbyRepository) LobbyService
NewLobbyService creates a new instance of LobbyService with the provided ControlGateway and LobbyRepository and returns it.
import "github.com/sceredi/co-type/server/internal/snippet"
Package snippet provides a helper for generating random code snippets from the server module’s own Go source files.
This file is just here as a way to get code snippets, a non toy implementation would use a service ad hoc.
func Random() string
Random reads a random .go source file (excluding test files) from the embedded server module sources and returns a random window of 10-30 lines.
import "github.com/sceredi/co-type/server/internal/repository/memory"
Package memory provides an in-memory implementation of the repository interfaces.
func NewLobbyRepository() repository.LobbyRepository
NewLobbyRepository creates a new instance of an in-memory LobbyRepository.
import "github.com/sceredi/co-type/server/internal/api/grpc/gateway"
Package gateway provides the implementation for the Gateways to connect gRPC services to the relative service.
ControlGateway defines the interface for managing control operations in the server service.
type ControlGateway interface {
// RegisterServer registers the server with the control service using the provided name, host, port, and
// the list of lobby IDs currently managed by this server (empty on first startup).
RegisterServer(name, host string, port int, lobbyIDs []string) error
RegisterLobby(lobbyID, serverName string) error
UnregisterLobby(lobbyID string) error
// Heartbeat sends a heartbeat to the broker with the server's current load.
Heartbeat(name string, load int) error
}
func NewControlGateway(ctx context.Context, conn control.ControlServiceClient) ControlGateway
NewControlGateway creates a new instance of ControlGateway with the provided gRPC stream and returns it.
import "github.com/sceredi/co-type/server/internal/api/grpc/handler"
Package handler provides the implementation for the gRPC handlers to manage incoming requests and interact with the relative service.
LobbyHandler implements the gRPC server for managing game-related operations, such as creating lobbies and handling game sessions.
type LobbyHandler struct {
lobby.UnimplementedLobbyServiceServer
// contains filtered or unexported fields
}
func NewLobbyHandler(lobbySvc service.LobbyService) *LobbyHandler
NewLobbyHandler creates a new instance of LobbyHandler with the provided LobbyService and returns it.
func (h *LobbyHandler) CreateLobby(_ context.Context, req *lobby.CreateLobbyRequest) (*lobby.CreateLobbyResponse, error)
CreateLobby handles the gRPC request to create a new game lobby.
func (h *LobbyHandler) EditPlayer(_ context.Context, req *lobby.EditPlayerRequest) (*lobby.EditPlayerResponse, error)
EditPlayer handles the gRPC request to edit a player’s settings in a lobby.
func (h *LobbyHandler) JoinLobby(_ context.Context, req *lobby.JoinLobbyRequest) (*lobby.JoinLobbyResponse, error)
JoinLobby handles the gRPC request to join an existing game lobby.
func (h *LobbyHandler) LeaveLobby(_ context.Context, req *lobby.LeaveLobbyRequest) (*lobby.LeaveLobbyResponse, error)
LeaveLobby handles the gRPC request to leave a game lobby.
func (h *LobbyHandler) ReadyPlayer(_ context.Context, req *lobby.ReadyPlayerRequest) (*lobby.ReadyPlayerResponse, error)
ReadyPlayer handles the gRPC request to toggle a player’s ready status in a lobby.
func (h *LobbyHandler) ResumeGame(_ context.Context, req *lobby.ResumeGameRequest) (*lobby.ResumeGameResponse, error)
ResumeGame handles the gRPC request to resume a crashed game on this server.
func (h *LobbyHandler) SendKeyPress(_ context.Context, req *lobby.SendKeyPressRequest) (*lobby.SendKeyPressResponse, error)
SendKeyPress handles the gRPC request to send a key press to the game.
func (h *LobbyHandler) Subscribe(req *lobby.SubscribeRequest, stream lobby.LobbyService_SubscribeServer) error
Subscribe handles the gRPC subscription to lobby events.
Generated by gomarkdoc