refactor: extract shared player.ID type and GenerateID to player package
Both game and snake packages had identical PlayerID types and the snake package imported game.GenerateID. Now both use player.ID and player.GenerateID from the shared player package.
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/ryanhamamura/c4/features/c4game/components"
|
||||
"github.com/ryanhamamura/c4/features/c4game/pages"
|
||||
"github.com/ryanhamamura/c4/game"
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
)
|
||||
|
||||
func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
|
||||
@@ -30,15 +31,15 @@ func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, queries
|
||||
return
|
||||
}
|
||||
|
||||
playerID := game.PlayerID(sessions.GetString(r.Context(), "player_id"))
|
||||
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
|
||||
if playerID == "" {
|
||||
playerID = game.PlayerID(game.GenerateID(8))
|
||||
playerID = player.ID(player.GenerateID(8))
|
||||
sessions.Put(r.Context(), "player_id", string(playerID))
|
||||
}
|
||||
|
||||
userID := sessions.GetString(r.Context(), "user_id")
|
||||
if userID != "" {
|
||||
playerID = game.PlayerID(userID)
|
||||
playerID = player.ID(userID)
|
||||
}
|
||||
|
||||
nickname := sessions.GetString(r.Context(), "nickname")
|
||||
@@ -95,10 +96,10 @@ func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.Sessio
|
||||
return
|
||||
}
|
||||
|
||||
playerID := game.PlayerID(sessions.GetString(r.Context(), "player_id"))
|
||||
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
|
||||
userID := sessions.GetString(r.Context(), "user_id")
|
||||
if userID != "" {
|
||||
playerID = game.PlayerID(userID)
|
||||
playerID = player.ID(userID)
|
||||
}
|
||||
|
||||
myColor := gi.GetPlayerColor(playerID)
|
||||
@@ -185,10 +186,10 @@ func HandleDropPiece(store *game.GameStore, sessions *scs.SessionManager) http.H
|
||||
return
|
||||
}
|
||||
|
||||
playerID := game.PlayerID(sessions.GetString(r.Context(), "player_id"))
|
||||
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
|
||||
userID := sessions.GetString(r.Context(), "user_id")
|
||||
if userID != "" {
|
||||
playerID = game.PlayerID(userID)
|
||||
playerID = player.ID(userID)
|
||||
}
|
||||
|
||||
myColor := gi.GetPlayerColor(playerID)
|
||||
@@ -229,10 +230,10 @@ func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionM
|
||||
return
|
||||
}
|
||||
|
||||
playerID := game.PlayerID(sessions.GetString(r.Context(), "player_id"))
|
||||
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
|
||||
userID := sessions.GetString(r.Context(), "user_id")
|
||||
if userID != "" {
|
||||
playerID = game.PlayerID(userID)
|
||||
playerID = player.ID(userID)
|
||||
}
|
||||
|
||||
myColor := gi.GetPlayerColor(playerID)
|
||||
@@ -298,10 +299,10 @@ func HandleSetNickname(store *game.GameStore, sessions *scs.SessionManager) http
|
||||
|
||||
sessions.Put(r.Context(), "nickname", signals.Nickname)
|
||||
|
||||
playerID := game.PlayerID(sessions.GetString(r.Context(), "player_id"))
|
||||
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
|
||||
userID := sessions.GetString(r.Context(), "user_id")
|
||||
if userID != "" {
|
||||
playerID = game.PlayerID(userID)
|
||||
playerID = player.ID(userID)
|
||||
}
|
||||
|
||||
if gi.GetPlayerColor(playerID) == 0 {
|
||||
|
||||
@@ -13,21 +13,21 @@ import (
|
||||
|
||||
"github.com/ryanhamamura/c4/features/snakegame/components"
|
||||
"github.com/ryanhamamura/c4/features/snakegame/pages"
|
||||
"github.com/ryanhamamura/c4/game"
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
"github.com/ryanhamamura/c4/snake"
|
||||
)
|
||||
|
||||
func getPlayerID(sessions *scs.SessionManager, r *http.Request) snake.PlayerID {
|
||||
func getPlayerID(sessions *scs.SessionManager, r *http.Request) player.ID {
|
||||
pid := sessions.GetString(r.Context(), "player_id")
|
||||
if pid == "" {
|
||||
pid = game.GenerateID(8)
|
||||
pid = player.GenerateID(8)
|
||||
sessions.Put(r.Context(), "player_id", pid)
|
||||
}
|
||||
userID := sessions.GetString(r.Context(), "user_id")
|
||||
if userID != "" {
|
||||
return snake.PlayerID(userID)
|
||||
return player.ID(userID)
|
||||
}
|
||||
return snake.PlayerID(pid)
|
||||
return player.ID(pid)
|
||||
}
|
||||
|
||||
func HandleSnakePage(snakeStore *snake.SnakeStore, sessions *scs.SessionManager) http.HandlerFunc {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/ryanhamamura/c4/db/repository"
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
@@ -109,19 +110,19 @@ func gameFromRow(row *repository.Game) (*Game, error) {
|
||||
func playersFromRows(rows []*repository.GamePlayer) []*Player {
|
||||
players := make([]*Player, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
player := &Player{
|
||||
p := &Player{
|
||||
Nickname: row.Nickname,
|
||||
Color: int(row.Color),
|
||||
}
|
||||
|
||||
if row.UserID != nil {
|
||||
player.UserID = row.UserID
|
||||
player.ID = PlayerID(*row.UserID)
|
||||
p.UserID = row.UserID
|
||||
p.ID = player.ID(*row.UserID)
|
||||
} else if row.GuestPlayerID != nil {
|
||||
player.ID = PlayerID(*row.GuestPlayerID)
|
||||
p.ID = player.ID(*row.GuestPlayerID)
|
||||
}
|
||||
|
||||
players = append(players, player)
|
||||
players = append(players, p)
|
||||
}
|
||||
return players
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ package game
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"sync"
|
||||
|
||||
"github.com/ryanhamamura/c4/db/repository"
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
)
|
||||
|
||||
type PlayerSession struct {
|
||||
@@ -40,7 +39,7 @@ func (gs *GameStore) makeNotify(gameID string) func() {
|
||||
}
|
||||
|
||||
func (gs *GameStore) Create() *GameInstance {
|
||||
id := GenerateID(4)
|
||||
id := player.GenerateID(4)
|
||||
gi := NewGameInstance(id)
|
||||
gi.queries = gs.queries
|
||||
gi.notify = gs.makeNotify(id)
|
||||
@@ -107,12 +106,6 @@ func (gs *GameStore) Delete(id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateID(size int) string {
|
||||
b := make([]byte, size)
|
||||
_, _ = rand.Read(b)
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
type GameInstance struct {
|
||||
game *Game
|
||||
gameMu sync.RWMutex
|
||||
@@ -166,7 +159,7 @@ func (gi *GameInstance) GetGame() *Game {
|
||||
return gi.game
|
||||
}
|
||||
|
||||
func (gi *GameInstance) GetPlayerColor(pid PlayerID) int {
|
||||
func (gi *GameInstance) GetPlayerColor(pid player.ID) int {
|
||||
gi.gameMu.RLock()
|
||||
defer gi.gameMu.RUnlock()
|
||||
for _, p := range gi.game.Players {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package game
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
type PlayerID string
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
)
|
||||
|
||||
type Player struct {
|
||||
ID PlayerID
|
||||
ID player.ID
|
||||
UserID *string // UUID for authenticated users, nil for guests
|
||||
Nickname string
|
||||
Color int // 1 = Red, 2 = Yellow
|
||||
|
||||
18
player/player.go
Normal file
18
player/player.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Package player provides shared identity types used across game packages.
|
||||
package player
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// ID uniquely identifies a player within a session. For authenticated users
|
||||
// this is their user UUID; for guests it's a random hex string.
|
||||
type ID string
|
||||
|
||||
// GenerateID returns a random hex string of 2*size characters.
|
||||
func GenerateID(size int) string {
|
||||
b := make([]byte, size)
|
||||
_, _ = rand.Read(b)
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/ryanhamamura/c4/db/repository"
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
@@ -122,19 +123,19 @@ func snakeGameFromRow(row *repository.Game) (*SnakeGame, error) {
|
||||
func snakePlayersFromRows(rows []*repository.GamePlayer) []*Player {
|
||||
players := make([]*Player, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
player := &Player{
|
||||
p := &Player{
|
||||
Nickname: row.Nickname,
|
||||
Slot: int(row.Slot),
|
||||
}
|
||||
|
||||
if row.UserID != nil {
|
||||
player.UserID = row.UserID
|
||||
player.ID = PlayerID(*row.UserID)
|
||||
p.UserID = row.UserID
|
||||
p.ID = player.ID(*row.UserID)
|
||||
} else if row.GuestPlayerID != nil {
|
||||
player.ID = PlayerID(*row.GuestPlayerID)
|
||||
p.ID = player.ID(*row.GuestPlayerID)
|
||||
}
|
||||
|
||||
players = append(players, player)
|
||||
players = append(players, p)
|
||||
}
|
||||
return players
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/ryanhamamura/c4/db/repository"
|
||||
"github.com/ryanhamamura/c4/game"
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
)
|
||||
|
||||
type SnakeStore struct {
|
||||
@@ -38,7 +38,7 @@ func (ss *SnakeStore) Create(width, height int, mode GameMode, speed int) *Snake
|
||||
if speed <= 0 {
|
||||
speed = DefaultSpeed
|
||||
}
|
||||
id := game.GenerateID(4)
|
||||
id := player.GenerateID(4)
|
||||
sg := &SnakeGame{
|
||||
ID: id,
|
||||
State: &GameState{
|
||||
@@ -172,7 +172,7 @@ func (si *SnakeGameInstance) GetGame() *SnakeGame {
|
||||
return si.game.snapshot()
|
||||
}
|
||||
|
||||
func (si *SnakeGameInstance) GetPlayerSlot(pid PlayerID) int {
|
||||
func (si *SnakeGameInstance) GetPlayerSlot(pid player.ID) int {
|
||||
si.gameMu.RLock()
|
||||
defer si.gameMu.RUnlock()
|
||||
for i, p := range si.game.Players {
|
||||
|
||||
@@ -3,6 +3,8 @@ package snake
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/ryanhamamura/c4/player"
|
||||
)
|
||||
|
||||
type Direction int
|
||||
@@ -78,10 +80,8 @@ const (
|
||||
StatusFinished
|
||||
)
|
||||
|
||||
type PlayerID string
|
||||
|
||||
type Player struct {
|
||||
ID PlayerID
|
||||
ID player.ID
|
||||
UserID *string
|
||||
Nickname string
|
||||
Slot int // 0-7
|
||||
|
||||
Reference in New Issue
Block a user