port messenger to more versions

This commit is contained in:
Admin Else
2026-08-04 19:28:43 +02:00
parent d9bca7e517
commit acb5fe8d90
3 changed files with 111 additions and 23 deletions
+47 -17
View File
@@ -16,6 +16,7 @@ import (
"github.com/admin-else/strom/mc/event" "github.com/admin-else/strom/mc/event"
"github.com/admin-else/strom/mc/proto" "github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_generated/v1_21_11" "github.com/admin-else/strom/mc/proto_generated/v1_21_11"
"github.com/admin-else/strom/mc/proto_generated/v1_8"
) )
func stror(a, b string) string { func stror(a, b string) string {
@@ -29,12 +30,14 @@ var (
cmd = flag.NewFlagSet("status", flag.ContinueOnError) cmd = flag.NewFlagSet("status", flag.ContinueOnError)
connectToFlag = cmd.String("addr", "", "server address to connect to") connectToFlag = cmd.String("addr", "", "server address to connect to")
accFlag = cmd.String("acc", stror(os.Getenv("STROM_ACC"), "strom_messenger"), "the name to use if longer will be treated as ygg token") accFlag = cmd.String("acc", stror(os.Getenv("STROM_ACC"), "strom_messenger"), "the name to use if longer will be treated as ygg token")
versionFlag = cmd.String("version", "26.2", "minecraft version to use (e.g. 1.8, 1.21.11)")
) )
type Messenger struct { type Messenger struct {
*proto.Conn *proto.Conn
chat *chat.Module chat *chat.Module
world *world.Module world *world.Module
legacy bool
} }
func (m *Messenger) OnChat(e *v1_21_11.PlayToClientPacketPlayerChat) (err error) { func (m *Messenger) OnChat(e *v1_21_11.PlayToClientPacketPlayerChat) (err error) {
@@ -52,15 +55,27 @@ func (m *Messenger) OnChatSystem(e *v1_21_11.PlayToClientPacketSystemChat) (err
return return
} }
func (m *Messenger) OnChatLegacy(e *v1_8.PlayToClientPacketChat) (err error) {
m.Log.Info("chat", "m", e.Message)
return
}
func (m *Messenger) OnStdin(e event.Stdin) (err error) { func (m *Messenger) OnStdin(e event.Stdin) (err error) {
input := strings.TrimSpace(e.Val) input := strings.TrimSpace(e.Val)
if strings.HasPrefix(input, ">say ") { if strings.HasPrefix(input, ">say ") {
return m.chat.SendMessage(strings.TrimSpace(strings.TrimPrefix(input, ">say"))) return m.sendChat(strings.TrimSpace(strings.TrimPrefix(input, ">say")))
} }
if strings.HasPrefix(input, ">getblock ") { if !m.legacy && strings.HasPrefix(input, ">getblock ") {
return m.handleGetBlock(strings.TrimSpace(strings.TrimPrefix(input, ">getblock"))) return m.handleGetBlock(strings.TrimSpace(strings.TrimPrefix(input, ">getblock")))
} }
return m.chat.SendMessage(input) return m.sendChat(input)
}
func (m *Messenger) sendChat(message string) (err error) {
if m.legacy {
return m.Send(&v1_8.PlayToServerPacketChat{Message: message})
}
return m.chat.SendMessage(message)
} }
func (m *Messenger) handleGetBlock(args string) (err error) { func (m *Messenger) handleGetBlock(args string) (err error) {
@@ -105,30 +120,45 @@ func Run(args []string) (err error) {
if err != nil { if err != nil {
return return
} }
c, err := client.Login(*connectToFlag, acc) c, err := client.Login(*connectToFlag, acc, client.WithVersion(*versionFlag))
if err != nil { if err != nil {
return return
} }
defer c.Close() defer c.Close()
chatMod, err := chat.Start(c, acc) isLegacy := c.ProtocolVersion < 764
if err != nil {
return var chatMod *chat.Module
if !isLegacy {
chatMod, err = chat.Start(c, acc)
if err != nil {
return
}
} }
// Shareable world storage. Other bots can subscribe to the same World.
w := world.NewWorld(c.Version, -64, 384)
m := &Messenger{ m := &Messenger{
Conn: c, Conn: c,
chat: chatMod, chat: chatMod,
world: world.Start(c, w), legacy: isLegacy,
}
if !isLegacy {
w := world.NewWorld(c.Version, -64, 384)
m.world = world.Start(c, w)
} }
event.StartListingStdin(m.Loop) event.StartListingStdin(m.Loop)
m.Register(m.OnStdin) m.Register(m.OnStdin)
m.RegisterUntilLatest(m.OnChat, m.OnChatUnsigned, m.OnChatSystem)
keepalive.Start(m.Conn) if isLegacy {
m.Register(m.OnChatLegacy)
} else {
m.RegisterUntilLatest(m.OnChat, m.OnChatUnsigned, m.OnChatSystem)
}
if !isLegacy {
keepalive.Start(m.Conn)
}
return m.StartConn() return m.StartConn()
} }
+44 -6
View File
@@ -15,8 +15,10 @@ import (
"github.com/admin-else/strom/mc/proto" "github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base" "github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8" "github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/proto_generated/v1_8"
"github.com/admin-else/strom/mc/proto_generated/v26_2" "github.com/admin-else/strom/mc/proto_generated/v26_2"
"github.com/admin-else/strom/mc/text" "github.com/admin-else/strom/mc/text"
"github.com/google/uuid"
) )
type LoginClient struct { type LoginClient struct {
@@ -112,13 +114,42 @@ func (s *LoginClient) OnDisconnect(packet *v1_21_8.LoginToClientPacketDisconnect
return return
} }
func (s *LoginClient) OnSuccess(success *v1_21_8.LoginToClientPacketSuccess) (err error) { func (s *LoginClient) OnDisconnectV1_8(packet *v1_8.LoginToClientPacketDisconnect) (err error) {
s.GivenAccount = success var reason text.Component
err = s.Send(&v1_21_8.LoginToServerPacketLoginAcknowledged{}) err = json.Unmarshal([]byte(packet.Reason), &reason)
if err != nil { if err != nil {
return return
} }
s.SetState(proto_base.Configuration) err = KickedDuringLoginErr{reason}
return
}
func (s *LoginClient) OnCompressV1_8(packet *v1_8.LoginToClientPacketCompress) (err error) {
s.SetCompressionThreshold(packet.Threshold)
return
}
func (s *LoginClient) OnSuccessV1_8(success *v1_8.LoginToClientPacketSuccess) (err error) {
s.GivenAccount = &v1_21_8.LoginToClientPacketSuccess{
Uuid: uuid.MustParse(success.Uuid),
Username: success.Username,
}
s.SetState(proto_base.Play)
err = event.HandlerDoneErr{}
return
}
func (s *LoginClient) OnSuccess(success *v1_21_8.LoginToClientPacketSuccess) (err error) {
s.GivenAccount = success
if s.ProtocolVersion >= 764 {
err = s.Send(&v1_21_8.LoginToServerPacketLoginAcknowledged{})
if err != nil {
return
}
s.SetState(proto_base.Configuration)
} else {
s.SetState(proto_base.Play)
}
err = event.HandlerDoneErr{} err = event.HandlerDoneErr{}
return return
} }
@@ -155,6 +186,9 @@ func LoginRawAddr(c *proto.Conn, account *api.Account, hostAddr string) (err err
lc.RegisterCriticalUntilLatest(lc.OnDisconnect) lc.RegisterCriticalUntilLatest(lc.OnDisconnect)
lc.RegisterCriticalUntil("26.1", lc.OnSuccess) lc.RegisterCriticalUntil("26.1", lc.OnSuccess)
lc.RegisterCriticalUntilLatest(lc.OnSuccess26_2) lc.RegisterCriticalUntilLatest(lc.OnSuccess26_2)
lc.RegisterCritical(lc.OnCompressV1_8)
lc.RegisterCritical(lc.OnDisconnectV1_8)
lc.RegisterCritical(lc.OnSuccessV1_8)
var p proto_base.EncodeDecodeAble var p proto_base.EncodeDecodeAble
if hostAddr != "" { if hostAddr != "" {
@@ -171,7 +205,11 @@ func LoginRawAddr(c *proto.Conn, account *api.Account, hostAddr string) (err err
return return
} }
lc.SetState(proto_base.Login) lc.SetState(proto_base.Login)
err = lc.Send(&v1_21_8.LoginToServerPacketLoginStart{Username: lc.Account.Name, PlayerUUID: lc.Account.Uuid}) if lc.Conn.ProtocolVersion < 759 {
err = lc.Send(&v1_8.LoginToServerPacketLoginStart{Username: lc.Account.Name})
} else {
err = lc.Send(&v1_21_8.LoginToServerPacketLoginStart{Username: lc.Account.Name, PlayerUUID: lc.Account.Uuid})
}
err = lc.StartConn() err = lc.StartConn()
if err != nil { if err != nil {
@@ -293,7 +331,7 @@ func Login(connectTo string, account *api.Account, settings ...func(ls *loginSet
if err != nil { if err != nil {
return return
} }
if !ls.IgnoreConfig { if !ls.IgnoreConfig && c.ProtocolVersion >= 764 {
err = IgnoreConfig(c) err = IgnoreConfig(c)
} }
return return
+20
View File
@@ -9,6 +9,7 @@ import (
"github.com/admin-else/strom/mc/proto" "github.com/admin-else/strom/mc/proto"
"github.com/admin-else/strom/mc/proto_base" "github.com/admin-else/strom/mc/proto_base"
"github.com/admin-else/strom/mc/proto_generated/v1_21_8" "github.com/admin-else/strom/mc/proto_generated/v1_21_8"
"github.com/admin-else/strom/mc/proto_generated/v1_8"
"github.com/admin-else/strom/mc/server" "github.com/admin-else/strom/mc/server"
) )
@@ -36,6 +37,23 @@ func (s *StatusClient) OnPong(p *v1_21_8.StatusToClientPacketPing) (err error) {
return return
} }
func (s *StatusClient) OnStatusV1_8(p *v1_8.StatusToClientPacketServerInfo) (err error) {
s.Status = p.Response
s.PingSendTime = time.Now()
if s.DoPingRoundTripTime {
err = s.Send(&v1_21_8.StatusToServerPacketPing{Time: s.PingSendTime.UnixMilli()})
} else {
err = event.HandlerDoneErr{}
}
return
}
func (s *StatusClient) OnPongV1_8(p *v1_8.StatusToClientPacketPing) (err error) {
s.PingReceiveTime = time.Now()
err = event.HandlerDoneErr{}
return
}
// StatusRaw returns a StatusClient that is not connected to a server. // StatusRaw returns a StatusClient that is not connected to a server.
// So ignore the resource leak warning. And maybe attach a warn ignore comment. // So ignore the resource leak warning. And maybe attach a warn ignore comment.
// It does not resolve SRV records. // It does not resolve SRV records.
@@ -59,6 +77,8 @@ func StatusRawWithVersion(ctx context.Context, addr, version string) (s *StatusC
} }
s.RegisterCriticalUntilLatest(s.OnStatus) s.RegisterCriticalUntilLatest(s.OnStatus)
s.RegisterCriticalUntilLatest(s.OnPong) s.RegisterCriticalUntilLatest(s.OnPong)
s.RegisterCritical(s.OnStatusV1_8)
s.RegisterCritical(s.OnPongV1_8)
p, err := MakeHandshakePacketAddr(s.Conn, proto_base.Status, addr) p, err := MakeHandshakePacketAddr(s.Conn, proto_base.Status, addr)
if err != nil { if err != nil {