mirror of
https://github.com/hypervortex/VH-Bombsquad-Modded-Server-Files
synced 2025-11-07 17:36:08 +00:00
Delete dist directory
This commit is contained in:
parent
b2bfb6afd8
commit
9e59089810
1776 changed files with 0 additions and 548278 deletions
329
dist/ba_data/python/ba/_player.py
vendored
329
dist/ba_data/python/ba/_player.py
vendored
|
|
@ -1,329 +0,0 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Player related functionality."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, TypeVar, Generic, cast
|
||||
|
||||
import _ba
|
||||
from ba._error import (
|
||||
SessionPlayerNotFoundError,
|
||||
print_exception,
|
||||
ActorNotFoundError,
|
||||
)
|
||||
from ba._messages import DeathType, DieMessage
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Any, Callable
|
||||
import ba
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
PlayerType = TypeVar('PlayerType', bound='ba.Player')
|
||||
TeamType = TypeVar('TeamType', bound='ba.Team')
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlayerInfo:
|
||||
"""Holds basic info about a player.
|
||||
|
||||
Category: Gameplay Classes
|
||||
"""
|
||||
|
||||
name: str
|
||||
character: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class StandLocation:
|
||||
"""Describes a point in space and an angle to face.
|
||||
|
||||
Category: Gameplay Classes
|
||||
"""
|
||||
|
||||
position: ba.Vec3
|
||||
angle: float | None = None
|
||||
|
||||
|
||||
class Player(Generic[TeamType]):
|
||||
"""A player in a specific ba.Activity.
|
||||
|
||||
Category: Gameplay Classes
|
||||
|
||||
These correspond to ba.SessionPlayer objects, but are associated with a
|
||||
single ba.Activity instance. This allows activities to specify their
|
||||
own custom ba.Player types.
|
||||
"""
|
||||
|
||||
# These are instance attrs but we define them at the type level so
|
||||
# their type annotations are introspectable (for docs generation).
|
||||
character: str
|
||||
|
||||
actor: ba.Actor | None
|
||||
"""The ba.Actor associated with the player."""
|
||||
|
||||
color: Sequence[float]
|
||||
highlight: Sequence[float]
|
||||
|
||||
_team: TeamType
|
||||
_sessionplayer: ba.SessionPlayer
|
||||
_nodeactor: ba.NodeActor | None
|
||||
_expired: bool
|
||||
_postinited: bool
|
||||
_customdata: dict
|
||||
|
||||
# NOTE: avoiding having any __init__() here since it seems to not
|
||||
# get called by default if a dataclass inherits from us.
|
||||
# This also lets us keep trivial player classes cleaner by skipping
|
||||
# the super().__init__() line.
|
||||
|
||||
def postinit(self, sessionplayer: ba.SessionPlayer) -> None:
|
||||
"""Wire up a newly created player.
|
||||
|
||||
(internal)
|
||||
"""
|
||||
from ba._nodeactor import NodeActor
|
||||
|
||||
# Sanity check; if a dataclass is created that inherits from us,
|
||||
# it will define an equality operator by default which will break
|
||||
# internal game logic. So complain loudly if we find one.
|
||||
if type(self).__eq__ is not object.__eq__:
|
||||
raise RuntimeError(
|
||||
f'Player class {type(self)} defines an equality'
|
||||
f' operator (__eq__) which will break internal'
|
||||
f' logic. Please remove it.\n'
|
||||
f'For dataclasses you can do "dataclass(eq=False)"'
|
||||
f' in the class decorator.'
|
||||
)
|
||||
|
||||
self.actor = None
|
||||
self.character = ''
|
||||
self._nodeactor: ba.NodeActor | None = None
|
||||
self._sessionplayer = sessionplayer
|
||||
self.character = sessionplayer.character
|
||||
self.color = sessionplayer.color
|
||||
self.highlight = sessionplayer.highlight
|
||||
self._team = cast(TeamType, sessionplayer.sessionteam.activityteam)
|
||||
assert self._team is not None
|
||||
self._customdata = {}
|
||||
self._expired = False
|
||||
self._postinited = True
|
||||
node = _ba.newnode('player', attrs={'playerID': sessionplayer.id})
|
||||
self._nodeactor = NodeActor(node)
|
||||
sessionplayer.setnode(node)
|
||||
|
||||
def leave(self) -> None:
|
||||
"""Called when the Player leaves a running game.
|
||||
|
||||
(internal)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
try:
|
||||
# If they still have an actor, kill it.
|
||||
if self.actor:
|
||||
self.actor.handlemessage(DieMessage(how=DeathType.LEFT_GAME))
|
||||
self.actor = None
|
||||
except Exception:
|
||||
print_exception(f'Error killing actor on leave for {self}')
|
||||
self._nodeactor = None
|
||||
del self._team
|
||||
del self._customdata
|
||||
|
||||
def expire(self) -> None:
|
||||
"""Called when the Player is expiring (when its Activity does so).
|
||||
|
||||
(internal)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
self._expired = True
|
||||
|
||||
try:
|
||||
self.on_expire()
|
||||
except Exception:
|
||||
print_exception(f'Error in on_expire for {self}.')
|
||||
|
||||
self._nodeactor = None
|
||||
self.actor = None
|
||||
del self._team
|
||||
del self._customdata
|
||||
|
||||
def on_expire(self) -> None:
|
||||
"""Can be overridden to handle player expiration.
|
||||
|
||||
The player expires when the Activity it is a part of expires.
|
||||
Expired players should no longer run any game logic (which will
|
||||
likely error). They should, however, remove any references to
|
||||
players/teams/games/etc. which could prevent them from being freed.
|
||||
"""
|
||||
|
||||
@property
|
||||
def team(self) -> TeamType:
|
||||
"""The ba.Team for this player."""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._team
|
||||
|
||||
@property
|
||||
def customdata(self) -> dict:
|
||||
"""Arbitrary values associated with the player.
|
||||
Though it is encouraged that most player values be properly defined
|
||||
on the ba.Player subclass, it may be useful for player-agnostic
|
||||
objects to store values here. This dict is cleared when the player
|
||||
leaves or expires so objects stored here will be disposed of at
|
||||
the expected time, unlike the Player instance itself which may
|
||||
continue to be referenced after it is no longer part of the game.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._customdata
|
||||
|
||||
@property
|
||||
def sessionplayer(self) -> ba.SessionPlayer:
|
||||
"""Return the ba.SessionPlayer corresponding to this Player.
|
||||
|
||||
Throws a ba.SessionPlayerNotFoundError if it does not exist.
|
||||
"""
|
||||
assert self._postinited
|
||||
if bool(self._sessionplayer):
|
||||
return self._sessionplayer
|
||||
raise SessionPlayerNotFoundError()
|
||||
|
||||
@property
|
||||
def node(self) -> ba.Node:
|
||||
"""A ba.Node of type 'player' associated with this Player.
|
||||
|
||||
This node can be used to get a generic player position/etc.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
assert self._nodeactor
|
||||
return self._nodeactor.node
|
||||
|
||||
@property
|
||||
def position(self) -> ba.Vec3:
|
||||
"""The position of the player, as defined by its current ba.Actor.
|
||||
|
||||
If the player currently has no actor, raises a ba.ActorNotFoundError.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
if self.actor is None:
|
||||
raise ActorNotFoundError
|
||||
return _ba.Vec3(self.node.position)
|
||||
|
||||
def exists(self) -> bool:
|
||||
"""Whether the underlying player still exists.
|
||||
|
||||
This will return False if the underlying ba.SessionPlayer has
|
||||
left the game or if the ba.Activity this player was associated
|
||||
with has ended.
|
||||
Most functionality will fail on a nonexistent player.
|
||||
Note that you can also use the boolean operator for this same
|
||||
functionality, so a statement such as "if player" will do
|
||||
the right thing both for Player objects and values of None.
|
||||
"""
|
||||
assert self._postinited
|
||||
return self._sessionplayer.exists() and not self._expired
|
||||
|
||||
def getname(self, full: bool = False, icon: bool = True) -> str:
|
||||
"""
|
||||
Returns the player's name. If icon is True, the long version of the
|
||||
name may include an icon.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._sessionplayer.getname(full=full, icon=icon)
|
||||
|
||||
def is_alive(self) -> bool:
|
||||
"""
|
||||
Returns True if the player has a ba.Actor assigned and its
|
||||
is_alive() method return True. False is returned otherwise.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self.actor is not None and self.actor.is_alive()
|
||||
|
||||
def get_icon(self) -> dict[str, Any]:
|
||||
"""
|
||||
Returns the character's icon (images, colors, etc contained in a dict)
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._sessionplayer.get_icon()
|
||||
|
||||
def assigninput(
|
||||
self, inputtype: ba.InputType | tuple[ba.InputType, ...], call: Callable
|
||||
) -> None:
|
||||
"""
|
||||
Set the python callable to be run for one or more types of input.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
return self._sessionplayer.assigninput(type=inputtype, call=call)
|
||||
|
||||
def resetinput(self) -> None:
|
||||
"""
|
||||
Clears out the player's assigned input actions.
|
||||
"""
|
||||
assert self._postinited
|
||||
assert not self._expired
|
||||
self._sessionplayer.resetinput()
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.exists()
|
||||
|
||||
|
||||
class EmptyPlayer(Player['ba.EmptyTeam']):
|
||||
"""An empty player for use by Activities that don't need to define one.
|
||||
|
||||
Category: Gameplay Classes
|
||||
|
||||
ba.Player and ba.Team are 'Generic' types, and so passing those top level
|
||||
classes as type arguments when defining a ba.Activity reduces type safety.
|
||||
For example, activity.teams[0].player will have type 'Any' in that case.
|
||||
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
||||
defining a ba.Activity that does not need custom types of its own.
|
||||
|
||||
Note that EmptyPlayer defines its team type as EmptyTeam and vice versa,
|
||||
so if you want to define your own class for one of them you should do so
|
||||
for both.
|
||||
"""
|
||||
|
||||
|
||||
# NOTE: It seems we might not need these playercast() calls; have gone
|
||||
# the direction where things returning players generally take a type arg
|
||||
# and do this themselves; that way the user is 'forced' to deal with types
|
||||
# instead of requiring extra work by them.
|
||||
|
||||
|
||||
def playercast(totype: type[PlayerType], player: ba.Player) -> PlayerType:
|
||||
"""Cast a ba.Player to a specific ba.Player subclass.
|
||||
|
||||
Category: Gameplay Functions
|
||||
|
||||
When writing type-checked code, sometimes code will deal with raw
|
||||
ba.Player objects which need to be cast back to the game's actual
|
||||
player type so that access can be properly type-checked. This function
|
||||
is a safe way to do so. It ensures that Optional values are not cast
|
||||
into Non-Optional, etc.
|
||||
"""
|
||||
assert isinstance(player, totype)
|
||||
return player
|
||||
|
||||
|
||||
# NOTE: ideally we should have a single playercast() call and use overloads
|
||||
# for the optional variety, but that currently seems to not be working.
|
||||
# See: https://github.com/python/mypy/issues/8800
|
||||
def playercast_o(
|
||||
totype: type[PlayerType], player: ba.Player | None
|
||||
) -> PlayerType | None:
|
||||
"""A variant of ba.playercast() for use with optional ba.Player values.
|
||||
|
||||
Category: Gameplay Functions
|
||||
"""
|
||||
assert isinstance(player, (totype, type(None)))
|
||||
return player
|
||||
Loading…
Add table
Add a link
Reference in a new issue