diff --git a/cmd/strom/messenger/main.go b/cmd/strom/messenger/main.go index 5e1e2f0..154e587 100644 --- a/cmd/strom/messenger/main.go +++ b/cmd/strom/messenger/main.go @@ -16,6 +16,7 @@ import ( "github.com/admin-else/strom/mc/event" "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_8" ) func stror(a, b string) string { @@ -29,12 +30,14 @@ var ( cmd = flag.NewFlagSet("status", flag.ContinueOnError) 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") + versionFlag = cmd.String("version", "26.2", "minecraft version to use (e.g. 1.8, 1.21.11)") ) type Messenger struct { *proto.Conn - chat *chat.Module - world *world.Module + chat *chat.Module + world *world.Module + legacy bool } 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 } +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) { input := strings.TrimSpace(e.Val) 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.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) { @@ -105,30 +120,45 @@ func Run(args []string) (err error) { if err != nil { return } - c, err := client.Login(*connectToFlag, acc) + c, err := client.Login(*connectToFlag, acc, client.WithVersion(*versionFlag)) if err != nil { return } defer c.Close() - chatMod, err := chat.Start(c, acc) - if err != nil { - return + isLegacy := c.ProtocolVersion < 764 + + 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{ - Conn: c, - chat: chatMod, - world: world.Start(c, w), + Conn: c, + chat: chatMod, + legacy: isLegacy, + } + + if !isLegacy { + w := world.NewWorld(c.Version, -64, 384) + m.world = world.Start(c, w) } event.StartListingStdin(m.Loop) 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() } diff --git a/mc/client/login.go b/mc/client/login.go index 7b5a1c7..35ae1c6 100644 --- a/mc/client/login.go +++ b/mc/client/login.go @@ -15,8 +15,10 @@ import ( "github.com/admin-else/strom/mc/proto" "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_8" "github.com/admin-else/strom/mc/proto_generated/v26_2" "github.com/admin-else/strom/mc/text" + "github.com/google/uuid" ) type LoginClient struct { @@ -112,13 +114,42 @@ func (s *LoginClient) OnDisconnect(packet *v1_21_8.LoginToClientPacketDisconnect return } -func (s *LoginClient) OnSuccess(success *v1_21_8.LoginToClientPacketSuccess) (err error) { - s.GivenAccount = success - err = s.Send(&v1_21_8.LoginToServerPacketLoginAcknowledged{}) +func (s *LoginClient) OnDisconnectV1_8(packet *v1_8.LoginToClientPacketDisconnect) (err error) { + var reason text.Component + err = json.Unmarshal([]byte(packet.Reason), &reason) if err != nil { 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{} return } @@ -155,6 +186,9 @@ func LoginRawAddr(c *proto.Conn, account *api.Account, hostAddr string) (err err lc.RegisterCriticalUntilLatest(lc.OnDisconnect) lc.RegisterCriticalUntil("26.1", lc.OnSuccess) 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 if hostAddr != "" { @@ -171,7 +205,11 @@ func LoginRawAddr(c *proto.Conn, account *api.Account, hostAddr string) (err err return } 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() if err != nil { @@ -293,7 +331,7 @@ func Login(connectTo string, account *api.Account, settings ...func(ls *loginSet if err != nil { return } - if !ls.IgnoreConfig { + if !ls.IgnoreConfig && c.ProtocolVersion >= 764 { err = IgnoreConfig(c) } return diff --git a/mc/client/status.go b/mc/client/status.go index cdf8cc6..3fdcb43 100644 --- a/mc/client/status.go +++ b/mc/client/status.go @@ -9,6 +9,7 @@ import ( "github.com/admin-else/strom/mc/proto" "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_8" "github.com/admin-else/strom/mc/server" ) @@ -36,6 +37,23 @@ func (s *StatusClient) OnPong(p *v1_21_8.StatusToClientPacketPing) (err error) { 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. // So ignore the resource leak warning. And maybe attach a warn ignore comment. // 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.OnPong) + s.RegisterCritical(s.OnStatusV1_8) + s.RegisterCritical(s.OnPongV1_8) p, err := MakeHandshakePacketAddr(s.Conn, proto_base.Status, addr) if err != nil {