-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathconnection.go
More file actions
154 lines (131 loc) · 3.97 KB
/
Copy pathconnection.go
File metadata and controls
154 lines (131 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package gointerface
import (
"encoding/binary"
"errors"
"io"
"net"
"os"
flat "github.com/RLBot/go-interface/flat"
flatbuffers "github.com/google/flatbuffers/go"
)
type RLBotConnection struct {
conn net.Conn
builder flatbuffers.Builder
}
func Connect(addr string) (RLBotConnection, error) {
conn, err := net.Dial("tcp", addr)
if tcpConn, ok := conn.(*net.TCPConn); ok {
tcpConn.SetNoDelay(true)
}
return RLBotConnection{conn, *flatbuffers.NewBuilder(65536)}, err
}
func (conn RLBotConnection) Initialize(default_agent_id string, wants_ball_predictions bool, wants_comms bool) (*flat.MatchConfigurationT, *flat.FieldInfoT, *flat.ControllableTeamInfoT, error) {
agent_id := os.Getenv("RLBOT_AGENT_ID")
if agent_id == "" {
agent_id = default_agent_id
}
err := conn.SendPacket(&flat.ConnectionSettingsT{
AgentId: agent_id,
WantsBallPredictions: wants_ball_predictions,
WantsComms: wants_comms,
CloseBetweenMatches: true,
})
if err != nil {
return nil, nil, nil, err
}
var match_config *flat.MatchConfigurationT
var field_info *flat.FieldInfoT
var controllables *flat.ControllableTeamInfoT
for {
packet, err := conn.RecvPacket()
if err != nil {
return nil, nil, nil, err
}
switch packet := packet.Value.(type) {
case *flat.MatchConfigurationT:
match_config = packet
case *flat.FieldInfoT:
field_info = packet
case *flat.ControllableTeamInfoT:
controllables = packet
}
if match_config != nil && field_info != nil && controllables != nil {
break
}
}
err = conn.SendPacket(&flat.InitCompleteT{})
if err != nil {
return nil, nil, nil, err
}
return match_config, field_info, controllables, nil
}
func (conn RLBotConnection) SendPacket(msg any) error {
var packetType flat.InterfaceMessage
switch msg.(type) {
case *flat.DisconnectSignalT:
packetType = flat.InterfaceMessageDisconnectSignal
case *flat.StartCommandT:
packetType = flat.InterfaceMessageStartCommand
case *flat.MatchConfigurationT:
packetType = flat.InterfaceMessageMatchConfiguration
case *flat.PlayerInputT:
packetType = flat.InterfaceMessagePlayerInput
case *flat.DesiredGameStateT:
packetType = flat.InterfaceMessageDesiredGameState
case *flat.RenderGroupT:
packetType = flat.InterfaceMessageRenderGroup
case *flat.RemoveRenderGroupT:
packetType = flat.InterfaceMessageRemoveRenderGroup
case *flat.MatchCommT:
packetType = flat.InterfaceMessageMatchComm
case *flat.ConnectionSettingsT:
packetType = flat.InterfaceMessageConnectionSettings
case *flat.StopCommandT:
packetType = flat.InterfaceMessageStopCommand
case *flat.SetLoadoutT:
packetType = flat.InterfaceMessageSetLoadout
case *flat.InitCompleteT:
packetType = flat.InterfaceMessageInitComplete
case *flat.RenderingStatusT:
packetType = flat.InterfaceMessageRenderingStatus
case *flat.PingRequestT:
packetType = flat.InterfaceMessagePingRequest
case *flat.PingResponseT:
packetType = flat.InterfaceMessagePingResponse
case *flat.UpdatePerformanceMonitorT:
packetType = flat.InterfaceMessageUpdatePerformanceMonitor
default:
return errors.New("unsupported packet type")
}
packet := flat.InterfacePacketT{
Message: &flat.InterfaceMessageT{
Type: packetType,
Value: msg,
},
}
conn.builder.Reset()
conn.builder.Finish(packet.Pack(&conn.builder))
packetPayload := conn.builder.FinishedBytes()
packetLen := len(packetPayload)
finalBuf := make([]byte, 2)
binary.BigEndian.PutUint16(finalBuf, uint16(packetLen))
finalBuf = append(finalBuf, packetPayload...)
_, err := conn.conn.Write(finalBuf)
return err
}
func (conn RLBotConnection) RecvPacket() (*flat.CoreMessageT, error) {
buffer := make([]byte, 2)
// Read packetLen
_, err := io.ReadFull(conn.conn, buffer)
if err != nil {
return nil, err
}
packetLen := binary.BigEndian.Uint16(buffer)
// Read packetPayload
buffer = make([]byte, packetLen)
_, err = io.ReadFull(conn.conn, buffer)
if err != nil {
return nil, err
}
return flat.GetRootAsCorePacket(buffer, 0).UnPack().Message, nil
}