mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-19 13:25:31 +08:00
added load_exported_classes function to meta system
This commit is contained in:
parent
0a25b07ec8
commit
9c63b8b4f9
@ -3995,26 +3995,26 @@
|
||||
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
|
||||
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34",
|
||||
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/16/55/a14a247c0db04420117a8ed371f6",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/00/ce/c04891665cbcfbdcd40befef320e",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b9/47/7ec5ce0741537a0a63bb812519e9",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/21/67/16065d61c11709286cbf58a8c1d3",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ef/0a/ac07d9d822e90baa8f7342041017",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f6/55/75ec6378098ac6c398432c4b2abc",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/11/b0/2e4b8b67b4ed827e6c70c5d4566a",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c2/fd/849f092a3abf28486999b5393552",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/05/91/4ebfc45bc0b5da7384ae8f93c921",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/09/d7/12317ddd52d8c59ed93423aaed46",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/16/b6/2f8c82eb93716e8aaad8613a2b6a",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b1/17/2893e78c6482b5d0e8cd3c267f41",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/71/18/ca3952e50e1b4961dac32174daef",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/cf/85/5e1fb710aa4eabbf4d54d2fd5e43",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ad/c9/9fa020ee678e12074f5d1f848055",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/25/fe/5084d63800be13121bbce5e2b718",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/67/52/13872d8fedb93a23be3931ab4ac8",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/82/7a/0eff468145e4ae32e9de2f564ede",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/7f/1b/4853e57aa94b004b8dd301ac0482",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/20/e6/9f3058021a438a944da4511fce3f",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/c7/0e/47a1cc6413aaad0c0afe0884b716",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/53/6f/5daf49965bace69f17f7b4ed2e55",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9a/35/4e8366fc775df35f7633d7a224ae",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/93/f2/0d4333951f150ea0aadfeaaae852",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/e7/01/2bec5299c6ff6bc9722f51b7839e",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/b3/70/90c234a390e49a1eff61a0de9eca",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2d/33/2ef1276ec090ed01884623346dd7",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/49/21/89e770f7339c8fa9782c7280c0af",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/62/15/699580dbe1d45625e063e056a547",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/4b/45/d857357c0c226d768434ade291d3",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f5/53/e0a72c39bbc8980f6cf3309e8074",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8b/6d/7c315ab5f44211be0f025d7b2c68",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/32/ad/5f826af4b9773a900b2709298943",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/82/31/94fef121e7a83af30760e550d800",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9a/12/e77b1a75fd08a625755d862700c4",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3d/4a/a0a222d942d7b36d4a58325c3f95",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/50/e8/001aa174b93d5ee0f076390add7a",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/15/2d/f1bc569de45c97fd5c1a769a4cb2",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/14/4f/6729d832b56076aeeb5b62db0b18",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/fc/ac/fdeac05ecc7a4ff5d4a0e33b4cd4",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/13/6a/baff53fa7c286e51469b0b32f05b",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/57/24/9f56b62f3d49ffcab8813e155311",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/db/15/191884a40ea1128a47058b19da6b",
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
### 1.7.7 (build 20690, api 7, 2022-08-11)
|
||||
- added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread
|
||||
- improved logging of missing playlist game types
|
||||
- some ba.Lstr functionality can now be used in background threads
|
||||
|
||||
|
||||
### 1.7.6 (build 20687, api 7, 2022-08-11)
|
||||
- Cleaned up da MetaSubsystem code.
|
||||
- It is now possible to tell the meta system about arbitrary classes (ba_meta export foo.bar.Class) instead of just the preset types 'plugin', 'game', etc.
|
||||
|
||||
@ -1 +1 @@
|
||||
105185559858403296763219852162674470262
|
||||
58062653605658487107918437258195542763
|
||||
@ -399,24 +399,3 @@ def cameraflash(duration: float = 999.0) -> None:
|
||||
light.node.delete,
|
||||
timeformat=TimeFormat.MILLISECONDS)
|
||||
activity.camera_flash_data.append(light) # type: ignore
|
||||
|
||||
|
||||
def get_game_types() -> list[type[ba.GameActivity]]:
|
||||
"""Return all available game types."""
|
||||
# pylint: disable=cyclic-import
|
||||
from ba._general import getclass
|
||||
from ba._gameactivity import GameActivity
|
||||
from ba._store import get_unowned_game_types
|
||||
|
||||
gameclassnames = _ba.app.meta.wait_for_scan_results().exports_of_class(
|
||||
GameActivity)
|
||||
gameclasses = []
|
||||
for gameclassname in gameclassnames:
|
||||
try:
|
||||
cls = getclass(gameclassname, GameActivity)
|
||||
gameclasses.append(cls)
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('error importing ' + str(gameclassname))
|
||||
unowned = get_unowned_game_types()
|
||||
return [cls for cls in gameclasses if cls not in unowned]
|
||||
|
||||
@ -12,6 +12,7 @@ from pathlib import Path
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from efro.call import tpartial
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -81,23 +82,73 @@ class MetadataSubsystem:
|
||||
self._scan = DirectoryScan(
|
||||
[_ba.app.python_directory_app, _ba.app.python_directory_user])
|
||||
|
||||
Thread(target=self._do_scan_dirs, daemon=True).start()
|
||||
Thread(target=self._run_scan_in_bg, daemon=True).start()
|
||||
|
||||
def start_extra_scan(self) -> None:
|
||||
"""Provide extra dirs to be scanned (namely Workspace dirs).
|
||||
"""Proceed to the extra_scan_dirs portion of the scan.
|
||||
|
||||
This is the bare minimum part of the scan that must be delayed until
|
||||
workspaces have been synced/etc. This must be called exactly once.
|
||||
This is for parts of the scan that must be delayed until
|
||||
workspace sync completion or other such events. This must be
|
||||
called exactly once.
|
||||
"""
|
||||
assert self._scan is not None
|
||||
self._scan.set_extras(self.extra_scan_dirs)
|
||||
|
||||
def wait_for_scan_results(self) -> ScanResults:
|
||||
def load_exported_classes(
|
||||
self,
|
||||
cls: type[T],
|
||||
completion_cb: Callable[[list[type[T]]], None],
|
||||
completion_cb_in_bg_thread: bool = False,
|
||||
) -> None:
|
||||
"""High level function to load meta-exported classes.
|
||||
|
||||
Will wait for scanning to complete if necessary, and will load all
|
||||
registered classes of a particular type in a background thread before
|
||||
calling the passed callback in the logic thread. Errors may be logged
|
||||
to messaged to the user in some way but the callback will be called
|
||||
regardless.
|
||||
To run the completion callback directly in the bg thread where the
|
||||
loading work happens, pass completion_cb_in_bg_thread=True.
|
||||
"""
|
||||
Thread(
|
||||
target=tpartial(self._load_exported_classes, cls, completion_cb,
|
||||
completion_cb_in_bg_thread),
|
||||
daemon=True,
|
||||
).start()
|
||||
|
||||
def _load_exported_classes(
|
||||
self,
|
||||
cls: type[T],
|
||||
completion_cb: Callable[[list[type[T]]], None],
|
||||
completion_cb_in_bg_thread: bool,
|
||||
) -> None:
|
||||
from ba._general import getclass
|
||||
classes: list[type[T]] = []
|
||||
try:
|
||||
classnames = self._wait_for_scan_results().exports_of_class(cls)
|
||||
for classname in classnames:
|
||||
try:
|
||||
classes.append(getclass(classname, cls))
|
||||
except Exception:
|
||||
logging.exception('error importing %s', classname)
|
||||
|
||||
except Exception:
|
||||
logging.exception('Error loading exported classes.')
|
||||
|
||||
completion_call = tpartial(completion_cb, classes)
|
||||
if completion_cb_in_bg_thread:
|
||||
completion_call()
|
||||
else:
|
||||
_ba.pushcall(completion_call, from_other_thread=True)
|
||||
|
||||
def _wait_for_scan_results(self) -> ScanResults:
|
||||
"""Return scan results, blocking if the scan is not yet complete."""
|
||||
if self.scanresults is None:
|
||||
logging.warning('ba.meta.wait_for_scan_results()'
|
||||
' called before scan completed;'
|
||||
' this can cause hitches.')
|
||||
if _ba.in_game_thread():
|
||||
logging.warning(
|
||||
'ba.meta._wait_for_scan_results()'
|
||||
' called in logic thread before scan completed;'
|
||||
' this can cause hitches.')
|
||||
|
||||
# Now wait a bit for the scan to complete.
|
||||
# Eventually error though if it doesn't.
|
||||
@ -109,6 +160,20 @@ class MetadataSubsystem:
|
||||
'timeout waiting for meta scan to complete.')
|
||||
return self.scanresults
|
||||
|
||||
def _run_scan_in_bg(self) -> None:
|
||||
"""Runs a scan (for use in background thread)."""
|
||||
try:
|
||||
assert self._scan is not None
|
||||
self._scan.run()
|
||||
results = self._scan.results
|
||||
self._scan = None
|
||||
except Exception as exc:
|
||||
results = ScanResults(errors=[f'Scan exception: {exc}'])
|
||||
|
||||
# Place results and tell the logic thread they're ready.
|
||||
self.scanresults = results
|
||||
_ba.pushcall(self._handle_scan_results, from_other_thread=True)
|
||||
|
||||
def _handle_scan_results(self) -> None:
|
||||
"""Called in the logic thread with results of a completed scan."""
|
||||
from ba._language import Lstr
|
||||
@ -139,20 +204,6 @@ class MetadataSubsystem:
|
||||
assert self._scan_complete_cb is not None
|
||||
self._scan_complete_cb()
|
||||
|
||||
def _do_scan_dirs(self) -> None:
|
||||
"""Runs a scan (for use in background thread)."""
|
||||
try:
|
||||
assert self._scan is not None
|
||||
self._scan.run()
|
||||
results = self._scan.results
|
||||
self._scan = None
|
||||
except Exception as exc:
|
||||
results = ScanResults(errors=[f'Scan exception: {exc}'])
|
||||
|
||||
# Place results and tell the logic thread they're ready.
|
||||
self.scanresults = results
|
||||
_ba.pushcall(self._handle_scan_results, from_other_thread=True)
|
||||
|
||||
|
||||
class DirectoryScan:
|
||||
"""Scans directories for metadata."""
|
||||
|
||||
@ -94,9 +94,11 @@ class MultiTeamSession(Session):
|
||||
playlist = _playlist.get_default_free_for_all_playlist()
|
||||
|
||||
# Resolve types and whatnot to get our final playlist.
|
||||
playlist_resolved = _playlist.filter_playlist(playlist,
|
||||
sessiontype=type(self),
|
||||
add_resolved_type=True)
|
||||
playlist_resolved = _playlist.filter_playlist(
|
||||
playlist,
|
||||
sessiontype=type(self),
|
||||
add_resolved_type=True,
|
||||
name='default teams' if self.use_teams else 'default ffa')
|
||||
|
||||
if not playlist_resolved:
|
||||
raise RuntimeError('Playlist contains no valid games.')
|
||||
|
||||
@ -18,7 +18,8 @@ def filter_playlist(playlist: PlaylistType,
|
||||
sessiontype: type[_session.Session],
|
||||
add_resolved_type: bool = False,
|
||||
remove_unowned: bool = True,
|
||||
mark_unowned: bool = False) -> PlaylistType:
|
||||
mark_unowned: bool = False,
|
||||
name: str = '?') -> PlaylistType:
|
||||
"""Return a filtered version of a playlist.
|
||||
|
||||
Strips out or replaces invalid or unowned game types, makes sure all
|
||||
@ -139,7 +140,7 @@ def filter_playlist(playlist: PlaylistType,
|
||||
entry['settings'][setting.name] = setting.default
|
||||
goodlist.append(entry)
|
||||
except ImportError as exc:
|
||||
_ba.log(f'Import failed while scanning playlist: {exc}',
|
||||
_ba.log(f'Import failed while scanning playlist \'{name}\': {exc}',
|
||||
to_server=False)
|
||||
except Exception:
|
||||
from ba import _error
|
||||
|
||||
@ -36,7 +36,7 @@ from ba._store import (get_available_sale_time, get_available_purchase_count,
|
||||
get_store_item, get_clean_price, get_unowned_maps,
|
||||
get_unowned_game_types)
|
||||
from ba._tournament import get_tournament_prize_strings
|
||||
from ba._gameutils import get_trophy_string, get_game_types
|
||||
from ba._gameutils import get_trophy_string
|
||||
|
||||
__all__ = [
|
||||
'get_unowned_maps', 'get_unowned_game_types', 'get_map_class',
|
||||
@ -56,6 +56,5 @@ __all__ = [
|
||||
'get_default_teams_playlist', 'filter_playlist', 'get_available_sale_time',
|
||||
'get_available_purchase_count', 'get_store_item_name_translated',
|
||||
'get_store_item_display_size', 'get_store_layout', 'get_store_item',
|
||||
'get_clean_price', 'get_tournament_prize_strings', 'get_trophy_string',
|
||||
'get_game_types'
|
||||
'get_clean_price', 'get_tournament_prize_strings', 'get_trophy_string'
|
||||
]
|
||||
|
||||
@ -184,7 +184,9 @@ class PrivateGatherTab(GatherTab):
|
||||
if playlist is None:
|
||||
playlist = pvars.get_default_list_call()
|
||||
|
||||
hcfg.playlist = filter_playlist(playlist, sessiontype)
|
||||
hcfg.playlist = filter_playlist(playlist,
|
||||
sessiontype,
|
||||
name=playlist_name)
|
||||
|
||||
randomize = cfg.get(f'{pvars.config_name} Playlist Randomize')
|
||||
if not isinstance(randomize, bool):
|
||||
|
||||
@ -116,10 +116,39 @@ class PlaylistAddGameWindow(ba.Window):
|
||||
ba.containerwidget(edit=self._root_widget,
|
||||
selected_child=self._scrollwidget)
|
||||
|
||||
self._game_types: list[type[ba.GameActivity]] = []
|
||||
|
||||
# Get actual games loading in the bg.
|
||||
ba.app.meta.load_exported_classes(ba.GameActivity,
|
||||
self._on_game_types_loaded,
|
||||
completion_cb_in_bg_thread=True)
|
||||
|
||||
# Refresh with our initial empty list. We'll refresh again once
|
||||
# game loading is complete.
|
||||
self._refresh()
|
||||
|
||||
def _on_game_types_loaded(self,
|
||||
gametypes: list[type[ba.GameActivity]]) -> None:
|
||||
from ba.internal import get_unowned_game_types
|
||||
|
||||
# We asked for a bg thread completion cb so we can do some
|
||||
# filtering here in the bg thread where its not gonna cause hitches.
|
||||
assert not _ba.in_game_thread()
|
||||
sessiontype = self._editcontroller.get_session_type()
|
||||
unowned = get_unowned_game_types()
|
||||
self._game_types = [
|
||||
gt for gt in gametypes
|
||||
if gt not in unowned and gt.supports_session_type(sessiontype)
|
||||
]
|
||||
|
||||
# Sort in the current language.
|
||||
self._game_types.sort(key=lambda g: g.get_display_string().evaluate())
|
||||
|
||||
# Tell ourself to refresh back in the logic thread.
|
||||
ba.pushcall(self._refresh, from_other_thread=True)
|
||||
|
||||
def _refresh(self, select_get_more_games_button: bool = False) -> None:
|
||||
from ba.internal import get_game_types
|
||||
# from ba.internal import get_game_types
|
||||
|
||||
if self._column is not None:
|
||||
self._column.delete()
|
||||
@ -128,15 +157,7 @@ class PlaylistAddGameWindow(ba.Window):
|
||||
border=2,
|
||||
margin=0)
|
||||
|
||||
gametypes = [
|
||||
gt for gt in get_game_types() if gt.supports_session_type(
|
||||
self._editcontroller.get_session_type())
|
||||
]
|
||||
|
||||
# Sort in the current language.
|
||||
gametypes.sort(key=lambda g: g.get_display_string().evaluate())
|
||||
|
||||
for i, gametype in enumerate(gametypes):
|
||||
for i, gametype in enumerate(self._game_types):
|
||||
|
||||
def _doit() -> None:
|
||||
if self._select_button:
|
||||
|
||||
@ -429,7 +429,8 @@ class PlaylistBrowserWindow(ba.Window):
|
||||
playlist = filter_playlist(playlist,
|
||||
self._sessiontype,
|
||||
remove_unowned=False,
|
||||
mark_unowned=True)
|
||||
mark_unowned=True,
|
||||
name=name)
|
||||
for entry in playlist:
|
||||
mapname = entry['settings']['map']
|
||||
maptype: type[ba.Map] | None
|
||||
|
||||
@ -52,7 +52,8 @@ class PlaylistEditController:
|
||||
appconfig[self._pvars.config_name +
|
||||
' Playlists'][existing_playlist_name],
|
||||
sessiontype=sessiontype,
|
||||
remove_unowned=False)
|
||||
remove_unowned=False,
|
||||
name=existing_playlist_name)
|
||||
self._edit_ui_selection = None
|
||||
else:
|
||||
if playlist is not None:
|
||||
|
||||
@ -86,7 +86,8 @@ class PlayOptionsWindow(popup.PopupWindow):
|
||||
plst = filter_playlist(plst,
|
||||
self._sessiontype,
|
||||
remove_unowned=False,
|
||||
mark_unowned=True)
|
||||
mark_unowned=True,
|
||||
name=name)
|
||||
game_count = len(plst)
|
||||
for entry in plst:
|
||||
mapname = entry['settings']['map']
|
||||
|
||||
@ -21,8 +21,8 @@
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kAppBuildNumber = 20687;
|
||||
const char* kAppVersion = "1.7.6";
|
||||
const int kAppBuildNumber = 20690;
|
||||
const char* kAppVersion = "1.7.7";
|
||||
|
||||
// Our standalone globals.
|
||||
// These are separated out for easy access.
|
||||
|
||||
@ -1569,7 +1569,10 @@ void Game::SetLanguageKeys(
|
||||
}
|
||||
|
||||
auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
assert(InGameThread());
|
||||
// NOTE: We currently talk to Python here so need to be sure
|
||||
// we're holding the GIL. Perhaps in the future we could handle this
|
||||
// stuff completely in C++ and be free of this limitation.
|
||||
assert(Python::HaveGIL());
|
||||
assert(obj != nullptr);
|
||||
|
||||
std::string result;
|
||||
@ -1707,8 +1710,8 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
if (subs->type != cJSON_Array) {
|
||||
throw Exception("expected an array for 'subs'");
|
||||
}
|
||||
int subsCount = cJSON_GetArraySize(subs);
|
||||
for (int i = 0; i < subsCount; i++) {
|
||||
int subs_count = cJSON_GetArraySize(subs);
|
||||
for (int i = 0; i < subs_count; i++) {
|
||||
cJSON* sub = cJSON_GetArrayItem(subs, i);
|
||||
if (sub->type != cJSON_Array || cJSON_GetArraySize(sub) != 2) {
|
||||
throw Exception(
|
||||
@ -1753,7 +1756,6 @@ auto DoCompileResourceString(cJSON* obj) -> std::string {
|
||||
|
||||
auto Game::CompileResourceString(const std::string& s, const std::string& loc,
|
||||
bool* valid) -> std::string {
|
||||
assert(InGameThread());
|
||||
assert(g_python != nullptr);
|
||||
|
||||
bool dummyvalid;
|
||||
|
||||
@ -1078,7 +1078,7 @@ Python::~Python() { Reset(false); }
|
||||
|
||||
auto Python::GetResource(const char* key, const char* fallback_resource,
|
||||
const char* fallback_value) -> std::string {
|
||||
assert(InGameThread());
|
||||
assert(HaveGIL());
|
||||
PythonRef results;
|
||||
BA_PRECONDITION(key != nullptr);
|
||||
const PythonRef& get_resource_call(obj(ObjID::kGetResourceCall));
|
||||
@ -1130,7 +1130,7 @@ auto Python::GetResource(const char* key, const char* fallback_resource,
|
||||
|
||||
auto Python::GetTranslation(const char* category, const char* s)
|
||||
-> std::string {
|
||||
assert(InGameThread());
|
||||
assert(HaveGIL());
|
||||
PythonRef results;
|
||||
PythonRef args(Py_BuildValue("(ss)", category, s), PythonRef::kSteal);
|
||||
// Don't print errors.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user