Use packet queue for bot framework.

Providing concurrently-safing for sending packets.
This commit is contained in:
Tnze
2023-03-05 10:19:18 +08:00
parent 90501f1357
commit 925b1359fc
5 changed files with 85 additions and 14 deletions

View File

@ -1,15 +1,19 @@
package bot
import (
"errors"
"github.com/google/uuid"
"github.com/Tnze/go-mc/data/packetid"
"github.com/Tnze/go-mc/net"
pk "github.com/Tnze/go-mc/net/packet"
"github.com/Tnze/go-mc/net/queue"
)
// Client is used to access Minecraft server
type Client struct {
Conn *net.Conn
Conn *Conn
Auth Auth
Name string
@ -37,6 +41,71 @@ func NewClient() *Client {
}
}
// Conn is a concurrently-safe warpper of net.Conn with packet queue.
// Note that not all methods are concurrently-safe.
type Conn struct {
conn *net.Conn
send, recv queue.Queue[pk.Packet]
rerr error
}
func warpConn(c *net.Conn) *Conn {
wc := Conn{
conn: c,
send: make(queue.ChannelQueue[pk.Packet], 256),
recv: make(queue.ChannelQueue[pk.Packet], 256),
rerr: nil,
}
go func() {
for {
var p pk.Packet
if err := c.ReadPacket(&p); err != nil {
wc.rerr = err
break
}
if ok := wc.recv.Push(p); !ok {
break
}
}
wc.recv.Close()
}()
go func() {
for {
p, ok := wc.send.Pull()
if !ok {
break
}
if err := c.WritePacket(p); err != nil {
break
}
}
}()
return &wc
}
func (c *Conn) ReadPacket(p *pk.Packet) error {
packet, ok := c.recv.Pull()
if !ok {
return c.rerr
}
*p = packet
return nil
}
func (c *Conn) WritePacket(p pk.Packet) error {
ok := c.send.Push(p)
if !ok {
return errors.New("queue is full")
}
return nil
}
func (c *Conn) Close() error {
c.send.Close()
return c.conn.Close()
}
// Position is a 3D vector.
type Position struct {
X, Y, Z int