Remove com.Uid from the API

This commit is contained in:
sergystepanov 2025-12-24 21:23:19 +03:00
parent baa9bad6f8
commit 059e19d790
15 changed files with 149 additions and 153 deletions

View file

@ -26,27 +26,19 @@ type (
Id interface {
String() string
}
Stateful[T Id] struct {
Id T `json:"id"`
Stateful struct {
Id string `json:"id"`
}
Room struct {
Rid string `json:"room_id"` // room id
Rid string `json:"room_id"`
}
StatefulRoom[T Id] struct {
Stateful[T]
Room
StatefulRoom struct {
Id string `json:"id"`
Rid string `json:"room_id"`
}
PT uint8
)
func State[T Id](id T) Stateful[T] {
return Stateful[T]{Id: id}
}
func StateRoom[T Id](id T, rid string) StatefulRoom[T] {
return StatefulRoom[T]{Stateful: State(id), Room: Room{Rid: rid}}
}
type In[I Id] struct {
Id I `json:"id,omitempty"`
T PT `json:"t"`

View file

@ -1,28 +1,20 @@
package api
type (
ChangePlayerRequest[T Id] struct {
StatefulRoom[T]
ChangePlayerRequest struct {
StatefulRoom
Index int `json:"index"`
}
ChangePlayerResponse int
GameQuitRequest[T Id] struct {
StatefulRoom[T]
}
LoadGameRequest[T Id] struct {
StatefulRoom[T]
}
LoadGameResponse string
ResetGameRequest[T Id] struct {
StatefulRoom[T]
}
ResetGameResponse string
SaveGameRequest[T Id] struct {
StatefulRoom[T]
}
SaveGameResponse string
StartGameRequest[T Id] struct {
StatefulRoom[T]
ChangePlayerResponse int
GameQuitRequest StatefulRoom
LoadGameRequest StatefulRoom
LoadGameResponse string
ResetGameRequest StatefulRoom
ResetGameResponse string
SaveGameRequest StatefulRoom
SaveGameResponse string
StartGameRequest struct {
StatefulRoom
Record bool
RecordUser string
Game string `json:"game"`
@ -42,26 +34,22 @@ type (
Record bool `json:"record"`
KbMouse bool `json:"kb_mouse"`
}
RecordGameRequest[T Id] struct {
StatefulRoom[T]
RecordGameRequest struct {
StatefulRoom
Active bool `json:"active"`
User string `json:"user"`
}
RecordGameResponse string
TerminateSessionRequest[T Id] struct {
Stateful[T]
}
WebrtcAnswerRequest[T Id] struct {
Stateful[T]
RecordGameResponse string
TerminateSessionRequest Stateful
WebrtcAnswerRequest struct {
Stateful
Sdp string `json:"sdp"`
}
WebrtcIceCandidateRequest[T Id] struct {
Stateful[T]
WebrtcIceCandidateRequest struct {
Stateful
Candidate string `json:"candidate"` // Base64-encoded ICE candidate
}
WebrtcInitRequest[T Id] struct {
Stateful[T]
}
WebrtcInitRequest Stateful
WebrtcInitResponse string
AppVideoInfo struct {

View file

@ -2,14 +2,19 @@ package com
import "github.com/giongto35/cloud-game/v3/pkg/logger"
type NetClient[K comparable] interface {
type stringer interface {
comparable
String() string
}
type NetClient[K stringer] interface {
Disconnect()
Id() K
}
type NetMap[K comparable, T NetClient[K]] struct{ Map[K, T] }
type NetMap[K stringer, T NetClient[K]] struct{ Map[K, T] }
func NewNetMap[K comparable, T NetClient[K]]() NetMap[K, T] {
func NewNetMap[K stringer, T NetClient[K]]() NetMap[K, T] {
return NetMap[K, T]{Map: Map[K, T]{m: make(map[K]T, 10)}}
}
@ -19,6 +24,12 @@ func (m *NetMap[K, T]) Remove(client T) { m.Map.Remove(client.Id()) }
func (m *NetMap[K, T]) RemoveL(client T) int { return m.Map.RemoveL(client.Id()) }
func (m *NetMap[K, T]) Reset() { m.Map = Map[K, T]{m: make(map[K]T, 10)} }
func (m *NetMap[K, T]) RemoveDisconnect(client T) { client.Disconnect(); m.Remove(client) }
func (m *NetMap[K, T]) Find(id string) T {
v, _ := m.Map.FindBy(func(v T) bool {
return v.Id().String() == id
})
return v
}
type SocketClient[T ~uint8, P Packet[T], X any, P2 Packet2[X]] struct {
id Uid

View file

@ -29,7 +29,6 @@ func UidFromString(id string) (Uid, error) {
}
func (u Uid) Short() string { return u.String()[:3] + "." + u.String()[len(u.String())-3:] }
func (u Uid) Id() string { return u.String() }
type HasCallId interface {
SetGetId(fmt.Stringer)

View file

@ -39,7 +39,7 @@ func (u *User) Bind(w *Worker) bool {
func (u *User) Disconnect() {
u.Connection.Disconnect()
if u.w != nil {
u.w.TerminateSession(u.Id())
u.w.TerminateSession(u.Id().String())
}
}

View file

@ -5,12 +5,12 @@ import (
"time"
"github.com/giongto35/cloud-game/v3/pkg/api"
"github.com/giongto35/cloud-game/v3/pkg/com"
"github.com/giongto35/cloud-game/v3/pkg/config"
)
func (u *User) HandleWebrtcInit() {
resp, err := u.w.WebrtcInit(u.Id())
uid := u.Id().String()
resp, err := u.w.WebrtcInit(uid)
if err != nil || resp == nil || *resp == api.EMPTY {
u.log.Error().Err(err).Msg("malformed WebRTC init response")
return
@ -19,11 +19,11 @@ func (u *User) HandleWebrtcInit() {
}
func (u *User) HandleWebrtcAnswer(rq api.WebrtcAnswerUserRequest) {
u.w.WebrtcAnswer(u.Id(), string(rq))
u.w.WebrtcAnswer(u.Id().String(), string(rq))
}
func (u *User) HandleWebrtcIceCandidate(rq api.WebrtcUserIceCandidate) {
u.w.WebrtcIceCandidate(u.Id(), string(rq))
u.w.WebrtcIceCandidate(u.Id().String(), string(rq))
}
func (u *User) HandleStartGame(rq api.GameStartUserRequest, conf config.CoordinatorConfig) {
@ -76,7 +76,7 @@ func (u *User) HandleStartGame(rq api.GameStartUserRequest, conf config.Coordina
}
}
startGameResp, err := u.w.StartGame(u.Id(), rq)
startGameResp, err := u.w.StartGame(u.Id().String(), rq)
if err != nil || startGameResp == nil {
u.log.Error().Err(err).Msg("malformed game start response")
return
@ -94,21 +94,21 @@ func (u *User) HandleStartGame(rq api.GameStartUserRequest, conf config.Coordina
}
}
func (u *User) HandleQuitGame(rq api.GameQuitRequest[com.Uid]) {
if rq.Room.Rid == u.w.RoomId {
u.w.QuitGame(u.Id())
func (u *User) HandleQuitGame(rq api.GameQuitRequest) {
if rq.Rid == u.w.RoomId {
u.w.QuitGame(u.Id().String())
}
}
func (u *User) HandleResetGame(rq api.ResetGameRequest[com.Uid]) {
if rq.Room.Rid != u.w.RoomId {
func (u *User) HandleResetGame(rq api.ResetGameRequest) {
if rq.Rid != u.w.RoomId {
return
}
u.w.ResetGame(u.Id())
u.w.ResetGame(u.Id().String())
}
func (u *User) HandleSaveGame() error {
resp, err := u.w.SaveGame(u.Id())
resp, err := u.w.SaveGame(u.Id().String())
if err != nil {
return err
}
@ -124,7 +124,7 @@ func (u *User) HandleSaveGame() error {
}
func (u *User) HandleLoadGame() error {
resp, err := u.w.LoadGame(u.Id())
resp, err := u.w.LoadGame(u.Id().String())
if err != nil {
return err
}
@ -133,7 +133,7 @@ func (u *User) HandleLoadGame() error {
}
func (u *User) HandleChangePlayer(rq api.ChangePlayerUserRequest) {
resp, err := u.w.ChangePlayer(u.Id(), int(rq))
resp, err := u.w.ChangePlayer(u.Id().String(), int(rq))
// !to make it a little less convoluted
if err != nil || resp == nil || *resp == -1 {
u.log.Error().Err(err).Msgf("player select fail, req: %v", rq)
@ -142,7 +142,7 @@ func (u *User) HandleChangePlayer(rq api.ChangePlayerUserRequest) {
u.Notify(api.ChangePlayer, rq)
}
func (u *User) HandleRecordGame(rq api.RecordGameRequest[com.Uid]) {
func (u *User) HandleRecordGame(rq api.RecordGameRequest) {
if u.w == nil {
return
}
@ -154,7 +154,7 @@ func (u *User) HandleRecordGame(rq api.RecordGameRequest[com.Uid]) {
return
}
resp, err := u.w.RecordGame(u.Id(), rq.Active, rq.User)
resp, err := u.w.RecordGame(u.Id().String(), rq.Active, rq.User)
if err != nil {
u.log.Error().Err(err).Msg("malformed game record request")
return

View file

@ -35,7 +35,7 @@ type RegionalClient interface {
}
type HasUserRegistry interface {
Find(com.Uid) *User
Find(id string) *User
}
type AppLibrary interface {
@ -86,7 +86,7 @@ func (w *Worker) HandleRequests(users HasUserRegistry) chan struct{} {
case api.CloseRoom:
err = api.Do(p, w.HandleCloseRoom)
case api.IceCandidate:
err = api.DoE(p, func(d api.WebrtcIceCandidateRequest[com.Uid]) error {
err = api.DoE(p, func(d api.WebrtcIceCandidateRequest) error {
return w.HandleIceCandidate(d, users)
})
case api.LibNewGameList:

View file

@ -1,31 +1,26 @@
package coordinator
import (
"github.com/giongto35/cloud-game/v3/pkg/api"
"github.com/giongto35/cloud-game/v3/pkg/com"
)
import "github.com/giongto35/cloud-game/v3/pkg/api"
func (w *Worker) room(id com.Uid) api.StatefulRoom[com.Uid] {
return api.StateRoom(id, w.RoomId)
}
func (w *Worker) WebrtcInit(id com.Uid) (*api.WebrtcInitResponse, error) {
func (w *Worker) WebrtcInit(id string) (*api.WebrtcInitResponse, error) {
return api.UnwrapChecked[api.WebrtcInitResponse](
w.Send(api.WebrtcInit, api.WebrtcInitRequest[com.Uid]{Stateful: api.State(id)}))
w.Send(api.WebrtcInit, api.WebrtcInitRequest{Id: id}))
}
func (w *Worker) WebrtcAnswer(id com.Uid, sdp string) {
w.Notify(api.WebrtcAnswer, api.WebrtcAnswerRequest[com.Uid]{Stateful: api.State(id), Sdp: sdp})
func (w *Worker) WebrtcAnswer(id string, sdp string) {
w.Notify(api.WebrtcAnswer,
api.WebrtcAnswerRequest{Stateful: api.Stateful{Id: id}, Sdp: sdp})
}
func (w *Worker) WebrtcIceCandidate(id com.Uid, can string) {
w.Notify(api.WebrtcIce, api.WebrtcIceCandidateRequest[com.Uid]{Stateful: api.State(id), Candidate: can})
func (w *Worker) WebrtcIceCandidate(id string, candidate string) {
w.Notify(api.WebrtcIce,
api.WebrtcIceCandidateRequest{Stateful: api.Stateful{Id: id}, Candidate: candidate})
}
func (w *Worker) StartGame(id com.Uid, req api.GameStartUserRequest) (*api.StartGameResponse, error) {
func (w *Worker) StartGame(id string, req api.GameStartUserRequest) (*api.StartGameResponse, error) {
return api.UnwrapChecked[api.StartGameResponse](
w.Send(api.StartGame, api.StartGameRequest[com.Uid]{
StatefulRoom: api.StateRoom(id, req.RoomId),
w.Send(api.StartGame, api.StartGameRequest{
StatefulRoom: api.StatefulRoom{Id: id, Rid: req.RoomId},
Game: req.GameName,
PlayerIndex: req.PlayerIndex,
Record: req.Record,
@ -33,34 +28,41 @@ func (w *Worker) StartGame(id com.Uid, req api.GameStartUserRequest) (*api.Start
}))
}
func (w *Worker) QuitGame(id com.Uid) {
w.Notify(api.QuitGame, api.GameQuitRequest[com.Uid]{StatefulRoom: w.room(id)})
func (w *Worker) QuitGame(id string) {
w.Notify(api.QuitGame, api.GameQuitRequest{Id: id, Rid: w.RoomId})
}
func (w *Worker) SaveGame(id com.Uid) (*api.SaveGameResponse, error) {
func (w *Worker) SaveGame(id string) (*api.SaveGameResponse, error) {
return api.UnwrapChecked[api.SaveGameResponse](
w.Send(api.SaveGame, api.SaveGameRequest[com.Uid]{StatefulRoom: w.room(id)}))
w.Send(api.SaveGame, api.SaveGameRequest{Id: id, Rid: w.RoomId}))
}
func (w *Worker) LoadGame(id com.Uid) (*api.LoadGameResponse, error) {
func (w *Worker) LoadGame(id string) (*api.LoadGameResponse, error) {
return api.UnwrapChecked[api.LoadGameResponse](
w.Send(api.LoadGame, api.LoadGameRequest[com.Uid]{StatefulRoom: w.room(id)}))
w.Send(api.LoadGame, api.LoadGameRequest{Id: id, Rid: w.RoomId}))
}
func (w *Worker) ChangePlayer(id com.Uid, index int) (*api.ChangePlayerResponse, error) {
func (w *Worker) ChangePlayer(id string, index int) (*api.ChangePlayerResponse, error) {
return api.UnwrapChecked[api.ChangePlayerResponse](
w.Send(api.ChangePlayer, api.ChangePlayerRequest[com.Uid]{StatefulRoom: w.room(id), Index: index}))
w.Send(api.ChangePlayer, api.ChangePlayerRequest{
StatefulRoom: api.StatefulRoom{Id: id, Rid: w.RoomId},
Index: index,
}))
}
func (w *Worker) ResetGame(id com.Uid) {
w.Notify(api.ResetGame, api.ResetGameRequest[com.Uid]{StatefulRoom: w.room(id)})
func (w *Worker) ResetGame(id string) {
w.Notify(api.ResetGame, api.ResetGameRequest{Id: id, Rid: w.RoomId})
}
func (w *Worker) RecordGame(id com.Uid, rec bool, recUser string) (*api.RecordGameResponse, error) {
func (w *Worker) RecordGame(id string, rec bool, recUser string) (*api.RecordGameResponse, error) {
return api.UnwrapChecked[api.RecordGameResponse](
w.Send(api.RecordGame, api.RecordGameRequest[com.Uid]{StatefulRoom: w.room(id), Active: rec, User: recUser}))
w.Send(api.RecordGame, api.RecordGameRequest{
StatefulRoom: api.StatefulRoom{Id: id, Rid: w.RoomId},
Active: rec,
User: recUser,
}))
}
func (w *Worker) TerminateSession(id com.Uid) {
_, _ = w.Send(api.TerminateSession, api.TerminateSessionRequest[com.Uid]{Stateful: api.State(id)})
func (w *Worker) TerminateSession(id string) {
_, _ = w.Send(api.TerminateSession, api.TerminateSessionRequest{Id: id})
}

View file

@ -1,9 +1,6 @@
package coordinator
import (
"github.com/giongto35/cloud-game/v3/pkg/api"
"github.com/giongto35/cloud-game/v3/pkg/com"
)
import "github.com/giongto35/cloud-game/v3/pkg/api"
func (w *Worker) HandleRegisterRoom(rq api.RegisterRoomRequest) { w.RoomId = string(rq) }
@ -14,11 +11,11 @@ func (w *Worker) HandleCloseRoom(rq api.CloseRoomRequest) {
}
}
func (w *Worker) HandleIceCandidate(rq api.WebrtcIceCandidateRequest[com.Uid], users HasUserRegistry) error {
func (w *Worker) HandleIceCandidate(rq api.WebrtcIceCandidateRequest, users HasUserRegistry) error {
if usr := users.Find(rq.Id); usr != nil {
usr.SendWebrtcIceCandidate(rq.Candidate)
} else {
w.log.Warn().Str("id", rq.Id.String()).Msg("unknown session")
w.log.Warn().Str("id", rq.Id).Msg("unknown session")
}
return nil
}

View file

@ -73,27 +73,27 @@ func (c *coordinator) HandleRequests(w *Worker) chan struct{} {
switch x.T {
case api.WebrtcInit:
err = api.Do(x, func(d api.WebrtcInitRequest[com.Uid]) { out = c.HandleWebrtcInit(d, w, ap) })
err = api.Do(x, func(d api.WebrtcInitRequest) { out = c.HandleWebrtcInit(d, w, ap) })
case api.StartGame:
err = api.Do(x, func(d api.StartGameRequest[com.Uid]) { out = c.HandleGameStart(d, w) })
err = api.Do(x, func(d api.StartGameRequest) { out = c.HandleGameStart(d, w) })
case api.SaveGame:
err = api.Do(x, func(d api.SaveGameRequest[com.Uid]) { out = c.HandleSaveGame(d, w) })
err = api.Do(x, func(d api.SaveGameRequest) { out = c.HandleSaveGame(d, w) })
case api.LoadGame:
err = api.Do(x, func(d api.LoadGameRequest[com.Uid]) { out = c.HandleLoadGame(d, w) })
err = api.Do(x, func(d api.LoadGameRequest) { out = c.HandleLoadGame(d, w) })
case api.ChangePlayer:
err = api.Do(x, func(d api.ChangePlayerRequest[com.Uid]) { out = c.HandleChangePlayer(d, w) })
err = api.Do(x, func(d api.ChangePlayerRequest) { out = c.HandleChangePlayer(d, w) })
case api.RecordGame:
err = api.Do(x, func(d api.RecordGameRequest[com.Uid]) { out = c.HandleRecordGame(d, w) })
err = api.Do(x, func(d api.RecordGameRequest) { out = c.HandleRecordGame(d, w) })
case api.WebrtcAnswer:
err = api.Do(x, func(d api.WebrtcAnswerRequest[com.Uid]) { c.HandleWebrtcAnswer(d, w) })
err = api.Do(x, func(d api.WebrtcAnswerRequest) { c.HandleWebrtcAnswer(d, w) })
case api.WebrtcIce:
err = api.Do(x, func(d api.WebrtcIceCandidateRequest[com.Uid]) { c.HandleWebrtcIceCandidate(d, w) })
err = api.Do(x, func(d api.WebrtcIceCandidateRequest) { c.HandleWebrtcIceCandidate(d, w) })
case api.TerminateSession:
err = api.Do(x, func(d api.TerminateSessionRequest[com.Uid]) { c.HandleTerminateSession(d, w) })
err = api.Do(x, func(d api.TerminateSessionRequest) { c.HandleTerminateSession(d, w) })
case api.QuitGame:
err = api.Do(x, func(d api.GameQuitRequest[com.Uid]) { c.HandleQuitGame(d, w) })
err = api.Do(x, func(d api.GameQuitRequest) { c.HandleQuitGame(d, w) })
case api.ResetGame:
err = api.Do(x, func(d api.ResetGameRequest[com.Uid]) { c.HandleResetGame(d, w) })
err = api.Do(x, func(d api.ResetGameRequest) { c.HandleResetGame(d, w) })
default:
c.log.Warn().Msgf("unhandled packet type %v", x.T)
}
@ -109,8 +109,11 @@ func (c *coordinator) RegisterRoom(id string) { c.Notify(api.RegisterRoom, id) }
// CloseRoom sends a signal to coordinator which will remove that room from its list.
func (c *coordinator) CloseRoom(id string) { c.Notify(api.CloseRoom, id) }
func (c *coordinator) IceCandidate(candidate string, sessionId com.Uid) {
c.Notify(api.WebrtcIce, api.WebrtcIceCandidateRequest[com.Uid]{Stateful: api.Stateful[com.Uid]{Id: sessionId}, Candidate: candidate})
func (c *coordinator) IceCandidate(candidate string, sessionId string) {
c.Notify(api.WebrtcIce, api.WebrtcIceCandidateRequest{
Stateful: api.Stateful{Id: sessionId},
Candidate: candidate,
})
}
func (c *coordinator) SendLibrary(w *Worker) {

View file

@ -28,7 +28,7 @@ func buildConnQuery(id com.Uid, conf config.Worker, address string) (string, err
})
}
func (c *coordinator) HandleWebrtcInit(rq api.WebrtcInitRequest[com.Uid], w *Worker, factory *webrtc.ApiFactory) api.Out {
func (c *coordinator) HandleWebrtcInit(rq api.WebrtcInitRequest, w *Worker, factory *webrtc.ApiFactory) api.Out {
peer := webrtc.New(c.log, factory)
localSDP, err := peer.NewCall(w.conf.Encoder.Video.Codec, "opus", func(data any) {
candidate, err := toBase64Json(data)
@ -55,7 +55,7 @@ func (c *coordinator) HandleWebrtcInit(rq api.WebrtcInitRequest[com.Uid], w *Wor
return api.Out{Payload: sdp}
}
func (c *coordinator) HandleWebrtcAnswer(rq api.WebrtcAnswerRequest[com.Uid], w *Worker) {
func (c *coordinator) HandleWebrtcAnswer(rq api.WebrtcAnswerRequest, w *Worker) {
if user := w.router.FindUser(rq.Id); user != nil {
if err := room.WithWebRTC(user.Session).SetRemoteSDP(rq.Sdp, fromBase64Json); err != nil {
c.log.Error().Err(err).Msgf("cannot set remote SDP of client [%v]", rq.Id)
@ -63,7 +63,7 @@ func (c *coordinator) HandleWebrtcAnswer(rq api.WebrtcAnswerRequest[com.Uid], w
}
}
func (c *coordinator) HandleWebrtcIceCandidate(rs api.WebrtcIceCandidateRequest[com.Uid], w *Worker) {
func (c *coordinator) HandleWebrtcIceCandidate(rs api.WebrtcIceCandidateRequest, w *Worker) {
if user := w.router.FindUser(rs.Id); user != nil {
if err := room.WithWebRTC(user.Session).AddCandidate(rs.Candidate, fromBase64Json); err != nil {
c.log.Error().Err(err).Msgf("cannot add ICE candidate of the client [%v]", rs.Id)
@ -71,7 +71,7 @@ func (c *coordinator) HandleWebrtcIceCandidate(rs api.WebrtcIceCandidateRequest[
}
}
func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worker) api.Out {
func (c *coordinator) HandleGameStart(rq api.StartGameRequest, w *Worker) api.Out {
user := w.router.FindUser(rq.Id)
if user == nil {
c.log.Error().Msgf("no user [%v]", rq.Id)
@ -79,14 +79,14 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
}
user.Index = rq.PlayerIndex
r := w.router.FindRoom(rq.Room.Rid)
r := w.router.FindRoom(rq.Rid)
// +injects game data into the original game request
// the name of the game either in the `room id` field or
// it's in the initial request
gameName := rq.Game
if rq.Room.Rid != "" {
name := w.launcher.ExtractAppNameFromUrl(rq.Room.Rid)
if rq.Rid != "" {
name := w.launcher.ExtractAppNameFromUrl(rq.Rid)
if name == "" {
c.log.Warn().Msg("couldn't decode game name from the room id")
return api.EmptyPacket
@ -101,7 +101,7 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
}
if r == nil { // new room
uid := rq.Room.Rid
uid := rq.Rid
if uid == "" {
uid = games.GenerateRoomID(gameName)
}
@ -218,7 +218,7 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
}
// HandleTerminateSession handles cases when a user has been disconnected from the websocket of coordinator.
func (c *coordinator) HandleTerminateSession(rq api.TerminateSessionRequest[com.Uid], w *Worker) {
func (c *coordinator) HandleTerminateSession(rq api.TerminateSessionRequest, w *Worker) {
if user := w.router.FindUser(rq.Id); user != nil {
w.router.Remove(user)
c.log.Debug().Msgf(">>> users: %v", w.router.Users())
@ -227,14 +227,14 @@ func (c *coordinator) HandleTerminateSession(rq api.TerminateSessionRequest[com.
}
// HandleQuitGame handles cases when a user manually exits the game.
func (c *coordinator) HandleQuitGame(rq api.GameQuitRequest[com.Uid], w *Worker) {
func (c *coordinator) HandleQuitGame(rq api.GameQuitRequest, w *Worker) {
if user := w.router.FindUser(rq.Id); user != nil {
w.router.Remove(user)
c.log.Debug().Msgf(">>> users: %v", w.router.Users())
}
}
func (c *coordinator) HandleResetGame(rq api.ResetGameRequest[com.Uid], w *Worker) api.Out {
func (c *coordinator) HandleResetGame(rq api.ResetGameRequest, w *Worker) api.Out {
if r := w.router.FindRoom(rq.Rid); r != nil {
room.WithEmulator(r.App()).Reset()
return api.OkPacket
@ -242,7 +242,7 @@ func (c *coordinator) HandleResetGame(rq api.ResetGameRequest[com.Uid], w *Worke
return api.ErrPacket
}
func (c *coordinator) HandleSaveGame(rq api.SaveGameRequest[com.Uid], w *Worker) api.Out {
func (c *coordinator) HandleSaveGame(rq api.SaveGameRequest, w *Worker) api.Out {
r := w.router.FindRoom(rq.Rid)
if r == nil {
return api.ErrPacket
@ -254,7 +254,7 @@ func (c *coordinator) HandleSaveGame(rq api.SaveGameRequest[com.Uid], w *Worker)
return api.OkPacket
}
func (c *coordinator) HandleLoadGame(rq api.LoadGameRequest[com.Uid], w *Worker) api.Out {
func (c *coordinator) HandleLoadGame(rq api.LoadGameRequest, w *Worker) api.Out {
r := w.router.FindRoom(rq.Rid)
if r == nil {
return api.ErrPacket
@ -266,7 +266,7 @@ func (c *coordinator) HandleLoadGame(rq api.LoadGameRequest[com.Uid], w *Worker)
return api.OkPacket
}
func (c *coordinator) HandleChangePlayer(rq api.ChangePlayerRequest[com.Uid], w *Worker) api.Out {
func (c *coordinator) HandleChangePlayer(rq api.ChangePlayerRequest, w *Worker) api.Out {
user := w.router.FindUser(rq.Id)
if user == nil || w.router.FindRoom(rq.Rid) == nil {
return api.Out{Payload: -1} // semi-predicates
@ -276,7 +276,7 @@ func (c *coordinator) HandleChangePlayer(rq api.ChangePlayerRequest[com.Uid], w
return api.Out{Payload: rq.Index}
}
func (c *coordinator) HandleRecordGame(rq api.RecordGameRequest[com.Uid], w *Worker) api.Out {
func (c *coordinator) HandleRecordGame(rq api.RecordGameRequest, w *Worker) api.Out {
if !w.conf.Recording.Enabled {
return api.ErrPacket
}

View file

@ -11,7 +11,7 @@ type GameRouter struct {
}
func NewGameRouter() *GameRouter {
u := com.NewNetMap[string, *GameSession]()
u := com.NewNetMap[SessionKey, *GameSession]()
return &GameRouter{Router: Router[*GameSession]{users: &u}}
}

View file

@ -41,9 +41,10 @@ type Session interface {
SendData([]byte)
}
type Uid interface {
Id() string
}
type SessionKey string
func (s SessionKey) String() string { return string(s) }
func (s SessionKey) Id() string { return s.String() }
type Room[T Session] struct {
app app.App
@ -137,7 +138,7 @@ func (r *Router[T]) Remove(user T) {
func (r *Router[T]) AddUser(user T) { r.users.Add(user) }
func (r *Router[T]) Close() { r.mu.Lock(); r.room.Close(); r.room = nil; r.mu.Unlock() }
func (r *Router[T]) FindUser(uid Uid) T { return r.users.Find(uid.Id()) }
func (r *Router[T]) FindUser(uid string) T { return r.users.Find(uid) }
func (r *Router[T]) Room() *Room[T] { r.mu.Lock(); defer r.mu.Unlock(); return r.room }
func (r *Router[T]) SetRoom(room *Room[T]) { r.mu.Lock(); r.room = room; r.mu.Unlock() }
func (r *Router[T]) HasRoom() bool { r.mu.Lock(); defer r.mu.Unlock(); return r.room != nil }
@ -156,18 +157,17 @@ func (r *Router[T]) Reset() {
}
type AppSession struct {
Uid
Session
uid string
uid SessionKey
}
func (p AppSession) Id() string { return p.uid }
func (p AppSession) Id() SessionKey { return p.uid }
type GameSession struct {
AppSession
Index int // track user Index (i.e. player 1,2,3,4 select)
}
func NewGameSession(id Uid, s Session) *GameSession {
return &GameSession{AppSession: AppSession{uid: id.Id(), Session: s}}
func NewGameSession(id string, s Session) *GameSession {
return &GameSession{AppSession: AppSession{uid: SessionKey(id), Session: s}}
}

View file

@ -236,7 +236,7 @@ func room(cfg conf) testRoom {
l.Fatal().Err(err).Msgf("no init")
}
room := NewRoom[*GameSession](id, emu, &com.NetMap[string, *GameSession]{}, m)
room := NewRoom[*GameSession](id, emu, &com.NetMap[SessionKey, *GameSession]{}, m)
if cfg.autoAppStart {
room.StartApp()
}

View file

@ -6,8 +6,12 @@ import (
"github.com/giongto35/cloud-game/v3/pkg/com"
)
type sKey string
func (s sKey) String() string { return string(s) }
type tSession struct {
id string
id sKey
connected bool
}
@ -16,15 +20,15 @@ func (t *tSession) SendVideo([]byte, int32) {}
func (t *tSession) SendData([]byte) {}
func (t *tSession) Connect() { t.connected = true }
func (t *tSession) Disconnect() { t.connected = false }
func (t *tSession) Id() string { return t.id }
func (t *tSession) Id() sKey { return t.id }
type lookMap struct {
com.NetMap[string, *tSession]
prev com.NetMap[string, *tSession] // we could use pointers in the original :3
com.NetMap[sKey, *tSession]
prev com.NetMap[sKey, *tSession] // we could use pointers in the original :3
}
func (l *lookMap) Reset() {
l.prev = com.NewNetMap[string, *tSession]()
l.prev = com.NewNetMap[sKey, *tSession]()
for s := range l.Map.Values() {
l.prev.Add(s)
}
@ -51,7 +55,7 @@ func TestRouter(t *testing.T) {
}
func TestRouterReset(t *testing.T) {
u := lookMap{NetMap: com.NewNetMap[string, *tSession]()}
u := lookMap{NetMap: com.NewNetMap[sKey, *tSession]()}
router := Router[*tSession]{users: &u}
router.AddUser(&tSession{id: "1", connected: true})
@ -73,6 +77,6 @@ func TestRouterReset(t *testing.T) {
}
func newTestRouter() *Router[*tSession] {
u := com.NewNetMap[string, *tSession]()
u := com.NewNetMap[sKey, *tSession]()
return &Router[*tSession]{users: &u}
}