Source code for bacommon.bs._clienteffect
# Released under the MIT License. See LICENSE for details.
#
"""ClientEffect related functionality."""
from __future__ import annotations
import datetime
from enum import Enum
from dataclasses import dataclass, field
from typing import Annotated, override, assert_never
from efro.dataclassio import ioprepped, IOAttrs, IOMultiType
[docs]
class ClientEffectTypeID(Enum):
"""Type ID for each of our subclasses."""
UNKNOWN = 'u'
SCREEN_MESSAGE = 'm'
SOUND = 's'
DELAY = 'd'
CHEST_WAIT_TIME_ANIMATION = 't'
TICKETS_ANIMATION = 'ta'
TOKENS_ANIMATION = 'toa'
[docs]
class ClientEffect(IOMultiType[ClientEffectTypeID]):
"""Something that can happen on the client.
This can include screen messages, sounds, visual effects, etc.
"""
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
# Require child classes to supply this themselves. If we did a
# full type registry/lookup here it would require us to import
# everything and would prevent lazy loading.
raise NotImplementedError()
[docs]
@override
@classmethod
def get_type(cls, type_id: ClientEffectTypeID) -> type[ClientEffect]:
"""Return the subclass for each of our type-ids."""
# pylint: disable=cyclic-import
# pylint: disable=too-many-return-statements
t = ClientEffectTypeID
if type_id is t.UNKNOWN:
return ClientEffectUnknown
if type_id is t.SCREEN_MESSAGE:
return ClientEffectScreenMessage
if type_id is t.SOUND:
return ClientEffectSound
if type_id is t.DELAY:
return ClientEffectDelay
if type_id is t.CHEST_WAIT_TIME_ANIMATION:
return ClientEffectChestWaitTimeAnimation
if type_id is t.TICKETS_ANIMATION:
return ClientEffectTicketsAnimation
if type_id is t.TOKENS_ANIMATION:
return ClientEffectTokensAnimation
# Important to make sure we provide all types.
assert_never(type_id)
[docs]
@override
@classmethod
def get_unknown_type_fallback(cls) -> ClientEffect:
# If we encounter some future message type we don't know
# anything about, drop in a placeholder.
return ClientEffectUnknown()
[docs]
@ioprepped
@dataclass
class ClientEffectUnknown(ClientEffect):
"""Fallback substitute for types we don't recognize."""
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
return ClientEffectTypeID.UNKNOWN
[docs]
@ioprepped
@dataclass
class ClientEffectScreenMessage(ClientEffect):
"""Display a screen-message."""
message: str
subs: list[str] = field(default_factory=list)
color: tuple[float, float, float] = (1.0, 1.0, 1.0)
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
return ClientEffectTypeID.SCREEN_MESSAGE
[docs]
@ioprepped
@dataclass
class ClientEffectSound(ClientEffect):
"""Play a sound."""
[docs]
class Sound(Enum):
"""Sounds that can be made alongside the message."""
UNKNOWN = 'u'
CASH_REGISTER = 'c'
ERROR = 'e'
POWER_DOWN = 'p'
GUN_COCKING = 'g'
sound: Sound
volume: float = 1.0
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
return ClientEffectTypeID.SOUND
[docs]
@ioprepped
@dataclass
class ClientEffectChestWaitTimeAnimation(ClientEffect):
"""Animate chest wait time changing."""
chestid: str
duration: float
startvalue: datetime.datetime
endvalue: datetime.datetime
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
return ClientEffectTypeID.CHEST_WAIT_TIME_ANIMATION
[docs]
@ioprepped
@dataclass
class ClientEffectTicketsAnimation(ClientEffect):
"""Animate tickets count."""
duration: float
startvalue: int
endvalue: int
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
return ClientEffectTypeID.TICKETS_ANIMATION
[docs]
@ioprepped
@dataclass
class ClientEffectTokensAnimation(ClientEffect):
"""Animate tokens count."""
duration: float
startvalue: int
endvalue: int
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
return ClientEffectTypeID.TOKENS_ANIMATION
[docs]
@ioprepped
@dataclass
class ClientEffectDelay(ClientEffect):
"""Delay effect processing."""
seconds: float
[docs]
@override
@classmethod
def get_type_id(cls) -> ClientEffectTypeID:
return ClientEffectTypeID.DELAY
# 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)
import asyncio
from concurrent.futures import Future
from pathlib import Path
from enum import Enum