From 27f34ec149683d8fe9785197846af9f832b65e37 Mon Sep 17 00:00:00 2001 From: adman Date: Mon, 10 Nov 2025 23:24:58 +0100 Subject: [PATCH] Add login and status clients with modular compression handling --- connection.go | 62 +++++++++++++++++++++++++++++++++----- examples/status/main.go | 44 +++++++-------------------- modules/login.go | 66 +++++++++++++++++++++++++++++++++++++++++ modules/status.go | 52 ++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 41 deletions(-) create mode 100644 modules/login.go create mode 100644 modules/status.go diff --git a/connection.go b/connection.go index c855423..c18ae20 100644 --- a/connection.go +++ b/connection.go @@ -2,6 +2,7 @@ package strom import ( "bytes" + "compress/zlib" "errors" "io" "net" @@ -42,7 +43,7 @@ func (a Actor) ReceiveDirection() queser.Direction { } type Connection struct { - io.ReadWriteCloser + net.Conn CompressionThreshold int32 State queser.State Actor Actor @@ -62,7 +63,26 @@ func (c *Connection) Send(packet any) (err error) { } var packetBytes []byte if c.CompressionThreshold > 0 { - panic("todo") + packetBuffer := bytes.NewBuffer(nil) + if int32(len(packetBytes)) >= c.CompressionThreshold { + err = queser.VarInt(len(packetBytes)).Encode(packetBuffer) + if err != nil { + return + } + _, err = zlib.NewWriter(packetBuffer).Write(packetBytes) + if err != nil { + return + } + } else { + err = queser.VarInt(0).Encode(packetBuffer) + if err != nil { + return + } + _, err = packetBuffer.Write(packetBytes) + if err != nil { + return + } + } } else { packetBytes = rawPacketBuffer.Bytes() } @@ -75,18 +95,37 @@ func (c *Connection) Send(packet any) (err error) { } func (c *Connection) Receive() (packet any, err error) { - var packetLen queser.VarInt - packetLen, err = packetLen.Decode(c) + var rawPacketLen queser.VarInt + rawPacketLen, err = rawPacketLen.Decode(c) if err != nil { return } - rawPacketBytes, err := io.ReadAll(io.LimitReader(c, int64(packetLen))) + rawPacketBytes, err := io.ReadAll(io.LimitReader(c, int64(rawPacketLen))) if err != nil { return } + rawPacketBuffer := bytes.NewBuffer(rawPacketBytes) var packetBytes []byte if c.CompressionThreshold > 0 { - panic("todo") + var packetLen queser.VarInt + packetLen, err = packetLen.Decode(rawPacketBuffer) + if err != nil { + return + } + if packetLen == 0 { + packetBytes, err = io.ReadAll(rawPacketBuffer) + } else { + var zReader io.ReadCloser + zReader, err = zlib.NewReader(rawPacketBuffer) + if err != nil { + return + } + defer zReader.Close() + packetBytes, err = io.ReadAll(zReader) + if err != nil { + return + } + } } else { packetBytes = rawPacketBytes } @@ -100,9 +139,18 @@ func ClientConnect(addr string) (ret *Connection, err error) { ret.State = queser.Handshaking ret.CompressionThreshold = -1 ret.Actor = Client - ret.ReadWriteCloser, err = net.Dial("tcp", addr) + ret.Conn, err = net.Dial("tcp", addr) if err != nil { return } return } + +func ConnectAndStart(addr string, inst HandlerInst) (ret *Connection, err error) { + ret, err = ClientConnect(addr) + if err != nil { + return + } + err = ret.Start(inst) + return +} diff --git a/examples/status/main.go b/examples/status/main.go index 3f2eb73..0eda6a5 100644 --- a/examples/status/main.go +++ b/examples/status/main.go @@ -1,43 +1,12 @@ package main import ( - "fmt" "strom" + "strom/modules" - "github.com/admin-else/queser" - "github.com/admin-else/queser/generated/v1_21_8" + "github.com/google/uuid" ) -type StatusClient struct { - *strom.Connection -} - -func (s *StatusClient) Default(event any) (err error) { - err = fmt.Errorf("unexpected event: %v", event) - return -} - -func (s *StatusClient) OnStart(_ strom.OnStart) (err error) { - err = s.Send(v1_21_8.HandshakingToServerPacketSetProtocol{ - ProtocolVersion: 772, - ServerHost: "127.0.0.1", - ServerPort: 25566, - NextState: queser.VarInt(queser.Status), - }) - if err != nil { - return - } - s.State = queser.Status - err = s.Send(v1_21_8.StatusToServerPacketPingStart{}) - return -} - -func (s *StatusClient) OnStatus(p v1_21_8.StatusToClientPacketServerInfo) (err error) { - fmt.Println(p) - err = strom.HandlerDone - return -} - func must(err error) { if err != nil { panic(err) @@ -47,6 +16,13 @@ func must(err error) { func main() { c, err := strom.ClientConnect("127.0.0.1:25566") must(err) - err = c.Start(&StatusClient{c}) + err = c.Start(&modules.LoginClient{ + Account: modules.Account{ + Username: "Admin_rizz", + UUID: uuid.UUID{}, + Token: "", + }, + Connection: c, + }) must(err) } diff --git a/modules/login.go b/modules/login.go new file mode 100644 index 0000000..c6ca1d0 --- /dev/null +++ b/modules/login.go @@ -0,0 +1,66 @@ +package modules + +import ( + "fmt" + "strconv" + "strings" + "strom" + + "github.com/admin-else/queser" + "github.com/admin-else/queser/data" + "github.com/admin-else/queser/generated/v1_21_8" + "github.com/google/uuid" +) + +type Account struct { + Username string + UUID uuid.UUID + Token string +} +type LoginClient struct { + *strom.Connection + Account Account +} + +func (s *LoginClient) Default(event any) (err error) { + err = fmt.Errorf("unexpected event: %T%v", event, event) + return +} + +func (s *LoginClient) OnStart(_ strom.OnStart) (err error) { + parts := strings.Split(s.RemoteAddr().String(), ":") + versionData, err := data.LookUpProtocolVersionByName(s.Version) + if err != nil { + return + } + port, err := strconv.Atoi(parts[1]) + if err != nil { + return + } + err = s.Send(v1_21_8.HandshakingToServerPacketSetProtocol{ + ProtocolVersion: queser.VarInt(versionData.Version), + ServerHost: parts[0], + ServerPort: uint16(port), + NextState: queser.VarInt(queser.Login), + }) + if err != nil { + return + } + s.State = queser.Login + err = s.Send(v1_21_8.LoginToServerPacketLoginStart{Username: s.Account.Username, PlayerUUID: s.Account.UUID}) + return +} + +func (s *LoginClient) OnCompress(compress v1_21_8.LoginToClientPacketCompress) (err error) { + s.CompressionThreshold = int32(compress.Threshold) + return +} + +func (s *LoginClient) OnSuccess(success v1_21_8.LoginToClientPacketSuccess) (err error) { + err = s.Send(v1_21_8.LoginToServerPacketLoginAcknowledged{}) + if err != nil { + return + } + s.State = queser.Configuration + return +} diff --git a/modules/status.go b/modules/status.go new file mode 100644 index 0000000..eac859b --- /dev/null +++ b/modules/status.go @@ -0,0 +1,52 @@ +package modules + +import ( + "fmt" + "strconv" + "strings" + "strom" + + "github.com/admin-else/queser" + "github.com/admin-else/queser/data" + "github.com/admin-else/queser/generated/v1_21_8" +) + +type StatusClient struct { + *strom.Connection + Status string +} + +func (s *StatusClient) Default(event any) (err error) { + err = fmt.Errorf("unexpected event: %v", event) + return +} + +func (s *StatusClient) OnStart(_ strom.OnStart) (err error) { + parts := strings.Split(s.RemoteAddr().String(), ":") + versionData, err := data.LookUpProtocolVersionByName(s.Version) + if err != nil { + return + } + port, err := strconv.Atoi(parts[1]) + if err != nil { + return + } + err = s.Send(v1_21_8.HandshakingToServerPacketSetProtocol{ + ProtocolVersion: queser.VarInt(versionData.Version), + ServerHost: parts[0], + ServerPort: uint16(port), + NextState: queser.VarInt(queser.Status), + }) + if err != nil { + return + } + s.State = queser.Status + err = s.Send(v1_21_8.StatusToServerPacketPingStart{}) + return +} + +func (s *StatusClient) OnStatus(p v1_21_8.StatusToClientPacketServerInfo) (err error) { + s.Status = p.Response + err = strom.HandlerDone + return +}