package websocket import ( "git.reya.zone/reya/hexmap/server/action" "go.uber.org/zap/zapcore" ) // ClientCommandType is an enum type for the client's protocol messages. type ClientCommandType string const ( ClientHelloType ClientCommandType = "HELLO" ClientRefreshType ClientCommandType = "REFRESH" ClientActType ClientCommandType = "ACT" ClientGoodbyeType ClientCommandType = GoodbyeType ClientMalformedCommandType ClientCommandType = "(malformed command)" ) // ClientCommand s are those sent by the client. type ClientCommand interface { zapcore.ObjectMarshaler // ClientType gives the type constant that will be sent on or read from the wire. ClientType() ClientCommandType } // ClientHello is the command sent by the client when it first establishes the connection. type ClientHello struct { // Version is the protocol version the client is running. Version int `json:"version"` } func (c ClientHello) ClientType() ClientCommandType { return ClientHelloType } func (c ClientHello) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddString("type", string(ClientHelloType)) encoder.AddInt("version", c.Version) return nil } // ClientRefresh is the command sent by the client when it needs the full state re-sent. type ClientRefresh struct { } func (c ClientRefresh) ClientType() ClientCommandType { return ClientRefreshType } func (c ClientRefresh) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddString("type", string(ClientRefreshType)) return nil } // IDed contains a pair of ID and Action, as sent by the client. type IDed struct { // ID contains the arbitrary ID that was sent by the client, for identifying the action in future messages. ID int `json:"id"` // Action contains the action that was actually being sent. Action action.Action `json:"action"` } func (i IDed) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddInt("id", i.ID) return encoder.AddObject("action", i.Action) } type IDPairs []IDed func (a IDPairs) MarshalLogArray(encoder zapcore.ArrayEncoder) error { var finalErr error = nil for _, v := range a { err := encoder.AppendObject(v) if err != nil && finalErr == nil { finalErr = err } } return finalErr } // ClientAct is a command sent in order to deliver one or more Action actions to the server. type ClientAct struct { // Actions contains the actions the client wants to apply, in the order they should be applied. Actions IDPairs `json:"actions"` } func (c ClientAct) ClientType() ClientCommandType { return ClientActType } func (c ClientAct) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddString("type", string(ClientActType)) return encoder.AddArray("actions", c.Actions) } // ClientMalformed is synthesized by the reader when it has read a command that does not appear to match the // protocol. type ClientMalformed struct { // Error is the error in parse that caused the reader to be unable to read the message. Error error } func (c ClientMalformed) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddString("type", string(ClientMalformedCommandType)) encoder.AddString("error", c.Error.Error()) return nil } func (c ClientMalformed) ClientType() ClientCommandType { return ClientMalformedCommandType }