The example from the readme now actually works
This commit is contained in:
parent
60f9e182a8
commit
a0020d8eef
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
teeworlds_client
|
teeworlds_client
|
||||||
teeworlds
|
teeworlds
|
||||||
|
go-teeworlds-protocol
|
||||||
|
|
||||||
|
|
|
@ -28,14 +28,20 @@ func main() {
|
||||||
|
|
||||||
// read incoming traffic
|
// read incoming traffic
|
||||||
// you can also alter packet here before it will be processed by the internal state machine
|
// you can also alter packet here before it will be processed by the internal state machine
|
||||||
client.OnPacket(func(packet *protocol7.Packet) {
|
//
|
||||||
|
// return false to drop the packet
|
||||||
|
client.OnPacket(func(packet *protocol7.Packet) bool {
|
||||||
fmt.Printf("got packet with %d messages\n", len(packet.Messages))
|
fmt.Printf("got packet with %d messages\n", len(packet.Messages))
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
// inspect outgoing traffic
|
// inspect outgoing traffic
|
||||||
// you can also alter packet here before it will be sent to the server
|
// you can also alter packet here before it will be sent to the server
|
||||||
client.OnSend(func(packet *protocol7.Packet) {
|
//
|
||||||
|
// return false to drop the packet
|
||||||
|
client.OnSend(func(packet *protocol7.Packet) bool {
|
||||||
fmt.Printf("sending packet with %d messages\n", len(packet.Messages))
|
fmt.Printf("sending packet with %d messages\n", len(packet.Messages))
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
client.OnChat(func(msg *messages7.SvChat, defaultAction teeworlds7.DefaultAction) {
|
client.OnChat(func(msg *messages7.SvChat, defaultAction teeworlds7.DefaultAction) {
|
||||||
|
|
57
messages7/cl_say.go
Normal file
57
messages7/cl_say.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package messages7
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"github.com/teeworlds-go/go-teeworlds-protocol/chunk7"
|
||||||
|
"github.com/teeworlds-go/go-teeworlds-protocol/network7"
|
||||||
|
"github.com/teeworlds-go/go-teeworlds-protocol/packer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClSay struct {
|
||||||
|
ChunkHeader *chunk7.ChunkHeader
|
||||||
|
|
||||||
|
Mode network7.ChatMode
|
||||||
|
TargetId int
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) MsgId() int {
|
||||||
|
return network7.MsgGameClSay
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) MsgType() network7.MsgType {
|
||||||
|
return network7.TypeNet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) System() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) Vital() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) Pack() []byte {
|
||||||
|
return slices.Concat(
|
||||||
|
packer.PackInt(int(msg.Mode)),
|
||||||
|
packer.PackInt(msg.TargetId),
|
||||||
|
packer.PackStr(msg.Message),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) Unpack(u *packer.Unpacker) error {
|
||||||
|
msg.Mode = network7.ChatMode(u.GetInt())
|
||||||
|
msg.TargetId = u.GetInt()
|
||||||
|
msg.Message = u.GetString()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) Header() *chunk7.ChunkHeader {
|
||||||
|
return msg.ChunkHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ClSay) SetHeader(header *chunk7.ChunkHeader) {
|
||||||
|
msg.ChunkHeader = header
|
||||||
|
}
|
|
@ -285,6 +285,7 @@ func (packet *Packet) Unpack(data []byte) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: return error if maxium packet size is exceeded
|
||||||
func (packet *Packet) Pack(connection *Session) []byte {
|
func (packet *Packet) Pack(connection *Session) []byte {
|
||||||
payload := []byte{}
|
payload := []byte{}
|
||||||
control := false
|
control := false
|
||||||
|
@ -297,6 +298,7 @@ func (packet *Packet) Pack(connection *Session) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
packet.Header.NumChunks = len(packet.Messages)
|
packet.Header.NumChunks = len(packet.Messages)
|
||||||
|
packet.Header.Ack = connection.Ack
|
||||||
|
|
||||||
if control {
|
if control {
|
||||||
packet.Header.Flags = PacketFlags{
|
packet.Header.Flags = PacketFlags{
|
||||||
|
|
|
@ -140,6 +140,7 @@ func TestRepackUnknownMessages(t *testing.T) {
|
||||||
err := packet.Unpack(dump)
|
err := packet.Unpack(dump)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
conn.Ack = packet.Header.Ack
|
||||||
repack := packet.Pack(&conn)
|
repack := packet.Pack(&conn)
|
||||||
require.Equal(t, dump, repack)
|
require.Equal(t, dump, repack)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ type Session struct {
|
||||||
PeerAck int
|
PeerAck int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: should this be removed? All of this could be set in Packet.Pack()
|
||||||
func (connection *Session) BuildResponse() *Packet {
|
func (connection *Session) BuildResponse() *Packet {
|
||||||
return &Packet{
|
return &Packet{
|
||||||
Header: PacketHeader{
|
Header: PacketHeader{
|
||||||
|
@ -26,7 +27,7 @@ func (connection *Session) BuildResponse() *Packet {
|
||||||
Resend: false,
|
Resend: false,
|
||||||
Control: false,
|
Control: false,
|
||||||
},
|
},
|
||||||
Ack: connection.Ack,
|
Ack: 0, // will be set in Packet.Pack()
|
||||||
NumChunks: 0, // will be set in Packet.Pack()
|
NumChunks: 0, // will be set in Packet.Pack()
|
||||||
Token: connection.ServerToken,
|
Token: connection.ServerToken,
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,8 +15,8 @@ type DefaultAction func()
|
||||||
// // key is the network7.MessageId
|
// // key is the network7.MessageId
|
||||||
// UserMsgCallbacks map[int]UserMsgCallback
|
// UserMsgCallbacks map[int]UserMsgCallback
|
||||||
type UserMsgCallbacks struct {
|
type UserMsgCallbacks struct {
|
||||||
PacketIn func(*protocol7.Packet)
|
PacketIn func(*protocol7.Packet) bool
|
||||||
PacketOut func(*protocol7.Packet)
|
PacketOut func(*protocol7.Packet) bool
|
||||||
MsgUnknown func(*messages7.Unknown, DefaultAction)
|
MsgUnknown func(*messages7.Unknown, DefaultAction)
|
||||||
InternalError func(error)
|
InternalError func(error)
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,9 @@ func (client *Client) processMessage(msg messages7.NetMessage, response *protoco
|
||||||
|
|
||||||
func (client *Client) processPacket(packet *protocol7.Packet) error {
|
func (client *Client) processPacket(packet *protocol7.Packet) error {
|
||||||
if client.Callbacks.PacketIn != nil {
|
if client.Callbacks.PacketIn != nil {
|
||||||
client.Callbacks.PacketIn(packet)
|
if client.Callbacks.PacketIn(packet) == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response := client.Session.BuildResponse()
|
response := client.Session.BuildResponse()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package teeworlds7
|
package teeworlds7
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/teeworlds-go/go-teeworlds-protocol/messages7"
|
"github.com/teeworlds-go/go-teeworlds-protocol/messages7"
|
||||||
"github.com/teeworlds-go/go-teeworlds-protocol/network7"
|
"github.com/teeworlds-go/go-teeworlds-protocol/network7"
|
||||||
"github.com/teeworlds-go/go-teeworlds-protocol/protocol7"
|
"github.com/teeworlds-go/go-teeworlds-protocol/protocol7"
|
||||||
|
@ -10,14 +12,77 @@ import (
|
||||||
// low level access for experts
|
// low level access for experts
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
|
||||||
func (client *Client) SendPacket(packet *protocol7.Packet) {
|
// flish()boo {
|
||||||
|
//
|
||||||
|
// ifhf lenesusue
|
||||||
|
// packte:=}{}
|
||||||
|
// SendPkacte8)
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if now > lastsnend d+9191 {
|
||||||
|
// if !flush() {
|
||||||
|
// keepalive
|
||||||
|
// }
|
||||||
|
// }A
|
||||||
|
|
||||||
// TODO: append queued messages to packet messages here
|
func (client *Client) SendPacket(packet *protocol7.Packet) error {
|
||||||
|
if packet.Header.Flags.Resend == false && len(packet.Messages) == 0 && len(client.QueuedMessages) == 0 {
|
||||||
|
return fmt.Errorf("Failed to send packet: payload is empty.")
|
||||||
|
}
|
||||||
|
|
||||||
|
gotNet := false
|
||||||
|
numCtrlMsgs := 0
|
||||||
|
|
||||||
|
for _, msg := range packet.Messages {
|
||||||
|
if msg.MsgType() == network7.TypeControl {
|
||||||
|
numCtrlMsgs++
|
||||||
|
} else if msg.MsgType() == network7.TypeNet {
|
||||||
|
gotNet = true
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Failed to send packet: only game, system and control messages are supported.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if gotNet && numCtrlMsgs > 0 {
|
||||||
|
return fmt.Errorf("Failed to send packet: can not mix control messages with others.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if numCtrlMsgs > 1 {
|
||||||
|
// TODO: should this automatically split it up into multiple packets?
|
||||||
|
return fmt.Errorf("Failed to send packet: can only send one control message at a time.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user queued a game message and then sends a control message
|
||||||
|
// before the queue got processed we send two packets in the correct order
|
||||||
|
// For example in this case:
|
||||||
|
//
|
||||||
|
// client.SendChat("bye") // queue game chunk
|
||||||
|
// client.Disconnect() // SendPacket(ctrl) -> first flush out the game chunk packet then send the control packet
|
||||||
|
//
|
||||||
|
if numCtrlMsgs > 0 && len(client.QueuedMessages) > 0 {
|
||||||
|
// TODO: we could apply compression here
|
||||||
|
// flushPacket.Header.Flags.Compression = true
|
||||||
|
|
||||||
|
flushPacket := client.Session.BuildResponse()
|
||||||
|
client.SendPacket(flushPacket)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, queuedChunk := range client.QueuedMessages {
|
||||||
|
// TODO: check if we exceed packet size and only put in as many chunks as we can
|
||||||
|
// also use a more performant queue implementation then if we unshift it partially
|
||||||
|
// popping of one element from the queue should not reallocate the entire queued messages slice
|
||||||
|
packet.Messages = append(packet.Messages, queuedChunk)
|
||||||
|
}
|
||||||
|
client.QueuedMessages = nil
|
||||||
|
|
||||||
if client.Callbacks.PacketOut != nil {
|
if client.Callbacks.PacketOut != nil {
|
||||||
client.Callbacks.PacketOut(packet)
|
if client.Callbacks.PacketOut(packet) == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.Conn.Write(packet.Pack(&client.Session))
|
client.Conn.Write(packet.Pack(&client.Session))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING! this is does not send chat messages
|
// WARNING! this is does not send chat messages
|
||||||
|
@ -25,7 +90,18 @@ func (client *Client) SendPacket(packet *protocol7.Packet) {
|
||||||
//
|
//
|
||||||
// if you want to send a chat message use SendChat()
|
// if you want to send a chat message use SendChat()
|
||||||
func (client *Client) SendMessage(msg messages7.NetMessage) {
|
func (client *Client) SendMessage(msg messages7.NetMessage) {
|
||||||
// TODO: set vital header and stuff
|
if msg.MsgType() == network7.TypeControl {
|
||||||
|
packet := client.Session.BuildResponse()
|
||||||
|
packet.Header.Flags.Control = true
|
||||||
|
packet.Messages = append(packet.Messages, msg)
|
||||||
|
client.SendPacket(packet)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if msg.MsgType() == network7.TypeConnless {
|
||||||
|
// TODO: connless
|
||||||
|
panic("connless messages are not supported yet")
|
||||||
|
}
|
||||||
|
|
||||||
client.QueuedMessages = append(client.QueuedMessages, msg)
|
client.QueuedMessages = append(client.QueuedMessages, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +113,7 @@ func (client *Client) SendMessage(msg messages7.NetMessage) {
|
||||||
// see also SendChatTeam()
|
// see also SendChatTeam()
|
||||||
func (client *Client) SendChat(msg string) {
|
func (client *Client) SendChat(msg string) {
|
||||||
client.SendMessage(
|
client.SendMessage(
|
||||||
&messages7.SvChat{
|
&messages7.ClSay{
|
||||||
Mode: network7.ChatAll,
|
Mode: network7.ChatAll,
|
||||||
Message: msg,
|
Message: msg,
|
||||||
TargetId: -1,
|
TargetId: -1,
|
||||||
|
@ -49,7 +125,7 @@ func (client *Client) SendChat(msg string) {
|
||||||
// see also SendChat()
|
// see also SendChat()
|
||||||
func (client *Client) SendChatTeam(msg string) {
|
func (client *Client) SendChatTeam(msg string) {
|
||||||
client.SendMessage(
|
client.SendMessage(
|
||||||
&messages7.SvChat{
|
&messages7.ClSay{
|
||||||
Mode: network7.ChatTeam,
|
Mode: network7.ChatTeam,
|
||||||
Message: msg,
|
Message: msg,
|
||||||
TargetId: -1,
|
TargetId: -1,
|
||||||
|
@ -61,7 +137,7 @@ func (client *Client) SendChatTeam(msg string) {
|
||||||
// see also SendChatTeam()
|
// see also SendChatTeam()
|
||||||
func (client *Client) SendWhisper(targetId int, msg string) {
|
func (client *Client) SendWhisper(targetId int, msg string) {
|
||||||
client.SendMessage(
|
client.SendMessage(
|
||||||
&messages7.SvChat{
|
&messages7.ClSay{
|
||||||
Mode: network7.ChatWhisper,
|
Mode: network7.ChatWhisper,
|
||||||
Message: msg,
|
Message: msg,
|
||||||
TargetId: targetId,
|
TargetId: targetId,
|
||||||
|
|
|
@ -16,13 +16,17 @@ func (client *Client) OnError(callback func(err error)) {
|
||||||
|
|
||||||
// inspect outgoing traffic
|
// inspect outgoing traffic
|
||||||
// and alter it before it gets sent to the server
|
// and alter it before it gets sent to the server
|
||||||
func (client *Client) OnSend(callback func(packet *protocol7.Packet)) {
|
//
|
||||||
|
// return false to drop the packet
|
||||||
|
func (client *Client) OnSend(callback func(packet *protocol7.Packet) bool) {
|
||||||
client.Callbacks.PacketOut = callback
|
client.Callbacks.PacketOut = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
// read incoming traffic
|
// read incoming traffic
|
||||||
// and alter it before it hits the internal state machine
|
// and alter it before it hits the internal state machine
|
||||||
func (client *Client) OnPacket(callback func(packet *protocol7.Packet)) {
|
//
|
||||||
|
// return false to drop the packet
|
||||||
|
func (client *Client) OnPacket(callback func(packet *protocol7.Packet) bool) {
|
||||||
client.Callbacks.PacketIn = callback
|
client.Callbacks.PacketIn = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue