如何在specqueue.py中正确调用auto_rebalance.py的函数并传参?
问题描述
我需要在specqueue.py的team_placement方法调用player.put(team)时,将handle_team_switch_attempt(self, player, old_team, new_team)的参数传递给auto_rebalance.py中的同名方法。之前尝试在player.put(team)后执行self.plugins['auto_rebalance'].handle_team_switch_attempt(self, player, old, new),但该方法无效。
相关代码
auto_rebalance.py
def handle_team_switch_attempt(self, player, old, new): """ Handles the case where a player switches from spectators to "red", "blue", or "any" team, and the resulting teams would be suboptimal balanced. :param: player: the player that attempted the switch :param: old: the old team of the switching player :param: new: the new team that switching player would be put onto :return: minqlx.RET_NONE if the team switch should be allowed or minqlx.RET_STOP_EVENT if the switch should not be allowed, and we put the player on a better-suited team. """ if not self.game: return minqlx.RET_NONE if self.last_new_player_id == player.steam_id and new in ["spectator", "free"]: self.last_new_player_id = None if self.game.state != "in_progress": return minqlx.RET_NONE if old not in ["spectator", "free"] or new not in ['red', 'blue', 'any']: return minqlx.RET_NONE if "balance" not in self.plugins: Plugin.msg("^1balance^7 plugin not loaded, ^1auto rebalance^7 not possible.") return minqlx.RET_NONE gametype = self.game.type_short if gametype not in SUPPORTED_GAMETYPES: return minqlx.RET_NONE teams = self.teams() if len(teams["red"]) == len(teams["blue"]): self.last_new_player_id = player.steam_id return minqlx.RET_NONE if not self.last_new_player_id: return minqlx.RET_NONE last_new_player = Plugin.player(self.last_new_player_id) if not last_new_player: self.last_new_player_id = None return minqlx.RET_NONE other_than_last_players_team = self.other_team(last_new_player.team) new_player_team = teams[other_than_last_players_team].copy() + [player] proposed_diff = self.calculate_player_average_difference(gametype, teams[last_new_player.team].copy(), new_player_team) alternative_team_a = [player for player in teams[last_new_player.team] if player != last_new_player] + \ [player] alternative_team_b = teams[other_than_last_players_team].copy() + [last_new_player] alternative_diff = self.calculate_player_average_difference(gametype, alternative_team_a, alternative_team_b) self.last_new_player_id = None if proposed_diff > alternative_diff: last_new_player.tell(f"{last_new_player.clean_name}, you have been moved to " f"{self.format_team(other_than_last_players_team)} to maintain team balance.") last_new_player.put(other_than_last_players_team) if new in [last_new_player.team]: return minqlx.RET_NONE if new not in ["any"]: player.tell(f"{player.clean_name}, you have been moved to {self.format_team(last_new_player.team)} " f"to maintain team balance.") player.put(last_new_player.team) return minqlx.RET_STOP_ALL
specqueue.py
def handle_team_switch_attempt(self, player, old_team, new_team): if self.q_game_info[0] in SUPPORTED_GAMETYPES and new_team != "spectator" and old_team == "spectator": teams = self.teams() at_max_players = False join_locked = False self.remove_from_afk(player) if self.q_game_info[0] in TEAM_BASED_GAMETYPES: if len(teams["red"]) + len(teams["blue"]) >= self.get_max_players(): at_max_players = True join_locked = self.free_locked elif self.q_game_info[0] in NONTEAM_BASED_GAMETYPES: if len(self.teams()["free"]) >= self.get_max_players(): at_max_players = True join_locked = self.red_locked or self.blue_locked if self._queue or join_locked or self.game.state in ["in_progress", "countdown"] or\ at_max_players: self.add_to_queue(player) self.remove_from_spec(player) self.check_for_opening(0.2) self.update_queue_tags() return minqlx.RET_STP_ALL def team_placement(self, player, team, add_queue=False): if ENABLE_LOG: self.queue_log.info("specqueue team placement: {} put on team {}".format(player, team)) try: player.put(team) if add_queue: self.add_to_queue_pos(player, 0) except Exception as e: if ENABLE_LOG: self.queue_log.info("specqueue team placement Exception: {}".format([e]))
解决方案
你之前的调用错误在于传递了specqueue的self给auto_rebalance的方法,而且没有正确获取玩家的旧团队信息,修正步骤如下:
- 记录玩家旧团队
在调用player.put(team)前,先获取玩家当前所在的团队(即切换前的旧团队):
old_team = player.team
- 正确调用auto_rebalance的方法
auto_rebalance的handle_team_switch_attempt方法需要传入它自身的实例作为第一个参数,而非specqueue的self。先获取插件实例,再调用方法:
auto_rebalance = self.plugins.get('auto_rebalance') if auto_rebalance: auto_rebalance.handle_team_switch_attempt(auto_rebalance, player, old_team, team)
- 修改后的team_placement方法
完整修改后的代码如下:
def team_placement(self, player, team, add_queue=False): if ENABLE_LOG: self.queue_log.info("specqueue team placement: {} put on team {}".format(player, team)) try: old_team = player.team # 记录切换前的旧团队 player.put(team) # 调用auto_rebalance的团队切换处理方法 auto_rebalance = self.plugins.get('auto_rebalance') if auto_rebalance: auto_rebalance.handle_team_switch_attempt(auto_rebalance, player, old_team, team) if add_queue: self.add_to_queue_pos(player, 0) except Exception as e: if ENABLE_LOG: self.queue_log.info("specqueue team placement Exception: {}".format([e]))
- 注意事项
- 确保
auto_rebalance插件已正确加载,避免因实例不存在导致调用失败; - 检查传递的
old_team和team是否为合法值(如spectator、red、blue等),符合auto_rebalance方法的参数校验要求。
内容的提问来源于stack exchange,提问作者David Houk
相关产品推荐
相关产品推荐

