Combine Workshop addon and fix prison startup

Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
This commit is contained in:
2026-09-20 16:42:52 +02:00
parent 7d94953b53
commit cab998fb64
513 changed files with 18940 additions and 862 deletions
+13 -12
View File
@@ -129,7 +129,7 @@ def packed_request(a):
def prepare_packed(packed):
"""Called only while holding the ordinary runner's existing prefix lock."""
if packed.get('schema_version') == 3:
if packed.get('schema_version') == 4:
from packed_external import prepare
return prepare(packed)
packed['session'].mkdir(exist_ok=False)
@@ -148,7 +148,7 @@ def prepare_packed(packed):
def packed_snapshot(packed, command, profile):
if packed.get('schema_version') == 3:
if packed.get('schema_version') == 4:
from packed_external import snapshot
return snapshot(packed, command, profile)
project = packed.get('project', 'core')
@@ -169,7 +169,7 @@ def packed_snapshot(packed, command, profile):
def packed_seal(packed, raw, session):
"""Fail closed on changed/deleted inputs, retaining a useful failure record."""
if packed.get('schema_version') == 3:
if packed.get('schema_version') == 4:
from packed_external import seal
return seal(packed, raw, session)
metadata = json.loads(raw)
@@ -201,7 +201,7 @@ def native_path(value, game_root):
def packed_evidence(content, packed, steam, profile):
if packed.get('schema_version') == 3:
if packed.get('schema_version') == 4:
from packed_external import evidence
return evidence(content, packed, steam, profile, sys.modules[__name__])
project = packed.get('project', 'core')
@@ -379,9 +379,9 @@ def command_for(root, steam, compat, profile, project, packed=None, capture_pris
if project != packed.get('project', 'core') or project not in {'core', 'chat'}:
refuse('Packed input project does not match requested ordinary scenario')
addon_root = packed['input'] if project == 'chat' else packed['input'].parent
command += ['-addonsDir', 'Z:'+str(addon_root), '-addons', PACKED_PROJECTS[project][1]]
command += ['-addonsDir', 'Z:'+str(addon_root), '-addons', ('2528466DE220D91C' if packed.get('schema_version') == 4 else PACKED_PROJECTS[project][1])]
elif project != CONTROL:
project_text = (root/'addons'/project/'addon.gproj').read_text()
project_text = (root/'addons/core/addon.gproj').read_text()
guid = re.search(r'\bGUID "([A-F0-9]{16})"', project_text)[1]
command += ['-addonsDir', 'Z:'+str(root/'addons'), '-addons', guid]
command += ['-profile', 'Z:'+str(profile)]
@@ -411,7 +411,7 @@ def vanilla_evidence(content):
allowed = {'5614BBCCBB55ED1C', '58D0FB3206B6F859'}
wrong_addons = bool(set(guids) - allowed)
base_only = bool(blocks) and set(guids) == allowed and not wrong_addons
successor = any(token in content for token in ('ERR ORDINARY:', 'ERR SMOKE ', 'Rereintroduced [mission]'))
successor = any(token in content for token in ('ERR ORDINARY:', 'ERR SMOKE ')) or bool(re.search(r'Re(?:re)?introduced \[mission\]', content))
menu = "Entities load 'worlds/MainMenuWorld/MainMenuWorld.ent'" in content and 'Entered main menu.' in content
failed = bool(report['engine_errors'] or report['script_or_runtime_failures']) or bad_defines or wrong_addons or successor
return {**report, 'control_only': True, 'loaded_addon_guids': guids, 'vanilla_addons_only': base_only,
@@ -433,10 +433,11 @@ def game_evidence(content, project=None):
header_verified = bool(headers) and (project is None or project in headers)
participants = re.findall(r'ERR ORDINARY: local participant verified project=(core|chat) phase=prison', content)
participant_verified = bool(participants) and (project is None or project in participants)
ready = header_verified and participant_verified and 'Rereintroduced [mission]: phase 0 -> 1' in content
# Accept the historical spelling when reviewing immutable older evidence.
ready = header_verified and participant_verified and bool(re.search(r'Re(?:re)?introduced \[mission\]: phase 0 -> 1', content))
unexpected_fixture = 'ERR SMOKE ' in content
failed = (bool(report['engine_errors'] or report['script_or_runtime_failures'])
or 'Rereintroduced: scenario preparation failed' in content
or bool(re.search(r'Re(?:re)?introduced: scenario preparation failed', content))
or 'Can\'t compile "Game"' in content or unexpected_fixture
or any({'WORKBENCH', 'ENF_WB'}.intersection(value.split(',')) for value in defines))
return {**report, 'local_participant_verified': participant_verified, 'scenario_header_verified': header_verified, 'verified_header_projects': headers, 'game_module_defines': defines, 'workbench_undefined': non_workbench,
@@ -1297,7 +1298,7 @@ def run_locked(a, steam, compat, profile, packed=None):
link = addons/'ArmaReforger'
if not link.exists() and not link.is_symlink():
link.symlink_to(vanilla, target_is_directory=True)
if packed and packed.get('schema_version') == 3:
if packed and packed.get('schema_version') == 4:
from packed_external import prepare_profile
prepare_profile(packed, steam, profile)
elif link.resolve() != vanilla.resolve() or any(x.name not in {'ArmaReforger', 'saves'} for x in addons.iterdir()) or any((addons/'saves').rglob('*.gproj')):
@@ -1469,8 +1470,8 @@ def main():
parser.add_argument('--project', choices=['core', 'chat', CONTROL], default='core')
packed_options = parser.add_mutually_exclusive_group()
packed_options.add_argument('--packed-core', type=Path, help='Unqualified Core candidate directory containing exactly addon.gproj, data.pak and resourceDatabase.rdb')
packed_options.add_argument('--packed-addons', type=Path, help='Unqualified complete core/ai/intel/map/chat packed directories; requires --project chat')
parser.add_argument('--external-addons', type=Path, help='Explicit DEVELOPMENT packed Chat v3 only: audited installed RHS/WCS/BMP root; six private links, no broad workshop mount')
packed_options.add_argument('--packed-addons', type=Path, help='Packed addon root; with --external-addons expects the single combined core folder (v4), otherwise historical five-addon v2; requires --project chat')
parser.add_argument('--external-addons', type=Path, help='Explicit DEVELOPMENT combined packed mod v4 only: audited installed RHS/WCS/BMP root; six private links, no broad workshop mount')
parser.add_argument('--packed-session', type=Path, help='New /tmp/erri-packed-core-<name> or erri-packed-chat-<name> session; owns a fresh input copy and profile')
parser.add_argument('--inspect-processes', action='store_true', help='Read-only process preflight report; never launch, lock, write a profile or configure audio')
parser.add_argument('--inspect-headless-display', action='store_true', help='Read-only ownership inspection within the hidden display; no input sent, loose Core/Chat only')