Merge pull request #145 from bombsquad-community/api8

Migrate to API 8
This commit is contained in:
Rikko 2023-06-30 04:41:20 +05:30 committed by GitHub
commit a53477ff02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 1436 additions and 1274 deletions

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: ["3.10"] python-version: ["3.11"]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:

View file

@ -1,5 +1,13 @@
## Plugin Manager (dd-mm-yyyy) ## 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) ### 0.3.5 (16-06-2023)
- Replace the "Loading..." text with the exception message in case something goes wrong. - Replace the "Loading..." text with the exception message in case something goes wrong.

View file

@ -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) [![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 # plugin-manager
A plugin manager for the game - [Bombsquad](https://www.froemling.net/apps/bombsquad). Plugin manager is a plugin in itself, 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. - 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` 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. 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 #### Known 3rd Party Plugin Sources

View file

@ -1,6 +1,18 @@
{ {
"plugin_manager_url": "https://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugin_manager.py", "plugin_manager_url": "https://github.com/bombsquad-community/plugin-manager/{content_type}/{tag}/plugin_manager.py",
"versions": { "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": { "0.3.5": {
"api_version": 7, "api_version": 7,
"commit_sha": "985e486", "commit_sha": "985e486",

File diff suppressed because it is too large Load diff

View file

@ -266,6 +266,12 @@
} }
], ],
"versions": { "versions": {
"1.1.0": {
"api_version": 8,
"commit_sha": "0069f15",
"released_on": "08-06-2023",
"md5sum": "b8168bd3e6fae96b9339a727bd50842f"
},
"1.0.0": { "1.0.0": {
"api_version": 7, "api_version": 7,
"commit_sha": "095a773", "commit_sha": "095a773",

File diff suppressed because it is too large Load diff

View file

@ -223,6 +223,12 @@
} }
], ],
"versions": { "versions": {
"2.0.0": {
"api_version": 8,
"commit_sha": "0b55bc2",
"released_on": "20-06-2023",
"md5sum": "517fec3938f31627c1cfd2126f1ee9da"
},
"1.2.3": { "1.2.3": {
"api_version": 7, "api_version": 7,
"commit_sha": "7753b87", "commit_sha": "7753b87",
@ -694,6 +700,12 @@
} }
], ],
"versions": { "versions": {
"1.1.0": {
"api_version": 8,
"commit_sha": "5fb8195",
"released_on": "28-06-2023",
"md5sum": "f6c1105b34d0426327688841d7e89bb9"
},
"1.0.1": { "1.0.1": {
"api_version": 7, "api_version": 7,
"commit_sha": "3ef572f", "commit_sha": "3ef572f",

View file

@ -6,39 +6,21 @@
# Settings -> Advanced -> Enter Code # Settings -> Advanced -> Enter Code
# to bring up the colorscheme UI. # to bring up the colorscheme UI.
# ba_meta require api 7 # ba_meta require api 8
import _ba import _babase
import ba import babase
import bauiv1 as bui
from bastd.ui.colorpicker import ColorPicker from bauiv1lib.colorpicker import ColorPicker
original_buttonwidget = ba.buttonwidget original_buttonwidget = bui.buttonwidget
original_containerwidget = ba.containerwidget original_containerwidget = bui.containerwidget
original_checkboxwidget = ba.checkboxwidget original_checkboxwidget = bui.checkboxwidget
# We set this later so we store the overridden method in case the # We set this later so we store the overridden method in case the
# player is using pro-unlocker plugins that override 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 original_have_pro = None
original_add_transaction = bui.app.plus.add_v1_account_transaction
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
class ColorScheme: class ColorScheme:
@ -61,24 +43,24 @@ class ColorScheme:
-------- --------
+ Apply dark colorscheme: + Apply dark colorscheme:
>>> import _ba >>> import _babase
>>> dark = _ba.ColorScheme((0.2,0.2,0.2), (0.8,0.8,0.8)) >>> dark = _babase.ColorScheme((0.2,0.2,0.2), (0.8,0.8,0.8))
>>> dark.apply() >>> dark.apply()
# Reset back to game's default colorscheme # Reset back to game's default colorscheme
>>> dark.disable() >>> dark.disable()
+ Colorscheme that modifies only the main colors: + Colorscheme that modifies only the main colors:
>>> import _ba >>> import _babase
>>> bluey = _ba.ColorScheme(color=(0.1,0.3,0.6)) >>> bluey = _babase.ColorScheme(color=(0.1,0.3,0.6))
>>> bluey.apply() >>> bluey.apply()
# Reset back to game's default colorscheme # Reset back to game's default colorscheme
>>> bluey.disable() >>> bluey.disable()
+ Colorscheme that modifies only the highlight colors: + Colorscheme that modifies only the highlight colors:
>>> import _ba >>> import _babase
>>> reddish = _ba.ColorScheme(highlight=(0.8,0.35,0.35)) >>> reddish = _babase.ColorScheme(highlight=(0.8,0.35,0.35))
>>> reddish.apply() >>> reddish.apply()
# Reset back to game's default colorscheme # Reset back to game's default colorscheme
>>> reddish.disable() >>> reddish.disable()
@ -86,8 +68,8 @@ class ColorScheme:
+ Revert back to game's default colorscheme irrespective of + Revert back to game's default colorscheme irrespective of
whatever colorscheme is active at the moment: whatever colorscheme is active at the moment:
>>> import _ba >>> import _babase
>>> _ba.ColorScheme.disable() >>> _babase.ColorScheme.disable()
""" """
def __init__(self, color=None, highlight=None): def __init__(self, color=None, highlight=None):
@ -112,13 +94,13 @@ class ColorScheme:
def _apply_color(self): def _apply_color(self):
if self.color is None: if self.color is None:
raise TypeError("Expected color to be an (R,G,B) tuple.") 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): def _apply_highlight(self):
if self.highlight is None: if self.highlight is None:
raise TypeError("Expected highlight to be an (R,G,B) tuple.") raise TypeError("Expected highlight to be an (R,G,B) tuple.")
ba.buttonwidget = self._custom_buttonwidget bui.buttonwidget = self._custom_buttonwidget
ba.checkboxwidget = self._custom_checkboxwidget bui.checkboxwidget = self._custom_checkboxwidget
def apply(self): def apply(self):
if self.color: if self.color:
@ -128,12 +110,12 @@ class ColorScheme:
@staticmethod @staticmethod
def _disable_color(): def _disable_color():
ba.buttonwidget = original_buttonwidget bui.buttonwidget = original_buttonwidget
ba.checkboxwidget = original_checkboxwidget bui.checkboxwidget = original_checkboxwidget
@staticmethod @staticmethod
def _disable_highlight(): def _disable_highlight():
ba.containerwidget = original_containerwidget bui.containerwidget = original_containerwidget
@classmethod @classmethod
def disable(cls): def disable(cls):
@ -141,10 +123,10 @@ class ColorScheme:
cls._disable_highlight() 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))): def __init__(self, default_colors=((0.41, 0.39, 0.5), (0.5, 0.7, 0.25))):
self._default_colors = default_colors 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_color = self._color
self._last_highlight = self._highlight 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, # A hack to let players select any RGB color value through the UI,
# otherwise this is limited only to pro accounts. # 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() self.draw_ui()
def draw_ui(self): def draw_ui(self):
# Most of the stuff here for drawing the UI is referred from the # NOTE: 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 # legacy (1.6 < version <= 1.7.19) game's bastd/ui/profile/edit.py, and
# cruft here due to my oversight. # so there could be some cruft here due to my oversight.
uiscale = ba.app.ui.uiscale uiscale = bui.app.ui_v1.uiscale
self._width = width = 480.0 if uiscale is ba.UIScale.SMALL else 380.0 self._width = width = 480.0 if uiscale is babase.UIScale.SMALL else 380.0
self._x_inset = x_inset = 40.0 if uiscale is ba.UIScale.SMALL else 0.0 self._x_inset = x_inset = 40.0 if uiscale is babase.UIScale.SMALL else 0.0
self._height = height = ( self._height = height = (
275.0 275.0
if uiscale is ba.UIScale.SMALL if uiscale is babase.UIScale.SMALL
else 288.0 else 288.0
if uiscale is ba.UIScale.MEDIUM if uiscale is babase.UIScale.MEDIUM
else 300.0 else 300.0
) )
spacing = 40 spacing = 40
self._base_scale = ( self._base_scale = (
2.05 2.05
if uiscale is ba.UIScale.SMALL if uiscale is babase.UIScale.SMALL
else 1.5 else 1.5
if uiscale is ba.UIScale.MEDIUM if uiscale is babase.UIScale.MEDIUM
else 1.0 else 1.0
) )
top_extra = 15 top_extra = 15
super().__init__( super().__init__(
root_widget=ba.containerwidget( root_widget=bui.containerwidget(
size=(width, height + top_extra), size=(width, height + top_extra),
on_outside_click_call=self.cancel_on_outside_click, on_outside_click_call=self.cancel_on_outside_click,
transition="in_right", transition="in_right",
scale=self._base_scale, 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, parent=self._root_widget,
position=(52 + x_inset, height - 60), position=(52 + x_inset, height - 60),
size=(155, 60), size=(155, 60),
scale=0.8, scale=0.8,
autoselect=True, autoselect=True,
label=ba.Lstr(resource="cancelText"), label=babase.Lstr(resource="cancelText"),
on_activate_call=self._cancel, 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, parent=self._root_widget,
position=(width - (177 + x_inset), height - 110), position=(width - (177 + x_inset), height - 110),
size=(155, 60), size=(155, 60),
autoselect=True, autoselect=True,
scale=0.8, scale=0.8,
label=ba.Lstr(resource="saveText"), label=babase.Lstr(resource="saveText"),
) )
ba.widget(edit=save_button, left_widget=cancel_button) bui.widget(edit=save_button, left_widget=cancel_button)
ba.buttonwidget(edit=save_button, on_activate_call=self.save) bui.buttonwidget(edit=save_button, on_activate_call=self.save)
ba.widget(edit=cancel_button, right_widget=save_button) bui.widget(edit=cancel_button, right_widget=save_button)
ba.containerwidget(edit=self._root_widget, start_button=save_button) bui.containerwidget(edit=self._root_widget, start_button=save_button)
reset_button = ba.buttonwidget( reset_button = bui.buttonwidget(
parent=self._root_widget, parent=self._root_widget,
position=(width - (177 + x_inset), height - 60), position=(width - (177 + x_inset), height - 60),
size=(155, 60), size=(155, 60),
color=(0.2, 0.5, 0.6), color=(0.2, 0.5, 0.6),
autoselect=True, autoselect=True,
scale=0.8, scale=0.8,
label=ba.Lstr(resource="settingsWindowAdvanced.resetText"), label=babase.Lstr(resource="settingsWindowAdvanced.resetText"),
) )
ba.widget(edit=reset_button, left_widget=reset_button) bui.widget(edit=reset_button, left_widget=reset_button)
ba.buttonwidget(edit=reset_button, on_activate_call=self.reset) bui.buttonwidget(edit=reset_button, on_activate_call=self.reset)
ba.widget(edit=cancel_button, right_widget=reset_button) bui.widget(edit=cancel_button, right_widget=reset_button)
ba.containerwidget(edit=self._root_widget, start_button=reset_button) bui.containerwidget(edit=self._root_widget, start_button=reset_button)
v = height - 65.0 v = height - 65.0
v -= spacing * 3.0 v -= spacing * 3.0
b_size = 80 b_size = 80
b_offs = 75 b_offs = 75
self._color_button = ba.buttonwidget( self._color_button = bui.buttonwidget(
parent=self._root_widget, parent=self._root_widget,
autoselect=True, autoselect=True,
position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50), position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50),
@ -247,23 +229,23 @@ class ColorSchemeWindow(ba.Window):
label="", label="",
button_type="square", button_type="square",
) )
ba.buttonwidget( bui.buttonwidget(
edit=self._color_button, on_activate_call=ba.Call(self._pick_color, "color") edit=self._color_button, on_activate_call=babase.Call(self._pick_color, "color")
) )
ba.textwidget( bui.textwidget(
parent=self._root_widget, parent=self._root_widget,
h_align="center", h_align="center",
v_align="center", v_align="center",
position=(self._width * 0.5 - b_offs, v - 65), position=(self._width * 0.5 - b_offs, v - 65),
size=(0, 0), size=(0, 0),
draw_controller=self._color_button, draw_controller=self._color_button,
text=ba.Lstr(resource="editProfileWindow.colorText"), text=babase.Lstr(resource="editProfileWindow.colorText"),
scale=0.7, scale=0.7,
color=ba.app.ui.title_color, color=bui.app.ui_v1.title_color,
maxwidth=120, maxwidth=120,
) )
self._highlight_button = ba.buttonwidget( self._highlight_button = bui.buttonwidget(
parent=self._root_widget, parent=self._root_widget,
autoselect=True, autoselect=True,
position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50), position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50),
@ -273,20 +255,20 @@ class ColorSchemeWindow(ba.Window):
button_type="square", button_type="square",
) )
ba.buttonwidget( bui.buttonwidget(
edit=self._highlight_button, 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, parent=self._root_widget,
h_align="center", h_align="center",
v_align="center", v_align="center",
position=(self._width * 0.5 + b_offs, v - 65), position=(self._width * 0.5 + b_offs, v - 65),
size=(0, 0), size=(0, 0),
draw_controller=self._highlight_button, draw_controller=self._highlight_button,
text=ba.Lstr(resource="editProfileWindow.highlightText"), text=babase.Lstr(resource="editProfileWindow.highlightText"),
scale=0.7, scale=0.7,
color=ba.app.ui.title_color, color=bui.app.ui_v1.title_color,
maxwidth=120, maxwidth=120,
) )
@ -306,7 +288,7 @@ class ColorSchemeWindow(ba.Window):
) )
def cancel_on_outside_click(self): def cancel_on_outside_click(self):
ba.playsound(ba.getsound("swish")) bui.getsound("swish").play()
self._cancel() self._cancel()
def _cancel(self): def _cancel(self):
@ -314,44 +296,44 @@ class ColorSchemeWindow(ba.Window):
colorscheme = ColorScheme(self._last_color, self._last_highlight) colorscheme = ColorScheme(self._last_color, self._last_highlight)
colorscheme.apply() colorscheme.apply()
# Good idea to revert this back now so we do not break anything else. # Good idea to revert this back now so we do not break anything else.
ba.app.accounts_v1.have_pro = original_have_pro bui.app.classic.accounts.have_pro = original_have_pro
ba.containerwidget(edit=self._root_widget, transition="out_right") bui.containerwidget(edit=self._root_widget, transition="out_right")
def reset(self, transition_out=True): def reset(self, transition_out=True):
if transition_out: if transition_out:
ba.playsound(ba.getsound("gunCocking")) bui.getsound("gunCocking").play()
ba.app.config["ColorScheme"] = (None, None) babase.app.config["ColorScheme"] = (None, None)
# Good idea to revert this back now so we do not break anything else. # Good idea to revert this back now so we do not break anything else.
ba.app.accounts_v1.have_pro = original_have_pro bui.app.classic.accounts.have_pro = original_have_pro
ba.app.config.commit() babase.app.config.commit()
ba.containerwidget(edit=self._root_widget, transition="out_right") bui.containerwidget(edit=self._root_widget, transition="out_right")
def save(self, transition_out=True): def save(self, transition_out=True):
if transition_out: if transition_out:
ba.playsound(ba.getsound("gunCocking")) bui.getsound("gunCocking").play()
colorscheme = ColorScheme( colorscheme = ColorScheme(
self._color or self._default_colors[0], self._color or self._default_colors[0],
self._highlight or self._default_colors[1], self._highlight or self._default_colors[1],
) )
colorscheme.apply() colorscheme.apply()
# Good idea to revert this back now so we do not break anything else. # Good idea to revert this back now so we do not break anything else.
ba.app.accounts_v1.have_pro = original_have_pro bui.app.classic.accounts.have_pro = original_have_pro
ba.app.config["ColorScheme"] = ( babase.app.config["ColorScheme"] = (
self._color or self._default_colors[0], self._color or self._default_colors[0],
self._highlight or self._default_colors[1], self._highlight or self._default_colors[1],
) )
ba.app.config.commit() babase.app.config.commit()
ba.containerwidget(edit=self._root_widget, transition="out_right") bui.containerwidget(edit=self._root_widget, transition="out_right")
def _set_color(self, color): def _set_color(self, color):
self._color = color self._color = color
if self._color_button: 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): def _set_highlight(self, color):
self._highlight = color self._highlight = color
if self._highlight_button: 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): def color_picker_selected_color(self, picker, color):
# The `ColorPicker` calls this method in the delegate once a 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 self.custom_transactions[transaction_code] = transaction_fn
def enable(self): def enable(self):
# Adds backward compatibility for a breaking change released in bui.app.plus.add_v1_account_transaction = self._handle
# 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
def launch_colorscheme_selection_window(): 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 # has pro-unlocked or not if our plugin runs before the dedicated
# pro-unlocker plugin has been applied. # pro-unlocker plugin has been applied.
global original_have_pro global original_have_pro
original_have_pro = ba.app.accounts_v1.have_pro original_have_pro = bui.app.classic.accounts.have_pro
ColorSchemeWindow() ColorSchemeWindow()
@ -420,7 +396,7 @@ def colorscheme_transaction(transaction, *args, **kwargs):
def load_colorscheme(): 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: if color and highlight:
colorscheme = ColorScheme(color, highlight) colorscheme = ColorScheme(color, highlight)
colorscheme.apply() colorscheme.apply()
@ -429,7 +405,7 @@ def load_colorscheme():
def load_plugin(): def load_plugin():
# Allow access to changing colorschemes manually through the in-game # Allow access to changing colorschemes manually through the in-game
# console. # console.
_ba.ColorScheme = ColorScheme _babase.ColorScheme = ColorScheme
# Adds a new advanced code entry named "colorscheme" which can be # Adds a new advanced code entry named "colorscheme" which can be
# entered through Settings -> Advanced -> Enter Code, allowing # entered through Settings -> Advanced -> Enter Code, allowing
# colorscheme modification through a friendly UI. # colorscheme modification through a friendly UI.
@ -441,7 +417,7 @@ def load_plugin():
# ba_meta export plugin # ba_meta export plugin
class Main(ba.Plugin): class Main(babase.Plugin):
def on_app_running(self): def on_app_running(self):
load_plugin() load_plugin()

View file

@ -1,11 +1,22 @@
# ba_meta require api 7 # ba_meta require api 8
from random import choice, randint from random import choice, randint
from typing import Any, Union from typing import Any, Union
# pylint: disable=import-error # pylint: disable=import-error
import _ba import babase
import ba from bascenev1 import (
from bastd.ui.playlist.browser import PlaylistBrowserWindow 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_COLORS = ((0.1, 0.25, 1.0), (1.0, 0.25, 0.2))
DEFAULT_TEAM_NAMES = ("Blue", "Red") DEFAULT_TEAM_NAMES = ("Blue", "Red")
@ -13,16 +24,16 @@ DEFAULT_TEAM_NAMES = ("Blue", "Red")
# More or less copied from game code # More or less copied from game code
# I have no idea what I'm doing here # I have no idea what I'm doing here
class RandomPlaySessionMixin(ba.MultiTeamSession, ba.Session): class RandomPlaySessionMixin(MultiTeamSession, Session):
def __init__(self, playlist) -> None: def __init__(self, playlist) -> None:
"""Set up playlists and launches a ba.Activity to accept joiners.""" """Set up playlists & launch a bascenev1.Activity to accept joiners."""
# pylint: disable=cyclic-import
from bastd.activity.multiteamjoin import MultiTeamJoinActivity
app = _ba.app app = babase.app
classic = app.classic
assert classic is not None
_cfg = app.config _cfg = app.config
super(ba.MultiTeamSession, self).__init__( super(MultiTeamSession, self).__init__(
[], [],
team_names=DEFAULT_TEAM_NAMES, team_names=DEFAULT_TEAM_NAMES,
team_colors=DEFAULT_TEAM_COLORS, team_colors=DEFAULT_TEAM_COLORS,
@ -30,8 +41,8 @@ class RandomPlaySessionMixin(ba.MultiTeamSession, ba.Session):
max_players=self.get_max_players(), max_players=self.get_max_players(),
) )
self._series_length = app.teams_series_length self._series_length: int = classic.teams_series_length
self._ffa_series_length = app.ffa_series_length self._ffa_series_length: int = classic.ffa_series_length
self._tutorial_activity_instance = None self._tutorial_activity_instance = None
self._game_number = 0 self._game_number = 0
@ -41,37 +52,37 @@ class RandomPlaySessionMixin(ba.MultiTeamSession, ba.Session):
self._current_game_spec: dict[str, Any] | None = None self._current_game_spec: dict[str, Any] | None = None
self._next_game_spec: dict[str, Any] = self._playlist.pull_next() 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._instantiate_next_game()
self.setactivity(_ba.newactivity(MultiTeamJoinActivity)) self.setactivity(newactivity(MultiTeamJoinActivity))
# Classes for Teams autopilot and FFA autopilot # Classes for Teams autopilot and FFA autopilot
# I think they have to be separate in order to comply with `ba.GameActivity.supports_session_type()` # 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): def __init__(self):
playlist = RandomPlaylist(ba.FreeForAllSession) playlist = RandomPlaylist(FreeForAllSession)
super(ba.FreeForAllSession, self).__init__(playlist) super(FreeForAllSession, self).__init__(playlist)
class RandDualTeamSession(ba.DualTeamSession, RandomPlaySessionMixin): class RandDualTeamSession(DualTeamSession, RandomPlaySessionMixin):
def __init__(self): def __init__(self):
playlist = RandomPlaylist(ba.DualTeamSession) playlist = RandomPlaylist(DualTeamSession)
super(ba.DualTeamSession, self).__init__(playlist) super(DualTeamSession, self).__init__(playlist)
# The faux playlist that just picks games at random # The faux playlist that just picks games at random
class RandomPlaylist: class RandomPlaylist:
sessiontype: ba.Session sessiontype: Session
all_games: list[ba.GameActivity] all_games: list[GameActivity]
usable_games: list[ba.GameActivity] usable_games: list[GameActivity]
last_game: str last_game: str
def __init__(self, sessiontype): def __init__(self, sessiontype):
self.sessiontype = sessiontype self.sessiontype = sessiontype
self.usable_games: list[ba.GameActivity] = [ self.usable_games: list[GameActivity] = [
gt gt
for gt in RandomPlaylist.all_games for gt in RandomPlaylist.all_games
if gt.supports_session_type(self.sessiontype) if gt.supports_session_type(self.sessiontype)
@ -90,7 +101,7 @@ class RandomPlaylist:
if game.name == self.last_game: if game.name == self.last_game:
# Don't repeat the same game twice # Don't repeat the same game twice
if has_only_one_game: 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 break
else: else:
break break
@ -113,40 +124,42 @@ class RandomPlaylist:
# Hope you don't mind. # Hope you don't mind.
def patched__init__( def patched__init__(
self, self,
sessiontype: type[ba.Session], sessiontype: type[Session],
transition: str | None = "in_right", transition: str | None = "in_right",
origin_widget: ba.Widget | None = None, origin_widget: Widget | None = None,
): ):
width = 800 width = 800
height = 650 height = 650
ui_scale = ba.app.ui.uiscale ui_scale = babase.app.ui_v1.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 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) self.old__init__(sessiontype, transition, origin_widget)
# pylint: disable=protected-access # pylint: disable=protected-access
self._quick_game_button = ba.buttonwidget( self._quick_game_button = buttonwidget(
parent=self._root_widget, parent=self._root_widget,
position=(width - 120 * 2 + x_offset, height - 132 + y_offset), position=(width - 120 * 2 + x_offset, height - 132 + y_offset),
autoselect=True, autoselect=True,
size=(120, 60), size=(80, 60),
scale=1.1, scale=1.1,
text_scale=1.2, text_scale=1.2,
label="Random games", label="Random",
on_activate_call=game_starter_factory(sessiontype), on_activate_call=game_starter_factory(sessiontype),
color=(0.54, 0.52, 0.67), color=(0.54, 0.52, 0.67),
textcolor=(0.7, 0.65, 0.7), textcolor=(0.7, 0.65, 0.7),
) )
# Returns a function that starts the game # 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 session: Union[RandFreeForAllSession, RandDualTeamSession] = None
if issubclass(sessiontype, ba.FreeForAllSession): if issubclass(sessiontype, FreeForAllSession):
session = RandFreeForAllSession session = RandFreeForAllSession
elif issubclass(sessiontype, ba.DualTeamSession): elif issubclass(sessiontype, DualTeamSession):
session = RandDualTeamSession session = RandDualTeamSession
else: else:
raise RuntimeError("Can't determine session type") raise RuntimeError("Can't determine session type")
@ -170,18 +183,18 @@ def game_starter_factory(sessiontype: type[ba.Session]):
start() start()
def start(): def start():
_ba.unlock_all_input() babase.unlock_all_input()
_ba.new_host_session(session) new_host_session(session)
_ba.fade_screen(False, time=0.25, endcall=has_faded) babase.fade_screen(False, time=0.25, endcall=has_faded)
_ba.lock_all_input() babase.lock_all_input()
ba.app.meta.load_exported_classes(ba.GameActivity, do_start) babase.app.meta.load_exported_classes(GameActivity, do_start)
return on_run return on_run
# ba_meta export plugin # 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. 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. This eliminates the need to set up long playlists to enjoy all your BombSquad content.

View file

@ -1 +1,2 @@
packaging
GitPython GitPython

View file

@ -7,7 +7,7 @@ import io
import os import os
import pathlib import pathlib
from distutils.version import StrictVersion from packaging.version import Version
import unittest import unittest
@ -33,7 +33,7 @@ class TestPluginManagerMetadata(unittest.TestCase):
versions = list(self.content["versions"].items()) versions = list(self.content["versions"].items())
sorted_versions = sorted( sorted_versions = sorted(
versions, versions,
key=lambda version: StrictVersion(version[0]), key=lambda version: Version(version[0]),
reverse=True, reverse=True,
) )
assert sorted_versions == versions assert sorted_versions == versions
@ -105,7 +105,7 @@ class BaseCategoryMetadataTestCases:
versions = list(plugin_metadata["versions"].items()) versions = list(plugin_metadata["versions"].items())
sorted_versions = sorted( sorted_versions = sorted(
versions, versions,
key=lambda version: StrictVersion(version[0]), key=lambda version: Version(version[0]),
reverse=True, reverse=True,
) )
self.assertEqual(sorted_versions, versions) self.assertEqual(sorted_versions, versions)