11import os
2+ from threading import Thread , Event
23from traceback import print_exc
34from typing import Optional
45
@@ -28,6 +29,12 @@ class Bot:
2829 _has_match_settings = False
2930 _has_field_info = False
3031
32+ _latest_packet = flat .GameTickPacket ()
33+ _lastest_prediction = flat .BallPrediction ()
34+ _packet_event = Event ()
35+ _packet_thread = None
36+ _run_packet_thread = True
37+
3138 def __init__ (self ):
3239 spawn_id = os .environ .get ("RLBOT_SPAWN_IDS" )
3340
@@ -48,6 +55,9 @@ def __init__(self):
4855 )
4956 self ._game_interface .packet_handlers .append (self ._handle_packet )
5057
58+ self ._packet_thread = Thread (target = self ._packet_processor , daemon = True )
59+ self ._packet_thread .start ()
60+
5161 self .renderer = Renderer (self ._game_interface )
5262
5363 def _initialize_agent (self ):
@@ -86,9 +96,13 @@ def _handle_field_info(self, field_info: flat.FieldInfo):
8696 self ._initialize_agent ()
8797
8898 def _handle_ball_prediction (self , ball_prediction : flat .BallPrediction ):
89- self .ball_prediction = ball_prediction
99+ self ._lastest_prediction = ball_prediction
90100
91101 def _handle_packet (self , packet : flat .GameTickPacket ):
102+ self ._latest_packet = packet
103+ self ._packet_event .set ()
104+
105+ def _packet_preprocess (self , packet : flat .GameTickPacket ) -> bool :
92106 if (
93107 self .index == - 1
94108 or len (packet .players ) <= self .index
@@ -107,7 +121,7 @@ def _handle_packet(self, packet: flat.GameTickPacket):
107121 self .logger .error (
108122 "Multiple bots in the game, please set RLBOT_SPAWN_IDS"
109123 )
110- return
124+ return False
111125
112126 player_index = i
113127 self .index = player_index
@@ -118,17 +132,37 @@ def _handle_packet(self, packet: flat.GameTickPacket):
118132 break
119133
120134 if self .index == - 1 :
135+ return False
136+
137+ return True
138+
139+ def _packet_processor (self ):
140+ while self ._run_packet_thread :
141+ self ._packet_event .wait ()
142+
143+ # if the thread was unblocked,
144+ # but it we're not supposed to be running,
145+ # then exit
146+ if not self ._run_packet_thread :
121147 return
122148
123- try :
124- controller = self .get_output (packet )
125- except Exception as e :
126- self .logger .error ("Bot %s returned an error to RLBot: %s" , self .name , e )
127- print_exc ()
128- return
149+ self .ball_prediction = self ._lastest_prediction
150+ packet : flat .GameTickPacket = self ._latest_packet
151+
152+ self ._packet_event .clear ()
153+
154+ if not self ._packet_preprocess (packet ):
155+ continue
129156
130- player_input = flat .PlayerInput (self .index , controller )
131- self ._game_interface .send_player_input (player_input )
157+ try :
158+ controller = self .get_output (packet )
159+ except Exception as e :
160+ self .logger .error ("Bot %s returned an error to RLBot: %s" , self .name , e )
161+ print_exc ()
162+ continue
163+
164+ player_input = flat .PlayerInput (self .index , controller )
165+ self ._game_interface .send_player_input (player_input )
132166
133167 def run (
134168 self ,
@@ -144,6 +178,9 @@ def run(
144178 rlbot_server_port = rlbot_server_port ,
145179 )
146180 finally :
181+ self ._run_packet_thread = False
182+ self ._packet_event .set ()
183+
147184 self .retire ()
148185 del self ._game_interface
149186
0 commit comments