Source code for bacommon.docui.routes.classicchest

# Released under the MIT License. See LICENSE for details.
#
"""Routes for the classic chest doc-ui domain.

One chest slot: what's in it, its prize odds and its unlock wait, with
buttons to open it (now, for tokens, or once unlocked) or to watch an
ad to cut the wait. Opening answers with the chest's contents and the
open animation as client-effects.
"""

from __future__ import annotations  # Docs-generation hack.

from dataclasses import dataclass
from typing import Annotated, override

from efro.dataclassio import ioprepped, IOAttrs

import bacommon.docui.v2 as dui2
from bacommon.docui.routes import (
    DocUIRoute,
    DocUILocalActionBase,
    PressSound,
    family_members,
)


[docs] class ChestRoute(DocUIRoute): """Family class for classic chest routes."""
[docs] @override @classmethod def get_route_types(cls) -> tuple[type[DocUIRoute], ...]: return family_members(AnyChestRoute)
[docs] @override @classmethod def get_window_layout(cls) -> dui2.WindowLayout: # One chest centered, its odds beside it, buttons below. return dui2.WindowLayout.WIDE
[docs] @ioprepped @dataclass class Root(ChestRoute, path='/'): """A chest slot: its chest (if any) and what can be done with it. The two flags are things only the client knows, so it states them when asking. """ #: Which slot (0-based). slot: int #: Whether an ad is ready to show right now (so a 'watch an ad to #: reduce the wait' button can work). ad_ready: bool = False #: Whether to remind about opening early with tokens (the player #: can switch the reminder off). open_me: bool = False
[docs] @ioprepped @dataclass class Open(ChestRoute, path='/open', method=dui2.RequestMethod.POST): """Open a chest, paying any tokens its wait currently costs. Answered with its contents and the open animation. """ slot: int #: Tokens the player agreed to pay (0 for an unlocked chest). The #: open fails if the cost has since changed. token_payment: int
[docs] @ioprepped @dataclass class AdWatched(ChestRoute, path='/adwatched', method=dui2.RequestMethod.POST): """The player watched an ad to reduce a chest's wait. Answered like :class:`Open` if that unlocked it; otherwise with the slot as it now stands. """ slot: int
# All chest routes. AnyChestRoute = Root | Open | AdWatched
[docs] class ChestLocalAction(DocUILocalActionBase): """Family class for classic chest local-actions."""
[docs] @override @classmethod def get_action_types(cls) -> tuple[type[DocUILocalActionBase], ...]: return family_members(AnyChestLocalAction)
[docs] @ioprepped @dataclass class WatchAd(ChestLocalAction, name='watch_ad'): """Show an ad; once watched, ask for :class:`AdWatched`.""" slot: int
[docs] @ioprepped @dataclass class StopReminding(ChestLocalAction, name='stop_reminding'): """Stop reminding about opening chests early; re-show the slot.""" slot: int
[docs] @ioprepped @dataclass class GetTokens(ChestLocalAction, name='get_tokens'): """Offer to get more tokens (not enough to open a chest now)."""
[docs] @override @classmethod def get_press_sound(cls) -> PressSound: return PressSound.SWISH
# All chest local-actions. AnyChestLocalAction = WatchAd | StopReminding | GetTokens # Docs-generation hack; import some stuff that we likely only forward-declared # in our actual source code so that docs tools can find it. from typing import (Coroutine, Any, Literal, Callable, Generator, Awaitable, Sequence, Self, TypeIs) import asyncio from concurrent.futures import Future from pathlib import Path from enum import Enum