More work for introducing a new game handler, also: ratelimiter
This commit is contained in:
parent
58002a1b38
commit
fc088a04fe
@ -1,24 +1,26 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
"mchess_server/api"
|
||||
"mchess_server/chess"
|
||||
lobbies "mchess_server/lobby_registry"
|
||||
"mchess_server/usher"
|
||||
"mchess_server/lobbies"
|
||||
"mchess_server/utils"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"go.uber.org/ratelimit"
|
||||
)
|
||||
|
||||
var mut sync.Mutex
|
||||
var limiter = ratelimit.New(10)
|
||||
|
||||
func HostGameHandler(c *gin.Context) {
|
||||
limiter.Take()
|
||||
|
||||
func HostPrivateGameHandler(c *gin.Context) {
|
||||
player := chess.NewPlayer(uuid.New())
|
||||
u := usher.GetUsher()
|
||||
u := lobbies.GetUsher()
|
||||
|
||||
mut.Lock()
|
||||
defer mut.Unlock()
|
||||
@ -36,6 +38,8 @@ func HostPrivateGameHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
func GetLobbyForPassphraseHandler(c *gin.Context) {
|
||||
limiter.Take()
|
||||
|
||||
reqPassphrase := c.Param("phrase")
|
||||
if reqPassphrase == "" {
|
||||
c.IndentedJSON(http.StatusBadRequest, reqPassphrase)
|
||||
@ -57,34 +61,17 @@ func GetLobbyForPassphraseHandler(c *gin.Context) {
|
||||
c.IndentedJSON(http.StatusOK, lobbyInfo)
|
||||
}
|
||||
|
||||
func RegisterForRandomGame(c *gin.Context) {
|
||||
player := chess.NewPlayer(uuid.New())
|
||||
usher := usher.GetUsher()
|
||||
|
||||
mut.Lock()
|
||||
defer mut.Unlock()
|
||||
lobby := usher.WelcomeNewPlayer(player)
|
||||
usher.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
|
||||
|
||||
info := api.PlayerInfo{
|
||||
PlayerID: &player.Uuid,
|
||||
LobbyID: &lobby.Uuid,
|
||||
}
|
||||
log.Println("responding with info ", info)
|
||||
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
c.IndentedJSON(http.StatusOK, info)
|
||||
}
|
||||
|
||||
// TODO: this will be replaced by the JoinGameHandler()
|
||||
func JoinPrivateGame(c *gin.Context) {
|
||||
limiter.Take()
|
||||
|
||||
req := api.PlayerInfo{}
|
||||
log.Println(c.Request.Body)
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil || req.Passphrase == nil || *req.Passphrase == "" {
|
||||
c.IndentedJSON(http.StatusNotFound, req)
|
||||
}
|
||||
|
||||
u := usher.GetUsher()
|
||||
u := lobbies.GetUsher()
|
||||
|
||||
if req.Passphrase != nil &&
|
||||
*req.Passphrase != "" &&
|
||||
@ -127,8 +114,29 @@ func JoinPrivateGame(c *gin.Context) {
|
||||
c.IndentedJSON(http.StatusOK, info)
|
||||
}
|
||||
|
||||
func JoinGame(c *gin.Context) {
|
||||
gameID := c.Param("id")
|
||||
log.Println(gameID)
|
||||
c.JSON(http.StatusOK, gameID)
|
||||
func JoinGameHandler(c *gin.Context) {
|
||||
limiter.Take()
|
||||
|
||||
id := c.Param("id")
|
||||
idAsUUID, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
c.IndentedJSON(http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
|
||||
passphrase := api.Passphrase{}
|
||||
c.ShouldBindJSON(&passphrase)
|
||||
|
||||
u := lobbies.GetUsher()
|
||||
lobby := u.GetLobbyByID(idAsUUID)
|
||||
if lobby == nil {
|
||||
c.IndentedJSON(http.StatusNotFound, nil)
|
||||
return
|
||||
}
|
||||
|
||||
lobbyInfo := api.LobbyInfo{
|
||||
ID: &lobby.Uuid,
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, lobbyInfo)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ func Test_GetLobbyFromPassphraseHandler(t *testing.T) {
|
||||
t.Run("host a lobby", func(t *testing.T) {
|
||||
r1 := httptest.NewRecorder()
|
||||
ctx1, e1 := gin.CreateTestContext(r1)
|
||||
e1.GET("/api/hostPrivate", HostPrivateGameHandler)
|
||||
e1.GET("/api/hostPrivate", HostGameHandler)
|
||||
hostGameRequest, _ := http.NewRequest("GET", "/api/hostPrivate", nil)
|
||||
ctx1.Request = hostGameRequest
|
||||
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"mchess_server/api"
|
||||
"net/http"
|
||||
|
||||
lobbies "mchess_server/lobby_registry"
|
||||
"mchess_server/lobbies"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
gorillaws "github.com/gorilla/websocket"
|
||||
|
3
go.mod
3
go.mod
@ -9,6 +9,8 @@ require (
|
||||
github.com/stretchr/testify v1.9.0
|
||||
)
|
||||
|
||||
require github.com/benbjohnson/clock v1.3.0 // indirect
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
@ -32,6 +34,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
go.uber.org/ratelimit v0.3.1
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -1,3 +1,5 @@
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
@ -69,6 +71,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0=
|
||||
go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
|
@ -1,58 +0,0 @@
|
||||
package lobby_registry
|
||||
|
||||
import (
|
||||
"mchess_server/chess"
|
||||
"mchess_server/utils"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Lobby struct {
|
||||
Uuid uuid.UUID
|
||||
Game *chess.Game
|
||||
PlayerJoined chan bool
|
||||
Passphrase utils.Passphrase
|
||||
}
|
||||
|
||||
func NewEmptyLobbyWithUUID(uuid uuid.UUID) *Lobby {
|
||||
return &Lobby{
|
||||
Uuid: uuid,
|
||||
Game: chess.NewGame(),
|
||||
PlayerJoined: make(chan bool),
|
||||
}
|
||||
}
|
||||
|
||||
func newEmptyLobbyWithPassphrase() *Lobby {
|
||||
lobby := NewEmptyLobbyWithUUID(uuid.New())
|
||||
lobby.Passphrase = utils.NewPassphrase()
|
||||
|
||||
return lobby
|
||||
}
|
||||
|
||||
func (l *Lobby) AddPlayerAndStartGameIfFull(player *chess.Player) {
|
||||
l.Game.AddPlayersToGame(player)
|
||||
if l.IsFull() {
|
||||
l.Game.StartHandling()
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Lobby) IsFull() bool {
|
||||
return len(w.Game.GetPlayers()) == 2
|
||||
}
|
||||
|
||||
func (l *Lobby) GetPlayerByUUID(uuid uuid.UUID) (*chess.Player, bool) {
|
||||
for _, player := range l.Game.GetPlayers() {
|
||||
if player.Uuid == uuid {
|
||||
return player, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (l *Lobby) GetPlayer1() *chess.Player {
|
||||
return l.Game.GetPlayer1()
|
||||
}
|
||||
|
||||
func (l *Lobby) GetPlayer2() *chess.Player {
|
||||
return l.Game.GetPlayer2()
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package lobby_registry
|
||||
|
||||
import (
|
||||
"mchess_server/utils"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type LobbyRegistry struct {
|
||||
lobbies map[uuid.UUID]*Lobby
|
||||
}
|
||||
|
||||
var instance *LobbyRegistry
|
||||
|
||||
func GetLobbyRegistry() *LobbyRegistry {
|
||||
if instance == nil {
|
||||
instance = newLobbyRegistry()
|
||||
}
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
func newLobbyRegistry() *LobbyRegistry {
|
||||
return &LobbyRegistry{lobbies: make(map[uuid.UUID]*Lobby)}
|
||||
}
|
||||
|
||||
func (r *LobbyRegistry) CreateNewPrivateLobby() *Lobby {
|
||||
lobby := newEmptyLobbyWithPassphrase()
|
||||
r.addNewLobby(lobby)
|
||||
return lobby
|
||||
}
|
||||
|
||||
func (r *LobbyRegistry) GetLobbyForPlayer() *Lobby {
|
||||
for _, lobby := range r.lobbies {
|
||||
if !lobby.IsFull() {
|
||||
return lobby
|
||||
}
|
||||
}
|
||||
|
||||
newLobby := NewEmptyLobbyWithUUID(uuid.New())
|
||||
r.addNewLobby(newLobby)
|
||||
return newLobby
|
||||
}
|
||||
|
||||
func (r *LobbyRegistry) GetLobbyByUUID(uuid uuid.UUID) *Lobby {
|
||||
return r.lobbies[uuid]
|
||||
}
|
||||
|
||||
func (r *LobbyRegistry) GetLobbyByPassphrase(p utils.Passphrase) *Lobby {
|
||||
for _, lobby := range r.lobbies {
|
||||
if lobby.Passphrase == p {
|
||||
return lobby
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *LobbyRegistry) addNewLobby(lobby *Lobby) uuid.UUID {
|
||||
r.lobbies[lobby.Uuid] = lobby
|
||||
return lobby.Uuid
|
||||
}
|
5
main.go
5
main.go
@ -24,14 +24,13 @@ func main() {
|
||||
}
|
||||
|
||||
router := gin.Default()
|
||||
router.GET("/api/random", handler.RegisterForRandomGame)
|
||||
router.GET("/api/hostPrivate", handler.HostPrivateGameHandler)
|
||||
router.GET("/api/hostPrivate", handler.HostGameHandler)
|
||||
router.POST("/api/joinPrivate", handler.JoinPrivateGame)
|
||||
router.GET("/api/ws", websocket.RegisterWebSocketConnection)
|
||||
|
||||
router.GET("/api/getLobbyForPassphrase/:phrase", handler.GetLobbyForPassphraseHandler)
|
||||
router.GET("/api/registerWsForGame/:id", websocket.ConnectWsForGame)
|
||||
router.POST("/api/joinGame/:id", handler.JoinGame)
|
||||
router.POST("/api/joinGame/:id", handler.JoinGameHandler)
|
||||
|
||||
if debugMode {
|
||||
log.Println("Starting service WITHOUT TLS")
|
||||
|
@ -1,45 +0,0 @@
|
||||
package usher
|
||||
|
||||
import (
|
||||
"mchess_server/chess"
|
||||
lobbies "mchess_server/lobby_registry"
|
||||
"mchess_server/utils"
|
||||
)
|
||||
|
||||
type Usher struct {
|
||||
}
|
||||
|
||||
var instance *Usher
|
||||
|
||||
func newUsher() *Usher {
|
||||
return &Usher{}
|
||||
}
|
||||
|
||||
func GetUsher() *Usher {
|
||||
if instance == nil {
|
||||
instance = newUsher()
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
func (u *Usher) WelcomeNewPlayer(player *chess.Player) *lobbies.Lobby {
|
||||
lobby := lobbies.GetLobbyRegistry().GetLobbyForPlayer()
|
||||
return lobby
|
||||
}
|
||||
|
||||
func (u *Usher) CreateNewPrivateLobby(player *chess.Player) *lobbies.Lobby {
|
||||
lobby := lobbies.GetLobbyRegistry().CreateNewPrivateLobby()
|
||||
return lobby
|
||||
}
|
||||
|
||||
func (u *Usher) FindExistingPrivateLobby(p utils.Passphrase) *lobbies.Lobby {
|
||||
lobby := lobbies.GetLobbyRegistry().GetLobbyByPassphrase(p)
|
||||
if lobby == nil || lobby.IsFull() {
|
||||
return nil
|
||||
}
|
||||
return lobby
|
||||
}
|
||||
|
||||
func (u *Usher) AddPlayerToLobbyAndStartGameIfFull(player *chess.Player, lobby *lobbies.Lobby) {
|
||||
lobby.AddPlayerAndStartGameIfFull(player)
|
||||
}
|
Loading…
Reference in New Issue
Block a user