bauiv1lib.connectivity

UI functionality related to master-server connectivity.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""UI functionality related to master-server connectivity."""
  4
  5from __future__ import annotations
  6
  7import time
  8from typing import TYPE_CHECKING
  9
 10import bauiv1 as bui
 11
 12if TYPE_CHECKING:
 13    from typing import Callable, Any
 14
 15
 16def wait_for_connectivity(
 17    on_connected: Callable[[], Any],
 18    on_cancel: Callable[[], Any] | None = None,
 19) -> None:
 20    """Wait for the engine to establish a master-server connection.
 21
 22    If need be, shows a window to keep the user informed of connectivity
 23    state and allows the user to cancel the operation. Note that canceling
 24    does not prevent the engine from continuing its attempt to establish
 25    connectivity; it simply cancels the operation that depends on it.
 26    """
 27    plus = bui.app.plus
 28    assert plus is not None
 29
 30    # Quick-out: if we're already connected, don't bother with the UI.
 31    # We do, however, push this call instead of calling it immediately
 32    # so as to be consistent with the waiting path.
 33    if plus.cloud.connected:
 34        bui.pushcall(on_connected)
 35        return
 36
 37    WaitForConnectivityWindow(on_connected=on_connected, on_cancel=on_cancel)
 38
 39
 40class WaitForConnectivityWindow(bui.Window):
 41    """Window informing the user that the game is establishing connectivity."""
 42
 43    def __init__(
 44        self,
 45        on_connected: Callable[[], Any],
 46        on_cancel: Callable[[], Any] | None,
 47    ) -> None:
 48        self._on_connected = on_connected
 49        self._on_cancel = on_cancel
 50        self._width = 650
 51        self._height = 300
 52        self._infos: list[str | bui.Lstr] = [
 53            'This can take a few moments, especially on first launch.',
 54            'Make sure your internet connection is working.',
 55        ]
 56        self._last_info_switch_time = time.monotonic()
 57        self._info_index = 0
 58        super().__init__(
 59            root_widget=bui.containerwidget(
 60                size=(self._width, self._height),
 61                transition='in_scale',
 62                parent=bui.get_special_widget('overlay_stack'),
 63            )
 64        )
 65        bui.textwidget(
 66            parent=self._root_widget,
 67            position=(self._width * 0.5, self._height * 0.65),
 68            size=(0, 0),
 69            scale=1.2,
 70            h_align='center',
 71            v_align='center',
 72            text='Locating nearest regional servers...',
 73            maxwidth=self._width * 0.9,
 74        )
 75        self._info_text = bui.textwidget(
 76            parent=self._root_widget,
 77            position=(self._width * 0.5, self._height * 0.45),
 78            size=(0, 0),
 79            color=(0.7, 0.6, 0.7),
 80            flatness=1.0,
 81            scale=0.8,
 82            h_align='center',
 83            v_align='center',
 84            text=self._infos[0],
 85            maxwidth=self._width * 0.9,
 86        )
 87        cancel_button = bui.buttonwidget(
 88            parent=self._root_widget,
 89            autoselect=True,
 90            position=(50, 30),
 91            size=(150, 50),
 92            label=bui.Lstr(resource='cancelText'),
 93            on_activate_call=self._cancel,
 94        )
 95        bui.containerwidget(edit=self._root_widget, cancel_button=cancel_button)
 96        self._update_timer = bui.AppTimer(
 97            0.113, bui.WeakCall(self._update), repeat=True
 98        )
 99
100    def _update(self) -> None:
101        now = time.monotonic()
102
103        plus = bui.app.plus
104        assert plus is not None
105
106        if plus.cloud.connected:
107            self._connected()
108            return
109
110        if now - self._last_info_switch_time > 5.0:
111            self._info_index = (self._info_index + 1) % len(self._infos)
112            bui.textwidget(
113                edit=self._info_text, text=self._infos[self._info_index]
114            )
115            self._last_info_switch_time = now
116
117    def _connected(self) -> None:
118        if not self._root_widget or self._root_widget.transitioning_out:
119            return
120        bui.containerwidget(
121            edit=self._root_widget,
122            transition=('out_scale'),
123        )
124        bui.pushcall(self._on_connected)
125
126    def _cancel(self) -> None:
127        if not self._root_widget or self._root_widget.transitioning_out:
128            return
129        bui.containerwidget(
130            edit=self._root_widget,
131            transition=('out_scale'),
132        )
133        if self._on_cancel is not None:
134            bui.pushcall(self._on_cancel)
def wait_for_connectivity( on_connected: Callable[[], Any], on_cancel: Optional[Callable[[], Any]] = None) -> None:
17def wait_for_connectivity(
18    on_connected: Callable[[], Any],
19    on_cancel: Callable[[], Any] | None = None,
20) -> None:
21    """Wait for the engine to establish a master-server connection.
22
23    If need be, shows a window to keep the user informed of connectivity
24    state and allows the user to cancel the operation. Note that canceling
25    does not prevent the engine from continuing its attempt to establish
26    connectivity; it simply cancels the operation that depends on it.
27    """
28    plus = bui.app.plus
29    assert plus is not None
30
31    # Quick-out: if we're already connected, don't bother with the UI.
32    # We do, however, push this call instead of calling it immediately
33    # so as to be consistent with the waiting path.
34    if plus.cloud.connected:
35        bui.pushcall(on_connected)
36        return
37
38    WaitForConnectivityWindow(on_connected=on_connected, on_cancel=on_cancel)

Wait for the engine to establish a master-server connection.

If need be, shows a window to keep the user informed of connectivity state and allows the user to cancel the operation. Note that canceling does not prevent the engine from continuing its attempt to establish connectivity; it simply cancels the operation that depends on it.

class WaitForConnectivityWindow(bauiv1._uitypes.Window):
 41class WaitForConnectivityWindow(bui.Window):
 42    """Window informing the user that the game is establishing connectivity."""
 43
 44    def __init__(
 45        self,
 46        on_connected: Callable[[], Any],
 47        on_cancel: Callable[[], Any] | None,
 48    ) -> None:
 49        self._on_connected = on_connected
 50        self._on_cancel = on_cancel
 51        self._width = 650
 52        self._height = 300
 53        self._infos: list[str | bui.Lstr] = [
 54            'This can take a few moments, especially on first launch.',
 55            'Make sure your internet connection is working.',
 56        ]
 57        self._last_info_switch_time = time.monotonic()
 58        self._info_index = 0
 59        super().__init__(
 60            root_widget=bui.containerwidget(
 61                size=(self._width, self._height),
 62                transition='in_scale',
 63                parent=bui.get_special_widget('overlay_stack'),
 64            )
 65        )
 66        bui.textwidget(
 67            parent=self._root_widget,
 68            position=(self._width * 0.5, self._height * 0.65),
 69            size=(0, 0),
 70            scale=1.2,
 71            h_align='center',
 72            v_align='center',
 73            text='Locating nearest regional servers...',
 74            maxwidth=self._width * 0.9,
 75        )
 76        self._info_text = bui.textwidget(
 77            parent=self._root_widget,
 78            position=(self._width * 0.5, self._height * 0.45),
 79            size=(0, 0),
 80            color=(0.7, 0.6, 0.7),
 81            flatness=1.0,
 82            scale=0.8,
 83            h_align='center',
 84            v_align='center',
 85            text=self._infos[0],
 86            maxwidth=self._width * 0.9,
 87        )
 88        cancel_button = bui.buttonwidget(
 89            parent=self._root_widget,
 90            autoselect=True,
 91            position=(50, 30),
 92            size=(150, 50),
 93            label=bui.Lstr(resource='cancelText'),
 94            on_activate_call=self._cancel,
 95        )
 96        bui.containerwidget(edit=self._root_widget, cancel_button=cancel_button)
 97        self._update_timer = bui.AppTimer(
 98            0.113, bui.WeakCall(self._update), repeat=True
 99        )
100
101    def _update(self) -> None:
102        now = time.monotonic()
103
104        plus = bui.app.plus
105        assert plus is not None
106
107        if plus.cloud.connected:
108            self._connected()
109            return
110
111        if now - self._last_info_switch_time > 5.0:
112            self._info_index = (self._info_index + 1) % len(self._infos)
113            bui.textwidget(
114                edit=self._info_text, text=self._infos[self._info_index]
115            )
116            self._last_info_switch_time = now
117
118    def _connected(self) -> None:
119        if not self._root_widget or self._root_widget.transitioning_out:
120            return
121        bui.containerwidget(
122            edit=self._root_widget,
123            transition=('out_scale'),
124        )
125        bui.pushcall(self._on_connected)
126
127    def _cancel(self) -> None:
128        if not self._root_widget or self._root_widget.transitioning_out:
129            return
130        bui.containerwidget(
131            edit=self._root_widget,
132            transition=('out_scale'),
133        )
134        if self._on_cancel is not None:
135            bui.pushcall(self._on_cancel)

Window informing the user that the game is establishing connectivity.

WaitForConnectivityWindow( on_connected: Callable[[], Any], on_cancel: Optional[Callable[[], Any]])
44    def __init__(
45        self,
46        on_connected: Callable[[], Any],
47        on_cancel: Callable[[], Any] | None,
48    ) -> None:
49        self._on_connected = on_connected
50        self._on_cancel = on_cancel
51        self._width = 650
52        self._height = 300
53        self._infos: list[str | bui.Lstr] = [
54            'This can take a few moments, especially on first launch.',
55            'Make sure your internet connection is working.',
56        ]
57        self._last_info_switch_time = time.monotonic()
58        self._info_index = 0
59        super().__init__(
60            root_widget=bui.containerwidget(
61                size=(self._width, self._height),
62                transition='in_scale',
63                parent=bui.get_special_widget('overlay_stack'),
64            )
65        )
66        bui.textwidget(
67            parent=self._root_widget,
68            position=(self._width * 0.5, self._height * 0.65),
69            size=(0, 0),
70            scale=1.2,
71            h_align='center',
72            v_align='center',
73            text='Locating nearest regional servers...',
74            maxwidth=self._width * 0.9,
75        )
76        self._info_text = bui.textwidget(
77            parent=self._root_widget,
78            position=(self._width * 0.5, self._height * 0.45),
79            size=(0, 0),
80            color=(0.7, 0.6, 0.7),
81            flatness=1.0,
82            scale=0.8,
83            h_align='center',
84            v_align='center',
85            text=self._infos[0],
86            maxwidth=self._width * 0.9,
87        )
88        cancel_button = bui.buttonwidget(
89            parent=self._root_widget,
90            autoselect=True,
91            position=(50, 30),
92            size=(150, 50),
93            label=bui.Lstr(resource='cancelText'),
94            on_activate_call=self._cancel,
95        )
96        bui.containerwidget(edit=self._root_widget, cancel_button=cancel_button)
97        self._update_timer = bui.AppTimer(
98            0.113, bui.WeakCall(self._update), repeat=True
99        )