From 8d1c41fa4f340997873e91cddda5ed2f3308f194 Mon Sep 17 00:00:00 2001 From: Nikhil Banerjee <97465665+nikbanerjee-unity@users.noreply.github.com> Date: Thu, 13 Oct 2022 17:43:09 +0100 Subject: [PATCH] feat(tf2-e): Update tf2e query for v9 schema (#29) This change implements the latest version (v9) of the TF2E protocol --- .gitignore | 3 ++ lib/svrquery/protocol/titanfall/query.go | 30 +++++++++-- lib/svrquery/protocol/titanfall/query_test.go | 28 +++++++++- lib/svrquery/protocol/titanfall/register.go | 1 + .../protocol/titanfall/testdata/request-v9 | Bin 0 -> 1200 bytes .../protocol/titanfall/testdata/response-v9 | Bin 0 -> 197 bytes lib/svrquery/protocol/titanfall/types.go | 50 ++++++++++++++---- 7 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 lib/svrquery/protocol/titanfall/testdata/request-v9 create mode 100755 lib/svrquery/protocol/titanfall/testdata/response-v9 diff --git a/.gitignore b/.gitignore index fd6223a..2ede1fa 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ .idea/ .DS_Store Thumbs.db + +# Binary +go-svrquery diff --git a/lib/svrquery/protocol/titanfall/query.go b/lib/svrquery/protocol/titanfall/query.go index af54264..c2c6b7e 100644 --- a/lib/svrquery/protocol/titanfall/query.go +++ b/lib/svrquery/protocol/titanfall/query.go @@ -161,7 +161,12 @@ func (q *queryer) Query() (resp protocol.Responser, err error) { return nil, err } - if i.Version > 4 { + if i.Version >= 9 { + // PerformanceInfoV9. + if err = r.Read(&i.PerformanceInfoV9); err != nil { + return nil, err + } + } else if i.Version > 4 { // PerformanceInfo. if err = r.Read(&i.PerformanceInfo); err != nil { return nil, err @@ -169,7 +174,11 @@ func (q *queryer) Query() (resp protocol.Responser, err error) { } if i.Version > 2 { - if i.Version > 5 { + if i.Version >= 9 { + if err = r.Read(&i.MatchStateV9); err != nil { + return nil, err + } + } else if i.Version > 5 { // MatchState and Teams. if err = r.Read(&i.MatchState); err != nil { return nil, err @@ -249,9 +258,24 @@ func (q *queryer) basicInfo(r *common.BinaryReader, i *Info) (err error) { if err = r.Read(&i.BasicInfo.NumClients); err != nil { return err - } else if err = r.Read(&i.BasicInfo.MaxClients); err != nil { + } + + if i.Version >= 9 { + if err = r.Read(&i.BasicInfo.NumBotClients); err != nil { + return err + } + } + + if err = r.Read(&i.BasicInfo.MaxClients); err != nil { return err } + + if i.Version >= 9 { + if err = r.Read(&i.BasicInfo.TotalClientsConnectedEver); err != nil { + return err + } + } + i.BasicInfo.Map, err = r.ReadString() return err } diff --git a/lib/svrquery/protocol/titanfall/query_test.go b/lib/svrquery/protocol/titanfall/query_test.go index 71b7efb..23332e0 100644 --- a/lib/svrquery/protocol/titanfall/query_test.go +++ b/lib/svrquery/protocol/titanfall/query_test.go @@ -75,7 +75,7 @@ func TestQuery(t *testing.T) { AverageUserCommandTime: 3, MaxUserCommandTime: 4, } - v7.TeamsLeftWithPlayersNum = 6 + v7.MatchState.TeamsLeftWithPlayersNum = 6 v8 := v7 v8.Version = 8 @@ -89,6 +89,23 @@ func TestQuery(t *testing.T) { } v8.InstanceInfo = InstanceInfo{} + v9 := v8 + v9.Version = 9 + v9.BasicInfo.NumBotClients = 3 + v9.BasicInfo.TotalClientsConnectedEver = 0 + v9.PerformanceInfoV9 = PerformanceInfoV9{ + PerformanceInfo: v8.PerformanceInfo, + CommitMemory: 8472, + ResidentMemory: 3901, + } + v9.PerformanceInfo = PerformanceInfo{} + v9.MatchStateV9 = MatchStateV9{ + Phase: 3, + TimePassed: 0, + TeamsLeftWithPlayersNum: 0, + } + v9.MatchState = MatchState{} + cases := []struct { name string version byte @@ -121,6 +138,15 @@ func TestQuery(t *testing.T) { key: testKey, expEncypted: true, }, + { + name: "v9", + version: 9, + request: "request-v9", + response: "response-v9", + expected: v9, + key: testKey, + expEncypted: true, + }, { name: "keyed", version: 5, diff --git a/lib/svrquery/protocol/titanfall/register.go b/lib/svrquery/protocol/titanfall/register.go index a2e48b4..fb9d5a1 100644 --- a/lib/svrquery/protocol/titanfall/register.go +++ b/lib/svrquery/protocol/titanfall/register.go @@ -9,4 +9,5 @@ func init() { protocol.MustRegister("tf2e", newQueryer(3)) protocol.MustRegister("tf2e-v7", newQueryer(7)) protocol.MustRegister("tf2e-v8", newQueryer(8)) + protocol.MustRegister("tf2e-v9", newQueryer(9)) } diff --git a/lib/svrquery/protocol/titanfall/testdata/request-v9 b/lib/svrquery/protocol/titanfall/testdata/request-v9 new file mode 100644 index 0000000000000000000000000000000000000000..4c925c03e47ad01340e3d21fb67dec1aa46c4921 GIT binary patch literal 1200 acmezW|Nnnq4u(-M8UmvsFd71bJ_GZHe>)k3k0t&4wAZmVQFJK6e_S%e&{nyAQ50 z#^iIywaYAA{B@0GNh)r5-Qf0LLZZ*(1z^Nk4$AG<5&~ literal 0 HcmV?d00001 diff --git a/lib/svrquery/protocol/titanfall/types.go b/lib/svrquery/protocol/titanfall/types.go index c3eeab1..2a58efa 100644 --- a/lib/svrquery/protocol/titanfall/types.go +++ b/lib/svrquery/protocol/titanfall/types.go @@ -22,8 +22,13 @@ type Info struct { BasicInfo // Version 4+ PerformanceInfo + // Version 9+ + PerformanceInfoV9 // Version 2+ MatchState + // Version 9+ + MatchStateV9 + Teams []Team Clients []Client } @@ -33,11 +38,21 @@ func (i Info) NumClients() int64 { return int64(i.BasicInfo.NumClients) } +// NumBotClients implements protocol.Responser. +func (i Info) NumBotClients() int64 { + return int64(i.BasicInfo.NumBotClients) +} + // MaxClients implements protocol.Responser. func (i Info) MaxClients() int64 { return int64(i.BasicInfo.MaxClients) } +// TotalClientsConnectedEver implements protocol.Responser. +func (i Info) TotalClientsConnectedEver() int64 { + return int64(i.BasicInfo.TotalClientsConnectedEver) +} + // Map implements protocol.Mapper. func (i Info) Map() string { return i.BasicInfo.Map @@ -139,15 +154,24 @@ func (a HealthFlags) DOS() bool { // BasicInfo represents basic information contained in a query response. type BasicInfo struct { - Port uint16 - Platform string - PlaylistVersion string - PlaylistNum uint32 - PlaylistName string - NumClients byte - MaxClients byte - Map string - PlatformPlayers map[string]byte + Port uint16 + Platform string + PlaylistVersion string + PlaylistNum uint32 + PlaylistName string + NumClients byte + NumBotClients byte + MaxClients byte + TotalClientsConnectedEver uint32 + Map string + PlatformPlayers map[string]byte +} + +// PerformanceInfoV9 represents frame information contained in a query response. +type PerformanceInfoV9 struct { + PerformanceInfo + CommitMemory uint32 + ResidentMemory uint32 } // PerformanceInfo represents frame information contained in a query response. @@ -158,6 +182,14 @@ type PerformanceInfo struct { MaxUserCommandTime float32 } +// MatchStateV9 represents match state contained in a query response. +// A number of fields were removed in this version of the schema. +type MatchStateV9 struct { + Phase byte + TimePassed uint16 // seconds + TeamsLeftWithPlayersNum uint16 +} + // MatchStateV2 represents match state contained in a query response. // This contains a legacy v2 version of matchstate type MatchStateV2 struct {