Files
EscapistsReintroduced/docs/medical-kit-teardown-ownership.md
jakub cab998fb64 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.
2026-09-20 16:42:52 +02:00

6.5 KiB

Medical-kit teardown ownership audit

No production cleanup is proposed yet: the two identified medical-kit instances have not been established as successor-owned scene stock. Deleting tracked stock to remove these errors would therefore be an unproven change with a risk of removing carried inventory.

Established evidence

  • docs/evidence/native-2026-09-19-050515/console.log.txt:620-621 identifies {AE578EEA4244D41F}Prefabs/Items/Equipment/Kits/MedicalKit_01/MedicalKit_01_US.et and {21EF98BFC1EB3793}Prefabs/Items/Equipment/Kits/MedicalKit_01/MedicalKit_01_USSR.et. Both have unnamed owners, valid cached/global catalog references, and no current GameMode at that teardown point. This session did not reproduce a missing-manager error.
  • Current addons/core/Configs/ERR/EveronSites.conf stocks field dressings, saline and morphine; neither diagnostic medical-kit resource appears in any successor addon source/resource. The prisoner loadout also does not explicitly add these kits.
  • Both kit prefabs remain in the installed vanilla US/USSR inventory catalogs (InventoryItems_EntityCatalog_US.conf:1290, USSR :1002). Preserving complete medical/inventory support is intentional. Catalog membership is not proof that the deleting entity is a world instance owned by the successor.
  • Installed SCR_EntityCatalogEntry.ClassSpecificInit and SCR_EntityCatalogInventoryItem.ClassSpecificInit call Resource.Load and inspect entity/component sources. These inspected methods do not call SpawnEntityPrefab or register entities with successor ownership. Resource/template cleanup or another native subsystem is a possibility, not a proven cause.
  • Installed SCR_BaseItemSupportStationComponent.DelayedInit caches the global catalog manager and calls super. Its InitValidSetup prints the stale-named resupply error if that reference is absent.
  • Installed SCR_BaseSupportStationComponent.OnDelete invokes virtual InitValidSetup before unsubscribing damage/support dependencies. Its EOnInit queues DelayedInit and OnDelete does not explicitly remove that callback. Both dependency teardown order and initialization/delete ordering remain relevant hypotheses.

Why blanket successor cleanup is unsafe

ERR_SiteService.m_Entities contains sites, containers, stock, transport and extraction aircraft. Successful preparation also registers all those objects in GameMode ownership. The collection records creation ownership, not current inventory custody. A stock item remains listed after a player picks it up. ERR_Actors.DeleteSpawned(item) only refuses a directly controlled player entity; it does not protect an item merely because it is now in that player's inventory. Rollback() deletes this entire list in reverse order and would also remove the extraction aircraft. It must not be repurposed as normal endscreen cleanup.

The current Stop() intentionally stops updates without removing those physical objects. Ordinary victory preserves passengers, aircraft and result while the native endscreen exists. This is appropriate and should remain unchanged.

Exact possible pre-restart boundary

Installed SCR_BaseGameMode invokes RestartSession after GetAutoReloadDelay (lines 715-717), after its game-mode-end notification. protected void RestartSession() (line 781) checks authority, invokes TryShutdownServer, then calls GameStateTransitions.RequestScenarioRestart() (line 789). A successor-only override could perform bounded owned-item disposal immediately before calling unchanged super, while the old world's manager still exists. This would happen after the endscreen delay, not on victory.

That hook is only justified as the error fix if the deleting station is proven to be one of the owned objects, and every relevant restart route uses this method. Direct scenario-restart requests or shutdown/Workbench play termination are separate lifecycle paths. A generic component destructor is already too late to guarantee catalog manager lifetime.

If ownership is established, the narrow implementation should track spawned stock items separately from sites/vehicles, establish current custody before deletion, and remove only items still in their owned site storage or unclaimed world stock. Never traverse/delete a player body, reconnection-reserved body, aircraft/passenger hierarchy or other subsystem's catalog prototype. Only release bookkeeping for taken or already-deleted stock. Call item deletion while the required manager exists; retain vanilla OnDelete and its errors. Verify idempotence and delete ordering with actual named instances. Do not claim kit errors fixed until the exact observed owners are handled and raw two-round logs demonstrate it.

Isolated diagnostic extension

The only code change in this handoff is addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c, extending the existing WORKBENCH-only opt-in diagnostic. Use existing --station-teardown-diagnostics / -errStationTeardownDiag 1 activation. It still invokes unchanged super in DelayedInit, OnDelete and InitValidSetup, and leaves all native errors visible.

At native DelayedInit it captures scalar/string evidence: whether initialization was observed, successor mode present, owner world equals the current game world, whether the site service knows that exact owner, inventory-slot presence, and parent prefab. It prints at most 64 initialization records. Teardown's existing maximum 64 records gain those initial facts plus current world/site/inventory/parent observations. It stores no new entity/manager references and schedules no work. initSiteOwned=false alone does not prove permanent nonownership; an item could be adopted later. Likewise absence of GameMode at delete makes current ownership unavailable, so the initialization and world evidence must be interpreted together.

Suggested run: ordinary two-round Core scenario with retained vanilla inventory catalogs and the existing diagnostic flag. Correlate kit resource names and init/delete records, then repeat with physical medical treatment and representative looting. Determine whether the kit owner is in the main world and ever successor-owned before proposing its removal. Also retain the raw catalog-manager error count. No completed-smoke marker is added and no runner qualification is changed.

No engine run, original workspace edit, installed resource change or production deletion was performed for this audit. The diagnostic extension is source-reviewed and awaiting native compilation. Existing source-hash evidence for the base lifecycle remains in docs/evidence/native-error-audit-2026-09-19/source-hashes.json.