mapper

package
v5.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2023 License: BSD-3-Clause Imports: 20 Imported by: 0

Documentation

Overview

Package mapper implements a standard client interface for the mapper service.

EXPERIMENTAL CODE

THIS PACKAGE IS STILL A WORK IN PROGRESS and has not been completely tested yet. Although GMA generally is a stable product, this module of it is new, and is not.

This package handles the details of communicating with the GMA mapper service communication channel used to keep the mapper clients in sync with each other and with the other GMA tools.

A client should establish a connection to the game server by calling the Dial method in this package. This function will sign on to the server and then enter a loop, sending incoming server messages back on the channel(s) established via the Subscribe method. Dial returns when the session with the server has terminated.

Typically, an application will invoke the Dial method in a goroutine. Calling the associated context's cancel function will signal that we want to stop talking to the server, resulting in the termination of the running Dial method.

Index

Constants

View Source
const (
	GMAMapperProtocol           = 400     // @@##@@ auto-configured
	GMAVersionNumber            = "5.0.0" // @@##@@ auto-configured
	MinimumSupportedMapProtocol = 400
	MaximumSupportedMapProtocol = 400
)

The GMA Mapper Protocol version number current as of this build, and protocol versions supported by this code.

View Source
const GMAMapperFileFormat = 20 // @@##@@ auto-configured

GMAMapperFileFormat gives the GMA File Format version number current as of this build. This is the format which will be used for saving map data.

View Source
const IncomingClientPacketBacklog = 64 // How many incoming packets we can buffer waiting to be processed by the server before blocking
View Source
const MaximumSupportedMapFileFormat = 20

MaximumSupportedMapFileFormat gives the highest file format this package can understand. Saved data will be in this format.

View Source
const MinimumSupportedMapFileFormat = 17

MinimumSupportedMapFileFormat gives the lowest file format this package can understand.

Variables

View Source
var ErrAuthenticationFailed = errors.New("access denied to server")

ErrAuthenticationFailed is the error returned when our authentication was rejected by the server.

View Source
var ErrAuthenticationRequired = errors.New("authenticator required for connection")

ErrAuthenticationRequired is the error returned when the server requires authentication but we didn't provide any.

View Source
var ErrProtocol = errors.New("internal protocol error")

ErrProtocol is the error returned when there is a protocol-level issue. This generally indicates a bug in the code, not a communications issue.

View Source
var ErrServerProtocolError = errors.New("server protocol error; unable to continue")

ErrServerProtocolError is the error returned when something fundamental about the server's conversation with us is so wrong we can't even deal with the conversation any further.

View Source
var ServerMessageByName = map[string]ServerMessage{
	"Accept":                      Accept,
	"AddCharacter":                AddCharacter,
	"AddDicePresets":              AddDicePresets,
	"AddImage":                    AddImage,
	"AddObjAttributes":            AddObjAttributes,
	"AdjustView":                  AdjustView,
	"Allow":                       Allow,
	"Auth":                        Auth,
	"Challenge":                   Challenge,
	"ChatMessage":                 ChatMessage,
	"Clear":                       Clear,
	"ClearChat":                   ClearChat,
	"ClearFrom":                   ClearFrom,
	"CombatMode":                  CombatMode,
	"Comment":                     Comment,
	"DefineDicePresets":           DefineDicePresets,
	"Denied":                      Denied,
	"Echo":                        Echo,
	"FilterDicePresets":           FilterDicePresets,
	"Granted":                     Granted,
	"LoadFrom":                    LoadFrom,
	"LoadArcObject":               LoadArcObject,
	"LoadCircleObject":            LoadCircleObject,
	"LoadLineObject":              LoadLineObject,
	"LoadPolygonObject":           LoadPolygonObject,
	"LoadRectangleObject":         LoadRectangleObject,
	"LoadSpellAreaOfEffectObject": LoadSpellAreaOfEffectObject,
	"LoadTextObject":              LoadTextObject,
	"LoadTileObject":              LoadTileObject,
	"Marco":                       Marco,
	"Mark":                        Mark,
	"PlaceSomeone":                PlaceSomeone,
	"Polo":                        Polo,
	"Priv":                        Priv,
	"Protocol":                    Protocol,
	"QueryDicePresets":            QueryDicePresets,
	"QueryImage":                  QueryImage,
	"QueryPeers":                  QueryPeers,
	"Ready":                       Ready,
	"RemoveObjAttributes":         RemoveObjAttributes,
	"RollDice":                    RollDice,
	"RollResult":                  RollResult,
	"Sync":                        Sync,
	"SyncChat":                    SyncChat,
	"Toolbar":                     Toolbar,
	"UpdateClock":                 UpdateClock,
	"UpdateDicePresets":           UpdateDicePresets,
	"UpdateInitiative":            UpdateInitiative,
	"UpdateObjAttributes":         UpdateObjAttributes,
	"UpdatePeerList":              UpdatePeerList,
	"UpdateProgress":              UpdateProgress,
	"UpdateStatusMarker":          UpdateStatusMarker,
	"UpdateTurn":                  UpdateTurn,
	"UpdateVersions":              UpdateVersions,
	"World":                       World,
}

Functions

func DebugFlagNameSlice

func DebugFlagNameSlice(flags DebugFlags) []string

DebugFlagNames returns a string representation of the debugging flags (topics) stored in the DebugFlags value passed in.

func DebugFlagNames

func DebugFlagNames(flags DebugFlags) string

func SaveMapFile

func SaveMapFile(output io.Writer, objList []any, meta MapMetaData) error

SaveMapFile is the same as WriteMapFile, except it writes to an open data stream.

If the Timestamp field of the metadata is zero, the current date and time will be written to the Timestamp and DateTime fields on output.

func WhenReady

func WhenReady(ch chan byte) func(*Connection) error

WhenReady specifies a channel on which to send a single byte when the server login process is complete and the server is ready to receive our commands.

func WithContext

func WithContext(ctx context.Context) func(*Connection) error

WithContext modifies the behavior of the NewConnection function by supplying a context for this connection, which may be used to signal the Dial method that the connection to the server should be terminated.

N.B.: When making the initial TCP connection to the server, if there is a timeout value specified via WithTimeout, then a hanging connection will terminate when that timer expires, regardless of the context. Otherwise, the connection will wait indefinitely to complete OR until the context is cancelled.

func WriteMapFile

func WriteMapFile(path string, objList []any, meta MapMetaData) error

WriteMapFile writes mapper data from a slice of map object values and MapMetaData struct into the named file. It is identical to SaveMapFile other than the fact that it creates and opens the requested file to be written into.

Types

type AcceptMessagePayload

type AcceptMessagePayload struct {
	BaseMessagePayload

	// Messages is a list of message command words.
	Messages []string `json:",omitempty"`
}

AcceptMessagePayload holds the information sent by a client requesting that the server only send a subset of its possible message types to it.

Clients send this by calling the Subscribe method on their connection.

type AddCharacterMessagePayload

type AddCharacterMessagePayload struct {
	BaseMessagePayload
	PlayerToken
}

AddCharacterMessagePayload holds the information sent by the server's AddCharacter message to add a new PC to the party. This is not done for most creatures and NPCs encountered; it is for the PCs and significant NPCs who are important enough to be treated specially by clients (such as being included in menus).

type AddDicePresetsMessagePayload

type AddDicePresetsMessagePayload struct {
	BaseMessagePayload
	For     string               `json:",omitempty"`
	Presets []dice.DieRollPreset `json:",omitempty"`
}

type AddImageMessagePayload

type AddImageMessagePayload struct {
	BaseMessagePayload
	ImageDefinition
}

AddImageMessagePayload holds the information sent by the server's AddImage message informing the client as to where it can locate an image's data.

Call the AddImage method to send this message out to others if you know of an image file they should be aware of.

type AddObjAttributesMessagePayload

type AddObjAttributesMessagePayload struct {
	BaseMessagePayload
	ObjID    string
	AttrName string
	Values   []string
}

AddObjAttributesMessagePayload holds the information sent by the server's AddObjAttributes message. This tells the client to adjust the multi-value attribute of the object with the given ID by adding the new values to it.

Call the AddObjAttributes method to send this message out to other clients.

type AdjustViewMessagePayload

type AdjustViewMessagePayload struct {
	BaseMessagePayload
	XView, YView float64 `json:",omitempty"`
}

AdjustViewMessagePayload holds the information sent by the server's AdjustView message. This tells the client to set its viewable area so that its x and y scrollbars are at the given proportion of their full range.

Call the AdjustView method to send this message out to other clients.

type AllowMessagePayload

type AllowMessagePayload struct {
	BaseMessagePayload

	// List of supported optional feature names
	Features []string `json:",omitempty"`
}

AllowMessagePayload holds the data sent by a client when indicating which optional features it supports.

type AnchorDirection

type AnchorDirection byte

The valid values for the Anchor attribute of a TextElement.

const (
	AnchorCenter AnchorDirection = iota
	AnchorNorth
	AnchorSouth
	AnchorEast
	AnchorWest
	AnchorNE
	AnchorNW
	AnchorSW
	AnchorSE
)

type AoEType

type AoEType byte

These are the valid values for the AoEShape attribute.

const (
	AoEShapeCone AoEType = iota
	AoEShapeRadius
	AoEShapeRay
)

type ArcElement

type ArcElement struct {
	MapElement
	ArcMode ArcModeType
	Start   float64
	Extent  float64
}

ArcElement is a MapElement that draws an arc on-screen. The arc is defined as a portion of a circle which is inscribed within the rectangle formed by the reference point and the single additional point in its Points attribute.

Start and Extent specify the portion of that circle to include in the arc, measured in degrees.

ArcMode defines how to draw the arc: it may be an arc (curve along the circle's permieter without connecting the endpoints), chord (the endpoints connected to each other with a straight line), or a pieslice (endpoints connected to the center of the circle with straight lines).

type ArcModeType

type ArcModeType byte

These are the allowed values for the ArcMode attribute of an ArcElement.

const (
	ArcModePieSlice ArcModeType = iota
	ArcModeArc
	ArcModeChord
)

type ArrowType

type ArrowType byte

Valid values for a line's Arrow attribute.

const (
	ArrowNone ArrowType = iota
	ArrowFirst
	ArrowLast
	ArrowBoth
)

type AuthMessagePayload

type AuthMessagePayload struct {
	BaseMessagePayload

	// Client describes the client program (e.g., "mapper 4.0.1")
	Client string `json:",omitempty"`

	// Response gives the binary response to the server's challenge
	Response []byte

	// User gives the username requested by the client
	User string `json:",omitempty"`
}

AuthMessagePayload holds the data sent by a client when authenticating to the server.

type BaseMapObject

type BaseMapObject struct {
	// Unique object identifier. May be any string
	// consisting of upper- or lower-case letters, digits, '_', and "#"
	// characters.
	//
	// By convention, we create these from a UUID expressed in
	// hex without punctuation. Local conventions may also be
	// used, such as PC character tokens using ID strings such as
	// "PC1", "PC2", etc.
	ID string
}

BaseMapObject holds attributes all MapObjects have in common, so they will import BaseMapObject into their definitions by composition.

func (BaseMapObject) ObjID

func (o BaseMapObject) ObjID() string

ObjID returns the unique ID of a MapObject. Each type must have one of these methods to satisfy the MapObject interface.

type BaseMessagePayload

type BaseMessagePayload struct {
	// contains filtered or unexported fields
}

BaseMessagePayload is not a payload type that you should ever encounter directly, but it is included in all other payload types. It holds the bare minimum data for any server message.

func (BaseMessagePayload) MessageType

func (p BaseMessagePayload) MessageType() ServerMessage

MessageType returns the type of message this MessagePayload represents. This value will be the same as the ServerMessage value used for the Subscribe function, and may be used with channels which receive multiple kinds of messages to differentiate them, like so:

select {
case p<-messages:
    // This channel may receive a ChatMessage or RollResult.
    switch p.MessageType() {
    case ChatMessage:
        // Do whatever with p.(ChatMessageMessagePayload)
    case RollResult:
        // Do whatever with p.(RollResultMessagePayload)
    default:
        // Something bad happened!
    }
 ...
}

You can also use a type switch to accomplish the same thing and avoid the explicit type assertions:

select {
case p<-messages:
    // This channel may receive a ChatMessage or RollResult.
    switch msg := p.(type) {
    case ChatMessageMessagePayload:
        // Do whatever with msg
    case RollResultMessagePayload:
        // Do whatever with msg
    default:
        // Something bad happened!
    }
 ...
}

func (BaseMessagePayload) RawBytes

func (p BaseMessagePayload) RawBytes() []byte

func (BaseMessagePayload) RawMessage

func (p BaseMessagePayload) RawMessage() string

RawMessage returns the raw message received from the server before it was parsed out into the MessagePayload the client should arguably be looking at instead.

The raw message data may be useful for debugging purposes or other low-level poking around, though, so we make it available here.

type ChallengeMessagePayload

type ChallengeMessagePayload struct {
	BaseMessagePayload
	Protocol  int
	Challenge []byte `json:",omitempty"`
}

type CharacterDefinitions

type CharacterDefinitions map[string]PlayerToken

CharacterDefinitions is a map of a character name to their token object.

func (CharacterDefinitions) Text

func (cs CharacterDefinitions) Text() string

Text produces a simple text description of a map of PlayerTokens

type ChatCommon

type ChatCommon struct {
	// The name of the person sending the message.
	Sender string `json:",omitempty"`

	// The names of the people the message was explicitly addressed to.
	// This will be nil for global messages.
	Recipients []string `json:",omitempty"`

	// The unique ID number for the chat message.
	MessageID int `json:",omitempty"`

	// True if this is a global message (sent to all users).
	ToAll bool `json:",omitempty"`

	// True if this message was sent only to the GM.
	ToGM bool `json:",omitempty"`
}

ChatCommon holds fields common to chat messages and die-roll results.

type ChatMessageMessagePayload

type ChatMessageMessagePayload struct {
	BaseMessagePayload
	ChatCommon

	// The text of the chat message we received.
	Text string
}

ChatMessageMessagePayload holds the information sent by the server's ChatMessage message. This is a message sent by other players or perhaps by the server itself.

Call the ChatMessage, ChatMessageToAll, or ChatMessageToGM methods to send this message out to other clients.

type CircleElement

type CircleElement struct {
	MapElement
}

CircleElement is a MapElement that draws an ellipse or circle on-screen. The ellipse is described by the rectangle formed by the reference point and the single point in the Points attribute (as diagonally opposing points), with the circle/ellipse being inscribed in that rectangle.

type ClearChatMessagePayload

type ClearChatMessagePayload struct {
	BaseMessagePayload

	// User requesting the action, if known.
	RequestedBy string `json:",omitempty"`

	// Don't notify the user of the operation.
	DoSilently bool `json:",omitempty"`

	// If >0, clear all messages with IDs greater than target.
	// If <0, clear most recent -N messages.
	// If 0, clear all messages.
	Target int `json:",omitempty"`

	// Chat message ID of this notice.
	MessageID int `json:",omitempty"`
}

ClearChatMessagePayload holds the information sent by the server's ClearChat message. This tells the client to remove some messages from its chat history.

Call the ClearChat method to send this message out to other clients.

type ClearFromMessagePayload

type ClearFromMessagePayload struct {
	BaseMessagePayload
	FileDefinition
}

ClearFromMessagePayload holds the information sent by the server's ClearFrom message. This tells the client to remove all elements mentioned in the specified map file.

Call the ClearFrom method to send this message out to other clients.

type ClearMessagePayload

type ClearMessagePayload struct {
	BaseMessagePayload

	// The ObjID gives the object ID for the object to be removed, or one of
	// the following:
	//   *                    Remove all objects
	//   E*                   Remove all map elements
	//   M*                   Remove all monster tokens
	//   P*                   Remove all player tokens
	//   [<imagename>=]<name> Remove token with given <name>
	ObjID string
}

ClearMessagePayload holds the information sent by the server's Clear message. This tells the client to remove one or more objects from its canvas.

Call the Clear method to send this message out to other clients.

type ClientConnection

type ClientConnection struct {
	// Client features enabled
	Features struct {
		DiceColorBoxes bool
	}

	// The client's host and port number
	Address string

	// The last time we heard a ping reply from the client
	LastPoloTime time.Time

	// The messages this client wishes to receive
	// (nil means to receive all messages)
	Subscriptions map[ServerMessage]bool

	// Authentication information for this user
	Auth *auth.Authenticator

	// Level of debugging requested for this client
	DebuggingLevel DebugFlags

	Server MapServer

	Conn MapConnection
	D    *dice.DieRoller
}

ClientConnection describes the connection to a single client from the server's point of view.

func NewClientConnection

func NewClientConnection(socket net.Conn, opts ...ClientConnectionOption) (ClientConnection, error)

func (*ClientConnection) Close

func (c *ClientConnection) Close()

func (*ClientConnection) IdTag

func (c *ClientConnection) IdTag() string

func (*ClientConnection) Log

func (c *ClientConnection) Log(message ...any)

func (*ClientConnection) Logf

func (c *ClientConnection) Logf(format string, args ...any)

func (*ClientConnection) ServeToClient

func (c *ClientConnection) ServeToClient(ctx context.Context)

ServeToClient is intended to be run in its own thread, and speaks to one client for the duration of its session.

type ClientConnectionOption

type ClientConnectionOption func(*ClientConnection) error

func WithClientAuthenticator

func WithClientAuthenticator(a *auth.Authenticator) ClientConnectionOption

func WithClientDebuggingLevel

func WithClientDebuggingLevel(l DebugFlags) ClientConnectionOption

func WithDebugFunctions

func WithDebugFunctions(debugFunc func(DebugFlags, string), debugfFunc func(DebugFlags, string, ...any)) ClientConnectionOption

func WithServer

func WithServer(s MapServer) ClientConnectionOption

type ClientPreamble

type ClientPreamble struct {
	// Do we send the connecting client a full dump of the current game state?
	SyncData bool

	// Initial commands sent at the start, after authentication, and
	// at the end of the sign-on sequence.
	Preamble  []string
	PostAuth  []string
	PostReady []string
}

ClientPreamble contains information given to each client upon connection to the server.

type CombatModeMessagePayload

type CombatModeMessagePayload struct {
	BaseMessagePayload

	// If true, we should be in combat mode.
	Enabled bool `json:",omitempty"`
}

CombatModeMessagePayload holds the information sent by the server's CombatMode message. This tells the client to enter or exit combat (initiative) mode.

Call the CombatMode method to send this message out to other clients.

type CommentMessagePayload

type CommentMessagePayload struct {
	BaseMessagePayload
	Text string
}

CommentMessagePayload holds the information sent by the server's Comment message. This provides information from the server that the client is free to ignore, but may find interesting. Nothing sent in comments is critical to the operation of a client. However, some incidental bits of information such as an advisement of currently-supported client versions and progress gauge data are sent via comments.

type Connection

type Connection struct {
	// If true, we will always try to reconnect to the server if we
	// lose our connection.
	StayConnected bool

	// If nonzero, we will re-try a failing connection this many
	// times before giving up on the server. Otherwise we will keep
	// trying forever.
	Retries uint

	// The server's protocol version number.
	Protocol int

	// The verbosity level of debugging log messages.
	DebuggingLevel DebugFlags

	// If nonzero, our connection attempts will timeout after the
	// specified time interval. Otherwise they will wait indefinitely.
	Timeout time.Duration

	// The server endpoint, in any form acceptable to the net.Dial
	// function.
	Endpoint string

	// Characters received from the server.
	Characters map[string]PlayerToken

	// Conditions and their token markings received from the server.
	Conditions map[string]StatusMarkerDefinition

	// If we received pre-authentication data from the server other than
	// definition of characters and condition codes, they are technically
	// too early to be valid (the server shouldn't do anything else before
	// authenticating), so we'll merely collect them here in case they are
	// of interest forensically.
	Preamble []string

	// Any progress gauges sent by the server will be tracked here as well
	// as passed to a channel subscribed to UpdateProgress.
	Gauges map[string]*UpdateProgressMessagePayload

	// The list of advertised updates to our software
	PackageUpdatesAvailable map[string][]PackageVersion

	// The last error encountered while communicating with the server.
	LastError error

	// The calendar system the server indicated as preferred, if any
	CalendarSystem string

	// The context for our session, either one we created in the
	// NewConnection function or one we received from the caller.
	Context context.Context

	// If this is non-nil, we will use this to identify the user
	// to the server.
	Authenticator *auth.Authenticator

	// We will log informational messages here as we work.
	Logger *log.Logger

	// Server message subscriptions currently in effect.
	Subscriptions map[ServerMessage]chan MessagePayload

	// Our signal that we're ready for the client to talk.
	ReadySignal chan byte
	// contains filtered or unexported fields
}

Connection describes a connection to the server. These are created with NewConnection and then send methods such as Subscribe and Dial.

func NewConnection

func NewConnection(endpoint string, opts ...ConnectionOption) (Connection, error)

NewConnection creates a new server connection value which can then be used to manage our communication with the server.

After the endpoint, you may specify any of the following options to define the behavior desired for this connection:

StayConnected(bool)
WithAuthenticator(a)
WithDebugging(level)
WithContext(ctx)
WithLogger(l)
WithRetries(n)
WithSubscription(ch, msgs...)
WithTimeout(t)

Example:

a := NewClientAuthenticator("fred", []byte("sekret"), "some random client")
ctx, cancel := context.Background()
defer cancel()

messages := make(chan MessagePayload, 10)
problems := make(chan MessagePayload, 10)

server, err := NewConnection("mygame.example.org:2323",
                  WithAuthenticator(a),
                  WithContext(ctx),
                  StayConnected(true),
                  WithSubscription(messages, ChatMessage, RollResult),
                  WithSubscription(problems, ERROR, UNKNOWN))
if err != nil {
   log.Fatalf("can't reach the server: %v", err)
}
go server.Dial()

func (*Connection) AddDicePresets

func (c *Connection) AddDicePresets(presets []dice.DieRollPreset) error

AddDicePresets is like DefineDicePresets except that it adds the presets passed in to the existing set rather than replacing them.

func (*Connection) AddDicePresetsFor

func (c *Connection) AddDicePresetsFor(user string, presets []dice.DieRollPreset) error

AddDicePresetsFor is just like AddDicePresets but performs the operation for another user (GM only).

func (*Connection) AddImage

func (c *Connection) AddImage(idef ImageDefinition) error

AddImage informs the server and peers about an image they can use.

func (*Connection) AddObjAttributes

func (c *Connection) AddObjAttributes(objID, attrName string, values []string) error

AddObjAttributes informs peers to add a set of string values to the existing value of an object attribute. The attribute must be one whose value is a list of strings, such as StatusList.

func (*Connection) AdjustView

func (c *Connection) AdjustView(xview, yview float64) error

AdjustView tells other clients to adjust their scrollbars so that the x and y directions are scrolled to xview and yview respectively, where those values are a fraction from 0.0 to 1.0 indicating the proportion of the full range in each direction.

func (*Connection) Allow

func (c *Connection) Allow(features ...OptionalFeature) error

Allow tells the server which optional features this client is prepared to accept.

func (*Connection) CacheFile

func (c *Connection) CacheFile(serverID string) error

CacheFile asks other clients to be sure they retrieve and cache the map file with the given server ID.

func (*Connection) ChatMessage

func (c *Connection) ChatMessage(to []string, message string) error

ChatMessage sends a message on the chat channel to other users. The to paramter is a slice of user names of the people who should receive this message.

func (*Connection) ChatMessageToAll

func (c *Connection) ChatMessageToAll(message string) error

ChatMessageToAll is equivalent to ChatMessage, but is addressed to all users.

func (*Connection) ChatMessageToGM

func (c *Connection) ChatMessageToGM(message string) error

ChatMessageToGM is equivalent to ChatMessage, but is addressed only to the GM.

func (*Connection) CheckVersionOf

func (c *Connection) CheckVersionOf(packageName, myVersionNumber string) (*PackageVersion, error)

CheckVersionOf returns the closest match of the requested package to the platform we are currently running, or nil if we're already on the advertised version.

func (*Connection) Clear

func (c *Connection) Clear(objID string) error

Clear tells peers to remove objects from their canvases. The objID may be one of the following:

  • Remove all objects E* Remove all map elements M* Remove all monster tokens P* Remove all player tokens [<imagename>=]<name> Remove token with given <name> <id> Remove object with given <id>

func (*Connection) ClearChat

func (c *Connection) ClearChat(target int, silently bool) error

ClearChat tells peers to remove all messages from their chat histories if target is zero. If target>0, then all messages with IDs greater than target are removed. Otherwise, if target<0 then only the most recent |target| messages are kept.

func (*Connection) ClearFrom

func (c *Connection) ClearFrom(serverID string) error

ClearFrom tells all peers to load the map file with the given server ID, but to remove from their canvases all objects described in the file rather than loading them on.

func (*Connection) Close

func (c *Connection) Close()

Close terminates the connection to the server. Note that the Dial function normally closes the connection before it returns, so calling this explicitly should not normally be necessary.

Calling Close will result in the Dial function stopping due to the connection disappearing, but it is better to cancel the context being watched by Dial instead.

func (*Connection) CombatMode

func (c *Connection) CombatMode(enabled bool) error

CombatMode tells all peers to enable or disable combat mode.

func (*Connection) DefineDicePresets

func (c *Connection) DefineDicePresets(presets []dice.DieRollPreset) error

DefineDicePresets replaces any existing die-roll presets you have stored on the server with the new set passed as the presets parameter.

func (*Connection) DefineDicePresetsFor

func (c *Connection) DefineDicePresetsFor(user string, presets []dice.DieRollPreset) error

DefineDicePresetsFor is just like DefineDicePresets but performs the operation for another user (GM only).

func (*Connection) Dial

func (c *Connection) Dial()

Dial connects to the server, negotiates the initial sign-on sequence with it, and then enters a loop to receive messages from the server until the connection is broken or the context is cancelled, at which point the Dial method returns.

Dial is designed to be called in a goroutine so it can run in the background while the rest of the appliction continues with other tasks.

Any errors encountered by the Dial method will be reported to the channel subscribed to watch for ERROR messages. If the client application did not subscribe to ERROR messages, they will be logged.

Example:

ctx, cancel := context.Background()
server, err := NewConnection("example.org:2323",
                             WithAuthenticator(a),
                             WithContext(ctx))
defer cancel()
go server.Dial()

func (*Connection) Echo

func (c *Connection) Echo(b bool, i int, s string, o map[string]any) error

func (*Connection) EchoBool

func (c *Connection) EchoBool(b bool) error

func (*Connection) EchoInt

func (c *Connection) EchoInt(i int) error

func (*Connection) EchoString

func (c *Connection) EchoString(s string) error

func (*Connection) FilterDicePresets

func (c *Connection) FilterDicePresets(re string) error

FilterDicePresets asks the server to remove all of your die-roll presets whose names match the given regular expression.

func (*Connection) FilterDicePresetsFor

func (c *Connection) FilterDicePresetsFor(user, re string) error

FilterDicePresetsFor is like FilterDicePresets but works on another user's saved presets (GM only).

func (*Connection) IsReady

func (c *Connection) IsReady() bool

IsReady returns true if the connection to the server has completed and authentication was successful, so the connection is ready for interactive use.

func (*Connection) LoadFrom

func (c *Connection) LoadFrom(path string, local bool, merge bool) error

LoadFrom asks other clients to load a map files from a local disk file or from the server. The previous map contents are erased before each file is loaded.

If local is true, a local path is specified. This is discouraged in favor of storing files on the server.

Otherwise, the path should be the ID for the file stored on the server.

If merge is true, then the current map elements are not deleted first. In this case, the newly-loaded elements will be merged with what is already on the map.

func (*Connection) LoadObject

func (c *Connection) LoadObject(mo MapObject) error

LoadObject sends a MapObject to all peers. It may be given a value of any of the supported MapObject types for map graphic elements (Arc, Circle, Line, Polygon, Rectangle, SpellAreaOfEffect, Text, or Tile).

func (*Connection) Log

func (c *Connection) Log(message ...any)

Log writes data to our log destination.

func (*Connection) Logf

func (c *Connection) Logf(format string, data ...any)

Logf writes data to our log destination.

func (*Connection) Mark

func (c *Connection) Mark(x, y float64) error

Mark tells clients to visibly mark a location centered on the given (x, y) coordinates.

func (*Connection) PlaceSomeone

func (c *Connection) PlaceSomeone(someone any) error

PlaceSomeone tells all peers to add a new creature token on their maps. The parameter passed must be either a PlayerToken or MonsterToken.

If the creature is already on the map, it will be replaced by the new one being presented here. Thus, PlaceSomeone may be used to change the name or location of an existing creature, although the preferred way to do that would be to use UpdateObjAttributes to change those specific attributes of the creature directly.

func (*Connection) Polo

func (c *Connection) Polo() error

Polo send the client's response to the server's MARCO ping message.

func (*Connection) QueryDicePresets

func (c *Connection) QueryDicePresets() error

QueryDicePresets requests that the server send you the die-roll presets currently stored for you. It will send you an UpdateDicePresets message.

func (*Connection) QueryImage

func (c *Connection) QueryImage(idef ImageDefinition) error

QueryImage asks the server and peers if anyone else knows where to find the data for the given image name and zoom factor. If someone does, you'll receive an AddImage message.

func (*Connection) QueryPeers

func (c *Connection) QueryPeers() error

QueryPeers asks the server to send an UpdatePeerList message with the current set of peers who are connected to the server.

func (*Connection) RemoveObjAttributes

func (c *Connection) RemoveObjAttributes(objID, attrName string, values []string) error

RemoveObjAttributes informs peers to remove a set of string values from the existing value of an object attribute. The attribute must be one whose value is a list of strings, such as StatusList.

func (*Connection) RollDice

func (c *Connection) RollDice(to []string, rollspec string) error

RollDice sends a rollspec such as "d20+12" or "6d6 fire" to the server, initiating a die roll using the server's built-in facility for that.

This will result in a response in the form of a RollResult message. If something went wrong when trying to satisfy the request, you'll receive a ChatMessage with an explanation instead.

The to parameter lists the users who should receive the results of the die roll, in the same way as recipients are listed to the ChatMessage function.

The rollspec may have any form that would be accepted to the dice.Roll function and dice.DieRoller.DoRoll method. See the dice package for details. https://pkg.go.dev/github.com/MadScienceZone/go-gma/v5/dice#DieRoller.DoRoll

func (*Connection) RollDiceToAll

func (c *Connection) RollDiceToAll(rollspec string) error

RollDiceToAll is equivalent to RollDice, sending the results to all users.

func (*Connection) RollDiceToGM

func (c *Connection) RollDiceToGM(rollspec string) error

RollDiceToGM is equivalent to RollDice, sending the results only to the GM.

func (*Connection) RollDiceWithID

func (c *Connection) RollDiceWithID(to []string, rollspec string, requestID string) error

RollDiceWithID is identical to RollDice except it passes a user-supplied request ID to the server, which will be sent back with the corresponding result message(s).

func (*Connection) Subscribe

func (c *Connection) Subscribe(ch chan MessagePayload, messages ...ServerMessage) error

Subscribe arranges for server messages to be sent to the specified channel when they arrive.

If multiple messages are specified, they are all directed to send their payloads to the channel, which may use the MessageType method to differentiate what kind of payload was sent.

This method may be called multiple times for the same channel, in which case the specified message(s) are added to the set which sends to that channel.

If another Subscribe method is called with the same ServerMessage that a previous Subscribe mentioned, that will change the subscription for that message to go to the new channel instead of the previous one.

Unless subscribed, the following default behaviors are assumed:

Marco:   Auto-reply with Polo
ERROR:   Log a message
UNKNOWN: Log a message

If any of these are subscribed to, then the default behavior is NOT taken, on the assumption that the code consuming the subscribed events will fully handle an appropriate response.

Further, if AddCharacter or UpdateStatusMarker messages are received from the server, the Connection struct's Characters and Conditions maps are automatically updated (respectively) regardless of whether they are subscribed to.

The default behavior for all other incoming server messages is to ignore them completely. The client will ask the server not to send any non-subscribed messages.

This method may be called on an established connection to change the subscription list on the fly.

If the channel is nil, the message(s) are unsubscribed and will not be received by the client until subscribed to again.

Example: (error checking not shown for the sake of brevity)

cm := make(chan MessagePayload, 1)
service, err := NewConnection(endpoint)
err = service.Subscribe(cm, ChatMessage)

func (*Connection) Sync

func (c *Connection) Sync() error

Sync requests that the server send the entire game state to it.

func (*Connection) SyncChat

func (c *Connection) SyncChat(target int) error

SyncChat requests that the server (re-)send past messages greater than the target message ID (target≥0) or the most recent |target| messages (target<0).

func (*Connection) Toolbar

func (c *Connection) Toolbar(enabled bool) error

Toolbar tells peers to turn on or off their toolbars.

func (*Connection) UNSAFEsendRaw

func (c *Connection) UNSAFEsendRaw(data string) error

UNSAFEsendRaw will send raw data to the server without any checks or controls. Use this function at your own risk. If you don't phrase the data perfectly, the server will not understand your request. This is intended only for testing purposes including manually communicating with the server for debugging.

func (*Connection) UpdateClock

func (c *Connection) UpdateClock(absolute, relative int64, keepRunning bool) error

UpdateClock informs everyone of the current time

func (*Connection) UpdateInitiative

func (c *Connection) UpdateInitiative(ilist []InitiativeSlot) error

UpdateInitiative informs our peers of a change to the inititive order.

func (*Connection) UpdateObjAttributes

func (c *Connection) UpdateObjAttributes(objID string, newAttrs map[string]any) error

UpdateObjAttributes informs peers that they should modify the specified object's attributes which are mentioned in the newAttrs map. This maps attribute names to their new values.

func (*Connection) UpdateStatusMarker

func (c *Connection) UpdateStatusMarker(smd StatusMarkerDefinition) error

UpdateStatusMarker changes, removes, or adds a status marker to place on a creature marker.

func (*Connection) UpdateTurn

func (c *Connection) UpdateTurn(relative float64, actor string) error

UpdateTurn advances the initiative turn clock for connected clients.

type ConnectionOption

type ConnectionOption func(*Connection) error

ConnectionOption is an option to be passed to the NewConnection function.

func StayConnected

func StayConnected(enable bool) ConnectionOption

StayConnected modifies the behavior of the NewConnection call so that when Dial is called on the new Connection, it will continue to try to re-establish connections to the server (if enable is true) until it utterly fails in the attempt. This is useful in case connections to the server tend to get inadvertently dropped, since this will allow the client to automatically reconnect and resume operations.

If enable is false (the default), Dial will return as soon as the server connection is dropped for any reason.

func WithAuthenticator

func WithAuthenticator(a *auth.Authenticator) ConnectionOption

WithAuthenticator modifies the behavior of the NewConnection function by adding an authenticator which will be used to identify the client to the server. If this option is not given, no attempt will be made to authenticate, which is only appropriate for servers which do not require authentication. (Which, hopefully, won't be the case anyway.)

func WithDebugging

func WithDebugging(flags DebugFlags) ConnectionOption

WithDebugging modifies the behavior of the NewConnection function so that the operations of the Connection's interaction with the server are logged to varying levels of verbosity.

func WithLogger

func WithLogger(l *log.Logger) ConnectionOption

WithLogger modifies the behavior of the NewConnection function by specifying a custom logger instead of the default one for the Connection to use during its operations.

func WithRetries

func WithRetries(n uint) ConnectionOption

WithRetries modifies the behavior of the NewConnection function to indicate how many times the Dial method should try to establish a connection to the server before giving up.

Setting this to 0 means to retry infinitely many times. The default is to make a single attempt to connect to the server.

func WithSubscription

func WithSubscription(ch chan MessagePayload, messages ...ServerMessage) ConnectionOption

WithSubscription modifies the behavior of the NewConnection function by adding a server message subscription to the connection just as if the Subscribe method had been called on the connection value.

For example, this:

server, err := NewConnection(endpoint,
                 WithSubscription(chats, ChatMessage, RollResult),
                 WithSubscription(oops, ERROR, UNKNOWN))
go server.Dial()

is equivalent to this:

server, err := NewConnection(endpoint)
err = server.Subscribe(chats, ChatMessage, RollResult)
err = server.Subscribe(oops, ERROR, UNKNOWN)
go server.Dial()

(Of course, real production code should check the returned error values.)

func WithTimeout

func WithTimeout(t time.Duration) ConnectionOption

WithTimeout modifies the behavior of the NewConnection function by specifying the time to allow the Dial method to make the TCP connection to the server. After this time expires, the attempt is abandoned (but may be retried based on the value of WithRetries, if any).

N.B.: When making the initial TCP connection to the server, if there is a timeout value specified via WithTimeout, then a hanging connection will terminate when that timer expires, regardless of the context (although a canceled context will stop retry attempts). Otherwise, the connection will wait indefinitely to complete OR until the context is cancelled.

type Coordinates

type Coordinates struct {
	X, Y float64
}

Coordinates give an (x, y) coordinate pair to locate something on the map. Coordinates are in standard map pixel units (10 pixels = 1 foot).

type CreatureHealth

type CreatureHealth struct {
	// Is the creature flat-footed?
	IsFlatFooted bool `json:",omitempty"`

	// Has the creature been stabilized to prevent death while critically wounded?
	IsStable bool `json:",omitempty"`

	// The maximum hit points possible for the creature.
	MaxHP int `json:",omitempty"`

	// The amount of lethal and non-lethal damage suffered by the creature.
	LethalDamage    int `json:",omitempty"`
	NonLethalDamage int `json:",omitempty"`

	// The grace amount of hit points a creature may suffer over their maximum before
	// they are actually dead (as opposed to critically wounded). This is generally
	// the creature's Constitution score, hence the name.
	Con int `json:",omitempty"`

	// If 0, the creature's health is displayed accurately on the map. Otherwise,
	// this gives the percentage by which to "blur" the hit points as seen by the
	// players. For example, if HPBlur is 10, then hit points are displayed only in
	// 10% increments.
	HPBlur int `json:",omitempty"`

	// Override the map client's idea of how to display the creature's health condition.
	// Normally this is the empty string which allows the client to calculate it from the
	// information available to it.
	Condition string `json:",omitempty"`
}

CreatureHealth describes the current health statistics of a creature if we are tracking it for them.

type CreatureToken

type CreatureToken struct {
	BaseMapObject

	// Is the creature currently dead? (This takes precedence over the
	// Health attribute's indication that the creature has taken a
	// fatal amount of damage.)
	Killed bool `json:",omitempty"`

	// In combat, if this is true, the token is "dimmed" to indicate
	// that it is not their turn to act.
	Dim bool `json:",omitempty"`

	// The creature type.
	CreatureType CreatureTypeCode

	// The method of locomotion currently being used by this creature.
	// Normally this is MoveModeLand for land-based creatures which
	// are walking/running.
	MoveMode MoveModeType `json:",omitempty"`

	// Is the creature currently wielding a reach weapon or otherwise
	// using the "reach" alternate threat zone?
	// If this value is 0, the threat zone is normal for a creature
	// of its size. If 1, an extended area (appropriate for using
	// a reach weapon) is used instead. If 2, both areas are used,
	// so the creature may attack into the reach zone AND adjacent
	// foes.
	Reach int `json:",omitempty"`

	// For creatures which may change their shape or appearance,
	// multiple "skins" may be defined to display as appropriate.
	//
	// Skin is 0 for the default appearance of the creature, 1
	// for the alternate image, 2 for the 2nd alternate image, etc.
	Skin int `json:",omitempty"`

	// Current elevation in feet relative to the "floor" of the
	// current location.
	Elev int `json:",omitempty"`

	// Grid (x, y) coordinates for the reference point of the
	// creature.  Unlike MapElement coordinates, these are in
	// grid units (1 grid = 5 feet).  The upper-left corner of
	// the creature token is at this location.
	Gx, Gy float64

	// The name of the creature as displayed on the map. Must be unique
	// among the other creatures.
	Name string

	// If non-nil, this tracks the health status of the creature.
	Health *CreatureHealth `json:",omitempty"`

	// If the different "skins" are different sizes, this is a list
	// of size codes for each of them. For example, if there are 3
	// skins defined, the first two medium-size and the 3rd large
	// size, then SkinSize would have the value {"M", "M", "L"}.
	// If this is empty or nil, all skins are assumed to be the
	// size specified in the Size attribute. Note that SkinSize
	// also sets the Area at the same time.
	SkinSize []string `json:",omitempty"`

	// The color to draw the creature's threat zone when in combat.
	Color string

	// A note to attach to the creature token to indicate special
	// conditions affecting the creature which are not otherwise shown.
	Note string `json:",omitempty"`

	// The tactical size category of the creature ("S", "M", "L",
	// etc). Lower-case letters indicate the "wide" version of the
	// category while upper-case indicates "tall" versions.
	//
	// May also be the size in feet (DEPRECATED USAGE).
	Size string

	// The tactical threat zone size of the creature, specified just
	// as with Size.
	Area string

	// A list of condition codes which apply to the character. These
	// are arbitrary and defined by the server according to the needs
	// of the particular game, but may include things such
	// as "confused", "helpless", "hasted", etc.
	StatusList []string `json:",omitempty"`

	// If there is a spell effect radiating from the creature, its
	// area of effect is described by this value. If there is none,
	// this is nil.
	//
	// Currently only radius emanations are supported. In future, the
	// type of this attribute may change to handle other shapes.
	AoE *RadiusAoE `json:",omitempty"`
}

CreatureToken is a MapObject (but not a MapElement) which displays a movable token indicating the size and location of a creature in the game.

type CreatureTypeCode

type CreatureTypeCode byte

Creature type codes for the CreatureType field of CreatureToken (and PlayerToken and MonsterToken) values.

const (
	CreatureTypeUnknown CreatureTypeCode = iota
	CreatureTypeMonster
	CreatureTypePlayer
)

type DashType

type DashType byte

These are the allowed values for the Dash attribute of a MapElement.

const (
	DashSolid DashType = iota
	DashLong
	DashMedium
	DashShort
	DashLongShort
	DashLong2Short
)

type DebugFlags

type DebugFlags uint64

Debugging information is enabled by selecting a nummber of discrete topics which you want logged as the application runs (previous versions used a "level" of verbosity which doesn't provide the better granularity this version provides to just get the info you want.

const (
	DebugAuth DebugFlags = 1 << iota
	DebugBinary
	DebugEvents
	DebugIO
	DebugMessages
	DebugMisc
	DebugAll DebugFlags = 0xffffffff
)

func NamedDebugFlags

func NamedDebugFlags(names ...string) (DebugFlags, error)

NamedDebugFlags takes a comma-separated list of debug flag (topic) names, or a list of individual names, or both, and returns the DebugFlags value which includes all of them.

If "none" appears in the list, it cancels all previous values seen, but subsequent names will add their values to the list.

type DefineDicePresetsMessagePayload

type DefineDicePresetsMessagePayload struct {
	BaseMessagePayload
	For     string               `json:",omitempty"`
	Presets []dice.DieRollPreset `json:",omitempty"`
}

type DeniedMessagePayload

type DeniedMessagePayload struct {
	BaseMessagePayload
	Reason string
}

DeniedMessagePayload holds the reason the client was denied access to the server.

type EchoMessagePayload

type EchoMessagePayload struct {
	BaseMessagePayload

	B bool           `json:"b,omitempty"`
	I int            `json:"i,omitempty"`
	S string         `json:"s,omitempty"`
	O map[string]any `json:"o,omitempty"`
}

EchoMessagePayload holds information the client wants echoed back to it. This is typically used to synchronize a client with a server by issuing a number of commands and then sending an Echo packet, waiting for the server to send back the echo so the client knows it's seen the previous messages at that point.

The echo payload may contain an arbitrary boolean, integer, or string value named B, I, and S, respectively, for convenience in keeping track of the client's state or intentions behind sending the echo request. An arbitrary map of named values may also be given as the O value.

type ErrorMessagePayload

type ErrorMessagePayload struct {
	BaseMessagePayload
	OriginalMessageType ServerMessage
	Error               error
}

ErrorMessagePayload describes an error which encountered when trying to receive a message.

type FileDefinition

type FileDefinition struct {
	// If IsLocalFile is true, File is the name of the file on disk;
	// otherwise it is the server's internal ID by which you may request
	// that file from the server.
	IsLocalFile bool `json:",omitempty"`

	// The filename or Server ID.
	File string
}

FileDefinition describes a file as known to the mapper which may be of interest to retrieve at some point.

type FilterDicePresetsMessagePayload

type FilterDicePresetsMessagePayload struct {
	BaseMessagePayload
	Filter string `json:",omitempty"`
	For    string `json:",omitempty"`
}

FilterDicePresetMessagePayload holds the filter expression the client sends to the server.

type FontSlantType

type FontSlantType byte

The valid font slants.

const (
	FontSlantRoman FontSlantType = iota
	FontSlantItalic
)

type FontWeightType

type FontWeightType byte

The valid font weights.

const (
	FontWeightNormal FontWeightType = iota
	FontWeightBold
)

type GrantedMessagePayload

type GrantedMessagePayload struct {
	BaseMessagePayload
	User string
}

GrantedMessagePayload holds the response from the server informing the client that its access was granted.

type ImageDefinition

type ImageDefinition struct {
	// The name of the image as known within the mapper.
	Name  string
	Sizes []ImageInstance
}

ImageDefinition describes an image as known to the mapper system. TileElements' Image attribute refers to the Name attribute of one of these.

type ImageInstance

type ImageInstance struct {
	// If IsLocalFile is true, File is the name of the image file on disk;
	// otherwise it is the server's internal ID by which you may request
	// that file from the server.
	IsLocalFile bool `json:",omitempty"`

	// The zoom (magnification) level this bitmap represents for the given
	// image.
	Zoom float64

	// The filename by which the image can be retrieved.
	File string

	// If non-nil, this holds the image data received directly
	// from the server. This usage is not recommended but still
	// supported.
	ImageData []byte `json:",omitempty"`
}

type InitiativeSlot

type InitiativeSlot struct {
	// The slot number (currently 0–59, corresponding to the 1/10th second "count" in the initiative round)
	Slot int

	// The current hit point total for the creature.
	CurrentHP int

	// The creature's name as displayed on the map.
	Name string

	// If true, the creature is holding their action.
	IsHolding bool `json:",omitempty"`

	// If true, the creature has a readied action.
	HasReadiedAction bool `json:",omitempty"`

	// It true, the creature is flat-footed.
	IsFlatFooted bool `json:",omitempty"`
}

InitiativeSlot describes the creature occupying a given slot of the initiative list.

type JoinStyle

type JoinStyle byte

These are the allowed values for the Join attribute of a PolygonElement.

const (
	JoinBevel JoinStyle = iota
	JoinMiter
	JoinRound
)

type LineElement

type LineElement struct {
	MapElement

	// What arrowheads, if any, to draw on the endpoints
	Arrow ArrowType `json:",omitempty"`
}

LineElement is a MapElement that draws a straight line segment from the reference point to the single point in the Points attribute.

If there are multiple points in the Points attribute, the element will be drawn from each point to the next, as connected line segments.

The line will have arrowheads drawn on the first (reference) point, the last point, both, or neither, as indicated by the Arrow attribute.

N.B.: the lines will be drawn with the Fill color, not the Line color, to match the behavior of the Tk library underlying our client implementations.

type LoadArcObjectMessagePayload

type LoadArcObjectMessagePayload struct {
	BaseMessagePayload
	ArcElement
}

LoadArcObjectMessagePayload holds the information needed to send an arc element to a map.

type LoadCircleObjectMessagePayload

type LoadCircleObjectMessagePayload struct {
	BaseMessagePayload
	CircleElement
}

LoadCircleObjectMessagePayload holds the information needed to send an ellipse element to a map.

type LoadFromMessagePayload

type LoadFromMessagePayload struct {
	BaseMessagePayload
	FileDefinition

	// If true, the client should only pre-load this data into a
	// local cache, but not start displaying these elements yet.
	CacheOnly bool `json:",omitempty"`

	// If true, the elements are merged with the existing map
	// contents rather than replacing them.
	Merge bool `json:",omitempty"`
}

LoadFromMessagePayload holds the information sent by the server's LoadFrom message. This tells the client to open the file named (which may either be a local disk file or one retrieved from the server), and either replacing their current canvas contents with the elements from that file, or adding those elements to the existing contents.

Call the LoadFrom method to send this message out to other clients.

type LoadLineObjectMessagePayload

type LoadLineObjectMessagePayload struct {
	BaseMessagePayload
	LineElement
}

LoadLineObjectMessagePayload holds the information needed to send a line element to a map.

type LoadPolygonObjectMessagePayload

type LoadPolygonObjectMessagePayload struct {
	BaseMessagePayload
	PolygonElement
}

LoadPolygonObjectMessagePayload holds the information needed to send a polygon element to a map.

type LoadRectangleObjectMessagePayload

type LoadRectangleObjectMessagePayload struct {
	BaseMessagePayload
	RectangleElement
}

LoadRectangleObjectMessagePayload holds the information needed to send a rectangle element to a map.

type LoadSpellAreaOfEffectObjectMessagePayload

type LoadSpellAreaOfEffectObjectMessagePayload struct {
	BaseMessagePayload
	SpellAreaOfEffectElement
}

LoadSpellAreaOfEffectObjectMessagePayload holds the information needed to send a spell area of effect element to a map.

type LoadTextObjectMessagePayload

type LoadTextObjectMessagePayload struct {
	BaseMessagePayload
	TextElement
}

LoadTextObjectMessagePayload holds the information needed to send a text element to a map.

type LoadTileObjectMessagePayload

type LoadTileObjectMessagePayload struct {
	BaseMessagePayload
	TileElement
}

LoadTileObjectMessagePayload holds the information needed to send a graphic tile element to a map.

type MapConnection

type MapConnection struct {
	// contains filtered or unexported fields
}

func NewMapConnection

func NewMapConnection(c net.Conn) MapConnection

func (*MapConnection) Close

func (c *MapConnection) Close()

func (*MapConnection) Flush

func (c *MapConnection) Flush() error

Send out all waiting outbound messages and then return

func (*MapConnection) IsReady

func (m *MapConnection) IsReady() bool

func (*MapConnection) Receive

func (c *MapConnection) Receive() (MessagePayload, error)

Receive waits for a message to arrive on the MapConnection's input then returns it.

func (*MapConnection) Send

func (c *MapConnection) Send(command ServerMessage, data any) error

Send sends a message to the peer using the mapper protocol.

func (*MapConnection) UNSAFEsendRaw

func (c *MapConnection) UNSAFEsendRaw(data string) error

UNSAFEsendRaw will send raw data to the server without any checks or controls. Use this function at your own risk. If you don't phrase the data perfectly, the server will not understand your request. This is intended only for testing purposes including manually communicating with the server for debugging.

type MapElement

type MapElement struct {
	BaseMapObject
	Coordinates

	// Is this element currently concealed from view?
	Hidden bool `json:",omitempty"`

	// Is the object locked from editing by the user?
	Locked bool `json:",omitempty"`

	// The element's line(s) are to be drawn with this dash pattern.
	Dash DashType `json:",omitempty"`

	// The z "coordinate" is the vertical stacking order relative to the other
	// displayed on-screen objects.
	Z int

	// The width in pixel units to draw the element's outline.
	Width int `json:",omitempty"`

	// The dungeon level where this element appears. Typically, level 0
	// is the default (ground) level, with level numbers increasing as
	// 1, 2, 3, etc., for floors above it, and with underground levels
	Level int `json:",omitempty"`

	// Objects which need additional coordinate pairs to describe their
	// geometry (beyond the standard reference point) store them here.
	Points []Coordinates `json:",omitempty"`

	// The colors used to draw the element's outline and/or to fill it's interior.
	// These may be standard color names such as "blue" or an RGB string such as
	// "#336699". A fill color that is the empty string means not to fill that element.
	Line string `json:",omitempty"`
	Fill string `json:",omitempty"`

	// The map layer this element belongs to.
	Layer string `json:",omitempty"`

	// Elements may be arranged into logical groups to be manipulated
	// together. This is the ID of the group to which this belongs, or
	// is empty if this element is not grouped.
	Group string `json:",omitempty"`
}

MapElement is a MapObject which represents a static map feature to be displayed.

Each MapElement has at least one pair of (x, y) coordinates which locate the element's "reference point" on the map. What this means is up to each different kind of MapElement.

type MapMetaData

type MapMetaData struct {
	// Timestamp is the generation or modification time of the map file
	// as a 64-bit integer Unix timestamp value.
	Timestamp int64 `json:",omitempty"`

	// DateTime is a human-readable string which gives the same information
	// as Timestamp. The software only uses Timestamp. DateTime is provided
	// only for convenience and is not guaranteed to match Timestamp's time
	// value or even any valid value at all. The format is this string is
	// arbitrary.
	DateTime string `json:",omitempty"`

	// Comment is any brief comment the map author wishes to leave in the file
	// about this map.
	Comment string `json:",omitempty"`

	// Location is a string describing the locale within the adventure area or
	// world which is represented by this file.
	Location string `json:",omitempty"`

	// FileVersion is the file format version number detected when reading in
	// the data from this file. This is for informational purposes only and does
	// not control the format used to write the data to a new file.
	FileVersion uint `json:"-"`
}

MapMetaData describes a mapper location save file (itself, not its contents)

func LoadMapFile

func LoadMapFile(input io.Reader) ([]any, MapMetaData, error)

LoadMapFile reads GMA mapper data from an already-open data stream, returning a slice of map elements and the metadata read from the stream.

If called with a nil input object, it just returns with empty data values.

func LoadMapMetaData

func LoadMapMetaData(input io.Reader) (MapMetaData, error)

LoadMapMetaData is just like LoadMapFile but only reads enough of the file to get the meta data, which is returned.

func ReadMapFile

func ReadMapFile(path string) ([]any, MapMetaData, error)

ReadMapFile loads GMA mapper data from the named file, returning the data as three values: a slice of MapObject values (which the caller will want to interpret based on their actual data type), the file metadata, and an error (which will be nil if everything went as planned).

Other than opening the named input file, it is identical to LoadMapFile.

func ReadMapMetaData

func ReadMapMetaData(path string) (MapMetaData, error)

ReadMapMetaData is just like ReadMapFile, except that it only goes as far as reading the metadata from the file, returning that, but including any of the actual map data.

Its operation is identical to LoadMapMetaData other than opening the input file for you.

type MapObject

type MapObject interface {
	ObjID() string
}

MapObject is anything the map server or client tracks and manages. These are generally things that are displayed on-screen such as map features, creature tokens, etc.

type MapServer

type MapServer interface {
	Log(messsage ...any)
	Logf(format string, args ...any)
	GetPersonalCredentials(user string) []byte
	GetClientPreamble() *ClientPreamble
	HandleServerMessage(MessagePayload, *ClientConnection)
	AddClient(*ClientConnection)
	RemoveClient(*ClientConnection)
	SendGameState(*ClientConnection)
}

type MarcoMessagePayload

type MarcoMessagePayload struct {
	BaseMessagePayload
}

MarcoMessagePayload holds the information sent by the server's Marco message. This is a "ping" message the server periodically sends to all clients to ensure they are still responding. A client who receives a MARCO message is expected to respond with a POLO message.

If the client doesn't subscribe to Marco messages, the Dial method will automatically reply with Polo messages.

type MarkMessagePayload

type MarkMessagePayload struct {
	BaseMessagePayload
	Coordinates
}

MarkMessagePayload holds the information sent by the server's Mark message. This tells the client to visually mark the given map coordinates.

Call the Mark method to send this message out to other clients.

type MessagePayload

type MessagePayload interface {
	MessageType() ServerMessage
	RawMessage() string
	RawBytes() []byte
}

MessagePayload is an interface that includes any kind of message the server will send to us.

type MonsterToken

type MonsterToken struct {
	CreatureToken
}

MonsterToken is a CreatureToken which describes a monster or NPC adversary.

type MoveModeType

type MoveModeType byte

The valid values for a creature's MoveMode attribute.

const (
	MoveModeLand MoveModeType = iota
	MoveModeBurrow
	MoveModeClimb
	MoveModeFly
	MoveModeSwim
)

type OptionalFeature

type OptionalFeature byte
const (
	DiceColorBoxes OptionalFeature = iota
)

type PackageUpdate

type PackageUpdate struct {
	Name      string
	Instances []PackageVersion
}

type PackageVersion

type PackageVersion struct {
	OS      string `json:",omitempty"`
	Arch    string `json:",omitempty"`
	Version string
	Token   string `json:",omitempty"`
}

type Peer

type Peer struct {
	// IP address and port of the peer
	Addr string

	// The username provided by the peer when it authenticated
	User string

	// A description of the peer client program (provided by that client)
	Client string `json:",omitempty"`

	// How many seconds ago the peer last answered a "still alive?" ping from the server
	LastPolo float64

	// True if the client authenticated successfully
	IsAuthenticated bool `json:",omitempty"`

	// True if this structure describes the connection of this client program
	IsMe bool `json:",omitempty"`
}

Peer describes each peer we can reach via our server connection.

type PlaceSomeoneMessagePayload

type PlaceSomeoneMessagePayload struct {
	BaseMessagePayload
	CreatureToken
}

PlaceSomeoneMessagePayload holds the information sent by the server's PlaceSomeone message. This tells the client to introduce a new creature token, or if that token is already on the board, update it with the new information (usually just moving its location).

Retain any existing attributes in the original which have nil values here (notably, this server message never carries health stats so that structure will always be nil).

Call the PlaceSomeone method to send this message out to other clients.

type PlayerToken

type PlayerToken struct {
	CreatureToken
}

PlayerToken is a CreatureToken which describes a player character or NPC ally.

type PoloMessagePayload

type PoloMessagePayload struct {
	BaseMessagePayload
}

type PolygonElement

type PolygonElement struct {
	MapElement

	// The join style to control how the intersection between line segments is drawn.
	Join JoinStyle `json:",omitempty"`

	// Spline gives the factor to use when smoothing the sides of the polygon between
	// its points. 0 means not to smooth them at all, resulting in a shape with straight
	// edges between the vertices. Otherwise, larger values provide greater smoothing.
	Spline float64 `json:",omitempty"`
}

PolygonElement is a MapElement that draws an arbitrary polygon, just as with the LineElement, but the interior of the shape described by the line segments may be filled in as a solid shape.

type PrivMessagePayload

type PrivMessagePayload struct {
	BaseMessagePayload
	Command string
	Reason  string
}

type ProtocolMessagePayload

type ProtocolMessagePayload struct {
	BaseMessagePayload
	ProtocolVersion int
}

ProtocolMessagePayload describes the server's statement of what protocol version it implements.

type QueryDicePresetsMessagePayload

type QueryDicePresetsMessagePayload struct {
	BaseMessagePayload
	For string `json:",omitempty"`
}

type QueryImageMessagePayload

type QueryImageMessagePayload struct {
	BaseMessagePayload
	ImageDefinition
}

QueryImageMessagePayload holds the information sent by the server's QueryImage message. This tells the client that a peer wants to know where to find a given image and the server didn't know either. If you know the definition for that image, reply with an AddImage message of your own.

Call the QueryImage method to send this message out to other clients.

type QueryPeersMessagePayload

type QueryPeersMessagePayload struct {
	BaseMessagePayload
}

type RadiusAoE

type RadiusAoE struct {
	// Distance in standard map pixels away from the creature token's center
	// to the perimeter of the affected area.
	Radius float64

	// Color to draw the affected zone.
	Color string
}

RadiusAoE describes the area of some spell or special effect emanating from the creature.

type ReadyMessagePayload

type ReadyMessagePayload struct {
	BaseMessagePayload
}

ReadyMessagePayload indicates that the server is fully ready to interact with the client and all preliminary data has been sent to the client.

type RectangleElement

type RectangleElement struct {
	MapElement
}

RectangleElement is a MapElement which describes a rectangle as defined by diagonally opposing points: the reference point and the single coordinate pair in the Points attribute.

type RemoveObjAttributesMessagePayload

type RemoveObjAttributesMessagePayload struct {
	BaseMessagePayload

	// The ID of the object to be modified
	ObjID string

	// The name of the attribute to modify. Must be one with a []string value.
	AttrName string

	// The values to remove from the attribute.
	Values []string
}

RemoveObjAttributesMessagePayload holds the information sent by the server's RemoveObjAttributes message. This tells the client to adjust the multi-value attribute of the object with the given ID by removing the listed values from it.

Call the RemoveObjAttributes method to send this message out to other clients.

type RollDiceMessagePayload

type RollDiceMessagePayload struct {
	BaseMessagePayload
	ChatCommon

	// If you want to track the results to the requests that created them,
	// put a unique ID here. It will be repeated in the corresponding result(s).
	RequestID string `json:",omitempty"`

	// RollSpec describes the dice to be rolled and any modifiers.
	RollSpec string
}

RollDiceMessagePayload holds the data sent from the client to the server when requesting a die roll.

type RollResultMessagePayload

type RollResultMessagePayload struct {
	BaseMessagePayload
	ChatCommon

	// True if there will be more results following this one for the same request
	MoreResults bool `json:",omitempty"`

	// The ID string passed by the user to associate this result with their request (may be blank)
	RequestID string `json:",omitempty"`

	// The title describing the purpose of the die-roll, as set by the user.
	Title string `json:",omitempty"`

	// The die roll result and details behind where it came from.
	Result dice.StructuredResult
}

RollResultMessagePayload holds the information sent by the server's RollResult message. This tells the client the results of a die roll.

type ServerMessage

type ServerMessage byte

ServerMessage is an arbitrary code which identifies specific message types that we can receive from the server. This value is passed to the Subscribe method and returned by the MessageType method. These values are intended for use within an actively-running program but are not guaranteed to remain stable across new releases of the code, so they should not be stored and re-used by a later execution of the client, nor passed to other programs whose definition of these values may not agree.

const (
	Accept ServerMessage = iota
	AddCharacter
	AddDicePresets
	AddImage
	AddObjAttributes
	AdjustView
	Allow
	Auth
	Challenge
	ChatMessage
	Clear
	ClearChat
	ClearFrom
	CombatMode
	Comment
	DefineDicePresets
	Denied
	Echo
	FilterDicePresets
	Granted
	LoadFrom
	LoadArcObject
	LoadCircleObject
	LoadLineObject
	LoadPolygonObject
	LoadRectangleObject
	LoadSpellAreaOfEffectObject
	LoadTextObject
	LoadTileObject
	Marco
	Mark
	PlaceSomeone
	Polo
	Priv
	Protocol
	QueryDicePresets
	QueryImage
	QueryPeers
	Ready
	RemoveObjAttributes
	RollDice
	RollResult
	Sync
	SyncChat
	Toolbar
	UpdateClock
	UpdateDicePresets
	UpdateInitiative
	UpdateObjAttributes
	UpdatePeerList
	UpdateProgress
	UpdateStatusMarker
	UpdateTurn
	UpdateVersions
	World
	UNKNOWN
	ERROR
)

ServerMessage values (see the comments accompanying the type definition).

type SpellAreaOfEffectElement

type SpellAreaOfEffectElement struct {
	MapElement

	// The shape of the affected region of the map.
	AoEShape AoEType
}

SpellAreaOfEffectElement is a MapElement that shows a region on the map affected by a spell or other area effect.

The region has one of the following shapes as indicated by the AoEShape attribute:

cone    A 90° pieslice described as with ArcElement
radius  An ellipse described as with CircleElement
ray     A rectangle described as with RectangleElement

type StatusMarkerDefinition

type StatusMarkerDefinition struct {
	// The name of the condition
	Condition string

	// The shape of the marker to be drawn on the token. This may
	// be one of the following:
	//   |v  small downward-pointing triangle against the left edge
	//   v|  small downward-pointing triangle against the right edge
	//   |o  small circle against the left edge
	//   o|  small circle against the right edge
	//   |<> small diamond against the left edge
	//   <>| small diamond against the right edge
	//   /   slash from upper right to lower left
	//   \   slash from upper left to lower right
	//   //  double slash from upper right to lower left
	//   \\  double slash from upper left to lower right
	//   -   horizontal line through the center of the token
	//   =   double horizontal line through the center
	//   |   vertical line through the center
	//   ||  double vertical line through the center
	//   +   cross (vertical and horizontal lines) through center
	//   #   double cross (vertical and horizontal lines) through center
	//   V   large downward-pointing triangle around token
	//   ^   large upward-pointing triangle around token
	//   <>  large diamond around token
	//   O   large circle around token
	Shape string

	// The color to draw the marker. If the name begins with a pair
	// of hyphens (e.g., "--red") then the marker is drawn with long
	// dashed lines. If it begins with dots (e.g., "..blue") it is
	// drawn with short dashed lines.
	//
	// The special color "*" may be used to indicate that the marker
	// should be drawn in the same color as the creature's threat zone.
	Color string

	// A player-readable description of the effect the condition has on
	// the affected creature.
	Description string `json:",omitempty"`
}

StatusMarkerDefinition describes each creature token status that the map clients indicate.

func (StatusMarkerDefinition) Text

func (c StatusMarkerDefinition) Text() string

Text produces a simple text description of a StatusMarkerDefinition structure.

type StatusMarkerDefinitions

type StatusMarkerDefinitions map[string]StatusMarkerDefinition

StatusMarkerDefinitions is a map of a condition code name to the full description of the marker to use for that condition.

func (StatusMarkerDefinitions) Text

func (cs StatusMarkerDefinitions) Text() string

Text produces a simple text description of a map of StatusMarkerDefinitions as a multi-line string.

type SyncChatMessagePayload

type SyncChatMessagePayload struct {
	BaseMessagePayload
	Target int `json:",omitempty"`
}

type SyncMessagePayload

type SyncMessagePayload struct {
	BaseMessagePayload
}

type TextElement

type TextElement struct {
	MapElement

	// Where is the reference point in relation to the text?
	Anchor AnchorDirection `json:",omitempty"`

	// The text to be displayed.
	Text string

	// Font to use for the text.
	Font TextFont
}

TextElement is a MapElement which displays text on the map.

The reference point is at the center of the text if Anchor is AnchorCenter, or is at the top-left corner of the text if Anchor is AnchorNW, and so on.

type TextFont

type TextFont struct {
	// The name of the font family as recognized by Tk.
	Family string

	// The font size as recognized by Tk.
	Size float64

	// The font weight (normal or bold).
	Weight FontWeightType `json:",omitempty"`

	// The font slant (roman or italic).
	Slant FontSlantType `json:",omitempty"`
}

TextFont describes a font used by TextElements.

type TileElement

type TileElement struct {
	MapElement

	// Image name as known to the mapper system.
	Image string

	// Bounding box in pixels for the image tile.
	// If for some reason the tile can't be found, clients
	// can use the bounding box to indicate where the tile should be.
	// If the bounding box is not known, these values may both
	// be zero.
	BBHeight, BBWidth float64 `json:",omitempty"`
}

TileElement is a MapElement which displays a bitmap image on the map. The upper-left corner of the image will be drawn at the reference point.

type ToolbarMessagePayload

type ToolbarMessagePayload struct {
	BaseMessagePayload
	Enabled bool `json:",omitempty"`
}

ToolbarMessagePayload holds the information sent by the server's Toolbar message. This tells the client to display or hide its toolbar.

type UnknownMessagePayload

type UnknownMessagePayload struct {
	BaseMessagePayload
}

UnknownMessagePayload describes a server message we received but have no idea what it is.

type UpdateClockMessagePayload

type UpdateClockMessagePayload struct {
	BaseMessagePayload

	// The clock is now at the given absolute number of
	// seconds from the GMA clock's global epoch.
	Absolute int64

	// The elapsed time counter is now this many seconds from
	// some reference point set by the GM (often the start of
	// combat).
	Relative int64

	// If true and not in combat mode, local clients should
	// keep running the clock in real time.
	Running bool `json:",omitempty"`
}

UpdateClockMessagePayload holds the information sent by the server's UpdateClock message. This tells the client to update its clock display to the new value.

type UpdateDicePresetsMessagePayload

type UpdateDicePresetsMessagePayload struct {
	BaseMessagePayload
	Presets []dice.DieRollPreset
}

UpdateDicePresetsMessagePayload holds the information sent by the server's UpdateDicePresets message. This tells the client to accept the die-roll presets described here, replacing any previous presets it was using.

type UpdateInitiativeMessagePayload

type UpdateInitiativeMessagePayload struct {
	BaseMessagePayload
	InitiativeList []InitiativeSlot
}

UpdateInitiativeMessagePayload holds the information sent by the server's UpdateInitiative message. This tells the client that the initiative order has been changed. Its current notion of the initiative order should be replaced by the one given here.

type UpdateObjAttributesMessagePayload

type UpdateObjAttributesMessagePayload struct {
	BaseMessagePayload

	// The ID of the object to be modified.
	ObjID string

	// A map of attribute name to its new value.
	NewAttrs map[string]any
}

UpdateObjAttributesMessagePayload holds the information sent by the server's UpdateObjAttributes message. This tells the client to update an existing object with new attributes. Any attributes not listed here should remain intact.

Call the UpdateObjAttributes method to send this message out to other clients.

type UpdatePeerListMessagePayload

type UpdatePeerListMessagePayload struct {
	BaseMessagePayload
	PeerList []Peer
}

UpdatePeerListMessagePayload holds the information sent by the server's UpdatePeerList message. This tells the client that the list of other connected peers has changed.

type UpdateProgressMessagePayload

type UpdateProgressMessagePayload struct {
	BaseMessagePayload

	// If true, we can dispose of the tracked operation
	// and should not expect further updates about it.
	IsDone bool `json:",omitempty"`

	// The current progress toward MaxValue.
	Value int

	// The maximum expected value for the progress indication.
	// If this is 0, we don't yet know what the maximum will be.
	// Note that this may change from one message to another, if
	// the server realizes its previous estimate was incorrect.
	MaxValue int `json:",omitempty"`

	// Unique identifier for the operation we're tracking
	OperationID string

	// Description of the operation in progress, suitable for display.
	Title string `json:",omitempty"`
}

UpdateProgressMessagePayload holds the information sent by the server's UpdateProgress Comment notification. This advises the client of the status of an operation in progress. The client may wish to display a progress indicator to the user.

type UpdateStatusMarkerMessagePayload

type UpdateStatusMarkerMessagePayload struct {
	BaseMessagePayload
	StatusMarkerDefinition
}

UpdateStatusMarkerMessagePayload holds the information sent by the server's UpdateStatusMarker message. This tells the client to add or change a status marker which may be placed on creature tokens.

Note: the server usually sends these upon login, which the Connection struct stores internally.

type UpdateTurnMessagePayload

type UpdateTurnMessagePayload struct {
	BaseMessagePayload

	// The ObjID of the creature whose turn it is. This may also be one of:
	//   *Monsters*   All monsters are up now.
	//   (empty)      It is no one's turn now.
	//   /regex       All creatures whose names match regex
	ActorID string

	// The time lapsed so far since the start of combat.
	// Count is the initiative slot within the round.
	Hours, Minutes, Seconds, Rounds, Count int
}

UpdateTurnMessagePayload holds the information sent by the server's UpdateTurn message. This tells the client whose turn it is in combat.

type UpdateVersionsMessagePayload

type UpdateVersionsMessagePayload struct {
	BaseMessagePayload
	Packages []PackageUpdate `json:",omitempty"`
}

type WorldMessagePayload

type WorldMessagePayload struct {
	BaseMessagePayload
	Calendar string
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL