0
0
Fork 0
This repository has been archived on 2024-05-09. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
game-server/pkg/server/server.go
2018-09-18 08:35:41 -05:00

118 lines
2.6 KiB
Go

package server
import (
"encoding/json"
"errors"
"fmt"
"sync"
"time"
"github.com/GregoryDosh/game-server/pkg/event"
"github.com/GregoryDosh/game-server/pkg/gsinterfaces"
ws "github.com/GregoryDosh/game-server/pkg/websocket"
log "github.com/Sirupsen/logrus"
)
type server struct {
umtx sync.RWMutex
users map[string]gsinterfaces.User
gmtx sync.RWMutex
games map[string]gsinterfaces.Game
}
func New() gsinterfaces.Server {
return &server{
users: make(map[string]gsinterfaces.User),
games: make(map[string]gsinterfaces.Game),
}
}
func (s *server) GetUser(uuid, name string) gsinterfaces.User {
s.umtx.RLock()
u, ok := s.users[uuid]
s.umtx.RUnlock()
if !ok {
nu := ws.NewUser(uuid, name)
nu.SetFromHandler(s.eventFromUserHandler)
s.umtx.Lock()
s.users[uuid] = nu
s.umtx.Unlock()
return nu
}
return u
}
func (s *server) Shutdown(timeout int) {
timeoutTicker := time.NewTicker(time.Duration(timeout) * time.Second)
done := make(chan bool)
go func(done chan bool) {
s.umtx.RLock()
for _, u := range s.users {
u.Shutdown()
}
s.umtx.RUnlock()
s.gmtx.RLock()
for _, g := range s.games {
g.Shutdown()
}
s.gmtx.RUnlock()
close(done)
}(done)
for {
select {
case <-done:
log.Info("closed all connections")
return
case <-timeoutTicker.C:
log.Warn("not all connections closed before timeout")
return
}
}
}
func (s *server) DebugAddUser(n string, u gsinterfaces.User) {
s.umtx.Lock()
s.users[n] = u
s.umtx.Unlock()
}
func (s *server) eventFromUserHandler(userUUID string, b []byte) {
u := s.GetUser(userUUID, "")
log.Debugf("Received from '%s' this message: %s", u.Name(), b)
e := &event.General{}
if err := json.Unmarshal(b, &e); err != nil {
log.Error(err)
}
log.Warn(e)
switch e.Event {
case "BROADCAST":
if err := s.broadcastHandler(u, e); err != nil {
u.SendData(event.WrapError(err))
}
case "CREATE_GAME":
if err := s.createGameHandler(u, e); err != nil {
u.SendData(event.WrapError(err))
}
case "GAME":
if err := s.gameEventHandler(u, e); err != nil {
u.SendData(event.WrapError(err))
}
case "CHANGE_USERNAME":
if err := s.changeUsernameHandler(u, e); err != nil {
u.SendData(event.WrapError(err))
}
default:
m := fmt.Sprintf("unknown event from '%s': '%s'", userUUID, e.Event)
log.Infof(m)
u.SendData(event.WrapError(errors.New(m)))
}
}
func (s *server) eventFromGameHandler(userUUID string, gameUUID string, e interface{}) {
log.Debugf("game %s wants to send to %s: %s", gameUUID, userUUID, e)
u := s.GetUser(userUUID, "")
u.SendData(event.WrapValues("GAME_EVENT", map[string]interface{}{
"id": gameUUID,
"event_details": e,
}))
}