diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 621ca6a..b4bf462 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.10"] + python-version: ["3.11"] steps: - uses: actions/checkout@v3 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 85ebd58..7b9fd57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## Plugin Manager (dd-mm-yyyy) +### 1.0.1 (30-06-2023) + +- Allow specifying branch names in custom sources. + +### 1.0.0 (20-06-2023) + +- Migrate plugin manager's source code to API 8. + ### 0.3.5 (16-06-2023) - Replace the "Loading..." text with the exception message in case something goes wrong. diff --git a/README.md b/README.md index c853fa2..fe057a9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ [![CI](https://github.com/bombsquad-community/plugin-manager/actions/workflows/ci.yml/badge.svg)](https://github.com/bombsquad-community/plugin-manager/actions/workflows/ci.yml) +**Important:** Please check out the [api7](https://github.com/bombsquad-community/plugin-manager/tree/api7) branch if you're +using the game version (1.7.0 <= your game version <= 1.7.19) which uses API 7 plugins. +If you're on game version (1.7.20 or a later version) where it uses API 8 plugins, then proceed with the rest of the +README here. + +------------------------------- + # plugin-manager A plugin manager for the game - [Bombsquad](https://www.froemling.net/apps/bombsquad). Plugin manager is a plugin in itself, @@ -177,6 +184,8 @@ That's it! Now you can make a [pull request](../../compare) with both the update - Check out [bombsquad-community/sample-plugin-source](https://github.com/bombsquad-community/sample-plugin-source) as an example. You can choose to show up plugins from this repository in your plugin manager by adding `bombsquad-community/sample-plugin-source` as a custom source through the category selection popup window in-game. +- Plugin manager will default to picking up plugins from the `main` branch of the custom source repository. You + can specify a different branch by suffixing the source URI with `@branchname`, such as `bombsquad-community/sample-plugin-source@experimental`. #### Known 3rd Party Plugin Sources diff --git a/index.json b/index.json index 3e3e90e..51896d5 100644 --- a/index.json +++ b/index.json @@ -1,6 +1,18 @@ { "plugin_manager_url": "https://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugin_manager.py", "versions": { + "1.0.1": { + "api_version": 8, + "commit_sha": "e31a789", + "released_on": "29-06-2023", + "md5sum": "e54913a789a31f60f18ef24edbfdd130" + }, + "1.0.0": { + "api_version": 8, + "commit_sha": "0b55bc2", + "released_on": "20-06-2023", + "md5sum": "98fa2f29c3a2d34b5ff53b7abde7ec64" + }, "0.3.5": { "api_version": 7, "commit_sha": "985e486", diff --git a/plugin_manager.py b/plugin_manager.py index ea83afe..dc8dbae 100644 --- a/plugin_manager.py +++ b/plugin_manager.py @@ -1,7 +1,9 @@ -# ba_meta require api 7 -import ba -import _ba -from bastd.ui import popup, confirm +# ba_meta require api 8 +from babase._meta import EXPORT_CLASS_NAME_SHORTCUTS +import babase +import _babase +import bauiv1 as bui +from bauiv1lib import popup, confirm import urllib.request import http.client @@ -17,47 +19,79 @@ import pathlib import contextlib import hashlib import copy +import traceback from typing import Union, Optional from datetime import datetime -_env = _ba.env() -_uiscale = ba.app.ui.uiscale +# Modules used for overriding AllSettingsWindow +from threading import Thread +import logging + +_env = _babase.env() +_uiscale = bui.app.ui_v1.uiscale -PLUGIN_MANAGER_VERSION = "0.3.5" +PLUGIN_MANAGER_VERSION = "1.0.1" REPOSITORY_URL = "https://github.com/bombsquad-community/plugin-manager" # Current tag can be changed to "staging" or any other branch in # plugin manager repo for testing purpose. CURRENT_TAG = "main" INDEX_META = "{repository_url}/{content_type}/{tag}/index.json" HEADERS = { - "User-Agent": _env["user_agent_string"], + "User-Agent": _env["legacy_user_agent_string"], } PLUGIN_DIRECTORY = _env["python_directory_user"] + + +def _regexp_friendly_class_name_shortcut(string): return string.replace(".", "\\.") + + REGEXP = { "plugin_api_version": re.compile(b"(?<=ba_meta require api )(.*)"), - "plugin_entry_points": re.compile(b"(ba_meta export plugin\n+class )(.*)\\("), - "minigames": re.compile(b"(ba_meta export game\n+class )(.*)\\("), + "plugin_entry_points": re.compile( + bytes( + "(ba_meta export (plugin|{})\n+class )(.*)\\(".format( + _regexp_friendly_class_name_shortcut(EXPORT_CLASS_NAME_SHORTCUTS["plugin"]), + ), + "utf-8" + ), + ), + "minigames": re.compile( + bytes( + "(ba_meta export ({})\n+class )(.*)\\(".format( + _regexp_friendly_class_name_shortcut("bascenev1.GameActivity"), + ), + "utf-8" + ), + ), } DISCORD_URL = "https://ballistica.net/discord" _CACHE = {} -class MD5CheckSumFailedError(Exception): +class MD5CheckSumFailed(Exception): pass -class PluginNotInstalledError(Exception): +class PluginNotInstalled(Exception): pass -class CategoryDoesNotExistError(Exception): +class CategoryDoesNotExist(Exception): pass -class NoCompatibleVersionError(Exception): +class NoCompatibleVersion(Exception): + pass + + +class PluginSourceNetworkError(Exception): + pass + + +class CategoryMetadataParseError(Exception): pass @@ -84,7 +118,7 @@ def stream_network_response_to_file(request, file, md5sum=None, retries=3): content += chunk if md5sum and hashlib.md5(content).hexdigest() != md5sum: if retries <= 0: - raise MD5CheckSumFailedError("MD5 checksum match failed.") + raise MD5CheckSumFailed("MD5 checksum match failed.") return stream_network_response_to_file( request, file, @@ -214,9 +248,9 @@ class StartupTasks: def setup_config(self): # is_config_updated = False existing_plugin_manager_config = copy.deepcopy( - ba.app.config.get("Community Plugin Manager")) + babase.app.config.get("Community Plugin Manager")) - plugin_manager_config = ba.app.config.setdefault("Community Plugin Manager", {}) + plugin_manager_config = babase.app.config.setdefault("Community Plugin Manager", {}) plugin_manager_config.setdefault("Custom Sources", []) installed_plugins = plugin_manager_config.setdefault("Installed Plugins", {}) for plugin_name in tuple(installed_plugins.keys()): @@ -240,26 +274,26 @@ class StartupTasks: plugin_manager_config["Settings"] = current_settings if plugin_manager_config != existing_plugin_manager_config: - ba.app.config.commit() + babase.app.config.commit() async def update_plugin_manager(self): - if not ba.app.config["Community Plugin Manager"]["Settings"]["Auto Update Plugin Manager"]: + if not babase.app.config["Community Plugin Manager"]["Settings"]["Auto Update Plugin Manager"]: return update_details = await self.plugin_manager.get_update_details() if update_details: to_version, commit_sha = update_details - ba.screenmessage(f"Plugin Manager is being updated to v{to_version}") + bui.screenmessage(f"Plugin Manager is being updated to v{to_version}") try: await self.plugin_manager.update(to_version, commit_sha) - except MD5CheckSumFailedError: - ba.playsound(ba.getsound('error')) + except MD5CheckSumFailed: + bui.getsound('error').play() else: - ba.screenmessage("Update successful. Restart game to reload changes.", - color=(0, 1, 0)) - ba.playsound(ba.getsound('shieldUp')) + bui.screenmessage("Update successful. Restart game to reload changes.", + color=(0, 1, 0)) + bui.getsound('shieldUp').play() async def update_plugins(self): - if not ba.app.config["Community Plugin Manager"]["Settings"]["Auto Update Plugins"]: + if not babase.app.config["Community Plugin Manager"]["Settings"]["Auto Update Plugins"]: return await self.plugin_manager.setup_index() all_plugins = await self.plugin_manager.categories["All"].get_plugins() @@ -276,22 +310,22 @@ class StartupTasks: return False try: plugin.latest_compatible_version - except NoCompatibleVersionError: + except NoCompatibleVersion: return False else: return True async def notify_new_plugins(self): - if not ba.app.config["Community Plugin Manager"]["Settings"]["Notify New Plugins"]: + if not babase.app.config["Community Plugin Manager"]["Settings"]["Notify New Plugins"]: return await self.plugin_manager.setup_index() new_num_of_plugins = len(await self.plugin_manager.categories["All"].get_plugins()) try: - existing_num_of_plugins = ba.app.config["Community Plugin Manager"]["Existing Number of Plugins"] + existing_num_of_plugins = babase.app.config["Community Plugin Manager"]["Existing Number of Plugins"] except KeyError: - ba.app.config["Community Plugin Manager"]["Existing Number of Plugins"] = new_num_of_plugins - ba.app.config.commit() + babase.app.config["Community Plugin Manager"]["Existing Number of Plugins"] = new_num_of_plugins + babase.app.config.commit() return if existing_num_of_plugins < new_num_of_plugins: @@ -310,11 +344,11 @@ class StartupTasks: notification_text = f"{new_supported_plugins_count} new plugin ({new_supported_plugins}) is available!" else: notification_text = f"{new_supported_plugins_count} new plugins ({new_supported_plugins}) are available!" - ba.screenmessage(notification_text, color=(0, 1, 0)) + bui.screenmessage(notification_text, color=(0, 1, 0)) if existing_num_of_plugins != new_num_of_plugins: - ba.app.config["Community Plugin Manager"]["Existing Number of Plugins"] = new_num_of_plugins - ba.app.config.commit() + babase.app.config["Community Plugin Manager"]["Existing Number of Plugins"] = new_num_of_plugins + babase.app.config.commit() async def execute(self): self.setup_config() @@ -329,9 +363,9 @@ class StartupTasks: class Category: - def __init__(self, meta_url, is_3rd_party=False): + def __init__(self, meta_url, tag=CURRENT_TAG): self.meta_url = meta_url - self.is_3rd_party = is_3rd_party + self.tag = tag self.request_headers = HEADERS self._metadata = _CACHE.get("categories", {}).get(meta_url, {}).get("metadata") self._plugins = _CACHE.get("categories", {}).get(meta_url, {}).get("plugins") @@ -340,9 +374,8 @@ class Category: if self._metadata is None: # Let's keep depending on the "main" branch for 3rd party sources # even if we're using a different branch of plugin manager's repository. - tag = "main" if self.is_3rd_party else CURRENT_TAG request = urllib.request.Request( - self.meta_url.format(content_type="raw", tag=tag), + self.meta_url.format(content_type="raw", tag=self.tag), headers=self.request_headers, ) response = await async_send_network_request(request) @@ -350,11 +383,13 @@ class Category: self.set_category_global_cache("metadata", self._metadata) return self - async def is_valid(self): + async def validate(self): try: await self.fetch_metadata() - except urllib.error.HTTPError: - return False + except urllib.error.HTTPError as e: + raise PluginSourceNetworkError(str(e)) + except json.decoder.JSONDecodeError as e: + raise CategoryMetadataParseError(f"Failed to parse JSON: {str(e)}") try: await asyncio.gather( self.get_name(), @@ -363,7 +398,7 @@ class Category: self.get_plugins(), ) except KeyError: - return False + raise CategoryMetadataParseError(f"Failed to parse JSON; missing required fields.") else: return True @@ -386,7 +421,7 @@ class Category: Plugin( plugin_info, f"{await self.get_plugins_base_url()}/{plugin_info[0]}.py", - is_3rd_party=self.is_3rd_party, + tag=self.tag, ) for plugin_info in self._metadata["plugins"].items() ]) @@ -416,8 +451,8 @@ class Category: await self.get_plugins() def save(self): - ba.app.config["Community Plugin Manager"]["Custom Sources"].append(self.meta_url) - ba.app.config.commit() + babase.app.config["Community Plugin Manager"]["Custom Sources"].append(self.meta_url) + babase.app.config.commit() class CategoryAll(Category): @@ -450,11 +485,11 @@ class PluginLocal: @property def is_installed_via_plugin_manager(self): - return self.name in ba.app.config["Community Plugin Manager"]["Installed Plugins"] + return self.name in babase.app.config["Community Plugin Manager"]["Installed Plugins"] def initialize(self): - if self.name not in ba.app.config["Community Plugin Manager"]["Installed Plugins"]: - ba.app.config["Community Plugin Manager"]["Installed Plugins"][self.name] = {} + if self.name not in babase.app.config["Community Plugin Manager"]["Installed Plugins"]: + babase.app.config["Community Plugin Manager"]["Installed Plugins"][self.name] = {} return self async def uninstall(self): @@ -465,7 +500,7 @@ class PluginLocal: except FileNotFoundError: pass try: - del ba.app.config["Community Plugin Manager"]["Installed Plugins"][self.name] + del babase.app.config["Community Plugin Manager"]["Installed Plugins"][self.name] except KeyError: pass else: @@ -474,7 +509,7 @@ class PluginLocal: @property def version(self): try: - version = (ba.app.config["Community Plugin Manager"] + version = (babase.app.config["Community Plugin Manager"] ["Installed Plugins"][self.name]["version"]) except KeyError: version = None @@ -489,19 +524,19 @@ class PluginLocal: fout.write(content) def has_settings(self): - for plugin_entry_point, plugin_class in ba.app.plugins.active_plugins.items(): + for plugin_entry_point, plugin_spec in bui.app.plugins.plugin_specs.items(): if plugin_entry_point.startswith(self._entry_point_initials): - return plugin_class.has_settings_ui() + return plugin_spec.plugin.has_settings_ui() def launch_settings(self, source_widget): - for plugin_entry_point, plugin_class in ba.app.plugins.active_plugins.items(): + for plugin_entry_point, plugin_spec in bui.app.plugins.plugin_specs.items(): if plugin_entry_point.startswith(self._entry_point_initials): - return plugin_class.show_settings_ui(source_widget) + return plugin_spec.plugin.show_settings_ui(source_widget) async def get_content(self): if self._content is None: if not self.is_installed: - raise PluginNotInstalledError("Plugin is not available locally.") + raise PluginNotInstalled("Plugin is not available locally.") loop = asyncio.get_event_loop() self._content = await loop.run_in_executor(None, self._get_content) return self._content @@ -516,8 +551,8 @@ class PluginLocal: if not self._entry_points: content = await self.get_content() groups = REGEXP["plugin_entry_points"].findall(content) - # Actual entry points are stored in the first index inside the matching groups. - entry_points = tuple(f"{self.name}.{group[1].decode('utf-8')}" for group in groups) + # Actual entry points are stored in the last index inside the matching groups. + entry_points = tuple(f"{self.name}.{group[-1].decode('utf-8')}" for group in groups) self._entry_points = entry_points return self._entry_points @@ -532,32 +567,32 @@ class PluginLocal: return len(entry_points) > 0 def load_minigames(self): - scanner = ba._meta.DirectoryScan(paths="") + scanner = babase._meta.DirectoryScan(paths="") directory, module = self.install_path.rsplit(os.path.sep, 1) scanner._scan_module( pathlib.Path(directory), pathlib.Path(module), ) - scanned_results = set(ba.app.meta.scanresults.exports["ba.GameActivity"]) - for game in scanner.results.exports["ba.GameActivity"]: + scanned_results = set(babase.app.meta.scanresults.exports["bascenev1.GameActivity"]) + for game in scanner.results.exports["bascenev1.GameActivity"]: if game not in scanned_results: - ba.screenmessage(f"{game} minigame loaded") - ba.app.meta.scanresults.exports["ba.GameActivity"].append(game) + bui.screenmessage(f"{game} minigame loaded") + babase.app.meta.scanresults.exports["bascenev1.GameActivity"].append(game) def unload_minigames(self): - scanner = ba._meta.DirectoryScan(paths="") + scanner = babase._meta.DirectoryScan(paths="") directory, module = self.install_path.rsplit(os.path.sep, 1) scanner._scan_module( pathlib.Path(directory), pathlib.Path(module), ) new_scanned_results_games = [] - for game in ba.app.meta.scanresults.exports["ba.GameActivity"]: - if game in scanner.results.exports["ba.GameActivity"]: - ba.screenmessage(f"{game} minigame unloaded") + for game in babase.app.meta.scanresults.exports["bascenev1.GameActivity"]: + if game in scanner.results.exports["bascenev1.GameActivity"]: + bui.screenmessage(f"{game} minigame unloaded") else: new_scanned_results_games.append(game) - ba.app.meta.scanresults.exports["ba.GameActivity"] = new_scanned_results_games + babase.app.meta.scanresults.exports["bascenev1.GameActivity"] = new_scanned_results_games async def is_enabled(self): """ @@ -565,13 +600,13 @@ class PluginLocal: """ if not await self.has_plugins(): return True - for entry_point, plugin_info in ba.app.config["Plugins"].items(): + for entry_point, plugin_info in babase.app.config["Plugins"].items(): if entry_point.startswith(self._entry_point_initials) and plugin_info["enabled"]: return True # XXX: The below logic is more accurate but less efficient, since it actually # reads the local plugin file and parses entry points from it. # for entry_point in await self.get_entry_points(): - # if ba.app.config["Plugins"][entry_point]["enabled"]: + # if babase.app.config["Plugins"][entry_point]["enabled"]: # return True return False @@ -579,31 +614,37 @@ class PluginLocal: # own separate logic. # async def _set_status(self, to_enable=True): # for entry_point in await self.get_entry_points: - # if entry_point not in ba.app.config["Plugins"]: - # ba.app.config["Plugins"][entry_point] = {} - # ba.app.config["Plugins"][entry_point]["enabled"] = to_enable + # if entry_point not in babase.app.config["Plugins"]: + # babase.app.config["Plugins"][entry_point] = {} + # babase.app.config["Plugins"][entry_point]["enabled"] = to_enable async def enable(self): for entry_point in await self.get_entry_points(): - if entry_point not in ba.app.config["Plugins"]: - ba.app.config["Plugins"][entry_point] = {} - ba.app.config["Plugins"][entry_point]["enabled"] = True - if entry_point not in ba.app.plugins.active_plugins: + if entry_point not in babase.app.config["Plugins"]: + babase.app.config["Plugins"][entry_point] = {} + babase.app.config["Plugins"][entry_point]["enabled"] = True + plugin_spec = bui.app.plugins.plugin_specs.get(entry_point) + if plugin_spec not in bui.app.plugins.active_plugins: self.load_plugin(entry_point) - ba.screenmessage(f"{entry_point} loaded") + bui.screenmessage(f"{entry_point} loaded") if await self.has_minigames(): self.load_minigames() # await self._set_status(to_enable=True) self.save() def load_plugin(self, entry_point): - plugin_class = ba._general.getclass(entry_point, ba.Plugin) - loaded_plugin_class = plugin_class() - loaded_plugin_class.on_app_running() - ba.app.plugins.active_plugins[entry_point] = loaded_plugin_class + plugin_class = babase._general.getclass(entry_point, babase.Plugin) + loaded_plugin_instance = plugin_class() + loaded_plugin_instance.on_app_running() + + plugin_spec = babase.PluginSpec(class_path=entry_point, loadable=True) + plugin_spec.enabled = True + plugin_spec.plugin = loaded_plugin_instance + bui.app.plugins.plugin_specs[entry_point] = plugin_spec + bui.app.plugins.active_plugins.append(plugin_spec.plugin) def disable(self): - for entry_point, plugin_info in ba.app.config["Plugins"].items(): + for entry_point, plugin_info in babase.app.config["Plugins"].items(): if entry_point.startswith(self._entry_point_initials): # if plugin_info["enabled"]: plugin_info["enabled"] = False @@ -613,17 +654,17 @@ class PluginLocal: self.save() def set_version(self, version): - app = ba.app + app = babase.app app.config["Community Plugin Manager"]["Installed Plugins"][self.name]["version"] = version return self # def set_entry_points(self): - # if not "entry_points" in ba.app.config["Community Plugin Manager"] + # if not "entry_points" in babase.app.config["Community Plugin Manager"] # ["Installed Plugins"][self.name]: - # ba.app.config["Community Plugin Manager"]["Installed Plugins"] + # babase.app.config["Community Plugin Manager"]["Installed Plugins"] # [self.name]["entry_points"] = [] # for entry_point in await self.get_entry_points(): - # ba.app.config["Community Plugin Manager"]["Installed Plugins"][self.name] + # babase.app.config["Community Plugin Manager"]["Installed Plugins"][self.name] # ["entry_points"].append(entry_point) async def set_content(self, content): @@ -644,12 +685,12 @@ class PluginLocal: return self._content def save(self): - ba.app.config.commit() + babase.app.config.commit() return self class PluginVersion: - def __init__(self, plugin, version, tag=None): + def __init__(self, plugin, version, tag=CURRENT_TAG): self.number, info = version self.plugin = plugin self.api_version = info["api_version"] @@ -657,10 +698,8 @@ class PluginVersion: self.commit_sha = info["commit_sha"] self.md5sum = info["md5sum"] - if tag is None: - tag = self.commit_sha - self.download_url = self.plugin.url.format(content_type="raw", tag=tag) + print(self.download_url) self.view_url = self.plugin.url.format(content_type="blob", tag=tag) def __eq__(self, plugin_version): @@ -688,35 +727,29 @@ class PluginVersion: async def install(self, suppress_screenmessage=False): try: local_plugin = await self._download() - except MD5CheckSumFailedError: + except MD5CheckSumFailed: if not suppress_screenmessage: - ba.screenmessage( + bui.screenmessage( f"{self.plugin.name} failed MD5 checksum during installation", color=(1, 0, 0)) return False else: if not suppress_screenmessage: - ba.screenmessage(f"{self.plugin.name} installed", color=(0, 1, 0)) - check = ba.app.config["Community Plugin Manager"]["Settings"] + bui.screenmessage(f"{self.plugin.name} installed", color=(0, 1, 0)) + check = babase.app.config["Community Plugin Manager"]["Settings"] if check["Auto Enable Plugins After Installation"]: await local_plugin.enable() return True class Plugin: - def __init__(self, plugin, url, is_3rd_party=False): + def __init__(self, plugin, url, tag=CURRENT_TAG): """ Initialize a plugin from network repository. """ self.name, self.info = plugin - self.is_3rd_party = is_3rd_party self.install_path = os.path.join(PLUGIN_DIRECTORY, f"{self.name}.py") - # if is_3rd_party: - # tag = CURRENT_TAG - # else: - # tag = CURRENT_TAG - tag = CURRENT_TAG self.url = url - self.download_url = url.format(content_type="raw", tag=tag) + self.tag = tag self._local_plugin = None self._versions = None @@ -748,6 +781,7 @@ class Plugin: PluginVersion( self, version, + tag=self.tag, ) for version in self.info["versions"].items() ] return self._versions @@ -758,7 +792,7 @@ class Plugin: self._latest_version = PluginVersion( self, tuple(self.info["versions"].items())[0], - tag=CURRENT_TAG, + tag=self.tag, ) return self._latest_version @@ -766,22 +800,22 @@ class Plugin: def latest_compatible_version(self): if self._latest_compatible_version is None: for number, info in self.info["versions"].items(): - if info["api_version"] == ba.app.api_version: + if info["api_version"] == babase.app.api_version: self._latest_compatible_version = PluginVersion( self, (number, info), - CURRENT_TAG if self.latest_version.number == number else None + tag=self.tag if self.latest_version.number == number else info["commit_sha"] ) break if self._latest_compatible_version is None: - raise NoCompatibleVersionError( - f"{self.name} has no version compatible with API {ba.app.api_version}." + raise NoCompatibleVersion( + f"{self.name} has no version compatible with API {babase.app.api_version}." ) return self._latest_compatible_version def get_local(self): if not self.is_installed: - raise PluginNotInstalledError( + raise PluginNotInstalled( f"{self.name} needs to be installed to get its local plugin.") if self._local_plugin is None: self._local_plugin = PluginLocal(self.name) @@ -795,26 +829,26 @@ class Plugin: async def uninstall(self): await self.get_local().uninstall() - ba.screenmessage(f"{self.name} uninstalled", color=(0.9, 1, 0)) + bui.screenmessage(f"{self.name} uninstalled", color=(0.9, 1, 0)) def has_update(self): try: latest_compatible_version = self.latest_compatible_version - except NoCompatibleVersionError: + except NoCompatibleVersion: return False else: return self.get_local().version != latest_compatible_version.number async def update(self): if await self.latest_compatible_version.install(suppress_screenmessage=True): - ba.screenmessage(f"{self.name} updated to {self.latest_compatible_version.number}", - color=(0, 1, 0)) - ba.playsound(ba.getsound('shieldUp')) + bui.screenmessage(f"{self.name} updated to {self.latest_compatible_version.number}", + color=(0, 1, 0)) + bui.getsound('shieldUp').play() else: - ba.screenmessage(f"{self.name} failed MD5 checksum while updating to " - f"{self.latest_compatible_version.number}", - color=(1, 0, 0)) - ba.playsound(ba.getsound('error')) + bui.screenmessage(f"{self.name} failed MD5 checksum while updating to " + f"{self.latest_compatible_version.number}", + color=(1, 0, 0)) + bui.getsound('error').play() class PluginWindow(popup.PopupWindow): @@ -849,11 +883,9 @@ class PluginWindow(popup.PopupWindow): return partitioned_string async def draw_ui(self): - # print(ba.app.plugins.active_plugins) - - ba.playsound(ba.getsound('swish')) + bui.getsound('swish').play() b_text_color = (0.75, 0.7, 0.8) - s = 1.25 if _uiscale is ba.UIScale.SMALL else 1.39 if ba.UIScale.MEDIUM else 1.67 + s = 1.25 if _uiscale is babase.UIScale.SMALL else 1.39 if babase.UIScale.MEDIUM else 1.67 width = 400 * s height = 120 + 100 * s color = (1, 1, 1) @@ -861,46 +893,46 @@ class PluginWindow(popup.PopupWindow): self._transition_out = 'out_scale' transition = 'in_scale' - self._root_widget = ba.containerwidget(size=(width, height), - # parent=_ba.get_special_widget( - # 'overlay_stack'), - on_outside_click_call=self._cancel, - transition=transition, - scale=(2.1 if _uiscale is ba.UIScale.SMALL else 1.5 - if _uiscale is ba.UIScale.MEDIUM else 1.0), - scale_origin_stack_offset=self.scale_origin) + self._root_widget = bui.containerwidget(size=(width, height), + # parent=_babase.get_special_widget( + # 'overlay_stack'), + on_outside_click_call=self._cancel, + transition=transition, + scale=(2.1 if _uiscale is babase.UIScale.SMALL else 1.5 + if _uiscale is babase.UIScale.MEDIUM else 1.0), + scale_origin_stack_offset=self.scale_origin) pos = height * 0.8 plugin_title = f"{self.plugin.name} (v{self.plugin.latest_compatible_version.number})" - ba.textwidget(parent=self._root_widget, - position=(width * 0.49, pos), size=(0, 0), - h_align='center', v_align='center', text=plugin_title, - scale=text_scale * 1.25, color=color, - maxwidth=width * 0.9) + bui.textwidget(parent=self._root_widget, + position=(width * 0.49, pos), size=(0, 0), + h_align='center', v_align='center', text=plugin_title, + scale=text_scale * 1.25, color=color, + maxwidth=width * 0.9) pos -= 25 # author = - ba.textwidget(parent=self._root_widget, - position=(width * 0.49, pos), - size=(0, 0), - h_align='center', - v_align='center', - text='by ' + self.plugin.info["authors"][0]["name"], - scale=text_scale * 0.8, - color=color, maxwidth=width * 0.9) + bui.textwidget(parent=self._root_widget, + position=(width * 0.49, pos), + size=(0, 0), + h_align='center', + v_align='center', + text='by ' + self.plugin.info["authors"][0]["name"], + scale=text_scale * 0.8, + color=color, maxwidth=width * 0.9) pos -= 35 - # status = ba.textwidget(parent=self._root_widget, + # status = bui.textwidget(parent=self._root_widget, # position=(width * 0.49, pos), size=(0, 0), # h_align='center', v_align='center', # text=status_text, scale=text_scale * 0.8, # color=color, maxwidth=width * 0.9) pos -= 25 # info = - ba.textwidget(parent=self._root_widget, - position=(width * 0.49, pos), size=(0, 0), - h_align='center', v_align='center', - text=self.get_description(), - scale=text_scale * 0.6, color=color, - maxwidth=width * 0.95) + bui.textwidget(parent=self._root_widget, + position=(width * 0.49, pos), size=(0, 0), + h_align='center', v_align='center', + text=self.get_description(), + scale=text_scale * 0.6, color=color, + maxwidth=width * 0.95) b1_color = None b2_color = (0.8, 0.15, 0.35) b3_color = (0.2, 0.8, 0.3) @@ -934,69 +966,69 @@ class PluginWindow(popup.PopupWindow): button1_action = self.install if to_draw_button1: - ba.buttonwidget(parent=self._root_widget, - position=(width * 0.1, pos), - size=button_size, - on_activate_call=button1_action, - color=b1_color, - textcolor=b_text_color, - button_type='square', - text_scale=1, - label=button1_label) + bui.buttonwidget(parent=self._root_widget, + position=(width * 0.1, pos), + size=button_size, + on_activate_call=button1_action, + color=b1_color, + textcolor=b_text_color, + button_type='square', + text_scale=1, + label=button1_label) if self.plugin.is_installed: - ba.buttonwidget(parent=self._root_widget, - position=(width * 0.4, pos), - size=button_size, - on_activate_call=button2_action, - color=b2_color, - textcolor=b_text_color, - button_type='square', - text_scale=1, - label=button2_label) + bui.buttonwidget(parent=self._root_widget, + position=(width * 0.4, pos), + size=button_size, + on_activate_call=button2_action, + color=b2_color, + textcolor=b_text_color, + button_type='square', + text_scale=1, + label=button2_label) if has_update: # button3 = - ba.buttonwidget(parent=self._root_widget, - position=(width * 0.7, pos), - size=button_size, - on_activate_call=button3_action, - color=b3_color, - textcolor=b_text_color, - autoselect=True, - button_type='square', - text_scale=1, - label=button3_label) - ba.containerwidget(edit=self._root_widget, - on_cancel_call=self._cancel) + bui.buttonwidget(parent=self._root_widget, + position=(width * 0.7, pos), + size=button_size, + on_activate_call=button3_action, + color=b3_color, + textcolor=b_text_color, + autoselect=True, + button_type='square', + text_scale=1, + label=button3_label) + bui.containerwidget(edit=self._root_widget, + on_cancel_call=self._cancel) - open_pos_x = (390 if _uiscale is ba.UIScale.SMALL else - 450 if _uiscale is ba.UIScale.MEDIUM else 440) - open_pos_y = (100 if _uiscale is ba.UIScale.SMALL else - 110 if _uiscale is ba.UIScale.MEDIUM else 120) - open_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(open_pos_x, open_pos_y), - size=(40, 40), - button_type="square", - label="", - # color=ba.app.ui.title_color, - color=(0.6, 0.53, 0.63), - on_activate_call=lambda: ba.open_url(self.plugin.view_url)) - ba.imagewidget(parent=self._root_widget, - position=(open_pos_x, open_pos_y), - size=(40, 40), - color=(0.8, 0.95, 1), - texture=ba.gettexture("file"), - draw_controller=open_button) - ba.textwidget(parent=self._root_widget, - position=(open_pos_x-3, open_pos_y+12), - text="Source", - size=(10, 10), - draw_controller=open_button, - color=(1, 1, 1, 1), - rotate=25, - scale=0.45) + open_pos_x = (390 if _uiscale is babase.UIScale.SMALL else + 450 if _uiscale is babase.UIScale.MEDIUM else 440) + open_pos_y = (100 if _uiscale is babase.UIScale.SMALL else + 110 if _uiscale is babase.UIScale.MEDIUM else 120) + open_button = bui.buttonwidget(parent=self._root_widget, + autoselect=True, + position=(open_pos_x, open_pos_y), + size=(40, 40), + button_type="square", + label="", + # color=bui.app.ui_v1.title_color, + color=(0.6, 0.53, 0.63), + on_activate_call=lambda: bui.open_url(self.plugin.view_url)) + bui.imagewidget(parent=self._root_widget, + position=(open_pos_x, open_pos_y), + size=(40, 40), + color=(0.8, 0.95, 1), + texture=bui.gettexture("file"), + draw_controller=open_button) + bui.textwidget(parent=self._root_widget, + position=(open_pos_x-3, open_pos_y+12), + text="Source", + size=(10, 10), + draw_controller=open_button, + color=(1, 1, 1, 1), + rotate=25, + scale=0.45) # Below snippet handles the tutorial button in the plugin window tutorial_url = self.plugin.info["external_url"] @@ -1005,69 +1037,69 @@ class PluginWindow(popup.PopupWindow): text = "This will take you to \n\""+self.plugin.info["external_url"] + "\"" tutorial_confirm_window = confirm.ConfirmWindow( text=text, - action=lambda: ba.open_url(self.plugin.info["external_url"]), + action=lambda: bui.open_url(self.plugin.info["external_url"]), ) - open_pos_x = (440 if _uiscale is ba.UIScale.SMALL else - 500 if _uiscale is ba.UIScale.MEDIUM else 490) - open_pos_y = (100 if _uiscale is ba.UIScale.SMALL else - 110 if _uiscale is ba.UIScale.MEDIUM else 120) - open_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(open_pos_x, open_pos_y), - size=(40, 40), - button_type="square", - label="", - # color=ba.app.ui.title_color, - color=(0.6, 0.53, 0.63), + open_pos_x = (440 if _uiscale is babase.UIScale.SMALL else + 500 if _uiscale is babase.UIScale.MEDIUM else 490) + open_pos_y = (100 if _uiscale is babase.UIScale.SMALL else + 110 if _uiscale is babase.UIScale.MEDIUM else 120) + open_button = bui.buttonwidget(parent=self._root_widget, + autoselect=True, + position=(open_pos_x, open_pos_y), + size=(40, 40), + button_type="square", + label="", + # color=bui.app.ui_v1.title_color, + color=(0.6, 0.53, 0.63), - on_activate_call=tutorial_confirm_window) + on_activate_call=tutorial_confirm_window) - ba.imagewidget(parent=self._root_widget, - position=(open_pos_x, open_pos_y), - size=(40, 40), - color=(0.8, 0.95, 1), - texture=ba.gettexture("frameInset"), - draw_controller=open_button) - ba.textwidget(parent=self._root_widget, - position=(open_pos_x - 3, open_pos_y + 12), - text="Tutorial", - size=(10, 10), - draw_controller=open_button, - color=(1, 1, 1, 1), - rotate=25, - scale=0.45) + bui.imagewidget(parent=self._root_widget, + position=(open_pos_x, open_pos_y), + size=(40, 40), + color=(0.8, 0.95, 1), + texture=bui.gettexture("frameInset"), + draw_controller=open_button) + bui.textwidget(parent=self._root_widget, + position=(open_pos_x - 3, open_pos_y + 12), + text="Tutorial", + size=(10, 10), + draw_controller=open_button, + color=(1, 1, 1, 1), + rotate=25, + scale=0.45) if to_draw_button4: - settings_pos_x = (60 if _uiscale is ba.UIScale.SMALL else - 60 if _uiscale is ba.UIScale.MEDIUM else 60) - settings_pos_y = (100 if _uiscale is ba.UIScale.SMALL else - 110 if _uiscale is ba.UIScale.MEDIUM else 120) - settings_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(settings_pos_x, settings_pos_y), - size=(40, 40), - button_type="square", - label="", - color=(0, 0.75, 0.75),) - ba.buttonwidget( + settings_pos_x = (60 if _uiscale is babase.UIScale.SMALL else + 60 if _uiscale is babase.UIScale.MEDIUM else 60) + settings_pos_y = (100 if _uiscale is babase.UIScale.SMALL else + 110 if _uiscale is babase.UIScale.MEDIUM else 120) + settings_button = bui.buttonwidget(parent=self._root_widget, + autoselect=True, + position=(settings_pos_x, settings_pos_y), + size=(40, 40), + button_type="square", + label="", + color=(0, 0.75, 0.75),) + bui.buttonwidget( edit=settings_button, - on_activate_call=ba.Call(self.settings, settings_button),) - ba.imagewidget(parent=self._root_widget, - position=(settings_pos_x, settings_pos_y), - size=(40, 40), - color=(0.8, 0.95, 1), - texture=ba.gettexture("settingsIcon"), - draw_controller=settings_button) + on_activate_call=babase.Call(self.settings, settings_button),) + bui.imagewidget(parent=self._root_widget, + position=(settings_pos_x, settings_pos_y), + size=(40, 40), + color=(0.8, 0.95, 1), + texture=bui.gettexture("settingsIcon"), + draw_controller=settings_button) - # ba.containerwidget(edit=self._root_widget, selected_child=button3) - # ba.containerwidget(edit=self._root_widget, start_button=button3) + # bui.containerwidget(edit=self._root_widget, selected_child=button3) + # bui.containerwidget(edit=self._root_widget, start_button=button3) def _ok(self) -> None: - ba.containerwidget(edit=self._root_widget, transition='out_scale') + bui.containerwidget(edit=self._root_widget, transition='out_scale') def _cancel(self) -> None: - ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self._root_widget, transition='out_scale') + bui.getsound('swish').play() + bui.containerwidget(edit=self._root_widget, transition='out_scale') def button(fn): async def asyncio_handler(fn, self, *args, **kwargs): @@ -1095,22 +1127,22 @@ class PluginWindow(popup.PopupWindow): @button async def enable(self) -> None: await self.local_plugin.enable() - ba.playsound(ba.getsound('gunCocking')) + bui.getsound('gunCocking').play() @button async def install(self): await self.plugin.latest_compatible_version.install() - ba.playsound(ba.getsound('cashRegister2')) + bui.getsound('cashRegister2').play() @button async def uninstall(self): await self.plugin.uninstall() - ba.playsound(ba.getsound('shieldDown')) + bui.getsound('shieldDown').play() @button async def update(self): await self.plugin.update() - ba.playsound(ba.getsound('shieldUp')) + bui.getsound('shieldUp').play() class PluginManager: @@ -1152,14 +1184,22 @@ class PluginManager: self.categories["All"] = None requests = [] - for plugin_category_url in plugin_index["categories"]: - category = Category(plugin_category_url) + for meta_url in plugin_index["categories"]: + category = Category(meta_url) request = category.fetch_metadata() requests.append(request) - for repository in ba.app.config["Community Plugin Manager"]["Custom Sources"]: - plugin_category_url = partial_format(plugin_index["external_source_url"], - repository=repository) - category = Category(plugin_category_url, is_3rd_party=True) + for source in babase.app.config["Community Plugin Manager"]["Custom Sources"]: + source_splits = source.split("@", maxsplit=1) + if len(source_splits) == 1: + # Fallack to `main` if `@branchname` isn't specified in an external source URI. + source_repo, source_tag = source_splits[0], "main" + else: + source_repo, source_tag = source_splits + meta_url = partial_format( + plugin_index["external_source_url"], + repository=source_repo, + ) + category = Category(meta_url, tag=source_tag) request = category.fetch_metadata() requests.append(request) categories = await asyncio.gather(*requests) @@ -1194,7 +1234,7 @@ class PluginManager: async def get_update_details(self): index = await self.get_index() for version, info in index["versions"].items(): - if info["api_version"] != ba.app.api_version: + if info["api_version"] != babase.app.api_version: # No point checking a version of the API game doesn't support. continue if version == PLUGIN_MANAGER_VERSION: @@ -1222,7 +1262,7 @@ class PluginManager: response = await async_send_network_request(download_url) content = response.read() if hashlib.md5(content).hexdigest() != to_version_info["md5sum"]: - raise MD5CheckSumFailedError("MD5 checksum failed during plugin manager update.") + raise MD5CheckSumFailed("MD5 checksum failed during plugin manager update.") with open(self.module_path, "wb") as fout: fout.write(content) return to_version_info @@ -1238,74 +1278,74 @@ class PluginSourcesWindow(popup.PopupWindow): self.scale_origin = origin_widget.get_screen_space_center() b_textcolor = (0.75, 0.7, 0.8) - # s = 1.1 if _uiscale is ba.UIScale.SMALL else 1.27 if ba.UIScale.MEDIUM else 1.57 + # s = 1.1 if _uiscale is babase.UIScale.SMALL else 1.27 if babase.UIScale.MEDIUM else 1.57 # text_scale = 0.7 * s self._transition_out = 'out_scale' transition = 'in_scale' - self._root_widget = ba.containerwidget(size=(400, 340), - # parent=_ba.get_special_widget( - # 'overlay_stack'), - on_outside_click_call=self._ok, - transition=transition, - scale=(2.1 if _uiscale is ba.UIScale.SMALL else 1.5 - if _uiscale is ba.UIScale.MEDIUM else 1.0), - scale_origin_stack_offset=self.scale_origin, - on_cancel_call=self._ok) + self._root_widget = bui.containerwidget(size=(400, 340), + # parent=_babase.get_special_widget( + # 'overlay_stack'), + on_outside_click_call=self._ok, + transition=transition, + scale=(2.1 if _uiscale is babase.UIScale.SMALL else 1.5 + if _uiscale is babase.UIScale.MEDIUM else 1.0), + scale_origin_stack_offset=self.scale_origin, + on_cancel_call=self._ok) - ba.textwidget( + bui.textwidget( parent=self._root_widget, position=(155, 300), size=(100, 25), text="Custom Plugin Sources", - color=ba.app.ui.title_color, + color=bui.app.ui_v1.title_color, scale=0.8, h_align="center", v_align="center", maxwidth=270, ) - scroll_size_x = (290 if _uiscale is ba.UIScale.SMALL else - 300 if _uiscale is ba.UIScale.MEDIUM else 290) - scroll_size_y = (170 if _uiscale is ba.UIScale.SMALL else - 185 if _uiscale is ba.UIScale.MEDIUM else 180) - scroll_pos_x = (55 if _uiscale is ba.UIScale.SMALL else - 40 if _uiscale is ba.UIScale.MEDIUM else 60) + scroll_size_x = (290 if _uiscale is babase.UIScale.SMALL else + 300 if _uiscale is babase.UIScale.MEDIUM else 290) + scroll_size_y = (170 if _uiscale is babase.UIScale.SMALL else + 185 if _uiscale is babase.UIScale.MEDIUM else 180) + scroll_pos_x = (55 if _uiscale is babase.UIScale.SMALL else + 40 if _uiscale is babase.UIScale.MEDIUM else 60) scroll_pos_y = 105 - self._scrollwidget = ba.scrollwidget(parent=self._root_widget, - size=(scroll_size_x, scroll_size_y), - position=(scroll_pos_x, scroll_pos_y)) - self._columnwidget = ba.columnwidget(parent=self._scrollwidget, - border=1, - margin=0) + self._scrollwidget = bui.scrollwidget(parent=self._root_widget, + size=(scroll_size_x, scroll_size_y), + position=(scroll_pos_x, scroll_pos_y)) + self._columnwidget = bui.columnwidget(parent=self._scrollwidget, + border=1, + margin=0) delete_source_button_position_pos_x = 360 delete_source_button_position_pos_y = 110 - delete_source_button = ba.buttonwidget(parent=self._root_widget, - position=(delete_source_button_position_pos_x, - delete_source_button_position_pos_y), - size=(25, 25), - on_activate_call=self.delete_selected_source, - label="", - # texture=ba.gettexture("crossOut"), - button_type="square", - color=(0.6, 0, 0), - textcolor=b_textcolor, - # autoselect=True, - text_scale=1) + delete_source_button = bui.buttonwidget(parent=self._root_widget, + position=(delete_source_button_position_pos_x, + delete_source_button_position_pos_y), + size=(25, 25), + on_activate_call=self.delete_selected_source, + label="", + # texture=bui.gettexture("crossOut"), + button_type="square", + color=(0.6, 0, 0), + textcolor=b_textcolor, + # autoselect=True, + text_scale=1) - ba.imagewidget(parent=self._root_widget, - position=(delete_source_button_position_pos_x + 2, - delete_source_button_position_pos_y), - size=(25, 25), - color=(5, 2, 2), - texture=ba.gettexture("crossOut"), - draw_controller=delete_source_button) + bui.imagewidget(parent=self._root_widget, + position=(delete_source_button_position_pos_x + 2, + delete_source_button_position_pos_y), + size=(25, 25), + color=(5, 2, 2), + texture=bui.gettexture("crossOut"), + draw_controller=delete_source_button) - warning_pos_x = (43 if _uiscale is ba.UIScale.SMALL else - 35 if _uiscale is ba.UIScale.MEDIUM else + warning_pos_x = (43 if _uiscale is babase.UIScale.SMALL else + 35 if _uiscale is babase.UIScale.MEDIUM else 48) - ba.textwidget( + bui.textwidget( parent=self._root_widget, position=(warning_pos_x, 74), size=(50, 22), @@ -1318,32 +1358,32 @@ class PluginSourcesWindow(popup.PopupWindow): maxwidth=400, ) - self._add_source_widget = ba.textwidget(parent=self._root_widget, - # text="rikkolovescats/sahilp-plugins", - size=(335, 50), - position=(21, 22), - h_align='left', - v_align='center', - editable=True, - scale=0.75, - maxwidth=215, - # autoselect=True, - description="Add Source") + self._add_source_widget = bui.textwidget(parent=self._root_widget, + # text="rikkolovescats/sahilp-plugins", + size=(335, 50), + position=(21, 22), + h_align='left', + v_align='center', + editable=True, + scale=0.75, + maxwidth=215, + # autoselect=True, + description="Add Source") loop = asyncio.get_event_loop() - ba.buttonwidget(parent=self._root_widget, - position=(330, 28), - size=(37, 37), - on_activate_call=lambda: loop.create_task(self.add_source()), - label="", - texture=ba.gettexture("startButton"), - # texture=ba.gettexture("chestOpenIcon"), - button_type="square", - color=(0, 0.9, 0), - textcolor=b_textcolor, - # autoselect=True, - text_scale=1) + bui.buttonwidget(parent=self._root_widget, + position=(330, 28), + size=(37, 37), + on_activate_call=lambda: loop.create_task(self.add_source()), + label="", + texture=bui.gettexture("startButton"), + # texture=bui.gettexture("chestOpenIcon"), + button_type="square", + color=(0, 0.9, 0), + textcolor=b_textcolor, + # autoselect=True, + text_scale=1) self.draw_sources() @@ -1352,59 +1392,68 @@ class PluginSourcesWindow(popup.PopupWindow): plugin.delete() color = (1, 1, 1) - for custom_source in ba.app.config["Community Plugin Manager"]["Custom Sources"]: - ba.textwidget(parent=self._columnwidget, - # size=(410, 30), - selectable=True, - # always_highlight=True, - color=color, - text=custom_source, - # click_activate=True, - on_select_call=lambda: self.select_source(custom_source), - h_align='left', - v_align='center', - scale=0.75, - maxwidth=260) + for custom_source in babase.app.config["Community Plugin Manager"]["Custom Sources"]: + bui.textwidget(parent=self._columnwidget, + # size=(410, 30), + selectable=True, + # always_highlight=True, + color=color, + text=custom_source, + # click_activate=True, + on_select_call=lambda: self.select_source(custom_source), + h_align='left', + v_align='center', + scale=0.75, + maxwidth=260) def select_source(self, source): self.selected_source = source async def add_source(self): - source = ba.textwidget(query=self._add_source_widget) - meta_url = _CACHE["index"]["external_source_url"].format( - repository=source, - content_type="raw", - tag=CURRENT_TAG + source = bui.textwidget(query=self._add_source_widget) + # External source URIs can optionally suffix `@branchname`, for example: + # `bombsquad-community/sample-plugin-source@experimental` + source_splits = source.split("@", maxsplit=1) + if len(source_splits) == 1: + # Fallack to `main` if `@branchname` isn't specified in an external source URI. + source_repo, source_tag = source_splits[0], "main" + else: + source_repo, source_tag = source_splits + meta_url = partial_format( + _CACHE["index"]["external_source_url"], + repository=source_repo, ) - category = Category(meta_url, is_3rd_party=True) - if not await category.is_valid(): - ba.screenmessage("Enter a valid plugin source", color=(1, 0, 0)) - ba.playsound(ba.getsound('error')) + category = Category(meta_url, tag=source_tag) + try: + await category.validate() + except (PluginSourceNetworkError, CategoryMetadataParseError) as e: + bui.screenmessage(str(e), color=(1, 0, 0)) + bui.getsound('error').play() return - if source in ba.app.config["Community Plugin Manager"]["Custom Sources"]: - ba.screenmessage("Plugin source already exists") - ba.playsound(ba.getsound('error')) + if source in babase.app.config["Community Plugin Manager"]["Custom Sources"]: + bui.screenmessage("Plugin source already exists") + bui.getsound('error').play() return - ba.app.config["Community Plugin Manager"]["Custom Sources"].append(source) - ba.app.config.commit() - ba.screenmessage("Plugin source added; Refresh plugin list to see changes", - color=(0, 1, 0)) - ba.playsound(ba.getsound('cashRegister2')) + babase.app.config["Community Plugin Manager"]["Custom Sources"].append(source) + babase.app.config.commit() + bui.screenmessage("Plugin source added; Refresh plugin list to see changes", + color=(0, 1, 0)) + bui.getsound('cashRegister2').play() self.draw_sources() def delete_selected_source(self): if self.selected_source is None: return - ba.app.config["Community Plugin Manager"]["Custom Sources"].remove(self.selected_source) - ba.app.config.commit() - ba.screenmessage("Plugin source deleted; Refresh plugin list to see changes", - color=(0.9, 1, 0)) - ba.playsound(ba.getsound('shieldDown')) + babase.app.config["Community Plugin Manager"]["Custom Sources"].remove(self.selected_source) + babase.app.config.commit() + bui.screenmessage("Plugin source deleted; Refresh plugin list to see changes", + color=(0.9, 1, 0)) + bui.getsound('shieldDown').play() self.draw_sources() def _ok(self) -> None: - ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self._root_widget, transition='out_scale') + bui.getsound('swish').play() + bui.containerwidget(edit=self._root_widget, transition='out_scale') class PluginCategoryWindow(popup.PopupMenuWindow): @@ -1414,17 +1463,17 @@ class PluginCategoryWindow(popup.PopupMenuWindow): self.scale_origin = origin_widget.get_screen_space_center() super().__init__( position=(200, 0), - scale=(2.3 if _uiscale is ba.UIScale.SMALL else - 1.65 if _uiscale is ba.UIScale.MEDIUM else 1.23), + scale=(2.3 if _uiscale is babase.UIScale.SMALL else + 1.65 if _uiscale is babase.UIScale.MEDIUM else 1.23), choices=choices, current_choice=current_choice, delegate=self) self._update_custom_sources_widget() def _update_custom_sources_widget(self): - ba.textwidget(edit=self._columnwidget.get_children()[-1], - color=(0.5, 0.5, 0.5), - on_activate_call=self.show_sources_window) + bui.textwidget(edit=self._columnwidget.get_children()[-1], + color=(0.5, 0.5, 0.5), + on_activate_call=self.show_sources_window) def popup_menu_selected_choice(self, window, choice): loop = asyncio.get_event_loop() @@ -1438,12 +1487,12 @@ class PluginCategoryWindow(popup.PopupMenuWindow): PluginSourcesWindow(origin_widget=self.root_widget) def _ok(self) -> None: - ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self.root_widget, transition='out_scale') + bui.getsound('swish').play() + bui.containerwidget(edit=self.root_widget, transition='out_scale') -class PluginManagerWindow(ba.Window): - def __init__(self, transition: str = "in_right", origin_widget: ba.Widget = None): +class PluginManagerWindow(bui.Window): + def __init__(self, transition: str = "in_right", origin_widget: bui.Widget = None): self.plugin_manager = PluginManager() self.category_selection_button = None self.selected_category = None @@ -1452,69 +1501,69 @@ class PluginManagerWindow(ba.Window): loop = asyncio.get_event_loop() loop.create_task(self.draw_index()) - self._width = (700 if _uiscale is ba.UIScale.SMALL - else 550 if _uiscale is ba.UIScale.MEDIUM + self._width = (700 if _uiscale is babase.UIScale.SMALL + else 550 if _uiscale is babase.UIScale.MEDIUM else 570) - self._height = (500 if _uiscale is ba.UIScale.SMALL - else 422 if _uiscale is ba.UIScale.MEDIUM + self._height = (500 if _uiscale is babase.UIScale.SMALL + else 422 if _uiscale is babase.UIScale.MEDIUM else 500) - top_extra = 20 if _uiscale is ba.UIScale.SMALL else 0 + top_extra = 20 if _uiscale is babase.UIScale.SMALL else 0 if origin_widget: self._transition_out = "out_scale" self._scale_origin = origin_widget.get_screen_space_center() transition = "in_scale" - super().__init__(root_widget=ba.containerwidget( + super().__init__(root_widget=bui.containerwidget( size=(self._width, self._height + top_extra), transition=transition, toolbar_visibility="menu_minimal", scale_origin_stack_offset=self._scale_origin, - scale=(1.9 if _uiscale is ba.UIScale.SMALL - else 1.5 if _uiscale is ba.UIScale.MEDIUM + scale=(1.9 if _uiscale is babase.UIScale.SMALL + else 1.5 if _uiscale is babase.UIScale.MEDIUM else 1.0), - stack_offset=(0, -25) if _uiscale is ba.UIScale.SMALL else (0, 0) + stack_offset=(0, -25) if _uiscale is babase.UIScale.SMALL else (0, 0) )) - back_pos_x = 5 + (37 if _uiscale is ba.UIScale.SMALL else - 27 if _uiscale is ba.UIScale.MEDIUM else 68) - back_pos_y = self._height - (95 if _uiscale is ba.UIScale.SMALL else - 65 if _uiscale is ba.UIScale.MEDIUM else 50) - self._back_button = back_button = ba.buttonwidget( + back_pos_x = 5 + (37 if _uiscale is babase.UIScale.SMALL else + 27 if _uiscale is babase.UIScale.MEDIUM else 68) + back_pos_y = self._height - (95 if _uiscale is babase.UIScale.SMALL else + 65 if _uiscale is babase.UIScale.MEDIUM else 50) + self._back_button = back_button = bui.buttonwidget( parent=self._root_widget, position=(back_pos_x, back_pos_y), size=(60, 60), scale=0.8, - label=ba.charstr(ba.SpecialChar.BACK), + label=babase.charstr(babase.SpecialChar.BACK), # autoselect=True, button_type='backSmall', on_activate_call=self._back) - ba.containerwidget(edit=self._root_widget, cancel_button=back_button) + bui.containerwidget(edit=self._root_widget, cancel_button=back_button) - title_pos = self._height - (83 if _uiscale is ba.UIScale.SMALL else - 50 if _uiscale is ba.UIScale.MEDIUM else 50) - ba.textwidget( + title_pos = self._height - (83 if _uiscale is babase.UIScale.SMALL else + 50 if _uiscale is babase.UIScale.MEDIUM else 50) + bui.textwidget( parent=self._root_widget, position=(-10, title_pos), size=(self._width, 25), text="Community Plugin Manager", - color=ba.app.ui.title_color, + color=bui.app.ui_v1.title_color, scale=1.05, h_align="center", v_align="center", maxwidth=270, ) - loading_pos_y = self._height - (275 if _uiscale is ba.UIScale.SMALL else - 235 if _uiscale is ba.UIScale.MEDIUM else 270) + loading_pos_y = self._height - (275 if _uiscale is babase.UIScale.SMALL else + 235 if _uiscale is babase.UIScale.MEDIUM else 270) - self._plugin_manager_status_text = ba.textwidget( + self._plugin_manager_status_text = bui.textwidget( parent=self._root_widget, position=(-5, loading_pos_y), size=(self._width, 25), text="Loading...", - color=ba.app.ui.title_color, + color=bui.app.ui_v1.title_color, scale=0.7, h_align="center", v_align="center", @@ -1522,10 +1571,10 @@ class PluginManagerWindow(ba.Window): ) def _back(self) -> None: - from bastd.ui.settings.allsettings import AllSettingsWindow - ba.containerwidget(edit=self._root_widget, - transition=self._transition_out) - ba.app.ui.set_main_menu_window( + from bauiv1lib.settings.allsettings import AllSettingsWindow + bui.containerwidget(edit=self._root_widget, + transition=self._transition_out) + bui.app.ui_v1.set_main_menu_window( AllSettingsWindow(transition='in_left').get_root_widget()) @contextlib.contextmanager @@ -1533,14 +1582,14 @@ class PluginManagerWindow(ba.Window): try: yield except urllib.error.URLError: - ba.textwidget(edit=self._plugin_manager_status_text, - text="Make sure you are connected\n to the Internet and try again.") + bui.textwidget(edit=self._plugin_manager_status_text, + text="Make sure you are connected\n to the Internet and try again.") except RuntimeError: - # User probably went back before a ba.Window could finish loading. + # User probably went back before a bui.Window could finish loading. pass except Exception as e: - ba.textwidget(edit=self._plugin_manager_status_text, - text=str(e)) + bui.textwidget(edit=self._plugin_manager_status_text, + text=str(e)) raise async def draw_index(self): @@ -1551,31 +1600,31 @@ class PluginManagerWindow(ba.Window): self.draw_settings_icon() with self.exception_handler(): await self.plugin_manager.setup_index() - ba.textwidget(edit=self._plugin_manager_status_text, - text="") + bui.textwidget(edit=self._plugin_manager_status_text, + text="") await self.select_category("All") def draw_plugins_scroll_bar(self): - scroll_size_x = (515 if _uiscale is ba.UIScale.SMALL else - 430 if _uiscale is ba.UIScale.MEDIUM else 420) - scroll_size_y = (245 if _uiscale is ba.UIScale.SMALL else - 265 if _uiscale is ba.UIScale.MEDIUM else 335) - scroll_pos_x = (70 if _uiscale is ba.UIScale.SMALL else - 50 if _uiscale is ba.UIScale.MEDIUM else 70) - scroll_pos_y = (100 if _uiscale is ba.UIScale.SMALL else - 35 if _uiscale is ba.UIScale.MEDIUM else 40) - self._scrollwidget = ba.scrollwidget(parent=self._root_widget, - size=(scroll_size_x, scroll_size_y), - position=(scroll_pos_x, scroll_pos_y)) - self._columnwidget = ba.columnwidget(parent=self._scrollwidget, - border=2, - margin=0) + scroll_size_x = (515 if _uiscale is babase.UIScale.SMALL else + 430 if _uiscale is babase.UIScale.MEDIUM else 420) + scroll_size_y = (245 if _uiscale is babase.UIScale.SMALL else + 265 if _uiscale is babase.UIScale.MEDIUM else 335) + scroll_pos_x = (70 if _uiscale is babase.UIScale.SMALL else + 50 if _uiscale is babase.UIScale.MEDIUM else 70) + scroll_pos_y = (100 if _uiscale is babase.UIScale.SMALL else + 35 if _uiscale is babase.UIScale.MEDIUM else 40) + self._scrollwidget = bui.scrollwidget(parent=self._root_widget, + size=(scroll_size_x, scroll_size_y), + position=(scroll_pos_x, scroll_pos_y)) + self._columnwidget = bui.columnwidget(parent=self._scrollwidget, + border=2, + margin=0) def draw_category_selection_button(self, post_label): - category_pos_x = (440 if _uiscale is ba.UIScale.SMALL else - 340 if _uiscale is ba.UIScale.MEDIUM else 350) - category_pos_y = self._height - (141 if _uiscale is ba.UIScale.SMALL else - 110 if _uiscale is ba.UIScale.MEDIUM else 110) + category_pos_x = (440 if _uiscale is babase.UIScale.SMALL else + 340 if _uiscale is babase.UIScale.MEDIUM else 350) + category_pos_y = self._height - (141 if _uiscale is babase.UIScale.SMALL else + 110 if _uiscale is babase.UIScale.MEDIUM else 110) b_size = (140, 30) # b_textcolor = (0.75, 0.7, 0.8) b_textcolor = (0.8, 0.8, 0.85) @@ -1584,64 +1633,64 @@ class PluginManagerWindow(ba.Window): label = f"Category: {post_label}" if self.category_selection_button is None: - self.category_selection_button = ba.buttonwidget(parent=self._root_widget, - position=(category_pos_x, - category_pos_y), - size=b_size, - on_activate_call=( - self.show_categories_window), - label=label, - button_type="square", - # color=b_color, - textcolor=b_textcolor, - # autoselect=True, - text_scale=0.6) + self.category_selection_button = bui.buttonwidget(parent=self._root_widget, + position=(category_pos_x, + category_pos_y), + size=b_size, + on_activate_call=( + self.show_categories_window), + label=label, + button_type="square", + # color=b_color, + textcolor=b_textcolor, + # autoselect=True, + text_scale=0.6) else: - self.category_selection_button = ba.buttonwidget(edit=self.category_selection_button, - label=label) + self.category_selection_button = bui.buttonwidget(edit=self.category_selection_button, + label=label) def draw_search_bar(self): - search_bar_pos_x = (85 if _uiscale is ba.UIScale.SMALL else - 68 if _uiscale is ba.UIScale.MEDIUM else 90) + search_bar_pos_x = (85 if _uiscale is babase.UIScale.SMALL else + 68 if _uiscale is babase.UIScale.MEDIUM else 90) search_bar_pos_y = self._height - ( - 145 if _uiscale is ba.UIScale.SMALL else - 110 if _uiscale is ba.UIScale.MEDIUM else 116) + 145 if _uiscale is babase.UIScale.SMALL else + 110 if _uiscale is babase.UIScale.MEDIUM else 116) - search_bar_size_x = (320 if _uiscale is ba.UIScale.SMALL else - 230 if _uiscale is ba.UIScale.MEDIUM else 260) + search_bar_size_x = (320 if _uiscale is babase.UIScale.SMALL else + 230 if _uiscale is babase.UIScale.MEDIUM else 260) search_bar_size_y = ( - 35 if _uiscale is ba.UIScale.SMALL else - 35 if _uiscale is ba.UIScale.MEDIUM else 45) + 35 if _uiscale is babase.UIScale.SMALL else + 35 if _uiscale is babase.UIScale.MEDIUM else 45) - filter_txt_pos_x = (60 if _uiscale is ba.UIScale.SMALL else - 40 if _uiscale is ba.UIScale.MEDIUM else 60) - filter_txt_pos_y = search_bar_pos_y + (3 if _uiscale is ba.UIScale.SMALL else - 4 if _uiscale is ba.UIScale.MEDIUM else 8) + filter_txt_pos_x = (60 if _uiscale is babase.UIScale.SMALL else + 40 if _uiscale is babase.UIScale.MEDIUM else 60) + filter_txt_pos_y = search_bar_pos_y + (3 if _uiscale is babase.UIScale.SMALL else + 4 if _uiscale is babase.UIScale.MEDIUM else 8) - ba.textwidget(parent=self._root_widget, - text="Filter", - position=(filter_txt_pos_x, filter_txt_pos_y), - selectable=False, - h_align='left', - v_align='center', - color=ba.app.ui.title_color, - scale=0.5) + bui.textwidget(parent=self._root_widget, + text="Filter", + position=(filter_txt_pos_x, filter_txt_pos_y), + selectable=False, + h_align='left', + v_align='center', + color=bui.app.ui_v1.title_color, + scale=0.5) - filter_txt = ba.Lstr(resource='filterText') - search_bar_maxwidth = search_bar_size_x - (95 if _uiscale is ba.UIScale.SMALL else - 77 if _uiscale is ba.UIScale.MEDIUM else + filter_txt = babase.Lstr(resource='filterText') + search_bar_maxwidth = search_bar_size_x - (95 if _uiscale is babase.UIScale.SMALL else + 77 if _uiscale is babase.UIScale.MEDIUM else 85) - self._filter_widget = ba.textwidget(parent=self._root_widget, - text="", - size=(search_bar_size_x, search_bar_size_y), - position=(search_bar_pos_x, search_bar_pos_y), - h_align='left', - v_align='center', - editable=True, - scale=0.8, - autoselect=True, - maxwidth=search_bar_maxwidth, - description=filter_txt) + self._filter_widget = bui.textwidget(parent=self._root_widget, + text="", + size=(search_bar_size_x, search_bar_size_y), + position=(search_bar_pos_x, search_bar_pos_y), + h_align='left', + v_align='center', + editable=True, + scale=0.8, + autoselect=True, + maxwidth=search_bar_maxwidth, + description=filter_txt) self._last_filter_text = None self._last_filter_plugins = [] loop = asyncio.get_event_loop() @@ -1651,7 +1700,7 @@ class PluginManagerWindow(ba.Window): while True: await asyncio.sleep(0.2) try: - filter_text = ba.textwidget(query=self._filter_widget) + filter_text = bui.textwidget(query=self._filter_widget) except RuntimeError: # Search filter widget got destroyed. No point checking for filter text anymore. return @@ -1659,65 +1708,65 @@ class PluginManagerWindow(ba.Window): continue try: await self.draw_plugin_names(self.selected_category, search_term=filter_text) - except CategoryDoesNotExistError: + except CategoryDoesNotExist: pass # XXX: This may be more efficient, but we need a way to get a plugin's textwidget # attributes like color, position and more. # for plugin in self._columnwidget.get_children(): # for name, widget in tuple(self.plugins_in_current_view.items()): - # # print(ba.textwidget(query=plugin)) + # # print(bui.textwidget(query=plugin)) # # plugin.delete() # print(dir(widget)) # if filter_text in name: # import random # if random.random() > 0.9: - # ba.textwidget(edit=widget).delete() + # bui.textwidget(edit=widget).delete() # else: - # ba.textwidget(edit=widget, position=None) + # bui.textwidget(edit=widget, position=None) # else: - # ba.textwidget(edit=widget, position=None) + # bui.textwidget(edit=widget, position=None) def draw_settings_icon(self): - settings_pos_x = (610 if _uiscale is ba.UIScale.SMALL else - 500 if _uiscale is ba.UIScale.MEDIUM else 510) - settings_pos_y = (130 if _uiscale is ba.UIScale.SMALL else - 60 if _uiscale is ba.UIScale.MEDIUM else 70) - controller_button = ba.buttonwidget(parent=self._root_widget, - # autoselect=True, - position=(settings_pos_x, settings_pos_y), - size=(30, 30), - button_type="square", - label="", - on_activate_call=ba.Call(PluginManagerSettingsWindow, - self.plugin_manager, - self._root_widget)) - ba.imagewidget(parent=self._root_widget, - position=(settings_pos_x, settings_pos_y), - size=(30, 30), - color=(0.8, 0.95, 1), - texture=ba.gettexture("settingsIcon"), - draw_controller=controller_button) + settings_pos_x = (610 if _uiscale is babase.UIScale.SMALL else + 500 if _uiscale is babase.UIScale.MEDIUM else 510) + settings_pos_y = (130 if _uiscale is babase.UIScale.SMALL else + 60 if _uiscale is babase.UIScale.MEDIUM else 70) + controller_button = bui.buttonwidget(parent=self._root_widget, + # autoselect=True, + position=(settings_pos_x, settings_pos_y), + size=(30, 30), + button_type="square", + label="", + on_activate_call=babase.Call(PluginManagerSettingsWindow, + self.plugin_manager, + self._root_widget)) + bui.imagewidget(parent=self._root_widget, + position=(settings_pos_x, settings_pos_y), + size=(30, 30), + color=(0.8, 0.95, 1), + texture=bui.gettexture("settingsIcon"), + draw_controller=controller_button) def draw_refresh_icon(self): - refresh_pos_x = (610 if _uiscale is ba.UIScale.SMALL else - 500 if _uiscale is ba.UIScale.MEDIUM else 510) - refresh_pos_y = (180 if _uiscale is ba.UIScale.SMALL else - 108 if _uiscale is ba.UIScale.MEDIUM else 120) + refresh_pos_x = (610 if _uiscale is babase.UIScale.SMALL else + 500 if _uiscale is babase.UIScale.MEDIUM else 510) + refresh_pos_y = (180 if _uiscale is babase.UIScale.SMALL else + 108 if _uiscale is babase.UIScale.MEDIUM else 120) loop = asyncio.get_event_loop() - controller_button = ba.buttonwidget(parent=self._root_widget, - # autoselect=True, - position=(refresh_pos_x, refresh_pos_y), - size=(30, 30), - button_type="square", - label="", - on_activate_call=lambda: - loop.create_task(self.refresh())) - ba.imagewidget(parent=self._root_widget, - position=(refresh_pos_x, refresh_pos_y), - size=(30, 30), - color=(0.8, 0.95, 1), - texture=ba.gettexture("replayIcon"), - draw_controller=controller_button) + controller_button = bui.buttonwidget(parent=self._root_widget, + # autoselect=True, + position=(refresh_pos_x, refresh_pos_y), + size=(30, 30), + button_type="square", + label="", + on_activate_call=lambda: + loop.create_task(self.refresh())) + bui.imagewidget(parent=self._root_widget, + position=(refresh_pos_x, refresh_pos_y), + size=(30, 30), + color=(0.8, 0.95, 1), + texture=bui.gettexture("replayIcon"), + draw_controller=controller_button) def search_term_filterer(self, plugin, search_term): # This helps resolve "plugin name" to "plugin_name". @@ -1750,7 +1799,7 @@ class PluginManagerWindow(ba.Window): try: category_plugins = await self.plugin_manager.categories[category].get_plugins() except (KeyError, AttributeError): - raise CategoryDoesNotExistError(f"{category} does not exist.") + raise CategoryDoesNotExist(f"{category} does not exist.") if search_term: def search_term_filterer(plugin): return self.search_term_filterer(plugin, search_term) @@ -1775,7 +1824,7 @@ class PluginManagerWindow(ba.Window): async def draw_plugin_name(self, plugin): try: latest_compatible_version = plugin.latest_compatible_version - except NoCompatibleVersionError: + except NoCompatibleVersion: # We currently don't show plugins that have no compatible versions. return @@ -1795,21 +1844,21 @@ class PluginManagerWindow(ba.Window): plugin_name_widget_to_update = self.plugins_in_current_view.get(plugin.name) if plugin_name_widget_to_update: - ba.textwidget(edit=plugin_name_widget_to_update, - color=color) + bui.textwidget(edit=plugin_name_widget_to_update, + color=color) else: - text_widget = ba.textwidget(parent=self._columnwidget, - size=(410, 30), - selectable=True, - always_highlight=True, - color=color, - # on_select_call=lambda: None, - text=plugin.name, - click_activate=True, - on_activate_call=lambda: self.show_plugin_window(plugin), - h_align='left', - v_align='center', - maxwidth=420) + text_widget = bui.textwidget(parent=self._columnwidget, + size=(410, 30), + selectable=True, + always_highlight=True, + color=color, + # on_select_call=lambda: None, + text=plugin.name, + click_activate=True, + on_activate_call=lambda: self.show_plugin_window(plugin), + h_align='left', + v_align='center', + maxwidth=420) self.plugins_in_current_view[plugin.name] = text_widget # XXX: This seems nicer. Might wanna use this in future. # text_widget.add_delete_callback(lambda: self.plugins_in_current_view.pop(plugin.name)) @@ -1841,14 +1890,14 @@ class PluginManagerWindow(ba.Window): async def refresh(self): self.cleanup() - ba.textwidget(edit=self._plugin_manager_status_text, - text="Refreshing...") + bui.textwidget(edit=self._plugin_manager_status_text, + text="Refreshing...") with self.exception_handler(): await self.plugin_manager.refresh() await self.plugin_manager.setup_index() - ba.textwidget(edit=self._plugin_manager_status_text, - text="") + bui.textwidget(edit=self._plugin_manager_status_text, + text="") await self.select_category(self.selected_category) def soft_refresh(self): @@ -1859,13 +1908,13 @@ class PluginManagerSettingsWindow(popup.PopupWindow): def __init__(self, plugin_manager, origin_widget): self._plugin_manager = plugin_manager self.scale_origin = origin_widget.get_screen_space_center() - self.settings = ba.app.config["Community Plugin Manager"]["Settings"].copy() + self.settings = babase.app.config["Community Plugin Manager"]["Settings"].copy() loop = asyncio.get_event_loop() loop.create_task(self.draw_ui()) async def draw_ui(self): b_text_color = (0.8, 0.8, 0.85) - s = 1.25 if _uiscale is ba.UIScale.SMALL else 1.27 if _uiscale is ba.UIScale.MEDIUM else 1.3 + s = 1.25 if _uiscale is babase.UIScale.SMALL else 1.27 if _uiscale is babase.UIScale.MEDIUM else 1.3 width = 380 * s height = 150 + 150 * s color = (0.9, 0.9, 0.9) @@ -1880,99 +1929,99 @@ class PluginManagerSettingsWindow(popup.PopupWindow): transition = 'in_scale' button_size = (32 * s, 32 * s) # index = await self._plugin_manager.get_index() - self._root_widget = ba.containerwidget(size=(width, height), - # parent=_ba.get_special_widget( - # 'overlay_stack'), - on_outside_click_call=self._ok, - transition=transition, - scale=(2.1 if _uiscale is ba.UIScale.SMALL else 1.5 - if _uiscale is ba.UIScale.MEDIUM else 1.0), - scale_origin_stack_offset=self.scale_origin) + self._root_widget = bui.containerwidget(size=(width, height), + # parent=_babase.get_special_widget( + # 'overlay_stack'), + on_outside_click_call=self._ok, + transition=transition, + scale=(2.1 if _uiscale is babase.UIScale.SMALL else 1.5 + if _uiscale is babase.UIScale.MEDIUM else 1.0), + scale_origin_stack_offset=self.scale_origin) pos = height * 0.9 setting_title = "Settings" - ba.textwidget(parent=self._root_widget, - position=(width * 0.49, pos), - size=(0, 0), - h_align='center', - v_align='center', - text=setting_title, - scale=text_scale, - color=ba.app.ui.title_color, - maxwidth=width * 0.9) + bui.textwidget(parent=self._root_widget, + position=(width * 0.49, pos), + size=(0, 0), + h_align='center', + v_align='center', + text=setting_title, + scale=text_scale, + color=bui.app.ui_v1.title_color, + maxwidth=width * 0.9) pos -= 20 - self._save_button = ba.buttonwidget(parent=self._root_widget, - position=((width * 0.82) - button_size[0] / 2, pos), - size=(73, 35), - on_activate_call=self.save_settings_button, - textcolor=b_text_color, - button_type='square', - text_scale=1, - scale=0, - selectable=False, - label="Save") + self._save_button = bui.buttonwidget(parent=self._root_widget, + position=((width * 0.82) - button_size[0] / 2, pos), + size=(73, 35), + on_activate_call=self.save_settings_button, + textcolor=b_text_color, + button_type='square', + text_scale=1, + scale=0, + selectable=False, + label="Save") pos -= 40 for setting, value in self.settings.items(): - ba.checkboxwidget(parent=self._root_widget, - position=(width * 0.1, pos), - size=(170, 30), - text=setting, - value=value, - on_value_change_call=ba.Call(self.toggle_setting, setting), - maxwidth=500, - textcolor=(0.9, 0.9, 0.9), - scale=text_scale * 0.8) + bui.checkboxwidget(parent=self._root_widget, + position=(width * 0.1, pos), + size=(170, 30), + text=setting, + value=value, + on_value_change_call=babase.Call(self.toggle_setting, setting), + maxwidth=500, + textcolor=(0.9, 0.9, 0.9), + scale=text_scale * 0.8) pos -= 34 * text_scale pos = height - 200 - ba.textwidget(parent=self._root_widget, - position=(width * 0.49, pos-5), - size=(0, 0), - h_align='center', - v_align='center', - text='Contribute to plugins or to this community plugin manager!', - scale=text_scale * 0.65, - color=color, - maxwidth=width * 0.95) + bui.textwidget(parent=self._root_widget, + position=(width * 0.49, pos-5), + size=(0, 0), + h_align='center', + v_align='center', + text='Contribute to plugins or to this community plugin manager!', + scale=text_scale * 0.65, + color=color, + maxwidth=width * 0.95) pos -= 75 - self.discord_button = ba.buttonwidget(parent=self._root_widget, - position=((width * 0.20) - button_size[0] / 2, pos), + self.discord_button = bui.buttonwidget(parent=self._root_widget, + position=((width * 0.20) - button_size[0] / 2, pos), + size=button_size, + on_activate_call=lambda: bui.open_url(DISCORD_URL), + textcolor=b_text_color, + color=discord_bg_color, + button_type='square', + text_scale=1, + label="") + + bui.imagewidget(parent=self._root_widget, + position=((width * 0.20)+0.5 - button_size[0] / 2, pos), + size=button_size, + texture=bui.gettexture("discordLogo"), + color=discord_fg_color, + draw_controller=self.discord_button) + + self.github_button = bui.buttonwidget(parent=self._root_widget, + position=((width * 0.49) - button_size[0] / 2, pos), size=button_size, - on_activate_call=lambda: ba.open_url(DISCORD_URL), + on_activate_call=lambda: bui.open_url(REPOSITORY_URL), textcolor=b_text_color, - color=discord_bg_color, + color=github_bg_color, button_type='square', text_scale=1, - label="") + label='') - ba.imagewidget(parent=self._root_widget, - position=((width * 0.20)+0.5 - button_size[0] / 2, pos), - size=button_size, - texture=ba.gettexture("discordLogo"), - color=discord_fg_color, - draw_controller=self.discord_button) + bui.imagewidget(parent=self._root_widget, + position=((width * 0.49) + 0.5 - button_size[0] / 2, pos), + size=button_size, + texture=bui.gettexture("githubLogo"), + color=(1, 1, 1), + draw_controller=self.github_button) - self.github_button = ba.buttonwidget(parent=self._root_widget, - position=((width * 0.49) - button_size[0] / 2, pos), - size=button_size, - on_activate_call=lambda: ba.open_url(REPOSITORY_URL), - textcolor=b_text_color, - color=github_bg_color, - button_type='square', - text_scale=1, - label='') - - ba.imagewidget(parent=self._root_widget, - position=((width * 0.49) + 0.5 - button_size[0] / 2, pos), - size=button_size, - texture=ba.gettexture("githubLogo"), - color=(1, 1, 1), - draw_controller=self.github_button) - - ba.containerwidget(edit=self._root_widget, - on_cancel_call=self._ok) + bui.containerwidget(edit=self._root_widget, + on_cancel_call=self._ok) try: plugin_manager_update_available = await self._plugin_manager.get_update_details() @@ -1983,269 +2032,311 @@ class PluginManagerSettingsWindow(popup.PopupWindow): loop = asyncio.get_event_loop() button_size = (95 * s, 32 * s) update_button_label = f'Update to v{plugin_manager_update_available[0]}' - self._update_button = ba.buttonwidget(parent=self._root_widget, - position=((width * 0.77) - button_size[0] / 2, - pos), - size=button_size, - on_activate_call=lambda: - loop.create_task( - self.update( - *plugin_manager_update_available - ) - ), - textcolor=b_text_color, - button_type='square', - text_scale=1, - color=(0, 0.7, 0), - label=update_button_label) - self._restart_to_reload_changes_text = ba.textwidget(parent=self._root_widget, - position=(width * 0.79, pos + 20), - size=(0, 0), - h_align='center', - v_align='center', - text='', - scale=text_scale * 0.65, - color=(0, 0.8, 0), - maxwidth=width * 0.9) + self._update_button = bui.buttonwidget(parent=self._root_widget, + position=((width * 0.77) - button_size[0] / 2, + pos), + size=button_size, + on_activate_call=lambda: + loop.create_task( + self.update( + *plugin_manager_update_available + ) + ), + textcolor=b_text_color, + button_type='square', + text_scale=1, + color=(0, 0.7, 0), + label=update_button_label) + self._restart_to_reload_changes_text = bui.textwidget(parent=self._root_widget, + position=(width * 0.79, pos + 20), + size=(0, 0), + h_align='center', + v_align='center', + text='', + scale=text_scale * 0.65, + color=(0, 0.8, 0), + maxwidth=width * 0.9) else: text_color = (0, 0.8, 0) pos -= 25 - ba.textwidget(parent=self._root_widget, - position=(width * 0.49, pos), - size=(0, 0), - h_align='center', - v_align='center', - text=f'Plugin Manager v{PLUGIN_MANAGER_VERSION}', - scale=text_scale * 0.8, - color=text_color, - maxwidth=width * 0.9) + bui.textwidget(parent=self._root_widget, + position=(width * 0.49, pos), + size=(0, 0), + h_align='center', + v_align='center', + text=f'Plugin Manager v{PLUGIN_MANAGER_VERSION}', + scale=text_scale * 0.8, + color=text_color, + maxwidth=width * 0.9) pos -= 25 - ba.textwidget(parent=self._root_widget, - position=(width * 0.49, pos), - size=(0, 0), - h_align='center', - v_align='center', - text=f'API Version: {ba.app.api_version}', - scale=text_scale * 0.7, - color=(0.4, 0.8, 1), - maxwidth=width * 0.95) + bui.textwidget(parent=self._root_widget, + position=(width * 0.49, pos), + size=(0, 0), + h_align='center', + v_align='center', + text=f'API Version: {babase.app.api_version}', + scale=text_scale * 0.7, + color=(0.4, 0.8, 1), + maxwidth=width * 0.95) pos = height * 0.1 def toggle_setting(self, setting, set_value): self.settings[setting] = set_value - if self.settings == ba.app.config["Community Plugin Manager"]["Settings"]: - ba.buttonwidget(edit=self._save_button, - scale=0, - selectable=False) + if self.settings == babase.app.config["Community Plugin Manager"]["Settings"]: + bui.buttonwidget(edit=self._save_button, + scale=0, + selectable=False) else: - ba.buttonwidget(edit=self._save_button, - scale=1, - selectable=True) + bui.buttonwidget(edit=self._save_button, + scale=1, + selectable=True) def save_settings_button(self): - ba.app.config["Community Plugin Manager"]["Settings"] = self.settings.copy() - ba.app.config.commit() + babase.app.config["Community Plugin Manager"]["Settings"] = self.settings.copy() + babase.app.config.commit() self._ok() - ba.playsound(ba.getsound('gunCocking')) + bui.getsound('gunCocking').play() async def update(self, to_version=None, commit_sha=None): try: await self._plugin_manager.update(to_version, commit_sha) - except MD5CheckSumFailedError: - ba.screenmessage("MD5 checksum failed during plugin manager update", color=(1, 0, 0)) - ba.playsound(ba.getsound('error')) + except MD5CheckSumFailed: + bui.screenmessage("MD5 checksum failed during plugin manager update", color=(1, 0, 0)) + bui.getsound('error').play() else: - ba.screenmessage("Plugin manager update successful", color=(0, 1, 0)) - ba.playsound(ba.getsound('shieldUp')) - ba.textwidget(edit=self._restart_to_reload_changes_text, - text='Update Applied!\nRestart game to reload changes.') + bui.screenmessage("Plugin manager update successful", color=(0, 1, 0)) + bui.getsound('shieldUp').play() + bui.textwidget(edit=self._restart_to_reload_changes_text, + text='Update Applied!\nRestart game to reload changes.') self._update_button.delete() def _ok(self) -> None: - ba.playsound(ba.getsound('swish')) - ba.containerwidget(edit=self._root_widget, transition='out_scale') + bui.getsound('swish').play() + bui.containerwidget(edit=self._root_widget, transition='out_scale') -class NewAllSettingsWindow(ba.Window): - def __init__(self, - transition: str = "in_right", - origin_widget: ba.Widget = None): +class NewAllSettingsWindow(bui.Window): + """Window for selecting a settings category.""" + + def __init__( + self, + transition: str = 'in_right', + origin_widget: bui.Widget | None = None, + ): # pylint: disable=too-many-statements # pylint: disable=too-many-locals - import threading - # Preload some modules we use in a background thread so we won"t + # Preload some modules we use in a background thread so we won't # have a visual hitch when the user taps them. - threading.Thread(target=self._preload_modules).start() + Thread(target=self._preload_modules).start() - ba.set_analytics_screen("Settings Window") - scale_origin: Optional[tuple[float, float]] + bui.set_analytics_screen('Settings Window') + scale_origin: tuple[float, float] | None if origin_widget is not None: - self._transition_out = "out_scale" + self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() - transition = "in_scale" + transition = 'in_scale' else: - self._transition_out = "out_right" + self._transition_out = 'out_right' scale_origin = None - width = 900 if _uiscale is ba.UIScale.SMALL else 670 - x_inset = 75 if _uiscale is ba.UIScale.SMALL else 0 + assert bui.app.classic is not None + width = 900 if _uiscale is bui.UIScale.SMALL else 670 + x_inset = 75 if _uiscale is bui.UIScale.SMALL else 0 height = 435 - self._r = "settingsWindow" - top_extra = 20 if _uiscale is ba.UIScale.SMALL else 0 + self._r = 'settingsWindow' + top_extra = 20 if _uiscale is bui.UIScale.SMALL else 0 - super().__init__(root_widget=ba.containerwidget( - size=(width, height + top_extra), - transition=transition, - toolbar_visibility="menu_minimal", - scale_origin_stack_offset=scale_origin, - scale=(1.75 if _uiscale is ba.UIScale.SMALL else - 1.35 if _uiscale is ba.UIScale.MEDIUM else 1.0), - stack_offset=(0, -8) if _uiscale is ba.UIScale.SMALL else (0, 0))) + super().__init__( + root_widget=bui.containerwidget( + size=(width, height + top_extra), + transition=transition, + toolbar_visibility='menu_minimal', + scale_origin_stack_offset=scale_origin, + scale=( + 1.75 + if _uiscale is bui.UIScale.SMALL + else 1.35 + if _uiscale is bui.UIScale.MEDIUM + else 1.0 + ), + stack_offset=(0, -8) + if _uiscale is bui.UIScale.SMALL + else (0, 0), + ) + ) - if ba.app.ui.use_toolbars and _uiscale is ba.UIScale.SMALL: + if bui.app.ui_v1.use_toolbars and _uiscale is bui.UIScale.SMALL: self._back_button = None - ba.containerwidget(edit=self._root_widget, - on_cancel_call=self._do_back) + bui.containerwidget( + edit=self._root_widget, on_cancel_call=self._do_back + ) else: - self._back_button = btn = ba.buttonwidget( + self._back_button = btn = bui.buttonwidget( parent=self._root_widget, autoselect=True, position=(40 + x_inset, height - 55), size=(130, 60), scale=0.8, text_scale=1.2, - label=ba.Lstr(resource="backText"), - button_type="back", - on_activate_call=self._do_back) - ba.containerwidget(edit=self._root_widget, cancel_button=btn) + label=bui.Lstr(resource='backText'), + button_type='back', + on_activate_call=self._do_back, + ) + bui.containerwidget(edit=self._root_widget, cancel_button=btn) - ba.textwidget(parent=self._root_widget, - position=(0, height - 44), - size=(width, 25), - text=ba.Lstr(resource=self._r + ".titleText"), - color=ba.app.ui.title_color, - h_align="center", - v_align="center", - maxwidth=130) + bui.textwidget( + parent=self._root_widget, + position=(0, height - 44), + size=(width, 25), + text=bui.Lstr(resource=self._r + '.titleText'), + color=bui.app.ui_v1.title_color, + h_align='center', + v_align='center', + maxwidth=130, + ) if self._back_button is not None: - ba.buttonwidget(edit=self._back_button, - button_type="backSmall", - size=(60, 60), - label=ba.charstr(ba.SpecialChar.BACK)) + bui.buttonwidget( + edit=self._back_button, + button_type='backSmall', + size=(60, 60), + label=bui.charstr(bui.SpecialChar.BACK), + ) v = height - 80 v -= 145 basew = 200 baseh = 160 - - x_offs = x_inset + (105 if _uiscale is ba.UIScale.SMALL else - 72) - basew # now unused + x_offs = ( + x_inset + (105 if _uiscale is bui.UIScale.SMALL else 72) - basew + ) # now unused x_offs2 = x_offs + basew - 7 x_offs3 = x_offs + 2 * (basew - 7) x_offs4 = x_offs + 3 * (basew - 7) x_offs5 = x_offs2 + 0.5 * (basew - 7) x_offs6 = x_offs5 + (basew - 7) - def _b_title(x: float, y: float, button: ba.Widget, - text: Union[str, ba.Lstr]) -> None: - ba.textwidget(parent=self._root_widget, - text=text, - position=(x + basew * 0.47, y + baseh * 0.22), - maxwidth=basew * 0.7, size=(0, 0), - h_align="center", - v_align="center", - draw_controller=button, - color=(0.7, 0.9, 0.7, 1.0)) + def _b_title( + x: float, y: float, button: bui.Widget, text: str | bui.Lstr + ) -> None: + bui.textwidget( + parent=self._root_widget, + text=text, + position=(x + basew * 0.47, y + baseh * 0.22), + maxwidth=basew * 0.7, + size=(0, 0), + h_align='center', + v_align='center', + draw_controller=button, + color=(0.7, 0.9, 0.7, 1.0), + ) - ctb = self._controllers_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(x_offs2, v), - size=(basew, baseh), - button_type="square", - label="", - on_activate_call=self._do_controllers) - if ba.app.ui.use_toolbars and self._back_button is None: - bbtn = _ba.get_special_widget("back_button") - ba.widget(edit=ctb, left_widget=bbtn) - _b_title(x_offs2, v, ctb, - ba.Lstr(resource=self._r + ".controllersText")) + ctb = self._controllers_button = bui.buttonwidget( + parent=self._root_widget, + autoselect=True, + position=(x_offs2, v), + size=(basew, baseh), + button_type='square', + label='', + on_activate_call=self._do_controllers, + ) + if bui.app.ui_v1.use_toolbars and self._back_button is None: + bbtn = bui.get_special_widget('back_button') + bui.widget(edit=ctb, left_widget=bbtn) + _b_title( + x_offs2, v, ctb, bui.Lstr(resource=self._r + '.controllersText') + ) imgw = imgh = 130 - ba.imagewidget(parent=self._root_widget, - position=(x_offs2 + basew * 0.49 - imgw * 0.5, v + 35), - size=(imgw, imgh), - texture=ba.gettexture("controllerIcon"), - draw_controller=ctb) + bui.imagewidget( + parent=self._root_widget, + position=(x_offs2 + basew * 0.49 - imgw * 0.5, v + 35), + size=(imgw, imgh), + texture=bui.gettexture('controllerIcon'), + draw_controller=ctb, + ) - gfxb = self._graphics_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(x_offs3, v), - size=(basew, baseh), - button_type="square", - label="", - on_activate_call=self._do_graphics) - if ba.app.ui.use_toolbars: - pbtn = _ba.get_special_widget("party_button") - ba.widget(edit=gfxb, up_widget=pbtn, right_widget=pbtn) - _b_title(x_offs3, v, gfxb, ba.Lstr(resource=self._r + ".graphicsText")) + gfxb = self._graphics_button = bui.buttonwidget( + parent=self._root_widget, + autoselect=True, + position=(x_offs3, v), + size=(basew, baseh), + button_type='square', + label='', + on_activate_call=self._do_graphics, + ) + if bui.app.ui_v1.use_toolbars: + pbtn = bui.get_special_widget('party_button') + bui.widget(edit=gfxb, up_widget=pbtn, right_widget=pbtn) + _b_title(x_offs3, v, gfxb, bui.Lstr(resource=self._r + '.graphicsText')) imgw = imgh = 110 - ba.imagewidget(parent=self._root_widget, - position=(x_offs3 + basew * 0.49 - imgw * 0.5, v + 42), - size=(imgw, imgh), - texture=ba.gettexture("graphicsIcon"), - draw_controller=gfxb) + bui.imagewidget( + parent=self._root_widget, + position=(x_offs3 + basew * 0.49 - imgw * 0.5, v + 42), + size=(imgw, imgh), + texture=bui.gettexture('graphicsIcon'), + draw_controller=gfxb, + ) - abtn = self._audio_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(x_offs4, v), - size=(basew, baseh), - button_type="square", - label="", - on_activate_call=self._do_audio) - _b_title(x_offs4, v, abtn, ba.Lstr(resource=self._r + ".audioText")) + abtn = self._audio_button = bui.buttonwidget( + parent=self._root_widget, + autoselect=True, + position=(x_offs4, v), + size=(basew, baseh), + button_type='square', + label='', + on_activate_call=self._do_audio, + ) + _b_title(x_offs4, v, abtn, bui.Lstr(resource=self._r + '.audioText')) imgw = imgh = 120 - ba.imagewidget(parent=self._root_widget, - position=(x_offs4 + basew * 0.49 - imgw * 0.5 + 5, v + 35), - size=(imgw, imgh), - color=(1, 1, 0), texture=ba.gettexture("audioIcon"), - draw_controller=abtn) - v -= (baseh - 5) + bui.imagewidget( + parent=self._root_widget, + position=(x_offs4 + basew * 0.49 - imgw * 0.5 + 5, v + 35), + size=(imgw, imgh), + color=(1, 1, 0), + texture=bui.gettexture('audioIcon'), + draw_controller=abtn, + ) - avb = self._advanced_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(x_offs5, v), - size=(basew, baseh), - button_type="square", - label="", - on_activate_call=self._do_advanced) - _b_title(x_offs5, v, avb, ba.Lstr(resource=self._r + ".advancedText")) + v -= baseh - 5 + + avb = self._advanced_button = bui.buttonwidget( + parent=self._root_widget, + autoselect=True, + position=(x_offs5, v), + size=(basew, baseh), + button_type='square', + label='', + on_activate_call=self._do_advanced, + ) + _b_title(x_offs5, v, avb, bui.Lstr(resource=self._r + '.advancedText')) imgw = imgh = 120 - ba.imagewidget(parent=self._root_widget, - position=(x_offs5 + basew * 0.49 - imgw * 0.5 + 5, - v + 35), - size=(imgw, imgh), - color=(0.8, 0.95, 1), - texture=ba.gettexture("advancedIcon"), - draw_controller=avb) + bui.imagewidget( + parent=self._root_widget, + position=(x_offs5 + basew * 0.49 - imgw * 0.5 + 5, v + 35), + size=(imgw, imgh), + color=(0.8, 0.95, 1), + texture=bui.gettexture('advancedIcon'), + draw_controller=avb, + ) - mmb = self._modmgr_button = ba.buttonwidget(parent=self._root_widget, - autoselect=True, - position=(x_offs6, v), - size=(basew, baseh), - button_type="square", - label="", - on_activate_call=self._do_modmanager) - _b_title(x_offs6, v, mmb, ba.Lstr(value="Plugin Manager")) + mmb = self._modmgr_button = bui.buttonwidget(parent=self._root_widget, + autoselect=True, + position=(x_offs6, v), + size=(basew, baseh), + button_type="square", + label="", + on_activate_call=self._do_modmanager) + _b_title(x_offs6, v, mmb, bui.Lstr(value="Plugin Manager")) imgw = imgh = 112 - ba.imagewidget(parent=self._root_widget, - position=(x_offs6 + basew * 0.49 - imgw * 0.5 + 5, - v + 35), - size=(imgw, imgh), - color=(0.8, 0.95, 1), - texture=ba.gettexture("storeIcon"), - draw_controller=mmb) + bui.imagewidget(parent=self._root_widget, + position=(x_offs6 + basew * 0.49 - imgw * 0.5 + 5, + v + 35), + size=(imgw, imgh), + color=(0.8, 0.95, 1), + texture=bui.gettexture("storeIcon"), + draw_controller=mmb) self._restore_state() @@ -2253,113 +2344,145 @@ class NewAllSettingsWindow(ba.Window): @staticmethod def _preload_modules() -> None: """Preload modules we use (called in bg thread).""" - # import bastd.ui.mainmenu as _unused1 - # import bastd.ui.settings.controls as _unused2 - # import bastd.ui.settings.graphics as _unused3 - # import bastd.ui.settings.audio as _unused4 - # import bastd.ui.settings.advanced as _unused5 + import bauiv1lib.mainmenu as _unused1 + import bauiv1lib.settings.controls as _unused2 + import bauiv1lib.settings.graphics as _unused3 + import bauiv1lib.settings.audio as _unused4 + import bauiv1lib.settings.advanced as _unused5 def _do_back(self) -> None: # pylint: disable=cyclic-import - from bastd.ui.mainmenu import MainMenuWindow + from bauiv1lib.mainmenu import MainMenuWindow + self._save_state() - ba.containerwidget(edit=self._root_widget, - transition=self._transition_out) - ba.app.ui.set_main_menu_window( - MainMenuWindow(transition="in_left").get_root_widget()) + bui.containerwidget( + edit=self._root_widget, transition=self._transition_out + ) + assert bui.app.classic is not None + bui.app.ui_v1.set_main_menu_window( + MainMenuWindow(transition='in_left').get_root_widget() + ) def _do_controllers(self) -> None: # pylint: disable=cyclic-import - from bastd.ui.settings.controls import ControlsSettingsWindow + from bauiv1lib.settings.controls import ControlsSettingsWindow + self._save_state() - ba.containerwidget(edit=self._root_widget, transition="out_left") - ba.app.ui.set_main_menu_window(ControlsSettingsWindow( - origin_widget=self._controllers_button).get_root_widget()) + bui.containerwidget(edit=self._root_widget, transition='out_left') + assert bui.app.classic is not None + bui.app.ui_v1.set_main_menu_window( + ControlsSettingsWindow( + origin_widget=self._controllers_button + ).get_root_widget() + ) def _do_graphics(self) -> None: # pylint: disable=cyclic-import - from bastd.ui.settings.graphics import GraphicsSettingsWindow + from bauiv1lib.settings.graphics import GraphicsSettingsWindow + self._save_state() - ba.containerwidget(edit=self._root_widget, transition="out_left") - ba.app.ui.set_main_menu_window(GraphicsSettingsWindow( - origin_widget=self._graphics_button).get_root_widget()) + bui.containerwidget(edit=self._root_widget, transition='out_left') + assert bui.app.classic is not None + bui.app.ui_v1.set_main_menu_window( + GraphicsSettingsWindow( + origin_widget=self._graphics_button + ).get_root_widget() + ) def _do_audio(self) -> None: # pylint: disable=cyclic-import - from bastd.ui.settings.audio import AudioSettingsWindow + from bauiv1lib.settings.audio import AudioSettingsWindow + self._save_state() - ba.containerwidget(edit=self._root_widget, transition="out_left") - ba.app.ui.set_main_menu_window(AudioSettingsWindow( - origin_widget=self._audio_button).get_root_widget()) + bui.containerwidget(edit=self._root_widget, transition='out_left') + assert bui.app.classic is not None + bui.app.ui_v1.set_main_menu_window( + AudioSettingsWindow( + origin_widget=self._audio_button + ).get_root_widget() + ) def _do_advanced(self) -> None: # pylint: disable=cyclic-import - from bastd.ui.settings.advanced import AdvancedSettingsWindow + from bauiv1lib.settings.advanced import AdvancedSettingsWindow + self._save_state() - ba.containerwidget(edit=self._root_widget, transition="out_left") - ba.app.ui.set_main_menu_window(AdvancedSettingsWindow( - origin_widget=self._advanced_button).get_root_widget()) + bui.containerwidget(edit=self._root_widget, transition='out_left') + assert bui.app.classic is not None + bui.app.ui_v1.set_main_menu_window( + AdvancedSettingsWindow( + origin_widget=self._advanced_button + ).get_root_widget() + ) def _do_modmanager(self) -> None: self._save_state() - ba.containerwidget(edit=self._root_widget, transition="out_left") - ba.app.ui.set_main_menu_window(PluginManagerWindow( - origin_widget=self._modmgr_button).get_root_widget()) + bui.containerwidget(edit=self._root_widget, transition="out_left") + bui.app.ui_v1.set_main_menu_window( + PluginManagerWindow( + origin_widget=self._modmgr_button + ).get_root_widget() + ) def _save_state(self) -> None: try: sel = self._root_widget.get_selected_child() if sel == self._controllers_button: - sel_name = "Controllers" + sel_name = 'Controllers' elif sel == self._graphics_button: - sel_name = "Graphics" + sel_name = 'Graphics' elif sel == self._audio_button: - sel_name = "Audio" + sel_name = 'Audio' elif sel == self._advanced_button: - sel_name = "Advanced" + sel_name = 'Advanced' elif sel == self._modmgr_button: - sel_name = "Mod Manager" + sel_name = 'Mod Manager' elif sel == self._back_button: - sel_name = "Back" + sel_name = 'Back' else: - raise ValueError(f"unrecognized selection \"{sel}\"") - ba.app.ui.window_states[type(self)] = {"sel_name": sel_name} + raise ValueError(f'unrecognized selection \'{sel}\'') + assert bui.app.classic is not None + bui.app.ui_v1.window_states[type(self)] = { + 'sel_name': sel_name + } except Exception: - ba.print_exception(f"Error saving state for {self}.") + logging.exception('Error saving state for %s.', self) def _restore_state(self) -> None: try: - sel_name = ba.app.ui.window_states.get(type(self), - {}).get("sel_name") - sel: Optional[ba.Widget] - if sel_name == "Controllers": + assert bui.app.classic is not None + sel_name = bui.app.ui_v1.window_states.get(type(self), {}).get( + 'sel_name' + ) + sel: bui.Widget | None + if sel_name == 'Controllers': sel = self._controllers_button - elif sel_name == "Graphics": + elif sel_name == 'Graphics': sel = self._graphics_button - elif sel_name == "Audio": + elif sel_name == 'Audio': sel = self._audio_button - elif sel_name == "Advanced": + elif sel_name == 'Advanced': sel = self._advanced_button elif sel_name == "Mod Manager": sel = self._modmgr_button - elif sel_name == "Back": + elif sel_name == 'Back': sel = self._back_button else: sel = self._controllers_button if sel is not None: - ba.containerwidget(edit=self._root_widget, selected_child=sel) + bui.containerwidget(edit=self._root_widget, selected_child=sel) except Exception: - ba.print_exception(f"Error restoring state for {self}.") + logging.exception('Error restoring state for %s.', self) -# ba_meta export plugin -class EntryPoint(ba.Plugin): +# ba_meta export babase.Plugin +class EntryPoint(babase.Plugin): def on_app_running(self) -> None: """Called when the app is being launched.""" - from bastd.ui.settings import allsettings + from bauiv1lib.settings import allsettings allsettings.AllSettingsWindow = NewAllSettingsWindow DNSBlockWorkaround.apply() - asyncio.set_event_loop(ba._asyncio._asyncio_event_loop) + asyncio.set_event_loop(babase._asyncio._asyncio_event_loop) startup_tasks = StartupTasks() loop = asyncio.get_event_loop() loop.create_task(startup_tasks.execute()) diff --git a/plugins/minigames.json b/plugins/minigames.json index 08eb34a..a95fc4f 100644 --- a/plugins/minigames.json +++ b/plugins/minigames.json @@ -266,6 +266,12 @@ } ], "versions": { + "1.1.0": { + "api_version": 8, + "commit_sha": "0069f15", + "released_on": "08-06-2023", + "md5sum": "b8168bd3e6fae96b9339a727bd50842f" + }, "1.0.0": { "api_version": 7, "commit_sha": "095a773", diff --git a/plugins/minigames/hot_bomb.py b/plugins/minigames/hot_bomb.py index 66a81c6..ba68c09 100644 --- a/plugins/minigames/hot_bomb.py +++ b/plugins/minigames/hot_bomb.py @@ -2,7 +2,7 @@ # """Hot Bomb game by SEBASTIAN2059 and zPanxo""" -# ba_meta require api 7 +# ba_meta require api 8 # (see https://ballistica.net/wiki/meta-tag-system) from __future__ import annotations @@ -11,15 +11,19 @@ from typing import TYPE_CHECKING import random -import ba -import _ba -from bastd.actor.playerspaz import PlayerSpaz -from bastd.actor.scoreboard import Scoreboard -from bastd.actor.powerupbox import PowerupBoxFactory -from bastd.gameutils import SharedObjects -from ba._messages import StandMessage -from bastd.actor.bomb import Bomb -from bastd.actor.spaz import PickupMessage, BombDiedMessage +from bascenev1lib.actor.playerspaz import PlayerSpaz +from bascenev1lib.actor.scoreboard import Scoreboard +from bascenev1lib.actor.powerupbox import PowerupBoxFactory +from bascenev1lib.gameutils import SharedObjects +from bascenev1lib.actor.bomb import Bomb +from bascenev1lib.actor.spaz import PickupMessage, BombDiedMessage + +from bascenev1._messages import StandMessage + +import bascenev1 as bs +import _bascenev1 as _bs +import _babase + if TYPE_CHECKING: from typing import Any, Sequence, Dict, Type, List, Optional, Union @@ -36,7 +40,7 @@ class ExplodeHitMessage: """Tell an object it was hit by an explosion.""" -class Ball(ba.Actor): +class Ball(bs.Actor): """A lovely bomb mortal""" def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0), timer: int = 5, d_time=0.2, color=(1, 1, 1)): @@ -44,7 +48,7 @@ class Ball(ba.Actor): shared = SharedObjects.get() activity = self.getactivity() - self.explosion_material = ba.Material() + self.explosion_material = bs.Material() self.explosion_material.add_actions( conditions=( 'they_have_material', shared.object_material @@ -56,7 +60,7 @@ class Ball(ba.Actor): ), ) - ba.playsound(ba.getsound('scamper01'), volume=0.4) + bs.getsound('scamper01').play(volume=0.4) # Spawn just above the provided point. self._spawn_pos = (position[0], position[1] + 1.0, position[2]) self.last_players_to_touch: Dict[int, Player] = {} @@ -64,10 +68,10 @@ class Ball(ba.Actor): assert activity is not None assert isinstance(activity, HotBombGame) pmats = [shared.object_material, activity.ball_material] - self.node = ba.newnode('prop', + self.node = bs.newnode('prop', delegate=self, attrs={ - 'model': activity.ball_model, + 'mesh': activity.ball_mesh, 'color_texture': activity.ball_tex, 'body': activity.ball_body, 'body_scale': 1.0 if activity.ball_body == 'sphere' else 0.8, @@ -84,7 +88,7 @@ class Ball(ba.Actor): self.scale = 1.0 if activity.ball_body == 'sphere' else 0.8 self.color_l = (1, 1, 1) - self.light = ba.newnode('light', + self.light = bs.newnode('light', owner=self.node, attrs={ 'color': color, @@ -96,24 +100,24 @@ class Ball(ba.Actor): self.node.connectattr('position', self.light, 'position') self.animate_light = None - self._particles = ba.Timer(0.1, call=ba.WeakCall(self.particles), repeat=True) - self._sound_effect = ba.Timer(4, call=ba.WeakCall(self.sound_effect), repeat=True) + self._particles = bs.Timer(0.1, call=bs.WeakCall(self.particles), repeat=True) + self._sound_effect = bs.Timer(4, call=bs.WeakCall(self.sound_effect), repeat=True) self.d_time = d_time if timer is not None: timer = int(timer) self._timer = timer - self._counter: Optional[ba.Node] + self._counter: Optional[bs.Node] if self._timer is not None: self._count = self._timer - self._tick_timer = ba.Timer(1.0, - call=ba.WeakCall(self._tick), + self._tick_timer = bs.Timer(1.0, + call=bs.WeakCall(self._tick), repeat=True) - m = ba.newnode('math', owner=self.node, attrs={ + m = bs.newnode('math', owner=self.node, attrs={ 'input1': (0, 0.6, 0), 'operation': 'add'}) self.node.connectattr('position', m, 'input2') - self._counter = ba.newnode( + self._counter = bs.newnode( 'text', owner=self.node, attrs={ @@ -132,7 +136,7 @@ class Ball(ba.Actor): def particles(self): if self.node: - ba.emitfx( + bs.emitfx( position=self.node.position, velocity=(0, 3, 0), count=9, @@ -143,19 +147,19 @@ class Ball(ba.Actor): def sound_effect(self): if self.node: - ba.playsound(ba.getsound('scamper01'), volume=0.4) + bs.getsound('scamper01').play(volume=0.4) def explode(self, color=(3, 1, 0)) -> None: sound = random.choice(['explosion01', 'explosion02', 'explosion03', 'explosion04', 'explosion05']) - ba.playsound(ba.getsound(sound), volume=1) - ba.emitfx(position=self.node.position, + bs.getsound(sound).play(volume=1) + bs.emitfx(position=self.node.position, velocity=(0, 10, 0), count=100, scale=1.0, spread=1.0, chunk_type='spark') - explosion = ba.newnode( + explosion = bs.newnode( 'explosion', attrs={ 'position': self.node.position, @@ -165,7 +169,7 @@ class Ball(ba.Actor): 'color': color } ) - ba.timer(1.0, explosion.delete) + bs.timer(1.0, explosion.delete) if color == (5, 1, 0): color = (1, 0, 0) self.activity._handle_score(1) @@ -173,7 +177,7 @@ class Ball(ba.Actor): color = (0, 0, 1) self.activity._handle_score(0) - scorch = ba.newnode( + scorch = bs.newnode( 'scorch', attrs={ 'position': self.node.position, @@ -186,7 +190,7 @@ class Ball(ba.Actor): # Set our position a bit lower so we throw more things upward. rmats = (self.explosion_material,) - self.region = ba.newnode( + self.region = bs.newnode( 'region', delegate=self, attrs={ @@ -196,7 +200,7 @@ class Ball(ba.Actor): 'materials': rmats }, ) - ba.timer(0.05, self.region.delete) + bs.timer(0.05, self.region.delete) def _tick(self) -> None: c = self.color_l @@ -213,19 +217,19 @@ class Ball(ba.Actor): self._count -= 1 assert self._counter self._counter.text = str(self._count) - ba.playsound(ba.getsound('tick')) + bs.getsound('tick').play() if self._count == 1: - self._animate = ba.animate( + self._animate = bs.animate( self.node, - 'model_scale', + 'mesh_scale', { - 0: self.node.model_scale, + 0: self.node.mesh_scale, 0.1: 1.5, 0.2: self.scale }, loop=True ) - self.animate_light = ba.animate_array( + self.animate_light = bs.animate_array( self.light, 'color', 3, @@ -237,17 +241,17 @@ class Ball(ba.Actor): loop=True ) else: - self._animate = ba.animate( + self._animate = bs.animate( self.node, - 'model_scale', + 'mesh_scale', { - 0: self.node.model_scale, + 0: self.node.mesh_scale, 0.5: 1.5, 1.0: self.scale }, loop=True ) - self.animate_light = ba.animate_array( + self.animate_light = bs.animate_array( self.light, 'color', 3, @@ -261,7 +265,7 @@ class Ball(ba.Actor): ) def handlemessage(self, msg: Any) -> Any: - if isinstance(msg, ba.DieMessage): + if isinstance(msg, bs.DieMessage): if not self.node: return self.node.delete() @@ -270,11 +274,11 @@ class Ball(ba.Actor): activity.handlemessage(BallDiedMessage(self)) # If we go out of bounds, move back to where we started. - elif isinstance(msg, ba.OutOfBoundsMessage): + elif isinstance(msg, bs.OutOfBoundsMessage): assert self.node self.node.position = self._spawn_pos - elif isinstance(msg, ba.PickedUpMessage): + elif isinstance(msg, bs.PickedUpMessage): d = self.d_time def damage(): @@ -284,16 +288,16 @@ class Ball(ba.Actor): spaz.node.color = (spaz.node.color[0]-0.1, spaz.node.color[1]-0.1, spaz.node.color[2]-0.1) if spaz.node.hold_node != self.node: - self.handlemessage(ba.DroppedMessage(spaz.node)) + self.handlemessage(bs.DroppedMessage(spaz.node)) if spaz.hitpoints > 10000: - ba.playsound(ba.getsound('fuse01'), volume=0.3) + bs.getsound('fuse01').play(volume=0.3) spaz.hitpoints -= 10000 spaz._last_hit_time = None spaz._num_time_shit = 0 spaz.node.hurt = 1.0 - float(spaz.hitpoints) / spaz.hitpoints_max else: - spaz.handlemessage(ba.DieMessage()) - ba.emitfx( + spaz.handlemessage(bs.DieMessage()) + bs.emitfx( position=msg.node.position, velocity=(0, 3, 0), count=20 if d == 0.2 else 25 if d == 0.1 else 30 if d == 0.05 else 15, @@ -303,14 +307,13 @@ class Ball(ba.Actor): else: self.damage_timer = None - self.damage_timer = ba.Timer(self.d_time, damage, repeat=True) + self.damage_timer = bs.Timer(self.d_time, damage, repeat=True) - elif isinstance(msg, ba.DroppedMessage): - from ba import _math + elif isinstance(msg, bs.DroppedMessage): spaz = msg.node.getdelegate(PlayerSpaz) self.damage_timer = None - elif isinstance(msg, ba.HitMessage): + elif isinstance(msg, bs.HitMessage): assert self.node assert msg.force_direction is not None self.node.handlemessage( @@ -329,14 +332,14 @@ class Ball(ba.Actor): self.last_players_to_touch[s_player.team.id] = s_player elif isinstance(msg, ExplodeHitMessage): - node = ba.getcollision().opposingnode + node = bs.getcollision().opposingnode if not self.node: return nodepos = self.region.position mag = 2000.0 node.handlemessage( - ba.HitMessage( + bs.HitMessage( pos=nodepos, velocity=(0, 0, 0), magnitude=mag, @@ -345,7 +348,7 @@ class Ball(ba.Actor): radius=2.0 ) ) - self.handlemessage(ba.DieMessage()) + self.handlemessage(bs.DieMessage()) else: super().handlemessage(msg) @@ -368,7 +371,7 @@ class NewPlayerSpaz(PlayerSpaz): 0, 0, 0, 160, 0, 0, 0, 0, 205, 0) - ba.timer(0.4, self.refresh) + bs.timer(0.4, self.refresh) def refresh(self): self.reload = True @@ -390,7 +393,7 @@ class NewPlayerSpaz(PlayerSpaz): bomb_type = self.bomb_type if bomb_type == 'banana': - ba.playsound(ba.getsound('penguinHit1'), volume=0.3) + bs.getsound('penguinHit1').play(volume=0.3) bomb = NewBomb(position=(pos[0], pos[1] + 0.7, pos[2]), velocity=(vel[0], vel[1], vel[2]), bomb_type=bomb_type, @@ -409,7 +412,7 @@ class NewPlayerSpaz(PlayerSpaz): if dropping_bomb: self.bomb_count -= 1 bomb.node.add_death_action( - ba.WeakCall(self.handlemessage, BombDiedMessage())) + bs.WeakCall(self.handlemessage, BombDiedMessage())) self._pick_up(bomb.node) try: @@ -434,10 +437,10 @@ class NewPlayerSpaz(PlayerSpaz): if not self.node: return None try: - collision = ba.getcollision() + collision = bs.getcollision() opposingnode = collision.opposingnode opposingbody = collision.opposingbody - except ba.NotFoundError: + except bs.NotFoundError: return True if opposingnode.getnodetype() == 'spaz': player = opposingnode.getdelegate(PlayerSpaz, True).getplayer(Player, True) @@ -447,18 +450,18 @@ class NewPlayerSpaz(PlayerSpaz): return super().handlemessage(msg) -class Player(ba.Player['Team']): +class Player(bs.Player['Team']): """Our player type for this game.""" -class Team(ba.Team[Player]): +class Team(bs.Team[Player]): """Our team type for this game.""" def __init__(self) -> None: self.score = 0 -lang = ba.app.lang.language +lang = bs.app.lang.language if lang == 'Spanish': name = 'Hot Bomb' description = 'Consigue explotar la bomba en\nel equipo enemigo para ganar.' @@ -501,20 +504,20 @@ else: body = ['Sphere', 'Box'] -# ba_meta export game -class HotBombGame(ba.TeamGameActivity[Player, Team]): +# ba_meta export bascenev1.GameActivity +class HotBombGame(bs.TeamGameActivity[Player, Team]): """New game.""" name = name description = description available_settings = [ - ba.IntSetting( + bs.IntSetting( 'Score to Win', min_value=1, default=5, increment=1, ), - ba.IntChoiceSetting( + bs.IntChoiceSetting( 'Time Limit', choices=[ ('None', 0), @@ -526,7 +529,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ], default=0, ), - ba.FloatChoiceSetting( + bs.FloatChoiceSetting( 'Respawn Times', choices=[ ('Shorter', 0.25), @@ -538,7 +541,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): default=0.5, ), - ba.FloatChoiceSetting( + bs.FloatChoiceSetting( difficulty, choices=[ (difficulty_o[0], 0.15), @@ -548,13 +551,13 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): default=0.15, ), - ba.IntChoiceSetting( + bs.IntChoiceSetting( bomb_timer, choices=[(str(choice)+'s', choice) for choice in range(2, 11)], default=5, ), - ba.IntChoiceSetting( + bs.IntChoiceSetting( num_bones, choices=[ (b_count[0], 0), @@ -564,31 +567,31 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): default=2, ), - ba.IntChoiceSetting( + bs.IntChoiceSetting( ball_body, choices=[(b, body.index(b)) for b in body], default=0, ), - ba.IntChoiceSetting( + bs.IntChoiceSetting( wall_color, choices=[(color, w_c.index(color)) for color in w_c], default=0, ), - ba.BoolSetting('Epic Mode', default=False), - ba.BoolSetting(space_wall, default=True), - ba.BoolSetting(bomb, default=True), - ba.BoolSetting(shield, default=False), + bs.BoolSetting('Epic Mode', default=False), + bs.BoolSetting(space_wall, default=True), + bs.BoolSetting(bomb, default=True), + bs.BoolSetting(shield, default=False), ] - default_music = ba.MusicType.HOCKEY + default_music = bs.MusicType.HOCKEY @classmethod - def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: - return issubclass(sessiontype, ba.DualTeamSession) + def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool: + return issubclass(sessiontype, bs.DualTeamSession) @classmethod - def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]: return ['Football Stadium'] def __init__(self, settings: dict): @@ -604,19 +607,19 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): self._ball_body = int(settings[ball_body]) self.bodys = ['sphere', 'crate'] - self.models = ['bombSticky', 'powerupSimple'] + self.meshs = ['bombSticky', 'powerupSimple'] shared = SharedObjects.get() self._scoreboard = Scoreboard() - self._cheer_sound = ba.getsound('cheer') - self._chant_sound = ba.getsound('crowdChant') - self._foghorn_sound = ba.getsound('foghorn') - self._swipsound = ba.getsound('swip') - self._whistle_sound = ba.getsound('refWhistle') - self.ball_model = ba.getmodel(self.models[self._ball_body]) + self._cheer_sound = bs.getsound('cheer') + self._chant_sound = bs.getsound('crowdChant') + self._foghorn_sound = bs.getsound('foghorn') + self._swipsound = bs.getsound('swip') + self._whistle_sound = bs.getsound('refWhistle') + self.ball_mesh = bs.getmesh(self.meshs[self._ball_body]) self.ball_body = self.bodys[self._ball_body] - self.ball_tex = ba.gettexture('powerupCurse') - self._ball_sound = ba.getsound('splatter') + self.ball_tex = bs.gettexture('powerupCurse') + self._ball_sound = bs.getsound('splatter') self.last_point = None self.colors = [(0.25, 0.5, 0.25), (1, 0.15, 0.15), (1, 0.5, 0), (1, 1, 0), @@ -624,7 +627,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): # self.slow_motion = self._epic_mode - self.ball_material = ba.Material() + self.ball_material = bs.Material() self.ball_material.add_actions(actions=(('modify_part_collision', 'friction', 0.5))) self.ball_material.add_actions(conditions=('they_have_material', @@ -664,11 +667,11 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): 'they_have_material', PowerupBoxFactory.get().powerup_material), actions=( ('modify_part_collision', 'physical', False), - ('message', 'their_node', 'at_connect', ba.DieMessage()) + ('message', 'their_node', 'at_connect', bs.DieMessage()) ) ) - self._score_region_material = ba.Material() + self._score_region_material = bs.Material() self._score_region_material.add_actions( conditions=( 'they_have_material', self.ball_material @@ -680,7 +683,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ) ) ##### - self._check_region_material = ba.Material() + self._check_region_material = bs.Material() self._check_region_material.add_actions( conditions=( 'they_have_material', self.ball_material @@ -692,7 +695,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ) ) - self._reaction_material = ba.Material() + self._reaction_material = bs.Material() self._reaction_material.add_actions( conditions=( 'they_have_material', shared.player_material @@ -714,7 +717,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ) ) - self._collide = ba.Material() + self._collide = bs.Material() self._collide.add_actions( conditions=( ('they_are_different_node_than_us', ), @@ -726,7 +729,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ) ) - self._wall_material = ba.Material() + self._wall_material = bs.Material() self._wall_material.add_actions( conditions=( 'we_are_older_than', 1 @@ -736,7 +739,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ) ) - self.ice_material = ba.Material() + self.ice_material = bs.Material() self.ice_material.add_actions( actions=( 'modify_part_collision', 'friction', 0.05 @@ -762,16 +765,16 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): super().on_begin() self.setup_standard_time_limit(self._time_limit) self._ball_spawn_pos = (random.choice([-5, 5]), 4, 0) - ba.timer(5, self._spawn_ball) - ba.timer(0.1, self.update_ball, repeat=True) + bs.timer(5, self._spawn_ball) + bs.timer(0.1, self.update_ball, repeat=True) self.add_game_complements() self.add_map_complements() self._update_scoreboard() - ba.playsound(self._chant_sound) + self._chant_sound.play() def _reaction(self): - node: ba.Node = ba.getcollision().opposingnode - ba.playsound(ba.getsound('hiss'), volume=0.75) + node: bs.Node = bs.getcollision().opposingnode + bs.getsound('hiss').play(volume=0.75) node.handlemessage( "impulse", @@ -781,7 +784,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): -node.velocity[0], -node.velocity[1], -node.velocity[2] ) - ba.emitfx( + bs.emitfx( position=node.position, count=20, scale=1.5, @@ -812,7 +815,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): g += 1 ######################## self.wall_color = self.colors[self._wall_color] - part_of_wall = ba.newnode( + part_of_wall = bs.newnode( 'locator', attrs={ 'shape': 'box', @@ -825,7 +828,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): 'size': [14.7, 2, 16] } ) - part_of_wall2 = ba.newnode( + part_of_wall2 = bs.newnode( 'locator', attrs={ 'shape': 'box', @@ -838,7 +841,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): 'size': [0.3, 30, 13] if self._space_under_wall else [0.3, 75, 13] } ) - wall = ba.newnode( + wall = bs.newnode( 'region', attrs={ 'position': (0, 1.11, 0.5) if self._space_under_wall else (0, 0.75, 0.5), @@ -849,7 +852,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ) # RESET REGION pos = (0, 5.3, 0) - ba.newnode( + bs.newnode( 'region', attrs={ 'position': pos, @@ -859,7 +862,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): } ) - ba.newnode( + bs.newnode( 'region', attrs={ 'position': pos, @@ -871,7 +874,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): def add_map_complements(self): # TEXT - text = ba.newnode('text', + text = bs.newnode('text', attrs={'position': (0, 2.5, -6), 'text': 'Hot Bomb by\nSEBASTIAN2059 and zPanxo', 'in_world': True, @@ -900,7 +903,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): ], } for i in walls_data: - w = ba.newnode( + w = bs.newnode( 'region', attrs={ 'position': walls_data[i][0], @@ -938,10 +941,10 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): texture='powerupIceBombs' ) - def spawn_player(self, player: Player) -> ba.Actor: + def spawn_player(self, player: Player) -> bs.Actor: position = self.get_position(player) name = player.getname() - display_color = _ba.safecolor(player.color, target_intensity=0.75) + display_color = _babase.safecolor(player.color, target_intensity=0.75) actor = NewPlayerSpaz( color=player.color, highlight=player.highlight, @@ -973,18 +976,18 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): StandMessage( position, random.uniform(0, 360))) - ba.playsound(ba.getsound('spawn'), volume=0.6) + bs.getsound('spawn').play(volume=0.6) return actor def on_team_join(self, team: Team) -> None: self._update_scoreboard() def _handle_ball_player_collide(self) -> None: - collision = ba.getcollision() + collision = bs.getcollision() try: ball = collision.sourcenode.getdelegate(Ball, True) player = collision.opposingnode.getdelegate(PlayerSpaz, True).getplayer(Player, True) - except ba.NotFoundError: + except bs.NotFoundError: return ball.last_players_to_touch[player.team.id] = player @@ -1000,19 +1003,19 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): if self._ball.scored: return - ba.playsound(ba.getsound('laser')) + bs.getsound('laser').play() self._ball._count = self._bomb_timer self._ball._counter.text = str(self._bomb_timer) - self._ball._tick_timer = ba.Timer( + self._ball._tick_timer = bs.Timer( 1.0, - call=ba.WeakCall(self._ball._tick), + call=bs.WeakCall(self._ball._tick), repeat=True ) - self._ball._animate = ba.animate( + self._ball._animate = bs.animate( self._ball.node, - 'model_scale', + 'mesh_scale', { - 0: self._ball.node.model_scale, + 0: self._ball.node.mesh_scale, 0.1: self._ball.scale } ) @@ -1026,16 +1029,16 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): return if not self._ball.node: return - gnode = ba.getactivity().globalsnode + gnode = bs.getactivity().globalsnode if self._ball.node.position[0] > 0: - self._ball.node.color_texture = ba.gettexture('powerupIceBombs') - ba.animate_array(gnode, 'vignette_outer', 3, {1.0: (0.4, 0.4, 0.9)}) + self._ball.node.color_texture = bs.gettexture('powerupIceBombs') + bs.animate_array(gnode, 'vignette_outer', 3, {1.0: (0.4, 0.4, 0.9)}) self._ball.color_l = (0, 0, 3.5) self._ball._counter.color = (0, 0, 5) else: - self._ball.node.color_texture = ba.gettexture('powerupPunch') - ba.animate_array(gnode, 'vignette_outer', 3, {1.0: (0.6, 0.45, 0.45)}) + self._ball.node.color_texture = bs.gettexture('powerupPunch') + bs.animate_array(gnode, 'vignette_outer', 3, {1.0: (0.6, 0.45, 0.45)}) self._ball.color_l = (2.5, 0, 0) self._ball._counter.color = (1.2, 0, 0) @@ -1056,7 +1059,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): # Tell all players to celebrate. for player in team.players: if player.actor: - player.actor.handlemessage(ba.CelebrateMessage(2.0)) + player.actor.handlemessage(bs.CelebrateMessage(2.0)) # If we've got the player from the scoring team that last # touched us, give them points. @@ -1076,16 +1079,16 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): # Tell all players to celebrate. for player in team.players: if player.actor: - player.actor.handlemessage(ba.DieMessage()) + player.actor.handlemessage(bs.DieMessage()) - ba.playsound(self._foghorn_sound) - ba.playsound(self._cheer_sound) + self._foghorn_sound.play() + self._cheer_sound.play() - ba.cameraflash(duration=10.0) + bs.cameraflash(duration=10.0) self._update_scoreboard() def end_game(self) -> None: - results = ba.GameResults() + results = bs.GameResults() for team in self.teams: results.set_team_score(team, team.score) self.end(results=results) @@ -1098,22 +1101,22 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): def handlemessage(self, msg: Any) -> Any: # Respawn dead players if they're still in the game. - if isinstance(msg, ba.PlayerDiedMessage): + if isinstance(msg, bs.PlayerDiedMessage): player = msg.getplayer(Player) spaz = player.actor spaz.node.color = (-1, -1, -1) - spaz.node.color_mask_texture = ba.gettexture('bonesColorMask') - spaz.node.color_texture = ba.gettexture('bonesColor') - spaz.node.head_model = ba.getmodel('bonesHead') - spaz.node.hand_model = ba.getmodel('bonesHand') - spaz.node.torso_model = ba.getmodel('bonesTorso') - spaz.node.pelvis_model = ba.getmodel('bonesPelvis') - spaz.node.upper_arm_model = ba.getmodel('bonesUpperArm') - spaz.node.forearm_model = ba.getmodel('bonesForeArm') - spaz.node.upper_leg_model = ba.getmodel('bonesUpperLeg') - spaz.node.lower_leg_model = ba.getmodel('bonesLowerLeg') - spaz.node.toes_model = ba.getmodel('bonesToes') + spaz.node.color_mask_texture = bs.gettexture('bonesColorMask') + spaz.node.color_texture = bs.gettexture('bonesColor') + spaz.node.head_mesh = bs.getmesh('bonesHead') + spaz.node.hand_mesh = bs.getmesh('bonesHand') + spaz.node.torso_mesh = bs.getmesh('bonesTorso') + spaz.node.pelvis_mesh = bs.getmesh('bonesPelvis') + spaz.node.upper_arm_mesh = bs.getmesh('bonesUpperArm') + spaz.node.forearm_mesh = bs.getmesh('bonesForeArm') + spaz.node.upper_leg_mesh = bs.getmesh('bonesUpperLeg') + spaz.node.lower_leg_mesh = bs.getmesh('bonesLowerLeg') + spaz.node.toes_mesh = bs.getmesh('bonesToes') spaz.node.style = 'bones' # Augment standard behavior... super().handlemessage(msg) @@ -1124,26 +1127,26 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): if not self.has_ended(): try: if self._ball._count == 1: - ba.timer(3.0, self._spawn_ball) + bs.timer(3.0, self._spawn_ball) except Exception: return else: super().handlemessage(msg) def _flash_ball_spawn(self, pos, color=(1, 0, 0)) -> None: - light = ba.newnode('light', + light = bs.newnode('light', attrs={ 'position': pos, 'height_attenuated': False, 'color': color }) - ba.animate(light, 'intensity', {0.0: 0, 0.25: 0.2, 0.5: 0}, loop=True) - ba.timer(1.0, light.delete) + bs.animate(light, 'intensity', {0.0: 0, 0.25: 0.2, 0.5: 0}, loop=True) + bs.timer(1.0, light.delete) def _spawn_ball(self) -> None: timer = self._bomb_timer - ba.playsound(self._swipsound) - ba.playsound(self._whistle_sound) + self._swipsound.play() + self._whistle_sound.play() pos = (random.choice([5, -5]), 2, 0) if self.last_point != None: if self.last_point == 0: @@ -1156,10 +1159,10 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): counter_color = (1, 0, 0) if pos[0] == -5 else (0, 0, 5) # self._flash_ball_spawn(pos,color) self._ball = Ball(position=pos, timer=timer, d_time=self.damage_time, color=color) - self._ball.node.color_texture = ba.gettexture(texture) + self._ball.node.color_texture = bs.gettexture(texture) self._ball._counter.color = counter_color - def get_position(self, player: Player) -> ba.Actor: + def get_position(self, player: Player) -> bs.Actor: position = (0, 1, 0) team = player.team.id if team == 0: @@ -1173,8 +1176,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): def respawn_player(self, player: PlayerType, respawn_time: Optional[float] = None) -> None: - import _ba - from ba._general import Call, WeakCall + from babase._general import WeakCall assert player if respawn_time is None: @@ -1189,8 +1191,8 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): respawn_time = round(max(1.0, respawn_time), 0) if player.actor and not self.has_ended(): - from bastd.actor.respawnicon import RespawnIcon - player.customdata['respawn_timer'] = _ba.Timer( + from bascenev1lib.actor.respawnicon import RespawnIcon + player.customdata['respawn_timer'] = _bs.Timer( respawn_time, WeakCall(self.spawn_player_if_exists, player)) player.customdata['respawn_icon'] = RespawnIcon( player, respawn_time) @@ -1198,7 +1200,7 @@ class HotBombGame(ba.TeamGameActivity[Player, Team]): def spawn_player_if_exists(self, player: PlayerType) -> None: """ A utility method which calls self.spawn_player() *only* if the - ba.Player provided still exists; handy for use in timers and whatnot. + bs.Player provided still exists; handy for use in timers and whatnot. There is no need to override this; just override spawn_player(). """ @@ -1229,21 +1231,21 @@ class ImpactMessage: """Tell an object it touched something.""" -class NewBomb(ba.Actor): +class NewBomb(bs.Actor): def __init__(self, position: Sequence[float] = (0, 1, 0), velocity: Sequence[float] = (0, 0, 0), bomb_type: str = '', radius: float = 2.0, - source_player: ba.Player = None, - owner: ba.Node = None): + source_player: bs.Player = None, + owner: bs.Node = None): super().__init__() shared = SharedObjects.get() # Material for powerups. - self.bomb_material = ba.Material() - self.explode_material = ba.Material() + self.bomb_material = bs.Material() + self.explode_material = bs.Material() self.bomb_material.add_actions( conditions=( @@ -1276,12 +1278,12 @@ class NewBomb(ba.Actor): owner_color = self.owner.source_player._team.color if self.bomb_type == 'banana': - self.node: ba.Node = ba.newnode('prop', delegate=self, attrs={ + self.node: bs.Node = bs.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, - 'color_texture': ba.gettexture('powerupBomb'), - 'model': ba.getmodel('penguinTorso'), - 'model_scale': 0.7, + 'color_texture': bs.gettexture('powerupBomb'), + 'mesh': bs.getmesh('penguinTorso'), + 'mesh_scale': 0.7, 'body_scale': 0.7, 'density': 3, 'reflection': 'soft', @@ -1291,19 +1293,19 @@ class NewBomb(ba.Actor): 'owner': owner, 'materials': (shared.object_material, self.bomb_material)}) - ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1, 0.26: 0.7}) - self.light = ba.newnode('light', owner=self.node, attrs={ + bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: 1, 0.26: 0.7}) + self.light = bs.newnode('light', owner=self.node, attrs={ 'color': owner_color, 'volume_intensity_scale': 2.0, 'intensity': 1, 'radius': 0.1}) self.node.connectattr('position', self.light, 'position') - self.spawn: ba.Timer = ba.Timer( + self.spawn: bs.Timer = bs.Timer( 10.0, self._check, repeat=True) def _impact(self) -> None: - node = ba.getcollision().opposingnode + node = bs.getcollision().opposingnode node_delegate = node.getdelegate(object) if node: if (node is self.owner): @@ -1316,7 +1318,7 @@ class NewBomb(ba.Actor): pos = self.node.position rmats = (self.explode_material,) - self.explode_region = ba.newnode( + self.explode_region = bs.newnode( 'region', delegate=self, attrs={ @@ -1327,14 +1329,14 @@ class NewBomb(ba.Actor): }, ) if self.bomb_type == 'banana': - ba.playsound(ba.getsound('stickyImpact'), volume=0.35) - a = ba.emitfx(position=self.node.position, + bs.getsound('stickyImpact').play(volume=0.35) + a = bs.emitfx(position=self.node.position, velocity=(0, 1, 0), count=15, scale=1.0, spread=0.1, chunk_type='spark') - scorch = ba.newnode('scorch', + scorch = bs.newnode('scorch', attrs={ 'position': self.node.position, 'size': 1.0, @@ -1342,20 +1344,20 @@ class NewBomb(ba.Actor): 'color': (1, 1, 0) }) - ba.animate(scorch, 'size', {0: 1.0, 5: 0}) - ba.timer(5, scorch.delete) + bs.animate(scorch, 'size', {0: 1.0, 5: 0}) + bs.timer(5, scorch.delete) - ba.timer(0.05, self.explode_region.delete) - ba.timer(0.001, ba.WeakCall(self.handlemessage, ba.DieMessage())) + bs.timer(0.05, self.explode_region.delete) + bs.timer(0.001, bs.WeakCall(self.handlemessage, bs.DieMessage())) def _touch_player(self): - node = ba.getcollision().opposingnode - collision = ba.getcollision() + node = bs.getcollision().opposingnode + collision = bs.getcollision() try: player = collision.opposingnode.getdelegate(PlayerSpaz, True).getplayer( Player, True) - except ba.NotFoundError: + except bs.NotFoundError: return if self.bomb_type == 'banana': @@ -1366,7 +1368,7 @@ class NewBomb(ba.Actor): if player.team == owner_team: return player.actor.node.handlemessage('knockout', 500.0) - ba.animate_array(player.actor.node, 'color', 3, { + bs.animate_array(player.actor.node, 'color', 3, { 0: color, 0.1: (1.5, 1, 0), 0.5: (1.5, 1, 0), 0.6: color}) def _check(self) -> None: @@ -1377,10 +1379,10 @@ class NewBomb(ba.Actor): self._explode() elif isinstance(msg, ImpactMessage): self._impact() - elif isinstance(msg, ba.DieMessage): + elif isinstance(msg, bs.DieMessage): if self.node: self.node.delete() - elif isinstance(msg, ba.OutOfBoundsMessage): + elif isinstance(msg, bs.OutOfBoundsMessage): if self.node: self.node.delete() @@ -1388,7 +1390,7 @@ class NewBomb(ba.Actor): class HealthFactory: - """Wraps up media and other resources used by ba.Bombs. + """Wraps up media and other resources used by bs.Bombs. category: Gameplay Classes @@ -1397,25 +1399,25 @@ class HealthFactory: Attributes: - health_model - The ba.Model of a standard health. + health_mesh + The bs.mesh of a standard health. health_tex - The ba.Texture for health. + The bs.Texture for health. activate_sound - A ba.Sound for an activating ??. + A bs.Sound for an activating ??. health_material - A ba.Material applied to health. + A bs.Material applied to health. """ - _STORENAME = ba.storagename() + _STORENAME = bs.storagename() @classmethod def get(cls) -> HealthFactory: """Get/create a shared EggFactory object.""" - activity = ba.getactivity() + activity = bs.getactivity() factory = activity.customdata.get(cls._STORENAME) if factory is None: factory = HealthFactory() @@ -1431,15 +1433,15 @@ class HealthFactory: """ shared = SharedObjects.get() - self.health_model = ba.getmodel('egg') + self.health_mesh = bs.getmesh('egg') - self.health_tex = ba.gettexture('eggTex1') + self.health_tex = bs.gettexture('eggTex1') - self.health_sound = ba.getsound('activateBeep') + self.health_sound = bs.getsound('activateBeep') # Set up our material so new bombs don't collide with objects # that they are initially overlapping. - self.health_material = ba.Material() + self.health_material = bs.Material() self.health_material.add_actions( conditions=( @@ -1465,7 +1467,7 @@ class HealthFactory: 'friction', 0.3)) -class HealthBox(ba.Actor): +class HealthBox(bs.Actor): def __init__(self, position: Sequence[float] = (0, 1, 0), velocity: Sequence[float] = (0, 0, 0), @@ -1474,7 +1476,7 @@ class HealthBox(ba.Actor): shared = SharedObjects.get() factory = HealthFactory.get() - self.healthbox_material = ba.Material() + self.healthbox_material = bs.Material() self.healthbox_material.add_actions( conditions=( 'they_are_different_node_than_us', @@ -1483,13 +1485,13 @@ class HealthBox(ba.Actor): ('modify_part_collision', 'collide', True) ) ) - self.node: ba.Node = ba.newnode('prop', delegate=self, attrs={ + self.node: bs.Node = bs.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, - 'color_texture': ba.gettexture(texture), - 'model': ba.getmodel('powerup'), - 'light_model': ba.getmodel('powerupSimple'), - 'model_scale': 1, + 'color_texture': bs.gettexture(texture), + 'mesh': bs.getmesh('powerup'), + 'light_mesh': bs.getmesh('powerupSimple'), + 'mesh_scale': 1, 'body': 'crate', 'body_scale': 1, 'density': 1, @@ -1500,44 +1502,44 @@ class HealthBox(ba.Actor): 'shadow_size': 0.0, 'materials': (shared.object_material, self.healthbox_material, factory.health_material)}) - self.light = ba.newnode('light', owner=self.node, attrs={ + self.light = bs.newnode('light', owner=self.node, attrs={ 'color': (1, 1, 1), 'volume_intensity_scale': 0.4, 'intensity': 0.7, 'radius': 0.0}) self.node.connectattr('position', self.light, 'position') - self.spawn: ba.Timer = ba.Timer( + self.spawn: bs.Timer = bs.Timer( 10.0, self._check, repeat=True) def _check(self) -> None: """Prevent the cube from annihilating.""" def handlemessage(self, msg): - if isinstance(msg, ba.DieMessage): + if isinstance(msg, bs.DieMessage): if self.node: self.node.delete() - elif isinstance(msg, ba.OutOfBoundsMessage): + elif isinstance(msg, bs.OutOfBoundsMessage): if self.node: self.node.delete() - elif isinstance(msg, ba.HitMessage): + elif isinstance(msg, bs.HitMessage): try: spaz = msg._source_player - spaz.actor.node.handlemessage(ba.PowerupMessage(poweruptype='health')) + spaz.actor.node.handlemessage(bs.PowerupMessage(poweruptype='health')) t_color = spaz.team.color spaz.actor.node.color = t_color - ba.playsound(ba.getsound('healthPowerup'), volume=0.5) - ba.animate(self.light, 'radius', {0: 0.0, 0.1: 0.2, 0.7: 0}) + bs.getsound('healthPowerup').play(volume=0.5) + bs.animate(self.light, 'radius', {0: 0.0, 0.1: 0.2, 0.7: 0}) except: pass - elif isinstance(msg, ba.DroppedMessage): + elif isinstance(msg, bs.DroppedMessage): spaz = msg.node.getdelegate(PlayerSpaz) self.regen_timer = None -class Torso(ba.Actor): +class Torso(bs.Actor): def __init__(self, position: Sequence[float] = (0, 1, 0), velocity: Sequence[float] = (0, 0, 0), @@ -1546,12 +1548,12 @@ class Torso(ba.Actor): shared = SharedObjects.get() - self.node: ba.Node = ba.newnode('prop', delegate=self, attrs={ + self.node: bs.Node = bs.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, - 'color_texture': ba.gettexture(texture), - 'model': ba.getmodel('bonesTorso'), - 'model_scale': 1, + 'color_texture': bs.gettexture(texture), + 'mesh': bs.getmesh('bonesTorso'), + 'mesh_scale': 1, 'body': 'sphere', 'body_scale': 0.5, 'density': 6, @@ -1562,23 +1564,23 @@ class Torso(ba.Actor): 'shadow_size': 0.0, 'materials': (shared.object_material,)}) - self.spawn: ba.Timer = ba.Timer( + self.spawn: bs.Timer = bs.Timer( 10.0, self._check, repeat=True) def _check(self) -> None: """Prevent the cube from annihilating.""" def handlemessage(self, msg): - if isinstance(msg, ba.DieMessage): + if isinstance(msg, bs.DieMessage): if self.node: self.node.delete() - elif isinstance(msg, ba.OutOfBoundsMessage): + elif isinstance(msg, bs.OutOfBoundsMessage): if self.node: self.node.delete() -class Bone(ba.Actor): +class Bone(bs.Actor): def __init__(self, position: Sequence[float] = (0, 1, 0), velocity: Sequence[float] = (0, 0, 0), @@ -1587,21 +1589,21 @@ class Bone(ba.Actor): super().__init__() shared = SharedObjects.get() - models = ['bonesUpperArm', 'bonesUpperLeg', 'bonesForeArm', - 'bonesPelvis', 'bonesToes', 'bonesHand'] + meshs = ['bonesUpperArm', 'bonesUpperLeg', 'bonesForeArm', + 'bonesPelvis', 'bonesToes', 'bonesHand'] bone = None - model = 0 - for i in models: - if model == style: - bone = models[model] + mesh = 0 + for i in meshs: + if mesh == style: + bone = meshs[mesh] else: - model += 1 - self.node: ba.Node = ba.newnode('prop', delegate=self, attrs={ + mesh += 1 + self.node: bs.Node = bs.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, - 'color_texture': ba.gettexture(texture), - 'model': ba.getmodel(bone), - 'model_scale': 1.5, + 'color_texture': bs.gettexture(texture), + 'mesh': bs.getmesh(bone), + 'mesh_scale': 1.5, 'body': 'crate', 'body_scale': 0.6, 'density': 2, @@ -1612,25 +1614,25 @@ class Bone(ba.Actor): 'shadow_size': 0.0, 'materials': (shared.object_material,)}) - self.spawn: ba.Timer = ba.Timer( + self.spawn: bs.Timer = bs.Timer( 10.0, self._check, repeat=True) def _check(self) -> None: """Prevent the cube from annihilating.""" def handlemessage(self, msg): - if isinstance(msg, ba.DieMessage): + if isinstance(msg, bs.DieMessage): if self.node: self.node.delete() - elif isinstance(msg, ba.OutOfBoundsMessage): + elif isinstance(msg, bs.OutOfBoundsMessage): if self.node: self.node.delete() ###### Object##### -class Box(ba.Actor): +class Box(bs.Actor): def __init__(self, position: Sequence[float] = (0, 1, 0), velocity: Sequence[float] = (0, 0, 0), @@ -1638,7 +1640,7 @@ class Box(ba.Actor): super().__init__() shared = SharedObjects.get() - self.dont_collide = ba.Material() + self.dont_collide = bs.Material() self.dont_collide.add_actions( conditions=( 'they_are_different_node_than_us', @@ -1648,13 +1650,13 @@ class Box(ba.Actor): ) ) - self.node: ba.Node = ba.newnode('prop', delegate=self, attrs={ + self.node: bs.Node = bs.newnode('prop', delegate=self, attrs={ 'position': position, 'velocity': velocity, - 'color_texture': ba.gettexture(texture), - 'model': ba.getmodel('powerup'), - 'light_model': ba.getmodel('powerupSimple'), - 'model_scale': 4, + 'color_texture': bs.gettexture(texture), + 'mesh': bs.getmesh('powerup'), + 'light_mesh': bs.getmesh('powerupSimple'), + 'mesh_scale': 4, 'body': 'box', 'body_scale': 3, 'density': 9999, diff --git a/plugins/utilities.json b/plugins/utilities.json index c8adc4b..6cdfe22 100644 --- a/plugins/utilities.json +++ b/plugins/utilities.json @@ -223,6 +223,12 @@ } ], "versions": { + "2.0.0": { + "api_version": 8, + "commit_sha": "0b55bc2", + "released_on": "20-06-2023", + "md5sum": "517fec3938f31627c1cfd2126f1ee9da" + }, "1.2.3": { "api_version": 7, "commit_sha": "7753b87", @@ -694,6 +700,12 @@ } ], "versions": { + "1.1.0": { + "api_version": 8, + "commit_sha": "5fb8195", + "released_on": "28-06-2023", + "md5sum": "f6c1105b34d0426327688841d7e89bb9" + }, "1.0.1": { "api_version": 7, "commit_sha": "3ef572f", diff --git a/plugins/utilities/colorscheme.py b/plugins/utilities/colorscheme.py index bd4e4c5..a2998e3 100644 --- a/plugins/utilities/colorscheme.py +++ b/plugins/utilities/colorscheme.py @@ -6,39 +6,21 @@ # Settings -> Advanced -> Enter Code # to bring up the colorscheme UI. -# ba_meta require api 7 -import _ba -import ba +# ba_meta require api 8 +import _babase +import babase +import bauiv1 as bui -from bastd.ui.colorpicker import ColorPicker +from bauiv1lib.colorpicker import ColorPicker -original_buttonwidget = ba.buttonwidget -original_containerwidget = ba.containerwidget -original_checkboxwidget = ba.checkboxwidget +original_buttonwidget = bui.buttonwidget +original_containerwidget = bui.containerwidget +original_checkboxwidget = bui.checkboxwidget # We set this later so we store the overridden method in case the # player is using pro-unlocker plugins that override the -# `ba.app.accounts.have_pro` method. +# `bui.app.classic.accounts.have_pro` method. original_have_pro = None - - -def is_game_version_lower_than(version): - """ - Returns a boolean value indicating whether the current game - version is lower than the passed version. Useful for addressing - any breaking changes within game versions. - """ - game_version = tuple(map(int, ba.app.version.split("."))) - version = tuple(map(int, version.split("."))) - return game_version < version - - -# Adds backward compatibility for a breaking change released in -# game version 1.7.7, which moves `_ba.add_transaction` to -# `ba.internal.add_transaction`. -if is_game_version_lower_than("1.7.7"): - original_add_transaction = _ba.add_transaction -else: - original_add_transaction = ba.internal.add_transaction +original_add_transaction = bui.app.plus.add_v1_account_transaction class ColorScheme: @@ -61,24 +43,24 @@ class ColorScheme: -------- + Apply dark colorscheme: - >>> import _ba - >>> dark = _ba.ColorScheme((0.2,0.2,0.2), (0.8,0.8,0.8)) + >>> import _babase + >>> dark = _babase.ColorScheme((0.2,0.2,0.2), (0.8,0.8,0.8)) >>> dark.apply() # Reset back to game's default colorscheme >>> dark.disable() + Colorscheme that modifies only the main colors: - >>> import _ba - >>> bluey = _ba.ColorScheme(color=(0.1,0.3,0.6)) + >>> import _babase + >>> bluey = _babase.ColorScheme(color=(0.1,0.3,0.6)) >>> bluey.apply() # Reset back to game's default colorscheme >>> bluey.disable() + Colorscheme that modifies only the highlight colors: - >>> import _ba - >>> reddish = _ba.ColorScheme(highlight=(0.8,0.35,0.35)) + >>> import _babase + >>> reddish = _babase.ColorScheme(highlight=(0.8,0.35,0.35)) >>> reddish.apply() # Reset back to game's default colorscheme >>> reddish.disable() @@ -86,8 +68,8 @@ class ColorScheme: + Revert back to game's default colorscheme irrespective of whatever colorscheme is active at the moment: - >>> import _ba - >>> _ba.ColorScheme.disable() + >>> import _babase + >>> _babase.ColorScheme.disable() """ def __init__(self, color=None, highlight=None): @@ -112,13 +94,13 @@ class ColorScheme: def _apply_color(self): if self.color is None: raise TypeError("Expected color to be an (R,G,B) tuple.") - ba.containerwidget = self._custom_containerwidget + bui.containerwidget = self._custom_containerwidget def _apply_highlight(self): if self.highlight is None: raise TypeError("Expected highlight to be an (R,G,B) tuple.") - ba.buttonwidget = self._custom_buttonwidget - ba.checkboxwidget = self._custom_checkboxwidget + bui.buttonwidget = self._custom_buttonwidget + bui.checkboxwidget = self._custom_checkboxwidget def apply(self): if self.color: @@ -128,12 +110,12 @@ class ColorScheme: @staticmethod def _disable_color(): - ba.buttonwidget = original_buttonwidget - ba.checkboxwidget = original_checkboxwidget + bui.buttonwidget = original_buttonwidget + bui.checkboxwidget = original_checkboxwidget @staticmethod def _disable_highlight(): - ba.containerwidget = original_containerwidget + bui.containerwidget = original_containerwidget @classmethod def disable(cls): @@ -141,10 +123,10 @@ class ColorScheme: cls._disable_highlight() -class ColorSchemeWindow(ba.Window): +class ColorSchemeWindow(bui.Window): def __init__(self, default_colors=((0.41, 0.39, 0.5), (0.5, 0.7, 0.25))): self._default_colors = default_colors - self._color, self._highlight = ba.app.config.get("ColorScheme", (None, None)) + self._color, self._highlight = babase.app.config.get("ColorScheme", (None, None)) self._last_color = self._color self._last_highlight = self._highlight @@ -157,88 +139,88 @@ class ColorSchemeWindow(ba.Window): # A hack to let players select any RGB color value through the UI, # otherwise this is limited only to pro accounts. - ba.app.accounts_v1.have_pro = lambda: True + bui.app.classic.accounts.have_pro = lambda: True self.draw_ui() def draw_ui(self): - # Most of the stuff here for drawing the UI is referred from the - # game's bastd/ui/profile/edit.py, and so there could be some - # cruft here due to my oversight. - uiscale = ba.app.ui.uiscale - self._width = width = 480.0 if uiscale is ba.UIScale.SMALL else 380.0 - self._x_inset = x_inset = 40.0 if uiscale is ba.UIScale.SMALL else 0.0 + # NOTE: Most of the stuff here for drawing the UI is referred from the + # legacy (1.6 < version <= 1.7.19) game's bastd/ui/profile/edit.py, and + # so there could be some cruft here due to my oversight. + uiscale = bui.app.ui_v1.uiscale + self._width = width = 480.0 if uiscale is babase.UIScale.SMALL else 380.0 + self._x_inset = x_inset = 40.0 if uiscale is babase.UIScale.SMALL else 0.0 self._height = height = ( 275.0 - if uiscale is ba.UIScale.SMALL + if uiscale is babase.UIScale.SMALL else 288.0 - if uiscale is ba.UIScale.MEDIUM + if uiscale is babase.UIScale.MEDIUM else 300.0 ) spacing = 40 self._base_scale = ( 2.05 - if uiscale is ba.UIScale.SMALL + if uiscale is babase.UIScale.SMALL else 1.5 - if uiscale is ba.UIScale.MEDIUM + if uiscale is babase.UIScale.MEDIUM else 1.0 ) top_extra = 15 super().__init__( - root_widget=ba.containerwidget( + root_widget=bui.containerwidget( size=(width, height + top_extra), on_outside_click_call=self.cancel_on_outside_click, transition="in_right", scale=self._base_scale, - stack_offset=(0, 15) if uiscale is ba.UIScale.SMALL else (0, 0), + stack_offset=(0, 15) if uiscale is babase.UIScale.SMALL else (0, 0), ) ) - cancel_button = ba.buttonwidget( + cancel_button = bui.buttonwidget( parent=self._root_widget, position=(52 + x_inset, height - 60), size=(155, 60), scale=0.8, autoselect=True, - label=ba.Lstr(resource="cancelText"), + label=babase.Lstr(resource="cancelText"), on_activate_call=self._cancel, ) - ba.containerwidget(edit=self._root_widget, cancel_button=cancel_button) + bui.containerwidget(edit=self._root_widget, cancel_button=cancel_button) - save_button = ba.buttonwidget( + save_button = bui.buttonwidget( parent=self._root_widget, position=(width - (177 + x_inset), height - 110), size=(155, 60), autoselect=True, scale=0.8, - label=ba.Lstr(resource="saveText"), + label=babase.Lstr(resource="saveText"), ) - ba.widget(edit=save_button, left_widget=cancel_button) - ba.buttonwidget(edit=save_button, on_activate_call=self.save) - ba.widget(edit=cancel_button, right_widget=save_button) - ba.containerwidget(edit=self._root_widget, start_button=save_button) + bui.widget(edit=save_button, left_widget=cancel_button) + bui.buttonwidget(edit=save_button, on_activate_call=self.save) + bui.widget(edit=cancel_button, right_widget=save_button) + bui.containerwidget(edit=self._root_widget, start_button=save_button) - reset_button = ba.buttonwidget( + reset_button = bui.buttonwidget( parent=self._root_widget, position=(width - (177 + x_inset), height - 60), size=(155, 60), color=(0.2, 0.5, 0.6), autoselect=True, scale=0.8, - label=ba.Lstr(resource="settingsWindowAdvanced.resetText"), + label=babase.Lstr(resource="settingsWindowAdvanced.resetText"), ) - ba.widget(edit=reset_button, left_widget=reset_button) - ba.buttonwidget(edit=reset_button, on_activate_call=self.reset) - ba.widget(edit=cancel_button, right_widget=reset_button) - ba.containerwidget(edit=self._root_widget, start_button=reset_button) + bui.widget(edit=reset_button, left_widget=reset_button) + bui.buttonwidget(edit=reset_button, on_activate_call=self.reset) + bui.widget(edit=cancel_button, right_widget=reset_button) + bui.containerwidget(edit=self._root_widget, start_button=reset_button) v = height - 65.0 v -= spacing * 3.0 b_size = 80 b_offs = 75 - self._color_button = ba.buttonwidget( + self._color_button = bui.buttonwidget( parent=self._root_widget, autoselect=True, position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50), @@ -247,23 +229,23 @@ class ColorSchemeWindow(ba.Window): label="", button_type="square", ) - ba.buttonwidget( - edit=self._color_button, on_activate_call=ba.Call(self._pick_color, "color") + bui.buttonwidget( + edit=self._color_button, on_activate_call=babase.Call(self._pick_color, "color") ) - ba.textwidget( + bui.textwidget( parent=self._root_widget, h_align="center", v_align="center", position=(self._width * 0.5 - b_offs, v - 65), size=(0, 0), draw_controller=self._color_button, - text=ba.Lstr(resource="editProfileWindow.colorText"), + text=babase.Lstr(resource="editProfileWindow.colorText"), scale=0.7, - color=ba.app.ui.title_color, + color=bui.app.ui_v1.title_color, maxwidth=120, ) - self._highlight_button = ba.buttonwidget( + self._highlight_button = bui.buttonwidget( parent=self._root_widget, autoselect=True, position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50), @@ -273,20 +255,20 @@ class ColorSchemeWindow(ba.Window): button_type="square", ) - ba.buttonwidget( + bui.buttonwidget( edit=self._highlight_button, - on_activate_call=ba.Call(self._pick_color, "highlight"), + on_activate_call=babase.Call(self._pick_color, "highlight"), ) - ba.textwidget( + bui.textwidget( parent=self._root_widget, h_align="center", v_align="center", position=(self._width * 0.5 + b_offs, v - 65), size=(0, 0), draw_controller=self._highlight_button, - text=ba.Lstr(resource="editProfileWindow.highlightText"), + text=babase.Lstr(resource="editProfileWindow.highlightText"), scale=0.7, - color=ba.app.ui.title_color, + color=bui.app.ui_v1.title_color, maxwidth=120, ) @@ -306,7 +288,7 @@ class ColorSchemeWindow(ba.Window): ) def cancel_on_outside_click(self): - ba.playsound(ba.getsound("swish")) + bui.getsound("swish").play() self._cancel() def _cancel(self): @@ -314,44 +296,44 @@ class ColorSchemeWindow(ba.Window): colorscheme = ColorScheme(self._last_color, self._last_highlight) colorscheme.apply() # Good idea to revert this back now so we do not break anything else. - ba.app.accounts_v1.have_pro = original_have_pro - ba.containerwidget(edit=self._root_widget, transition="out_right") + bui.app.classic.accounts.have_pro = original_have_pro + bui.containerwidget(edit=self._root_widget, transition="out_right") def reset(self, transition_out=True): if transition_out: - ba.playsound(ba.getsound("gunCocking")) - ba.app.config["ColorScheme"] = (None, None) + bui.getsound("gunCocking").play() + babase.app.config["ColorScheme"] = (None, None) # Good idea to revert this back now so we do not break anything else. - ba.app.accounts_v1.have_pro = original_have_pro - ba.app.config.commit() - ba.containerwidget(edit=self._root_widget, transition="out_right") + bui.app.classic.accounts.have_pro = original_have_pro + babase.app.config.commit() + bui.containerwidget(edit=self._root_widget, transition="out_right") def save(self, transition_out=True): if transition_out: - ba.playsound(ba.getsound("gunCocking")) + bui.getsound("gunCocking").play() colorscheme = ColorScheme( self._color or self._default_colors[0], self._highlight or self._default_colors[1], ) colorscheme.apply() # Good idea to revert this back now so we do not break anything else. - ba.app.accounts_v1.have_pro = original_have_pro - ba.app.config["ColorScheme"] = ( + bui.app.classic.accounts.have_pro = original_have_pro + babase.app.config["ColorScheme"] = ( self._color or self._default_colors[0], self._highlight or self._default_colors[1], ) - ba.app.config.commit() - ba.containerwidget(edit=self._root_widget, transition="out_right") + babase.app.config.commit() + bui.containerwidget(edit=self._root_widget, transition="out_right") def _set_color(self, color): self._color = color if self._color_button: - ba.buttonwidget(edit=self._color_button, color=color) + bui.buttonwidget(edit=self._color_button, color=color) def _set_highlight(self, color): self._highlight = color if self._highlight_button: - ba.buttonwidget(edit=self._highlight_button, color=color) + bui.buttonwidget(edit=self._highlight_button, color=color) def color_picker_selected_color(self, picker, color): # The `ColorPicker` calls this method in the delegate once a color @@ -387,13 +369,7 @@ class CustomTransactions: self.custom_transactions[transaction_code] = transaction_fn def enable(self): - # Adds backward compatibility for a breaking change released in - # game version 1.7.7, which moves `_ba.add_transaction` to - # `ba.internal.add_transaction`. - if is_game_version_lower_than("1.7.7"): - _ba.add_transaction = self._handle - else: - ba.internal.add_transaction = self._handle + bui.app.plus.add_v1_account_transaction = self._handle def launch_colorscheme_selection_window(): @@ -410,7 +386,7 @@ def launch_colorscheme_selection_window(): # has pro-unlocked or not if our plugin runs before the dedicated # pro-unlocker plugin has been applied. global original_have_pro - original_have_pro = ba.app.accounts_v1.have_pro + original_have_pro = bui.app.classic.accounts.have_pro ColorSchemeWindow() @@ -420,7 +396,7 @@ def colorscheme_transaction(transaction, *args, **kwargs): def load_colorscheme(): - color, highlight = ba.app.config.get("ColorScheme", (None, None)) + color, highlight = babase.app.config.get("ColorScheme", (None, None)) if color and highlight: colorscheme = ColorScheme(color, highlight) colorscheme.apply() @@ -429,7 +405,7 @@ def load_colorscheme(): def load_plugin(): # Allow access to changing colorschemes manually through the in-game # console. - _ba.ColorScheme = ColorScheme + _babase.ColorScheme = ColorScheme # Adds a new advanced code entry named "colorscheme" which can be # entered through Settings -> Advanced -> Enter Code, allowing # colorscheme modification through a friendly UI. @@ -441,7 +417,7 @@ def load_plugin(): # ba_meta export plugin -class Main(ba.Plugin): +class Main(babase.Plugin): def on_app_running(self): load_plugin() diff --git a/plugins/utilities/random_play.py b/plugins/utilities/random_play.py index 463ecf9..a07b906 100644 --- a/plugins/utilities/random_play.py +++ b/plugins/utilities/random_play.py @@ -1,11 +1,22 @@ -# ba_meta require api 7 +# ba_meta require api 8 from random import choice, randint from typing import Any, Union # pylint: disable=import-error -import _ba -import ba -from bastd.ui.playlist.browser import PlaylistBrowserWindow +import babase +from bascenev1 import ( + Session, + MultiTeamSession, + FreeForAllSession, + DualTeamSession, + GameActivity, + newactivity, + new_host_session, +) + +from bauiv1 import Widget, UIScale, buttonwidget +from bauiv1lib.playlist.browser import PlaylistBrowserWindow +from bascenev1lib.activity.multiteamjoin import MultiTeamJoinActivity DEFAULT_TEAM_COLORS = ((0.1, 0.25, 1.0), (1.0, 0.25, 0.2)) DEFAULT_TEAM_NAMES = ("Blue", "Red") @@ -13,16 +24,16 @@ DEFAULT_TEAM_NAMES = ("Blue", "Red") # More or less copied from game code # I have no idea what I'm doing here -class RandomPlaySessionMixin(ba.MultiTeamSession, ba.Session): +class RandomPlaySessionMixin(MultiTeamSession, Session): def __init__(self, playlist) -> None: - """Set up playlists and launches a ba.Activity to accept joiners.""" - # pylint: disable=cyclic-import - from bastd.activity.multiteamjoin import MultiTeamJoinActivity + """Set up playlists & launch a bascenev1.Activity to accept joiners.""" - app = _ba.app + app = babase.app + classic = app.classic + assert classic is not None _cfg = app.config - super(ba.MultiTeamSession, self).__init__( + super(MultiTeamSession, self).__init__( [], team_names=DEFAULT_TEAM_NAMES, team_colors=DEFAULT_TEAM_COLORS, @@ -30,8 +41,8 @@ class RandomPlaySessionMixin(ba.MultiTeamSession, ba.Session): max_players=self.get_max_players(), ) - self._series_length = app.teams_series_length - self._ffa_series_length = app.ffa_series_length + self._series_length: int = classic.teams_series_length + self._ffa_series_length: int = classic.ffa_series_length self._tutorial_activity_instance = None self._game_number = 0 @@ -41,37 +52,37 @@ class RandomPlaySessionMixin(ba.MultiTeamSession, ba.Session): self._current_game_spec: dict[str, Any] | None = None self._next_game_spec: dict[str, Any] = self._playlist.pull_next() - self._next_game: type[ba.GameActivity] = self._next_game_spec["resolved_type"] + self._next_game: type[GameActivity] = self._next_game_spec["resolved_type"] self._instantiate_next_game() - self.setactivity(_ba.newactivity(MultiTeamJoinActivity)) + self.setactivity(newactivity(MultiTeamJoinActivity)) # Classes for Teams autopilot and FFA autopilot # I think they have to be separate in order to comply with `ba.GameActivity.supports_session_type()` -class RandFreeForAllSession(ba.FreeForAllSession, RandomPlaySessionMixin): +class RandFreeForAllSession(FreeForAllSession, RandomPlaySessionMixin): def __init__(self): - playlist = RandomPlaylist(ba.FreeForAllSession) - super(ba.FreeForAllSession, self).__init__(playlist) + playlist = RandomPlaylist(FreeForAllSession) + super(FreeForAllSession, self).__init__(playlist) -class RandDualTeamSession(ba.DualTeamSession, RandomPlaySessionMixin): +class RandDualTeamSession(DualTeamSession, RandomPlaySessionMixin): def __init__(self): - playlist = RandomPlaylist(ba.DualTeamSession) - super(ba.DualTeamSession, self).__init__(playlist) + playlist = RandomPlaylist(DualTeamSession) + super(DualTeamSession, self).__init__(playlist) # The faux playlist that just picks games at random class RandomPlaylist: - sessiontype: ba.Session - all_games: list[ba.GameActivity] - usable_games: list[ba.GameActivity] + sessiontype: Session + all_games: list[GameActivity] + usable_games: list[GameActivity] last_game: str def __init__(self, sessiontype): self.sessiontype = sessiontype - self.usable_games: list[ba.GameActivity] = [ + self.usable_games: list[GameActivity] = [ gt for gt in RandomPlaylist.all_games if gt.supports_session_type(self.sessiontype) @@ -90,7 +101,7 @@ class RandomPlaylist: if game.name == self.last_game: # Don't repeat the same game twice if has_only_one_game: - # ...but don't freeze the game when there's only one game + # ...but don't freeze when there's only one game break else: break @@ -113,40 +124,42 @@ class RandomPlaylist: # Hope you don't mind. def patched__init__( self, - sessiontype: type[ba.Session], + sessiontype: type[Session], transition: str | None = "in_right", - origin_widget: ba.Widget | None = None, + origin_widget: Widget | None = None, ): width = 800 height = 650 - ui_scale = ba.app.ui.uiscale - y_offset = -100 if ui_scale is ba.UIScale.SMALL else 0 - x_offset = 50 if ui_scale is ba.UIScale.SMALL else 0 + ui_scale = babase.app.ui_v1.uiscale + + y_offset = -100 if ui_scale is UIScale.SMALL else 0 + x_offset = 50 if ui_scale is UIScale.SMALL else 0 self.old__init__(sessiontype, transition, origin_widget) # pylint: disable=protected-access - self._quick_game_button = ba.buttonwidget( + self._quick_game_button = buttonwidget( parent=self._root_widget, position=(width - 120 * 2 + x_offset, height - 132 + y_offset), autoselect=True, - size=(120, 60), + size=(80, 60), scale=1.1, text_scale=1.2, - label="Random games", + label="Random", on_activate_call=game_starter_factory(sessiontype), color=(0.54, 0.52, 0.67), textcolor=(0.7, 0.65, 0.7), ) - # Returns a function that starts the game -def game_starter_factory(sessiontype: type[ba.Session]): + + +def game_starter_factory(sessiontype: type[Session]): session: Union[RandFreeForAllSession, RandDualTeamSession] = None - if issubclass(sessiontype, ba.FreeForAllSession): + if issubclass(sessiontype, FreeForAllSession): session = RandFreeForAllSession - elif issubclass(sessiontype, ba.DualTeamSession): + elif issubclass(sessiontype, DualTeamSession): session = RandDualTeamSession else: raise RuntimeError("Can't determine session type") @@ -170,18 +183,18 @@ def game_starter_factory(sessiontype: type[ba.Session]): start() def start(): - _ba.unlock_all_input() - _ba.new_host_session(session) + babase.unlock_all_input() + new_host_session(session) - _ba.fade_screen(False, time=0.25, endcall=has_faded) - _ba.lock_all_input() - ba.app.meta.load_exported_classes(ba.GameActivity, do_start) + babase.fade_screen(False, time=0.25, endcall=has_faded) + babase.lock_all_input() + babase.app.meta.load_exported_classes(GameActivity, do_start) return on_run # ba_meta export plugin -class RandomPlayPlugin(ba.Plugin): +class RandomPlayPlugin(babase.Plugin): """ A plugin that allows you to play randomly generated FFA or Teams matches by selecting a random minigame and map for each round. This eliminates the need to set up long playlists to enjoy all your BombSquad content. diff --git a/test/pip_reqs.txt b/test/pip_reqs.txt index 64b1ada..0d79228 100644 --- a/test/pip_reqs.txt +++ b/test/pip_reqs.txt @@ -1 +1,2 @@ +packaging GitPython diff --git a/test/test_checks.py b/test/test_checks.py index 4971bfe..72225bc 100644 --- a/test/test_checks.py +++ b/test/test_checks.py @@ -7,7 +7,7 @@ import io import os import pathlib -from distutils.version import StrictVersion +from packaging.version import Version import unittest @@ -33,7 +33,7 @@ class TestPluginManagerMetadata(unittest.TestCase): versions = list(self.content["versions"].items()) sorted_versions = sorted( versions, - key=lambda version: StrictVersion(version[0]), + key=lambda version: Version(version[0]), reverse=True, ) assert sorted_versions == versions @@ -105,7 +105,7 @@ class BaseCategoryMetadataTestCases: versions = list(plugin_metadata["versions"].items()) sorted_versions = sorted( versions, - key=lambda version: StrictVersion(version[0]), + key=lambda version: Version(version[0]), reverse=True, ) self.assertEqual(sorted_versions, versions)