diff --git a/app/websockets/main_handler.go b/app/websockets/main_handler.go index 9118d14..f515023 100644 --- a/app/websockets/main_handler.go +++ b/app/websockets/main_handler.go @@ -56,11 +56,11 @@ func handler(rawConn *websocket.Conn) { } type conn struct { - Conn *websocket.Conn - Mtx sync.Mutex - ID uint64 + Conn *websocket.Conn + Mtx sync.Mutex + ID uint64 RestrictedVisible bool - User *websocketUser + User *websocketUser } func (c *conn) WriteJSON(t string, data interface{}) error { @@ -72,6 +72,7 @@ func (c *conn) WriteJSON(t string, data interface{}) error { var messageHandler = map[string]func(c *conn, message incomingMessage){ TypeSubscribeScores: SubscribeScores, + TypeSubscribeMultiMatches: SubscribeMultiMatches, TypeSetRestrictedVisibility: SetRestrictedVisibility, TypeIdentify: Identify, TypePing: pingHandler, @@ -79,20 +80,23 @@ var messageHandler = map[string]func(c *conn, message incomingMessage){ // Server Message Types const ( - TypeConnected = "connected" - TypeInvalidMessage = "invalid_message_type" - TypeUnexpectedError = "unexpected_error" - TypeNotFound = "not_found" - TypeSubscribedToScores = "subscribed_to_scores" - TypeNewScore = "new_score" - TypeIdentified = "identified" - TypeRestrictedVisibilitySet = "restricted_visibility_set" - TypePong = "pong" + TypeConnected = "connected" + TypeInvalidMessage = "invalid_message_type" + TypeUnexpectedError = "unexpected_error" + TypeNotFound = "not_found" + TypeSubscribedToScores = "subscribed_to_scores" + TypeNewScore = "new_score" + TypeSubscribedToMultiMatches = "subscribed_mp_complete_match" + TypeNewMatch = "new_completed_match" + TypeIdentified = "identified" + TypeRestrictedVisibilitySet = "restricted_visibility_set" + TypePong = "pong" ) // Client Message Types const ( TypeSubscribeScores = "subscribe_scores" + TypeSubscribeMultiMatches = "subscribe_mp_complete_match" TypeIdentify = "identify" TypeSetRestrictedVisibility = "set_restricted_visibility" TypePing = "ping" diff --git a/app/websockets/multi.go b/app/websockets/multi.go new file mode 100644 index 0000000..6a44d50 --- /dev/null +++ b/app/websockets/multi.go @@ -0,0 +1,57 @@ +package websockets + +import ( + "encoding/json" + "fmt" + "sync" +) + +// SubscribeMultiMatches subscribes to receiving information from completed +// games in multiplayer matches. +func SubscribeMultiMatches(c *conn, message incomingMessage) { + multiSubscriptionsMtx.Lock() + var found bool + for _, el := range multiSubscriptions { + if el.ID == c.ID { + found = true + break + } + } + // if it was not found, we need to add it + if !found { + multiSubscriptions = append(multiSubscriptions, c) + } + multiSubscriptionsMtx.Unlock() + + c.WriteJSON(TypeSubscribedToMultiMatches, nil) +} + +var multiSubscriptions []*conn +var multiSubscriptionsMtx = new(sync.RWMutex) + +func matchRetriever() { + ps, err := red.Subscribe("api:mp_complete_match") + if err != nil { + fmt.Println(err) + } + for { + msg, err := ps.ReceiveMessage() + if err != nil { + fmt.Println(err.Error()) + return + } + go handleNewMultiGame(msg.Payload) + } +} + +func handleNewMultiGame(payload string) { + defer catchPanic() + multiSubscriptionsMtx.RLock() + cp := make([]*conn, len(multiSubscriptions)) + copy(cp, multiSubscriptions) + multiSubscriptionsMtx.RUnlock() + + for _, el := range cp { + el.WriteJSON(TypeNewMatch, json.RawMessage(payload)) + } +} diff --git a/app/websockets/websockets.go b/app/websockets/websockets.go index a48fa3e..ac26db5 100644 --- a/app/websockets/websockets.go +++ b/app/websockets/websockets.go @@ -16,6 +16,7 @@ func Start(r *redis.Client, _db *sqlx.DB) error { red = r db = _db go scoreRetriever() + go matchRetriever() return nil } @@ -29,4 +30,13 @@ func cleanup(connID uint64) { } } scoreSubscriptionsMtx.Unlock() + multiSubscriptionsMtx.Lock() + for idx, el := range multiSubscriptions { + if el.ID == connID { + multiSubscriptions[idx] = multiSubscriptions[len(multiSubscriptions)-1] + multiSubscriptions = multiSubscriptions[:len(multiSubscriptions)-1] + break + } + } + multiSubscriptionsMtx.Unlock() }