diff --git a/pkg/edition/java/proto/packet/plugin/util.go b/pkg/edition/java/proto/packet/plugin/util.go index 58cb3229..bda11821 100644 --- a/pkg/edition/java/proto/packet/plugin/util.go +++ b/pkg/edition/java/proto/packet/plugin/util.go @@ -117,7 +117,7 @@ func RewriteMinecraftBrand(message *Message, protocol proto.Protocol) *Message { return message } - currentBrand := readBrandMessage(message.Data) + currentBrand := ReadBrandMessage(message.Data) rewrittenBrand := fmt.Sprintf("%s (Gate by Minekube)", currentBrand) rewrittenBuf := new(bytes.Buffer) @@ -133,11 +133,14 @@ func RewriteMinecraftBrand(message *Message, protocol proto.Protocol) *Message { } } +// ReadBrandMessage reads the brand message from the given packet data. +// The returned string will be empty if the data is invalid. +// // Some clients (mostly poorly-implemented bots) do not send validly-formed brand messages. // In order to accommodate their broken behavior, we'll first try to read in the 1.8 format, and // if that fails, treat it as a 1.7-format message (which has no prefixed length). // (The message the proxy sends will be in the correct format depending on the protocol.) -func readBrandMessage(data []byte) string { +func ReadBrandMessage(data []byte) string { s, err := util.ReadString(bytes.NewReader(data)) if err != nil { s, _ = util.ReadStringWithoutLen(bytes.NewReader(data)) diff --git a/pkg/edition/java/proxy/player.go b/pkg/edition/java/proxy/player.go index 0e76f76a..03a44750 100644 --- a/pkg/edition/java/proxy/player.go +++ b/pkg/edition/java/proxy/player.go @@ -75,6 +75,7 @@ type Player interface { // SendActionBar sends an action bar to the player. SendActionBar(msg component.Component) error TabList() tablist.TabList // Returns the player's tab list. + ClientBrand() string // Returns the player's client brand. Empty if unspecified. // Looking for title or bossbar methods? See the title and bossbar packages. } @@ -107,6 +108,7 @@ type connectedPlayer struct { previousResourceResponse *bool pendingResourcePack *ResourcePackInfo appliedResourcePack *ResourcePackInfo + clientBrand string // may be empty serversToTry []string // names of servers to try if we got disconnected from previous tryIndex int @@ -699,3 +701,16 @@ func (p *connectedPlayer) switchToConfigState(pkt *cfgpacket.StartUpdate) { } p.SetState(state.Config) } + +func (p *connectedPlayer) ClientBrand() string { + p.mu.RLock() + defer p.mu.RUnlock() + return p.clientBrand +} + +// setClientBrand sets the client brand of the player. +func (p *connectedPlayer) setClientBrand(brand string) { + p.mu.Lock() + p.clientBrand = brand + p.mu.Unlock() +} diff --git a/pkg/edition/java/proxy/session_client_play.go b/pkg/edition/java/proxy/session_client_play.go index c3824523..fa9956bf 100644 --- a/pkg/edition/java/proxy/session_client_play.go +++ b/pkg/edition/java/proxy/session_client_play.go @@ -232,7 +232,8 @@ func (c *clientPlaySessionHandler) handlePluginMessage(packet *plugin.Message) { } else if plugin.IsUnregister(packet) { _ = backendConn.WritePacket(packet) } else if plugin.McBrand(packet) { - // TODO read brand message & fire PlayerClientBrandEvent & cache client brand + // TODO fire PlayerClientBrandEvent & cache client brand + c.player.setClientBrand(plugin.ReadBrandMessage(packet.Data)) _ = backendConn.WritePacket(plugin.RewriteMinecraftBrand(packet, c.player.Protocol())) } else { serverConnPhase := serverConn.phase()