-
Notifications
You must be signed in to change notification settings - Fork 0
/
requests.go
64 lines (53 loc) · 1.6 KB
/
requests.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package games
const (
reqBootGame byte = iota
reqKillGame
reqMessageChat
)
// handleRequest should only ever be called by the room's event-processing goroutine;
// it will branch based on the request type, decide whether the given client is allowed
// to make the request (also depending on the current room state), and will then update
// room state and emit an event to all connected clients accordingly.
//
// Invalid requests are simply ignored, without sending error feedback to the client.
// Please see decodeRequest() for my explanation of why.
func (r *room) handleRequest(req request) {
// TODO: disconnect any client that sends an invalid request structure?
if len(req.msg) < 2 || req.msg[0] > scopeGame {
return
}
if req.msg[0] == scopeGame {
if r.currentGame != nil {
r.currentGame.HandleRequest(r.members, req.src, req.msg[1:])
}
return
}
body := req.msg[2:]
switch req.msg[1] {
case reqBootGame:
if r.currentGame != nil || len(body) == 0 {
return
}
// TODO: can we just use bytes directly? Should consider places where
// allocations can be avoided
gameID := string(body)
if factory := r.gameRegistry[gameID]; factory != nil {
r.currentGameID = gameID
r.broadcast(encodeSetGameState(gameID))
r.currentGame = factory.NewInstance()
r.currentGame.Init(r.members)
}
case reqKillGame:
if r.currentGame == nil {
return
}
r.currentGame.Deinit()
r.currentGameID = ""
r.currentGame = nil
r.broadcast(encodeSetGameState(""))
case reqMessageChat:
if r.chat.addMessage(req.src.ID, body) {
r.broadcast(encodeNewChatMessageState(req.src.ID, body))
}
}
}