@@ -29,6 +29,7 @@ class Hivemind:
2929 _initialized_bot = False
3030 _has_match_settings = False
3131 _has_field_info = False
32+ _has_player_mapping = False
3233
3334 _latest_packet : Optional [flat .GameTickPacket ] = None
3435 _latest_prediction = flat .BallPrediction ()
@@ -54,6 +55,12 @@ def __init__(self):
5455 self .renderer = Renderer (self ._game_interface )
5556
5657 def _initialize_agent (self ):
58+ # search match settings for our spawn ids
59+ for player in self .match_settings .player_configurations :
60+ if player .spawn_id in self .spawn_ids :
61+ self .names .append (player .name )
62+ self .loggers .append (get_logger (player .name ))
63+
5764 try :
5865 self .initialize_agent ()
5966 except Exception as e :
@@ -72,21 +79,37 @@ def _handle_match_settings(self, match_settings: flat.MatchSettings):
7279 self .match_settings = match_settings
7380 self ._has_match_settings = True
7481
75- # search match settings for our spawn ids
76- for player in self .match_settings .player_configurations :
77- if player .spawn_id in self .spawn_ids :
78- self .team = player .team
79- self .names .append (player .name )
80- self .loggers .append (get_logger (player .name ))
81-
82- if not self ._initialized_bot and self ._has_field_info :
82+ if (
83+ not self ._initialized_bot
84+ and self ._has_field_info
85+ and self ._has_player_mapping
86+ ):
8387 self ._initialize_agent ()
8488
8589 def _handle_field_info (self , field_info : flat .FieldInfo ):
8690 self .field_info = field_info
8791 self ._has_field_info = True
8892
89- if not self ._initialized_bot and self ._has_match_settings :
93+ if (
94+ not self ._initialized_bot
95+ and self ._has_match_settings
96+ and self ._has_player_mapping
97+ ):
98+ self ._initialize_agent ()
99+
100+ def _handle_player_mappings (self , player_mappings : flat .TeamControllables ):
101+ self .team = player_mappings .team
102+ for controllable in player_mappings .controllables :
103+ self .spawn_ids .append (controllable .spawn_id )
104+ self .indices .append (controllable .index )
105+
106+ self ._has_player_mapping = True
107+
108+ if (
109+ not self ._initialized_bot
110+ and self ._has_match_settings
111+ and self ._has_field_info
112+ ):
90113 self ._initialize_agent ()
91114
92115 def _handle_ball_prediction (self , ball_prediction : flat .BallPrediction ):
@@ -96,17 +119,8 @@ def _handle_packet(self, packet: flat.GameTickPacket):
96119 self ._latest_packet = packet
97120
98121 def _packet_processor (self , packet : flat .GameTickPacket ):
99- if len (self .indices ) != len (self .spawn_ids ) or any (
100- packet .players [i ].spawn_id not in self .spawn_ids for i in self .indices
101- ):
102- self .indices = [
103- i
104- for i , player in enumerate (packet .players )
105- if player .spawn_id in self .spawn_ids
106- ]
107-
108- if len (self .indices ) != len (self .spawn_ids ):
109- return
122+ if len (packet .players ) <= self .indices [- 1 ]:
123+ return
110124
111125 self .ball_prediction = self ._latest_prediction
112126
@@ -137,34 +151,18 @@ def run(
137151 rlbot_server_port = rlbot_server_port ,
138152 )
139153
140- # custom message handling logic
141- # this reads all data in the socket until there's no more immediately available
142- # checks if there was a GameTickPacket in the data, and if so, processes it
143- # then sets the socket to non-blocking and waits for more data
144- # if there was no GameTickPacket, it sets to blocking and waits for more data
154+ # see bot.py for an explanation of this loop
145155 while True :
146156 try :
147157 self ._game_interface .handle_incoming_messages (True )
148-
149- # a clean exit means that the socket was closed
150158 break
151159 except BlockingIOError :
152- # the socket was still open,
153- # but we don't know if data was read
154160 pass
155161
156- # check data was read that needs to be processed
157162 if self ._latest_packet is None :
158- # there's no data we need to process
159- # data is coming, but we haven't gotten it yet - wait for it
160- # after `handle_incoming_messages` gets it's first message,
161- # it will set the socket back to non-blocking on its own
162- # that will ensure that `BlockingIOError` gets raised
163- # when it's done reading the next batch of messages
164163 self ._game_interface .socket .setblocking (True )
165164 continue
166165
167- # process the packet that we got
168166 self ._packet_processor (self ._latest_packet )
169167 self ._latest_packet = None
170168 finally :
0 commit comments