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
|
||||
go-teeworlds-protocol
|
||||
|
||||
|
|
|
@ -28,14 +28,20 @@ func main() {
|
|||
|
||||
// read incoming traffic
|
||||
// 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))
|
||||
return true
|
||||
})
|
||||
|
||||
// inspect outgoing traffic
|
||||
// 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))
|
||||
return true
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// TODO: return error if maxium packet size is exceeded
|
||||
func (packet *Packet) Pack(connection *Session) []byte {
|
||||
payload := []byte{}
|
||||
control := false
|
||||
|
@ -297,6 +298,7 @@ func (packet *Packet) Pack(connection *Session) []byte {
|
|||
}
|
||||
|
||||
packet.Header.NumChunks = len(packet.Messages)
|
||||
packet.Header.Ack = connection.Ack
|
||||
|
||||
if control {
|
||||
packet.Header.Flags = PacketFlags{
|
||||
|
|
|
@ -140,6 +140,7 @@ func TestRepackUnknownMessages(t *testing.T) {
|
|||
err := packet.Unpack(dump)
|
||||
require.NoError(t, err)
|
||||
|
||||
conn.Ack = packet.Header.Ack
|
||||
repack := packet.Pack(&conn)
|
||||
require.Equal(t, dump, repack)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ type Session struct {
|
|||
PeerAck int
|
||||
}
|
||||
|
||||
// TODO: should this be removed? All of this could be set in Packet.Pack()
|
||||
func (connection *Session) BuildResponse() *Packet {
|
||||
return &Packet{
|
||||
Header: PacketHeader{
|
||||
|
@ -26,7 +27,7 @@ func (connection *Session) BuildResponse() *Packet {
|
|||
Resend: false,
|
||||
Control: false,
|
||||
},
|
||||
Ack: connection.Ack,
|
||||
Ack: 0, // will be set in Packet.Pack()
|
||||
NumChunks: 0, // will be set in Packet.Pack()
|
||||
Token: connection.ServerToken,
|
||||
},
|
||||
|
|
|
@ -15,8 +15,8 @@ type DefaultAction func()
|
|||
// // key is the network7.MessageId
|
||||
// UserMsgCallbacks map[int]UserMsgCallback
|
||||
type UserMsgCallbacks struct {
|
||||
PacketIn func(*protocol7.Packet)
|
||||
PacketOut func(*protocol7.Packet)
|
||||
PacketIn func(*protocol7.Packet) bool
|
||||
PacketOut func(*protocol7.Packet) bool
|
||||
MsgUnknown func(*messages7.Unknown, DefaultAction)
|
||||
InternalError func(error)
|
||||
|
||||
|
|
|
@ -39,7 +39,9 @@ func (client *Client) processMessage(msg messages7.NetMessage, response *protoco
|
|||
|
||||
func (client *Client) processPacket(packet *protocol7.Packet) error {
|
||||
if client.Callbacks.PacketIn != nil {
|
||||
client.Callbacks.PacketIn(packet)
|
||||
if client.Callbacks.PacketIn(packet) == false {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
response := client.Session.BuildResponse()
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package teeworlds7
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/teeworlds-go/go-teeworlds-protocol/messages7"
|
||||
"github.com/teeworlds-go/go-teeworlds-protocol/network7"
|
||||
"github.com/teeworlds-go/go-teeworlds-protocol/protocol7"
|
||||
|
@ -10,14 +12,77 @@ import (
|
|||
// 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 {
|
||||
client.Callbacks.PacketOut(packet)
|
||||
if client.Callbacks.PacketOut(packet) == false {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
client.Conn.Write(packet.Pack(&client.Session))
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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()
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -37,7 +113,7 @@ func (client *Client) SendMessage(msg messages7.NetMessage) {
|
|||
// see also SendChatTeam()
|
||||
func (client *Client) SendChat(msg string) {
|
||||
client.SendMessage(
|
||||
&messages7.SvChat{
|
||||
&messages7.ClSay{
|
||||
Mode: network7.ChatAll,
|
||||
Message: msg,
|
||||
TargetId: -1,
|
||||
|
@ -49,7 +125,7 @@ func (client *Client) SendChat(msg string) {
|
|||
// see also SendChat()
|
||||
func (client *Client) SendChatTeam(msg string) {
|
||||
client.SendMessage(
|
||||
&messages7.SvChat{
|
||||
&messages7.ClSay{
|
||||
Mode: network7.ChatTeam,
|
||||
Message: msg,
|
||||
TargetId: -1,
|
||||
|
@ -61,7 +137,7 @@ func (client *Client) SendChatTeam(msg string) {
|
|||
// see also SendChatTeam()
|
||||
func (client *Client) SendWhisper(targetId int, msg string) {
|
||||
client.SendMessage(
|
||||
&messages7.SvChat{
|
||||
&messages7.ClSay{
|
||||
Mode: network7.ChatWhisper,
|
||||
Message: msg,
|
||||
TargetId: targetId,
|
||||
|
|
|
@ -16,13 +16,17 @@ func (client *Client) OnError(callback func(err error)) {
|
|||
|
||||
// inspect outgoing traffic
|
||||
// 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
|
||||
}
|
||||
|
||||
// read incoming traffic
|
||||
// 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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue