From 059e19d7903c29ce14a41a795ea8f2d57c8998ee Mon Sep 17 00:00:00 2001 From: sergystepanov Date: Wed, 24 Dec 2025 21:23:19 +0300 Subject: [PATCH] Remove com.Uid from the API --- pkg/api/api.go | 20 +++------- pkg/api/worker.go | 54 ++++++++++---------------- pkg/com/com.go | 17 ++++++-- pkg/com/net.go | 1 - pkg/coordinator/user.go | 2 +- pkg/coordinator/userhandlers.go | 32 ++++++++-------- pkg/coordinator/worker.go | 4 +- pkg/coordinator/workerapi.go | 64 ++++++++++++++++--------------- pkg/coordinator/workerhandlers.go | 9 ++--- pkg/worker/coordinator.go | 29 +++++++------- pkg/worker/coordinatorhandlers.go | 30 +++++++-------- pkg/worker/room/cast.go | 2 +- pkg/worker/room/room.go | 18 ++++----- pkg/worker/room/room_test.go | 2 +- pkg/worker/room/router_test.go | 18 +++++---- 15 files changed, 149 insertions(+), 153 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 93fedb17..6605a188 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -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"` diff --git a/pkg/api/worker.go b/pkg/api/worker.go index 189daf66..c498009d 100644 --- a/pkg/api/worker.go +++ b/pkg/api/worker.go @@ -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 { diff --git a/pkg/com/com.go b/pkg/com/com.go index bbeaa0d3..8b475622 100644 --- a/pkg/com/com.go +++ b/pkg/com/com.go @@ -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 diff --git a/pkg/com/net.go b/pkg/com/net.go index 04ed7e54..722ce9b5 100644 --- a/pkg/com/net.go +++ b/pkg/com/net.go @@ -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) diff --git a/pkg/coordinator/user.go b/pkg/coordinator/user.go index 2a4f1e98..e1efef49 100644 --- a/pkg/coordinator/user.go +++ b/pkg/coordinator/user.go @@ -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()) } } diff --git a/pkg/coordinator/userhandlers.go b/pkg/coordinator/userhandlers.go index 80d0dc6e..6dddd30e 100644 --- a/pkg/coordinator/userhandlers.go +++ b/pkg/coordinator/userhandlers.go @@ -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 diff --git a/pkg/coordinator/worker.go b/pkg/coordinator/worker.go index e89d3dad..137d7777 100644 --- a/pkg/coordinator/worker.go +++ b/pkg/coordinator/worker.go @@ -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: diff --git a/pkg/coordinator/workerapi.go b/pkg/coordinator/workerapi.go index 43205871..ccf8c700 100644 --- a/pkg/coordinator/workerapi.go +++ b/pkg/coordinator/workerapi.go @@ -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}) } diff --git a/pkg/coordinator/workerhandlers.go b/pkg/coordinator/workerhandlers.go index edd7e210..35609e06 100644 --- a/pkg/coordinator/workerhandlers.go +++ b/pkg/coordinator/workerhandlers.go @@ -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 } diff --git a/pkg/worker/coordinator.go b/pkg/worker/coordinator.go index f56f84b4..bd5cd3e1 100644 --- a/pkg/worker/coordinator.go +++ b/pkg/worker/coordinator.go @@ -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) { diff --git a/pkg/worker/coordinatorhandlers.go b/pkg/worker/coordinatorhandlers.go index 536c6ed6..d8e30a0e 100644 --- a/pkg/worker/coordinatorhandlers.go +++ b/pkg/worker/coordinatorhandlers.go @@ -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 } diff --git a/pkg/worker/room/cast.go b/pkg/worker/room/cast.go index d8a9710f..81a6c57d 100644 --- a/pkg/worker/room/cast.go +++ b/pkg/worker/room/cast.go @@ -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}} } diff --git a/pkg/worker/room/room.go b/pkg/worker/room/room.go index c2686bdc..88380683 100644 --- a/pkg/worker/room/room.go +++ b/pkg/worker/room/room.go @@ -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}} } diff --git a/pkg/worker/room/room_test.go b/pkg/worker/room/room_test.go index 9a4bdd73..7a537d69 100644 --- a/pkg/worker/room/room_test.go +++ b/pkg/worker/room/room_test.go @@ -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() } diff --git a/pkg/worker/room/router_test.go b/pkg/worker/room/router_test.go index 013f1e27..d4f2e621 100644 --- a/pkg/worker/room/router_test.go +++ b/pkg/worker/room/router_test.go @@ -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} }