Files
EscapistsReintroduced/docs/shared-map-ownership.md
T

20 lines
3.9 KiB
Markdown

# Shared field-map capture ownership
`ERRM_SharedMapComponent` briefly uses the native map renderer to capture the held item's surface, then freezes its own render target and delegates the normal local map behavior to `SCR_MapGadgetComponent`. It uses the existing map singleton; it does not own every later view displayed by that singleton.
The earlier boolean-only ownership check allowed a delayed pan/close callback to act on a replacement fullscreen or auxiliary map. It also restored the local character camera whenever any shared-map item was deleted, even if that spare or remote item had never captured anything. This conflicts with the camera suppression performed by a native fullscreen map.
The component now retains its exact `MapConfiguration` and requires all of the following before panning, closing, or restoring the character camera: its capture flag, the same current map singleton, an open native map, the exact configuration object, and the configuration's original root widget. Both configuration and root identity matter: installed `SCR_MapEntity.SetupMapConfig` reuses its active configuration when the requested mode is unchanged and mutates `RootWidgetRef`. A pointer-only test would still permit one same-mode capture to interfere with another.
Interrupted or completed capture disables only its own render target and clears its ownership before closing the native map. `CloseMap` already restores the character camera; Stop and deletion no longer perform an additional unconditional camera write. A stale Finish callback whose view has been replaced cannot close, pan or focus the replacement. It uses the existing retry path while the item remains in hand, waiting for that view to close before attempting its own capture again. Stop removes this component's three delayed callbacks, clears holder/map/config references, and freezes its target. Widget destruction remains separate from passing a deleted entity to the renderer.
Installed primary source references (read-only inspection):
- `scripts/Game/Map/SCR_MapEntity.c`: `GetMapConfig` returns `m_ActiveMapCfg`; `OpenMap` closes any prior view and assigns the new config/root, then suppresses the local character camera; `CloseMap` restores it; `SetupMapConfig` can reuse and retarget the same config object.
- `scripts/Game/Components/Gadgets/SCR_MapGadgetComponent.c`: stock `ModeSwitch` limits local focus/camera UI to the local controlled character. Its focus path schedules native map opening and fading, so it must not be triggered immediately by a stale capture callback against a replacement UI.
- `scripts/Game/Components/Gadgets/SCR_GadgetManagerComponent.c`: default gadget-state invokers exist for remote as well as local characters. `RegisterInitialGadgets` reapplies an already replicated gadget mode; this audit therefore does not claim that vanilla's JIP path omits mode initialization.
The meaningful offline regression `tests/test_shared_map_ownership.py` executes the actual ownership, release, finish, camera, stop and deletion methods with explicit native-boundary doubles. It covers distinct replacement configurations, same-object/different-root reuse, another current world/map singleton, never-owned deletion, delayed duplicate callbacks, the deferred-focus path, cancellation of this instance's callbacks while another instance's callback remains, and a missing game context during teardown. The test does not compile Enforce, render a texture or establish multi-client/JIP behavior. Native UI replacement, physical-surface visibility and remote streaming still require runtime validation.
This patch changes no discovery knowledge, marker lists, setting semantics, network serialization, shared-map resource identity or production player camera policy. Core discovery remains a separate owner. Its current production knowledge transitions are monotonic and the current settings catalog has no shared-map enable/disable switch; no hypothetical downgrade or disabled-setting defect was inferred here.