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,49 +96,67 @@ 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 ):
92- if (
93- self .index == - 1
94- or len (packet .players ) <= self .index
95- or packet .players [self .index ].spawn_id != self .spawn_id
96- ):
97- # spawn id should only be 0 if RLBOT_SPAWN_IDS was not set
98- if self .spawn_id == 0 :
99- # in this case, if there's only one player, we can assume it's us
100- player_index = - 1
101- for i , player in enumerate (packet .players ):
102- # skip human players/psyonix bots
103- if not player .is_bot :
104- continue
102+ self ._latest_packet = packet
103+ self ._packet_event .set ()
105104
106- if player_index != - 1 :
107- self .logger .error (
108- "Multiple bots in the game, please set RLBOT_SPAWN_IDS"
109- )
110- return
105+ def _packet_processor (self ):
106+ while self ._run_packet_thread :
107+ self ._packet_event .wait ()
111108
112- player_index = i
113- self .index = player_index
109+ # if the thread was unblocked,
110+ # but it we're not supposed to be running,
111+ # then exit
112+ if not self ._run_packet_thread :
113+ return
114114
115- for i , player in enumerate (packet .players ):
116- if player .spawn_id == self .spawn_id :
117- self .index = i
118- break
115+ self .ball_prediction = self ._lastest_prediction
116+ packet : flat .GameTickPacket = self ._latest_packet
117+
118+ self ._packet_event .clear ()
119+
120+ if (
121+ self .index == - 1
122+ or len (packet .players ) <= self .index
123+ or packet .players [self .index ].spawn_id != self .spawn_id
124+ ):
125+ # spawn id should only be 0 if RLBOT_SPAWN_IDS was not set
126+ if self .spawn_id == 0 :
127+ # in this case, if there's only one player, we can assume it's us
128+ player_index = - 1
129+ for i , player in enumerate (packet .players ):
130+ # skip human players/psyonix bots
131+ if not player .is_bot :
132+ continue
133+
134+ if player_index != - 1 :
135+ self .logger .error (
136+ "Multiple bots in the game, please set RLBOT_SPAWN_IDS"
137+ )
138+ return
139+
140+ player_index = i
141+ self .index = player_index
119142
120- if self .index == - 1 :
143+ for i , player in enumerate (packet .players ):
144+ if player .spawn_id == self .spawn_id :
145+ self .index = i
146+ break
147+
148+ if self .index == - 1 :
149+ return
150+
151+ try :
152+ controller = self .get_output (packet )
153+ except Exception as e :
154+ self .logger .error ("Bot %s returned an error to RLBot: %s" , self .name , e )
155+ print_exc ()
121156 return
122157
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
129-
130- player_input = flat .PlayerInput (self .index , controller )
131- self ._game_interface .send_player_input (player_input )
158+ player_input = flat .PlayerInput (self .index , controller )
159+ self ._game_interface .send_player_input (player_input )
132160
133161 def run (
134162 self ,
@@ -144,6 +172,9 @@ def run(
144172 rlbot_server_port = rlbot_server_port ,
145173 )
146174 finally :
175+ self ._run_packet_thread = False
176+ self ._packet_event .set ()
177+
147178 self .retire ()
148179 del self ._game_interface
149180
0 commit comments