Files
EscapistsReintroduced/docs/evidence/hunter-capture-2026-10-02/sdk-review/review.json
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

85 lines
8.4 KiB
JSON

{
"verdict": "Source/API design is feasible with explicit pre-cleanup capture latch and authoritative current-owner guards; implementation and native remote callback timing not qualified.",
"scope": "Read-only SDK/current-source review of proposed original-hunter entry-event migration. No native, target or original writes; no tests executed.",
"proposal": "/tmp/erri-next-gameplay-2156/proposal.json",
"native_api": [
{
"path": "/tmp/erri-vanilla-stock/scripts/Game/generated/Components/CompartmentAccessComponent.c",
"line": 84,
"signature": "event protected void OnCompartmentEntered(IEntity targetEntity, BaseCompartmentManagerComponent manager, int mgrID, int slotID, bool move);",
"claim": "Declared native event. Match exact argument names in override; prior native compile demonstrated strict name matching."
},
{
"path": "/tmp/erri-vanilla-stock/scripts/Game/Vehicle/SCR_CompartmentAccessComponent.c",
"line": 64,
"claim": "Vanilla override first invokes generic compartment-enter listeners, then registers life-state listener and adjusts turret inputs, then checks PlayerManager.GetPlayerIdFromControlledEntity(character) before player-specific event. Call super exactly once for both ignored and handled events."
},
{
"path": "/tmp/erri-vanilla-stock/scripts/Game/generated/Network/PlayerManager.c",
"line": 45,
"claim": "GetPlayerControlledEntity(int), GetPlayerIdFromControlledEntity(IEntity), GetPlayerController(int) provide server-capable ownership checks. A server hook must not require local GetGame().GetPlayerController equality."
},
{
"path": "/tmp/erri-vanilla-stock/scripts/Game/Player/SCR_PlayerController.c",
"line": 224,
"claim": "OnControlledEntityChanged invokes its subscriber before character cache/settings changes. It is a distinct event from compartment entry; adoption of an already-seated body is not proven covered by a compartment-only hook."
}
],
"recommended_contract": [
"Use server-only pre-super compartment entry. Current mode must be active, equal ERR_GameMode.Get(), and own the exact current HQ and hunter service. Ignore missing game/manager/target/owner and stale service.",
"At event time require positive PlayerManager player id for exact component owner and reciprocal GetPlayerControlledEntity(id)==owner. This handles remote players without relying on listen-server local controller. Do not require consciousness; unconscious entry is still player capture. Roster-only gating would narrow predecessor semantics for player-controlled non-roster bodies and should be an explicit choice.",
"Match callback target to the exact already-tracked original hunter root through bounded ancestry (existing PartOf cap32), never vehicle prefab/nearby position/new current vehicle fallback. Do not discover/adopt new hunters. Parent scope: reject Released records; this is capture of active driving ownership, not later cleanup of independent infantry.",
"Set an irreversible capture fact before Recovery.Stop, native AI behavior completion, waypoint cleanup or super callback. Reentrant/duplicate events must observe latch and submit no repeated cleanup.",
"Both Hunter.Release branch selection and base convoy survivor-retention check must honor explicit capture fact: live compartment occupancy/group player count can still be false at this callback boundary. Retain entities, finite receipts and counts; do not refund or spawn.",
"Keep ordinary current-occupancy polling as fallback. No new timer/RPC is required for this bounded entry hook."
],
"concrete_review_edges": [
{
"source": "ERR_HunterService.c:29 and ERR_ConvoyService.c:230",
"risk": "Both Release methods return immediately once Released. A normally released hunter stays in m_Hunters, with surviving original group retained for HQ. A later first player capture can set a flag but fail to revoke that existing HQ registration unless handled explicitly. Specify active-only scope or provide exact once-only late capture cleanup; do not claim lifetime capture if skipping this case.",
"resolution": "Parent chose explicit active-only scope. Require already-Released control to prove no infantry ownership revocation; no lifetime removal claim for independently retained infantry."
},
{
"source": "ERR_HunterCrewRecovery.c:27 and ERR_HunterService.c:29",
"risk": "Recovery.Stop completes its own native boarding behavior before Hunter.Release sets Released. Latch capture before invoking it so reentrant callbacks cannot enter the same cleanup twice."
},
{
"source": "ERR_HQ.c:591 and ERR_ConvoyService.c:230",
"risk": "Latest ReleaseConvoySurvivors retains current radio/equipment/roster and deliberately retains unresolved logistics tokens. Capture must use existing unregister/release ownership semantics and must not manually release inventory reservations or reset finite stock."
},
{
"source": "SCR_CompartmentAccessComponent.c:64",
"risk": "Using only the vanilla player-specific invoker performs capture after earlier generic listeners. Pre-super override is the supported place to establish the fact before synchronous observers; preserve vanilla call regardless of ignored event."
}
],
"required_actual_method_controls": [
"server vs client, exact reciprocal owner vs stale/current replacement",
"current mode/HQ/service vs stopped or replaced",
"root and turret child vs unrelated/unknown/deep ancestry",
"capture before native occupancy visible, followed by player mapping disappearing",
"duplicate/reentrant entry cannot replay cleanup",
"normal loss still retains eligible original survivors; captured branch never adopts/refunds/deletes",
"already-Released record ignored without revoking independently retained on-foot infantry",
"super called once on every path"
],
"limits": [
"SDK declarations and predecessor source establish available hook and ordering, not that every remote server entry arrives before disconnect or native ownership changes. No multiplayer timing claim.",
"No native vehicle entry, physical capture, survivor delivery, controller-ownership handoff or reconnect experiment executed.",
"A compartment-only hook does not prove capture on possession of an already-seated AI; retain polling and avoid expanding scope without evidence."
],
"sha256": {
"/tmp/erri-vanilla-stock/scripts/Game/Vehicle/SCR_CompartmentAccessComponent.c": "55fc213f5136080dac12e916bb20b3a11913d3e2830b05f9669ba2447965d837",
"/tmp/erri-vanilla-stock/scripts/Game/generated/Components/CompartmentAccessComponent.c": "a3a0907d771293d2423649aa0ff0e71b7f457279defac05fd693baf4dd7c447e",
"/tmp/erri-vanilla-stock/scripts/Game/generated/Network/PlayerManager.c": "92c950e08e5a526427e55d5f25a895ff59ba534730d4c578ba4734fef0c7d793",
"/tmp/erri-vanilla-stock/scripts/Game/Player/SCR_PlayerController.c": "9df2c026b6eaf8c47a4af948d4322dbfc7d6a92ed1bd1b554b9577b033f89d59",
"/home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
"/home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
"/home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "0769d4e7327439ce91b8f9ed0b47c4d92d382e97a1bbf62da8e6002ae4041bf0",
"/home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
"/home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "825a35f7afe485c1e5ddfc96dfff3498b39cce54dc19dce857b5d30fe5dc6557",
"/home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "5d66c53baf8762e76ae59e28721edaa348014af6d988d42891d9a84a6cf44969",
"/home/jakub/devel/escapists/escapists-ai/Scripts/Game/EscapistsAI/EAI_ResponseSafety.c": "b3dcbe8f3dd840791e91e9ec202cd392ebc4895714816cdcedcdc591baa62b05"
},
"scope_decision_from_parent": "Event capture applies only to active tracked hunters. Ignore already-Released records: they have no driving ownership and cannot re-adopt, and independently retained on-foot infantry are not revoked for later entry into their former parked vehicle."
}