/
main.go
134 lines (115 loc) · 2.93 KB
/
main.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"fmt"
"log"
"net/http"
"github.com/bmcszk/gptrts/pkg/comm"
"github.com/bmcszk/gptrts/pkg/game"
"github.com/bmcszk/gptrts/pkg/world"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
type server struct {
game *serverGame
clients map[game.PlayerIdType]*comm.Client
}
func newServer(g *serverGame) *server {
return &server{
game: g,
clients: make(map[game.PlayerIdType]*comm.Client, 0), // connected clients,
}
}
func main() {
s := newServer(newServerGame(game.NewStoreImpl(), world.NewWorldService()))
// Configure websocket route
http.HandleFunc("/ws", s.handleConnections)
// Start the server on localhost port 8000 and log any errors
log.Println("http server started on :8000")
err := http.ListenAndServe(":8000", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
func (s *server) handleConnections(w http.ResponseWriter, r *http.Request) {
// Upgrade initial GET request to a websocket
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatal(err)
}
// Make sure we close the connection when the function returns
defer ws.Close()
// Register our new client
client := comm.NewClient(ws)
for client.Connected {
action, err := client.HandleInMessages()
if err != nil {
log.Println(err)
continue
}
s.processAction(client, action)
}
}
func (s *server) processAction(client *comm.Client, action game.Action) {
// register new player
if action.GetType() == game.PlayerJoinActionType {
client.PlayerId = action.GetPayload().(game.Player).Id
s.clients[client.PlayerId] = client
}
// broadcast action to others
s.broadcastOthers(client, action)
// synchronous dispatch func
dispatch := func(a game.Action) {
if err := s.route(client, a); err != nil {
log.Println(err)
}
}
// action handling
s.game.HandleAction(action, dispatch)
}
func (s *server) broadcastOthers(client *comm.Client, action game.Action) {
switch action.(type) {
case game.PlayerJoinAction, game.MapLoadAction:
return
}
for _, c := range s.clients {
if c != client {
err := c.Send(action)
if err != nil {
log.Println(err)
}
}
}
}
func (s *server) broadcastAll(action game.Action) {
for _, c := range s.clients {
err := c.Send(action)
if err != nil {
log.Println(err)
}
}
}
// route - handler of outgoing actions
func (s *server) route(c *comm.Client, action game.Action) error {
dispatch := func(a game.Action) {
if err := s.route(c, a); err != nil {
log.Println(err)
}
}
switch a := action.(type) {
case game.MoveStepAction, game.MoveStopAction, game.SpawnUnitAction:
s.broadcastAll(a)
s.game.HandleAction(a, dispatch)
case game.PlayerJoinSuccessAction:
if err := c.Send(action); err != nil {
return fmt.Errorf("route %w", err)
}
case game.MapLoadSuccessAction:
if err := c.Send(action); err != nil {
return fmt.Errorf("route %w", err)
}
s.game.HandleAction(a, dispatch)
default:
s.broadcastAll(a)
}
return nil
}