mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-23 23:49:47 +08:00
v1.5.23
This commit is contained in:
parent
400488cc66
commit
49e4da8b4f
@ -4135,16 +4135,16 @@
|
||||
"assets/build/windows/x64/vc_redist.x64.exe": "https://files.ballistica.net/cache/ba1/ea/19/8b8787d81abcdce158ba608cd24f",
|
||||
"assets/build/windows/x64/vcruntime140_1d.dll": "https://files.ballistica.net/cache/ba1/11/d8/ff6344b429b00c24d9a1930d4338",
|
||||
"assets/build/windows/x64/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/20/33/0825e11e6518f87ece3009309933",
|
||||
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/26/e9/3cc27e1957894e2926093efaf419",
|
||||
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cc/6d/523557326436bb1f2c79b40db30f",
|
||||
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/59/b5/cd299564c2795a47f19253121289",
|
||||
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/90/15/400a238c241f4baaf593338c2f0e",
|
||||
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4a/17/9c657df88fcf1aa529a6d57c1c63",
|
||||
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2c/14/4af6ef9f9452c10d3dbc7b864045",
|
||||
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/11/05/2d5de66e04958be2440d10c96694",
|
||||
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/89/c8/2e9218badd4259e480c3b3315bf6",
|
||||
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/7e/7b/173c424cd6548670163304241161",
|
||||
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/bc/d9/52268ba89bf9e6821fd95d4b6852",
|
||||
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/e3/49/f6b920cf41705a40f7c00ad2cd26",
|
||||
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d4/9f/365187c2ebdeffdfba74a35cf4f7"
|
||||
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b2/16/0414b009ce117f73bb2bc8991d3b",
|
||||
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/66/07/d82a3ec80ff3243321e373439210",
|
||||
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/12/5f/f87158c3281a2616897fdd2165cb",
|
||||
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/69/23/a2d029f81db60cf89ad5f6510ddb",
|
||||
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c4/e3/5aba369252ed1977be8950e5a1ce",
|
||||
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f7/ef/c28554f863485e9cd54f0d8d4e6f",
|
||||
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/68/af/f060b3463bc31c202a830fb0b20a",
|
||||
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/96/46/a239821d00e782303077192817c5",
|
||||
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/dc/15/fdd9195afe2bf299405ec49ed238",
|
||||
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/68/f9/c42b1f9b5af34cb371f80250e16b",
|
||||
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/5d/9b/213c602a9aa9cbc28872d2753f51",
|
||||
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/2f/a4/e6a6a6e0e2b64c5232cccddffdd3"
|
||||
}
|
||||
4
.idea/dictionaries/ericf.xml
generated
4
.idea/dictionaries/ericf.xml
generated
@ -570,6 +570,7 @@
|
||||
<w>elim</w>
|
||||
<w>emitfx</w>
|
||||
<w>emoji</w>
|
||||
<w>emojis</w>
|
||||
<w>enablexinput</w>
|
||||
<w>ename</w>
|
||||
<w>encerr</w>
|
||||
@ -1453,7 +1454,10 @@
|
||||
<w>plistname</w>
|
||||
<w>plpt</w>
|
||||
<w>plst</w>
|
||||
<w>plugkey</w>
|
||||
<w>plugkeys</w>
|
||||
<w>pluglist</w>
|
||||
<w>plugstate</w>
|
||||
<w>plugstates</w>
|
||||
<w>plusbutton</w>
|
||||
<w>plvel</w>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
- Fixed the shebang line in `bombsquad_server` file by using `-S` flag for `/usr/bin/env`.
|
||||
- Fixed a bug with hardware keyboards emitting extra characters in the in-game console (~ or F2)
|
||||
- Added support for 'plugin' mods and user controls to configure them in settings->advanced->plugins.
|
||||
- renamed selection_loop_to_parent to selection_loops_to_parent in widget calls.
|
||||
- Renamed selection_loop_to_parent to selection_loops_to_parent in widget calls.
|
||||
- Added 'selection_loops_to_parent', 'border', 'margin', 'claims_left_right', and 'claims_tab' args to ba.columnwidget().
|
||||
- Column-widget now has a default 'border' of 0 (explicitly pass 2 to get the old look).
|
||||
- Column-widget now has a default 'margin' of 10 (explicitly pass 0 to get the old look).
|
||||
@ -10,7 +10,7 @@
|
||||
- Added 'selection_loops_to_parent', 'claims_left_right', and 'claims_tab' args to ba.rowwidget.
|
||||
- Added 'claims_left_right' and 'claims_tab' to ba.hscrollwidget().
|
||||
- Default widget 'show_buffer' is now 20 instead of 0 (causes scrolling to stay slightly ahead of widget selection). This can be overridden with the ba.widget() call if anything breaks.
|
||||
- Relocated ba.app.uiscale to ba.app.ui.uiscale
|
||||
- Relocated ba.app.uiscale to ba.app.ui.uiscale.
|
||||
- Top level settings window now properly saves/restores its state again.
|
||||
- Added Emojis to the Internal Game Keyboard.
|
||||
- Added continuous CAPITAL letters typing feature in the Internal Game Keyboard.
|
||||
|
||||
@ -38,7 +38,7 @@ from _ba import (CollideModel, Context, ContextCall, Data, InputDevice,
|
||||
set_analytics_screen, charstr, textwidget, time, timer,
|
||||
open_url, widget)
|
||||
from ba._activity import Activity
|
||||
from ba._plugin import AvailablePlugin, Plugin
|
||||
from ba._plugin import PotentialPlugin, Plugin
|
||||
from ba._actor import Actor
|
||||
from ba._player import PlayerInfo, Player, EmptyPlayer, StandLocation
|
||||
from ba._nodeactor import NodeActor
|
||||
|
||||
@ -306,8 +306,8 @@ class App:
|
||||
assert isinstance(self.headless_build, bool)
|
||||
|
||||
# Plugins.
|
||||
self.loaded_plugins: List[ba.Plugin] = []
|
||||
self.available_plugins: List[ba.AvailablePlugin] = []
|
||||
self.potential_plugins: List[ba.PotentialPlugin] = []
|
||||
self.active_plugins: Dict[str, ba.Plugin] = {}
|
||||
|
||||
# Misc.
|
||||
self.default_language = self._get_default_language()
|
||||
@ -411,6 +411,7 @@ class App:
|
||||
(internal)"""
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=cyclic-import
|
||||
# pylint: disable=too-many-statements
|
||||
from ba import _apputils
|
||||
from ba import _appconfig
|
||||
from ba import _achievement
|
||||
@ -520,11 +521,49 @@ class App:
|
||||
|
||||
_ba.pushcall(do_auto_sign_in)
|
||||
|
||||
# Load up our plugins and go ahead and call their on_app_launch calls.
|
||||
self.load_plugins()
|
||||
for plugin in self.active_plugins.values():
|
||||
try:
|
||||
plugin.on_app_launch()
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('Error in plugin on_app_launch()')
|
||||
|
||||
self.ran_on_app_launch = True
|
||||
|
||||
# from ba._dependency import test_depset
|
||||
# test_depset()
|
||||
|
||||
def load_plugins(self) -> None:
|
||||
"""(internal)"""
|
||||
from ba._general import getclass
|
||||
from ba._plugin import Plugin
|
||||
|
||||
# Note: the plugins we load is purely based on what's enabled
|
||||
# in the app config. Our meta-scan gives us a list of available
|
||||
# plugins, but that is only used to give the user a list of plugins
|
||||
# that they can enable. (we wouldn't want to look at meta-scan here
|
||||
# anyway because it may not be done yet at this point in the launch)
|
||||
plugstates: Dict[str, Dict] = self.config.get('Plugins', {})
|
||||
assert isinstance(plugstates, dict)
|
||||
plugkeys: List[str] = sorted(key for key, val in plugstates.items()
|
||||
if val.get('enabled', False))
|
||||
for plugkey in plugkeys:
|
||||
try:
|
||||
cls = getclass(plugkey, Plugin)
|
||||
except Exception as exc:
|
||||
_ba.log(f"Error loading plugin class '{plugkey}': {exc}",
|
||||
to_server=False)
|
||||
continue
|
||||
try:
|
||||
plugin = cls()
|
||||
assert plugkey not in self.active_plugins
|
||||
self.active_plugins[plugkey] = plugin
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception(f'Error loading plugin: {plugkey}')
|
||||
|
||||
def read_config(self) -> None:
|
||||
"""(internal)"""
|
||||
from ba import _appconfig
|
||||
|
||||
@ -66,6 +66,7 @@ def handle_scan_results(results: ScanResults) -> None:
|
||||
"""Called in the game thread with results of a completed scan."""
|
||||
|
||||
from ba._lang import Lstr
|
||||
from ba._plugin import PotentialPlugin
|
||||
|
||||
# Warnings generally only get printed locally for users' benefit
|
||||
# (things like out-of-date scripts being ignored, etc.)
|
||||
@ -87,18 +88,32 @@ def handle_scan_results(results: ScanResults) -> None:
|
||||
config_changed = False
|
||||
found_new = False
|
||||
plugstates: Dict[str, Dict] = _ba.app.config.setdefault('Plugins', {})
|
||||
if not isinstance(plugstates, dict):
|
||||
print('Warning; found non-dict for "Plugins" in config.')
|
||||
plugstates = {}
|
||||
config_changed = True
|
||||
assert isinstance(plugstates, dict)
|
||||
|
||||
for plug in results.plugins:
|
||||
if plug not in plugstates:
|
||||
print('found new plugin:', plug)
|
||||
plugstates[plug] = {'enabled': False}
|
||||
# Create a potential-plugin for each class we found in the scan.
|
||||
for class_path in results.plugins:
|
||||
_ba.app.potential_plugins.append(
|
||||
PotentialPlugin(display_name=Lstr(value=class_path),
|
||||
class_path=class_path,
|
||||
available=True))
|
||||
if class_path not in plugstates:
|
||||
plugstates[class_path] = {'enabled': False}
|
||||
config_changed = True
|
||||
found_new = True
|
||||
|
||||
# Also add a special one for any plugins set to load but *not* found
|
||||
# in the scan (this way they will show up in the UI so we can disable them)
|
||||
for class_path, plugstate in plugstates.items():
|
||||
enabled = plugstate.get('enabled', False)
|
||||
assert isinstance(enabled, bool)
|
||||
if enabled and class_path not in results.plugins:
|
||||
_ba.app.potential_plugins.append(
|
||||
PotentialPlugin(display_name=Lstr(value=class_path),
|
||||
class_path=class_path,
|
||||
available=False))
|
||||
|
||||
_ba.app.potential_plugins.sort(key=lambda p: p.class_path)
|
||||
|
||||
if found_new:
|
||||
_ba.screenmessage(Lstr(resource='pluginsDetectedText'),
|
||||
color=(0, 1, 0))
|
||||
@ -106,7 +121,6 @@ def handle_scan_results(results: ScanResults) -> None:
|
||||
|
||||
if config_changed:
|
||||
_ba.app.config.commit()
|
||||
# print(f'would check {len(results.plugins)} plugs')
|
||||
|
||||
|
||||
class ScanThread(threading.Thread):
|
||||
@ -189,6 +203,9 @@ class DirectoryScan:
|
||||
self.results.warnings += ("Error scanning '" + str(subpath) +
|
||||
"': " + traceback.format_exc() +
|
||||
'\n')
|
||||
# Sort our results
|
||||
self.results.games.sort()
|
||||
self.results.plugins.sort()
|
||||
|
||||
def scan_module(self, moduledir: pathlib.Path,
|
||||
subpath: pathlib.Path) -> None:
|
||||
|
||||
@ -26,23 +26,35 @@ from typing import TYPE_CHECKING
|
||||
from dataclasses import dataclass
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
import ba
|
||||
|
||||
|
||||
@dataclass
|
||||
class AvailablePlugin:
|
||||
"""Defines a plugin which can potentially be loaded.
|
||||
class PotentialPlugin:
|
||||
"""Represents a ba.Plugin which can potentially be loaded.
|
||||
|
||||
Category: App Classes
|
||||
|
||||
These generally represent plugins which were detected by the
|
||||
meta-tag scan. However they may also represent plugins which
|
||||
were previously set to be loaded but which were unable to be
|
||||
for some reason. In that case, 'available' will be set to False.
|
||||
"""
|
||||
display_name: str
|
||||
display_name: ba.Lstr
|
||||
class_path: str
|
||||
available: bool
|
||||
|
||||
|
||||
class Plugin:
|
||||
"""A plugin to alter app behavior in some way.
|
||||
|
||||
Category: App Classes
|
||||
|
||||
Plugins are discoverable by the meta-tag system
|
||||
and the user can select which ones they want to activate.
|
||||
Active plugins are then called at specific times as the
|
||||
app is running in order to modify its behavior in some way.
|
||||
"""
|
||||
|
||||
name: str
|
||||
def on_app_launch(self) -> None:
|
||||
"""Called when the app is being launched."""
|
||||
|
||||
@ -161,13 +161,3 @@ class SharedObjects:
|
||||
),
|
||||
)
|
||||
return self._railing_material
|
||||
|
||||
|
||||
# ba _meta export plugin
|
||||
class TestPlug1(ba.Plugin):
|
||||
"""Just Testing."""
|
||||
|
||||
|
||||
# ba _meta export plugin
|
||||
class TestPlug2(ba.Plugin):
|
||||
"""Just Testing 2."""
|
||||
|
||||
@ -27,20 +27,16 @@ from typing import TYPE_CHECKING
|
||||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Tuple, Optional
|
||||
from typing import Tuple, Optional, Dict
|
||||
|
||||
|
||||
class PluginSettingsWindow(ba.Window):
|
||||
"""Window for configuring plugins."""
|
||||
|
||||
def __del__(self) -> None:
|
||||
print('~PluginSettingsWindow()')
|
||||
|
||||
def __init__(self,
|
||||
transition: str = 'in_right',
|
||||
origin_widget: ba.Widget = None):
|
||||
print('PluginSettingsWindow()')
|
||||
|
||||
# pylint: disable=too-many-locals
|
||||
app = ba.app
|
||||
|
||||
# If they provided an origin-widget, scale up from that.
|
||||
@ -115,22 +111,29 @@ class PluginSettingsWindow(ba.Window):
|
||||
self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
|
||||
selection_loops_to_parent=True)
|
||||
|
||||
pluglist = [
|
||||
ba.AvailablePlugin(display_name=f'Test {i}',
|
||||
class_path='fakemodule') for i in range(10)
|
||||
]
|
||||
if ba.app.metascan is None:
|
||||
ba.screenmessage('Still scanning plugins; please try again.',
|
||||
color=(1, 0, 0))
|
||||
ba.playsound(ba.getsound('error'))
|
||||
pluglist = ba.app.potential_plugins
|
||||
plugstates: Dict[str, Dict] = ba.app.config.setdefault('Plugins', {})
|
||||
assert isinstance(plugstates, dict)
|
||||
for i, availplug in enumerate(pluglist):
|
||||
active = i % 3 < 2
|
||||
check = ba.checkboxwidget(parent=self._subcontainer,
|
||||
text=availplug.display_name,
|
||||
value=active,
|
||||
maxwidth=self._scroll_width - 100,
|
||||
size=(self._scroll_width - 40, 50),
|
||||
on_value_change_call=ba.Call(
|
||||
self._check_value_changed,
|
||||
availplug),
|
||||
textcolor=((0, 1, 0) if active else
|
||||
(0.6, 0.6, 0.6)))
|
||||
active = availplug.class_path in ba.app.active_plugins
|
||||
|
||||
plugstate = plugstates.setdefault(availplug.class_path, {})
|
||||
checked = plugstate.get('enabled', False)
|
||||
assert isinstance(checked, bool)
|
||||
check = ba.checkboxwidget(
|
||||
parent=self._subcontainer,
|
||||
text=availplug.display_name,
|
||||
value=checked,
|
||||
maxwidth=self._scroll_width - 100,
|
||||
size=(self._scroll_width - 40, 50),
|
||||
on_value_change_call=ba.Call(self._check_value_changed,
|
||||
availplug),
|
||||
textcolor=((0.8, 0.3, 0.3) if not availplug.available else
|
||||
(0, 1, 0) if active else (0.6, 0.6, 0.6)))
|
||||
|
||||
# Make sure we scroll all the way to the end when using
|
||||
# keyboard/button nav.
|
||||
@ -144,12 +147,16 @@ class PluginSettingsWindow(ba.Window):
|
||||
|
||||
self._restore_state()
|
||||
|
||||
def _check_value_changed(self, plug: ba.AvailablePlugin,
|
||||
def _check_value_changed(self, plug: ba.PotentialPlugin,
|
||||
value: bool) -> None:
|
||||
ba.screenmessage(
|
||||
ba.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
|
||||
color=(1.0, 0.5, 0.0))
|
||||
print(f'check value changed for {plug} to {value}')
|
||||
plugstates: Dict[str, Dict] = ba.app.config.setdefault('Plugins', {})
|
||||
assert isinstance(plugstates, dict)
|
||||
plugstate = plugstates.setdefault(plug.class_path, {})
|
||||
plugstate['enabled'] = value
|
||||
ba.app.config.commit()
|
||||
|
||||
def _save_state(self) -> None:
|
||||
pass
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<h4><em>last updated on 2020-07-21 for Ballistica version 1.5.23 build 20151</em></h4>
|
||||
<h4><em>last updated on 2020-07-22 for Ballistica version 1.5.23 build 20152</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,10 +150,10 @@
|
||||
<li><a href="#class_ba_App">ba.App</a></li>
|
||||
<li><a href="#class_ba_AppConfig">ba.AppConfig</a></li>
|
||||
<li><a href="#class_ba_AppDelegate">ba.AppDelegate</a></li>
|
||||
<li><a href="#class_ba_AvailablePlugin">ba.AvailablePlugin</a></li>
|
||||
<li><a href="#class_ba_Campaign">ba.Campaign</a></li>
|
||||
<li><a href="#class_ba_MusicPlayer">ba.MusicPlayer</a></li>
|
||||
<li><a href="#class_ba_Plugin">ba.Plugin</a></li>
|
||||
<li><a href="#class_ba_PotentialPlugin">ba.PotentialPlugin</a></li>
|
||||
<li><a href="#class_ba_ServerController">ba.ServerController</a></li>
|
||||
</ul>
|
||||
<h4><a name="class_category_User_Interface_Classes">User Interface Classes</a></h4>
|
||||
@ -1166,22 +1166,6 @@ when done.</p>
|
||||
|
||||
<p>Behavior is similar to <a href="#function_ba_gettexture">ba.gettexture</a>()</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2><strong><a name="class_ba_AvailablePlugin">ba.AvailablePlugin</a></strong></h3>
|
||||
<p><em><top level class></em>
|
||||
</p>
|
||||
<p>Defines a plugin which can potentially be loaded.</p>
|
||||
|
||||
<p>Category: <a href="#class_category_App_Classes">App Classes</a>
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_AvailablePlugin____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.AvailablePlugin(display_name: str, class_path: str)</span></p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
@ -4509,9 +4493,44 @@ the type-checker properly identifies the returned value as one.</p>
|
||||
</p>
|
||||
<p>A plugin to alter app behavior in some way.</p>
|
||||
|
||||
<p>Category: <a href="#class_category_App_Classes">App Classes</a>
|
||||
<p>Category: <a href="#class_category_App_Classes">App Classes</a></p>
|
||||
|
||||
<p> Plugins are discoverable by the meta-tag system
|
||||
and the user can select which ones they want to activate.
|
||||
Active plugins are then called at specific times as the
|
||||
app is running in order to modify its behavior in some way.
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_Plugin__on_app_launch">on_app_launch()</a></dt></h4><dd>
|
||||
<p><span>on_app_launch(self) -> None</span></p>
|
||||
|
||||
<p>Called when the app is being launched.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2><strong><a name="class_ba_PotentialPlugin">ba.PotentialPlugin</a></strong></h3>
|
||||
<p><em><top level class></em>
|
||||
</p>
|
||||
<p>Represents a <a href="#class_ba_Plugin">ba.Plugin</a> which can potentially be loaded.</p>
|
||||
|
||||
<p>Category: <a href="#class_category_App_Classes">App Classes</a></p>
|
||||
|
||||
<p> These generally represent plugins which were detected by the
|
||||
meta-tag scan. However they may also represent plugins which
|
||||
were previously set to be loaded but which were unable to be
|
||||
for some reason. In that case, 'available' will be set to False.
|
||||
</p>
|
||||
|
||||
<h3>Methods:</h3>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_PotentialPlugin____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.PotentialPlugin(display_name: <a href="#class_ba_Lstr">ba.Lstr</a>, class_path: str, available: bool)</span></p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2><strong><a name="class_ba_PowerupAcceptMessage">ba.PowerupAcceptMessage</a></strong></h3>
|
||||
<p><em><top level class></em>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user