diff --git a/.efrocachemap b/.efrocachemap
index 8a51eada..9a11f4aa 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -3989,6 +3989,9 @@
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/f5/8b/14895df9caf46f326a3c939b34a4",
"assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e",
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
+ "assets/build/workspace/ninjafightplug.py": "https://files.ballistica.net/cache/ba1/27/16/71d2713a32c66caf37806f645a71",
+ "assets/build/workspace/onslaughtplug.py": "https://files.ballistica.net/cache/ba1/c6/4c/47fe21bbcd938711d1ec2a19589d",
+ "assets/build/workspace/runaroundplug.py": "https://files.ballistica.net/cache/ba1/b1/38/beac9de90bee75363d1de76706b4",
"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",
@@ -4000,18 +4003,18 @@
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/77/77/6671c0637457b48041711daf27da",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/18/82/776af0c81fb17839b7b8bc264012",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1c/cf/75b00bce2ce670a5c95af086d9a0",
- "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b3/d3/4c0fc4960a1fd06fc0f86f6d5777",
+ "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/8a/35/ff23ca37f42b0bfa6ca159630fe4",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/9b/5f/904c100c7c5646c7331cb26b8db6",
- "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/86/4f/087dedb270ea874623e3da1a7c3e",
+ "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/89/9d/0aacb629f5dc8fd10ce55debbe79",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5c/ea/0f158f114b2b3d0a534aebfeaebf",
- "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ba/c2/b590f6860f465fa2a9803204124c",
+ "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f3/4c/06b71f58c5b03454b61360e8591b",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/72/4a/de64093c85f32f5dbba5389da90c",
- "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/73/4c/5aa3525b583998c2e0f4f8493c94",
+ "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/14/e0/9c9088bd9db01969bf1a1e838dda",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/7c/39/05b1d3873ca9f1d6a7b904732630",
- "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a0/28/15fff103cb8ee86ce62c9d09c12c",
- "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/fb/bc/0279767aab40958a8912d18d924b",
- "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/60/8b/9bd45d3d3ecb9430d9f4e54f061c",
- "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/ad/13/a9aa8f24b210a75ee22f4db0c386",
+ "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/1c/cb/2a1576774e2ac14fed571d1d3232",
+ "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/df/0a/0284198f2802439349515c8b83f2",
+ "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/63/66/c6fa125299b8dc26887a0e5c5f58",
+ "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/01/dd/d5d189b16974b6314ba76584b7b2",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/95/cf/7c343cd320548f535b75b5993275",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a5/ee/8c89b68c2b26464768335e4c3361",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/18/93/76a49888f17ea1677b9b49244416",
@@ -4028,14 +4031,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ae/bb/4a015a49120e908a6d17f302d0d8",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e2/ff/1b0c530cbba73a0ea895a56626b6",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9c/8e/53fdfaf4f5113970e2aefcb6a06e",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/91/30/b88dfadbd2c03ee3324ee331120c",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/6a/5f/d9c21a29c24bae4fe234eec09981",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/4a/1c/df6e06fdf2028fa206c7dce2e405",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/8f/b9/054894bdc040b2b2013c1cbc31ab",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/e3/d6/6724c587d81bfd4ebbea313a5388",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/e4/6b/7ddca5ca6ba5ac1a59c7e193ceb5",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/53/ac/0f8c81b9f6ee4d2006bd3096b355",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/57/56/31132df71eecafd491785a791d88",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/70/5a/bab38dcc254aeba112894ee278cd",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/ac/31/ce9ba1b80db55b753626d3053898",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/32/5e/3c919d17f772a5bd1192a9ac3eda",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/28/2b/9b48b6805ee243f2813d5f0359e8",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/bd/2a/8627c6f6938bc46a4fca7a033ab3",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/54/63/15a0d31548d76237c65529d3bf99",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/2d/d4/e7fb6077712e4267a4d64529e005",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/55/44/83e93c9d77ffd2589e7a8795b212",
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/6e/6f/004b696e9a13b083069374e4bb6a",
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/d3/db/e73d4dcf1280d5f677c3cf8b47c3"
}
\ No newline at end of file
diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml
index fdd708f3..8c6e8d2d 100644
--- a/.idea/dictionaries/ericf.xml
+++ b/.idea/dictionaries/ericf.xml
@@ -1633,6 +1633,7 @@
nfoo
nilly
ninjafight
+ ninjafightplug
nitpicky
nline
nlines
@@ -1707,6 +1708,7 @@
onscreencountdown
onscreenkeyboard
onscreentimer
+ onslaughtplug
opcode
opdir
opendiff
@@ -1917,6 +1919,7 @@
profilename
profilenames
proj
+ projbasename
projconfig
projdir
projectpath
@@ -2123,6 +2126,7 @@
rtxt
rtypes
rtypevar
+ runaroundplug
runmypy
runonly
runpy
diff --git a/assets/.asset_manifest_private.json b/assets/.asset_manifest_private.json
index 67e7d62e..64a81070 100644
--- a/assets/.asset_manifest_private.json
+++ b/assets/.asset_manifest_private.json
@@ -6322,5 +6322,11 @@
"windows/x64/ucrtbased.dll",
"windows/x64/vc_redist.x64.exe",
"windows/x64/vcruntime140_1d.dll",
- "windows/x64/vcruntime140d.dll"
+ "windows/x64/vcruntime140d.dll",
+ "workspace/__pycache__/ninjafightplug.cpython-310.opt-1.pyc",
+ "workspace/__pycache__/onslaughtplug.cpython-310.opt-1.pyc",
+ "workspace/__pycache__/runaroundplug.cpython-310.opt-1.pyc",
+ "workspace/ninjafightplug.py",
+ "workspace/onslaughtplug.py",
+ "workspace/runaroundplug.py"
]
\ No newline at end of file
diff --git a/assets/Makefile b/assets/Makefile
index b24095fd..bda34d3f 100644
--- a/assets/Makefile
+++ b/assets/Makefile
@@ -2548,7 +2548,10 @@ SCRIPT_TARGETS_PY_PRIVATE_COMMON = \
build/ba_data/python-site-packages/yaml/resolver.py \
build/ba_data/python-site-packages/yaml/scanner.py \
build/ba_data/python-site-packages/yaml/serializer.py \
- build/ba_data/python-site-packages/yaml/tokens.py
+ build/ba_data/python-site-packages/yaml/tokens.py \
+ build/workspace/ninjafightplug.py \
+ build/workspace/onslaughtplug.py \
+ build/workspace/runaroundplug.py
SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \
build/ba_data/python-site-packages/_yaml/__pycache__/__init__.cpython-310.opt-1.pyc \
@@ -2572,7 +2575,10 @@ SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \
build/ba_data/python-site-packages/yaml/__pycache__/resolver.cpython-310.opt-1.pyc \
build/ba_data/python-site-packages/yaml/__pycache__/scanner.cpython-310.opt-1.pyc \
build/ba_data/python-site-packages/yaml/__pycache__/serializer.cpython-310.opt-1.pyc \
- build/ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-310.opt-1.pyc
+ build/ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-310.opt-1.pyc \
+ build/workspace/__pycache__/ninjafightplug.cpython-310.opt-1.pyc \
+ build/workspace/__pycache__/onslaughtplug.cpython-310.opt-1.pyc \
+ build/workspace/__pycache__/runaroundplug.cpython-310.opt-1.pyc
# Rule to copy src asset scripts to dst.
# (and make non-writable so I'm less likely to accidentally edit them there)
diff --git a/assets/src/ba_data/python/ba/_campaign.py b/assets/src/ba_data/python/ba/_campaign.py
index 9a55282a..4b79c66a 100644
--- a/assets/src/ba_data/python/ba/_campaign.py
+++ b/assets/src/ba_data/python/ba/_campaign.py
@@ -49,12 +49,15 @@ class Campaign:
"""Whether this Campaign's levels must be played in sequence."""
return self._sequential
- def addlevel(self, level: ba.Level, index: int = -1) -> None:
+ def addlevel(self, level: ba.Level, index: int | None = None) -> None:
"""Adds a ba.Level to the Campaign."""
if level.campaign is not None:
raise RuntimeError('Level already belongs to a campaign.')
level.set_campaign(self, len(self._levels))
- self._levels.insert(index, level)
+ if index is None:
+ self._levels.append(level)
+ else:
+ self._levels.insert(index, level)
@property
def levels(self) -> list[ba.Level]:
diff --git a/assets/src/ba_data/python/bastd/game/onslaught.py b/assets/src/ba_data/python/bastd/game/onslaught.py
index dc6595a1..c3d51898 100644
--- a/assets/src/ba_data/python/bastd/game/onslaught.py
+++ b/assets/src/ba_data/python/bastd/game/onslaught.py
@@ -5,6 +5,9 @@
# Yes this is a long one..
# pylint: disable=too-many-lines
+# ba_meta require api 7
+# (see https://ballistica.net/wiki/meta-tag-system)
+
from __future__ import annotations
import math
diff --git a/assets/src/ba_data/python/bastd/game/runaround.py b/assets/src/ba_data/python/bastd/game/runaround.py
index da4d15b4..b80f3ece 100644
--- a/assets/src/ba_data/python/bastd/game/runaround.py
+++ b/assets/src/ba_data/python/bastd/game/runaround.py
@@ -5,6 +5,9 @@
# We wear the cone of shame.
# pylint: disable=too-many-lines
+# ba_meta require api 7
+# (see https://ballistica.net/wiki/meta-tag-system)
+
from __future__ import annotations
import random
diff --git a/ballisticacore-cmake/.idea/dictionaries/ericf.xml b/ballisticacore-cmake/.idea/dictionaries/ericf.xml
index 041f5d77..6afde94e 100644
--- a/ballisticacore-cmake/.idea/dictionaries/ericf.xml
+++ b/ballisticacore-cmake/.idea/dictionaries/ericf.xml
@@ -828,6 +828,7 @@
newnode
newtoken
nextchar
+ ninjafightplug
nitpicky
nlpos
nmemb
@@ -875,6 +876,7 @@
oldbook
oldname
oldtoken
+ onslaughtplug
oooo
ooooooo
ooooooooo
@@ -975,6 +977,7 @@
profilers
prog
proj
+ projbasename
projdir
projpath
projprefix
@@ -1090,6 +1093,7 @@
rtest
rtypes
rtypevar
+ runaroundplug
runnables
runseconds
rvec
diff --git a/config/config.json b/config/config.json
index cf4bc493..5b6c3394 100644
--- a/config/config.json
+++ b/config/config.json
@@ -45,6 +45,7 @@
"python_source_dirs": [
"assets/src/ba_data/python",
"assets/src/server",
+ "assets/src/workspace",
"src/meta",
"tools",
"tests"
diff --git a/tools/efrotools/pcommand.py b/tools/efrotools/pcommand.py
index e8400b3d..a9477f73 100644
--- a/tools/efrotools/pcommand.py
+++ b/tools/efrotools/pcommand.py
@@ -509,7 +509,7 @@ def sync_all() -> None:
def _format_project(fproject: str) -> None:
fcmd = f'cd "{fproject}" && make format'
- print(fcmd)
+ # print(fcmd)
subprocess.run(fcmd, shell=True, check=True)
# No matter what we're doing (even if just listing), run formatting
@@ -532,15 +532,14 @@ def sync_all() -> None:
# Real mode
for i in range(2):
if i == 0:
- print(Clr.BLD + 'Running sync pass 1:'
- ' (ensures all changes at dsts are pushed to src)' +
- Clr.RST)
+ print(f'{Clr.BLD}Running sync pass 1'
+ f' (ensures all changes at dsts are pushed to src):'
+ f'{Clr.RST}')
else:
- print(Clr.BLD + 'Running sync pass 2:'
- ' (ensures latest src is pulled to all dsts)' + Clr.RST)
+ print(f'{Clr.BLD}Running sync pass 2'
+ f' (ensures latest src is pulled to all dsts):{Clr.RST}')
for project in projects_str.split(':'):
cmd = f'cd "{project}" && make sync-full'
- print(cmd)
subprocess.run(cmd, shell=True, check=True)
print(Clr.BLD + 'Sync-all successful!' + Clr.RST)
diff --git a/tools/efrotools/sync.py b/tools/efrotools/sync.py
index 55d277db..cb532378 100644
--- a/tools/efrotools/sync.py
+++ b/tools/efrotools/sync.py
@@ -59,8 +59,11 @@ def run_standard_syncs(projectroot: Path, mode: Mode,
Syncitems should be a list of tuples consisting of a src project name,
a src subpath, and optionally a dst subpath (src will be used by default).
"""
+ # pylint: disable=too-many-locals
from efrotools import getlocalconfig
localconfig = getlocalconfig(projectroot)
+ total_count = 0
+ verbose = False
for syncitem in syncitems:
assert isinstance(syncitem, SyncItem)
src_project = syncitem.src_project_id
@@ -69,9 +72,12 @@ def run_standard_syncs(projectroot: Path, mode: Mode,
if syncitem.dst_path is not None else syncitem.src_path)
dstname = os.path.basename(dst_subpath)
if mode == Mode.CHECK:
- print(f'Checking sync target {dstname}...')
+ if verbose:
+ print(f'Checking sync target {dstname}...')
count = check_path(Path(dst_subpath))
- print(f'Sync check passed for {count} items.')
+ total_count += count
+ if verbose:
+ print(f'Sync check passed for {count} items.')
else:
link_entry = f'linked_{src_project}'
@@ -80,12 +86,21 @@ def run_standard_syncs(projectroot: Path, mode: Mode,
print(f'No link entry for {src_project}; skipping sync entry.')
continue
src = Path(localconfig[link_entry], src_subpath)
- print(f'Processing {dstname} in {mode.name} mode...')
+ if verbose:
+ print(f'Processing {dstname} in {mode.name} mode...')
count = sync_paths(src_project, src, Path(dst_subpath), mode)
- if mode in [Mode.LIST, Mode.CHECK]:
- print(f'Scanned {count} items.')
- else:
- print(f'Sync successful for {count} items.')
+ total_count += count
+ if verbose:
+ if mode in [Mode.LIST, Mode.CHECK]:
+ print(f'Scanned {count} items.')
+ else:
+ print(f'Sync successful for {count} items.')
+
+ projbasename = os.path.basename(projectroot)
+ if mode in [Mode.LIST, Mode.CHECK]:
+ print(f'Checked {total_count} synced items in {projbasename}.')
+ else:
+ print(f'Synced {total_count} items in {projbasename}.')
def sync_paths(src_proj: str, src: Path, dst: Path, mode: Mode) -> int: