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.
139 lines
9.6 KiB
Markdown
139 lines
9.6 KiB
Markdown
# Native shared-map replacement fixture
|
|
|
|
`addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c` is entirely
|
|
`WORKBENCH` guarded and inert unless `-errSmoke 1 -errSmokeOutcome map-ownership`
|
|
selects it. It does not change production map code, inventory, player state or
|
|
settings. The first native execution compiled and passed both replacement/callback
|
|
sequences but failed its immediate deletion assertion. It remains a failed run;
|
|
the revised bounded deletion observation passed in native run 12:06:33. Offline regressions are
|
|
not native rendering or multiplayer evidence.
|
|
|
|
Chat smoke integration: after the real local player and map entity initialize,
|
|
retain `ref ERRM_NativeMapOwnershipProbe`, create it without constructor arguments,
|
|
and call `Tick(GetWorld().GetWorldTime())` on the existing smoke cadence. Return
|
|
`0` means pending, `-1` failed, `1` complete with owned cleanup finished. Call
|
|
`Stop()` during smoke teardown and release the reference. The caller owns the
|
|
final smoke completion marker. Add the outcome to the Chat runner and the test
|
|
`tests/test_native_shared_map_ownership.py` to the repository check list. The
|
|
fixture's own deadline is 15 seconds after first tick; normal stages take about
|
|
9 seconds with a 500 ms caller cadence, with at most three seconds allowed for
|
|
native deletion before the final 1.5 second callback window.
|
|
|
|
The fixture refuses an already-open map or a current camera other than the
|
|
actual local player's camera. It spawns two real successor map prefabs next to
|
|
that player, without inserting them into anyone's inventory. Their real
|
|
components initialize their own render roots. A third hidden root is used for
|
|
the replacement view. All native map opens/closes target these verified roots;
|
|
no menu is opened and no synthetic map component replaces the actual prefab.
|
|
|
|
First, the production capture method opens the owned root. The fixture closes
|
|
only that verified view and opens a distinct native `MapConfiguration` pointing
|
|
to the hidden replacement root. The distinct config copies the native plain
|
|
config's fields, retaining the same settings/module references; it does not edit
|
|
the resource or invoke fullscreen-specific UI modules. The second pass calls
|
|
native `SetupMapConfig(PLAIN, ..., replacementRoot)` and requires that vanilla
|
|
reuse the **same config object** while changing its root. This is the ownership
|
|
case that a config-pointer-only check misses.
|
|
|
|
For each pass the fixture waits for the actual native map-open-complete event.
|
|
It checks native current pan and target zoom around the real stale centering
|
|
method, then schedules the actual production center and finish callbacks through
|
|
`ScriptCallQueue`. WORKBENCH adapters count their execution and always call
|
|
`super`; the fixture fails if either callback never ran or ran twice. Native
|
|
map-close events, active config/root, pan, zoom and successor completion calls
|
|
are checked after the callbacks. The ordinary production stop and real vanilla
|
|
`ModeClear(IN_HAND)` chain then run. Both actual map entities are deleted,
|
|
including the never-capturing spare, while the replacement remains open. Each
|
|
delete request is issued exactly once. The probe waits at most three seconds
|
|
for **all four** native entity/component references to become null, plus exactly
|
|
one observed `OnDelete` completion per tagged component **after** the complete
|
|
successor/vanilla `super.OnDelete(owner)` chain returns. The observer also checks
|
|
that production released its root, target, capture references and in-hand state;
|
|
it never clears those fields itself. Missing/duplicate callbacks, remaining
|
|
references or cleanup fields fail. A final 1.5 second observation period begins
|
|
only after this proof, rejecting late close/restore/completion callbacks.
|
|
Stop removes only this probe's subscriptions, entities and widgets, and closes
|
|
the native map only if its exact current config/root is still the replacement.
|
|
It does not restore or close an unrelated view that took over during a failure.
|
|
|
|
The original 100/500 ms capture callbacks are deliberately removed only on the
|
|
fixture-owned component and rescheduled at 100/200 ms **after** the replacement's
|
|
native initialization. This ensures a stale pan would affect a live map, rather
|
|
than passing because vanilla ignored a pan before initialization. Production
|
|
cadence outside these two owned prefabs is unchanged. The fixture invokes the
|
|
same stale camera-restore method explicitly, verifying that its authorization
|
|
rejects the replacement; it never intercepts or suppresses a native operation.
|
|
|
|
Camera evidence has a precise limit. Installed `PlayerController` exposes
|
|
`bool SetCharacterCameraRenderActive(bool active)` but no render-enabled getter;
|
|
`PlayerCamera`/`CameraBase` also provide no such getter. This fixture therefore
|
|
records successor restore-method calls and their exact ownership authorization,
|
|
and actual native map-close events. It does **not** claim a measured camera render
|
|
flag or visual screenshot. Native `OpenMap` and `CloseMap` retain their normal
|
|
camera behavior, and no guessed API or global camera override is introduced.
|
|
The ordinary actor's camera identity is checked, not its undocumented render
|
|
state. This remains a private diagnostic UI exercise, not human interaction or
|
|
remote/JIP qualification.
|
|
|
|
Installed-source audit (SHA-256 of the extracted read-only files):
|
|
|
|
| Source | Relevant behavior | SHA-256 |
|
|
| --- | --- | --- |
|
|
| `scripts/Game/Map/SCR_MapEntity.c` | `SetupMapConfig` reuses equal-mode config/root; `OpenMap`/`CloseMap` perform native camera changes; map-open-complete, pan/zoom and current-root APIs | `09ca0631ce2f5a196b7074e12a67c08255b7119b9600da635894097b35e4ad92` |
|
|
| `scripts/Game/Components/Gadgets/SCR_MapGadgetComponent.c` | no deletion override; `ModeClear` only unfocuses an in-hand map belonging to the local actor when actually focused | `3bfc0b6715a173654a3f9ecc5a4538be508905eb9d50aef82cb80262950fec9e` |
|
|
| `scripts/Game/Components/Gadgets/SCR_GadgetComponent.c` | `OnDelete` disconnects from gadget system then delegates; ordinary `ModeClear` only removes its own loadout subscription | `015c18b4c94245e72c923e718b74cf933cd516c0a9dc24946735482c2e4e191b` |
|
|
| `scripts/Game/generated/Player/PlayerController.c` | native camera-render setter without getter | `832c5925edbd41e05c469803abdea3b202c1de58d58251d77a8a7e136bdb7edc` |
|
|
| `scripts/GameCode/Map/MapConfiguration.c` | exact fields used by the distinct plain-config copy | `4ceb904d36c7e466ed5e02e7d72fe24944fb6dd4f7cae07809a2428fdf4d234e` |
|
|
|
|
An unused/spare map has no vanilla character owner or focused state, so its real
|
|
superclass cleanup cannot schedule native `ToggleMapGadget(false)`. A previously
|
|
focused stock map has a separate native delayed focus/menu path and is outside
|
|
this fixture's claim. The tests execute the actual fixture cleanup and evidence
|
|
decisions against explicit API doubles, including foreign config/root, changed
|
|
singleton, duplicate cleanup, unrelated observer ownership, missing callbacks,
|
|
changed pan and close/reopen rejection.
|
|
|
|
## First deletion observation and bounded follow-up
|
|
|
|
[Native run 2026-09-19 11:56:46](evidence/native-2026-09-19-115646-map-deletion-refusal/console.log.txt)
|
|
passed both actual map replacement sequences, native open-complete, delayed
|
|
callback execution, unchanged pan/zoom and actual stop/mode-clear checks. At
|
|
11:57:47.732 it failed immediately after requesting the two deletions, before
|
|
waiting a native frame. That record does not identify which reference remained
|
|
or whether either `OnDelete` had run, so deferred deletion is a hypothesis, not
|
|
a proven explanation or a reason to relabel the failed run.
|
|
|
|
Installed `scripts/Game/Helpers/SCR_EntityHelper.c:177` is only a wrapper for
|
|
`RplComponent.DeleteRplEntity(entity, false)`. The generated native contract
|
|
describes authority/proxy physical deletion, but promises no synchronous
|
|
reference invalidation before the method returns. Source SHA-256 values:
|
|
`31a7f7651237cd859400774fb6be62a0079f204e593831db55093ab59c69812c`
|
|
(helper) and
|
|
`0bdf89c3c65e23fa3cf1cab27f8899fd89f3c5fbb6e6c3431f5fdb007590f34c`
|
|
(`scripts/Game/generated/Components/RplComponent.c`). The revised probe logs
|
|
non-sensitive reference-presence booleans and callback counts at request return,
|
|
at actual post-super cleanup, and at later completion or timeout. These
|
|
observations distinguish delayed invalidation from incomplete cleanup without
|
|
manual reference clearing, repeated delete requests, weakened acceptance or
|
|
changing production deletion behavior. The offline regression now exercises
|
|
request-versus-completion separation, exact once-only requests, missing/duplicate
|
|
post-super evidence and retained component references.
|
|
|
|
## Native deletion diagnosis and scoped pass
|
|
|
|
[Native run 2026-09-19 12:06:33](evidence/native-2026-09-19-120633-map-ownership/console.log.txt)
|
|
passed the complete fixture. At 12:07:34.567 both tagged components reported
|
|
`OnDelete` **after super** with `released=1`, one callback each; both entity
|
|
references were already null, but both component references still existed. At
|
|
12:07:35.069 the next probe tick found all four references null, with no duplicate
|
|
callbacks or leftover production state. The unchanged 1.5 second observation
|
|
window passed at 12:07:36.582. This establishes delayed component-reference
|
|
invalidation as the cause of the original same-stack assertion failure; actual
|
|
superclass cleanup was already synchronous in this observed run.
|
|
|
|
This evidence covers the two real replacement/config-root cases, real queued
|
|
callbacks and native prefab deletion in the isolated local Workbench runtime.
|
|
It does not establish a measured camera render flag, remote/JIP behavior, a
|
|
previously focused native map's unrelated menu callbacks, or performance. The
|
|
11:56:46 attempt remains recorded as failed.
|