diff --git a/.efrocachemap b/.efrocachemap
index 48afcdae..7147fcd0 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -4072,26 +4072,26 @@
"build/assets/workspace/ninjafightplug.py": "https://files.ballistica.net/cache/ba1/c5/09/4f10b8a21ba87aa5509cff7a164b",
"build/assets/workspace/onslaughtplug.py": "https://files.ballistica.net/cache/ba1/ff/0a/a354984f9c074dab0676ac7e4877",
"build/assets/workspace/runaroundplug.py": "https://files.ballistica.net/cache/ba1/2a/1c/9ee5db6d1bceca7fa6638fb8abde",
- "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/27/dc/4461ec2c763316d0f738fbf72e6b",
- "build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/23/1e/35d837927c1715e936f41ff0c4d7",
- "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/1e/96/6b0a986344ff771d9ce82d58eae9",
- "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/34/b7/9d49ff2ab653b3e462d237e6a1cd",
- "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/1b/09/d19d7965237783341bc46a5fdbf6",
- "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/95/fb/51828c82315a5e91c5f8a2e678f4",
- "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d7/f8/b7288e653ce7c0362f37a593c5e6",
- "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/14/01/f40276b9d4dd8e84ba580ca6fd45",
- "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/37/3a/beb0e2a42e30415f58c480cc95be",
- "build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/61/f4/b30550e367475bd2d67c528f56b7",
- "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/e2/a4/00bacbbd429e054be3a99221d790",
- "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/fa/f2/644aab7337cf5244a6f67378c64c",
- "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/c5/51/a126f6c9229eddf2ea2b49ce0411",
- "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/9f/61/c9ec84831c096b443f0073af2044",
- "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/89/7b/190ec36b4a9df1f203fe1045d12e",
- "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/88/b2/47314eda637619d4ce37c99adbb2",
- "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/3d/5c/517d4615e73b042f3daa8c54666e",
- "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/17/ff/9644c1a371811284532d9318d242",
- "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/ec/84/097506824e9dc267b0d82d713143",
- "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/eb/72/24622b15642dd28f9e0377f6f45d",
+ "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/12/bf/7ec79c0aedc17a67b4dadfd08940",
+ "build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/4f/66/dba5b2aa02a80e80dff750a59553",
+ "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/8d/06/c4cb56349781f97a3ff8081ce3ac",
+ "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/c7/83/c7044a678a0bb28195d5a8c76972",
+ "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/08/90/96f0187beb141245d5ad0fdcd4f7",
+ "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/4f/fe/9446e923a16f2b13690604ec0772",
+ "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/c3/ab/2210004b5dc928aca3ed235d4bc3",
+ "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/c9/ff/904e8b4cdad471b5becd33800a53",
+ "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/d5/2c/c580c5031d93138dce8e6513f44b",
+ "build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/b9/12/a189b59b2bf373f4545dab5529b4",
+ "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/76/f0/f13c0fc030c17dd7b8ae70a14811",
+ "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/59/25/a117150d6353eaa36fd14d98850a",
+ "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/bc/66/3644111b6407169b361d6aaf19e4",
+ "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/b7/c1/d9c0f9a0eaf8545c7319325528c2",
+ "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/7f/36/67da0a6bdd15c3683cd7f2f05e4c",
+ "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/9f/04/1094813b2f57b157669b7bb7fef4",
+ "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/64/a8/21bbfb168fce276fc37a2483131c",
+ "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/20/0e/3da8e1dc080eb9f3f38072854084",
+ "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/8c/84/2ccb6892467dda04dccc3a588afb",
+ "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/a4/99/cbb84a6fc6560fbfebad7c4b5914",
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/66/b7/4be2fcf57b9bc9cb12d97d6ac298",
"build/prefab/lib/linux_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/4d/31/1654791c0ae8eb78b517b548f2f7",
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/62/04/d4b18d10e866785b23756d48f91c",
@@ -4108,14 +4108,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/a7/38/f5ebf21a44b3968a1623ae839721",
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/b7/fa/1f32d0fedf5e54092d434bff20ed",
"build/prefab/lib/mac_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/d2/5a/08f06543729620d0d08b31b4c0a4",
- "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/54/26/ff90fc304b6dccaa16520ec64c7e",
- "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/09/22/674953cef241287d44f6f8166886",
- "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/a1/a6/5303ac4c045520c1a9c9cf412157",
- "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/00/74/1bdb26aa39cac30211ae080e3ce9",
- "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/77/26/caa7f379c5f32e2f96edda7cfe0e",
- "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/ec/e3/0b00701c99c191a863877fc60aa5",
- "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/41/58/71125ca7e4e993fbc7f3ba289fcc",
- "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/81/c2/d83668721b23f4f2742c44a008e8",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/ea/0d/87102c47c88a5077106bfb030417",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/11/6e/1b3922bdfc900fb97b597f654ff3",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/2c/77/e7f546cd770b3882a5a45c08fad7",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/fe/51/65adfa3db7103ae3a0091c8f074d",
+ "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/56/6a/64335024396af0c5937351bc47d5",
+ "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/0c/82/cabf653687553241a25bcd58abba",
+ "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/92/c6/81a1b6e477a46b2ec087ad955a22",
+ "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/f5/fd/bad2f69341a2db63af7714702fe2",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "https://files.ballistica.net/cache/ba1/52/c6/c11130af7b10d6c0321add5518fa",
"src/assets/ba_data/python/babase/_mgen/enums.py": "https://files.ballistica.net/cache/ba1/38/c3/1dedd5e74f2508efc5974c8815a1",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/75/9f/bcf597b362c9f2480cb348188bdd",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e43d8ce2..f7ebe28d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-### 1.7.20 (build 21055, api 8, 2023-06-07)
+### 1.7.20 (build 21058, api 8, 2023-06-07)
- This seems like a good time for a `refactoring` release in anticipation of
changes coming in 1.8. Basically this means that a lot of things will be
@@ -268,8 +268,9 @@
when bascenev2 comes along, it can have its own unique associated library of
stuff (bascenev2lib). To upgrade existing code, go through and replace
instances of `bastd.ui` with `bauiv1lib` and all other instances of `bastd`
- with `bascenev1lib`. That should mostly do it. As a random tip: check out the
+ with `bascenev1lib`. That should mostly do it. Random tip: check out the
`tools/pcommand mypy_files` as a handy tool to help get your mods updated.
+- (build 21057) Fixed an issue with news items erroring on the main menu (thanks for the heads up Rikko)
### 1.7.19 (build 20997, api 7, 2023-01-19)
diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py
index 96f69d41..be7595e0 100644
--- a/src/assets/ba_data/python/baenv.py
+++ b/src/assets/ba_data/python/baenv.py
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
-TARGET_BALLISTICA_BUILD = 21055
+TARGET_BALLISTICA_BUILD = 21058
TARGET_BALLISTICA_VERSION = '1.7.20'
_g_env_config: EnvConfig | None = None
diff --git a/src/assets/ba_data/python/bascenev1lib/mainmenu.py b/src/assets/ba_data/python/bascenev1lib/mainmenu.py
index c797095c..d1e74f63 100644
--- a/src/assets/ba_data/python/bascenev1lib/mainmenu.py
+++ b/src/assets/ba_data/python/bascenev1lib/mainmenu.py
@@ -16,26 +16,39 @@ import bauiv1 as bui
if TYPE_CHECKING:
from typing import Any
-# FIXME: Clean this up if I ever revisit it.
-# pylint: disable=attribute-defined-outside-init
-# pylint: disable=too-many-branches
-# pylint: disable=too-many-statements
-# pylint: disable=too-many-locals
-# noinspection PyUnreachableCode
-# noinspection PyAttributeOutsideInit
-
class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
"""Activity showing the rotating main menu bg stuff."""
_stdassets = bs.Dependency(bs.AssetPackage, 'stdassets@1')
- def on_transition_in(self) -> None:
- super().on_transition_in()
- random.seed(123)
+ def __init__(self, settings: dict):
+ super().__init__(settings)
self._logo_node: bs.Node | None = None
self._custom_logo_tex_name: str | None = None
self._word_actors: list[bs.Actor] = []
+ self.my_name: bs.NodeActor | None = None
+ self._host_is_navigating_text: bs.NodeActor | None = None
+ self.version: bs.NodeActor | None = None
+ self.beta_info: bs.NodeActor | None = None
+ self.beta_info_2: bs.NodeActor | None = None
+ self.bottom: bs.NodeActor | None = None
+ self.vr_bottom_fill: bs.NodeActor | None = None
+ self.vr_top_fill: bs.NodeActor | None = None
+ self.terrain: bs.NodeActor | None = None
+ self.trees: bs.NodeActor | None = None
+ self.bgterrain: bs.NodeActor | None = None
+ self._ts = 0.86
+ self._language: str | None = None
+ self._update_timer: bs.Timer | None = None
+ self._news: NewsDisplay | None = None
+
+ def on_transition_in(self) -> None:
+ # pylint: disable=too-many-locals
+ # pylint: disable=too-many-statements
+ # pylint: disable=too-many-branches
+ super().on_transition_in()
+ random.seed(123)
app = bs.app
assert app.classic is not None
@@ -96,6 +109,7 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
if not app.classic.main_menu_did_initial_transition and hasattr(
self, 'my_name'
):
+ assert self.my_name is not None
assert self.my_name.node
bs.animate(self.my_name.node, 'opacity', {2.3: 0, 3.0: 1.0})
@@ -291,9 +305,6 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
)
)
- self._ts = 0.86
-
- self._language: str | None = None
self._update_timer = bs.Timer(1.0, self._update, repeat=True)
self._update()
@@ -302,189 +313,8 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
random.seed()
- # On the main menu, also show our news.
- class News:
- """Wrangles news display."""
-
- def __init__(self, activity: bs.Activity):
- self._valid = True
- self._message_duration = 10.0
- self._message_spacing = 2.0
- self._text: bs.NodeActor | None = None
- self._activity = weakref.ref(activity)
-
- # If we're signed in, fetch news immediately.
- # Otherwise wait until we are signed in.
- self._fetch_timer: bs.Timer | None = bs.Timer(
- 1.0, bs.WeakCall(self._try_fetching_news), repeat=True
- )
- self._try_fetching_news()
- self._used_phrases: list[str] = []
-
- # We now want to wait until we're signed in before fetching news.
- def _try_fetching_news(self) -> None:
- plus = bui.app.plus
- assert plus is not None
-
- if plus.get_v1_account_state() == 'signed_in':
- self._fetch_news()
- self._fetch_timer = None
-
- def _fetch_news(self) -> None:
- plus = bui.app.plus
- assert plus is not None
-
- assert bs.app.classic is not None
- bs.app.classic.main_menu_last_news_fetch_time = time.time()
-
- # UPDATE - We now just pull news from MRVs.
- news = plus.get_v1_account_misc_read_val('n', None)
- if news is not None:
- self._got_news(news)
-
- def _change_phrase(self) -> None:
- from bascenev1lib.actor.text import Text
-
- app = bs.app
- assert app.classic is not None
-
- # If our news is way out of date, lets re-request it;
- # otherwise, rotate our phrase.
- assert app.classic.main_menu_last_news_fetch_time is not None
- if (
- time.time() - app.classic.main_menu_last_news_fetch_time
- > 600.0
- ):
- self._fetch_news()
- self._text = None
- else:
- if self._text is not None:
- if not self._phrases:
- for phr in self._used_phrases:
- self._phrases.insert(0, phr)
- val = self._phrases.pop()
- if val == '__ACH__':
- vrmode = app.vr_mode
- Text(
- bs.Lstr(resource='nextAchievementsText'),
- color=(
- (1, 1, 1, 1)
- if vrmode
- else (0.95, 0.9, 1, 0.4)
- ),
- host_only=True,
- maxwidth=200,
- position=(-300, -35),
- h_align=Text.HAlign.RIGHT,
- transition=Text.Transition.FADE_IN,
- scale=0.9 if vrmode else 0.7,
- flatness=1.0 if vrmode else 0.6,
- shadow=1.0 if vrmode else 0.5,
- h_attach=Text.HAttach.CENTER,
- v_attach=Text.VAttach.TOP,
- transition_delay=1.0,
- transition_out_delay=self._message_duration,
- ).autoretain()
- achs = [
- a
- for a in app.classic.ach.achievements
- if not a.complete
- ]
- if achs:
- ach = achs.pop(
- random.randrange(min(4, len(achs)))
- )
- ach.create_display(
- -180,
- -35,
- 1.0,
- outdelay=self._message_duration,
- style='news',
- )
- if achs:
- ach = achs.pop(
- random.randrange(min(8, len(achs)))
- )
- ach.create_display(
- 180,
- -35,
- 1.25,
- outdelay=self._message_duration,
- style='news',
- )
- else:
- spc = self._message_spacing
- keys = {
- spc: 0.0,
- spc + 1.0: 1.0,
- spc + self._message_duration - 1.0: 1.0,
- spc + self._message_duration: 0.0,
- }
- assert self._text.node
- bs.animate(self._text.node, 'opacity', keys)
- # {k: v
- # for k, v in list(keys.items())})
- self._text.node.text = val
-
- def _got_news(self, news: str) -> None:
- # Run this stuff in the context of our activity since we
- # need to make nodes and stuff.. should fix the serverget
- # call so it.
- activity = self._activity()
- if activity is None or activity.expired:
- return
- with activity.context:
- self._phrases: list[str] = []
-
- # Show upcoming achievements in non-vr versions
- # (currently too hard to read in vr).
- self._used_phrases = (
- ['__ACH__'] if not bs.app.vr_mode else []
- ) + [s for s in news.split('
\n') if s != '']
- self._phrase_change_timer = bs.Timer(
- (self._message_duration + self._message_spacing),
- bs.WeakCall(self._change_phrase),
- repeat=True,
- )
-
- assert bs.app.classic is not None
- scl = (
- 1.2
- if (
- bs.app.classic.ui.uiscale is bs.UIScale.SMALL
- or bs.app.vr_mode
- )
- else 0.8
- )
-
- color2 = (
- (1, 1, 1, 1)
- if bs.app.vr_mode
- else (0.7, 0.65, 0.75, 1.0)
- )
- shadow = 1.0 if bs.app.vr_mode else 0.4
- self._text = bs.NodeActor(
- bs.newnode(
- 'text',
- attrs={
- 'v_attach': 'top',
- 'h_attach': 'center',
- 'h_align': 'center',
- 'vr_depth': -20,
- 'shadow': shadow,
- 'flatness': 0.8,
- 'v_align': 'top',
- 'color': color2,
- 'scale': scl,
- 'maxwidth': 900.0 / scl,
- 'position': (0, -10),
- },
- )
- )
- self._change_phrase()
-
if not (app.demo_mode or app.arcade_mode) and not app.toolbar_test:
- self._news = News(self)
+ self._news = NewsDisplay(self)
# Bring up the last place we were, or start at the main menu otherwise.
with bs.ContextRef.empty():
@@ -584,6 +414,8 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
app.classic.main_menu_did_initial_transition = True
def _update(self) -> None:
+ # pylint: disable=too-many-locals
+ # pylint: disable=too-many-statements
app = bs.app
assert app.classic is not None
@@ -799,6 +631,9 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
vr_depth_offset: float = 0.0,
shadow: bool = False,
) -> None:
+ # pylint: disable=too-many-branches
+ # pylint: disable=too-many-locals
+ # pylint: disable=too-many-statements
if shadow:
word_obj = bs.NodeActor(
bs.newnode(
@@ -925,6 +760,7 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
rotate: float = 0.0,
vr_depth_offset: float = 0.0,
) -> None:
+ # pylint: disable=too-many-locals
# Temp easter goodness.
if custom_texture is None:
custom_texture = self._get_custom_logo_tex_name()
@@ -1008,6 +844,174 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
bui.apptimer(0.5, _start_menu_music)
+class NewsDisplay:
+ """Wrangles news display."""
+
+ def __init__(self, activity: bs.Activity):
+ self._valid = True
+ self._message_duration = 10.0
+ self._message_spacing = 2.0
+ self._text: bs.NodeActor | None = None
+ self._activity = weakref.ref(activity)
+ self._phrases: list[str] = []
+ self._used_phrases: list[str] = []
+ self._phrase_change_timer: bs.Timer | None = None
+
+ # If we're signed in, fetch news immediately.
+ # Otherwise wait until we are signed in.
+ self._fetch_timer: bs.Timer | None = bs.Timer(
+ 1.0, bs.WeakCall(self._try_fetching_news), repeat=True
+ )
+ self._try_fetching_news()
+
+ # We now want to wait until we're signed in before fetching news.
+ def _try_fetching_news(self) -> None:
+ plus = bui.app.plus
+ assert plus is not None
+
+ if plus.get_v1_account_state() == 'signed_in':
+ self._fetch_news()
+ self._fetch_timer = None
+
+ def _fetch_news(self) -> None:
+ plus = bui.app.plus
+ assert plus is not None
+
+ assert bs.app.classic is not None
+ bs.app.classic.main_menu_last_news_fetch_time = time.time()
+
+ # UPDATE - We now just pull news from MRVs.
+ news = plus.get_v1_account_misc_read_val('n', None)
+ if news is not None:
+ self._got_news(news)
+
+ def _change_phrase(self) -> None:
+ from bascenev1lib.actor.text import Text
+
+ app = bs.app
+ assert app.classic is not None
+
+ # If our news is way out of date, lets re-request it;
+ # otherwise, rotate our phrase.
+ assert app.classic.main_menu_last_news_fetch_time is not None
+ if time.time() - app.classic.main_menu_last_news_fetch_time > 600.0:
+ self._fetch_news()
+ self._text = None
+ else:
+ if self._text is not None:
+ if not self._phrases:
+ for phr in self._used_phrases:
+ self._phrases.insert(0, phr)
+ val = self._phrases.pop()
+ if val == '__ACH__':
+ vrmode = app.vr_mode
+ Text(
+ bs.Lstr(resource='nextAchievementsText'),
+ color=((1, 1, 1, 1) if vrmode else (0.95, 0.9, 1, 0.4)),
+ host_only=True,
+ maxwidth=200,
+ position=(-300, -35),
+ h_align=Text.HAlign.RIGHT,
+ transition=Text.Transition.FADE_IN,
+ scale=0.9 if vrmode else 0.7,
+ flatness=1.0 if vrmode else 0.6,
+ shadow=1.0 if vrmode else 0.5,
+ h_attach=Text.HAttach.CENTER,
+ v_attach=Text.VAttach.TOP,
+ transition_delay=1.0,
+ transition_out_delay=self._message_duration,
+ ).autoretain()
+ achs = [
+ a
+ for a in app.classic.ach.achievements
+ if not a.complete
+ ]
+ if achs:
+ ach = achs.pop(random.randrange(min(4, len(achs))))
+ ach.create_display(
+ -180,
+ -35,
+ 1.0,
+ outdelay=self._message_duration,
+ style='news',
+ )
+ if achs:
+ ach = achs.pop(random.randrange(min(8, len(achs))))
+ ach.create_display(
+ 180,
+ -35,
+ 1.25,
+ outdelay=self._message_duration,
+ style='news',
+ )
+ else:
+ spc = self._message_spacing
+ keys = {
+ spc: 0.0,
+ spc + 1.0: 1.0,
+ spc + self._message_duration - 1.0: 1.0,
+ spc + self._message_duration: 0.0,
+ }
+ assert self._text.node
+ bs.animate(self._text.node, 'opacity', keys)
+ # {k: v
+ # for k, v in list(keys.items())})
+ self._text.node.text = val
+
+ def _got_news(self, news: str) -> None:
+ # Run this stuff in the context of our activity since we
+ # need to make nodes and stuff.. should fix the serverget
+ # call so it.
+ activity = self._activity()
+ if activity is None or activity.expired:
+ return
+ with activity.context:
+ self._phrases.clear()
+
+ # Show upcoming achievements in non-vr versions
+ # (currently too hard to read in vr).
+ self._used_phrases = (['__ACH__'] if not bs.app.vr_mode else []) + [
+ s for s in news.split('
\n') if s != ''
+ ]
+ self._phrase_change_timer = bs.Timer(
+ (self._message_duration + self._message_spacing),
+ bs.WeakCall(self._change_phrase),
+ repeat=True,
+ )
+
+ assert bs.app.classic is not None
+ scl = (
+ 1.2
+ if (
+ bs.app.classic.ui.uiscale is bs.UIScale.SMALL
+ or bs.app.vr_mode
+ )
+ else 0.8
+ )
+
+ color2 = (1, 1, 1, 1) if bs.app.vr_mode else (0.7, 0.65, 0.75, 1.0)
+ shadow = 1.0 if bs.app.vr_mode else 0.4
+ self._text = bs.NodeActor(
+ bs.newnode(
+ 'text',
+ attrs={
+ 'v_attach': 'top',
+ 'h_attach': 'center',
+ 'h_align': 'center',
+ 'vr_depth': -20,
+ 'shadow': shadow,
+ 'flatness': 0.8,
+ 'v_align': 'top',
+ 'color': color2,
+ 'scale': scl,
+ 'maxwidth': 900.0 / scl,
+ 'position': (0, -10),
+ },
+ )
+ )
+ self._change_phrase()
+
+
def _preload1() -> None:
"""Pre-load some assets a second or two into the main menu.
diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc
index 2d9c2ae8..00f6bf79 100644
--- a/src/ballistica/shared/ballistica.cc
+++ b/src/ballistica/shared/ballistica.cc
@@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
-const int kEngineBuildNumber = 21055;
+const int kEngineBuildNumber = 21058;
const char* kEngineVersion = "1.7.20";
auto MonolithicMain(const core::CoreConfig& core_config) -> int {