9.7 KiB
Explicit finite aircraft retention service
ERR_AircraftService is an unintegrated production candidate. It retains already existing physical aircraft and uses the existing bridge-backed route controller. It creates no aircraft, pilots, seats, fuel, radio messages or scheduled work. It does not select targets or claim that an order was authorized by HQ. The 202253 native route now exercises service registration, one retained controller/token/deadline, destination hold, contact landing, engine shutdown and drained state:40 assertions, zero captured errors, unchanged197-file source and verified cleanup. The separate 202706 airborne Stop also passes42assertions with zero captured errors and verified cleanup: the same controller/token/deadline remains pending while actual callback counters/readback continue, then stable physical contact and engine shutdown precede CANCELLED/drained. No destination arrival is claimed for cancellation.
Owner contract and API
Create one service for the exact active server ERR_GameMode, and retain that service for the round. Register(aircraft, originalGroup, originalPilot, originalSeat) accepts at most four unique tuples. The airframe, pilot and group must belong to the current world/enemy faction; the exact conscious AI pilot must physically occupy the controller's active pilot seat; no player may occupy the aircraft or control the group. Current fuel, damage, rotor, engine-off, awake dynamic physics and actual native ground contact must pass. The service neither wakes a sleeping vehicle nor changes its physics to satisfy these checks.
Each group, pilot and seat can appear only once in a service. A separate weak service-retention registry prevents two services from registering the same physical airframe simultaneously. This reservation does not claim an envelope or the flight controller's registry. The existing controller remains the final arbiter of flight ownership if a different owner has already started it.
StartRoute(aircraft, qualification, positiveToken, absoluteDeadline) requires a registered, currently ready original asset and a caller-supplied ERR_AircraftRouteEnvelope. The controller performs the existing single qualification claim; the service never calls Claim or constructs a substitute qualification. The original 18–20.05 m range, terrain/clearance checks, finite fuel, native callback proof, flight bounds and deadline limits are unchanged.
StartField(aircraft, qualification, positiveToken, absoluteDeadline) is a separate, unqualified prototype entry point accepting only ERR_AircraftFieldEnvelope. It constructs only ERR_AircraftFieldFlight, retaining it through the common ERR_AircraftFlight base. No caller-supplied controller is accepted. The existing StartRoute still constructs its exact original route class and preserves its admission and failure behavior. Neither entry point is connected to HQ or ordinary scenario activation here.
Both kinds share the same four-asset reservation limit, 128-attempt history, BeginAttempt bookkeeping and start-result handling. A token attempted through one kind cannot be replayed through the other, including on a different aircraft. A pending or retired asset cannot switch kinds to bypass its state. Each controller alone validates and claims its typed certificate. Field-specific refusal, including its stricter lease or 50-native-unit fuel admission, retires the attempted asset and burns the recorded token just like a route-controller refusal; it does not trigger a fallback controller or retry. Basic null-certificate/common-admission refusals still consume no attempt.
The field controller's 100 m geometry, candidate PI/braking response, initial fuel quantity and 20-unit low-fuel abort reserve remain unqualified physical behavior. These quantities are not a demonstrated range model or an asserted unit of litres. The prior twenty-metre native archives above do not qualify this typed-service change or a field flight. See the field plan. The allocating owner still must retain and tick the service until terminal; common-base storage does not weaken that requirement.
An accepted start attempt records its immutable token, absolute deadline and destination before calling the controller. Attempted tokens cannot be reused on any aircraft in that service, even after successful completion or a native start refusal. History is bounded to 128 attempts per service/round; exhaustion refuses additional work without dropping replay protection. Basic refusals before a ready, valid-deadline attempt consume no token. The future HQ owner must issue globally unique order tokens and must not reconstruct services to replay an old order.
If controller startup refuses after the attempt is recorded, that asset is conservatively retired for the service's lifetime. This includes a stale/already-used qualification or an external flight conflict. The service does not automatically retry, replace the pilot or mint a second order. An unexpected refusal after a nonterminal lease was established retains that flight and requests cancellation until its terminal result can be observed.
Cancel(aircraft, exactCurrentToken, reason) rejects foreign, completed and duplicate cancellations. It retains the same flight, order and original absolute deadline. The existing controller determines whether to stop on the ground, land while retaining airborne control, fail or relinquish captured ownership. The service continues to call that controller's Tick() until it finishes.
Stop() closes registration and order admission and requests cancellation of outstanding flights. The caller must retain the service and keep calling Tick() until Drained() is true. Repeated Stop does not renew a deadline or restart landing. During an active round the service keeps its asset reservations until all pending flights finish. Destruction is teardown, not proof of landing: it requests Stop and releases only its retention records; the existing flight destructor handles its control ownership, while all actual entities remain with their creating owner. Dropping an airborne service early does not produce a qualified safe landing.
Current mode/world loss causes retained controllers to observe their normal ownership loss and relinquish; it does not fabricate COMPLETE or CANCELLED. Normal scheduling must continue even when the server has no players. The existing Core ServerTick pauses before HQ ticking on an empty server, so simply adding this service to the present HQ Tick path would not satisfy this contract. No Core/HQ scheduling change is included here.
Status and availability
RegisteredCount, AttemptedOrders, Stopping, Drained, Pending(aircraft), Retired(aircraft), OrderToken, OrderDeadline, Destination, FlightState and Reason return observations without exposing a mutable entry or flight reference. FlightState is -1 before any attempt. Reason is diagnostic text, not a delivery receipt or an availability guarantee.
Ready(aircraft) always checks current original ownership and physical health, seat, fuel, rotor, engine and ground conditions. A historical COMPLETE/CANCELLED result alone never marks an asset ready. FAILED/RELINQUISHED outcomes and observed ownership changes retire the entry permanently. A successful returned aircraft may accept a fresh token and freshly qualified route only while those physical checks pass. No refueling, repair or automatic re-adoption is performed.
Retired entries continue to count toward the four registered assets. The service provides no unregister/replacement escape hatch that could silently expand the original finite fleet. Once Stop has drained, its service-retention records are released; the stopped service remains unable to accept new work.
Verification and next integration
python tests/test_aircraft_service.py executes the actual service context, registration, readiness gate, start, cancellation, Tick, Stop and observation methods with fake physical/controller boundaries. It checks the four-asset limit, cross-service conflicts, duplicate tuple members, immutable tokens/destination/deadline, one delegated claim, repeated cancellation, retained airborne work, final physical readiness, capture/terminal retirement, partial-start failure and the 128-attempt replay bound. The typed integration adds actual-method checks for known controller construction, cross-kind token replay refusal, mixed-kind attempt-budget exhaustion, field partial-start failures, and retained cancellation/Stop across both kinds. The WORKBENCH route observer casts the retained base reference back to its exact route subtype and returns null for a field flight, preventing route evidence from being relabeled. The test also checks the actual native-readiness call sites and absence of spawning, deletion, physics/input writes and scheduling. These checks are not native flight or multiplayer evidence.
The bounded native normal-route follow-up now registers the fixture's one finite aircraft/pilot after its usual physical readiness gate, then runs the same qualified20m route through this service. The separate cancellation run keeps the service alive after Stop and verifies actual continued airborne callbacks, contact landing, unchanged token/deadline, and Drained only at completion. Test refusal and capture without claiming a successful return. Production HQ radio delivery, asset authoring, empty-server scheduling and useful field-length routes remain separate work.
The initial201812native service attempt failed compilation in four compact status getters. Local defaults with one unconditional final return corrected that native compiler limitation; the failed archive remains intact.