From 942b7eb20b69e0ddb9a5bcae72099dd00defa1ea Mon Sep 17 00:00:00 2001 From: Mari Date: Sun, 11 Jul 2021 03:42:09 -0400 Subject: [PATCH] Implement ServerMessage for all the server messages. --- server/action/syncable.go | 14 +++++++- server/go.sum | 3 -- server/room/room.go | 6 ++-- server/state/synced.go | 4 +-- server/websocket/server.go | 69 ++++++++++++++++++++++++++++++++++---- 5 files changed, 80 insertions(+), 16 deletions(-) diff --git a/server/action/syncable.go b/server/action/syncable.go index 53fabaf..89b7d44 100644 --- a/server/action/syncable.go +++ b/server/action/syncable.go @@ -28,4 +28,16 @@ type Syncable interface { // If an action is correctly applied and has an effect, it should return nil. Apply(s *state.Synced) error } -type SyncableProducer func() + +type SyncableSlice []Syncable + +func (s SyncableSlice) MarshalLogArray(encoder zapcore.ArrayEncoder) error { + var finalErr error = nil + for _, a := range s { + err := encoder.AppendObject(a) + if err != nil && finalErr == nil { + finalErr = err + } + } + return finalErr +} diff --git a/server/go.sum b/server/go.sum index bc03dce..717064d 100644 --- a/server/go.sum +++ b/server/go.sum @@ -3,10 +3,8 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -40,7 +38,6 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 h1:Yq9t9jnGoR+dBuitxdo9l6Q golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= diff --git a/server/room/room.go b/server/room/room.go index 7ff1cd3..7228ade 100644 --- a/server/room/room.go +++ b/server/room/room.go @@ -11,7 +11,7 @@ type NewOptions struct { // BaseLogger is the logger that the room should attach its data to. BaseLogger *zap.Logger // StartingState is a state.Synced that defines the state of the room on creation. - StartingState state.Synced + StartingState *state.Synced // StartingClientOptions sets the configuration of the first client to be created, the one that will be returned // from New. StartingClientOptions NewClientOptions @@ -32,7 +32,7 @@ type room struct { logger *zap.Logger } -// Creates and starts up a new room, joins a new client to it and returns that client. +// New creates and starts up a new room, joins a new client to it and returns that client. func New(opts NewOptions) *Client { logger := opts.BaseLogger.Named("Room") id := xid.New() @@ -40,7 +40,7 @@ func New(opts NewOptions) *Client { id: id, incomingChannel: make(chan ClientMessage), clients: make(map[xid.ID]internalClient), - currentState: opts.StartingState, + currentState: *opts.StartingState, logger: logger, } go r.act() diff --git a/server/state/synced.go b/server/state/synced.go index cf38641..782c0a9 100644 --- a/server/state/synced.go +++ b/server/state/synced.go @@ -10,7 +10,7 @@ type Synced struct { User UserData `json:"user"` } -func (s Synced) MarshalLogObject(encoder zapcore.ObjectEncoder) error { +func (s *Synced) MarshalLogObject(encoder zapcore.ObjectEncoder) error { mapErr := encoder.AddObject("map", s.Map) userErr := encoder.AddObject("user", s.User) if mapErr != nil { @@ -21,7 +21,7 @@ func (s Synced) MarshalLogObject(encoder zapcore.ObjectEncoder) error { } // Copy creates a deep copy of this Synced instance. -func (s Synced) Copy() Synced { +func (s *Synced) Copy() Synced { return Synced{ Map: s.Map.Copy(), User: s.User.Copy(), diff --git a/server/websocket/server.go b/server/websocket/server.go index 320efa6..6c95672 100644 --- a/server/websocket/server.go +++ b/server/websocket/server.go @@ -6,8 +6,6 @@ import ( "hexmap-server/state" ) -// TODO: Make all the ServerMessages implement ServerMessage. - // ServerMessageType is an enum type for the server's messages. type ServerMessageType string @@ -32,13 +30,41 @@ type ServerHello struct { // Version is the protocol version the server is running. Version int `json:"version"` // State is the complete state of the server as of when the client joined. - State state.Synced `json:"state"` + State *state.Synced `json:"state"` +} + +func (s ServerHello) MarshalLogObject(encoder zapcore.ObjectEncoder) error { + encoder.AddString("type", string(ServerHelloType)) + encoder.AddInt("version", s.Version) + return encoder.AddObject("state", s.State) +} + +func (s ServerHello) ServerType() ServerMessageType { + return ServerHelloType } // ServerRefresh is the action sent to reestablish the current state of the server in response to ClientRefresh. type ServerRefresh struct { // State is the complete state of the server as of when the corresponding ClientRefresh was processed. - State state.Synced `json:"state"` + State *state.Synced `json:"state"` +} + +func (s ServerRefresh) MarshalLogObject(encoder zapcore.ObjectEncoder) error { + encoder.AddString("type", string(ServerRefreshType)) + return encoder.AddObject("state", s.State) +} + +func (s ServerRefresh) ServerType() ServerMessageType { + return ServerRefreshType +} + +type IDSlice []int + +func (i IDSlice) MarshalLogArray(encoder zapcore.ArrayEncoder) error { + for _, v := range i { + encoder.AppendInt(v) + } + return nil } // ServerOK is the action sent when one or more client actions have been accepted and applied. @@ -46,7 +72,16 @@ type ServerOK struct { // IDs contains the IDs of the actions which were accepted and applied, in the order they were accepted and applied. // This is the same as the order they were received, though other actions may have been between these that were // rejected. - IDs []int `json:"ids"` + IDs IDSlice `json:"ids"` +} + +func (s ServerOK) MarshalLogObject(encoder zapcore.ObjectEncoder) error { + encoder.AddString("type", string(ServerOKType)) + return encoder.AddArray("ids", s.IDs) +} + +func (s ServerOK) ServerType() ServerMessageType { + return ServerOKType } // ServerFailed is the action sent when one or more client actions have been rejected. @@ -54,14 +89,34 @@ type ServerFailed struct { // IDs contains the IDs of the actions which were rejected, in the order they were rejected. // This is the same as the order they were received, though other actions may have been between these that were // accepted and applied. - IDs []int `json:"ids"` + IDs IDSlice `json:"ids"` // Error contains the error text sent from the server about why these actions failed. Error string `json:"error"` } +func (s ServerFailed) MarshalLogObject(encoder zapcore.ObjectEncoder) error { + encoder.AddString("type", string(ServerFailedType)) + err := encoder.AddArray("ids", s.IDs) + encoder.AddString("error", s.Error) + return err +} + +func (s ServerFailed) ServerType() ServerMessageType { + return ServerFailedType +} + // ServerAct is the action sent when one or more client actions from other clients have been accepted and applied. // The client's own actions will never be included in this action. type ServerAct struct { // Actions contains the actions that are now being applied. - Actions []action.Syncable `json:"actions"` + Actions action.SyncableSlice `json:"actions"` +} + +func (s ServerAct) MarshalLogObject(encoder zapcore.ObjectEncoder) error { + encoder.AddString("type", string(ServerActType)) + return encoder.AddArray("actions", s.Actions) +} + +func (s ServerAct) ServerType() ServerMessageType { + return ServerActType }