package session import ( "time" "github.com/df-mc/dragonfly/server/player/chat" "github.com/df-mc/dragonfly/server/player/scoreboard" "github.com/sandertv/gophertunnel/minecraft/protocol" "github.com/sandertv/gophertunnel/minecraft/protocol/packet" "golang.org/x/text/language" ) // SendMessage ... func (s *Session) SendMessage(message string) { s.writePacket(&packet.Text{ TextType: packet.TextTypeRaw, Message: message, }) } // SendTranslation sends a translation localised for a specific language.Tag. func (s *Session) SendTranslation(t chat.Translation, l language.Tag, a []any) { tr := t.F(a...) s.writePacket(&packet.Text{ TextType: packet.TextTypeTranslation, NeedsTranslation: true, Message: tr.Resolve(l), Parameters: tr.Params(l), }) } // SendTip ... func (s *Session) SendTip(message string) { s.writePacket(&packet.Text{ TextType: packet.TextTypeTip, Message: message, }) } // SendAnnouncement ... func (s *Session) SendAnnouncement(message string) { s.writePacket(&packet.Text{ TextType: packet.TextTypeAnnouncement, Message: message, }) } // SendPopup ... func (s *Session) SendPopup(message string) { s.writePacket(&packet.Text{ TextType: packet.TextTypePopup, Message: message, }) } // SendJukeboxPopup ... func (s *Session) SendJukeboxPopup(message string) { s.writePacket(&packet.Text{ TextType: packet.TextTypeJukeboxPopup, Message: message, }) } // SendToast ... func (s *Session) SendToast(title, message string) { s.writePacket(&packet.ToastRequest{ Title: title, Message: message, }) } // SendScoreboard ... func (s *Session) SendScoreboard(sb *scoreboard.Scoreboard) { if s == Nop { return } currentName, currentLines := *s.currentScoreboard.Load(), *s.currentLines.Load() if currentName != sb.Name() { s.RemoveScoreboard() pk := &packet.SetDisplayObjective{ DisplaySlot: "sidebar", ObjectiveName: sb.Name(), DisplayName: sb.Name(), CriteriaName: "dummy", } if sb.Descending() { pk.SortOrder = packet.ScoreboardSortOrderDescending } else { pk.SortOrder = packet.ScoreboardSortOrderAscending } s.writePacket(pk) name, lines := sb.Name(), append([]string(nil), sb.Lines()...) s.currentScoreboard.Store(&name) s.currentLines.Store(&lines) } else { // Remove all current lines from the scoreboard. We can't replace them without removing them. pk := &packet.SetScore{ActionType: packet.ScoreboardActionRemove} for i := range currentLines { pk.Entries = append(pk.Entries, protocol.ScoreboardEntry{ EntryID: int64(i), ObjectiveName: currentName, Score: int32(i), }) } if len(pk.Entries) > 0 { s.writePacket(pk) } } pk := &packet.SetScore{ActionType: packet.ScoreboardActionModify} for k, line := range sb.Lines() { if len(line) == 0 { line = "ยง" + colours[k] } pk.Entries = append(pk.Entries, protocol.ScoreboardEntry{ EntryID: int64(k), ObjectiveName: sb.Name(), Score: int32(k), IdentityType: protocol.ScoreboardIdentityFakePlayer, DisplayName: line, }) } if len(pk.Entries) > 0 { s.writePacket(pk) } } // colours holds a list of colour codes to be filled out for empty lines in a scoreboard. var colours = [15]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"} // RemoveScoreboard ... func (s *Session) RemoveScoreboard() { s.writePacket(&packet.RemoveObjective{ObjectiveName: *s.currentScoreboard.Load()}) var name string var lines []string s.currentScoreboard.Store(&name) s.currentLines.Store(&lines) } // SendBossBar sends a boss bar to the player with the text passed and the health percentage of the bar. // SendBossBar removes any boss bar that might be active before sending the new one. func (s *Session) SendBossBar(text string, colour uint8, healthPercentage float64) { s.RemoveBossBar() s.writePacket(&packet.BossEvent{ BossEntityUniqueID: selfEntityRuntimeID, EventType: packet.BossEventShow, BossBarTitle: text, HealthPercentage: float32(healthPercentage), Colour: colour, }) } // RemoveBossBar removes any boss bar currently active on the player's screen. func (s *Session) RemoveBossBar() { s.writePacket(&packet.BossEvent{ BossEntityUniqueID: selfEntityRuntimeID, EventType: packet.BossEventHide, }) } const tickLength = time.Second / 20 // SetTitleDurations ... func (s *Session) SetTitleDurations(fadeInDuration, remainDuration, fadeOutDuration time.Duration) { s.writePacket(&packet.SetTitle{ ActionType: packet.TitleActionSetDurations, FadeInDuration: int32(fadeInDuration / tickLength), RemainDuration: int32(remainDuration / tickLength), FadeOutDuration: int32(fadeOutDuration / tickLength), }) } // SendTitle ... func (s *Session) SendTitle(text string) { s.writePacket(&packet.SetTitle{ActionType: packet.TitleActionSetTitle, Text: text}) } // SendSubtitle ... func (s *Session) SendSubtitle(text string) { s.writePacket(&packet.SetTitle{ActionType: packet.TitleActionSetSubtitle, Text: text}) } // SendActionBarMessage ... func (s *Session) SendActionBarMessage(text string) { s.writePacket(&packet.SetTitle{ActionType: packet.TitleActionSetActionBar, Text: text}) }