diff --git a/.efrocachemap b/.efrocachemap index 018b6d0c..35d2bad2 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -430,12 +430,12 @@ "build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0", "build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e", "build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e", - "build/assets/ba_data/data/languages/english.json": "e70277fc6325126d3d893524c8df03c9", + "build/assets/ba_data/data/languages/english.json": "550aecdf2530832a8c095c2bda9ea8f0", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "347f38524816691170d266708fe25894", "build/assets/ba_data/data/languages/french.json": "4e218dcd488fa63e7db5b4da2261b9e1", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", - "build/assets/ba_data/data/languages/gibberish.json": "b8dfd407fb7fd9b268129c364b70ca54", + "build/assets/ba_data/data/languages/gibberish.json": "517e9c79ce8242af82366bbdaaf678a4", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", @@ -4056,53 +4056,53 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "a88d77584445b56200f7a4d8114479e8", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "4e88d22f136619fefd64f6ae0fd7e52c", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a955ca7a92a1e76c93a3af5ffd0fcdf8", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1d00f4ee25aff23dd1a12fa08a1427c7", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "8917a834461b62e8e31baf6d31f50dc6", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a1292d9dfb8880ddfac6d6b0313ad9e9", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b417628417ee7c7d652da528ab0df59f", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7d5f3261fa944c79e3b5e80751c4ec02", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "afcc34bd2e482a0913ca9105413840ab", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "c4c62a908705df5c136a3df2eb58f67a", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3e25752aea8cdc0ae68fb49869dfe79f", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "64ccbd2e2d2f3322663ca1b496b362ba", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ab7725c946a92f76e0eb739d6c0e5c74", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "5190ee608b6b5b62a97620cae58241d3", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "aa29ab65e0c4d22bc81f85198c74c39f", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "89dddd6606408d3d9990992b8ae52deb", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "330b671091d23f4259dff471a006e40b", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "709017df7f0de395cc2c8ec2d22b5fac", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d4f9a706114fdb3763f4982c87608ed6", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "d6532d25e4f8541402fcf1d7b0160048", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "f029c0682da29f46e5c9782bd2567f82", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "d2fe151ab5836d1f60b85bdc7d7880b1", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "ca6b96c7c6f77ab6ca93698da0022cb6", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "5342b4e44c8f414b34582ceec0ef0c8d", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "67e06b38ba6e5fa44fcb0b196618dda7", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "5a1a366e4458f48230a8856a04e3d15a", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "c1f9b4a7e4d8aef89de664fd19178b17", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7608557c57d636c81213afe0a68cd921", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "31465c3f4b869d6d2a4a004bcf43c058", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "4092f2c09d4717cbe22a9847733458ea", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a98776c44ceae70a5582fa3a31894f42", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "107c108da827cc647d26ea8e20e5a02a", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "d4e3d6b79648d478003282e20b583cf3", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "396f882b13a97bec718222d14be7a825", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "118e5039eb06c8d641baa3a94c511a20", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "2c4b12f038ad8eb9838860b8cce2f491", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "650b1181dda309c492abe2a26cedfd9a", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "32ac6359eb0296a319ddfcba3fcd04bc", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "731540517a251db7332d0f841d686d01", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a19df9a09272d486666a4cb28702cf2b", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "473e7e6c0cf90b9e6ac653552b18f68d", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "473e7e6c0cf90b9e6ac653552b18f68d", "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b483573e1ef7e6be1090c67187e9d1d8", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "d9af1a429cff9346e0cad6fcea017e5b", "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b483573e1ef7e6be1090c67187e9d1d8", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "d9af1a429cff9346e0cad6fcea017e5b", "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "cf4e9ef8006953c365b0928c68f5a21b", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "110eef3dc285a35a1899510e368c73b1", "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "cf4e9ef8006953c365b0928c68f5a21b", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "110eef3dc285a35a1899510e368c73b1", "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "840e96e79a56393c353184475cf28fbc", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "344954c4f788d7d9b4d7035ebb6131d8", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d0940a2237c33b922cf3747cbf3910ef", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "abcede4e60fa8877f18e66e086fb7387", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "dbb1863afd32a5624a5ef949fe8b48aa", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "11cd1f5e8099c505f429d224e0d8dcbf", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "bb9c8c00b6ef5b66422910f8cf9ccc83", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "fe8dfa263afab3982571178b0f2cff68", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "7f83d9986e6f0d66ed54692e740c2769", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "6f67485c14b38415888360bb3122a721", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "ea6d6a2bcdf18995af09452be534c947", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "3290cee0f4d306788ebd8a60c608e5f5", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "13615b9d10736d72e3b3bec605518645", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "99369ccd4edfe5cc2d54b18aa77ca1cb", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "33a19e9eb9bd9b655cbe70d8e250425b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "021114e14a72c621dc6fb7d4b3e41b5f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "cff4a800e4ea1cdb7690d088a4db0abb", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "107e289fb15a0d3177ed16aa8f076041", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4d031e12072278cf78570b64a2f7e533", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d7e631f313c7b99d92c41efaf6305b65", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", - "src/ballistica/base/mgen/pyembed/binding_base.inc": "bb96031e3f844704fcc9a0549a6d2c41", + "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", "src/ballistica/base/mgen/pyembed/binding_base_app.inc": "00f81f9bd92386ec12a6e60170678a98", "src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3", "src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69", diff --git a/CHANGELOG.md b/CHANGELOG.md index 81e96b70..72a3dce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21487, api 8, 2023-10-20) +### 1.7.28 (build 21488, api 8, 2023-10-20) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/babase/_hooks.py b/src/assets/ba_data/python/babase/_hooks.py index 69881e96..8ea73a5e 100644 --- a/src/assets/ba_data/python/babase/_hooks.py +++ b/src/assets/ba_data/python/babase/_hooks.py @@ -389,3 +389,17 @@ def string_edit_adapter_can_be_replaced(adapter: StringEditAdapter) -> bool: def get_dev_console_tab_names() -> list[str]: """Return the current set of dev-console tab names.""" return [t.name for t in _babase.app.devconsole.tabs] + + +def unsupported_controller_message(name: str) -> None: + """Print a message when an unsupported controller is connected.""" + from babase._language import Lstr + + # Ick; this can get called early in the bootstrapping process + # before we're allowed to load assets. Guard against that. + if _babase.asset_loads_allowed(): + _babase.getsimplesound('error').play() + _babase.screenmessage( + Lstr(resource='unsupportedControllerText', subs=[('${NAME}', name)]), + color=(1, 0, 0), + ) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 7b8bcc0d..1b03a2f8 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21487 +TARGET_BALLISTICA_BUILD = 21488 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/assets/assets.cc b/src/ballistica/base/assets/assets.cc index e00b84f3..1fe097d1 100644 --- a/src/ballistica/base/assets/assets.cc +++ b/src/ballistica/base/assets/assets.cc @@ -83,10 +83,9 @@ void Assets::StartLoading() { assert(g_base->audio_server && g_base->assets_server && g_base->graphics_server); assert(g_base->graphics->has_client_context()); - // assert(g_base->graphics_server->texture_compression_types_are_set()); - // assert(g_base->graphics_server->texture_quality_set()); - assert(!asset_loads_allowed_); // We should only be called once. + // We should only be called once. + assert(!asset_loads_allowed_); asset_loads_allowed_ = true; // Just grab the lock once for all this stuff for efficiency. diff --git a/src/ballistica/base/assets/assets.h b/src/ballistica/base/assets/assets.h index cbfa7ba1..0dc756ec 100644 --- a/src/ballistica/base/assets/assets.h +++ b/src/ballistica/base/assets/assets.h @@ -117,6 +117,8 @@ class Assets { auto language_state() const { return language_state_; } + auto asset_loads_allowed() const { return asset_loads_allowed_; } + private: static void MarkAssetForLoad(Asset* c); void LoadSystemTexture(SysTextureID id, const char* name); diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index c834d38a..b7e4abb3 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -662,6 +662,10 @@ void BaseFeatureSet::DoPushObjCall(const PythonObjectSetBase* objset, int id, auto BaseFeatureSet::IsAppStarted() const -> bool { return app_started_; } +auto BaseFeatureSet::IsAppBootstrapped() const -> bool { + return logic->app_bootstrapping_complete(); +} + auto BaseFeatureSet::ShutdownSuppressBegin() -> bool { std::scoped_lock lock(shutdown_suppress_lock_); diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index fa413c36..473e5edf 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -675,11 +675,18 @@ class BaseFeatureSet : public FeatureSetNativeComponent, /// High level screen-message call usable from any thread. void ScreenMessage(const std::string& s, const Vector3f& color) override; - /// Has StartApp been called (and completely finished its work)? - /// Code that sends calls/messages to other threads or otherwise uses - /// app functionality may want to check this to avoid crashes. + /// Has StartApp been called (and completely finished its work)? Code that + /// sends calls/messages to other threads or otherwise uses app + /// functionality may want to check this to avoid crashes. Note that some + /// app functionality such as loading assets is not available until + /// IsAppBootstrapped returns true. This call is thread safe. auto IsAppStarted() const -> bool override; + /// Has the app bootstrapping phase completed? The bootstrapping phase + /// involves initial screen/graphics setup. Asset loading is not allowed + /// until it is complete. + auto IsAppBootstrapped() const -> bool override; + void PlusDirectSendV1CloudLogs(const std::string& prefix, const std::string& suffix, bool instant, int* result) override; diff --git a/src/ballistica/base/python/base_python.h b/src/ballistica/base/python/base_python.h index fc70c6db..dc31d93f 100644 --- a/src/ballistica/base/python/base_python.h +++ b/src/ballistica/base/python/base_python.h @@ -110,6 +110,7 @@ class BasePython { kDevConsoleStringEditAdapterClass, kGetDevConsoleTabNamesCall, kAppDevConsoleDoRefreshTabCall, + kUnsupportedControllerMessageCall, kLast // Sentinel; must be at end. }; diff --git a/src/ballistica/base/python/methods/python_methods_misc.cc b/src/ballistica/base/python/methods/python_methods_misc.cc index 2f968b12..b7d1f2a9 100644 --- a/src/ballistica/base/python/methods/python_methods_misc.cc +++ b/src/ballistica/base/python/methods/python_methods_misc.cc @@ -33,6 +33,8 @@ static auto PyGetSimpleSound(PyObject* self, PyObject* args, PyObject* keywds) const_cast(kwlist), &name)) { return nullptr; } + BA_PRECONDITION(g_base->InLogicThread()); + BA_PRECONDITION(g_base->assets->asset_loads_allowed()); { Assets::AssetListLock lock; return PythonClassSimpleSound::Create(g_base->assets->GetSound(name)); @@ -1658,6 +1660,27 @@ static PyMethodDef PyDevConsoleRequestRefreshDef = { "(internal)", }; +// -------------------------- asset_loads_allowed ------------------------------ + +static auto PyAssetLoadsAllowed(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + if (g_base->assets->asset_loads_allowed()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyAssetLoadsAllowedDef = { + "asset_loads_allowed", // name + (PyCFunction)PyAssetLoadsAllowed, // method + METH_NOARGS, // flags + + "asset_loads_allowed() -> bool\n" + "\n" + "(internal)", +}; + // ----------------------------------------------------------------------------- auto PythonMethodsMisc::GetMethods() -> std::vector { @@ -1720,6 +1743,7 @@ auto PythonMethodsMisc::GetMethods() -> std::vector { PyDevConsoleTabHeightDef, PyDevConsoleBaseScaleDef, PyDevConsoleRequestRefreshDef, + PyAssetLoadsAllowedDef, }; } diff --git a/src/ballistica/core/support/base_soft.h b/src/ballistica/core/support/base_soft.h index 49fc62c9..31c83d30 100644 --- a/src/ballistica/core/support/base_soft.h +++ b/src/ballistica/core/support/base_soft.h @@ -42,6 +42,7 @@ class BaseSoftInterface { virtual void DoPushObjCall(const PythonObjectSetBase* objset, int id, const std::string& arg) = 0; virtual auto IsAppStarted() const -> bool = 0; + virtual auto IsAppBootstrapped() const -> bool = 0; virtual auto GetReturnValue() const -> int = 0; }; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 06a5ad67..4d5638db 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 = 21487; +const int kEngineBuildNumber = 21488; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/python/python_ref.cc b/src/ballistica/shared/python/python_ref.cc index e57a9aa4..de883e13 100644 --- a/src/ballistica/shared/python/python_ref.cc +++ b/src/ballistica/shared/python/python_ref.cc @@ -118,6 +118,10 @@ auto PythonRef::FromString(const std::string& val) -> PythonRef { return Stolen(PyUnicode_FromString(val.c_str())); } +auto PythonRef::SingleStringTuple(const std::string& val) -> PythonRef { + return Stolen(Py_BuildValue("(s)", val.c_str())); +} + auto PythonRef::Str() const -> std::string { assert(Python::HaveGIL()); if (!obj_) { diff --git a/src/ballistica/shared/python/python_ref.h b/src/ballistica/shared/python/python_ref.h index bdcf020b..0370dffe 100644 --- a/src/ballistica/shared/python/python_ref.h +++ b/src/ballistica/shared/python/python_ref.h @@ -68,6 +68,7 @@ class PythonRef { /// Shortcut to create a string object. static auto FromString(const std::string& val) -> PythonRef; + static auto SingleStringTuple(const std::string& val) -> PythonRef; /// Assignment from another PythonRef acquires a reference to the object /// referenced by other if there is one. If other has no reference, any diff --git a/src/meta/babasemeta/pyembed/binding_base.py b/src/meta/babasemeta/pyembed/binding_base.py index 848803bd..95e1da12 100644 --- a/src/meta/babasemeta/pyembed/binding_base.py +++ b/src/meta/babasemeta/pyembed/binding_base.py @@ -56,6 +56,7 @@ values = [ _hooks.show_post_purchase_message, # kShowPostPurchaseMessageCall _hooks.string_edit_adapter_can_be_replaced, # kStringEditAdapterCanBeReplacedCall _hooks.get_dev_console_tab_names, # kGetDevConsoleTabNamesCall + _hooks.unsupported_controller_message, # kUnsupportedControllerMessageCall _language.Lstr, # kLStrClass _general.Call, # kCallClass _apputils.garbage_collect_session_end, # kGarbageCollectSessionEndCall