mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-31 03:39:04 +08:00
initial work on cloudtool functionality
This commit is contained in:
parent
6674c526ce
commit
05a4793cd1
5
.idea/ballisticacore.iml
generated
5
.idea/ballisticacore.iml
generated
@ -5,6 +5,7 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/assets/src/data/scripts" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tools" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/generated_src/ballistica" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.efrocache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/assets/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/assets/src/data/audio" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/assets/src/data/data" />
|
||||
@ -26,13 +27,13 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/ballisticacore-xcode" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/config" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/docs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/resources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/ballistica" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/external" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/generated" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/tools" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/submodules" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.efrocache" />
|
||||
<excludePattern pattern=".assetcache" />
|
||||
<excludePattern pattern=".cache*" />
|
||||
<excludePattern pattern=".clang-format" />
|
||||
@ -66,4 +67,4 @@
|
||||
<component name="TestRunnerService">
|
||||
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
||||
12
.idea/dictionaries/ericf.xml
generated
12
.idea/dictionaries/ericf.xml
generated
@ -14,6 +14,7 @@
|
||||
<w>abeb</w>
|
||||
<w>abot</w>
|
||||
<w>abtn</w>
|
||||
<w>accountname</w>
|
||||
<w>accountui</w>
|
||||
<w>accum</w>
|
||||
<w>accumkillcount</w>
|
||||
@ -94,6 +95,7 @@
|
||||
<w>audioop</w>
|
||||
<w>autodesk</w>
|
||||
<w>autogenerate</w>
|
||||
<w>autonoassets</w>
|
||||
<w>autoremove</w>
|
||||
<w>autoretain</w>
|
||||
<w>autoselect</w>
|
||||
@ -245,6 +247,8 @@
|
||||
<w>clionbin</w>
|
||||
<w>clioncode</w>
|
||||
<w>clionroot</w>
|
||||
<w>cloudtool</w>
|
||||
<w>cloudtoolcmd</w>
|
||||
<w>clrblu</w>
|
||||
<w>clrend</w>
|
||||
<w>clrgrn</w>
|
||||
@ -326,6 +330,7 @@
|
||||
<w>datamodule</w>
|
||||
<w>dataname</w>
|
||||
<w>datetimemodule</w>
|
||||
<w>datetimes</w>
|
||||
<w>daynum</w>
|
||||
<w>dayoffset</w>
|
||||
<w>dbapi</w>
|
||||
@ -339,6 +344,7 @@
|
||||
<w>depcls</w>
|
||||
<w>depdata</w>
|
||||
<w>depdatas</w>
|
||||
<w>depentry</w>
|
||||
<w>deps</w>
|
||||
<w>depset</w>
|
||||
<w>depsets</w>
|
||||
@ -871,6 +877,7 @@
|
||||
<w>locationval</w>
|
||||
<w>locs</w>
|
||||
<w>logcat</w>
|
||||
<w>logintoken</w>
|
||||
<w>logitech</w>
|
||||
<w>logput</w>
|
||||
<w>loofa</w>
|
||||
@ -1087,6 +1094,7 @@
|
||||
<w>ouya</w>
|
||||
<w>packagedir</w>
|
||||
<w>packagedirs</w>
|
||||
<w>packagename</w>
|
||||
<w>painttxtattr</w>
|
||||
<w>palmos</w>
|
||||
<w>pandoc</w>
|
||||
@ -1365,6 +1373,7 @@
|
||||
<w>servercallthread</w>
|
||||
<w>servercallthreadtype</w>
|
||||
<w>servercfg</w>
|
||||
<w>servercmd</w>
|
||||
<w>serverdialog</w>
|
||||
<w>serverget</w>
|
||||
<w>serverput</w>
|
||||
@ -1552,6 +1561,7 @@
|
||||
<w>testm</w>
|
||||
<w>testmagicmethods</w>
|
||||
<w>testmock</w>
|
||||
<w>testobj</w>
|
||||
<w>testpatch</w>
|
||||
<w>testpt</w>
|
||||
<w>testsealable</w>
|
||||
@ -1678,6 +1688,7 @@
|
||||
<w>useragentstring</w>
|
||||
<w>userbase</w>
|
||||
<w>userfunctions</w>
|
||||
<w>utcnow</w>
|
||||
<w>utimensat</w>
|
||||
<w>validpgpkeys</w>
|
||||
<w>valnew</w>
|
||||
@ -1737,6 +1748,7 @@
|
||||
<w>wmsbe</w>
|
||||
<w>woooo</w>
|
||||
<w>workdir</w>
|
||||
<w>workflows</w>
|
||||
<w>wpath</w>
|
||||
<w>writeclasses</w>
|
||||
<w>writefuncs</w>
|
||||
|
||||
15
Makefile
15
Makefile
@ -54,32 +54,31 @@ prereqs-clean:
|
||||
assets: prereqs
|
||||
@cd assets && make -j${CPUS}
|
||||
|
||||
# Build only assets required for cmake builds (linux, mac)
|
||||
# Build assets required for cmake builds (linux, mac)
|
||||
assets-cmake: prereqs
|
||||
@cd assets && $(MAKE) -j${CPUS} cmake
|
||||
|
||||
# Build only assets required for windows builds.
|
||||
# (honoring the WINDOWS_PLATFORM value)
|
||||
# Build assets required for WINDOWS_PLATFORM windows builds.
|
||||
assets-windows: prereqs
|
||||
@cd assets && $(MAKE) -j${CPUS} win-${WINDOWS_PLATFORM}
|
||||
|
||||
# Build only assets required for Win32 windows builds.
|
||||
# Build assets required for Win32 windows builds.
|
||||
assets-windows-Win32: prereqs
|
||||
@cd assets && $(MAKE) -j${CPUS} win-Win32
|
||||
|
||||
# Build only assets required for x64 windows builds.
|
||||
# Build assets required for x64 windows builds.
|
||||
assets-windows-x64: prereqs
|
||||
@cd assets && $(MAKE) -j${CPUS} win-x64
|
||||
|
||||
# Build only assets required for mac xcode builds
|
||||
# Build assets required for mac xcode builds
|
||||
assets-mac: prereqs
|
||||
@cd assets && $(MAKE) -j${CPUS} mac
|
||||
|
||||
# Build only assets required for ios.
|
||||
# Build assets required for ios.
|
||||
assets-ios: prereqs
|
||||
@cd assets && $(MAKE) -j${CPUS} ios
|
||||
|
||||
# Build only assets required for android.
|
||||
# Build assets required for android.
|
||||
assets-android: prereqs
|
||||
@cd assets && $(MAKE) -j${CPUS} android
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"data/scripts/ba/__pycache__/_campaign.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_coopgame.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_coopsession.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_dep.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_dependency.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_enums.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_error.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_freeforallsession.cpython-37.opt-1.pyc",
|
||||
@ -27,7 +27,7 @@
|
||||
"data/scripts/ba/__pycache__/_lang.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_level.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_lobby.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_maps.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_map.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_math.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_messages.cpython-37.opt-1.pyc",
|
||||
"data/scripts/ba/__pycache__/_meta.cpython-37.opt-1.pyc",
|
||||
@ -62,7 +62,7 @@
|
||||
"data/scripts/ba/_campaign.py",
|
||||
"data/scripts/ba/_coopgame.py",
|
||||
"data/scripts/ba/_coopsession.py",
|
||||
"data/scripts/ba/_dep.py",
|
||||
"data/scripts/ba/_dependency.py",
|
||||
"data/scripts/ba/_enums.py",
|
||||
"data/scripts/ba/_error.py",
|
||||
"data/scripts/ba/_freeforallsession.py",
|
||||
@ -75,7 +75,7 @@
|
||||
"data/scripts/ba/_lang.py",
|
||||
"data/scripts/ba/_level.py",
|
||||
"data/scripts/ba/_lobby.py",
|
||||
"data/scripts/ba/_maps.py",
|
||||
"data/scripts/ba/_map.py",
|
||||
"data/scripts/ba/_math.py",
|
||||
"data/scripts/ba/_messages.py",
|
||||
"data/scripts/ba/_meta.py",
|
||||
|
||||
@ -170,6 +170,7 @@ SCRIPT_TARGETS_PY_1 = \
|
||||
build/data/scripts/ba/_profile.py \
|
||||
build/data/scripts/ba/_error.py \
|
||||
build/data/scripts/ba/_achievement.py \
|
||||
build/data/scripts/ba/_map.py \
|
||||
build/data/scripts/ba/_teambasesession.py \
|
||||
build/data/scripts/ba/_gameutils.py \
|
||||
build/data/scripts/ba/_activity.py \
|
||||
@ -197,14 +198,13 @@ SCRIPT_TARGETS_PY_1 = \
|
||||
build/data/scripts/ba/_lobby.py \
|
||||
build/data/scripts/ba/_stats.py \
|
||||
build/data/scripts/ba/_input.py \
|
||||
build/data/scripts/ba/_dep.py \
|
||||
build/data/scripts/ba/_level.py \
|
||||
build/data/scripts/ba/_dependency.py \
|
||||
build/data/scripts/ba/_general.py \
|
||||
build/data/scripts/ba/_server.py \
|
||||
build/data/scripts/ba/_account.py \
|
||||
build/data/scripts/ba/_music.py \
|
||||
build/data/scripts/ba/_lang.py \
|
||||
build/data/scripts/ba/_maps.py \
|
||||
build/data/scripts/ba/_teamgame.py \
|
||||
build/data/scripts/ba/ui/__init__.py \
|
||||
build/data/scripts/bastd/mainmenu.py \
|
||||
@ -405,6 +405,7 @@ SCRIPT_TARGETS_PYC_1 = \
|
||||
build/data/scripts/ba/__pycache__/_profile.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_error.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_achievement.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_map.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_teambasesession.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_gameutils.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_activity.cpython-37.opt-1.pyc \
|
||||
@ -432,14 +433,13 @@ SCRIPT_TARGETS_PYC_1 = \
|
||||
build/data/scripts/ba/__pycache__/_lobby.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_stats.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_input.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_dep.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_level.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_dependency.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_general.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_server.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_account.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_music.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_lang.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_maps.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/__pycache__/_teamgame.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/ba/ui/__pycache__/__init__.cpython-37.opt-1.pyc \
|
||||
build/data/scripts/bastd/__pycache__/mainmenu.cpython-37.opt-1.pyc \
|
||||
@ -764,6 +764,11 @@ build/data/scripts/ba/__pycache__/_achievement.cpython-37.opt-1.pyc: \
|
||||
@echo Compiling script: $^
|
||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||
|
||||
build/data/scripts/ba/__pycache__/_map.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_map.py
|
||||
@echo Compiling script: $^
|
||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||
|
||||
build/data/scripts/ba/__pycache__/_teambasesession.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_teambasesession.py
|
||||
@echo Compiling script: $^
|
||||
@ -899,13 +904,13 @@ build/data/scripts/ba/__pycache__/_input.cpython-37.opt-1.pyc: \
|
||||
@echo Compiling script: $^
|
||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||
|
||||
build/data/scripts/ba/__pycache__/_dep.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_dep.py
|
||||
build/data/scripts/ba/__pycache__/_level.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_level.py
|
||||
@echo Compiling script: $^
|
||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||
|
||||
build/data/scripts/ba/__pycache__/_level.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_level.py
|
||||
build/data/scripts/ba/__pycache__/_dependency.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_dependency.py
|
||||
@echo Compiling script: $^
|
||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||
|
||||
@ -934,11 +939,6 @@ build/data/scripts/ba/__pycache__/_lang.cpython-37.opt-1.pyc: \
|
||||
@echo Compiling script: $^
|
||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||
|
||||
build/data/scripts/ba/__pycache__/_maps.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_maps.py
|
||||
@echo Compiling script: $^
|
||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||
|
||||
build/data/scripts/ba/__pycache__/_teamgame.cpython-37.opt-1.pyc: \
|
||||
build/data/scripts/ba/_teamgame.py
|
||||
@echo Compiling script: $^
|
||||
|
||||
@ -43,7 +43,8 @@ from ba._actor import Actor
|
||||
from ba._app import App
|
||||
from ba._coopgame import CoopGameActivity
|
||||
from ba._coopsession import CoopSession
|
||||
from ba._dep import Dep, Dependency, DepComponent, DepSet, AssetPackage
|
||||
from ba._dependency import (Dependency, DependencyComponent, DependencySet,
|
||||
AssetPackage)
|
||||
from ba._enums import TimeType, Permission, TimeFormat, SpecialChar
|
||||
from ba._error import (UNHANDLED, print_exception, print_error, NotFoundError,
|
||||
PlayerNotFoundError, NodeNotFoundError,
|
||||
@ -55,7 +56,7 @@ from ba._freeforallsession import FreeForAllSession
|
||||
from ba._gameactivity import GameActivity
|
||||
from ba._gameresults import TeamGameResults
|
||||
from ba._lang import Lstr, setlanguage, get_valid_languages
|
||||
from ba._maps import Map, getmaps
|
||||
from ba._map import Map, getmaps
|
||||
from ba._session import Session
|
||||
from ba._stats import PlayerScoredMessage, PlayerRecord, Stats
|
||||
from ba._team import Team
|
||||
|
||||
@ -25,7 +25,7 @@ import weakref
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _ba
|
||||
from ba._dep import InstancedDepComponent
|
||||
from ba._dependency import DependencyComponent
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from weakref import ReferenceType
|
||||
@ -34,7 +34,7 @@ if TYPE_CHECKING:
|
||||
from bastd.actor.respawnicon import RespawnIcon
|
||||
|
||||
|
||||
class Activity(InstancedDepComponent):
|
||||
class Activity(DependencyComponent):
|
||||
"""Units of execution wrangled by a ba.Session.
|
||||
|
||||
Category: Gameplay Classes
|
||||
|
||||
@ -422,7 +422,7 @@ class App:
|
||||
from ba import _appconfig
|
||||
from ba import ui as bsui
|
||||
from ba import _achievement
|
||||
from ba import _maps
|
||||
from ba import _map
|
||||
from ba import _meta
|
||||
from ba import _music
|
||||
from ba import _campaign
|
||||
@ -451,7 +451,7 @@ class App:
|
||||
stdmaps.CragCastle, stdmaps.TowerD, stdmaps.HappyThoughts,
|
||||
stdmaps.StepRightUp, stdmaps.Courtyard, stdmaps.Rampage
|
||||
]:
|
||||
_maps.register_map(maptype)
|
||||
_map.register_map(maptype)
|
||||
|
||||
if self.debug_build:
|
||||
_apputils.suppress_debug_reports()
|
||||
@ -590,7 +590,7 @@ class App:
|
||||
|
||||
self.ran_on_launch = True
|
||||
|
||||
from ba._dep import test_depset
|
||||
from ba._dependency import test_depset
|
||||
test_depset()
|
||||
# print('GAME TYPES ARE', meta.get_game_types())
|
||||
# _bs.quit()
|
||||
|
||||
@ -43,7 +43,7 @@ def run_cpu_benchmark() -> None:
|
||||
def __init__(self) -> None:
|
||||
|
||||
print('FIXME: BENCHMARK SESSION WOULD CALC DEPS.')
|
||||
depsets: Sequence[ba.DepSet] = []
|
||||
depsets: Sequence[ba.DependencySet] = []
|
||||
|
||||
super().__init__(depsets)
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ class CoopSession(Session):
|
||||
max_players = 4
|
||||
|
||||
print('FIXME: COOP SESSION WOULD CALC DEPS.')
|
||||
depsets: Sequence[ba.DepSet] = []
|
||||
depsets: Sequence[ba.DependencySet] = []
|
||||
|
||||
super().__init__(depsets,
|
||||
team_names=TEAM_NAMES,
|
||||
|
||||
@ -1,523 +0,0 @@
|
||||
# Copyright (c) 2011-2019 Eric Froemling
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# -----------------------------------------------------------------------------
|
||||
"""Functionality related to object/asset dependencies."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import weakref
|
||||
from typing import (Generic, TypeVar, TYPE_CHECKING, cast, Type, overload)
|
||||
|
||||
import _ba
|
||||
from ba import _general
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any, Dict, List, Set
|
||||
import ba
|
||||
|
||||
T = TypeVar('T', bound='DepComponent')
|
||||
TI = TypeVar('TI', bound='InstancedDepComponent')
|
||||
TS = TypeVar('TS', bound='StaticDepComponent')
|
||||
|
||||
|
||||
class Dependency(Generic[T]):
|
||||
"""A dependency on a DepComponent (with an optional config).
|
||||
|
||||
Category: Dependency Classes
|
||||
|
||||
This class is used to request and access functionality provided
|
||||
by other DepComponent classes from a DepComponent class.
|
||||
The class functions as a descriptor, allowing dependencies to
|
||||
be added at a class level much the same as properties or methods
|
||||
and then used with class instances to access those dependencies.
|
||||
For instance, if you do 'floofcls = ba.Dependency(FloofClass)' you
|
||||
would then be able to instantiate a FloofClass in your class's
|
||||
methods via self.floofcls().
|
||||
"""
|
||||
|
||||
def __init__(self, cls: Type[T], config: Any = None):
|
||||
"""Instantiate a Dependency given a ba.DepComponent subtype.
|
||||
|
||||
Optionally, an arbitrary object can be passed as 'config' to
|
||||
influence dependency calculation for the target class.
|
||||
"""
|
||||
self.cls: Type[T] = cls
|
||||
self.config = config
|
||||
self._hash: Optional[int] = None
|
||||
|
||||
def get_hash(self) -> int:
|
||||
"""Return the dependency's hash, calculating it if necessary."""
|
||||
if self._hash is None:
|
||||
self._hash = _general.make_hash((self.cls, self.config))
|
||||
return self._hash
|
||||
|
||||
# NOTE: it appears that mypy is currently not able to do overloads based
|
||||
# on the type of 'self', otherwise we could just overload this to
|
||||
# return different things based on self's type and avoid the need for
|
||||
# the fake dep classes below.
|
||||
# See https://github.com/python/mypy/issues/5320
|
||||
def __get__(self, obj: Any, cls: Any = None) -> Any:
|
||||
if obj is None:
|
||||
raise TypeError("Dependency must be accessed through an instance.")
|
||||
|
||||
# We expect to be instantiated from an already living DepComponent
|
||||
# with valid dep-data in place..
|
||||
assert type is not None
|
||||
depdata = getattr(obj, '_depdata')
|
||||
if depdata is None:
|
||||
raise RuntimeError("Invalid dependency access.")
|
||||
assert isinstance(depdata, DepData)
|
||||
|
||||
# Now look up the data for this particular dep
|
||||
depset = depdata.depset()
|
||||
assert isinstance(depset, DepSet)
|
||||
assert self._hash in depset.depdatas
|
||||
depdata = depset.depdatas[self._hash]
|
||||
assert isinstance(depdata, DepData)
|
||||
if depdata.valid is False:
|
||||
raise RuntimeError(
|
||||
f'Accessing DepComponent {depdata.cls} in an invalid state.')
|
||||
assert self.cls.dep_get_payload(depdata) is not None
|
||||
return self.cls.dep_get_payload(depdata)
|
||||
|
||||
|
||||
# We define a 'Dep' which at runtime simply aliases the Dependency class
|
||||
# but in type-checking points to two overloaded functions based on the argument
|
||||
# type. This lets the type system know what type of object the Dep represents.
|
||||
# (object instances in the case of StaticDep classes or object types in the
|
||||
# case of regular deps) At some point hopefully we can replace this with a
|
||||
# simple overload in Dependency.__get__ based on the type of self
|
||||
# (see note above).
|
||||
if not TYPE_CHECKING:
|
||||
Dep = Dependency
|
||||
else:
|
||||
|
||||
class _InstanceDep(Dependency[TI]):
|
||||
"""Fake stub we use to tell the type system we provide a type."""
|
||||
|
||||
def __get__(self, obj: Any, cls: Any = None) -> Type[TI]:
|
||||
return cast(Type[TI], None)
|
||||
|
||||
class _StaticDep(Dependency[TS]):
|
||||
"""Fake stub we use to tell the type system we provide an instance."""
|
||||
|
||||
def __get__(self, obj: Any, cls: Any = None) -> TS:
|
||||
return cast(TS, None)
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
# noinspection PyPep8Naming
|
||||
@overload
|
||||
def Dep(cls: Type[TI], config: Any = None) -> _InstanceDep[TI]:
|
||||
"""test"""
|
||||
return _InstanceDep(cls, config)
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@overload
|
||||
def Dep(cls: Type[TS], config: Any = None) -> _StaticDep[TS]:
|
||||
"""test"""
|
||||
return _StaticDep(cls, config)
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def Dep(cls: Any, config: Any = None) -> Any:
|
||||
"""test"""
|
||||
return Dependency(cls, config)
|
||||
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
|
||||
class BoundDepComponent:
|
||||
"""A DepComponent class bound to its DepSet data.
|
||||
|
||||
Can be called to instantiate the class with its data properly in place."""
|
||||
|
||||
def __init__(self, cls: Any, depdata: DepData):
|
||||
self.cls = cls
|
||||
# BoundDepComponents can be stored on depdatas so we use weakrefs
|
||||
# to avoid dependency cycles.
|
||||
self.depdata = weakref.ref(depdata)
|
||||
|
||||
def __call__(self, *args: Any, **keywds: Any) -> Any:
|
||||
# We don't simply call our target type to instantiate it;
|
||||
# instead we manually call __new__ and then __init__.
|
||||
# This allows us to inject its data properly before __init__().
|
||||
obj = self.cls.__new__(self.cls, *args, **keywds)
|
||||
obj._depdata = self.depdata()
|
||||
assert isinstance(obj._depdata, DepData)
|
||||
obj.__init__(*args, **keywds)
|
||||
return obj
|
||||
|
||||
|
||||
class DepComponent:
|
||||
"""Base class for all classes that can act as or use dependencies.
|
||||
|
||||
category: Dependency Classes
|
||||
"""
|
||||
|
||||
_depdata: DepData
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Instantiate a DepComponent."""
|
||||
|
||||
# For now lets issue a warning if these are instantiated without
|
||||
# data; we'll make this an error once we're no longer seeing warnings.
|
||||
depdata = getattr(self, '_depdata', None)
|
||||
if depdata is None:
|
||||
print(f'FIXME: INSTANTIATING DEP CLASS {type(self)} DIRECTLY.')
|
||||
|
||||
self.context = _ba.Context('current')
|
||||
|
||||
@classmethod
|
||||
def is_present(cls, config: Any = None) -> bool:
|
||||
"""Return whether this component/config is present on this device."""
|
||||
del config # Unused here.
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def get_dynamic_deps(cls, config: Any = None) -> List[Dependency]:
|
||||
"""Return any dynamically-calculated deps for this component/config.
|
||||
|
||||
Deps declared statically as part of the class do not need to be
|
||||
included here; this is only for additional deps that may vary based
|
||||
on the dep config value. (for instance a map required by a game type)
|
||||
"""
|
||||
del config # Unused here.
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def dep_get_payload(cls, depdata: DepData) -> Any:
|
||||
"""Return user-facing data for a loaded dep.
|
||||
|
||||
If this dep does not yet have a 'payload' value, it should
|
||||
be generated and cached. Otherwise the existing value
|
||||
should be returned.
|
||||
This is the value given for a DepComponent when accessed
|
||||
through a Dependency instance on a live object, etc.
|
||||
"""
|
||||
del depdata # Unused here.
|
||||
|
||||
|
||||
class DepData:
|
||||
"""Data associated with a dependency in a dependency set."""
|
||||
|
||||
def __init__(self, depset: DepSet, dep: Dependency[T]):
|
||||
# Note: identical Dep/config pairs will share data, so the dep
|
||||
# entry on a given Dep may not point to.
|
||||
self.cls = dep.cls
|
||||
self.config = dep.config
|
||||
|
||||
# Arbitrary data for use by dependencies in the resolved set
|
||||
# (the static instance for static-deps, etc).
|
||||
self.payload: Any = None
|
||||
self.valid: bool = False
|
||||
|
||||
# Weakref to the depset that includes us (to avoid ref loop).
|
||||
self.depset = weakref.ref(depset)
|
||||
|
||||
|
||||
class DepSet(Generic[TI]):
|
||||
"""Set of resolved dependencies and their associated data."""
|
||||
|
||||
def __init__(self, root: Dependency[TI]):
|
||||
self.root = root
|
||||
self._resolved = False
|
||||
|
||||
# Dependency data indexed by hash.
|
||||
self.depdatas: Dict[int, DepData] = {}
|
||||
|
||||
# Instantiated static-components.
|
||||
self.static_instances: List[StaticDepComponent] = []
|
||||
|
||||
def __del__(self) -> None:
|
||||
# When our dep-set goes down, clear out all dep-data payloads
|
||||
# so we can throw errors if anyone tries to use them anymore.
|
||||
for depdata in self.depdatas.values():
|
||||
depdata.payload = None
|
||||
depdata.valid = False
|
||||
|
||||
def resolve(self) -> None:
|
||||
"""Resolve the total set of required dependencies for the set.
|
||||
|
||||
Raises a ba.DependencyError if dependencies are missing (or other
|
||||
Exception types on other errors).
|
||||
"""
|
||||
|
||||
if self._resolved:
|
||||
raise Exception("DepSet has already been resolved.")
|
||||
|
||||
print('RESOLVING DEP SET')
|
||||
|
||||
# First, recursively expand out all dependencies.
|
||||
self._resolve(self.root, 0)
|
||||
|
||||
# Now, if any dependencies are not present, raise an Exception
|
||||
# telling exactly which ones (so hopefully they'll be able to be
|
||||
# downloaded/etc.
|
||||
missing = [
|
||||
Dependency(entry.cls, entry.config)
|
||||
for entry in self.depdatas.values()
|
||||
if not entry.cls.is_present(entry.config)
|
||||
]
|
||||
if missing:
|
||||
from ba._error import DependencyError
|
||||
raise DependencyError(missing)
|
||||
|
||||
self._resolved = True
|
||||
print('RESOLVE SUCCESS!')
|
||||
|
||||
def get_asset_package_ids(self) -> Set[str]:
|
||||
"""Return the set of asset-package-ids required by this dep-set.
|
||||
|
||||
Must be called on a resolved dep-set.
|
||||
"""
|
||||
ids: Set[str] = set()
|
||||
if not self._resolved:
|
||||
raise Exception('Must be called on a resolved dep-set.')
|
||||
for entry in self.depdatas.values():
|
||||
if issubclass(entry.cls, AssetPackage):
|
||||
assert isinstance(entry.config, str)
|
||||
ids.add(entry.config)
|
||||
return ids
|
||||
|
||||
def load(self) -> Type[TI]:
|
||||
"""Attach the resolved set to the current context.
|
||||
|
||||
Returns a wrapper which can be used to instantiate the root dep.
|
||||
"""
|
||||
# NOTE: stuff below here should probably go in a separate 'instantiate'
|
||||
# method or something.
|
||||
if not self._resolved:
|
||||
raise Exception("Can't instantiate an unresolved DepSet")
|
||||
|
||||
# Go through all of our dep entries and give them a chance to
|
||||
# preload whatever they want.
|
||||
for entry in self.depdatas.values():
|
||||
# First mark everything as valid so recursive loads don't fail.
|
||||
assert entry.valid is False
|
||||
entry.valid = True
|
||||
for entry in self.depdatas.values():
|
||||
# Do a get on everything which will init all payloads
|
||||
# in the proper order recursively.
|
||||
# NOTE: should we guard for recursion here?...
|
||||
entry.cls.dep_get_payload(entry)
|
||||
|
||||
# NOTE: like above, we're cheating here and telling the type
|
||||
# system we're simply returning the root dependency class, when
|
||||
# actually it's a bound-dependency wrapper containing its data/etc.
|
||||
# ..Should fix if/when mypy is smart enough to preserve type safety
|
||||
# on the wrapper's __call__()
|
||||
rootdata = self.depdatas[self.root.get_hash()]
|
||||
return cast(Type[TI], BoundDepComponent(self.root.cls, rootdata))
|
||||
|
||||
def _resolve(self, dep: Dependency[T], recursion: int) -> None:
|
||||
|
||||
# Watch for wacky infinite dep loops.
|
||||
if recursion > 10:
|
||||
raise Exception('Max recursion reached')
|
||||
|
||||
hashval = dep.get_hash()
|
||||
|
||||
if hashval in self.depdatas:
|
||||
# Found an already resolved one; we're done here.
|
||||
return
|
||||
|
||||
# Add our entry before we recurse so we don't repeat add it if
|
||||
# there's a dependency loop.
|
||||
self.depdatas[hashval] = DepData(self, dep)
|
||||
|
||||
# Grab all Dependency instances we find in the class.
|
||||
subdeps = [
|
||||
cls for cls in dep.cls.__dict__.values()
|
||||
if isinstance(cls, Dependency)
|
||||
]
|
||||
|
||||
# ..and add in any dynamic ones it provides.
|
||||
subdeps += dep.cls.get_dynamic_deps(dep.config)
|
||||
for subdep in subdeps:
|
||||
self._resolve(subdep, recursion + 1)
|
||||
|
||||
|
||||
class InstancedDepComponent(DepComponent):
|
||||
"""Base class for DepComponents intended to be instantiated as needed."""
|
||||
|
||||
@classmethod
|
||||
def dep_get_payload(cls, depdata: DepData) -> Any:
|
||||
"""Data provider override; returns a BoundDepComponent."""
|
||||
if depdata.payload is None:
|
||||
# The payload we want for ourself in the dep-set is simply
|
||||
# the bound-def that users can use to instantiate our class
|
||||
# with its data properly intact. We could also just store
|
||||
# the class and instantiate one of these each time.
|
||||
depdata.payload = BoundDepComponent(cls, depdata)
|
||||
return depdata.payload
|
||||
|
||||
|
||||
class StaticDepComponent(DepComponent):
|
||||
"""Base for DepComponents intended to be instantiated once and shared."""
|
||||
|
||||
@classmethod
|
||||
def dep_get_payload(cls, depdata: DepData) -> Any:
|
||||
"""Data provider override; returns shared instance."""
|
||||
if depdata.payload is None:
|
||||
# We want to share a single instance of our object with anything
|
||||
# in the set that requested it, so create a temp bound-dep and
|
||||
# create an instance from that.
|
||||
depcls = BoundDepComponent(cls, depdata)
|
||||
|
||||
# Instances have a strong ref to depdata so we can't give
|
||||
# depdata a strong reference to it without creating a cycle.
|
||||
# We also can't just weak-ref the instance or else it won't be
|
||||
# kept alive. Our solution is to stick strong refs to all static
|
||||
# components somewhere on the DepSet.
|
||||
instance = depcls()
|
||||
assert depdata.depset
|
||||
depset2 = depdata.depset()
|
||||
assert depset2 is not None
|
||||
depset2.static_instances.append(instance)
|
||||
depdata.payload = weakref.ref(instance)
|
||||
assert isinstance(depdata.payload, weakref.ref)
|
||||
payload = depdata.payload()
|
||||
if payload is None:
|
||||
raise RuntimeError(
|
||||
f'Accessing DepComponent {cls} in an invalid state.')
|
||||
return payload
|
||||
|
||||
|
||||
class AssetPackage(StaticDepComponent):
|
||||
"""DepComponent representing a bundled package of game assets."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
# pylint: disable=no-member
|
||||
assert isinstance(self._depdata.config, str)
|
||||
self.package_id = self._depdata.config
|
||||
print(f'LOADING ASSET PACKAGE {self.package_id}')
|
||||
|
||||
@classmethod
|
||||
def is_present(cls, config: Any = None) -> bool:
|
||||
assert isinstance(config, str)
|
||||
|
||||
# Temp: hard-coding for a single asset-package at the moment.
|
||||
if config == 'stdassets@1':
|
||||
return True
|
||||
return False
|
||||
|
||||
def gettexture(self, name: str) -> ba.Texture:
|
||||
"""Load a named ba.Texture from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.gettexture()
|
||||
"""
|
||||
return _ba.get_package_texture(self, name)
|
||||
|
||||
def getmodel(self, name: str) -> ba.Model:
|
||||
"""Load a named ba.Model from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getmodel()
|
||||
"""
|
||||
return _ba.get_package_model(self, name)
|
||||
|
||||
def getcollidemodel(self, name: str) -> ba.CollideModel:
|
||||
"""Load a named ba.CollideModel from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getcollideModel()
|
||||
"""
|
||||
return _ba.get_package_collide_model(self, name)
|
||||
|
||||
def getsound(self, name: str) -> ba.Sound:
|
||||
"""Load a named ba.Sound from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getsound()
|
||||
"""
|
||||
return _ba.get_package_sound(self, name)
|
||||
|
||||
def getdata(self, name: str) -> ba.Data:
|
||||
"""Load a named ba.Data from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getdata()
|
||||
"""
|
||||
return _ba.get_package_data(self, name)
|
||||
|
||||
|
||||
class TestClassFactory(StaticDepComponent):
|
||||
"""Another test dep-obj."""
|
||||
|
||||
_assets = Dep(AssetPackage, 'stdassets@1')
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
print("Instantiating TestClassFactory")
|
||||
self.tex = self._assets.gettexture('black')
|
||||
self.model = self._assets.getmodel('landMine')
|
||||
self.sound = self._assets.getsound('error')
|
||||
self.data = self._assets.getdata('langdata')
|
||||
|
||||
|
||||
class TestClassObj(InstancedDepComponent):
|
||||
"""Another test dep-obj."""
|
||||
|
||||
|
||||
class TestClass(InstancedDepComponent):
|
||||
"""A test dep-obj."""
|
||||
|
||||
_actorclass = Dep(TestClassObj)
|
||||
_factoryclass = Dep(TestClassFactory, 123)
|
||||
_factoryclass2 = Dep(TestClassFactory, 124)
|
||||
|
||||
def __init__(self, arg: int) -> None:
|
||||
super().__init__()
|
||||
del arg
|
||||
self._actor = self._actorclass()
|
||||
print('got actor', self._actor)
|
||||
print('have factory', self._factoryclass)
|
||||
print('have factory2', self._factoryclass2)
|
||||
|
||||
|
||||
def test_depset() -> None:
|
||||
"""Test call to try this stuff out..."""
|
||||
# noinspection PyUnreachableCode
|
||||
if False: # pylint: disable=using-constant-test
|
||||
print('running test_depset()...')
|
||||
|
||||
def doit() -> None:
|
||||
from ba._error import DependencyError
|
||||
depset = DepSet(Dep(TestClass))
|
||||
resolved = False
|
||||
try:
|
||||
depset.resolve()
|
||||
resolved = True
|
||||
except DependencyError as exc:
|
||||
for dep in exc.deps:
|
||||
if dep.cls is AssetPackage:
|
||||
print('MISSING PACKAGE', dep.config)
|
||||
else:
|
||||
raise Exception('unknown dependency error for ' +
|
||||
str(dep.cls))
|
||||
except Exception as exc:
|
||||
print('DepSet resolve failed with exc type:', type(exc))
|
||||
if resolved:
|
||||
testclass = depset.load()
|
||||
instance = testclass(123)
|
||||
print("INSTANTIATED ROOT:", instance)
|
||||
|
||||
doit()
|
||||
|
||||
# To test this, add prints on __del__ for stuff used above;
|
||||
# everything should be dead at this point if we have no cycles.
|
||||
print('everything should be cleaned up...')
|
||||
_ba.quit()
|
||||
437
assets/src/data/scripts/ba/_dependency.py
Normal file
437
assets/src/data/scripts/ba/_dependency.py
Normal file
@ -0,0 +1,437 @@
|
||||
# Copyright (c) 2011-2019 Eric Froemling
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# -----------------------------------------------------------------------------
|
||||
"""Functionality related to object/asset dependencies."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import weakref
|
||||
from typing import (Generic, TypeVar, TYPE_CHECKING)
|
||||
|
||||
import _ba
|
||||
from ba import _general
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any, Dict, List, Set, Type
|
||||
from weakref import ReferenceType
|
||||
import ba
|
||||
|
||||
T = TypeVar('T', bound='DependencyComponent')
|
||||
|
||||
|
||||
class Dependency(Generic[T]):
|
||||
"""A dependency on a DependencyComponent (with an optional config).
|
||||
|
||||
Category: Dependency Classes
|
||||
|
||||
This class is used to request and access functionality provided
|
||||
by other DependencyComponent classes from a DependencyComponent class.
|
||||
The class functions as a descriptor, allowing dependencies to
|
||||
be added at a class level much the same as properties or methods
|
||||
and then used with class instances to access those dependencies.
|
||||
For instance, if you do 'floofcls = ba.Dependency(FloofClass)' you
|
||||
would then be able to instantiate a FloofClass in your class's
|
||||
methods via self.floofcls().
|
||||
"""
|
||||
|
||||
def __init__(self, cls: Type[T], config: Any = None):
|
||||
"""Instantiate a Dependency given a ba.DependencyComponent type.
|
||||
|
||||
Optionally, an arbitrary object can be passed as 'config' to
|
||||
influence dependency calculation for the target class.
|
||||
"""
|
||||
self.cls: Type[T] = cls
|
||||
self.config = config
|
||||
self._hash: Optional[int] = None
|
||||
|
||||
def get_hash(self) -> int:
|
||||
"""Return the dependency's hash, calculating it if necessary."""
|
||||
if self._hash is None:
|
||||
self._hash = _general.make_hash((self.cls, self.config))
|
||||
return self._hash
|
||||
|
||||
def __get__(self, obj: Any, cls: Any = None) -> T:
|
||||
if not isinstance(obj, DependencyComponent):
|
||||
if obj is None:
|
||||
raise TypeError(
|
||||
"Dependency must be accessed through an instance.")
|
||||
raise TypeError(
|
||||
f"Dependency cannot be added to class of type {type(obj)}"
|
||||
" (class must inherit from ba.DependencyComponent).")
|
||||
|
||||
# We expect to be instantiated from an already living
|
||||
# DependencyComponent with valid dep-data in place..
|
||||
assert cls is not None
|
||||
|
||||
# Get the DependencyEntry this instance is associated with and from
|
||||
# there get back to the DependencySet
|
||||
entry = getattr(obj, '_dep_entry')
|
||||
if entry is None:
|
||||
raise RuntimeError("Invalid dependency access.")
|
||||
entry = entry()
|
||||
assert isinstance(entry, DependencyEntry)
|
||||
depset = entry.depset()
|
||||
assert isinstance(depset, DependencySet)
|
||||
|
||||
if not depset.resolved:
|
||||
raise RuntimeError(
|
||||
"Can't access data on an unresolved DependencySet.")
|
||||
|
||||
# Look up the data in the set based on the hash for this Dependency.
|
||||
assert self._hash in depset.entries
|
||||
entry = depset.entries[self._hash]
|
||||
assert isinstance(entry, DependencyEntry)
|
||||
retval = entry.get_component()
|
||||
assert isinstance(retval, self.cls)
|
||||
return retval
|
||||
|
||||
|
||||
class DependencyComponent:
|
||||
"""Base class for all classes that can act as or use dependencies.
|
||||
|
||||
category: Dependency Classes
|
||||
"""
|
||||
|
||||
_dep_entry: ReferenceType[DependencyEntry]
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Instantiate a DependencyComponent."""
|
||||
|
||||
# For now lets issue a warning if these are instantiated without
|
||||
# a dep-entry; we'll make this an error once we're no longer
|
||||
# seeing warnings.
|
||||
entry = getattr(self, '_dep_entry', None)
|
||||
if entry is None:
|
||||
print(f'FIXME: INSTANTIATING DEP CLASS {type(self)} DIRECTLY.')
|
||||
|
||||
@classmethod
|
||||
def dep_is_present(cls, config: Any = None) -> bool:
|
||||
"""Return whether this component/config is present on this device."""
|
||||
del config # Unused here.
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def get_dynamic_deps(cls, config: Any = None) -> List[Dependency]:
|
||||
"""Return any dynamically-calculated deps for this component/config.
|
||||
|
||||
Deps declared statically as part of the class do not need to be
|
||||
included here; this is only for additional deps that may vary based
|
||||
on the dep config value. (for instance a map required by a game type)
|
||||
"""
|
||||
del config # Unused here.
|
||||
return []
|
||||
|
||||
|
||||
class DependencyEntry:
|
||||
"""Data associated with a dependency/config pair in a ba.DependencySet."""
|
||||
|
||||
def __del__(self) -> None:
|
||||
print('~DepEntry()', self.cls)
|
||||
|
||||
def __init__(self, depset: DependencySet, dep: Dependency[T]):
|
||||
print("DepEntry()", dep.cls)
|
||||
self.cls = dep.cls
|
||||
self.config = dep.config
|
||||
|
||||
# Arbitrary data for use by dependencies in the resolved set
|
||||
# (the static instance for static-deps, etc).
|
||||
self.component: Optional[DependencyComponent] = None
|
||||
|
||||
# Weakref to the depset that includes us (to avoid ref loop).
|
||||
self.depset = weakref.ref(depset)
|
||||
|
||||
def get_component(self) -> DependencyComponent:
|
||||
"""Return the component instance, creating it if necessary."""
|
||||
if self.component is None:
|
||||
# We don't simply call our type to instantiate our instance;
|
||||
# instead we manually call __new__ and then __init__.
|
||||
# This allows us to inject its data properly before __init__().
|
||||
print('creating', self.cls)
|
||||
instance = self.cls.__new__(self.cls)
|
||||
# pylint: disable=protected-access
|
||||
instance._dep_entry = weakref.ref(self)
|
||||
instance.__init__()
|
||||
|
||||
assert self.depset
|
||||
depset = self.depset()
|
||||
assert depset is not None
|
||||
self.component = instance
|
||||
component = self.component
|
||||
assert isinstance(component, self.cls)
|
||||
if component is None:
|
||||
raise RuntimeError(f'Accessing DependencyComponent {self.cls} '
|
||||
'in an invalid state.')
|
||||
return component
|
||||
|
||||
|
||||
class DependencySet(Generic[T]):
|
||||
"""Set of resolved dependencies and their associated data.
|
||||
|
||||
To use DependencyComponents, a set must be created, resolved, and then
|
||||
loaded. The DependencyComponents are only valid while the set remains
|
||||
in existence.
|
||||
"""
|
||||
|
||||
def __init__(self, root_dependency: Dependency[T]):
|
||||
print('DepSet()')
|
||||
self._root_dependency = root_dependency
|
||||
self._resolved = False
|
||||
self._loaded = False
|
||||
|
||||
# Dependency data indexed by hash.
|
||||
self.entries: Dict[int, DependencyEntry] = {}
|
||||
|
||||
def __del__(self) -> None:
|
||||
print("~DepSet()")
|
||||
|
||||
def resolve(self) -> None:
|
||||
"""Resolve the complete set of required dependencies for this set.
|
||||
|
||||
Raises a ba.DependencyError if dependencies are missing (or other
|
||||
Exception types on other errors).
|
||||
"""
|
||||
|
||||
if self._resolved:
|
||||
raise Exception("DependencySet has already been resolved.")
|
||||
|
||||
print('RESOLVING DEP SET')
|
||||
|
||||
# First, recursively expand out all dependencies.
|
||||
self._resolve(self._root_dependency, 0)
|
||||
|
||||
# Now, if any dependencies are not present, raise an Exception
|
||||
# telling exactly which ones (so hopefully they'll be able to be
|
||||
# downloaded/etc.
|
||||
missing = [
|
||||
Dependency(entry.cls, entry.config)
|
||||
for entry in self.entries.values()
|
||||
if not entry.cls.dep_is_present(entry.config)
|
||||
]
|
||||
if missing:
|
||||
from ba._error import DependencyError
|
||||
raise DependencyError(missing)
|
||||
|
||||
self._resolved = True
|
||||
print('RESOLVE SUCCESS!')
|
||||
|
||||
@property
|
||||
def resolved(self) -> bool:
|
||||
"""Whether this set has been successfully resolved."""
|
||||
return self._resolved
|
||||
|
||||
def get_asset_package_ids(self) -> Set[str]:
|
||||
"""Return the set of asset-package-ids required by this dep-set.
|
||||
|
||||
Must be called on a resolved dep-set.
|
||||
"""
|
||||
ids: Set[str] = set()
|
||||
if not self._resolved:
|
||||
raise Exception('Must be called on a resolved dep-set.')
|
||||
for entry in self.entries.values():
|
||||
if issubclass(entry.cls, AssetPackage):
|
||||
assert isinstance(entry.config, str)
|
||||
ids.add(entry.config)
|
||||
return ids
|
||||
|
||||
def load(self) -> None:
|
||||
"""Instantiate all DependencyComponents in the set.
|
||||
|
||||
Returns a wrapper which can be used to instantiate the root dep.
|
||||
"""
|
||||
# NOTE: stuff below here should probably go in a separate 'instantiate'
|
||||
# method or something.
|
||||
if not self._resolved:
|
||||
raise RuntimeError("Can't load an unresolved DependencySet")
|
||||
|
||||
for entry in self.entries.values():
|
||||
# Do a get on everything which will init all payloads
|
||||
# in the proper order recursively.
|
||||
entry.get_component()
|
||||
|
||||
self._loaded = True
|
||||
|
||||
@property
|
||||
def root(self) -> T:
|
||||
"""The instantiated root DependencyComponent instance for the set."""
|
||||
if not self._loaded:
|
||||
raise RuntimeError("DependencySet is not loaded.")
|
||||
|
||||
rootdata = self.entries[self._root_dependency.get_hash()].component
|
||||
assert isinstance(rootdata, self._root_dependency.cls)
|
||||
return rootdata
|
||||
|
||||
def _resolve(self, dep: Dependency[T], recursion: int) -> None:
|
||||
|
||||
# Watch for wacky infinite dep loops.
|
||||
if recursion > 10:
|
||||
raise Exception('Max recursion reached')
|
||||
|
||||
hashval = dep.get_hash()
|
||||
|
||||
if hashval in self.entries:
|
||||
# Found an already resolved one; we're done here.
|
||||
return
|
||||
|
||||
# Add our entry before we recurse so we don't repeat add it if
|
||||
# there's a dependency loop.
|
||||
self.entries[hashval] = DependencyEntry(self, dep)
|
||||
|
||||
# Grab all Dependency instances we find in the class.
|
||||
subdeps = [
|
||||
cls for cls in dep.cls.__dict__.values()
|
||||
if isinstance(cls, Dependency)
|
||||
]
|
||||
|
||||
# ..and add in any dynamic ones it provides.
|
||||
subdeps += dep.cls.get_dynamic_deps(dep.config)
|
||||
for subdep in subdeps:
|
||||
self._resolve(subdep, recursion + 1)
|
||||
|
||||
|
||||
class AssetPackage(DependencyComponent):
|
||||
"""DependencyComponent representing a bundled package of game assets."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
# pylint: disable=no-member
|
||||
|
||||
# This is used internally by the get_package_xxx calls.
|
||||
self.context = _ba.Context('current')
|
||||
|
||||
entry = self._dep_entry()
|
||||
assert entry is not None
|
||||
assert isinstance(entry.config, str)
|
||||
self.package_id = entry.config
|
||||
print(f'LOADING ASSET PACKAGE {self.package_id}')
|
||||
|
||||
@classmethod
|
||||
def dep_is_present(cls, config: Any = None) -> bool:
|
||||
assert isinstance(config, str)
|
||||
|
||||
# Temp: hard-coding for a single asset-package at the moment.
|
||||
if config == 'stdassets@1':
|
||||
return True
|
||||
return False
|
||||
|
||||
def gettexture(self, name: str) -> ba.Texture:
|
||||
"""Load a named ba.Texture from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.gettexture()
|
||||
"""
|
||||
return _ba.get_package_texture(self, name)
|
||||
|
||||
def getmodel(self, name: str) -> ba.Model:
|
||||
"""Load a named ba.Model from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getmodel()
|
||||
"""
|
||||
return _ba.get_package_model(self, name)
|
||||
|
||||
def getcollidemodel(self, name: str) -> ba.CollideModel:
|
||||
"""Load a named ba.CollideModel from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getcollideModel()
|
||||
"""
|
||||
return _ba.get_package_collide_model(self, name)
|
||||
|
||||
def getsound(self, name: str) -> ba.Sound:
|
||||
"""Load a named ba.Sound from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getsound()
|
||||
"""
|
||||
return _ba.get_package_sound(self, name)
|
||||
|
||||
def getdata(self, name: str) -> ba.Data:
|
||||
"""Load a named ba.Data from the AssetPackage.
|
||||
|
||||
Behavior is similar to ba.getdata()
|
||||
"""
|
||||
return _ba.get_package_data(self, name)
|
||||
|
||||
|
||||
class TestClassFactory(DependencyComponent):
|
||||
"""Another test dep-obj."""
|
||||
|
||||
_assets = Dependency(AssetPackage, 'stdassets@1')
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
print("Instantiating TestClassFactory")
|
||||
self.tex = self._assets.gettexture('black')
|
||||
self.model = self._assets.getmodel('landMine')
|
||||
self.sound = self._assets.getsound('error')
|
||||
self.data = self._assets.getdata('langdata')
|
||||
|
||||
|
||||
class TestClassObj(DependencyComponent):
|
||||
"""Another test dep-obj."""
|
||||
|
||||
|
||||
class TestClass(DependencyComponent):
|
||||
"""A test dep-obj."""
|
||||
|
||||
_testclass = Dependency(TestClassObj)
|
||||
_factoryclass = Dependency(TestClassFactory, 123)
|
||||
_factoryclass2 = Dependency(TestClassFactory, 123)
|
||||
|
||||
def __del__(self) -> None:
|
||||
print("~TestClass()")
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
print('TestClass()')
|
||||
self._actor = self._testclass
|
||||
print('got actor', self._actor)
|
||||
print('have factory', self._factoryclass)
|
||||
print('have factory2', self._factoryclass2)
|
||||
|
||||
|
||||
def test_depset() -> None:
|
||||
"""Test call to try this stuff out..."""
|
||||
# noinspection PyUnreachableCode
|
||||
if False: # pylint: disable=using-constant-test
|
||||
print('running test_depset()...')
|
||||
|
||||
def doit() -> None:
|
||||
from ba._error import DependencyError
|
||||
depset = DependencySet(Dependency(TestClass))
|
||||
try:
|
||||
depset.resolve()
|
||||
except DependencyError as exc:
|
||||
for dep in exc.deps:
|
||||
if dep.cls is AssetPackage:
|
||||
print('MISSING ASSET PACKAGE', dep.config)
|
||||
else:
|
||||
raise Exception('unknown dependency error for ' +
|
||||
str(dep.cls))
|
||||
except Exception as exc:
|
||||
print('DependencySet resolve failed with exc type:', type(exc))
|
||||
if depset.resolved:
|
||||
depset.load()
|
||||
testobj = depset.root
|
||||
# instance = testclass(123)
|
||||
print("INSTANTIATED ROOT:", testobj)
|
||||
|
||||
doit()
|
||||
|
||||
# To test this, add prints on __del__ for stuff used above;
|
||||
# everything should be dead at this point if we have no cycles.
|
||||
print('everything should be cleaned up...')
|
||||
_ba.quit()
|
||||
@ -250,9 +250,9 @@ class GameActivity(Activity):
|
||||
implementation; should return a list of map names valid
|
||||
for this game-type for the given ba.Session type.
|
||||
"""
|
||||
from ba import _maps
|
||||
from ba import _map
|
||||
del sessiontype # unused arg
|
||||
return _maps.getmaps("melee")
|
||||
return _map.getmaps("melee")
|
||||
|
||||
@classmethod
|
||||
def get_config_display_string(cls, config: Dict[str, Any]) -> ba.Lstr:
|
||||
@ -261,7 +261,7 @@ class GameActivity(Activity):
|
||||
This is used when viewing game-lists or showing what game
|
||||
is up next in a series.
|
||||
"""
|
||||
from ba import _maps
|
||||
from ba import _map
|
||||
name = cls.get_display_string(config['settings'])
|
||||
|
||||
# in newer configs, map is in settings; it used to be in the
|
||||
@ -270,15 +270,15 @@ class GameActivity(Activity):
|
||||
sval = Lstr(value="${NAME} @ ${MAP}",
|
||||
subs=[('${NAME}', name),
|
||||
('${MAP}',
|
||||
_maps.get_map_display_string(
|
||||
_maps.get_filtered_map_name(
|
||||
_map.get_map_display_string(
|
||||
_map.get_filtered_map_name(
|
||||
config['settings']['map'])))])
|
||||
elif 'map' in config:
|
||||
sval = Lstr(value="${NAME} @ ${MAP}",
|
||||
subs=[('${NAME}', name),
|
||||
('${MAP}',
|
||||
_maps.get_map_display_string(
|
||||
_maps.get_filtered_map_name(config['map'])))
|
||||
_map.get_map_display_string(
|
||||
_map.get_filtered_map_name(config['map'])))
|
||||
])
|
||||
else:
|
||||
print('invalid game config - expected map entry under settings')
|
||||
@ -295,7 +295,7 @@ class GameActivity(Activity):
|
||||
|
||||
def __init__(self, settings: Dict[str, Any]):
|
||||
"""Instantiate the Activity."""
|
||||
from ba import _maps
|
||||
from ba import _map
|
||||
super().__init__(settings)
|
||||
|
||||
# Set some defaults.
|
||||
@ -313,7 +313,7 @@ class GameActivity(Activity):
|
||||
else:
|
||||
# If settings doesn't specify a map, pick a random one from the
|
||||
# list of supported ones.
|
||||
unowned_maps = _maps.get_unowned_maps()
|
||||
unowned_maps = _map.get_unowned_maps()
|
||||
valid_maps: List[str] = [
|
||||
m for m in self.get_supported_maps(type(self.session))
|
||||
if m not in unowned_maps
|
||||
@ -322,7 +322,7 @@ class GameActivity(Activity):
|
||||
_ba.screenmessage(Lstr(resource='noValidMapsErrorText'))
|
||||
raise Exception("No valid maps")
|
||||
map_name = valid_maps[random.randrange(len(valid_maps))]
|
||||
self._map_type = _maps.get_map_class(map_name)
|
||||
self._map_type = _map.get_map_class(map_name)
|
||||
self._map_type.preload()
|
||||
self._map: Optional[ba.Map] = None
|
||||
self._powerup_drop_timer: Optional[ba.Timer] = None
|
||||
|
||||
@ -47,13 +47,13 @@ def filter_playlist(playlist: PlaylistType,
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-statements
|
||||
from ba import _meta
|
||||
from ba import _maps
|
||||
from ba import _map
|
||||
from ba import _general
|
||||
from ba import _gameactivity
|
||||
goodlist: List[Dict] = []
|
||||
unowned_maps: Sequence[str]
|
||||
if remove_unowned or mark_unowned:
|
||||
unowned_maps = _maps.get_unowned_maps()
|
||||
unowned_maps = _map.get_unowned_maps()
|
||||
unowned_game_types = _meta.get_unowned_game_types()
|
||||
else:
|
||||
unowned_maps = []
|
||||
@ -69,7 +69,7 @@ def filter_playlist(playlist: PlaylistType,
|
||||
entry['settings']['map'] = entry['map']
|
||||
del entry['map']
|
||||
# update old map names to new ones
|
||||
entry['settings']['map'] = _maps.get_filtered_map_name(
|
||||
entry['settings']['map'] = _map.get_filtered_map_name(
|
||||
entry['settings']['map'])
|
||||
if remove_unowned and entry['settings']['map'] in unowned_maps:
|
||||
continue
|
||||
|
||||
@ -83,7 +83,7 @@ class Session:
|
||||
players: List[ba.Player]
|
||||
|
||||
def __init__(self,
|
||||
depsets: Sequence[ba.DepSet],
|
||||
depsets: Sequence[ba.DependencySet],
|
||||
team_names: Sequence[str] = None,
|
||||
team_colors: Sequence[Sequence[float]] = None,
|
||||
use_team_colors: bool = True,
|
||||
@ -94,7 +94,7 @@ class Session:
|
||||
# pylint: disable=too-many-branches
|
||||
"""Instantiate a session.
|
||||
|
||||
depsets should be a sequence of successfully resolved ba.DepSet
|
||||
depsets should be a sequence of successfully resolved ba.DependencySet
|
||||
instances; one for each ba.Activity the session may potentially run.
|
||||
"""
|
||||
# pylint: disable=too-many-locals
|
||||
@ -105,7 +105,7 @@ class Session:
|
||||
from ba._gameactivity import GameActivity
|
||||
from ba._team import Team
|
||||
from ba._error import DependencyError
|
||||
from ba._dep import Dep, AssetPackage
|
||||
from ba._dependency import Dependency, AssetPackage
|
||||
|
||||
print(' WOULD LOOK AT DEP SETS', depsets)
|
||||
|
||||
@ -131,7 +131,8 @@ class Session:
|
||||
# throw a combined exception if we found anything missing
|
||||
if missing_asset_packages:
|
||||
raise DependencyError([
|
||||
Dep(AssetPackage, set_id) for set_id in missing_asset_packages
|
||||
Dependency(AssetPackage, set_id)
|
||||
for set_id in missing_asset_packages
|
||||
])
|
||||
|
||||
# ok; looks like our dependencies check out.
|
||||
|
||||
@ -40,7 +40,7 @@ def get_store_item_name_translated(item_name: str) -> ba.Lstr:
|
||||
"""Return a ba.Lstr for a store item name."""
|
||||
# pylint: disable=cyclic-import
|
||||
from ba import _lang
|
||||
from ba import _maps
|
||||
from ba import _map
|
||||
item_info = get_store_item(item_name)
|
||||
if item_name.startswith('characters.'):
|
||||
return _lang.Lstr(translate=('characterNames', item_info['character']))
|
||||
@ -50,7 +50,7 @@ def get_store_item_name_translated(item_name: str) -> ba.Lstr:
|
||||
_lang.Lstr(resource='titleText'))])
|
||||
if item_name.startswith('maps.'):
|
||||
map_type: Type[ba.Map] = item_info['map_type']
|
||||
return _maps.get_map_display_string(map_type.name)
|
||||
return _map.get_map_display_string(map_type.name)
|
||||
if item_name.startswith('games.'):
|
||||
gametype: Type[ba.GameActivity] = item_info['gametype']
|
||||
return gametype.get_display_string()
|
||||
|
||||
@ -66,7 +66,7 @@ class TeamBaseSession(Session):
|
||||
team_colors = None
|
||||
|
||||
print('FIXME: TEAM BASE SESSION WOULD CALC DEPS.')
|
||||
depsets: Sequence[ba.DepSet] = []
|
||||
depsets: Sequence[ba.DependencySet] = []
|
||||
super().__init__(depsets,
|
||||
team_names=team_names,
|
||||
team_colors=team_colors,
|
||||
|
||||
@ -27,9 +27,9 @@ defensively) in mods.
|
||||
|
||||
# pylint: disable=unused-import
|
||||
|
||||
from ba._maps import (get_unowned_maps, get_map_class, register_map,
|
||||
preload_map_preview_media, get_map_display_string,
|
||||
get_filtered_map_name)
|
||||
from ba._map import (get_unowned_maps, get_map_class, register_map,
|
||||
preload_map_preview_media, get_map_display_string,
|
||||
get_filtered_map_name)
|
||||
from ba._appconfig import commit_app_config
|
||||
from ba._input import (get_device_value, get_input_map_hash,
|
||||
get_input_device_config)
|
||||
|
||||
@ -18,4 +18,4 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# -----------------------------------------------------------------------------
|
||||
"""Functionality shared between Ballistica client and server components."""
|
||||
"""Functionality shared between all Ballistica clients, servers, and tools."""
|
||||
|
||||
@ -36,7 +36,13 @@ TRET = TypeVar('TRET')
|
||||
|
||||
|
||||
def utc_now() -> datetime.datetime:
|
||||
"""Get offset-aware current utc time."""
|
||||
"""Get offset-aware current utc time.
|
||||
|
||||
This should be used for all datetimes getting sent over the network,
|
||||
used with the entity system, etc.
|
||||
(datetime.utcnow() gives a utc time value, but it is not timezone-aware
|
||||
which makes it less safe to use)
|
||||
"""
|
||||
return datetime.datetime.now(datetime.timezone.utc)
|
||||
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ if TYPE_CHECKING:
|
||||
class MainMenuActivity(ba.Activity):
|
||||
"""Activity showing the rotating main menu bg stuff."""
|
||||
|
||||
_stdassets = ba.Dep(ba.AssetPackage, 'stdassets@1')
|
||||
_stdassets = ba.Dependency(ba.AssetPackage, 'stdassets@1')
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
super().on_transition_in()
|
||||
@ -903,7 +903,7 @@ class MainMenuSession(ba.Session):
|
||||
def __init__(self) -> None:
|
||||
|
||||
# Gather dependencies we'll need (just our activity).
|
||||
self._activity_deps = ba.DepSet(ba.Dep(MainMenuActivity))
|
||||
self._activity_deps = ba.DependencySet(ba.Dependency(MainMenuActivity))
|
||||
|
||||
super().__init__([self._activity_deps])
|
||||
self._locked = False
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<!--DOCSHASH=f593a39e3a39b53bf74c893acf8c746b-->
|
||||
<h4><em>last updated on 2019-11-12 for Ballistica version 1.5.0 build 20001</em></h4>
|
||||
<!--DOCSHASH=51c5d02115be6a67ed7833c3ec13432e-->
|
||||
<h4><em>last updated on 2019-11-21 for Ballistica version 1.5.0 build 20001</em></h4>
|
||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||
<hr>
|
||||
@ -150,8 +150,8 @@
|
||||
</ul>
|
||||
<h4><a class="offsanchor" name="class_category_Dependency_Classes">Dependency Classes</a></h4>
|
||||
<ul>
|
||||
<li><a href="#class_ba_DepComponent">ba.DepComponent</a></li>
|
||||
<li><a href="#class_ba_Dependency">ba.Dependency</a></li>
|
||||
<li><a href="#class_ba_DependencyComponent">ba.DependencyComponent</a></li>
|
||||
</ul>
|
||||
<h4><a class="offsanchor" name="class_category_Enums">Enums</a></h4>
|
||||
<ul>
|
||||
@ -182,7 +182,7 @@
|
||||
<li><a href="#class_ba_AssetPackage">ba.AssetPackage</a></li>
|
||||
<li><a href="#class_ba_Campaign">ba.Campaign</a></li>
|
||||
<li><a href="#class_ba_Chooser">ba.Chooser</a></li>
|
||||
<li><a href="#class_ba_DepSet">ba.DepSet</a></li>
|
||||
<li><a href="#class_ba_DependencySet">ba.DependencySet</a></li>
|
||||
<li><a href="#class_ba_Lobby">ba.Lobby</a></li>
|
||||
<li><a href="#class_ba_MusicPlayer">ba.MusicPlayer</a></li>
|
||||
<li><a href="#class_ba_OldWindow">ba.OldWindow</a></li>
|
||||
@ -287,7 +287,7 @@ actually award achievements.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_Activity">ba.Activity</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba__dep_InstancedDepComponent">ba._dep.InstancedDepComponent</a>, <a href="#class_ba_DepComponent">ba.DepComponent</a></p>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a></p>
|
||||
<p style="padding-left: 30px;">Units of execution wrangled by a <a href="#class_ba_Session">ba.Session</a>.</p>
|
||||
|
||||
<p style="padding-left: 30px;">Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||
@ -329,7 +329,7 @@ player gets their own team; in teams mode there are always 2 teams
|
||||
regardless of the player count).</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods Inherited:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba__dep_InstancedDepComponent__dep_get_payload">dep_get_payload()</a>, <a href="#method_ba__dep_InstancedDepComponent__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba__dep_InstancedDepComponent__is_present">is_present()</a></h5>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_DependencyComponent__dep_is_present">dep_is_present()</a>, <a href="#method_ba_DependencyComponent__get_dynamic_deps">get_dynamic_deps()</a></h5>
|
||||
<h3 style="padding-left: 0px;">Methods Defined or Overridden:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_Activity____init__"><constructor></a>, <a href="#method_ba_Activity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_Activity__create_player_node">create_player_node()</a>, <a href="#method_ba_Activity__end">end()</a>, <a href="#method_ba_Activity__handlemessage">handlemessage()</a>, <a href="#method_ba_Activity__has_begun">has_begun()</a>, <a href="#method_ba_Activity__has_ended">has_ended()</a>, <a href="#method_ba_Activity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_Activity__is_expired">is_expired()</a>, <a href="#method_ba_Activity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_Activity__on_begin">on_begin()</a>, <a href="#method_ba_Activity__on_expire">on_expire()</a>, <a href="#method_ba_Activity__on_player_join">on_player_join()</a>, <a href="#method_ba_Activity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_Activity__on_team_join">on_team_join()</a>, <a href="#method_ba_Activity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Activity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_Activity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_Activity__retain_actor">retain_actor()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_Activity____init__"><strong><constructor></strong></a></h4>
|
||||
@ -903,17 +903,23 @@ when done.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_AssetPackage">ba.AssetPackage</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba__dep_StaticDepComponent">ba._dep.StaticDepComponent</a>, <a href="#class_ba_DepComponent">ba.DepComponent</a></p>
|
||||
<p style="padding-left: 30px;">DepComponent representing a bundled package of game assets.</p>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a></p>
|
||||
<p style="padding-left: 30px;">DependencyComponent representing a bundled package of game assets.</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods Inherited:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba__dep_StaticDepComponent__dep_get_payload">dep_get_payload()</a>, <a href="#method_ba__dep_StaticDepComponent__get_dynamic_deps">get_dynamic_deps()</a></h5>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_DependencyComponent__get_dynamic_deps">get_dynamic_deps()</a></h5>
|
||||
<h3 style="padding-left: 0px;">Methods Defined or Overridden:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_AssetPackage____init__"><constructor></a>, <a href="#method_ba_AssetPackage__getcollidemodel">getcollidemodel()</a>, <a href="#method_ba_AssetPackage__getdata">getdata()</a>, <a href="#method_ba_AssetPackage__getmodel">getmodel()</a>, <a href="#method_ba_AssetPackage__getsound">getsound()</a>, <a href="#method_ba_AssetPackage__gettexture">gettexture()</a>, <a href="#method_ba_AssetPackage__is_present">is_present()</a></h5>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_AssetPackage____init__"><constructor></a>, <a href="#method_ba_AssetPackage__dep_is_present">dep_is_present()</a>, <a href="#method_ba_AssetPackage__getcollidemodel">getcollidemodel()</a>, <a href="#method_ba_AssetPackage__getdata">getdata()</a>, <a href="#method_ba_AssetPackage__getmodel">getmodel()</a>, <a href="#method_ba_AssetPackage__getsound">getsound()</a>, <a href="#method_ba_AssetPackage__gettexture">gettexture()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_AssetPackage____init__"><strong><constructor></strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.AssetPackage()</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Instantiate a DepComponent.</p>
|
||||
<p style="padding-left: 60px;">Instantiate a DependencyComponent.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_AssetPackage__dep_is_present"><strong>dep_is_present()</strong></a></h4>
|
||||
<h5 style="padding-left: 60px;"><span style="color: #CC6600;"><em><class method></span></em></h5>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">dep_is_present(config: Any = None) -> bool </span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return whether this component/config is present on this device.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_AssetPackage__getcollidemodel"><strong>getcollidemodel()</strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">getcollidemodel(self, name: str) -> <a href="#class_ba_CollideModel">ba.CollideModel</a></span></p>
|
||||
@ -950,12 +956,6 @@ when done.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Behavior is similar to <a href="#function_ba_gettexture">ba.gettexture</a>()</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_AssetPackage__is_present"><strong>is_present()</strong></a></h4>
|
||||
<h5 style="padding-left: 60px;"><span style="color: #CC6600;"><em><class method></span></em></h5>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">is_present(config: Any = None) -> bool </span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return whether this component/config is present on this device.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_Call">ba.Call</a></strong></h3>
|
||||
<p style="padding-left: 30px;"><em><top level class></em>
|
||||
@ -1229,7 +1229,7 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_CoopGameActivity">ba.CoopGameActivity</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba__dep_InstancedDepComponent">ba._dep.InstancedDepComponent</a>, <a href="#class_ba_DepComponent">ba.DepComponent</a></p>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a></p>
|
||||
<p style="padding-left: 30px;">Base class for cooperative-mode games.</p>
|
||||
|
||||
<p style="padding-left: 30px;">Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a>
|
||||
@ -1258,7 +1258,7 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
||||
<p style="padding-left: 60px;"> If access is attempted before or after, raises a <a href="#class_ba_NotFoundError">ba.NotFoundError</a>.</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods Inherited:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player_node">create_player_node()</a>, <a href="#method_ba_GameActivity__dep_get_payload">dep_get_payload()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_resolved_score_info">get_resolved_score_info()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_expired">is_expired()</a>, <a href="#method_ba_GameActivity__is_present">is_present()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__start_transition_in">start_transition_in()</a></h5>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player_node">create_player_node()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_resolved_score_info">get_resolved_score_info()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_expired">is_expired()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__start_transition_in">start_transition_in()</a></h5>
|
||||
<h3 style="padding-left: 0px;">Methods Defined or Overridden:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_CoopGameActivity____init__"><constructor></a>, <a href="#method_ba_CoopGameActivity__celebrate">celebrate()</a>, <a href="#method_ba_CoopGameActivity__fade_to_red">fade_to_red()</a>, <a href="#method_ba_CoopGameActivity__get_score_type">get_score_type()</a>, <a href="#method_ba_CoopGameActivity__on_begin">on_begin()</a>, <a href="#method_ba_CoopGameActivity__setup_low_life_warning_sound">setup_low_life_warning_sound()</a>, <a href="#method_ba_CoopGameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_CoopGameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_CoopGameActivity____init__"><strong><constructor></strong></a></h4>
|
||||
@ -1386,59 +1386,15 @@ Note that this call will block if the data has not yet been loaded,
|
||||
so it can be beneficial to plan a short bit of time between when
|
||||
the data object is requested and when it's value is accessed.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_DepComponent">ba.DepComponent</a></strong></h3>
|
||||
<p style="padding-left: 30px;"><em><top level class></em>
|
||||
</p>
|
||||
<p style="padding-left: 30px;">Base class for all classes that can act as or use dependencies.</p>
|
||||
|
||||
<p style="padding-left: 30px;">Category: <a href="#class_category_Dependency_Classes">Dependency Classes</a>
|
||||
</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_DepComponent____init__"><constructor></a>, <a href="#method_ba_DepComponent__dep_get_payload">dep_get_payload()</a>, <a href="#method_ba_DepComponent__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_DepComponent__is_present">is_present()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepComponent____init__"><strong><constructor></strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.DepComponent()</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Instantiate a DepComponent.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepComponent__dep_get_payload"><strong>dep_get_payload()</strong></a></h4>
|
||||
<h5 style="padding-left: 60px;"><span style="color: #CC6600;"><em><class method></span></em></h5>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">dep_get_payload(depdata: DepData) -> Any </span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return user-facing data for a loaded dep.</p>
|
||||
|
||||
<p style="padding-left: 60px;">If this dep does not yet have a 'payload' value, it should
|
||||
be generated and cached. Otherwise the existing value
|
||||
should be returned.
|
||||
This is the value given for a DepComponent when accessed
|
||||
through a Dependency instance on a live object, etc.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepComponent__get_dynamic_deps"><strong>get_dynamic_deps()</strong></a></h4>
|
||||
<h5 style="padding-left: 60px;"><span style="color: #CC6600;"><em><class method></span></em></h5>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">get_dynamic_deps(config: Any = None) -> List[Dependency] </span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return any dynamically-calculated deps for this component/config.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Deps declared statically as part of the class do not need to be
|
||||
included here; this is only for additional deps that may vary based
|
||||
on the dep config value. (for instance a map required by a game type)</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepComponent__is_present"><strong>is_present()</strong></a></h4>
|
||||
<h5 style="padding-left: 60px;"><span style="color: #CC6600;"><em><class method></span></em></h5>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">is_present(config: Any = None) -> bool </span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return whether this component/config is present on this device.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_Dependency">ba.Dependency</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_typing_Generic">typing.Generic</a></p>
|
||||
<p style="padding-left: 30px;">A dependency on a DepComponent (with an optional config).</p>
|
||||
<p style="padding-left: 30px;">A dependency on a DependencyComponent (with an optional config).</p>
|
||||
|
||||
<p style="padding-left: 30px;">Category: <a href="#class_category_Dependency_Classes">Dependency Classes</a></p>
|
||||
|
||||
<p style="padding-left: 30px;"> This class is used to request and access functionality provided
|
||||
by other DepComponent classes from a DepComponent class.
|
||||
by other DependencyComponent classes from a DependencyComponent class.
|
||||
The class functions as a descriptor, allowing dependencies to
|
||||
be added at a class level much the same as properties or methods
|
||||
and then used with class instances to access those dependencies.
|
||||
@ -1452,7 +1408,7 @@ on the dep config value. (for instance a map required by a game type)</p>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_Dependency____init__"><strong><constructor></strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.Dependency(cls: Type[T], config: Any = None)</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Instantiate a Dependency given a <a href="#class_ba_DepComponent">ba.DepComponent</a> subtype.</p>
|
||||
<p style="padding-left: 60px;">Instantiate a Dependency given a <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a> type.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Optionally, an arbitrary object can be passed as 'config' to
|
||||
influence dependency calculation for the target class.</p>
|
||||
@ -1462,6 +1418,38 @@ influence dependency calculation for the target class.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Return the dependency's hash, calculating it if necessary.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_DependencyComponent">ba.DependencyComponent</a></strong></h3>
|
||||
<p style="padding-left: 30px;"><em><top level class></em>
|
||||
</p>
|
||||
<p style="padding-left: 30px;">Base class for all classes that can act as or use dependencies.</p>
|
||||
|
||||
<p style="padding-left: 30px;">Category: <a href="#class_category_Dependency_Classes">Dependency Classes</a>
|
||||
</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_DependencyComponent____init__"><constructor></a>, <a href="#method_ba_DependencyComponent__dep_is_present">dep_is_present()</a>, <a href="#method_ba_DependencyComponent__get_dynamic_deps">get_dynamic_deps()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DependencyComponent____init__"><strong><constructor></strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.DependencyComponent()</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Instantiate a DependencyComponent.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DependencyComponent__dep_is_present"><strong>dep_is_present()</strong></a></h4>
|
||||
<h5 style="padding-left: 60px;"><span style="color: #CC6600;"><em><class method></span></em></h5>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">dep_is_present(config: Any = None) -> bool </span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return whether this component/config is present on this device.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DependencyComponent__get_dynamic_deps"><strong>get_dynamic_deps()</strong></a></h4>
|
||||
<h5 style="padding-left: 60px;"><span style="color: #CC6600;"><em><class method></span></em></h5>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">get_dynamic_deps(config: Any = None) -> List[Dependency] </span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return any dynamically-calculated deps for this component/config.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Deps declared statically as part of the class do not need to be
|
||||
included here; this is only for additional deps that may vary based
|
||||
on the dep config value. (for instance a map required by a game type)</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_DependencyError">ba.DependencyError</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: Exception, BaseException</p>
|
||||
@ -1484,33 +1472,48 @@ influence dependency calculation for the target class.</p>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.DependencyError(deps: List[<a href="#class_ba_Dependency">ba.Dependency</a>])</span></p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_DepSet">ba.DepSet</a></strong></h3>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_DependencySet">ba.DependencySet</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_typing_Generic">typing.Generic</a></p>
|
||||
<p style="padding-left: 30px;">Set of resolved dependencies and their associated data.</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_DepSet____init__"><constructor></a>, <a href="#method_ba_DepSet__get_asset_package_ids">get_asset_package_ids()</a>, <a href="#method_ba_DepSet__load">load()</a>, <a href="#method_ba_DepSet__resolve">resolve()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepSet____init__"><strong><constructor></strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.DepSet(root: Dependency[TI])</span></p>
|
||||
<p style="padding-left: 30px;"> To use DependencyComponents, a set must be created, resolved, and then
|
||||
loaded. The DependencyComponents are only valid while the set remains
|
||||
in existence.
|
||||
</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepSet__get_asset_package_ids"><strong>get_asset_package_ids()</strong></a></h4>
|
||||
<h3 style="padding-left: 0px;">Attributes:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#attr_ba_DependencySet__resolved">resolved</a>, <a href="#attr_ba_DependencySet__root">root</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="attr_ba_DependencySet__resolved"><strong>resolved</strong></a></h4>
|
||||
<p style="padding-left: 60px;"><span style="color: #666677;">bool</span></p>
|
||||
<p style="padding-left: 60px;">Whether this set has been successfully resolved.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="attr_ba_DependencySet__root"><strong>root</strong></a></h4>
|
||||
<p style="padding-left: 60px;"><span style="color: #666677;">T</span></p>
|
||||
<p style="padding-left: 60px;">The instantiated root DependencyComponent instance for the set.</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_DependencySet____init__"><constructor></a>, <a href="#method_ba_DependencySet__get_asset_package_ids">get_asset_package_ids()</a>, <a href="#method_ba_DependencySet__load">load()</a>, <a href="#method_ba_DependencySet__resolve">resolve()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DependencySet____init__"><strong><constructor></strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.DependencySet(root_dependency: Dependency[T])</span></p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DependencySet__get_asset_package_ids"><strong>get_asset_package_ids()</strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">get_asset_package_ids(self) -> Set[str]</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Return the set of asset-package-ids required by this dep-set.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Must be called on a resolved dep-set.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepSet__load"><strong>load()</strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">load(self) -> Type[TI]</span></p>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DependencySet__load"><strong>load()</strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">load(self) -> None</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Attach the resolved set to the current context.</p>
|
||||
<p style="padding-left: 60px;">Instantiate all DependencyComponents in the set.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Returns a wrapper which can be used to instantiate the root dep.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DepSet__resolve"><strong>resolve()</strong></a></h4>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_DependencySet__resolve"><strong>resolve()</strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">resolve(self) -> None</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Resolve the total set of required dependencies for the set.</p>
|
||||
<p style="padding-left: 60px;">Resolve the complete set of required dependencies for this set.</p>
|
||||
|
||||
<p style="padding-left: 60px;">Raises a <a href="#class_ba_DependencyError">ba.DependencyError</a> if dependencies are missing (or other
|
||||
Exception types on other errors).</p>
|
||||
@ -1616,7 +1619,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_GameActivity">ba.GameActivity</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba__dep_InstancedDepComponent">ba._dep.InstancedDepComponent</a>, <a href="#class_ba_DepComponent">ba.DepComponent</a></p>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a></p>
|
||||
<p style="padding-left: 30px;">Common base class for all game ba.Activities.</p>
|
||||
|
||||
<p style="padding-left: 30px;">Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a>
|
||||
@ -1645,7 +1648,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
<p style="padding-left: 60px;"> If access is attempted before or after, raises a <a href="#class_ba_NotFoundError">ba.NotFoundError</a>.</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods Inherited:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_Activity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_Activity__begin">begin()</a>, <a href="#method_ba_Activity__create_player_node">create_player_node()</a>, <a href="#method_ba_Activity__dep_get_payload">dep_get_payload()</a>, <a href="#method_ba_Activity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_Activity__has_begun">has_begun()</a>, <a href="#method_ba_Activity__has_ended">has_ended()</a>, <a href="#method_ba_Activity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_Activity__is_expired">is_expired()</a>, <a href="#method_ba_Activity__is_present">is_present()</a>, <a href="#method_ba_Activity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_Activity__on_expire">on_expire()</a>, <a href="#method_ba_Activity__on_team_join">on_team_join()</a>, <a href="#method_ba_Activity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Activity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_Activity__retain_actor">retain_actor()</a>, <a href="#method_ba_Activity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_Activity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_Activity__start_transition_in">start_transition_in()</a></h5>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_Activity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_Activity__begin">begin()</a>, <a href="#method_ba_Activity__create_player_node">create_player_node()</a>, <a href="#method_ba_Activity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_Activity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_Activity__has_begun">has_begun()</a>, <a href="#method_ba_Activity__has_ended">has_ended()</a>, <a href="#method_ba_Activity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_Activity__is_expired">is_expired()</a>, <a href="#method_ba_Activity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_Activity__on_expire">on_expire()</a>, <a href="#method_ba_Activity__on_team_join">on_team_join()</a>, <a href="#method_ba_Activity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Activity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_Activity__retain_actor">retain_actor()</a>, <a href="#method_ba_Activity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_Activity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_Activity__start_transition_in">start_transition_in()</a></h5>
|
||||
<h3 style="padding-left: 0px;">Methods Defined or Overridden:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_GameActivity____init__"><constructor></a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_resolved_score_info">get_resolved_score_info()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_begin">on_begin()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_GameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_GameActivity____init__"><strong><constructor></strong></a></h4>
|
||||
@ -3303,11 +3306,11 @@ list in <a href="#class_ba_Activity">ba.Activity</a>; not this.</p>
|
||||
<h3 style="padding-left: 0px;">Methods:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_Session____init__"><constructor></a>, <a href="#method_ba_Session__begin_next_activity">begin_next_activity()</a>, <a href="#method_ba_Session__end">end()</a>, <a href="#method_ba_Session__end_activity">end_activity()</a>, <a href="#method_ba_Session__get_custom_menu_entries">get_custom_menu_entries()</a>, <a href="#method_ba_Session__getactivity">getactivity()</a>, <a href="#method_ba_Session__handlemessage">handlemessage()</a>, <a href="#method_ba_Session__on_activity_end">on_activity_end()</a>, <a href="#method_ba_Session__on_player_leave">on_player_leave()</a>, <a href="#method_ba_Session__on_player_request">on_player_request()</a>, <a href="#method_ba_Session__on_team_join">on_team_join()</a>, <a href="#method_ba_Session__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Session__set_activity">set_activity()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_Session____init__"><strong><constructor></strong></a></h4>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.Session(depsets: Sequence[<a href="#class_ba_DepSet">ba.DepSet</a>], team_names: Sequence[str] = None, team_colors: Sequence[Sequence[float]] = None, use_team_colors: bool = True, min_players: int = 1, max_players: int = 8, allow_mid_activity_joins: bool = True)</span></p>
|
||||
<p style="padding-left: 110px; text-indent: -50px;"><span style="color: #666677;">ba.Session(depsets: Sequence[<a href="#class_ba_DependencySet">ba.DependencySet</a>], team_names: Sequence[str] = None, team_colors: Sequence[Sequence[float]] = None, use_team_colors: bool = True, min_players: int = 1, max_players: int = 8, allow_mid_activity_joins: bool = True)</span></p>
|
||||
|
||||
<p style="padding-left: 60px;">Instantiate a session.</p>
|
||||
|
||||
<p style="padding-left: 60px;">depsets should be a sequence of successfully resolved <a href="#class_ba_DepSet">ba.DepSet</a>
|
||||
<p style="padding-left: 60px;">depsets should be a sequence of successfully resolved <a href="#class_ba_DependencySet">ba.DependencySet</a>
|
||||
instances; one for each <a href="#class_ba_Activity">ba.Activity</a> the session may potentially run.</p>
|
||||
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_Session__begin_next_activity"><strong>begin_next_activity()</strong></a></h4>
|
||||
@ -3754,7 +3757,7 @@ another <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||
|
||||
<hr>
|
||||
<h2><strong><a class="offsanchor" name="class_ba_TeamGameActivity">ba.TeamGameActivity</a></strong></h3>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba__dep_InstancedDepComponent">ba._dep.InstancedDepComponent</a>, <a href="#class_ba_DepComponent">ba.DepComponent</a></p>
|
||||
<p style="padding-left: 30px;">inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a></p>
|
||||
<p style="padding-left: 30px;">Base class for teams and free-for-all mode games.</p>
|
||||
|
||||
<p style="padding-left: 30px;">Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||
@ -3786,7 +3789,7 @@ another <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||
<p style="padding-left: 60px;"> If access is attempted before or after, raises a <a href="#class_ba_NotFoundError">ba.NotFoundError</a>.</p>
|
||||
|
||||
<h3 style="padding-left: 0px;">Methods Inherited:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player_node">create_player_node()</a>, <a href="#method_ba_GameActivity__dep_get_payload">dep_get_payload()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_resolved_score_info">get_resolved_score_info()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_expired">is_expired()</a>, <a href="#method_ba_GameActivity__is_present">is_present()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__start_transition_in">start_transition_in()</a></h5>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player_node">create_player_node()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_resolved_score_info">get_resolved_score_info()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_expired">is_expired()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__start_transition_in">start_transition_in()</a></h5>
|
||||
<h3 style="padding-left: 0px;">Methods Defined or Overridden:</h3>
|
||||
<h5 style="padding-left: 30px;"><a href="#method_ba_TeamGameActivity____init__"><constructor></a>, <a href="#method_ba_TeamGameActivity__end">end()</a>, <a href="#method_ba_TeamGameActivity__on_begin">on_begin()</a>, <a href="#method_ba_TeamGameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_TeamGameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_TeamGameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<h4 style="padding-left: 30px;"><a class="offsanchor" name="method_ba_TeamGameActivity____init__"><strong><constructor></strong></a></h4>
|
||||
|
||||
199
tools/cloudtool
Executable file
199
tools/cloudtool
Executable file
@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env python3.7
|
||||
# Copyright (c) 2011-2019 Eric Froemling
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# -----------------------------------------------------------------------------
|
||||
"""A tool for interacting with ballistica's cloud services.
|
||||
This facilitates workflows such as creating asset-bundles, etc.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import os
|
||||
from typing import TYPE_CHECKING
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import urllib.error
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
import json
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
# Version is sent to the master-server with all commands. Can be incremented
|
||||
# if we need to change behavior server-side to go along with client changes.
|
||||
VERSION = 1
|
||||
|
||||
TOOL_NAME = 'cloudtool'
|
||||
|
||||
# Set CLOUDTOOL_LOCAL env var to 1 to test with a locally-run master-server.
|
||||
MASTER_SERVER_ADDRESS = ('http://localhost:23524'
|
||||
if os.environ.get('CLOUDTOOL_LOCAL') == '1' else
|
||||
'https://bamaster.appspot.com')
|
||||
USER_AGENT_STRING = 'cloudtool'
|
||||
CACHE_DIR = Path('.cache/cloudtool')
|
||||
CACHE_DATA_PATH = Path(CACHE_DIR, 'state')
|
||||
|
||||
CLRHDR = '\033[95m' # Header.
|
||||
CLRGRN = '\033[92m' # Green.
|
||||
CLRBLU = '\033[94m' # Glue.
|
||||
CLRRED = '\033[91m' # Red.
|
||||
CLREND = '\033[0m' # End.
|
||||
|
||||
CMD_LOGIN = 'login'
|
||||
CMD_LOGOUT = 'logout'
|
||||
CMD_HELP = 'help'
|
||||
|
||||
|
||||
@dataclass
|
||||
class StateData:
|
||||
"""Persistent state data stored to disk."""
|
||||
login_token: Optional[str] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Response:
|
||||
"""Response data from the master server for a command."""
|
||||
message: Optional[str]
|
||||
error: Optional[str]
|
||||
data: Any
|
||||
|
||||
|
||||
class CleanError(Exception):
|
||||
"""Exception resulting in a clean error string print and exit."""
|
||||
|
||||
|
||||
class App:
|
||||
"""Context for a run of the tool."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._state = StateData()
|
||||
|
||||
def run(self) -> None:
|
||||
"""Run the tool."""
|
||||
|
||||
# Make reasonably sure we're being run from project root.
|
||||
if not os.path.exists(f'tools/{TOOL_NAME}'):
|
||||
raise CleanError(
|
||||
'This tool must be run from ballistica project root.')
|
||||
|
||||
self._load_cache()
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
raise CleanError(
|
||||
f'Invalid args. Run "cloudtool help" for usage info.')
|
||||
|
||||
cmd = sys.argv[1]
|
||||
if cmd == CMD_LOGIN:
|
||||
self.do_login()
|
||||
elif cmd == CMD_LOGOUT:
|
||||
self.do_logout()
|
||||
else:
|
||||
# For all other commands, simply pass them to the server verbatim.
|
||||
self.do_misc_command()
|
||||
|
||||
self._save_cache()
|
||||
|
||||
def _load_cache(self) -> None:
|
||||
if not os.path.exists(CACHE_DATA_PATH):
|
||||
return
|
||||
try:
|
||||
with open(CACHE_DATA_PATH, 'r') as infile:
|
||||
self._state = StateData(**json.loads(infile.read()))
|
||||
except Exception:
|
||||
print(CLRRED +
|
||||
f'Error loading {TOOL_NAME} data; resetting to defaults.' +
|
||||
CLREND)
|
||||
|
||||
def _save_cache(self) -> None:
|
||||
if not CACHE_DIR.exists():
|
||||
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
with open(CACHE_DATA_PATH, 'w') as outfile:
|
||||
outfile.write(json.dumps(self._state.__dict__))
|
||||
|
||||
def _servercmd(self, cmd: str, data: Dict) -> Response:
|
||||
"""Issue a command to the server and get a response."""
|
||||
|
||||
# We do all communication through POST requests to the server.
|
||||
response_raw = urllib.request.urlopen(
|
||||
urllib.request.Request(
|
||||
(MASTER_SERVER_ADDRESS + '/cloudtoolcmd'),
|
||||
urllib.parse.urlencode({
|
||||
'c': cmd,
|
||||
'v': VERSION,
|
||||
't': json.dumps(self._state.login_token),
|
||||
'd': json.dumps(data)
|
||||
}).encode(), {'User-Agent': USER_AGENT_STRING}))
|
||||
output = json.loads(response_raw.read().decode())
|
||||
assert isinstance(output, dict)
|
||||
response = Response(message=output['m'],
|
||||
data=output['d'],
|
||||
error=output['e'])
|
||||
|
||||
# Handle errors and messages which are common to all command types.
|
||||
if response.error is not None:
|
||||
raise CleanError(response.error)
|
||||
|
||||
if response.message is not None:
|
||||
print(response.message)
|
||||
|
||||
return response
|
||||
|
||||
def do_login(self) -> None:
|
||||
"""Run the login command."""
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
raise CleanError('Expected a login code.')
|
||||
|
||||
login_code = sys.argv[2]
|
||||
response = self._servercmd('login', {'c': login_code})
|
||||
|
||||
# If the command returned cleanly, we should have a token we can use
|
||||
# to log in.
|
||||
token = response.data['logintoken']
|
||||
assert isinstance(token, str)
|
||||
|
||||
aname = response.data['accountname']
|
||||
assert isinstance(aname, str)
|
||||
|
||||
print(f'{CLRGRN}Now logged in as {aname}.{CLREND}')
|
||||
self._state.login_token = token
|
||||
|
||||
def do_logout(self) -> None:
|
||||
"""Run the logout command."""
|
||||
self._state.login_token = None
|
||||
print(f'{CLRGRN}Cloudtool is now logged out.{CLREND}')
|
||||
|
||||
def do_misc_command(self) -> None:
|
||||
"""Run a miscellaneous command."""
|
||||
|
||||
# We don't do anything special with the response here; the normal
|
||||
# error-handling/message-printing is all that happens.
|
||||
self._servercmd('misc', {'a': sys.argv[1:]})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
App().run()
|
||||
except CleanError as exc:
|
||||
if str(exc):
|
||||
print(f'{CLRRED}{exc}{CLREND}')
|
||||
sys.exit(-1)
|
||||
@ -447,9 +447,9 @@ def makefile_target_list() -> None:
|
||||
return ' - ' + doc
|
||||
return doc
|
||||
|
||||
print('--------------------------\n'
|
||||
'Available Makefile Targets\n'
|
||||
'--------------------------')
|
||||
print('----------------------\n'
|
||||
'Available Make Targets\n'
|
||||
'----------------------')
|
||||
|
||||
entries: List[_Entry] = []
|
||||
for i, line in enumerate(lines):
|
||||
|
||||
@ -711,14 +711,16 @@ def checkenv() -> None:
|
||||
raise CleanError('pip (for {python_bin}) is required.')
|
||||
|
||||
# Check for some required python modules.
|
||||
for modname, minver in [
|
||||
('pylint', [2, 4, 3]),
|
||||
('mypy', [0, 740]),
|
||||
('yapf', [0, 28, 0]),
|
||||
('typing_extensions', None),
|
||||
('pytz', None),
|
||||
for modname, minver, packagename in [
|
||||
('pylint', [2, 4, 4], None),
|
||||
('mypy', [0, 740], None),
|
||||
('yapf', [0, 28, 0], None),
|
||||
('typing_extensions', None, None),
|
||||
('pytz', None, None),
|
||||
('yaml', None, 'PyYAML'),
|
||||
]:
|
||||
|
||||
if packagename is None:
|
||||
packagename = modname
|
||||
if minver is not None:
|
||||
results = subprocess.run(f'{python_bin} -m {modname} --version',
|
||||
shell=True,
|
||||
@ -730,9 +732,9 @@ def checkenv() -> None:
|
||||
check=False,
|
||||
capture_output=True)
|
||||
if results.returncode != 0:
|
||||
raise CleanError(
|
||||
f'{modname} (for {python_bin}) is required.\n'
|
||||
f'To install it, try: "{python_bin} -m pip install {modname}"')
|
||||
raise CleanError(f'{packagename} (for {python_bin}) is required.\n'
|
||||
f'To install it, try: "{python_bin}'
|
||||
f' -m pip install {packagename}"')
|
||||
if minver is not None:
|
||||
ver_line = results.stdout.decode().splitlines()[0]
|
||||
assert modname in ver_line
|
||||
@ -740,7 +742,7 @@ def checkenv() -> None:
|
||||
assert len(vnums) == len(minver)
|
||||
if vnums < minver:
|
||||
raise CleanError(
|
||||
f'{modname} ver. {_vstr(minver)} or newer required;'
|
||||
f'{packagename} ver. {_vstr(minver)} or newer required;'
|
||||
f' found {_vstr(vnums)}')
|
||||
|
||||
print('Environment ok.', flush=True)
|
||||
|
||||
@ -19,8 +19,7 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# -----------------------------------------------------------------------------
|
||||
"""
|
||||
This script acts as a 'meta' Makefile for the project. It is in charge
|
||||
"""This script acts as a 'meta' Makefile for the project. It is in charge
|
||||
of generating Makefiles, IDE project files, procedurally generated source
|
||||
files, etc. based on the current structure of the project.
|
||||
It can also perform sanity checks or cleanup tasks.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user