Add solo mode where players survive as long as possible while tracking score (food eaten). Single player games start with a shorter 3-second countdown vs 10 seconds for multiplayer, maintain exactly 1 food item for classic snake feel, and end when the player dies rather than when one player remains. - Add GameMode type (ModeMultiplayer/ModeSinglePlayer) and Score field - Filter single player games from "Join a Game" lobby list - Show "Ready?" and "Score: X" UI for single player mode - Hide invite link for single player games - Preserve game mode on rematch
274 lines
6.3 KiB
Go
274 lines
6.3 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: snake_games.sql
|
|
|
|
package gen
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
)
|
|
|
|
const createSnakeGame = `-- name: CreateSnakeGame :one
|
|
INSERT INTO games (id, board, current_turn, status, game_type, grid_width, grid_height, max_players, game_mode)
|
|
VALUES (?, ?, 0, ?, 'snake', ?, ?, 8, ?)
|
|
RETURNING id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at, rematch_game_id, game_type, grid_width, grid_height, max_players, game_mode, score
|
|
`
|
|
|
|
type CreateSnakeGameParams struct {
|
|
ID string
|
|
Board string
|
|
Status int64
|
|
GridWidth sql.NullInt64
|
|
GridHeight sql.NullInt64
|
|
GameMode int64
|
|
}
|
|
|
|
func (q *Queries) CreateSnakeGame(ctx context.Context, arg CreateSnakeGameParams) (Game, error) {
|
|
row := q.db.QueryRowContext(ctx, createSnakeGame,
|
|
arg.ID,
|
|
arg.Board,
|
|
arg.Status,
|
|
arg.GridWidth,
|
|
arg.GridHeight,
|
|
arg.GameMode,
|
|
)
|
|
var i Game
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Board,
|
|
&i.CurrentTurn,
|
|
&i.Status,
|
|
&i.WinnerUserID,
|
|
&i.WinningCells,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RematchGameID,
|
|
&i.GameType,
|
|
&i.GridWidth,
|
|
&i.GridHeight,
|
|
&i.MaxPlayers,
|
|
&i.GameMode,
|
|
&i.Score,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const createSnakePlayer = `-- name: CreateSnakePlayer :exec
|
|
INSERT INTO game_players (game_id, user_id, guest_player_id, nickname, color, slot)
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
`
|
|
|
|
type CreateSnakePlayerParams struct {
|
|
GameID string
|
|
UserID sql.NullString
|
|
GuestPlayerID sql.NullString
|
|
Nickname string
|
|
Color int64
|
|
Slot int64
|
|
}
|
|
|
|
func (q *Queries) CreateSnakePlayer(ctx context.Context, arg CreateSnakePlayerParams) error {
|
|
_, err := q.db.ExecContext(ctx, createSnakePlayer,
|
|
arg.GameID,
|
|
arg.UserID,
|
|
arg.GuestPlayerID,
|
|
arg.Nickname,
|
|
arg.Color,
|
|
arg.Slot,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const deleteSnakeGame = `-- name: DeleteSnakeGame :exec
|
|
DELETE FROM games WHERE id = ? AND game_type = 'snake'
|
|
`
|
|
|
|
func (q *Queries) DeleteSnakeGame(ctx context.Context, id string) error {
|
|
_, err := q.db.ExecContext(ctx, deleteSnakeGame, id)
|
|
return err
|
|
}
|
|
|
|
const getActiveSnakeGames = `-- name: GetActiveSnakeGames :many
|
|
SELECT id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at, rematch_game_id, game_type, grid_width, grid_height, max_players, game_mode, score FROM games WHERE game_type = 'snake' AND status < 2 AND game_mode = 0
|
|
`
|
|
|
|
func (q *Queries) GetActiveSnakeGames(ctx context.Context) ([]Game, error) {
|
|
rows, err := q.db.QueryContext(ctx, getActiveSnakeGames)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Game
|
|
for rows.Next() {
|
|
var i Game
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Board,
|
|
&i.CurrentTurn,
|
|
&i.Status,
|
|
&i.WinnerUserID,
|
|
&i.WinningCells,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RematchGameID,
|
|
&i.GameType,
|
|
&i.GridWidth,
|
|
&i.GridHeight,
|
|
&i.MaxPlayers,
|
|
&i.GameMode,
|
|
&i.Score,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const getSnakeGame = `-- name: GetSnakeGame :one
|
|
SELECT id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at, rematch_game_id, game_type, grid_width, grid_height, max_players, game_mode, score FROM games WHERE id = ? AND game_type = 'snake'
|
|
`
|
|
|
|
func (q *Queries) GetSnakeGame(ctx context.Context, id string) (Game, error) {
|
|
row := q.db.QueryRowContext(ctx, getSnakeGame, id)
|
|
var i Game
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Board,
|
|
&i.CurrentTurn,
|
|
&i.Status,
|
|
&i.WinnerUserID,
|
|
&i.WinningCells,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RematchGameID,
|
|
&i.GameType,
|
|
&i.GridWidth,
|
|
&i.GridHeight,
|
|
&i.MaxPlayers,
|
|
&i.GameMode,
|
|
&i.Score,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getSnakePlayers = `-- name: GetSnakePlayers :many
|
|
SELECT game_id, user_id, guest_player_id, nickname, color, slot, created_at FROM game_players WHERE game_id = ? ORDER BY slot
|
|
`
|
|
|
|
func (q *Queries) GetSnakePlayers(ctx context.Context, gameID string) ([]GamePlayer, error) {
|
|
rows, err := q.db.QueryContext(ctx, getSnakePlayers, gameID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []GamePlayer
|
|
for rows.Next() {
|
|
var i GamePlayer
|
|
if err := rows.Scan(
|
|
&i.GameID,
|
|
&i.UserID,
|
|
&i.GuestPlayerID,
|
|
&i.Nickname,
|
|
&i.Color,
|
|
&i.Slot,
|
|
&i.CreatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const getUserActiveSnakeGames = `-- name: GetUserActiveSnakeGames :many
|
|
SELECT
|
|
g.id,
|
|
g.status,
|
|
g.grid_width,
|
|
g.grid_height,
|
|
g.updated_at
|
|
FROM games g
|
|
JOIN game_players gp_user ON g.id = gp_user.game_id AND gp_user.user_id = ?
|
|
WHERE g.game_type = 'snake' AND g.status < 3
|
|
ORDER BY g.updated_at DESC
|
|
`
|
|
|
|
type GetUserActiveSnakeGamesRow struct {
|
|
ID string
|
|
Status int64
|
|
GridWidth sql.NullInt64
|
|
GridHeight sql.NullInt64
|
|
UpdatedAt sql.NullTime
|
|
}
|
|
|
|
func (q *Queries) GetUserActiveSnakeGames(ctx context.Context, userID sql.NullString) ([]GetUserActiveSnakeGamesRow, error) {
|
|
rows, err := q.db.QueryContext(ctx, getUserActiveSnakeGames, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []GetUserActiveSnakeGamesRow
|
|
for rows.Next() {
|
|
var i GetUserActiveSnakeGamesRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Status,
|
|
&i.GridWidth,
|
|
&i.GridHeight,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const updateSnakeGame = `-- name: UpdateSnakeGame :exec
|
|
UPDATE games
|
|
SET board = ?, status = ?, winner_user_id = ?, rematch_game_id = ?, score = ?, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ? AND game_type = 'snake'
|
|
`
|
|
|
|
type UpdateSnakeGameParams struct {
|
|
Board string
|
|
Status int64
|
|
WinnerUserID sql.NullString
|
|
RematchGameID sql.NullString
|
|
Score int64
|
|
ID string
|
|
}
|
|
|
|
func (q *Queries) UpdateSnakeGame(ctx context.Context, arg UpdateSnakeGameParams) error {
|
|
_, err := q.db.ExecContext(ctx, updateSnakeGame,
|
|
arg.Board,
|
|
arg.Status,
|
|
arg.WinnerUserID,
|
|
arg.RematchGameID,
|
|
arg.Score,
|
|
arg.ID,
|
|
)
|
|
return err
|
|
}
|