def load_ghosts(player_id, state, ghosts): folder = '%s/%s/ghosts/%s/%s' % (STORAGE_DIR, player_id, zo.get_course(state), zo.road_id(state)) if not zo.is_forward(state): folder += '/reverse' if not os.path.isdir(folder): return s = list() for f in os.listdir(folder): if f.endswith('.bin'): with open(os.path.join(folder, f), 'rb') as fd: g = ghosts.play.ghosts.add() g.ParseFromString(fd.read()) s.append(g.states[0].roadTime) ghosts.start_road = zo.road_id(state) ghosts.start_rt = 0 if os.path.isfile(START_LINES_FILE): with open(START_LINES_FILE, 'r') as fd: sl = [tuple(line) for line in csv.reader(fd)] rt = [ t for t in sl if t[0] == str(zo.get_course(state)) and t[1] == str(zo.road_id(state)) and ( boolean(t[2]) == zo.is_forward(state) or not t[2]) ] if rt: ghosts.start_road = int(rt[0][3]) ghosts.start_rt = int(rt[0][4]) if not ghosts.start_rt: s.append(state.roadTime) if zo.is_forward(state): ghosts.start_rt = max(s) else: ghosts.start_rt = min(s) for g in ghosts.play.ghosts: try: while zo.road_id(g.states[0]) != ghosts.start_road: del g.states[0] if zo.is_forward(g.states[0]): while g.states[0].roadTime < ghosts.start_rt or abs( g.states[0].roadTime - ghosts.start_rt) > 500000: del g.states[0] else: while g.states[0].roadTime > ghosts.start_rt or abs( g.states[0].roadTime - ghosts.start_rt) > 500000: del g.states[0] except IndexError: pass
def save_ghost(name, player_id): global global_ghosts if not player_id in global_ghosts.keys(): return ghosts = global_ghosts[player_id] if len(ghosts.rec.states) > 0: folder = '%s/%s/ghosts/%s/%s' % (STORAGE_DIR, player_id, zo.get_course(ghosts.rec.states[0]), zo.road_id(ghosts.rec.states[0])) if not zo.is_forward(ghosts.rec.states[0]): folder += '/reverse' try: if not os.path.isdir(folder): os.makedirs(folder) except Exception as exc: print('save_ghost: %s' % repr(exc)) f = '%s/%s-%s.bin' % ( folder, zo.get_utc_date_time().strftime("%Y-%m-%d-%H-%M-%S"), name) with open(f, 'wb') as fd: fd.write(ghosts.rec.SerializeToString()) ghosts.rec = None
def organize_ghosts(player_id): # organize ghosts in course/road_id directory structure # previously they were saved directly in player_id/ghosts folder = '%s/%s/ghosts' % (STORAGE_DIR, player_id) if not os.path.isdir(folder): return for f in os.listdir(folder): if f.endswith('.bin'): file = os.path.join(folder, f) with open(file, 'rb') as fd: g = udp_node_msgs_pb2.Ghost() g.ParseFromString(fd.read()) dest = '%s/%s/%s' % (folder, zo.get_course( g.states[0]), zo.road_id(g.states[0])) if not zo.is_forward(g.states[0]): dest += '/reverse' try: if not os.path.isdir(dest): os.makedirs(dest) except Exception as exc: print('organize_ghosts: %s' % repr(exc)) os.rename(file, os.path.join(dest, f))
def handle(self): data = self.request[0] socket = self.request[1] recv = udp_node_msgs_pb2.ClientToServer() try: recv.ParseFromString(data[:-4]) except: try: #If no sensors connected, first byte must be skipped recv.ParseFromString(data[1:-4]) except Exception as exc: print('UDPHandler ParseFromString exception: %s' % repr(exc)) return client_address = self.client_address player_id = recv.player_id state = recv.state #Add last updates for player if missing if not player_id in last_pp_updates.keys(): last_pp_updates[player_id] = 0 if not player_id in last_bot_updates.keys(): last_bot_updates[player_id] = 0 t = int(zo.get_utc_time()) #Update player online state if state.roadTime: if player_id in online.keys(): if online[player_id].worldTime > state.worldTime: return #udp is unordered -> drop old state elif time.time() > start_time + 10: discord.change_presence(len(online) + 1) online[player_id] = state #Add handling of ghosts for player if it's missing if not player_id in global_ghosts.keys(): global_ghosts[player_id] = GhostsVariables() ghosts = global_ghosts[player_id] ghosts.last_package_time = t if recv.seqno == 1: ghosts.rec = None organize_ghosts(player_id) #Changed course if zo.get_course(state) and ghosts.course != zo.get_course(state): ghosts.rec = None ghosts.course = zo.get_course(state) if ghosts.rec == None: ghosts.rec = udp_node_msgs_pb2.Ghost() ghosts.play = udp_node_msgs_pb2.Ghosts() ghosts.last_rt = 0 ghosts.play_count = 0 ghosts.loaded = False ghosts.started = False ghosts.rec.player_id = player_id if player_id in ghosts_enabled and ghosts_enabled[player_id]: #Load ghosts for current course if not ghosts.loaded and zo.get_course(state): ghosts.loaded = True load_ghosts(player_id, state, ghosts) #Save player state as ghost if moving if state.roadTime and ghosts.last_rt and state.roadTime != ghosts.last_rt: if t >= ghosts.last_rec + ghost_update_freq: s = ghosts.rec.states.add() s.CopyFrom(state) ghosts.last_rec = t #Start loaded ghosts if not ghosts.started and ghosts.play.ghosts and zo.road_id( state) == ghosts.start_road: if zo.is_forward(state): if state.roadTime > ghosts.start_rt and abs( state.roadTime - ghosts.start_rt) < 500000: ghosts.started = True else: if state.roadTime < ghosts.start_rt and abs( state.roadTime - ghosts.start_rt) < 500000: ghosts.started = True #Uncomment to print player state when stopped (to find new start lines) #else: print('course', zo.get_course(state), 'road', zo.road_id(state), 'isForward', zo.is_forward(state), 'roadTime', state.roadTime) ghosts.last_rt = state.roadTime #Set state of player being watched watching_state = None if state.watchingRiderId == player_id: watching_state = state elif state.watchingRiderId in online.keys(): watching_state = online[state.watchingRiderId] elif state.watchingRiderId in global_pace_partners.keys(): pp = global_pace_partners[state.watchingRiderId] watching_state = pp.route.states[pp.position] elif state.watchingRiderId in global_bots.keys(): bot = global_bots[state.watchingRiderId] watching_state = bot.route.states[bot.position] elif state.watchingRiderId > 10000000: ghost = ghosts.play.ghosts[math.floor(state.watchingRiderId / 10000000) - 1] if len(ghost.states) > ghosts.play_count: watching_state = ghost.states[ghosts.play_count] #Check if online players, pace partners, bots and ghosts are nearby nearby = list() for p_id in online.keys(): player = online[p_id] if player.id != player_id and zo.is_nearby( watching_state, player) and is_state_new_for( player, player_id): nearby.append(p_id) if t >= last_pp_updates[player_id] + pacer_update_freq: last_pp_updates[player_id] = t for p_id in global_pace_partners.keys(): pace_partner_variables = global_pace_partners[p_id] pace_partner = pace_partner_variables.route.states[ pace_partner_variables.position] if zo.is_nearby(watching_state, pace_partner): nearby.append(p_id) if t >= last_bot_updates[player_id] + bot_update_freq: last_bot_updates[player_id] = t for p_id in global_bots.keys(): bot_variables = global_bots[p_id] bot = bot_variables.route.states[bot_variables.position] if zo.is_nearby(watching_state, bot): nearby.append(p_id) if ghosts.started and t >= ghosts.last_play + ghost_update_freq: ghosts.last_play = t ghost_id = 1 for g in ghosts.play.ghosts: if len(g.states) > ghosts.play_count and zo.is_nearby( watching_state, g.states[ghosts.play_count]): nearby.append(player_id + ghost_id * 10000000) ghost_id += 1 ghosts.play_count += 1 #Send nearby riders states or empty message message = get_empty_message(player_id) if nearby: message.num_msgs = math.ceil(len(nearby) / 10) for p_id in nearby: player = None if p_id in online.keys(): player = online[p_id] elif p_id in global_pace_partners.keys(): pace_partner_variables = global_pace_partners[p_id] player = pace_partner_variables.route.states[ pace_partner_variables.position] elif p_id in global_bots.keys(): bot_variables = global_bots[p_id] player = bot_variables.route.states[bot_variables.position] elif p_id > 10000000: player = udp_node_msgs_pb2.PlayerState() player.CopyFrom( ghosts.play.ghosts[math.floor(p_id / 10000000) - 1].states[ghosts.play_count - 1]) player.id = p_id player.worldTime = zo.world_time() if player != None: if len(message.states) > 9: message.world_time = zo.world_time() message.cts_latency = message.world_time - recv.world_time socket.sendto(message.SerializeToString(), client_address) message.msgnum += 1 del message.states[:] s = message.states.add() s.CopyFrom(player) else: message.num_msgs = 1 message.world_time = zo.world_time() message.cts_latency = message.world_time - recv.world_time socket.sendto(message.SerializeToString(), client_address)