Add struct for startinfo
This commit is contained in:
parent
2ca8a03034
commit
c568a471d3
|
@ -10,6 +10,17 @@ type ChunkFlags struct {
|
|||
Resend bool
|
||||
}
|
||||
|
||||
func (flags *ChunkFlags) ToInt() int {
|
||||
v := 0
|
||||
if flags.Resend {
|
||||
v |= chunkFlagResend
|
||||
}
|
||||
if flags.Vital {
|
||||
v |= chunkFlagVital
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
type ChunkHeader struct {
|
||||
Flags ChunkFlags
|
||||
Size int
|
||||
|
@ -23,6 +34,21 @@ type Chunk struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
func (header *ChunkHeader) Pack() []byte {
|
||||
len := 2
|
||||
if header.Flags.Vital {
|
||||
len = 3
|
||||
}
|
||||
data := make([]byte, len)
|
||||
data[0] = (byte(header.Flags.ToInt()&0x03) << 6) | ((byte(header.Size) >> 6) & 0x3f)
|
||||
data[1] = (byte(header.Size) & 0x3f)
|
||||
if header.Flags.Vital {
|
||||
data[1] |= (byte(header.Seq) >> 2) & 0xc0
|
||||
data[2] = byte(header.Seq) & 0xff
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (header *ChunkHeader) Unpack(data []byte) {
|
||||
flagBits := (data[0] >> 6) & 0x03
|
||||
header.Flags.Vital = (flagBits & chunkFlagVital) != 0
|
||||
|
|
81
messages/cl_start_info.go
Normal file
81
messages/cl_start_info.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package message
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/teeworlds-go/teeworlds/packer"
|
||||
)
|
||||
|
||||
type ClStartInfo struct {
|
||||
Name string
|
||||
Clan string
|
||||
Country int
|
||||
Body string
|
||||
Marking string
|
||||
Decoration string
|
||||
Hands string
|
||||
Feet string
|
||||
Eyes string
|
||||
CustomColorBody bool
|
||||
CustomColorMarking bool
|
||||
CustomColorDecoration bool
|
||||
CustomColorHands bool
|
||||
CustomColorFeet bool
|
||||
CustomColorEyes bool
|
||||
ColorBody int
|
||||
ColorMarking int
|
||||
ColorDecoration int
|
||||
ColorHands int
|
||||
ColorFeet int
|
||||
ColorEyes int
|
||||
}
|
||||
|
||||
func (info *ClStartInfo) Pack() []byte {
|
||||
return slices.Concat(
|
||||
packer.PackStr(info.Name),
|
||||
packer.PackStr(info.Clan),
|
||||
packer.PackInt(info.Country),
|
||||
packer.PackStr(info.Body),
|
||||
packer.PackStr(info.Marking),
|
||||
packer.PackStr(info.Decoration),
|
||||
packer.PackStr(info.Hands),
|
||||
packer.PackStr(info.Feet),
|
||||
packer.PackStr(info.Eyes),
|
||||
packer.PackBool(info.CustomColorBody),
|
||||
packer.PackBool(info.CustomColorMarking),
|
||||
packer.PackBool(info.CustomColorDecoration),
|
||||
packer.PackBool(info.CustomColorHands),
|
||||
packer.PackBool(info.CustomColorFeet),
|
||||
packer.PackBool(info.CustomColorEyes),
|
||||
packer.PackInt(info.ColorBody),
|
||||
packer.PackInt(info.ColorMarking),
|
||||
packer.PackInt(info.ColorDecoration),
|
||||
packer.PackInt(info.ColorHands),
|
||||
packer.PackInt(info.ColorFeet),
|
||||
packer.PackInt(info.ColorEyes),
|
||||
)
|
||||
}
|
||||
|
||||
func (info *ClStartInfo) Unpack(u *packer.Unpacker) {
|
||||
info.Name = u.GetString()
|
||||
info.Clan = u.GetString()
|
||||
info.Country = u.GetInt()
|
||||
info.Body = u.GetString()
|
||||
info.Marking = u.GetString()
|
||||
info.Decoration = u.GetString()
|
||||
info.Hands = u.GetString()
|
||||
info.Feet = u.GetString()
|
||||
info.Eyes = u.GetString()
|
||||
info.CustomColorBody = u.GetInt() != 0
|
||||
info.CustomColorMarking = u.GetInt() != 0
|
||||
info.CustomColorDecoration = u.GetInt() != 0
|
||||
info.CustomColorHands = u.GetInt() != 0
|
||||
info.CustomColorFeet = u.GetInt() != 0
|
||||
info.CustomColorEyes = u.GetInt() != 0
|
||||
info.ColorBody = u.GetInt()
|
||||
info.ColorMarking = u.GetInt()
|
||||
info.ColorDecoration = u.GetInt()
|
||||
info.ColorHands = u.GetInt()
|
||||
info.ColorFeet = u.GetInt()
|
||||
info.ColorEyes = u.GetInt()
|
||||
}
|
124
messages/cl_start_info_test.go
Normal file
124
messages/cl_start_info_test.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
package message
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/teeworlds-go/teeworlds/packer"
|
||||
)
|
||||
|
||||
func TestPackStartInfo(t *testing.T) {
|
||||
want := []byte{
|
||||
0x67, 0x6f, 0x70, 0x68, 0x65, 0x72, 0x00,
|
||||
0x00, 0x40, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x77, 0x61, 0x72,
|
||||
0x64, 0x00, 0x64, 0x75, 0x6f, 0x64, 0x6f, 0x6e, 0x6e, 0x79, 0x00,
|
||||
0x00, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x73,
|
||||
0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0xfc, 0xaf, 0x05, 0xeb, 0x83, 0xd0, 0x0a, 0x80, 0xfe,
|
||||
0x07, 0x80, 0xfe, 0x07, 0x80, 0xfe, 0x07, 0x80, 0xfe, 0x07,
|
||||
}
|
||||
|
||||
info := ClStartInfo{
|
||||
Name: "gopher",
|
||||
Clan: "",
|
||||
Country: -1,
|
||||
Body: "greensward",
|
||||
Marking: "duodonny",
|
||||
Decoration: "",
|
||||
Hands: "standard",
|
||||
Feet: "standard",
|
||||
Eyes: "standard",
|
||||
CustomColorBody: true,
|
||||
CustomColorMarking: true,
|
||||
CustomColorDecoration: false,
|
||||
CustomColorHands: false,
|
||||
CustomColorFeet: false,
|
||||
CustomColorEyes: false,
|
||||
ColorBody: 5635840,
|
||||
ColorMarking: -11141356,
|
||||
ColorDecoration: 65408,
|
||||
ColorHands: 65408,
|
||||
ColorFeet: 65408,
|
||||
ColorEyes: 65408,
|
||||
}
|
||||
|
||||
got := info.Pack()
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnpackStartInfo(t *testing.T) {
|
||||
u := packer.Unpacker{}
|
||||
u.Reset([]byte{
|
||||
0x67, 0x6f, 0x70, 0x68, 0x65, 0x72, 0x00,
|
||||
0x00, 0x40, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x77, 0x61, 0x72,
|
||||
0x64, 0x00, 0x64, 0x75, 0x6f, 0x64, 0x6f, 0x6e, 0x6e, 0x79, 0x00,
|
||||
0x00, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x73,
|
||||
0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0xfc, 0xaf, 0x05, 0xeb, 0x83, 0xd0, 0x0a, 0x80, 0xfe,
|
||||
0x07, 0x80, 0xfe, 0x07, 0x80, 0xfe, 0x07, 0x80, 0xfe, 0x07,
|
||||
})
|
||||
|
||||
info := ClStartInfo{}
|
||||
info.Unpack(&u)
|
||||
|
||||
{
|
||||
got := info.Eyes
|
||||
want := "standard"
|
||||
if got != want {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
}
|
||||
|
||||
got = info.Decoration
|
||||
want = ""
|
||||
if got != want {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
}
|
||||
|
||||
got = info.Marking
|
||||
want = "duodonny"
|
||||
if got != want {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
got := info.ColorDecoration
|
||||
want := 65408
|
||||
if got != want {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
wantedInfo := ClStartInfo{
|
||||
Name: "gopher",
|
||||
Clan: "",
|
||||
Country: -1,
|
||||
Body: "greensward",
|
||||
Marking: "duodonny",
|
||||
Decoration: "",
|
||||
Hands: "standard",
|
||||
Feet: "standard",
|
||||
Eyes: "standard",
|
||||
CustomColorBody: true,
|
||||
CustomColorMarking: true,
|
||||
CustomColorDecoration: false,
|
||||
CustomColorHands: false,
|
||||
CustomColorFeet: false,
|
||||
CustomColorEyes: false,
|
||||
ColorBody: 5635840,
|
||||
ColorMarking: -11141356,
|
||||
ColorDecoration: 65408,
|
||||
ColorHands: 65408,
|
||||
ColorFeet: 65408,
|
||||
ColorEyes: 65408,
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(info, wantedInfo) {
|
||||
t.Errorf("got %v, wanted %v", info, wantedInfo)
|
||||
}
|
||||
}
|
|
@ -111,6 +111,20 @@ func (u *Unpacker) GetInt() int {
|
|||
return res
|
||||
}
|
||||
|
||||
func PackStr(str string) []byte {
|
||||
return slices.Concat(
|
||||
[]byte(str),
|
||||
[]byte{0x00},
|
||||
)
|
||||
}
|
||||
|
||||
func PackBool(b bool) []byte {
|
||||
if b {
|
||||
return []byte{0x01}
|
||||
}
|
||||
return []byte{0x00}
|
||||
}
|
||||
|
||||
func PackInt(num int) []byte {
|
||||
res := []byte{0x00}
|
||||
idx := 0
|
||||
|
|
|
@ -7,6 +7,24 @@ import (
|
|||
|
||||
// pack
|
||||
|
||||
func TestPackEmptyString(t *testing.T) {
|
||||
got := PackStr("")
|
||||
want := []byte{0x00}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackSimpleString(t *testing.T) {
|
||||
got := PackStr("foo")
|
||||
want := []byte{'f', 'o', 'o', 0x00}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got %v, wanted %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackSmallPositiveInts(t *testing.T) {
|
||||
got := PackInt(1)
|
||||
want := []byte{0x01}
|
||||
|
|
96
teeworlds.go
96
teeworlds.go
|
@ -35,6 +35,7 @@ const (
|
|||
msgGameSvChat = 3
|
||||
msgGameReadyToEnter = 8
|
||||
msgGameSvClientInfo = 18
|
||||
msgGameClStartInfo = 27
|
||||
)
|
||||
|
||||
func ctrlToken(myToken []byte) []byte {
|
||||
|
@ -80,12 +81,19 @@ type TeeworldsClient struct {
|
|||
serverToken [4]byte
|
||||
conn net.Conn
|
||||
|
||||
// The amount of vital chunks received
|
||||
Ack int
|
||||
|
||||
// The amount of vital chunks sent
|
||||
Sequence int
|
||||
|
||||
// The amount of vital chunks acknowledged by the peer
|
||||
PeerAck int
|
||||
|
||||
Players []Player
|
||||
}
|
||||
|
||||
func (client TeeworldsClient) sendCtrlMsg(data []byte) {
|
||||
func (client *TeeworldsClient) sendCtrlMsg(data []byte) {
|
||||
header := packet.PacketHeader{
|
||||
Flags: packet.PacketFlags{
|
||||
Connless: false,
|
||||
|
@ -102,17 +110,51 @@ func (client TeeworldsClient) sendCtrlMsg(data []byte) {
|
|||
client.conn.Write(packet)
|
||||
}
|
||||
|
||||
func (client TeeworldsClient) sendKeepAlive() {
|
||||
func (client *TeeworldsClient) sendKeepAlive() {
|
||||
client.sendCtrlMsg([]byte{msgCtrlKeepAlive})
|
||||
}
|
||||
|
||||
func (client TeeworldsClient) sendReady() {
|
||||
func (client *TeeworldsClient) sendReady() {
|
||||
ready := []byte{0x40, 0x01, 0x02, 0x25}
|
||||
|
||||
client.Sequence++
|
||||
client.sendPacket(ready, 1)
|
||||
}
|
||||
|
||||
func (client TeeworldsClient) sendPacket(payload []byte, numChunks int) {
|
||||
type ChunkArgs struct {
|
||||
MsgId int
|
||||
System bool
|
||||
Flags chunk.ChunkFlags
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
func (client *TeeworldsClient) packChunk(c ChunkArgs) []byte {
|
||||
c.MsgId <<= 1
|
||||
if c.System {
|
||||
c.MsgId |= 1
|
||||
}
|
||||
|
||||
client.Sequence++
|
||||
msgAndSys := packer.PackInt(c.MsgId)
|
||||
|
||||
chunkHeader := chunk.ChunkHeader{
|
||||
Flags: c.Flags,
|
||||
Size: len(msgAndSys) + len(c.Payload),
|
||||
Seq: client.Sequence,
|
||||
}
|
||||
|
||||
data := slices.Concat(
|
||||
chunkHeader.Pack(),
|
||||
msgAndSys,
|
||||
c.Payload,
|
||||
)
|
||||
|
||||
fmt.Printf("packed chunk: %x\n", data)
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func (client *TeeworldsClient) sendPacket(payload []byte, numChunks int) {
|
||||
header := packet.PacketHeader{
|
||||
Flags: packet.PacketFlags{
|
||||
Connless: false,
|
||||
|
@ -129,29 +171,53 @@ func (client TeeworldsClient) sendPacket(payload []byte, numChunks int) {
|
|||
client.conn.Write(packet)
|
||||
}
|
||||
|
||||
func (client TeeworldsClient) sendInfo() {
|
||||
func (client *TeeworldsClient) sendInfo() {
|
||||
info := []byte{0x40, 0x28, 0x01, 0x03, 0x30, 0x2E, 0x37, 0x20, 0x38, 0x30, 0x32, 0x66,
|
||||
0x31, 0x62, 0x65, 0x36, 0x30, 0x61, 0x30, 0x35, 0x36, 0x36, 0x35, 0x66,
|
||||
0x00, 0x6D, 0x79, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64,
|
||||
0x5F, 0x31, 0x32, 0x33, 0x00, 0x85, 0x1C, 0x00}
|
||||
|
||||
client.Sequence++
|
||||
client.sendPacket(info, 1)
|
||||
}
|
||||
|
||||
func (client TeeworldsClient) sendStartInfo() {
|
||||
info := []byte{
|
||||
0x41, 0x14, 0x03, 0x36, 0x67, 0x6f, 0x70, 0x68, 0x65, 0x72, 0x00, 0x00, 0x40, 0x67, 0x72, 0x65,
|
||||
0x65, 0x6e, 0x73, 0x77, 0x61, 0x72, 0x64, 0x00, 0x64, 0x75, 0x6f, 0x64, 0x6f, 0x6e, 0x6e, 0x79,
|
||||
0x00, 0x00, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x73, 0x74, 0x61, 0x6e, 0x64,
|
||||
0x61, 0x72, 0x64, 0x00, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x00, 0x01, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x80, 0xfc, 0xaf, 0x05, 0xeb, 0x83, 0xd0, 0x0a, 0x80, 0xfe, 0x07, 0x80, 0xfe,
|
||||
0x07, 0x80, 0xfe, 0x07, 0x80, 0xfe, 0x07,
|
||||
func (client *TeeworldsClient) sendStartInfo() {
|
||||
info := message.ClStartInfo{
|
||||
Name: "gopher",
|
||||
Clan: "",
|
||||
Country: 0,
|
||||
Body: "greensward",
|
||||
Marking: "duodonny",
|
||||
Decoration: "",
|
||||
Hands: "standard",
|
||||
Feet: "standard",
|
||||
Eyes: "standard",
|
||||
CustomColorBody: false,
|
||||
CustomColorMarking: false,
|
||||
CustomColorDecoration: false,
|
||||
CustomColorHands: false,
|
||||
CustomColorFeet: false,
|
||||
CustomColorEyes: false,
|
||||
ColorBody: 0,
|
||||
ColorMarking: 0,
|
||||
ColorDecoration: 0,
|
||||
ColorHands: 0,
|
||||
ColorFeet: 0,
|
||||
ColorEyes: 0,
|
||||
}
|
||||
|
||||
client.sendPacket(info, 1)
|
||||
payload := client.packChunk(ChunkArgs{
|
||||
MsgId: msgGameClStartInfo,
|
||||
Flags: chunk.ChunkFlags{
|
||||
Vital: true,
|
||||
},
|
||||
Payload: info.Pack(),
|
||||
})
|
||||
|
||||
client.sendPacket(payload, 1)
|
||||
}
|
||||
|
||||
func (client TeeworldsClient) sendEnterGame() {
|
||||
func (client *TeeworldsClient) sendEnterGame() {
|
||||
enter := []byte{
|
||||
0x40, 0x01, 0x04, 0x27,
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsCtrlMsg(t *testing.T) {
|
||||
data := []byte{0x04, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x04}
|
||||
|
||||
got := isCtrlMsg(data)
|
||||
want := true
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got %t, wanted %t", got, want)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue