Skip to content

Commit

Permalink
Sequence numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
horahoradev committed Jan 24, 2022
1 parent f02b7eb commit d5f2517
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 87 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ RUN apt-get update && \
mkdir public

RUN cd /usr/local && \
wget https://golang.org/dl/go1.17.3.linux-amd64.tar.gz && \
wget https://golang.org/dl/go1.17.5.linux-amd64.tar.gz && \
rm -rf /usr/local/go && \
tar -C /usr/local -xzf go1.17.3.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.17.5.linux-amd64.tar.gz

ENV PATH=$PATH:/usr/local/go/bin

Expand Down
36 changes: 28 additions & 8 deletions server/internal/client/clientmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import (
type ClientPubsubManager struct {
// Game name : client info
gameClientMap map[string]GameClientInfo
lock *sync.Mutex
lock *sync.RWMutex
}

func NewClientPubsubManager() *ClientPubsubManager {
return &ClientPubsubManager{
gameClientMap: make(map[string]GameClientInfo),
lock: &sync.Mutex{},
lock: &sync.RWMutex{},
}
}

Expand Down Expand Up @@ -56,8 +56,6 @@ func (cm *ClientPubsubManager) GetUsernameForGame(game, room, username string) (

func (cm *ClientPubsubManager) SubscribeClientToRoom(serviceName string, conn gnet.Conn) (*ClientSockInfo, error) {
// TODO: cleanup old sock addr in clientRemoteAddrMap
cm.lock.Lock()
defer cm.lock.Unlock()

// Split provided servicename into something we can use
gameName, roomName, err := SplitServiceName(serviceName)
Expand All @@ -71,6 +69,7 @@ func (cm *ClientPubsubManager) SubscribeClientToRoom(serviceName string, conn gn
}

// Does the game client manager exist? if not, create
cm.lock.Lock()
gameServ, ok := cm.gameClientMap[gameName]
if !ok {
gameServ = GameClientInfo{
Expand All @@ -79,6 +78,7 @@ func (cm *ClientPubsubManager) SubscribeClientToRoom(serviceName string, conn gn

cm.gameClientMap[gameName] = gameServ
}
cm.lock.Unlock()

// TODO: initialize second map

Expand All @@ -93,21 +93,39 @@ func (cm *ClientPubsubManager) SubscribeClientToRoom(serviceName string, conn gn
}

// Deletion in old room will be handled in an async worker
cm.lock.Lock()
gameServ.clientRoomRemoteAddrMap[roomName] = append(gameServ.clientRoomRemoteAddrMap[roomName], sockInfo)
cm.lock.Unlock()

if serviceType == Game {
cm.lock.RLock()
players := gameServ.clientRoomRemoteAddrMap[roomName]
cm.lock.RUnlock()
// Send client all player room state
for _, player := range gameServ.clientRoomRemoteAddrMap[roomName] {
for _, player := range players {
syncChanges := player.SyncObject.GetAllChanges()
syncPayload, err := json.Marshal(&syncChanges)
if err != nil {
log.Errorf("Could not get initial player state. Err: %s", err)
}

// Send the new client everyone's state
err = sockInfo.ClientInfo.SendFromPlayer(syncPayload, player.ClientInfo.GetAddr())
if err != nil {
log.Errorf("Failed to send initial state from player. Err: %s", err)
}

// Send the client's state to everyone
// syncChanges = sockInfo.SyncObject.GetAllChanges()
// syncPayload, err = json.Marshal(&syncChanges)
// if err != nil {
// log.Errorf("Could not get initial player state. Err: %s", err)
// }

// err = player.ClientInfo.SendFromPlayer(syncPayload, sockInfo.ClientInfo.GetAddr())
// if err != nil {
// log.Errorf("Failed to send initial state from player. Err: %s", err)
// }
}
}

Expand All @@ -132,24 +150,26 @@ func SplitServiceName(serviceName string) (gameName, serviceType string, err err

// TODO: refactor here too
func (cm *ClientPubsubManager) Broadcast(payload interface{}, sockinfo *ClientSockInfo, fromServer bool) error {
cm.lock.Lock()
defer cm.lock.Unlock()
payloadBytes, err := json.Marshal(payload)
if err != nil {
return err
}

cm.lock.RLock()
gameClientInfo, ok := cm.gameClientMap[sockinfo.GameName]
cm.lock.RUnlock()
if !ok {
return fmt.Errorf("Failed to broadcast, could not find game client info for game name %s", sockinfo.GameName)
}

cm.lock.RLock()
clients, ok := gameClientInfo.clientRoomRemoteAddrMap[sockinfo.RoomName]
cm.lock.RUnlock()
if !ok {
return fmt.Errorf("Failed to broadcast, could not find client list for room name %s", sockinfo.RoomName)
}

log.Printf("Broadcasting for room %s, clients: %s", sockinfo.RoomName, len(clients))
log.Debugf("Broadcasting for room %s, clients: %s", sockinfo.RoomName, len(clients))
for _, client := range clients {
switch fromServer {
case true:
Expand Down
62 changes: 48 additions & 14 deletions server/internal/client/syncobject.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package client

import (
"strconv"
"sync"
)

var serial int = 0
Expand Down Expand Up @@ -82,26 +83,50 @@ type SyncObject struct {

TypingStatus *uint16 `json:"typingstatus,omitempty"`
typingStatusChanged bool

moveSeq uint8
animframeSeq uint8
spriteSeq uint8
animspeedSeq uint8

// Could use more granular locking but this is ok
timeLock *sync.Mutex
posLock *sync.Mutex
}

func NewSyncObject() *SyncObject {
serial += 1
var defaultSpeed uint16 = 4
return &SyncObject{UID: strconv.Itoa(serial), Type: "objectSync", MovementAnimationSpeed: &defaultSpeed}
return &SyncObject{UID: strconv.Itoa(serial),
Type: "objectSync",
MovementAnimationSpeed: &defaultSpeed,
timeLock: &sync.Mutex{},
posLock: &sync.Mutex{},
}
}

func (so *SyncObject) SetPos(x, y uint16) {
so.posChanged = true
so.Pos = &Position{X: x, Y: y}
func (so *SyncObject) SetPos(x, y uint16, seqNum uint8) {
so.posLock.Lock()
defer so.posLock.Unlock()
if so.moveSeq < seqNum {
so.moveSeq = seqNum
so.posChanged = true
so.Pos = &Position{X: x, Y: y}
}
}

func (so *SyncObject) SetSprite(id uint16, sheet string) {
func (so *SyncObject) SetSprite(id uint16, sheet string, seqNum uint8) {
// "why do I have to do this?"
if id == 0 && sheet == "" {
return
}
so.Sprite = &Sprite{ID: id, Sheet: sheet}
so.spriteChanged = true
so.timeLock.Lock()
defer so.timeLock.Unlock()
if so.spriteSeq < seqNum {
so.spriteSeq = seqNum
so.Sprite = &Sprite{ID: id, Sheet: sheet}
so.spriteChanged = true
}
// TODO: sprite validation goes here
}

Expand All @@ -116,24 +141,33 @@ func (so *SyncObject) SetWeather(t, strength uint16) {
}

func (so *SyncObject) SetSwitch(id, value uint32) {
println("Set switch")
so.switchChanged = true
so.Switch = &Switch{ID: id, Value: value}
}

func (so *SyncObject) SetAnimFrame(frame uint16) {
so.AnimFrame = &frame
so.animframeChanged = true
func (so *SyncObject) SetAnimFrame(frame uint16, seqNum uint8) {
so.timeLock.Lock()
defer so.timeLock.Unlock()
if so.animframeSeq < seqNum {
so.animframeSeq = seqNum
so.AnimFrame = &frame
so.animframeChanged = true
}
}

func (so *SyncObject) SetName(name string) {
so.nameChanged = true
so.Name = name
}

func (so *SyncObject) SetMovementAnimationSpeed(animationSpeed uint16) {
so.movementAnimationSpeedChanged = true
so.MovementAnimationSpeed = &animationSpeed
func (so *SyncObject) SetMovementAnimationSpeed(animationSpeed uint16, seqNum uint8) {
so.timeLock.Lock()
defer so.timeLock.Unlock()
if so.animspeedSeq < seqNum {
so.animspeedSeq = seqNum
so.MovementAnimationSpeed = &animationSpeed
so.movementAnimationSpeedChanged = true
}
}

func (so *SyncObject) SetFacing(facing uint16) {
Expand Down
8 changes: 4 additions & 4 deletions server/internal/msghandler/chathandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (ch *ChatHandler) muxMessage(payload []byte, c gnet.Conn, s *client.ClientS

func (ch *ChatHandler) pardonChat(payload []byte, client *client.ClientSockInfo) error {
t := clientmessages.UnignoreChatEvents{}
matched, err := protocol.Marshal(payload, &t, false)
matched, _, err := protocol.Marshal(payload, &t, false)
switch {
case !matched:
return errors.New("Failed to match")
Expand Down Expand Up @@ -98,7 +98,7 @@ func (ch *ChatHandler) pardonChat(payload []byte, client *client.ClientSockInfo)

func (ch *ChatHandler) ignoreChat(payload []byte, client *client.ClientSockInfo) error {
t := clientmessages.IgnoreChatEvents{}
matched, err := protocol.Marshal(payload, &t, false)
matched, _, err := protocol.Marshal(payload, &t, false)
switch {
case !matched:
return errors.New("Failed to match")
Expand Down Expand Up @@ -136,7 +136,7 @@ func (ch *ChatHandler) ignoreChat(payload []byte, client *client.ClientSockInfo)

func (ch *ChatHandler) setUsername(payload []byte, client *client.ClientSockInfo) error {
t := clientmessages.SetUsername{}
matched, err := protocol.Marshal(payload, &t, false)
matched, _, err := protocol.Marshal(payload, &t, false)
switch {
case err != nil:
return err
Expand All @@ -160,7 +160,7 @@ func (ch *ChatHandler) setUsername(payload []byte, client *client.ClientSockInfo

func (ch *ChatHandler) sendUserMessage(payload []byte, client *client.ClientSockInfo) error {
t := clientmessages.SendMessage{}
matched, err := protocol.Marshal(payload, &t, false)
matched, _, err := protocol.Marshal(payload, &t, false)
switch {
case err != nil:
return err
Expand Down
Loading

0 comments on commit d5f2517

Please sign in to comment.