mirror of
https://github.com/hypervortex/VH-Bombsquad-Modded-Server-Files
synced 2025-11-07 17:36:08 +00:00
108 lines
2.7 KiB
Python
108 lines
2.7 KiB
Python
# Released under the MIT License. See LICENSE for details.
|
|
#
|
|
"""Functionality for sending and responding to messages.
|
|
Supports static typing for message types and possible return types.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Annotated
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
|
|
from efro.dataclassio import ioprepped, IOAttrs
|
|
|
|
if TYPE_CHECKING:
|
|
pass
|
|
|
|
|
|
class UnregisteredMessageIDError(Exception):
|
|
"""A message or response id is not covered by our protocol."""
|
|
|
|
|
|
class Message:
|
|
"""Base class for messages."""
|
|
|
|
@classmethod
|
|
def get_response_types(cls) -> list[type[Response] | None]:
|
|
"""Return all Response types this Message can return when sent.
|
|
|
|
The default implementation specifies a None return type.
|
|
"""
|
|
return [None]
|
|
|
|
|
|
class Response:
|
|
"""Base class for responses to messages."""
|
|
|
|
|
|
class SysResponse:
|
|
"""Base class for system-responses to messages.
|
|
|
|
These are only sent/handled by the messaging system itself;
|
|
users of the api never see them.
|
|
"""
|
|
|
|
def set_local_exception(self, exc: Exception) -> None:
|
|
"""Attach a local exception to facilitate better logging/handling.
|
|
|
|
Be aware that this data does not get serialized and only
|
|
exists on the local object.
|
|
"""
|
|
setattr(self, '_sr_local_exception', exc)
|
|
|
|
def get_local_exception(self) -> Exception | None:
|
|
"""Fetch a local attached exception."""
|
|
value = getattr(self, '_sr_local_exception', None)
|
|
assert isinstance(value, Exception | None)
|
|
return value
|
|
|
|
|
|
# Some standard response types:
|
|
|
|
|
|
@ioprepped
|
|
@dataclass
|
|
class ErrorSysResponse(SysResponse):
|
|
"""SysResponse saying some error has occurred for the send.
|
|
|
|
This generally results in an Exception being raised for the caller.
|
|
"""
|
|
|
|
class ErrorType(Enum):
|
|
"""Type of error that occurred while sending a message."""
|
|
|
|
REMOTE = 0
|
|
REMOTE_CLEAN = 1
|
|
LOCAL = 2
|
|
COMMUNICATION = 3
|
|
REMOTE_COMMUNICATION = 4
|
|
|
|
error_message: Annotated[str, IOAttrs('m')]
|
|
error_type: Annotated[ErrorType, IOAttrs('e')] = ErrorType.REMOTE
|
|
|
|
|
|
@ioprepped
|
|
@dataclass
|
|
class EmptySysResponse(SysResponse):
|
|
"""The response equivalent of None."""
|
|
|
|
|
|
# TODO: could allow handlers to deal in raw values for these
|
|
# types similar to how we allow None in place of EmptySysResponse.
|
|
# Though not sure if they are widely used enough to warrant the
|
|
# extra code complexity.
|
|
@ioprepped
|
|
@dataclass
|
|
class BoolResponse(Response):
|
|
"""A simple bool value response."""
|
|
|
|
value: Annotated[bool, IOAttrs('v')]
|
|
|
|
|
|
@ioprepped
|
|
@dataclass
|
|
class StringResponse(Response):
|
|
"""A simple string value response."""
|
|
|
|
value: Annotated[str, IOAttrs('v')]
|