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/components"
|
||||||
"github.com/ryanhamamura/c4/features/c4game/pages"
|
"github.com/ryanhamamura/c4/features/c4game/pages"
|
||||||
"github.com/ryanhamamura/c4/game"
|
"github.com/ryanhamamura/c4/game"
|
||||||
|
"github.com/ryanhamamura/c4/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
playerID := game.PlayerID(sessions.GetString(r.Context(), "player_id"))
|
playerID := player.ID(sessions.GetString(r.Context(), "player_id"))
|
||||||
if playerID == "" {
|
if playerID == "" {
|
||||||
playerID = game.PlayerID(game.GenerateID(8))
|
playerID = player.ID(player.GenerateID(8))
|
||||||
sessions.Put(r.Context(), "player_id", string(playerID))
|
sessions.Put(r.Context(), "player_id", string(playerID))
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := sessions.GetString(r.Context(), "user_id")
|
userID := sessions.GetString(r.Context(), "user_id")
|
||||||
if userID != "" {
|
if userID != "" {
|
||||||
playerID = game.PlayerID(userID)
|
playerID = player.ID(userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
nickname := sessions.GetString(r.Context(), "nickname")
|
nickname := sessions.GetString(r.Context(), "nickname")
|
||||||
@@ -95,10 +96,10 @@ func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.Sessio
|
|||||||
return
|
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")
|
userID := sessions.GetString(r.Context(), "user_id")
|
||||||
if userID != "" {
|
if userID != "" {
|
||||||
playerID = game.PlayerID(userID)
|
playerID = player.ID(userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
myColor := gi.GetPlayerColor(playerID)
|
myColor := gi.GetPlayerColor(playerID)
|
||||||
@@ -185,10 +186,10 @@ func HandleDropPiece(store *game.GameStore, sessions *scs.SessionManager) http.H
|
|||||||
return
|
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")
|
userID := sessions.GetString(r.Context(), "user_id")
|
||||||
if userID != "" {
|
if userID != "" {
|
||||||
playerID = game.PlayerID(userID)
|
playerID = player.ID(userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
myColor := gi.GetPlayerColor(playerID)
|
myColor := gi.GetPlayerColor(playerID)
|
||||||
@@ -229,10 +230,10 @@ func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionM
|
|||||||
return
|
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")
|
userID := sessions.GetString(r.Context(), "user_id")
|
||||||
if userID != "" {
|
if userID != "" {
|
||||||
playerID = game.PlayerID(userID)
|
playerID = player.ID(userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
myColor := gi.GetPlayerColor(playerID)
|
myColor := gi.GetPlayerColor(playerID)
|
||||||
@@ -298,10 +299,10 @@ func HandleSetNickname(store *game.GameStore, sessions *scs.SessionManager) http
|
|||||||
|
|
||||||
sessions.Put(r.Context(), "nickname", signals.Nickname)
|
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")
|
userID := sessions.GetString(r.Context(), "user_id")
|
||||||
if userID != "" {
|
if userID != "" {
|
||||||
playerID = game.PlayerID(userID)
|
playerID = player.ID(userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if gi.GetPlayerColor(playerID) == 0 {
|
if gi.GetPlayerColor(playerID) == 0 {
|
||||||
|
|||||||
@@ -13,21 +13,21 @@ import (
|
|||||||
|
|
||||||
"github.com/ryanhamamura/c4/features/snakegame/components"
|
"github.com/ryanhamamura/c4/features/snakegame/components"
|
||||||
"github.com/ryanhamamura/c4/features/snakegame/pages"
|
"github.com/ryanhamamura/c4/features/snakegame/pages"
|
||||||
"github.com/ryanhamamura/c4/game"
|
"github.com/ryanhamamura/c4/player"
|
||||||
"github.com/ryanhamamura/c4/snake"
|
"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")
|
pid := sessions.GetString(r.Context(), "player_id")
|
||||||
if pid == "" {
|
if pid == "" {
|
||||||
pid = game.GenerateID(8)
|
pid = player.GenerateID(8)
|
||||||
sessions.Put(r.Context(), "player_id", pid)
|
sessions.Put(r.Context(), "player_id", pid)
|
||||||
}
|
}
|
||||||
userID := sessions.GetString(r.Context(), "user_id")
|
userID := sessions.GetString(r.Context(), "user_id")
|
||||||
if userID != "" {
|
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 {
|
func HandleSnakePage(snakeStore *snake.SnakeStore, sessions *scs.SessionManager) http.HandlerFunc {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/ryanhamamura/c4/db/repository"
|
"github.com/ryanhamamura/c4/db/repository"
|
||||||
|
"github.com/ryanhamamura/c4/player"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
@@ -109,19 +110,19 @@ func gameFromRow(row *repository.Game) (*Game, error) {
|
|||||||
func playersFromRows(rows []*repository.GamePlayer) []*Player {
|
func playersFromRows(rows []*repository.GamePlayer) []*Player {
|
||||||
players := make([]*Player, 0, len(rows))
|
players := make([]*Player, 0, len(rows))
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
player := &Player{
|
p := &Player{
|
||||||
Nickname: row.Nickname,
|
Nickname: row.Nickname,
|
||||||
Color: int(row.Color),
|
Color: int(row.Color),
|
||||||
}
|
}
|
||||||
|
|
||||||
if row.UserID != nil {
|
if row.UserID != nil {
|
||||||
player.UserID = row.UserID
|
p.UserID = row.UserID
|
||||||
player.ID = PlayerID(*row.UserID)
|
p.ID = player.ID(*row.UserID)
|
||||||
} else if row.GuestPlayerID != nil {
|
} 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
|
return players
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ package game
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ryanhamamura/c4/db/repository"
|
"github.com/ryanhamamura/c4/db/repository"
|
||||||
|
"github.com/ryanhamamura/c4/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PlayerSession struct {
|
type PlayerSession struct {
|
||||||
@@ -40,7 +39,7 @@ func (gs *GameStore) makeNotify(gameID string) func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gs *GameStore) Create() *GameInstance {
|
func (gs *GameStore) Create() *GameInstance {
|
||||||
id := GenerateID(4)
|
id := player.GenerateID(4)
|
||||||
gi := NewGameInstance(id)
|
gi := NewGameInstance(id)
|
||||||
gi.queries = gs.queries
|
gi.queries = gs.queries
|
||||||
gi.notify = gs.makeNotify(id)
|
gi.notify = gs.makeNotify(id)
|
||||||
@@ -107,12 +106,6 @@ func (gs *GameStore) Delete(id string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateID(size int) string {
|
|
||||||
b := make([]byte, size)
|
|
||||||
_, _ = rand.Read(b)
|
|
||||||
return hex.EncodeToString(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type GameInstance struct {
|
type GameInstance struct {
|
||||||
game *Game
|
game *Game
|
||||||
gameMu sync.RWMutex
|
gameMu sync.RWMutex
|
||||||
@@ -166,7 +159,7 @@ func (gi *GameInstance) GetGame() *Game {
|
|||||||
return gi.game
|
return gi.game
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gi *GameInstance) GetPlayerColor(pid PlayerID) int {
|
func (gi *GameInstance) GetPlayerColor(pid player.ID) int {
|
||||||
gi.gameMu.RLock()
|
gi.gameMu.RLock()
|
||||||
defer gi.gameMu.RUnlock()
|
defer gi.gameMu.RUnlock()
|
||||||
for _, p := range gi.game.Players {
|
for _, p := range gi.game.Players {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import "encoding/json"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
type PlayerID string
|
"github.com/ryanhamamura/c4/player"
|
||||||
|
)
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
ID PlayerID
|
ID player.ID
|
||||||
UserID *string // UUID for authenticated users, nil for guests
|
UserID *string // UUID for authenticated users, nil for guests
|
||||||
Nickname string
|
Nickname string
|
||||||
Color int // 1 = Red, 2 = Yellow
|
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"
|
"context"
|
||||||
|
|
||||||
"github.com/ryanhamamura/c4/db/repository"
|
"github.com/ryanhamamura/c4/db/repository"
|
||||||
|
"github.com/ryanhamamura/c4/player"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
@@ -122,19 +123,19 @@ func snakeGameFromRow(row *repository.Game) (*SnakeGame, error) {
|
|||||||
func snakePlayersFromRows(rows []*repository.GamePlayer) []*Player {
|
func snakePlayersFromRows(rows []*repository.GamePlayer) []*Player {
|
||||||
players := make([]*Player, 0, len(rows))
|
players := make([]*Player, 0, len(rows))
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
player := &Player{
|
p := &Player{
|
||||||
Nickname: row.Nickname,
|
Nickname: row.Nickname,
|
||||||
Slot: int(row.Slot),
|
Slot: int(row.Slot),
|
||||||
}
|
}
|
||||||
|
|
||||||
if row.UserID != nil {
|
if row.UserID != nil {
|
||||||
player.UserID = row.UserID
|
p.UserID = row.UserID
|
||||||
player.ID = PlayerID(*row.UserID)
|
p.ID = player.ID(*row.UserID)
|
||||||
} else if row.GuestPlayerID != nil {
|
} 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
|
return players
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ryanhamamura/c4/db/repository"
|
"github.com/ryanhamamura/c4/db/repository"
|
||||||
"github.com/ryanhamamura/c4/game"
|
"github.com/ryanhamamura/c4/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SnakeStore struct {
|
type SnakeStore struct {
|
||||||
@@ -38,7 +38,7 @@ func (ss *SnakeStore) Create(width, height int, mode GameMode, speed int) *Snake
|
|||||||
if speed <= 0 {
|
if speed <= 0 {
|
||||||
speed = DefaultSpeed
|
speed = DefaultSpeed
|
||||||
}
|
}
|
||||||
id := game.GenerateID(4)
|
id := player.GenerateID(4)
|
||||||
sg := &SnakeGame{
|
sg := &SnakeGame{
|
||||||
ID: id,
|
ID: id,
|
||||||
State: &GameState{
|
State: &GameState{
|
||||||
@@ -172,7 +172,7 @@ func (si *SnakeGameInstance) GetGame() *SnakeGame {
|
|||||||
return si.game.snapshot()
|
return si.game.snapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (si *SnakeGameInstance) GetPlayerSlot(pid PlayerID) int {
|
func (si *SnakeGameInstance) GetPlayerSlot(pid player.ID) int {
|
||||||
si.gameMu.RLock()
|
si.gameMu.RLock()
|
||||||
defer si.gameMu.RUnlock()
|
defer si.gameMu.RUnlock()
|
||||||
for i, p := range si.game.Players {
|
for i, p := range si.game.Players {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package snake
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ryanhamamura/c4/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Direction int
|
type Direction int
|
||||||
@@ -78,10 +80,8 @@ const (
|
|||||||
StatusFinished
|
StatusFinished
|
||||||
)
|
)
|
||||||
|
|
||||||
type PlayerID string
|
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
ID PlayerID
|
ID player.ID
|
||||||
UserID *string
|
UserID *string
|
||||||
Nickname string
|
Nickname string
|
||||||
Slot int // 0-7
|
Slot int // 0-7
|
||||||
|
|||||||
Reference in New Issue
Block a user