package state import ( "fmt" "github.com/rs/xid" "go.uber.org/zap/zapcore" ) // HexOrientation is the enum for the direction hexes are facing. type HexOrientation uint8 const ( // UnknownOrientation indicates that an invalid orientation was specified. UnknownOrientation HexOrientation = 0 // PointyTop indicates hexes that have a pair of sides on either side in the horizontal direction, // and points on the top and bottom in the vertical direction. PointyTop HexOrientation = 1 // FlatTop indicates hexes that have a pair of points on either side in the horizontal direction, // and sides on the top and bottom in the vertical direction. FlatTop HexOrientation = 2 ) // String returns the equivalent JavaScript constant name. func (o HexOrientation) String() string { switch o { case PointyTop: return "POINTY_TOP" case FlatTop: return "FLAT_TOP" default: return fmt.Sprintf("[unknown HexOrientation %d]", o) } } // LineParity indicates whether odd or even lines are indented. type LineParity uint8 const ( // UnknownParity indicates that parity was not specified or unknown. UnknownParity LineParity = 0 // OddLines indicates that odd lines - 1, 3, 5... - are indented by 1/2 cell. OddLines LineParity = 1 // EvenLines indicates that even lines - 0, 2, 4... - are indented by 1/2 cell. EvenLines LineParity = 2 ) // String returns the equivalent JavaScript constant name. func (o LineParity) String() string { switch o { case OddLines: return "ODD_LINES" case EvenLines: return "EVEN_LINES" default: return fmt.Sprintf("[unknown LineParity %d]", o) } } // Layout combines HexOrientation and LineParity to represent a map's display mode. type Layout struct { Orientation HexOrientation `json:"orientation"` IndentedLines LineParity `json:"indentedLines"` } func (l Layout) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddString("orientation", l.Orientation.String()) encoder.AddString("indentedLines", l.IndentedLines.String()) return nil } // HexCell contains data for a single cell of the map. type HexCell struct { // Color contains the color of the cell, in hex notation. Color Color `json:"color"` } func (h HexCell) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddString("color", h.Color.String()) return nil } // HexLine is a line of cells which are adjacent by flat sides in a vertical or horizontal direction. type HexLine []HexCell func (l HexLine) MarshalLogArray(encoder zapcore.ArrayEncoder) error { var finalErr error for _, cell := range l { err := encoder.AppendObject(cell) if err != nil && finalErr == nil { finalErr = err } } return finalErr } // Copy creates a deep copy of this HexLine. func (l HexLine) Copy() HexLine { duplicate := make(HexLine, len(l)) for index, value := range l { duplicate[index] = value } return duplicate } // HexLayer is a two-dimensional plane of cells which are arranged into lines. type HexLayer []HexLine func (l HexLayer) MarshalLogArray(encoder zapcore.ArrayEncoder) error { var finalErr error for _, line := range l { err := encoder.AppendArray(line) if err != nil && finalErr == nil { finalErr = err } } return finalErr } // GetCellAt returns a reference to the cell at the given coordinates. // If the coordinates are out of bounds for this map, an error will be returned. func (l HexLayer) GetCellAt(c StorageCoordinates) (*HexCell, error) { if int(c.Line) > len(l) { return nil, fmt.Errorf("line %d out of bounds (%d)", c.Line, len(l)) } line := l[c.Line] if int(c.Cell) > len(line) { return nil, fmt.Errorf("cell %d out of bounds (%d)", c.Cell, len(line)) } return &(line[c.Cell]), nil } // Copy creates a deep copy of this HexLayer. func (l HexLayer) Copy() HexLayer { duplicate := make(HexLayer, len(l)) for index, value := range l { duplicate[index] = value.Copy() } return duplicate } // HexMap contains the data for a map instance. type HexMap struct { // XID is the unique id of the HexMap, used to encourage clients not to blindly interact with a different map. XID xid.ID `json:"xid"` // Lines is the rough number of rows (in PointyTop orientation) or columns (in FlatTop orientation) in the map. // Because different lines will be staggered, it's somewhat hard to see. Lines uint8 `json:"lines"` // CellsPerLine is the rough number of columns (in PointyTop orientation) or rows (in FlatTop orientation). // This is the number of cells joined together, flat-edge to flat-edge, in each line. CellsPerLine uint8 `json:"cellsPerLine"` // Layout is the orientation and line parity used to display the map. Layout Layout `json:"displayMode"` // Layer contains the actual map data. // Layer itself is a slice with Lines elements, each of which is a line; // each of those lines is a slice of CellsPerLine cells. Layer HexLayer `json:"lineCells"` } func (m HexMap) MarshalLogObject(encoder zapcore.ObjectEncoder) error { encoder.AddString("id", m.XID.String()) encoder.AddUint8("lines", m.Lines) encoder.AddUint8("cellsPerLine", m.CellsPerLine) displayModeErr := encoder.AddObject("displayMode", m.Layout) lineCellsErr := encoder.AddArray("lineCells", m.Layer) if displayModeErr != nil { return displayModeErr } else { return lineCellsErr } } // Copy creates a deep copy of this HexMap. func (m HexMap) Copy() HexMap { return HexMap{ XID: m.XID, Lines: m.Lines, CellsPerLine: m.CellsPerLine, Layout: m.Layout, Layer: m.Layer.Copy(), } }