Module server.players

Player type definitions

Classes

class Player (login: str,
session: int = 0,
player_id: int = 0,
leaderboards: dict[str, Leaderboard] = {},
ratings: PlayerRatings | None = None,
clan: str | None = None,
game_count: dict[str, int] | None = None,
lobby_connection: ForwardRef('LobbyConnection') | None = None)
Expand source code
class Player:
    """
    Standard player object used for representing signed-in players.

    In the context of a game, the Game object holds game-specific
    information about players.
    """

    lobby_connection: WeakAttribute["LobbyConnection"] = WeakAttribute()
    game: WeakAttribute["Game"] = WeakAttribute()
    game_connection: WeakAttribute["GameConnection"] = WeakAttribute()

    def __init__(
        self,
        login: str,
        session: int = 0,
        player_id: int = 0,
        leaderboards: dict[str, Leaderboard] = {},
        ratings: Optional[PlayerRatings] = None,
        clan: Optional[str] = None,
        game_count: Optional[dict[str, int]] = None,
        lobby_connection: Optional["LobbyConnection"] = None
    ) -> None:
        self._faction = Faction.uef

        # The player_id of the user in the `login` table of the database.
        self.id = player_id
        self.login = login

        self.session = session

        self.ratings = PlayerRatings(leaderboards)
        if ratings is not None:
            self.ratings.update_with_transient(ratings)

        self.game_count: dict[str, int] = defaultdict(int)
        if game_count is not None:
            self.game_count.update(game_count)

        # social
        self.avatar: Optional[dict[str, str]] = None
        self.clan = clan
        self.country: Optional[str] = None

        self.friends: set[int] = set()
        self.foes: set[int] = set()

        self.user_groups: set[str] = set()

        self.state = PlayerState.IDLE

        if lobby_connection is not None:
            self.lobby_connection = lobby_connection

    @property
    def faction(self) -> Faction:
        return self._faction

    @faction.setter
    def faction(self, value: Union[str, int, Faction]) -> None:
        if isinstance(value, Faction):
            self._faction = value
        else:
            self._faction = Faction.from_value(value)

    def power(self) -> int:
        """An artifact of the old permission system. The client still uses this
        number to determine if a player gets a special category in the user list
        such as "Moderator"
        """
        if self.is_admin():
            return 2
        if self.is_moderator():
            return 1

        return 0

    def is_admin(self) -> bool:
        return "faf_server_administrators" in self.user_groups

    def is_moderator(self) -> bool:
        return "faf_moderators_global" in self.user_groups

    async def send_message(self, message: dict) -> None:
        """
        Try to send a message to this player.

        # Errors
        Raises `DisconnectedError` if the player has disconnected.
        """
        if self.lobby_connection is None:
            raise DisconnectedError("Player has disconnected!")

        await self.lobby_connection.send(message)

    def write_message(self, message: dict) -> None:
        """
        Try to queue a message to be sent to this player.

        Does nothing if the player has disconnected.
        """
        if self.lobby_connection is None:
            return

        with suppress(DisconnectedError):
            self.lobby_connection.write(message)

    def to_dict(self) -> dict:
        """
        Return a dictionary representing this player object
        """
        assert self.state is not None and self.state.value is not None

        cmd = {
            "id": self.id,
            "login": self.login,
            "avatar": self.avatar,
            "country": self.country,
            "clan": self.clan,
            # NOTE: We are only sending an 'offline' state for now to signal to
            # the client when a player disconnects. However, this could be
            # expanded in the future to expose more of the internal state
            # tracking to the client to make the UI for showing players in game
            # more correct.
            "state": None if self.lobby_connection else "offline",
            "ratings": {
                rating_type: {
                    "rating": self.ratings[rating_type],
                    "number_of_games": self.game_count[rating_type]
                }
                for rating_type in self.ratings
            },
            # DEPRECATED: Use ratings instead
            "global_rating": self.ratings[RatingType.GLOBAL],
            "ladder_rating": self.ratings[RatingType.LADDER_1V1],
            "number_of_games": self.game_count[RatingType.GLOBAL],
        }
        return {k: v for k, v in cmd.items() if v is not None}

    def __str__(self) -> str:
        return (f"Player({self.login}, {self.id}, "
                f"{self.ratings[RatingType.GLOBAL]}, "
                f"{self.ratings[RatingType.LADDER_1V1]})")

    def __repr__(self) -> str:
        return (f"Player(login={self.login}, session={self.session}, "
                f"id={self.id}, ratings={dict(self.ratings)}, "
                f"clan={self.clan}, game_count={dict(self.game_count)})")

Standard player object used for representing signed-in players.

In the context of a game, the Game object holds game-specific information about players.

Instance variables

prop factionFaction
Expand source code
@property
def faction(self) -> Faction:
    return self._faction
var game : ~T | None
Expand source code
def __get__(self, obj: object, objclass: type) -> Optional[T]:
    ref = obj.__dict__.get(self.name)
    if ref:
        return ref()
    return None

Transparently allow an object attribute to reference another object via a weak reference.

var game_connection : ~T | None
Expand source code
def __get__(self, obj: object, objclass: type) -> Optional[T]:
    ref = obj.__dict__.get(self.name)
    if ref:
        return ref()
    return None

Transparently allow an object attribute to reference another object via a weak reference.

var lobby_connection : ~T | None
Expand source code
def __get__(self, obj: object, objclass: type) -> Optional[T]:
    ref = obj.__dict__.get(self.name)
    if ref:
        return ref()
    return None

Transparently allow an object attribute to reference another object via a weak reference.

Methods

def is_admin(self) ‑> bool
Expand source code
def is_admin(self) -> bool:
    return "faf_server_administrators" in self.user_groups
def is_moderator(self) ‑> bool
Expand source code
def is_moderator(self) -> bool:
    return "faf_moderators_global" in self.user_groups
def power(self) ‑> int
Expand source code
def power(self) -> int:
    """An artifact of the old permission system. The client still uses this
    number to determine if a player gets a special category in the user list
    such as "Moderator"
    """
    if self.is_admin():
        return 2
    if self.is_moderator():
        return 1

    return 0

An artifact of the old permission system. The client still uses this number to determine if a player gets a special category in the user list such as "Moderator"

async def send_message(self, message: dict) ‑> None
Expand source code
async def send_message(self, message: dict) -> None:
    """
    Try to send a message to this player.

    # Errors
    Raises `DisconnectedError` if the player has disconnected.
    """
    if self.lobby_connection is None:
        raise DisconnectedError("Player has disconnected!")

    await self.lobby_connection.send(message)

Try to send a message to this player.

Errors

Raises DisconnectedError if the player has disconnected.

def to_dict(self) ‑> dict
Expand source code
def to_dict(self) -> dict:
    """
    Return a dictionary representing this player object
    """
    assert self.state is not None and self.state.value is not None

    cmd = {
        "id": self.id,
        "login": self.login,
        "avatar": self.avatar,
        "country": self.country,
        "clan": self.clan,
        # NOTE: We are only sending an 'offline' state for now to signal to
        # the client when a player disconnects. However, this could be
        # expanded in the future to expose more of the internal state
        # tracking to the client to make the UI for showing players in game
        # more correct.
        "state": None if self.lobby_connection else "offline",
        "ratings": {
            rating_type: {
                "rating": self.ratings[rating_type],
                "number_of_games": self.game_count[rating_type]
            }
            for rating_type in self.ratings
        },
        # DEPRECATED: Use ratings instead
        "global_rating": self.ratings[RatingType.GLOBAL],
        "ladder_rating": self.ratings[RatingType.LADDER_1V1],
        "number_of_games": self.game_count[RatingType.GLOBAL],
    }
    return {k: v for k, v in cmd.items() if v is not None}

Return a dictionary representing this player object

def write_message(self, message: dict) ‑> None
Expand source code
def write_message(self, message: dict) -> None:
    """
    Try to queue a message to be sent to this player.

    Does nothing if the player has disconnected.
    """
    if self.lobby_connection is None:
        return

    with suppress(DisconnectedError):
        self.lobby_connection.write(message)

Try to queue a message to be sent to this player.

Does nothing if the player has disconnected.

class PlayerState (*args, **kwds)
Expand source code
@unique
class PlayerState(Enum):
    IDLE = 1
    PLAYING = 2
    HOSTING = 3
    JOINING = 4
    SEARCHING_LADDER = 5
    STARTING_AUTOMATCH = 6
    STARTING_GAME = 7

Create a collection of name/value pairs.

Example enumeration:

>>> class Color(Enum):
...     RED = 1
...     BLUE = 2
...     GREEN = 3

Access them by:

  • attribute access:

Color.RED

  • value lookup:

Color(1)

  • name lookup:

Color['RED']

Enumerations can be iterated over, and know how many members they have:

>>> len(Color)
3
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

Methods can be added to enumerations, and members can have their own attributes – see the documentation for details.

Ancestors

  • enum.Enum

Class variables

var HOSTING

The type of the None singleton.

var IDLE

The type of the None singleton.

var JOINING

The type of the None singleton.

var PLAYING

The type of the None singleton.

var SEARCHING_LADDER

The type of the None singleton.

var STARTING_AUTOMATCH

The type of the None singleton.

var STARTING_GAME

The type of the None singleton.