mirror of
https://github.com/hypervortex/VH-Bombsquad-Modded-Server-Files
synced 2025-11-07 17:36:08 +00:00
updated files
This commit is contained in:
parent
5ba4986d59
commit
7a5e7698c0
1269 changed files with 551814 additions and 0 deletions
90
dist/ba_data/python/ba/_appcomponent.py
vendored
Normal file
90
dist/ba_data/python/ba/_appcomponent.py
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Provides the AppComponent class."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, TypeVar, cast
|
||||
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any
|
||||
|
||||
T = TypeVar('T', bound=type)
|
||||
|
||||
|
||||
class AppComponentSubsystem:
|
||||
"""Subsystem for wrangling AppComponents.
|
||||
|
||||
Category: **App Classes**
|
||||
|
||||
This subsystem acts as a registry for classes providing particular
|
||||
functionality for the app, and allows plugins or other custom code to
|
||||
easily override said functionality.
|
||||
|
||||
Use ba.app.components to get the single shared instance of this class.
|
||||
|
||||
The general idea with this setup is that a base-class is defined to
|
||||
provide some functionality and then anyone wanting that functionality
|
||||
uses the getclass() method with that base class to return the current
|
||||
registered implementation. The user should not know or care whether
|
||||
they are getting the base class itself or some other implementation.
|
||||
|
||||
Change-callbacks can also be requested for base classes which will
|
||||
fire in a deferred manner when particular base-classes are overridden.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._implementations: dict[type, type] = {}
|
||||
self._prev_implementations: dict[type, type] = {}
|
||||
self._dirty_base_classes: set[type] = set()
|
||||
self._change_callbacks: dict[type, list[Callable[[Any], None]]] = {}
|
||||
|
||||
def setclass(self, baseclass: type, implementation: type) -> None:
|
||||
"""Set the class providing an implementation of some base-class.
|
||||
|
||||
The provided implementation class must be a subclass of baseclass.
|
||||
"""
|
||||
# Currently limiting this to logic-thread use; can revisit if needed
|
||||
# (would need to guard access to our implementations dict).
|
||||
assert _ba.in_logic_thread()
|
||||
|
||||
if not issubclass(implementation, baseclass):
|
||||
raise TypeError(
|
||||
f'Implementation {implementation}'
|
||||
f' is not a subclass of baseclass {baseclass}.'
|
||||
)
|
||||
|
||||
self._implementations[baseclass] = implementation
|
||||
|
||||
# If we're the first thing getting dirtied, set up a callback to
|
||||
# clean everything. And add ourself to the dirty list regardless.
|
||||
if not self._dirty_base_classes:
|
||||
_ba.pushcall(self._run_change_callbacks)
|
||||
self._dirty_base_classes.add(baseclass)
|
||||
|
||||
def getclass(self, baseclass: T) -> T:
|
||||
"""Given a base-class, return the currently set implementation class.
|
||||
|
||||
If no custom implementation has been set, the provided base-class
|
||||
is returned.
|
||||
"""
|
||||
assert _ba.in_logic_thread()
|
||||
|
||||
del baseclass # Unused.
|
||||
return cast(T, None)
|
||||
|
||||
def register_change_callback(
|
||||
self, baseclass: T, callback: Callable[[T], None]
|
||||
) -> None:
|
||||
"""Register a callback to fire when a class implementation changes.
|
||||
|
||||
The callback will be scheduled to run in the logic thread event
|
||||
loop. Note that any further setclass calls before the callback
|
||||
runs will not result in additional callbacks.
|
||||
"""
|
||||
assert _ba.in_logic_thread()
|
||||
self._change_callbacks.setdefault(baseclass, []).append(callback)
|
||||
|
||||
def _run_change_callbacks(self) -> None:
|
||||
pass
|
||||
Loading…
Add table
Add a link
Reference in a new issue