github.com/df-mc/dragonfly@v0.9.13/server/player/scoreboard/scoreboard.go (about)

     1  package scoreboard
     2  
     3  import (
     4  	"fmt"
     5  	"slices"
     6  	"strings"
     7  )
     8  
     9  // Scoreboard represents a scoreboard that may be sent to a player. The scoreboard is shown on the right side
    10  // of the player's screen.
    11  // Scoreboard implements the io.Writer and io.StringWriter interfaces. fmt.Fprintf and fmt.Fprint may be used
    12  // to write formatted text to the scoreboard.
    13  type Scoreboard struct {
    14  	name    string
    15  	lines   []string
    16  	padding bool
    17  }
    18  
    19  // New returns a new scoreboard with the display name passed. Once returned, lines may be added to the
    20  // scoreboard to add text to it. The name is formatted according to the rules of fmt.Sprintln.
    21  // Changing the scoreboard after sending it to a player will not update the scoreboard of the player
    22  // automatically: Player.SendScoreboard() must be called again to update it.
    23  func New(name ...any) *Scoreboard {
    24  	return &Scoreboard{name: strings.TrimSuffix(fmt.Sprintln(name...), "\n"), padding: true}
    25  }
    26  
    27  // Name returns the display name of the scoreboard, as passed during the construction of the scoreboard.
    28  func (board *Scoreboard) Name() string {
    29  	return board.name
    30  }
    31  
    32  // Write writes a slice of data as text to the scoreboard. Newlines may be written to create a new line on
    33  // the scoreboard.
    34  func (board *Scoreboard) Write(p []byte) (n int, err error) {
    35  	return board.WriteString(string(p))
    36  }
    37  
    38  // WriteString writes a string of text to the scoreboard. Newlines may be written to create a new line on
    39  // the scoreboard.
    40  func (board *Scoreboard) WriteString(s string) (n int, err error) {
    41  	lines := strings.Split(s, "\n")
    42  	board.lines = append(board.lines, lines...)
    43  
    44  	// Scoreboards can have up to 15 lines. (16 including the title.)
    45  	if len(board.lines) >= 15 {
    46  		return len(lines), fmt.Errorf("write scoreboard: maximum of 15 lines of text exceeded")
    47  	}
    48  	return len(lines), nil
    49  }
    50  
    51  // Set changes a specific line in the scoreboard and adds empty lines until this index is reached. Set panics if the
    52  // index passed is negative or 15+.
    53  func (board *Scoreboard) Set(index int, s string) {
    54  	if index < 0 || index >= 15 {
    55  		panic(fmt.Sprintf("index out of range %v", index))
    56  	}
    57  	if diff := index - (len(board.lines) - 1); diff > 0 {
    58  		board.lines = append(board.lines, make([]string, diff)...)
    59  	}
    60  	// Remove new lines from the string
    61  	board.lines[index] = strings.TrimSuffix(strings.TrimSuffix(s, "\n"), "\n")
    62  }
    63  
    64  // Remove removes a specific line from the scoreboard. Remove panics if the index passed is negative or 15+.
    65  func (board *Scoreboard) Remove(index int) {
    66  	if index < 0 || index >= 15 {
    67  		panic(fmt.Sprintf("index out of range %v", index))
    68  	}
    69  	board.lines = append(board.lines[:index], board.lines[index+1:]...)
    70  }
    71  
    72  // RemovePadding removes the padding of one space that is added to the start of every line.
    73  func (board *Scoreboard) RemovePadding() {
    74  	board.padding = false
    75  }
    76  
    77  // Lines returns the data of the Scoreboard as a slice of strings.
    78  func (board *Scoreboard) Lines() []string {
    79  	lines := slices.Clone(board.lines)
    80  	if board.padding {
    81  		for i, line := range lines {
    82  			if len(board.name)-len(line)-2 <= 0 {
    83  				lines[i] = " " + line + " "
    84  				continue
    85  			}
    86  			lines[i] = " " + line + strings.Repeat(" ", len(board.name)-len(line)-2)
    87  		}
    88  	}
    89  	return lines
    90  }