mirror of
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server.git
synced 2025-10-20 00:00:39 +00:00
1.7.10
This commit is contained in:
parent
7d3de819bf
commit
59730e19b3
17 changed files with 180 additions and 65 deletions
2
dist/ba_data/data/langdata.json
vendored
2
dist/ba_data/data/langdata.json
vendored
|
|
@ -78,7 +78,7 @@
|
|||
"adan",
|
||||
"Adeel (AdeZ {@adez_})",
|
||||
"Adel",
|
||||
"Rio adi",
|
||||
"Rio Adi",
|
||||
"Rayhan Adiansyah",
|
||||
"Yonas Adiel",
|
||||
"admin",
|
||||
|
|
|
|||
2
dist/ba_data/data/languages/venetian.json
vendored
2
dist/ba_data/data/languages/venetian.json
vendored
|
|
@ -1238,7 +1238,7 @@
|
|||
"enablePackageModsText": "Ativa pacheti mod łogałi",
|
||||
"enterPromoCodeText": "Insarisi còdaze",
|
||||
"forTestingText": "Nota: vałori vàłidi soło par proe. Sortendo da l'apl łi vegnarà perdesti.",
|
||||
"helpTranslateText": "Łe tradusion de ${APP_NAME} łe ze curàe da vołontari.\nSe A te vol darghe na ociada a cheła veneta, struca so'l boton\ncuà soto. Curada da Còdaze Veneto: codazeveneto@gmail.com",
|
||||
"helpTranslateText": "Łe tradusion de ${APP_NAME} łe ze curàe da vołontari.\nSe te vołi darghe na ociada a cheła veneta, struca so'l boton\ncuà soto. Curada da VeC: venetianlanguage@gmail.com",
|
||||
"kickIdlePlayersText": "Para fora zugadori in sonera",
|
||||
"kidFriendlyModeText": "Modałidà bocia (viołensa reduzesta, evc)",
|
||||
"languageText": "Łengua",
|
||||
|
|
|
|||
15
dist/ba_data/python/ba/_accountv2.py
vendored
15
dist/ba_data/python/ba/_accountv2.py
vendored
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
from typing import Any
|
||||
|
||||
|
||||
class AccountV2Subsystem:
|
||||
|
|
@ -111,10 +111,21 @@ class AccountV2Subsystem:
|
|||
|
||||
|
||||
class AccountV2Handle:
|
||||
"""Handle for interacting with a v2 account."""
|
||||
"""Handle for interacting with a V2 account.
|
||||
|
||||
This class supports the 'with' statement, which is how it is
|
||||
used with some operations such as cloud messaging.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.tag = '?'
|
||||
|
||||
self.workspacename: str | None = None
|
||||
self.workspaceid: str | None = None
|
||||
|
||||
def __enter__(self) -> None:
|
||||
"""Support for "with" statement.
|
||||
"""
|
||||
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any:
|
||||
"""Support for "with" statement."""
|
||||
|
|
|
|||
5
dist/ba_data/python/ba/_benchmark.py
vendored
5
dist/ba_data/python/ba/_benchmark.py
vendored
|
|
@ -60,7 +60,7 @@ def run_stress_test(playlist_type: str = 'Random',
|
|||
from ba._generated.enums import TimeType
|
||||
_ba.screenmessage(
|
||||
'Beginning stress test.. use '
|
||||
"'End Game' to stop testing.",
|
||||
"'End Test' to stop testing.",
|
||||
color=(1, 1, 0))
|
||||
with _ba.Context('ui'):
|
||||
start_stress_test({
|
||||
|
|
@ -138,7 +138,8 @@ def _reset_stress_test(args: dict[str, Any]) -> None:
|
|||
|
||||
def run_gpu_benchmark() -> None:
|
||||
"""Kick off a benchmark to test gpu speeds."""
|
||||
_ba.screenmessage('FIXME: Not wired up yet.', color=(1, 0, 0))
|
||||
# FIXME: Not wired up yet.
|
||||
_ba.screenmessage('Not wired up yet.', color=(1, 0, 0))
|
||||
|
||||
|
||||
def run_media_reload_benchmark() -> None:
|
||||
|
|
|
|||
2
dist/ba_data/python/ba/_bootstrap.py
vendored
2
dist/ba_data/python/ba/_bootstrap.py
vendored
|
|
@ -45,7 +45,7 @@ def bootstrap() -> None:
|
|||
|
||||
# Give a soft warning if we're being used with a different binary
|
||||
# version than we expect.
|
||||
expected_build = 20887
|
||||
expected_build = 20891
|
||||
running_build: int = env['build_number']
|
||||
if running_build != expected_build:
|
||||
print(
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
position=((self._sub_width - button_width) * 0.5, v + 30),
|
||||
autoselect=True,
|
||||
size=(button_width, 60),
|
||||
label=ba.Lstr(resource=self._r + '.manageAccount'),
|
||||
label=ba.Lstr(resource=self._r + '.manageAccountText'),
|
||||
color=(0.55, 0.5, 0.6),
|
||||
icon=ba.gettexture('settingsIcon'),
|
||||
textcolor=(0.75, 0.7, 0.8),
|
||||
|
|
|
|||
53
dist/ba_data/python/bastd/ui/mainmenu.py
vendored
53
dist/ba_data/python/bastd/ui/mainmenu.py
vendored
|
|
@ -56,10 +56,11 @@ class MainMenuWindow(ba.Window):
|
|||
self._gather_button: ba.Widget | None = None
|
||||
self._start_button: ba.Widget | None = None
|
||||
self._watch_button: ba.Widget | None = None
|
||||
self._gc_button: ba.Widget | None = None
|
||||
self._account_button: ba.Widget | None = None
|
||||
self._how_to_play_button: ba.Widget | None = None
|
||||
self._credits_button: ba.Widget | None = None
|
||||
self._settings_button: ba.Widget | None = None
|
||||
self._next_refresh_allow_time = 0.0
|
||||
|
||||
self._store_char_tex = self._get_store_char_tex()
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ class MainMenuWindow(ba.Window):
|
|||
self._account_state_num = ba.internal.get_v1_account_state_num()
|
||||
self._account_type = (ba.internal.get_v1_account_type()
|
||||
if self._account_state == 'signed_in' else None)
|
||||
self._refresh_timer = ba.Timer(1.0,
|
||||
self._refresh_timer = ba.Timer(0.27,
|
||||
ba.WeakCall(self._check_refresh),
|
||||
repeat=True,
|
||||
timetype=ba.TimeType.REAL)
|
||||
|
|
@ -132,11 +133,15 @@ class MainMenuWindow(ba.Window):
|
|||
if not self._root_widget:
|
||||
return
|
||||
|
||||
now = ba.time(ba.TimeType.REAL)
|
||||
if now < self._next_refresh_allow_time:
|
||||
return
|
||||
|
||||
# Don't refresh for the first few seconds the game is up so we don't
|
||||
# interrupt the transition in.
|
||||
ba.app.main_menu_window_refresh_check_count += 1
|
||||
if ba.app.main_menu_window_refresh_check_count < 4:
|
||||
return
|
||||
# ba.app.main_menu_window_refresh_check_count += 1
|
||||
# if ba.app.main_menu_window_refresh_check_count < 4:
|
||||
# return
|
||||
|
||||
store_char_tex = self._get_store_char_tex()
|
||||
account_state_num = ba.internal.get_v1_account_state_num()
|
||||
|
|
@ -250,8 +255,12 @@ class MainMenuWindow(ba.Window):
|
|||
scale=scale,
|
||||
size=(self._button_width, self._button_height),
|
||||
autoselect=self._use_autoselect,
|
||||
label=ba.Lstr(resource=self._r + '.endGameText'),
|
||||
on_activate_call=self._confirm_end_game)
|
||||
label=ba.Lstr(resource=self._r +
|
||||
('.endTestText' if self._is_benchmark(
|
||||
) else '.endGameText')),
|
||||
on_activate_call=(self._confirm_end_test
|
||||
if self._is_benchmark() else
|
||||
self._confirm_end_game))
|
||||
# Assume we're in a client-session.
|
||||
else:
|
||||
ba.buttonwidget(
|
||||
|
|
@ -424,6 +433,7 @@ class MainMenuWindow(ba.Window):
|
|||
self._tdelay = 2.0
|
||||
self._t_delay_inc = 0.02
|
||||
self._t_delay_play = 1.7
|
||||
self._next_refresh_allow_time = ba.time(ba.TimeType.REAL) + 2.01
|
||||
ba.app.did_menu_intro = True
|
||||
self._width = 400.0
|
||||
self._height = 200.0
|
||||
|
|
@ -605,7 +615,7 @@ class MainMenuWindow(ba.Window):
|
|||
this_b_width = self._button_width
|
||||
h, v, scale = positions[self._p_index]
|
||||
self._p_index += 1
|
||||
self._gc_button = ba.buttonwidget(
|
||||
self._account_button = ba.buttonwidget(
|
||||
parent=self._root_widget,
|
||||
position=(h - this_b_width * 0.5 * scale, v),
|
||||
size=(this_b_width, self._button_height),
|
||||
|
|
@ -633,7 +643,7 @@ class MainMenuWindow(ba.Window):
|
|||
tilt_scale=0.0)
|
||||
self._tdelay += self._t_delay_inc
|
||||
else:
|
||||
self._gc_button = None
|
||||
self._account_button = None
|
||||
|
||||
# How-to-play button.
|
||||
h, v, scale = positions[self._p_index]
|
||||
|
|
@ -848,7 +858,7 @@ class MainMenuWindow(ba.Window):
|
|||
ba.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
ba.app.ui.set_main_menu_window(
|
||||
AccountSettingsWindow(
|
||||
origin_widget=self._gc_button).get_root_widget())
|
||||
origin_widget=self._account_button).get_root_widget())
|
||||
|
||||
def _on_store_pressed(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
|
|
@ -863,6 +873,11 @@ class MainMenuWindow(ba.Window):
|
|||
StoreBrowserWindow(
|
||||
origin_widget=self._store_button).get_root_widget())
|
||||
|
||||
def _is_benchmark(self) -> bool:
|
||||
session = ba.internal.get_foreground_host_session()
|
||||
return (getattr(session, 'benchmark_type', None) == 'cpu'
|
||||
or ba.app.stress_test_reset_timer is not None)
|
||||
|
||||
def _confirm_end_game(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from bastd.ui.confirm import ConfirmWindow
|
||||
|
|
@ -874,6 +889,16 @@ class MainMenuWindow(ba.Window):
|
|||
self._end_game,
|
||||
cancel_is_selected=True)
|
||||
|
||||
def _confirm_end_test(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from bastd.ui.confirm import ConfirmWindow
|
||||
|
||||
# Select cancel by default; this occasionally gets called by accident
|
||||
# in a fit of button mashing and this will help reduce damage.
|
||||
ConfirmWindow(ba.Lstr(resource=self._r + '.exitToMenuText'),
|
||||
self._end_game,
|
||||
cancel_is_selected=True)
|
||||
|
||||
def _confirm_end_replay(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from bastd.ui.confirm import ConfirmWindow
|
||||
|
|
@ -965,8 +990,8 @@ class MainMenuWindow(ba.Window):
|
|||
ba.app.ui.main_menu_selection = 'Credits'
|
||||
elif sel == self._settings_button:
|
||||
ba.app.ui.main_menu_selection = 'Settings'
|
||||
elif sel == self._gc_button:
|
||||
ba.app.ui.main_menu_selection = 'GameService'
|
||||
elif sel == self._account_button:
|
||||
ba.app.ui.main_menu_selection = 'Account'
|
||||
elif sel == self._store_button:
|
||||
ba.app.ui.main_menu_selection = 'Store'
|
||||
elif sel == self._quit_button:
|
||||
|
|
@ -997,8 +1022,8 @@ class MainMenuWindow(ba.Window):
|
|||
sel = self._credits_button
|
||||
elif sel_name == 'Settings':
|
||||
sel = self._settings_button
|
||||
elif sel_name == 'GameService':
|
||||
sel = self._gc_button
|
||||
elif sel_name == 'Account':
|
||||
sel = self._account_button
|
||||
elif sel_name == 'Store':
|
||||
sel = self._store_button
|
||||
elif sel_name == 'Quit':
|
||||
|
|
|
|||
|
|
@ -146,13 +146,14 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
|
|||
|
||||
ba.pushcall(_print_in_logic_thread, from_other_thread=True)
|
||||
|
||||
def _print_test_results(call: Callable[[], Any]) -> None:
|
||||
"""Run the provided call; return success/fail text & color."""
|
||||
def _print_test_results(call: Callable[[], Any]) -> bool:
|
||||
"""Run the provided call, print result, & return success."""
|
||||
starttime = time.monotonic()
|
||||
try:
|
||||
call()
|
||||
duration = time.monotonic() - starttime
|
||||
_print(f'Succeeded in {duration:.2f}s.', color=(0, 1, 0))
|
||||
return True
|
||||
except Exception as exc:
|
||||
import traceback
|
||||
duration = time.monotonic() - starttime
|
||||
|
|
@ -161,6 +162,7 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
|
|||
_print(msg, color=(1.0, 1.0, 0.3))
|
||||
_print(f'Failed in {duration:.2f}s.', color=(1, 0, 0))
|
||||
have_error[0] = True
|
||||
return False
|
||||
|
||||
try:
|
||||
_print(f'Running network diagnostics...\n'
|
||||
|
|
@ -177,14 +179,23 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
|
|||
# V1 ping
|
||||
baseaddr = ba.internal.get_master_server_address(source=0, version=1)
|
||||
_print(f'\nContacting V1 master-server src0 ({baseaddr})...')
|
||||
_print_test_results(lambda: _test_fetch(baseaddr))
|
||||
v1worked = _print_test_results(lambda: _test_fetch(baseaddr))
|
||||
|
||||
# V1 alternate ping
|
||||
baseaddr = ba.internal.get_master_server_address(source=1, version=1)
|
||||
_print(f'\nContacting V1 master-server src1 ({baseaddr})...')
|
||||
_print_test_results(lambda: _test_fetch(baseaddr))
|
||||
# V1 alternate ping (only if primary fails since this often fails).
|
||||
if v1worked:
|
||||
_print('\nSkipping V1 master-server src1 test since src0 worked.')
|
||||
else:
|
||||
baseaddr = ba.internal.get_master_server_address(source=1,
|
||||
version=1)
|
||||
_print(f'\nContacting V1 master-server src1 ({baseaddr})...')
|
||||
_print_test_results(lambda: _test_fetch(baseaddr))
|
||||
|
||||
_print(f'\nV1-test-log: {ba.app.net.v1_test_log}')
|
||||
if 'none succeeded' in ba.app.net.v1_test_log:
|
||||
_print(f'\nV1-test-log failed: {ba.app.net.v1_test_log}',
|
||||
color=(1, 0, 0))
|
||||
have_error[0] = True
|
||||
else:
|
||||
_print(f'\nV1-test-log ok: {ba.app.net.v1_test_log}')
|
||||
|
||||
for srcid, result in sorted(ba.app.net.v1_ctest_results.items()):
|
||||
_print(f'\nV1 src{srcid} result: {result}')
|
||||
|
|
|
|||
|
|
@ -522,6 +522,7 @@ class TournamentEntryWindow(popup.PopupWindow):
|
|||
if ticket_count is not None and ticket_count < ticket_cost:
|
||||
getcurrency.show_get_tickets_prompt()
|
||||
ba.playsound(ba.getsound('error'))
|
||||
self._transition_out()
|
||||
return
|
||||
|
||||
cur_time = ba.time(ba.TimeType.REAL, ba.TimeFormat.MILLISECONDS)
|
||||
|
|
|
|||
1
dist/ba_data/python/efro/message/_message.py
vendored
1
dist/ba_data/python/efro/message/_message.py
vendored
|
|
@ -61,6 +61,7 @@ class ErrorSysResponse(SysResponse):
|
|||
REMOTE_CLEAN = 1
|
||||
LOCAL = 2
|
||||
COMMUNICATION = 3
|
||||
REMOTE_COMMUNICATION = 4
|
||||
|
||||
error_message: Annotated[str, IOAttrs('m')]
|
||||
error_type: Annotated[ErrorType, IOAttrs('e')] = ErrorType.REMOTE
|
||||
|
|
|
|||
77
dist/ba_data/python/efro/message/_protocol.py
vendored
77
dist/ba_data/python/efro/message/_protocol.py
vendored
|
|
@ -8,10 +8,9 @@ from __future__ import annotations
|
|||
|
||||
from typing import TYPE_CHECKING
|
||||
import traceback
|
||||
import logging
|
||||
import json
|
||||
|
||||
from efro.error import CleanError
|
||||
from efro.error import CleanError, CommunicationError
|
||||
from efro.dataclassio import (is_ioprepped_dataclass, dataclass_to_dict,
|
||||
dataclass_from_dict)
|
||||
from efro.message._message import (Message, Response, SysResponse,
|
||||
|
|
@ -34,24 +33,50 @@ class MessageProtocol:
|
|||
def __init__(self,
|
||||
message_types: dict[int, type[Message]],
|
||||
response_types: dict[int, type[Response]],
|
||||
forward_communication_errors: bool = False,
|
||||
forward_clean_errors: bool = False,
|
||||
remote_errors_include_stack_traces: bool = False) -> None:
|
||||
remote_errors_include_stack_traces: bool = False,
|
||||
log_remote_errors: bool = True) -> None:
|
||||
"""Create a protocol with a given configuration.
|
||||
|
||||
Note that common response types are automatically registered
|
||||
with (unchanging negative ids) so they don't need to be passed
|
||||
explicitly (but can be if a different id is desired).
|
||||
If 'forward_communication_errors' is True,
|
||||
efro.error.CommunicationErrors raised on the receiver end will
|
||||
result in a matching error raised back on the sender. This can
|
||||
be useful if the receiver will be in some way forwarding
|
||||
messages along and the sender doesn't need to know where
|
||||
communication breakdowns occurred; only that they did.
|
||||
|
||||
If 'forward_clean_errors' is True, efro.error.CleanError
|
||||
exceptions raised on the receiver end will result in a matching
|
||||
CleanError raised back on the sender. All other Exception types
|
||||
come across as efro.error.RemoteError.
|
||||
CleanError raised back on the sender.
|
||||
|
||||
If 'remote_errors_include_stack_traces' is True, stringified stack
|
||||
traces will be returned to the sender for exceptions occurring
|
||||
on the receiver end. This can make debugging easier but should
|
||||
only be used when the client is trusted to see such info.
|
||||
When an exception is not covered by the optional forwarding
|
||||
mechanisms above, it will come across as efro.error.RemoteError
|
||||
and the exception will be logged on the receiver
|
||||
end - at least by default (see details below).
|
||||
|
||||
If 'remote_errors_include_stack_traces' is True, stringified
|
||||
stack traces will be returned with efro.error.RemoteError
|
||||
exceptions. This is useful for debugging but should only be
|
||||
enabled in cases where the sender is trusted to see internal
|
||||
details of the receiver.
|
||||
|
||||
By default, when a message-handling exception will result in an
|
||||
efro.error.RemoteError being returned to the sender, the
|
||||
exception will be logged on the receiver. This is because the
|
||||
goal is usually to avoid returning opaque RemoteErrors and to
|
||||
instead return something meaningful as part of the expected
|
||||
response type (even if that value itself represents a logical
|
||||
error state). If 'log_remote_errors' is False, however, such
|
||||
exceptions will not be logged on the receiver. This can be
|
||||
useful in combination with 'remote_errors_include_stack_traces'
|
||||
and 'forward_clean_errors' in situations where all error
|
||||
logging/management will be happening on the sender end. Be
|
||||
aware, however, that in that case it may be possible for
|
||||
communication errors to prevent such error messages from
|
||||
ever being seen.
|
||||
"""
|
||||
# pylint: disable=too-many-locals
|
||||
self.message_types_by_id: dict[int, type[Message]] = {}
|
||||
self.message_ids_by_type: dict[type[Message], int] = {}
|
||||
self.response_types_by_id: dict[int, type[Response]
|
||||
|
|
@ -123,8 +148,10 @@ class MessageProtocol:
|
|||
' all types are required to have unique names.')
|
||||
|
||||
self.forward_clean_errors = forward_clean_errors
|
||||
self.forward_communication_errors = forward_communication_errors
|
||||
self.remote_errors_include_stack_traces = (
|
||||
remote_errors_include_stack_traces)
|
||||
self.log_remote_errors = log_remote_errors
|
||||
|
||||
@staticmethod
|
||||
def encode_dict(obj: dict) -> str:
|
||||
|
|
@ -139,23 +166,31 @@ class MessageProtocol:
|
|||
"""Encode a response to a json ready dict."""
|
||||
return self._to_dict(response, self.response_ids_by_type, 'response')
|
||||
|
||||
def error_to_response(self, exc: Exception) -> SysResponse:
|
||||
"""Translate an error to a response."""
|
||||
def error_to_response(self, exc: Exception) -> tuple[SysResponse, bool]:
|
||||
"""Translate an Exception to a SysResponse.
|
||||
|
||||
# Log any errors we got during handling.
|
||||
logging.exception('Error in efro.message handling.')
|
||||
Also returns whether the error should be logged if this happened
|
||||
within handle_raw_message().
|
||||
"""
|
||||
|
||||
# If anything goes wrong, return a ErrorSysResponse instead.
|
||||
# (either CLEAN or generic REMOTE)
|
||||
if isinstance(exc, CleanError) and self.forward_clean_errors:
|
||||
return ErrorSysResponse(
|
||||
if self.forward_clean_errors and isinstance(exc, CleanError):
|
||||
return (ErrorSysResponse(
|
||||
error_message=str(exc),
|
||||
error_type=ErrorSysResponse.ErrorType.REMOTE_CLEAN)
|
||||
return ErrorSysResponse(
|
||||
error_type=ErrorSysResponse.ErrorType.REMOTE_CLEAN), False)
|
||||
if self.forward_communication_errors and isinstance(
|
||||
exc, CommunicationError):
|
||||
return (ErrorSysResponse(
|
||||
error_message=str(exc),
|
||||
error_type=ErrorSysResponse.ErrorType.REMOTE_COMMUNICATION),
|
||||
False)
|
||||
return (ErrorSysResponse(
|
||||
error_message=(traceback.format_exc()
|
||||
if self.remote_errors_include_stack_traces else
|
||||
'An internal error has occurred.'),
|
||||
error_type=ErrorSysResponse.ErrorType.REMOTE)
|
||||
error_type=ErrorSysResponse.ErrorType.REMOTE),
|
||||
self.log_remote_errors)
|
||||
|
||||
def _to_dict(self, message: Any, ids_by_type: dict[type, int],
|
||||
opname: str) -> dict:
|
||||
|
|
|
|||
26
dist/ba_data/python/efro/message/_receiver.py
vendored
26
dist/ba_data/python/efro/message/_receiver.py
vendored
|
|
@ -260,14 +260,14 @@ class MessageReceiver:
|
|||
return self.protocol.encode_dict(response_dict)
|
||||
|
||||
def encode_error_response(self, bound_obj: Any, message: Message | None,
|
||||
exc: Exception) -> str:
|
||||
"""Given an error, return a response ready for sending."""
|
||||
response = self.protocol.error_to_response(exc)
|
||||
exc: Exception) -> tuple[str, bool]:
|
||||
"""Given an error, return sysresponse str and whether to log."""
|
||||
response, dolog = self.protocol.error_to_response(exc)
|
||||
response_dict = self.protocol.response_to_dict(response)
|
||||
if self._encode_filter_call is not None:
|
||||
self._encode_filter_call(bound_obj, message, response,
|
||||
response_dict)
|
||||
return self.protocol.encode_dict(response_dict)
|
||||
return self.protocol.encode_dict(response_dict), dolog
|
||||
|
||||
def handle_raw_message(self,
|
||||
bound_obj: Any,
|
||||
|
|
@ -296,7 +296,11 @@ class MessageReceiver:
|
|||
if (raise_unregistered
|
||||
and isinstance(exc, UnregisteredMessageIDError)):
|
||||
raise
|
||||
return self.encode_error_response(bound_obj, msg_decoded, exc)
|
||||
rstr, dolog = self.encode_error_response(bound_obj, msg_decoded,
|
||||
exc)
|
||||
if dolog:
|
||||
logging.exception('Error in efro.message handling.')
|
||||
return rstr
|
||||
|
||||
async def handle_raw_message_async(
|
||||
self,
|
||||
|
|
@ -324,7 +328,11 @@ class MessageReceiver:
|
|||
if (raise_unregistered
|
||||
and isinstance(exc, UnregisteredMessageIDError)):
|
||||
raise
|
||||
return self.encode_error_response(bound_obj, msg_decoded, exc)
|
||||
rstr, dolog = self.encode_error_response(bound_obj, msg_decoded,
|
||||
exc)
|
||||
if dolog:
|
||||
logging.exception('Error in efro.message handling.')
|
||||
return rstr
|
||||
|
||||
|
||||
class BoundMessageReceiver:
|
||||
|
|
@ -348,9 +356,9 @@ class BoundMessageReceiver:
|
|||
"""Given an error, return a response ready to send.
|
||||
|
||||
This should be used for any errors that happen outside of
|
||||
of standard handle_raw_message calls. Any errors within those
|
||||
calls should be automatically returned as encoded strings.
|
||||
standard handle_raw_message calls. Any errors within those
|
||||
calls will be automatically returned as encoded strings.
|
||||
"""
|
||||
# Passing None for Message here; we would only have that available
|
||||
# for things going wrong in the handler (which this is not for).
|
||||
return self._receiver.encode_error_response(self._obj, None, exc)
|
||||
return self._receiver.encode_error_response(self._obj, None, exc)[0]
|
||||
|
|
|
|||
5
dist/ba_data/python/efro/message/_sender.py
vendored
5
dist/ba_data/python/efro/message/_sender.py
vendored
|
|
@ -272,6 +272,11 @@ class MessageSender:
|
|||
is ErrorSysResponse.ErrorType.REMOTE_CLEAN):
|
||||
raise CleanError(raw_response.error_message)
|
||||
|
||||
if (self.protocol.forward_communication_errors
|
||||
and raw_response.error_type is
|
||||
ErrorSysResponse.ErrorType.REMOTE_COMMUNICATION):
|
||||
raise CommunicationError(raw_response.error_message)
|
||||
|
||||
# Everything else gets lumped in as a remote error.
|
||||
raise RemoteError(raw_response.error_message,
|
||||
peer_desc=('peer' if self._peer_desc_call is None
|
||||
|
|
|
|||
27
dist/ba_data/python/efro/rpc.py
vendored
27
dist/ba_data/python/efro/rpc.py
vendored
|
|
@ -290,17 +290,24 @@ class RPCEndpoint:
|
|||
|
||||
async def send_message(self,
|
||||
message: bytes,
|
||||
timeout: float | None = None) -> bytes:
|
||||
timeout: float | None = None,
|
||||
close_on_error: bool = True) -> bytes:
|
||||
"""Send a message to the peer and return a response.
|
||||
|
||||
If timeout is not provided, the default will be used.
|
||||
Raises a CommunicationError if the round trip is not completed
|
||||
for any reason.
|
||||
|
||||
By default, the entire endpoint will go down in the case of
|
||||
errors. This allows messages to be treated as 'reliable' with
|
||||
respect to a given endpoint. Pass close_on_error=False to
|
||||
override this for a particular message.
|
||||
"""
|
||||
# pylint: disable=too-many-branches
|
||||
self._check_env()
|
||||
|
||||
if self._closing:
|
||||
raise CommunicationError('Endpoint is closed')
|
||||
raise CommunicationError('Endpoint is closed.')
|
||||
|
||||
# We need to know their protocol, so if we haven't gotten a handshake
|
||||
# from them yet, just wait.
|
||||
|
|
@ -358,6 +365,8 @@ class RPCEndpoint:
|
|||
if self._debug_print:
|
||||
self._debug_print_call(
|
||||
f'{self._label}: message {message_id} was cancelled.')
|
||||
if close_on_error:
|
||||
self.close()
|
||||
raise CommunicationError() from exc
|
||||
except asyncio.TimeoutError as exc:
|
||||
if self._debug_print:
|
||||
|
|
@ -370,6 +379,9 @@ class RPCEndpoint:
|
|||
# Remove the record of this message.
|
||||
del self._in_flight_messages[message_id]
|
||||
|
||||
if close_on_error:
|
||||
self.close()
|
||||
|
||||
# Let the user know something went wrong.
|
||||
raise CommunicationError() from exc
|
||||
|
||||
|
|
@ -407,7 +419,11 @@ class RPCEndpoint:
|
|||
return self._closing
|
||||
|
||||
async def wait_closed(self) -> None:
|
||||
"""I said seagulls; mmmm; stop it now."""
|
||||
"""I said seagulls; mmmm; stop it now.
|
||||
|
||||
Wait for the endpoint to finish closing. This is called by run()
|
||||
so generally does not need to be explicitly called.
|
||||
"""
|
||||
# pylint: disable=too-many-branches
|
||||
self._check_env()
|
||||
|
||||
|
|
@ -729,8 +745,9 @@ class RPCEndpoint:
|
|||
|
||||
def _check_env(self) -> None:
|
||||
# I was seeing that asyncio stuff wasn't working as expected if
|
||||
# created in one thread and used in another, so let's enforce
|
||||
# a single thread for all use of an instance.
|
||||
# created in one thread and used in another (and have verified
|
||||
# that this is part of the design), so let's enforce a single
|
||||
# thread for all use of an instance.
|
||||
if current_thread() is not self._thread:
|
||||
raise RuntimeError('This must be called from the same thread'
|
||||
' that the endpoint was created in.')
|
||||
|
|
|
|||
BIN
dist/ba_root/mods/aarch64/BridgitMash.so
vendored
BIN
dist/ba_root/mods/aarch64/BridgitMash.so
vendored
Binary file not shown.
BIN
dist/bombsquad_headless
vendored
BIN
dist/bombsquad_headless
vendored
Binary file not shown.
BIN
dist/bombsquad_headless_aarch64
vendored
BIN
dist/bombsquad_headless_aarch64
vendored
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue