Skip to content

Public service contract catalogue

The per-method machine authority is sdk/contracts/. It lives with SDK metadata rather than site content so downstream consumers share one versioned format. This document’s method cells are checked against those records: update both together; CI refuses disagreement. Common reading rules, per-service narrative and remaining gaps stay authoritative here and are carried into the built catalogue, not copied into another editable prose source.

Terminal window
python3 tools/sdk_catalogue.py check
python3 tools/sdk_catalogue.py extract
python3 tools/sdk_catalogue.py build --out dist/sdk-catalogue.json --source-sha "$(git rev-parse HEAD)"
python3 tools/test_sdk_catalogue.py

Extraction requires Clang and an x64 C11 compiler environment. Clang’s AST supplies table membership and function types; compiled probes supply complete member extents, sizes, service names and versions, reusing tools/abi_snapshot.py for the frozen root table. The gate also compiles the C declarations printed in the rows. No header or ABI pin is generated or changed. These checks prove inventory/layout and source-backed language exposure, not runtime behavior or game verification. The combined core/game records are repository metadata, excluded from SDK package profiles by sdk/components.json; CI publishes the built catalogue as evidence.

The deterministic UTF-8 JSON has sorted keys, records sorted by stable id, no timestamps or absolute paths, and an explicitly supplied full source_sha. Top-level keys are schema_version, sdk_version (from sdk/VERSION), game_pack_version (compiled SCO_GAME_PACK_VERSION), source_sha, contract_context, tables and records.

  • contract_context: source (docs/contracts.md), reading_rules, entrypoint_context, remaining_gaps; the prose is Markdown, with relative links interpreted against source.
  • tables: object keyed by C table name. Each value has source_header, version_macro, members (header field order), size (x64 bytes), version (packed major/minor integer), service and context (service narrative).
  • Each record has id, kind, symbol, table, service, version_macro, source_header, signature, member_extent, table_size, since, purpose, buffer_contract, ownership, thread_affinity, callback_context, reentrancy, results, absent_capability, cleanup, language_mappings, examples, tests, limitations. table, member_extent and table_size are null for entrypoints. Signatures are compiler-normalized C types; extents include the whole pointer. Preserve id across prose changes and symbol renames.
  • language_mappings has c, cpp, csharp, lua; each has status (direct, typed-wrapper, restricted, unsupported) and nonempty evidence containing {path, token} source references. restricted means an exposed subset/adaptation, not unrestricted native access; read its source token and contract. Each mapping also has tests: paths drawn from the record’s test inventory. A supported mapping requires nonempty language-specific tests; an unsupported mapping may use an empty list. C layout pins compile as C11 and C++20; C# and Lua must reference their own test suites. These are source links, not a recorded successful run or per-method runtime certification. Game mutations are unsupported in read-only Lua. A raw C# function pointer field is direct interop, not a typed wrapper.
  • examples and tests contain repository-relative file paths; an empty examples list means none is identified, not proof that no example can exist. ABI test references are layout evidence, not semantic or live-game coverage. limitations contains explicit unestablished guarantees; unspecified never implies safety.

extract validates records and returns header-only methods, tables and game_pack_version (without semantic contexts). check refuses inventory/type/ extent drift, duplicate IDs, missing paths, documentation drift and language support claims without source evidence or language-specific tests. build validates before writing.

This catalogue covers the plain-C plugin boundary: every function-pointer method in sco_api and every public service table declared by the top-level include/*.h headers, plus the three native plugin entrypoints. It does not inventory data fields, callback typedefs as independent methods, SDK wrappers, internal C++ classes or product-link helpers under include/sco/. Wire-only helpers in sc_ipc.h and sc_net.h, bridge layout headers, version constants and event payload structs have no service tables and are excluded. Callback contracts are included with the method that registers or invokes them. This scope is not a claim to cover every exported symbol in a built binary.

The mechanically enumerated inventory is 164 table methods across 30 tables, plus 3 plugin entrypoints: 167 method rows. The inventory below is the checklist; each method has exactly one row in its table’s section, in header field order.

Sources are the linked public headers, ABI layout pins, implementations and API reference / game services. A source-described contract is distinguished from an implementation observation. Unspecified means no guarantee is established here; it is not permission to rely on observed behavior. Game-service behavior has not been verified in a game session; see game service status. This document does not upgrade that status.

Local-player request/cancel/status contract; game pack only. The game pack’s provider is fail-closed: the capability game.relocation is on only while the host certifies offline admission and the engine rows resolve, a live player and known star system exist and the product switch is on (details). Fixtures test the machinery and provider, not gameplay. Native C/raw C++ supported; C# and Lua unsupported. Frozen sco_api and legacy teleport.spatial unchanged.

Member Since Buffer contract Ownership Thread Results Cleanup
sc_relocation_v1.request size >= 16; 1.0 sco_result (*request)(sco_plugin* self, const sc_relocation_request* request, uint64_t* out_ticket);
Admit a copied finite bounded position and normalized quaternion for a streamed nonzero target zone. Request size at least 72, timeout 1..60000ms. Requires known equal nonzero systems, host-certified offline/session/player and validated transport. Unknown safety or system refuses. One global pending request. Output ticket unchanged on refusal; admission is not completion.
Local player only; owner-scoped opaque tickets. No arbitrary entity/pointer/owner writes. Copied request and caller-owned output. 32 retained terminal tickets; oldest terminal evicted at admission. Game thread only; wrong thread returns SCO_WRONG_THREAD without touching state. SCO_OK success; SCO_BAD_ARG invalid input/self; SCO_UNAVAILABLE missing safety/player/transport or unknown/different systems; SCO_TOO_MANY pending global request or ticket exhaustion; SCO_NOT_FOUND foreign/unknown/evicted ticket. Outputs unchanged on failure. Owner unload cancels/forgets tickets; stop forgets all; ticket sequence never recycled. Session/player/system change, safety/transport loss or fault fails pending. Stream loss waits up to timeout. Completion requires fresh pose within 0.05m and quaternion absolute normalized dot at least 0.999999. Cancellation is not undo.
sc_relocation_v1.cancel size >= 24; 1.0 sco_result (*cancel)(sco_plugin* self, uint64_t ticket);
Owner-only idempotent cancellation of a known ticket. Does not undo movement already initiated. Foreign or evicted tickets are NOT_FOUND. Zero ticket is BAD_ARG.
Local player only; owner-scoped opaque tickets. No arbitrary entity/pointer/owner writes. Copied request and caller-owned output. 32 retained terminal tickets; oldest terminal evicted at admission. Game thread only; wrong thread returns SCO_WRONG_THREAD without touching state. SCO_OK success; SCO_BAD_ARG invalid input/self; SCO_UNAVAILABLE missing safety/player/transport or unknown/different systems; SCO_TOO_MANY pending global request or ticket exhaustion; SCO_NOT_FOUND foreign/unknown/evicted ticket. Outputs unchanged on failure. Owner unload cancels/forgets tickets; stop forgets all; ticket sequence never recycled. Session/player/system change, safety/transport loss or fault fails pending. Stream loss waits up to timeout. Completion requires fresh pose within 0.05m and quaternion absolute normalized dot at least 0.999999. Cancellation is not undo.
sc_relocation_v1.status size >= 32; 1.0 sco_result (*status)(sco_plugin* self, uint64_t ticket, sc_relocation_status* out);
Owner-only copied status; caller size at least 24. Preserve caller size and unknown tail. Pending, complete, cancelled or failed plus bounded reason and applied flag. Status does not advance work. Foreign or evicted ticket NOT_FOUND; output unchanged on failure.
Local player only; owner-scoped opaque tickets. No arbitrary entity/pointer/owner writes. Copied request and caller-owned output. 32 retained terminal tickets; oldest terminal evicted at admission. Game thread only; wrong thread returns SCO_WRONG_THREAD without touching state. SCO_OK success; SCO_BAD_ARG invalid input/self; SCO_UNAVAILABLE missing safety/player/transport or unknown/different systems; SCO_TOO_MANY pending global request or ticket exhaustion; SCO_NOT_FOUND foreign/unknown/evicted ticket. Outputs unchanged on failure. Owner unload cancels/forgets tickets; stop forgets all; ticket sequence never recycled. Session/player/system change, safety/transport loss or fault fails pending. Stream loss waits up to timeout. Completion requires fresh pose within 0.05m and quaternion absolute normalized dot at least 0.999999. Cancellation is not undo.

The mappings describe individual primitives, not identical end-to-end language surfaces. C++ actor/entity Open accepts a readable service prefix and guards each method at the point of use; C# Open requires the complete 1.0 table before opening. Neither IsOpen/Boolean conversion establishes operation capability. For the bounded inspector, native C/C++ and C# can combine local-player, health and entity-transform reads; Lua can use the read-only optional game adapter. A zero health maximum is unknown. Alive == false is not proof of removal: it also covers not-yet-streamed entities, missing capability and wrong thread. Positions are zone-local metres; rotations are quaternion x/y/z/w.

Route Fixture / compile evidence Boundary
C public tables tests/abi_v1.c, abi_game_actors.c, abi_game_entities.c, abi_spatial.c, abi_game_events.c; tests/test_language_routes.c Direct calls must check complete member extents and non-null pointers. The recipe uses synthetic reads and caller-position spawn/remove requests.
C++ wrappers tests/test_language_routes.cpp; tests/test_sdk.cpp, tests/game_contracts/sdk_cases.inc, tests/host_sim.cmake Actor/entity wrappers reject partial and null method fields. cpp_hello dynamically loads, ticks, invokes its command and queries its service through the neutral host; no typed spatial wrapper exists.
C# wrappers / layout sdk/csharp/Sco.Sdk.Tests/{FakeHost,GameFakeHost,Layout,GameLayout}.cs Requires .NET 8 test execution. Actor/entity wrappers clear cached state on a failed reopen and reject absent pointers/tails. There is no C# spatial route; an owned-NPC caller-position primitive is not player-pose workflow parity.
C# NativeAOT host loading .github/workflows/sdk.yml: csharp-host-sim Windows x64 cs_hello loads through sco-host-sim, ticks, invokes a command and finds a service. This generic plugin does not test inspector/NPC game-provider behavior.
Lua sandbox / game adapter tests/test_lua.cpp, tests/game_contracts/lua_cases.inc Real Lua loader/sandbox with optional adapter and synthetic providers; absence, budget overruns, short event payloads, callback cleanup and partial/null query methods are covered.

Owned NPC creation/removal is unsupported in Lua. Scripts own no NPCs and do not gain mutation by invoking a product command. DataCore’s separate patch/write service is not a game-object mutation binding. Native C++ may call the public C teleport.spatial table; C# lacks that mapping. No wrapper is invented for parity.

The supported game-runtime target is Windows x64. macOS ARM64 and Linux runs are development-fixture evidence; header cross-compilation to Windows x64 is layout/compile evidence, not execution on Windows. C# layout/NativeAOT and real host loading must run in their SDK CI jobs when dotnet is unavailable locally. Complete combined game-workflow loading, delayed streaming/removal, provider cleanup, and actual game semantics still require their corresponding host/game acceptance. No simulator response certifies gameplay or arbitrary native-process recovery. Provider reload refusal and retained raw-table lifetimes remain as specified in the lifetime audit.

  • Result names without the prefix mean the corresponding SCO_* value. Normal success is SCO_OK unless the row describes a Boolean, ID, count, string or void result. Listed failures are known cases, not an exhaustive proof of every fault; unspecified cases and precedence between simultaneous errors remain unspecified.
  • The size / since cell gives the minimum x64 table byte extent that includes the whole function pointer, not just its first byte. Check size >= offsetof(Table, method) + sizeof(table->method) before reading that pointer, then check it is non-NULL. A version match alone does not justify reading an uncovered tail. The historical examples using size > offsetof(...) presume a well-formed complete provider table; current consumers must use the full extent and non-null method check, not that historical shorthand.
  • For service discovery, query_service requires equal version majors and a provider minor at least the requested minor. Missing service: SCO_NOT_FOUND; incompatible/older version: SCO_UNAVAILABLE; output table NULL except on success. No missing pointer or service should be called. Tables may grow only by appending fields; unknown tails are not to be inspected. Host/game-owned tables outlive all plugins and are withdrawn after plugin unload. Third-party tables have the provider’s lifetime, not that of the querying plugin.
  • Caller size-prefixed inputs/outputs use sizeof as built by the caller. An oversized buffer/struct is not a promise that an unknown tail is initialized: tail initialization and preservation are unspecified unless noted. Command argument-definition stride is arg_def_size; sco_arg is frozen at 16 bytes, sco_sql_value at 16 bytes and sc_vehicle_seat at 96 bytes. Padding/reserved input fields are zero. Enums are 4 bytes; do not pass _FORCE32 sentinels.
  • Byte handshake: *inout_size is capacity on entry, bytes written on success, bytes needed with SCO_TOO_MANY; NULL output with zero capacity asks the size. Text is NUL-terminated and the terminator counts. This is not the same as get_peers’ element-count handshake or the truncating fixed-capacity name calls. Required size may change between calls: retry if needed, not an atomic snapshot.
  • Caller buffers stay caller-owned. No returned service pointer, string, mapping, command descriptor, frame or game ID is an allocation the plugin may free. “No allocation transfer” does not mean “no internal allocation” or “real-time safe.” Internal allocation bounds/latency are unspecified unless recorded.
  • Unless a row says inputs are copied, their retention is unspecified beyond the synchronous call. Keep borrowed callback code and ctx alive for its registration or queued lifetime; ctx is not automatically freed. Callback payload pointers are valid during the callback only; copy retained data.
  • Any-thread permission is not a recursive-reentrancy guarantee. Rows explicitly mark known callback-safe operations and otherwise say reentrancy unspecified. Game-thread permission does not permit calls from a game hook or arbitrary worker.
  • “No cancellation entrypoint” records API surface, not guaranteed completion, rollback or an interruptible call. Unload/crash cleanup and callback quiescence are stated separately. Synchronous calls have no cancel token. Cancellation of an operation already in progress is unspecified unless stated.
  • last_error is a diagnostic, not a return-value replacement: scope varies by service and another call may overwrite it. Complete diagnostics for every failure and error-text retention after success are unspecified unless documented.
Table / entrypoints Methods Current x64 size Contract version
sc_economy_v1 3 32 1.0
sc_missions_v1 7 64 1.0
sco_api 15 128 1.1
sco_storage_v1 15 128 1.0
sco_datacore_v1 10 88 1.1
sco_ipc_v1 9 80 1.0
sco_net_v1 7 64 1.0
sco_settings_v1 5 48 1.0
sco_content_v1 2 24 1.0
sco_ui_v1 9 80 1.0
sco_ui_surfaces_v1 4 40 1.0
sco_widgets_v1 5 48 1.1
sco_diagnostics_publisher_v1 1 16 1.0
sc_relocation_v1 3 32 1.0
sc_spatial_v1 6 56 1.0
sc_game_spatial_v1 4 40 1.0
sc_spawn_service_v1 7 64 1.2
sc_actors_v1 6 56 1.1
sc_vehicles_v1 7 64 1.0
sc_creative_v1 7 64 1.0
sc_hangar_v1 4 40 1.0
sc_reputation_v1 2 24 1.0
sc_asop_v1 3 32 1.0
sc_contracts_v1 2 24 1.0
sc_loadout_v1 1 16 1.1
sc_quantum_v1 4 40 1.0
sc_mining_v1 2 24 1.0
sc_private_session_v1 4 40 1.0
sc_cvars_v1 1 16 1.0
sc_cvars_write_v1 2 24 1.0
sc_world_v1 4 40 1.1
sc_world_control_v1 4 40 1.0
sc_entities_v1 11 96 1.1
sc_prefabs_v1 1 16 1.0
sc_owned_v1 6 56 1.0
Native plugin entrypoints 3 sco_plugin_info: 32 API 1.1

Source: sco_api.h, loader.cpp, plugin exports. All three are required for a native DLL. The loader contains faults in these exports; this is containment, not memory safety or a sandbox. Query is called before load; load is called after version checks. Shutdown delivery is best effort, not a crash-safe persistence mechanism. Ordinary owner release runs resource hooks; restart-required retained-provider faults skip them. An exposed provider whose load returns non-OK may instead be refused with backing state retained; this is distinct from a fault and does not run owner release or clear exports/module state.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_plugin_query API 1.0; returned info must cover 32-byte sco_plugin_info const sco_plugin_info* sco_plugin_query(void); info.size set to sizeof, name/version/author UTF-8 NUL strings Plugin-owned static info/string storage valid until DLL unload; host copies checked metadata. Never free from host Query-thread identity unspecified; recursive reentrancy unspecified NULL info, undersized info, major mismatch, newer minor, mismatched plugin id or guarded fault refuses load; no capability gate No cancellation entrypoint; query does not register a cleanup notification
sco_plugin_load API 1.0; received API fields gated by size sco_result sco_plugin_load(const sco_api* api, sco_plugin* self) Borrowed host API and opaque self valid until unload; plugin owns its private state/allocations; internal allocation unspecified Game thread per API reference; recursive load reentrancy unspecified OK stays loaded; any other return rejects load; guarded fault disables plugin. Missing required capabilities handled by discovery; load-specific absence policy belongs to plugin Ordinary failed-load/non-retained crash cleanup removes registrations, queued work and owned resources. If a nested consumer obtained the provider table during load, a failed load is refused with backing state retained: no owner release, resource hooks, export clearing or module closure. Exposed-provider faults instead become terminal faulted with retained state and restart required. Do not rely on unload after a failed load.
sco_plugin_unload API 1.0; no sized parameter void sco_plugin_unload(void); final normal lifecycle call for that instance Plugin frees its own state and stops its workers; host owns API/self/registries; borrowed external pointers must not be freed Normal host lifecycle uses game-thread release; an independent export thread guarantee and recursive reentrancy are unspecified void, no error result; loader guards faults. Capability availability during teardown unspecified Terminal shutdown or permitted reload; crashed/failed-load instances need not receive it. Live-session unload/reload of a provider whose table was handed out is refused. Retained-provider faults skip unload/resource hooks and require restart; mapped code does not make cached calls safe.

Source: sco_api.h, implementation, layout pin.

API 1.0 ends at 88 bytes; 1.1 adds the five final methods through 128 bytes. register_command requires at least the 72-byte descriptor, at most 16 arguments, non-NULL fn, and for nonempty defs arg_def_size >= 24 and aligned to the argument definition alignment. Copied strings have limits: name/title/capability 63 bytes, help 255, argument name 31 and help 127, excluding NUL. Replies have a 256-byte host buffer including NUL. Normal unloading removes owned registrations/queued work; void methods silently ignore invalid self rather than returning BAD_ARG. Source for registry/queue details: commands, events, tasks, services, raw handlers. The immediate invoke’s “done once” rule applies after initial validation; invalid self/name/count/buffer combinations can return without entering completion.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_api.host_version size >= 16; 1.0 const char* (*host_version)(void);
“sc-offline 0.8.0”. Static string.
Borrowed static host string; never free. Internal allocation unspecified. Any thread; reentrancy unspecified. No result/error channel. No capability gate. NULL before host version setup possible in implementation; published-host lifetime is host-owned. No cancellation entrypoint; synchronous unless noted.
sco_api.has size >= 24; 1.0 int (*has)(const char* capability);
1 if the capability is available on this game build, else 0.
Capability string borrowed during call; no allocation transfer; fixed registry lookup. Any thread; reentrancy unspecified. 1 available; 0 absent/unknown/NULL name. No result/error channel. No cancellation entrypoint; synchronous unless noted.
sco_api.run_on_game_thread size >= 32; 1.0 sco_result (*run_on_game_thread)(sco_plugin* self, sco_task_fn fn, void* ctx);
Any thread. Runs fn(ctx) on the game thread, in order, on the next tick. SCO_TOO_MANY only when 65536 tasks are already waiting (the host’s cap) or memory runs out.
fn/ctx borrowed until execution or owner release; ctx is not copied/freed. First 256 waiting tasks use fixed ring; overflow allocates nodes up to 65,536 waiting tasks. Any thread; reentrancy unspecified. OK queued; BAD_ARG invalid/released self or NULL fn; TOO_MANY at queue hard cap or allocation failure; no capability gate. Queued tasks dropped on unload/failed load/crash; no task-specific cancel or drop notification; caller must clean ctx.
sco_api.subscribe size >= 40; 1.0 sco_result (*subscribe)(sco_plugin* self, const char* event, sco_event_fn fn, void* ctx);
Any thread. Applies from the next dispatch.
Event name copied; fn/ctx borrowed until unsubscribe/unload. Host allocates copy-on-write subscription list; caller owns ctx. Any thread; reentrancy unspecified. BAD_ARG invalid/released self, NULL/empty event, NULL fn or duplicate (self,event,fn); TOO_MANY capacity/allocation failure. Missing event producer is not a registration error; no event may arrive. unsubscribe or owner unload/crash ends delivery; in-flight callback may finish.
sco_api.unsubscribe size >= 48; 1.0 sco_result (*unsubscribe)(sco_plugin* self, const char* event, sco_event_fn fn);
Any thread. Applies at once: a running dispatch won’t call fn again. Freeing ctx: on the game thread, right after unsubscribe returns (also from inside fn itself). From another thread fn may be running now; call run_on_game_thread after unsubscribe returns and free ctx in that task. Tasks never run while a dispatch is in progress.
Caller owns fn/ctx. Host may allocate replacement subscription list. Follow callback-quiescence rule before freeing ctx. Any thread; allowed inside own event callback. Does not join off-thread in-flight callback; other reentrancy unspecified. BAD_ARG invalid/released self or NULL event/fn; NOT_FOUND no matching subscription; TOO_MANY replacement-list allocation failure. No capability gate. On successful removal no new callback, including remainder of current dispatch; off-thread already-running callback may finish. Free ctx via later game-thread task.
sco_api.status size >= 56; 1.0 void (*status)(sco_plugin* self, const char* message);
Shows <plugin>: message on status line. CR/LF become spaces; NULL/invalid self ignored; longer message cut to fit the host buffer.
Message borrowed for call, copied/sanitized through 256-byte stack buffer; no allocation transfer. Any thread; reentrancy unspecified. void; invalid/released self or NULL message silently ignored; CR/LF become spaces and message truncates. No capability gate. No cancellation entrypoint; synchronous unless noted.
sco_api.log size >= 64; 1.0 void (*log)(sco_plugin* self, sco_log_level level, const char* message);
Logs [plugin] message on one line; warn/error add a tag, CR/LF become spaces and long message is cut.
Message borrowed for call, copied/sanitized through 512-byte stack buffer; no allocation transfer. Any thread; reentrancy unspecified. void; invalid/released self or NULL message silently ignored; CR/LF become spaces and message truncates; unknown level follows info branch. No capability gate. No cancellation entrypoint; synchronous unless noted.
sco_api.register_command size >= 72; 1.0 sco_result (*register_command)(sco_plugin* self, const sco_command* cmd);
Commands: the one way to use a feature. The host copies cmd, its strings and its arg defs; only fn and ctx must stay valid until the plugin unloads.
Host copies descriptor strings and argument definitions; only fn/ctx borrowed until unload. Registry slots host-owned; no allocation transfer. Any thread; reentrancy unspecified. BAD_ARG invalid descriptor/size/stride, args/type/name/prefix or duplicate; TOO_MANY capacity/allocation. Missing command capability gates invocation, not registration. Owner unload/crash removes registration; no individual unregister API.
sco_api.invoke size >= 80; 1.0 sco_result (*invoke)(sco_plugin* self, const char* name, const sco_arg* args, uint32_t nargs, sco_invoke_done done, void* ctx);
From the game thread: runs now, calls done (if set) once before returning, and returns the same result. From another thread: copies name and args, queues the call and returns SCO_OK; done then runs exactly once, on the game thread. Any other return (SCO_BAD_ARG, or SCO_TOO_MANY when the queue is full or memory runs out) means nothing was queued and done is never called. A call still queued when the plugin unloads is dropped without calling done.
On game thread, arguments borrowed during call. Else name/arguments/string values copied into host queue allocations; done/ctx borrowed. reply borrowed during done only. Any thread; on game thread command/done run synchronously; elsewhere queued and done runs on game thread. Recursive invoke depth/limit unspecified. Game thread: command result incl NOT_FOUND, BAD_ARG, UNAVAILABLE capability, CRASHED guarded fault, or provider result. Other thread: OK queued, BAD_ARG/TOO_MANY nothing queued. Initial validation can return before done. Queued call dropped on calling owner release without done; non-OK enqueue return means done never runs. No invocation-specific cancellation.
sco_api.list_commands size >= 88; 1.0 uint32_t (*list_commands)(const sco_command** out, uint32_t max);
Writes up to max command pointers to out; returns the number of live commands. The pointers stay valid until their owning plugin unloads.
out array caller-owned; command pointers host-owned until owner unload/slot reuse. Keep names, not pointers. Internal allocation unspecified. Any thread; reentrancy unspecified. Returns total live count, not number written; NULL out or max 0 counts only. No result/error channel or capability gate. No cancellation entrypoint; synchronous unless noted.
sco_api.provide_service size >= 96; 1.1 sco_result (*provide_service)(sco_plugin* self, const char* name, uint32_t version, const void* vtable);
Any thread. Publishes vtable under name (“<plugin id>” or “<plugin id>.<name>”, [a-z0-9_.], 1-63 chars) with version (major << 16) | minor. SCO_BAD_ARG: a bad or taken name, or a name outside this plugin’s id. Withdrawn when this plugin unloads or crashes, or by release_service. Start the table with a uint32_t size so it can grow.
Host copies name/version, borrows table contents/code until withdrawal or unload; provider retains state ownership. Registry allocation may fail. Any thread; reentrancy unspecified. BAD_ARG invalid/released self, NULL table, invalid/taken/out-of-prefix name; TOO_MANY allocation. No capability gate. release_service or owner unload/crash withdraws lookup; no cancellation/quiescence guarantee for calls already using table.
sco_api.query_service size >= 104; 1.1 sco_result (*query_service)(const char* name, uint32_t min_version, const void** out_vtable);
Any thread. SCO_OK: *out_vtable = the table of the service with this name, same major as min_version and at least as new. SCO_UNAVAILABLE: another major, or older. SCO_NOT_FOUND: none. *out_vtable is NULL unless SCO_OK. A plugin’s table goes away when it unloads: query when needed.
Returns borrowed provider table; never free. Host/game tables live through plugin lifetime. Native provider code remains mapped after handout, not necessarily its state. Handout tracking may allocate. Any thread; reentrancy unspecified. BAD_ARG NULL name/out; NOT_FOUND absent; UNAVAILABLE incompatible major/older minor; TOO_MANY handout-tracking allocation. *out NULL unless OK. No cancellation. Native provider hot reload/unload during session refused after handout; shutdown still tears down state. Do not assume held state stays usable after withdrawal/crash.
sco_api.release_service size >= 112; 1.1 sco_result (*release_service)(sco_plugin* self, const char* name);
Any thread. Withdraws one of this plugin’s services. SCO_NOT_FOUND: it publishes nothing by that name.
Withdraws borrowed pointer, never frees provider table. Concurrency/quiescence for callers holding it unspecified. Any thread; reentrancy unspecified. BAD_ARG invalid self or NULL name; NOT_FOUND no owned service (including one already withdrawn). No capability gate; released-self handling not an explicit wrapper check. Stops future lookup; effects on calls already executing unspecified.
sco_api.invoke_raw size >= 120; 1.1 sco_result (*invoke_raw)(sco_plugin* self, const char* name, const void* in_bytes, uint32_t in_size, void* out_bytes, uint32_t* inout_out_size);
Game thread. Calls the raw handler registered under name, now: in_size bytes in, up to *inout_out_size bytes out (on return: bytes written, or needed with SCO_TOO_MANY). in may be NULL with in_size 0; out may be NULL with *inout_out_size 0 (asks the size), and inout_out_size NULL when no output is wanted. SCO_NOT_FOUND, SCO_UNAVAILABLE (capability missing), SCO_WRONG_THREAD (other threads), SCO_CRASHED (the handler faulted).
in/out are caller buffers borrowed synchronously; layout and byte ownership are handler contract. Host does not keep bytes. Game thread only (WRONG_THREAD elsewhere); recursive raw-handler invocation unspecified. BAD_ARG invalid self/name/buffer combinations; WRONG_THREAD; NOT_FOUND; UNAVAILABLE handler gate; CRASHED fault (out size 0); TOO_MANY required size/overstated output; other handler result. Error output-byte contents unspecified. No cancellation entrypoint; synchronous unless noted.
sco_api.register_raw size >= 128; 1.1 sco_result (*register_raw)(sco_plugin* self, const char* name, const char* capability, sco_raw_fn fn, void* ctx);
Any thread. Registers fn under name (“<plugin id>.<name>”, the command name rule), gated on capability (NULL: none). Only fn and ctx are borrowed, until this plugin unloads. SCO_BAD_ARG: a bad or taken name.
Name/capability copied; fn/ctx borrowed until unload/crash. Host records and registry own allocations, not ctx. Any thread; reentrancy unspecified. BAD_ARG invalid/released self, NULL fn, bad/taken/out-of-prefix name or capability syntax; TOO_MANY raw registry capacity/allocation or 1024 successful wrapper registrations over process lifetime. Missing capability gates invocation, not registration. Owner unload/crash removes registration; no individual unregister API.

Source: sco_storage.h, implementation, layout pin.

One database, transaction and cursor namespace per plugin, not per thread. Any thread can use the plugin’s transaction/cursor, but concurrent calls serialize. Keys are 1–255 bytes; values 0–1 MiB; at most 64 open cursors per plugin. The host may allocate copies, statements and cursors; callers never receive SQLite memory. Database quota and statement budgets are host-configured, not fixed by the method table. A budget failure is FAILED, not an API cancellation callback. For SQL restrictions and persistence settings see storage.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_storage_v1.put size >= 16; 1.0 sco_result (*put)(sco_plugin* self, const char* key, const void* value, uint32_t value_size);
Writes value (value_size bytes; value may be NULL with 0), replacing any old one. Durable when it returns, unless a transaction is open. SCO_TOO_MANY: the plugin’s quota is full.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.get size >= 24; 1.0 sco_result (*get)(sco_plugin* self, const char* key, void* out, uint32_t* inout_size);
Reads a value with the size handshake. SCO_NOT_FOUND: no such key (*inout_size 0).
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.del size >= 32; 1.0 sco_result (*del)(sco_plugin* self, const char* key);
Removes a key. SCO_NOT_FOUND: there was none.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.next_key size >= 40; 1.0 sco_result (*next_key)(sco_plugin* self, const char* prefix, const char* after, char* out, uint32_t* inout_size);
The first key that starts with prefix (NULL or “”: any key) and sorts after “after” (NULL: from the start), in byte order, copied NUL-terminated with the size handshake. Iterate by passing the last key back as after. SCO_NOT_FOUND: no more keys.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.begin size >= 48; 1.0 sco_result (*begin)(sco_plugin* self);
SCO_BAD_ARG: one is already open. Until commit nothing the plugin writes is durable; ordinary unload, non-retained crash cleanup or rollback undoes all of it. Retained-provider faults skip rollback/close hooks and require restart.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. rollback or ordinary unload/non-retained crash cleanup undoes uncommitted writes; no per-call interrupt API. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.commit size >= 56; 1.0 sco_result (*commit)(sco_plugin* self);
Makes everything since begin durable. SCO_BAD_ARG: none open.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. Synchronous; no cancellation API; successful commit durable and not undone by unload. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.rollback size >= 64; 1.0 sco_result (*rollback)(sco_plugin* self);
Undoes everything since begin. SCO_BAD_ARG: none open.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. Synchronous rollback, not a request to interrupt another thread’s running statement.
sco_storage_v1.exec size >= 72; 1.0 sco_result (*exec)(sco_plugin* self, const char* sql, const sco_sql_value* params, uint32_t nparams, int64_t* out_changes);
Runs one statement with nparams bound parameters (?, ?NNN, :name in index order; nparams must equal the statement’s count; params may be NULL with 0). Rows it returns are dropped. out_changes (optional): rows changed. SCO_BAD_ARG: not exactly one statement, a syntax error, a wrong parameter count, or something storage refuses (ATTACH, DETACH, BEGIN, COMMIT, SAVEPOINT, VACUUM, a PRAGMA outside the list in docs/storage.md, schema changes to a table or index named sco_*). SCO_FAILED: it ran and failed (a constraint, its time budget, the database busy); last_error says why. SCO_TOO_MANY: the quota is full.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.query size >= 80; 1.0 sco_result (*query)(sco_plugin* self, const char* sql, const sco_sql_value* params, uint32_t nparams, uint64_t* out_cursor);
Prepares one statement as exec does and opens a cursor before its first row. Close it when done. SCO_TOO_MANY: SCO_STORAGE_MAX_CURSORS already open. out_cursor initialized to 0 before validation; caller must close cursor even after end-of-rows.
Host-owned cursor ID; close when done. SQL/parameters copied during call, TEXT needs no NUL; no SQLite memory crosses ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.step size >= 88; 1.0 sco_result (*step)(sco_plugin* self, uint64_t cursor);
Moves to the next row. SCO_OK: a row is ready. SCO_NOT_FOUND: no more rows, or an id this plugin doesn’t hold. SCO_FAILED / SCO_TOO_MANY: as for exec.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.column_count size >= 96; 1.0 sco_result (*column_count)(sco_plugin* self, uint64_t cursor, uint32_t* out_count);
Returns number of columns of a held cursor into required uint32_t out_count; no current row needed; output initialized to 0.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Common storage failures; BAD_ARG NULL output; NOT_FOUND unknown/non-owned cursor; *out_count initialized to 0. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.column size >= 104; 1.0 sco_result (*column)(sco_plugin* self, uint64_t cursor, uint32_t index, sco_sql_value* out, void* buf, uint32_t* inout_size);
Column index of the current row. out gets the type and value; TEXT and BLOB bytes go to buf with the size handshake (TEXT NUL-terminated; inout_size NULL: no bytes wanted). SCO_BAD_ARG: no current row, or index out of range.
Caller owns descriptor and byte buffer. TEXT/BLOB descriptor v.p is NULL; numeric values copied. Host may allocate staging text. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.column_name size >= 112; 1.0 sco_result (*column_name)(sco_plugin* self, uint64_t cursor, uint32_t index, char* out, uint32_t* inout_size);
The column’s name, NUL-terminated, with the size handshake.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Common storage failures; NOT_FOUND unknown/non-owned cursor; BAD_ARG invalid buffer/index; TOO_MANY required bytes. Does not require a current row. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.close size >= 120; 1.0 sco_result (*close)(sco_plugin* self, uint64_t cursor);
Closes a cursor. SCO_NOT_FOUND: this plugin holds no cursor by that id.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_storage_v1.last_error size >= 128; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The message of this plugin’s last failed call (“” if none), NUL-terminated, with the size handshake.
Caller buffers; inputs/SQL parameters copied during call. Host owns database/cursors; no SQLite pointer or allocation crosses the ABI. Any thread; calls serialize per plugin. Same-call recursive reentrancy unspecified. Absent table: query_service NOT_FOUND. Stopped: UNAVAILABLE; invalid/released self: BAD_ARG. Allocation exceptions: TOO_MANY; database errors may be FAILED. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; ordinary unload/non-retained crash cleanup rolls back transaction and closes cursors/database. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.

Source: sco_content.h, implementation, layout pin. G14 audit/design records why the private index and command registry were insufficient. This game-neutral service copies enabled list/script pack bytes before consumer loads. Only startup snapshots are exposed; no file paths or script execution. All calls require the game thread and live self. Global limits: 4096 items, 16 MiB bytes; 1 MiB per file. A pack is refused atomically on unsafe/unreadable content or quotas, including dependent packs. Size handshakes are binary: no appended NUL. Host restart invalidates old IDs. C++ scosdk/content.hpp guards full extents/null pointers and failed reopen; C#/Lua are not exposed. Synthetic kernel-only fixtures are not game evidence.

Method Size / since Signature; inputs, outputs and buffers Ownership / lifetime / allocation Thread / callback context / reentrancy Results / absent capability Cancellation / cleanup
sco_content_v1.item size >= 16; 1.0 sco_result (*item)(sco_plugin* self, sco_content_kind kind, uint32_t ordinal, sco_content_item* out);
Copies one supported list/script record by zero-based kind ordinal in plugin/name order. Caller sets size >= sizeof(sco_content_item). Duplicate names retain distinct IDs. Failure leaves output untouched.
Caller-owned copied records/bytes; host owns bounded startup snapshot. No paths, borrowed content pointers or allocation transfer. Game thread only; synchronous memory copies, no callouts or file IO. Query NOT_FOUND when absent; UNAVAILABLE when stopped/terminal shutdown; WRONG_THREAD off game thread; BAD_ARG invalid/released self or invalid buffer/kind; NOT_FOUND ordinal end or unknown/stale ID; read TOO_MANY reports needed bytes. No cancel or per-owner resource; host Stop clears snapshot and invalidates IDs. Table storage is process-lifetime; packs require restart.
sco_content_v1.read size >= 24; 1.0 sco_result (*read)(sco_plugin* self, uint64_t id, void* out, uint32_t* inout_size);
Copies exact immutable startup bytes; no added NUL. Size handshake: capacity in, written on OK, needed on TOO_MANY. NULL out requires zero capacity; empty file is OK/0. Only TOO_MANY changes size on failure; no failed call writes bytes.
Caller-owned copied records/bytes; host owns bounded startup snapshot. No paths, borrowed content pointers or allocation transfer. Game thread only; synchronous memory copies, no callouts or file IO. Query NOT_FOUND when absent; UNAVAILABLE when stopped/terminal shutdown; WRONG_THREAD off game thread; BAD_ARG invalid/released self or invalid buffer/kind; NOT_FOUND ordinal end or unknown/stale ID; read TOO_MANY reports needed bytes. No cancel or per-owner resource; host Stop clears snapshot and invalidates IDs. Table storage is process-lifetime; packs require restart.

Source: sco_datacore.h, implementation, layout pin.

1.1 changes add_record availability, not layout: both versions are 88 bytes and that pointer already exists in 1.0 (returns UNAVAILABLE there). Value structs use sco_dc_value.size; report requires at least sizeof(sco_dc_report). 64 open/queued patches per plugin and 65,536 operations per patch. Operations copy inputs and validate syntax immediately; record/type/field resolution and atomic application happen at the one game load. Before load, commit queues; after load it saves for future launches, never patches the current session late. NON_ATOMIC permits partial application. Patch-level reports carry deferred failures; there is no last_error method. The implementation’s container/string allocations have no per-method allocation-exception translation guarantee in this table; that failure contract is unspecified rather than inferred from other services’ guards. See DataCore.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_datacore_v1.state size >= 16; 1.0 uint32_t (*state)(void);
SCO_DC_OPEN or SCO_DC_LOADED.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Returns OPEN or LOADED; no sco_result. Absent table NOT_FOUND; stopped-state value unspecified as a contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.begin size >= 24; 1.0 sco_result (*begin)(sco_plugin* self, uint32_t flags, uint64_t* out_patch);
A new patch owned by self. flags: 0 or SCO_DC_NON_ATOMIC. SCO_BAD_ARG: a bad self or flags. SCO_TOO_MANY: SCO_DC_MAX_PATCHES of this plugin’s patches are open or queued for the load. Implementation initializes out_patch to 0 on failure.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.set size >= 32; 1.0 sco_result (*set)(uint64_t patch, const char* record, const char* field, const sco_dc_value* v);
record: a record name, or “guid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”. field: a field path, name / name[3] / name[Type] joined with ‘.’. Sets a value in place; v NULL or SCO_DC_NULL sets a null pointer, SCO_DC_INSTANCE points the field at an added instance. Implementation refuses duplicate set of same target/field within one patch with BAD_ARG.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.add_instance size >= 40; 1.0 sco_result (*add_instance)(uint64_t patch, const char* type, const char* clone_record, const char* clone_field, uint64_t* out_instance);
A new instance of struct type, copied from clone_record’s clone_field (NULL or “”: the record’s root) or zero-filled (clone_record NULL). out_instance: its id, usable in this patch’s SCO_DC_INSTANCE values and set_pointer. Implementation initializes out_instance to 0 on failure.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.set_pointer size >= 48; 1.0 sco_result (*set_pointer)(uint64_t patch, const char* record, const char* field, uint64_t instance);
Points a strong or weak pointer field at an added instance. Uses set internally; therefore duplicate-target/field rule and value.size validation apply.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.append size >= 56; 1.0 sco_result (*append)(uint64_t patch, const char* record, const char* field, const sco_dc_value* v);
Appends one element to an array field: a value, a pointer (SCO_DC_NULL, SCO_DC_INSTANCE), or for an array of structs SCO_DC_INSTANCE, the added instance to copy in.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.add_record size >= 64; 1.0 slot; works 1.1 sco_result (*add_record)(uint64_t patch, const char* type, const char* name, const char* guid, const char* clone_record, const char* file_path, uint64_t* out_record);
1.1: a new record of struct type named name (unique among records), its root copied from the record clone_record (a name or “guid:…”, required; a record of the same struct). guid: NULL or “” derives a stable one from the plugin id and name (the same at every launch); else “xxxxxxxx-…”, not zero. file_path: NULL or “” is libs/foundry/records/sco/<plugin id>/<name>.xml; else libs/foundry/records/… ending in .xml. out_record: an id like add_instance’s (the record’s root: “@<id>” as a record argument, SCO_DC_INSTANCE as a value); later operations may also name the record by name or GUID, and reference fields take it as SCO_DC_REF. SCO_BAD_ARG: a bad argument, or a name or GUID this patch already adds. The rest (struct has records, name and GUID new to the file, clone’s struct) is checked at the load. In the saved .toml it is a [[record]] operation. SCO_UNAVAILABLE on a 1.0 host. Implementation initializes out_record to 0 on failure.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.commit size >= 72; 1.0 sco_result (*commit)(uint64_t patch);
Before the load: queues the patch for it (reports SCO_DC_QUEUED). After it: saves the patch as data/datacore/pending/<plugin id>.toml (written to a temporary file, then renamed over the old one) and reports SCO_DC_QUEUED “applies at the next launch”; an empty patch clears the saved one. No more operations on it either way. SCO_BAD_ARG: already committed. SCO_FAILED: the file couldn’t be written (the patch stays open; commit again).
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.discard size >= 80; 1.0 sco_result (*discard)(uint64_t patch);
Drops a patch: an open one, or a committed one before the load. After it was saved or applied only the id is forgotten (delete the saved file by committing an empty patch).
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.
sco_datacore_v1.report size >= 88; 1.0 sco_result (*report)(uint64_t patch, uint32_t index, sco_dc_report* out);
Entry index: 0 .. operations-1 are the operations in call order, then one entry for the patch itself (op_index SCO_DC_OP_PATCH). out->size must be at least sizeof(sco_dc_report). SCO_NOT_FOUND past the last entry or for an unknown, discarded or released patch.
Strings/values copied; host owns patches and instances; IDs, not allocations, cross the ABI. Internal allocation/failure guarantee unspecified. Any thread; short locks, no wait for game load. Recursive/concurrent same-patch reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped operations: UNAVAILABLE. Unknown/released patch: NOT_FOUND; closed patch: BAD_ARG; operation cap: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; discard drops open/queued patch, not applied or saved effects. Unload forgets owned patches.

Source: sco_ipc.h, implementation, layout pin.

Channels are restricted to the caller’s namespace. New Windows mappings receive a DACL granting access only to the current user. Reused mappings are checked for current-user ownership and sufficient size, not their existing DACL; current-user-only access is therefore not guaranteed on reuse. Bounds: 16 channels/plugin, 32 rings/channel, 4 KiB–256 MiB/channel, 512 MiB total per plugin. Offsets exclude the first 64 header bytes; blocks align to 8 bytes, rings to 64; ring data capacity is power-of-two, at least 64. Peer data is untrusted. Wire FULL/TOO_SMALL map to TOO_MANY; EMPTY/NOT_READY to NOT_FOUND; BAD_ARG/MISMATCH to BAD_ARG; corrupt/epoch/busy/gone cases to FAILED. The header says copy operations never block; the implementation still takes mutexes and allocates staging buffers, so no lock-free or bounded-latency guarantee is established. View access/close synchronization is the caller’s responsibility; its precise concurrency contract is unspecified. See IPC.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_ipc_v1.create size >= 16; 1.0 sco_result (*create)(sco_plugin* self, const char* name, uint64_t bytes, uint32_t layout_id, uint32_t layout_version, uint64_t* out_channel);
Creates (or, if the peer still holds it, re-opens) Local\SCO_<plugin id>.<name> with bytes bytes and lays out the sc_ipc_hdr with the bridge’s layout_id / layout_version and a new epoch (rings must be laid out again). SCO_BAD_ARG: a bad name or size, or a channel of that name already open. SCO_TOO_MANY: the channel or byte quota is full. SCO_FAILED: the OS refused, or an existing mapping of that name is smaller or another user’s. New Windows mappings receive a current-user-only DACL; reuse checks ownership and size, not the existing DACL, so access by other accounts is not excluded on reuse.
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.peer_age_ms size >= 24; 1.0 sco_result (*peer_age_ms)(sco_plugin* self, uint64_t channel, uint32_t* out_ms);
Milliseconds since the peer’s last beat (capped at UINT32_MAX). SCO_NOT_FOUND: no such channel, or the peer hasn’t beaten yet (*out_ms 0).
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.block_write size >= 32; 1.0 sco_result (*block_write)(sco_plugin* self, uint64_t channel, uint64_t offset, const void* data, uint32_t size);
Writes a seqlock snapshot of size bytes into the block at offset.
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.block_read size >= 40; 1.0 sco_result (*block_read)(sco_plugin* self, uint64_t channel, uint64_t offset, void* out, uint32_t size);
Reads exactly size bytes of the block at offset. SCO_NOT_FOUND: never written. SCO_BAD_ARG: the writer’s snapshot has another size. SCO_FAILED: the writer kept it torn; retry.
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.ring_init size >= 48; 1.0 sco_result (*ring_init)(sco_plugin* self, uint64_t channel, uint64_t offset, uint64_t capacity, uint32_t direction);
Lays out an empty ring at offset with capacity data bytes (a power of two, at least 64), in one direction (SCO_IPC_TO_PEER or SCO_IPC_FROM_PEER). Re-initializing a ring at the same offset resets it. SCO_BAD_ARG: outside the mapping, overlapping another ring, a bad capacity or direction. SCO_TOO_MANY: SCO_IPC_MAX_RINGS already.
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.ring_push size >= 56; 1.0 sco_result (*ring_push)(sco_plugin* self, uint64_t channel, uint64_t offset, uint32_t type, const void* data, uint32_t size);
Appends one record to the SCO_IPC_TO_PEER ring at offset. SCO_TOO_MANY: full now. SCO_NOT_FOUND: no ring laid out there. SCO_BAD_ARG: a FROM_PEER ring, type 0xFFFFFFFF, or a record the ring can never hold.
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.ring_pop size >= 64; 1.0 sco_result (*ring_pop)(sco_plugin* self, uint64_t channel, uint64_t offset, uint32_t* out_type, void* out, uint32_t* inout_size);
Takes the oldest record of the SCO_IPC_FROM_PEER ring at offset, with the size handshake: *inout_size holds out’s capacity on entry, the record’s size on return; with SCO_TOO_MANY the size needed, and the record stays queued (pass out NULL with *inout_size 0 to ask). out_type may be NULL. SCO_NOT_FOUND: empty, or no ring there. SCO_FAILED: the peer wrote something invalid.
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.view size >= 72; 1.0 sco_result (*view)(sco_plugin* self, uint64_t channel, void** out_base, uint64_t* out_bytes);
The plugin’s own mapping (header included) and its size, for bulk regions. Valid until close or unload; the host still validates everything it reads there.
Borrowed own mapping including header; valid until close/unload/crash. Never free; synchronization with close and direct-view access unspecified. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_ipc_v1.close size >= 80; 1.0 sco_result (*close)(sco_plugin* self, uint64_t channel);
Marks the channel closed for the peer and unmaps it. SCO_NOT_FOUND: no such channel.
Host owns mapping/channel; data copied via host staging buffers. No allocation transfer except borrowed view, never free it. Any thread; per-channel lock during copy. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown/non-owned channel: NOT_FOUND; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation; close/ordinary unload/non-retained crash cleanup marks closed and unmaps channels. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.

Source: sco_net.h, implementation, layout pin.

Publication also exposes sco.net capability. No active session is different from no service: registrations work offline, is_active/self_peer return 0, get_peers succeeds with zero peers, sends return UNAVAILABLE. No plugin method opens/joins/leaves a session. Session-scoped peer IDs are opaque; host ID is 1. Channel name at most 64 bytes, under own plugin id; 32 channels/plugin. Payload max is 1,200 unreliable or 262,144 reliable bytes. Defaults: 256 messages and 524,288 bytes/plugin/second, product-adjustable; quota overflow drops send. Reliable channel ordering/delivery semantics apply to an established session, not a guarantee that queued sends survive disconnection or unload. Messages are not encrypted: do not send secrets. See network messages.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_net_v1.is_active size >= 16; 1.0 int (*is_active)(void);
1 while a session is up (hosting, or joined with the channel table received), else 0.
Caller buffers; sends copied, callbacks borrow buf for call only. Host owns channels/messages; no allocation transfer. Any thread; callbacks game thread. Callbacks may call any method in this table. Absent table: query_service NOT_FOUND. Stopped result methods: UNAVAILABLE; self-taking methods reject invalid/released self with BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No delivery cancellation API; ordinary unload/non-retained crash cleanup drops channels and queued messages. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_net_v1.get_peers size >= 24; 1.0 sco_result (*get_peers)(sco_net_peer* out, uint32_t* inout_count);
The session’s peers, self first, then by id. *inout_count holds out’s capacity on entry (out may be NULL with 0) and the number of peers on return; up to the capacity are written. SCO_TOO_MANY: more peers than the capacity (the first ones were written). SCO_OK with 0 when no session is active. SCO_BAD_ARG: inout_count NULL, or out NULL with a nonzero capacity. Element-count handshake, not bytes: writes min(capacity,total) and returns total in inout_count; no session means OK/0.
Caller buffers; sends copied, callbacks borrow buf for call only. Host owns channels/messages; no allocation transfer. Any thread; callbacks game thread. Callbacks may call any method in this table. Absent table: query_service NOT_FOUND. Stopped result methods: UNAVAILABLE; self-taking methods reject invalid/released self with BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No delivery cancellation API; ordinary unload/non-retained crash cleanup drops channels and queued messages. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_net_v1.get_peer_name size >= 32; 1.0 sco_result (*get_peer_name)(uint64_t peer_id, char* buf, uint32_t cap);
Copies the peer’s chosen name (UTF-8) into buf, NUL-terminated, cut to cap - 1 bytes. SCO_NOT_FOUND: no such peer in the active session. SCO_BAD_ARG: buf NULL or cap 0.
Caller buffers; sends copied, callbacks borrow buf for call only. Host owns channels/messages; no allocation transfer. Any thread; callbacks game thread. Callbacks may call any method in this table. Absent table: query_service NOT_FOUND. Stopped result methods: UNAVAILABLE; self-taking methods reject invalid/released self with BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No delivery cancellation API; ordinary unload/non-retained crash cleanup drops channels and queued messages. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_net_v1.send_channel size >= 40; 1.0 sco_result (*send_channel)(sco_plugin* self, const char* channel_fqn, const void* buf, uint32_t len);
Queues len bytes on channel_fqn to the other peers (only the host for SCO_NET_TO_HOST). Copies buf; never blocks. SCO_BAD_ARG: a name outside this plugin’s id, len over the channel’s max_len, buf NULL with len > 0, or the wrong direction (a FROM_HOST channel from a joiner, a TO_HOST channel from the host). SCO_NOT_FOUND: this plugin hasn’t registered the channel. SCO_UNAVAILABLE: no active session. SCO_TOO_MANY: over the send quota, or the plugin’s outgoing queue is full; dropped. A message no other peer has a channel for is dropped silently.
Caller buffers; sends copied, callbacks borrow buf for call only. Host owns channels/messages; no allocation transfer. Any thread; callbacks game thread. Callbacks may call any method in this table. Absent table: query_service NOT_FOUND. Stopped result methods: UNAVAILABLE; self-taking methods reject invalid/released self with BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. OK means queued, not delivery acknowledgement. Quota/queue failure drops send; no matching peer channel drops silently; unload drops queued messages. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_net_v1.register_channel size >= 48; 1.0 sco_result (*register_channel)(sco_plugin* self, const char* channel_fqn, uint32_t flags, uint32_t max_len, sco_net_on_message cb, void* ctx);
Registers channel_fqn (“<this plugin id>.<name>”) with flags (SCO_NET_*) and the largest message this side accepts or sends, max_len (1..SCO_NET_MAX_UNREL, or 1..SCO_NET_MAX_RELIABLE with SCO_NET_RELIABLE); a longer incoming message is dropped before it is reassembled. cb runs on the game thread for each message; ctx is borrowed until unregister_channel or unload. Works with or without a session. SCO_BAD_ARG: a bad name, a name outside this plugin’s id, one already registered, bad flags (FROM_HOST with TO_HOST), a bad max_len or a NULL cb. SCO_TOO_MANY: SCO_NET_MAX_CHANNELS already.
Name copied; cb/ctx borrowed until unregister/unload. Callback buf valid for call only; host registry allocation. Any thread; callbacks game thread. Callbacks may call any method in this table. Absent table: query_service NOT_FOUND. Stopped result methods: UNAVAILABLE; self-taking methods reject invalid/released self with BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. Ordinary unregister/unload/non-retained crash cleanup removes the channel; incoming oversized payload dropped before reassembly; no callback cancel token. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_net_v1.unregister_channel size >= 56; 1.0 sco_result (*unregister_channel)(sco_plugin* self, const char* channel_fqn);
Removes one of this plugin’s channels: no callback runs for it after this returns (on the game thread; from another thread, one already running may finish). SCO_NOT_FOUND: not registered by this plugin.
Host drops owned channel; caller ctx can be freed on game thread after return; off-thread an already running callback may finish. Any thread; callbacks game thread. Callbacks may call any method in this table. Absent table: query_service NOT_FOUND. Stopped result methods: UNAVAILABLE; self-taking methods reject invalid/released self with BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. On game thread no later callback; off-thread callback already running may finish. Further transport timing unspecified.
sco_net_v1.self_peer size >= 64; 1.0 uint64_t (*self_peer)(void);
This player’s peer id in the active session (the host is 1), 0 when none.
Caller buffers; sends copied, callbacks borrow buf for call only. Host owns channels/messages; no allocation transfer. Any thread; callbacks game thread. Callbacks may call any method in this table. Absent table: query_service NOT_FOUND. Stopped result methods: UNAVAILABLE; self-taking methods reject invalid/released self with BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No delivery cancellation API; ordinary unload/non-retained crash cleanup drops channels and queued messages. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.

Source: sco_settings.h, implementation, layout pin.

Read-only declared settings; no setters. Names at most 31 bytes, strings at most 255 bytes excluding NUL. Scalar failure leaves output untouched; a string size handshake can change its size output while leaving its text buffer untouched. Values read from memory, not storage per call. settings.changed payload is borrowed and size-prefixed, dispatched on game thread after storing the value, for every plugin’s changes. See settings.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_settings_v1.get_bool size >= 16; 1.0 sco_result (*get_bool)(sco_plugin* self, const char* name, int32_t* out);
out = 0 or 1. SCO_BAD_ARG: not a bool setting, a NULL name or out, or a bad self.
Caller outputs; host owns settings; no allocation transfer. String/error copy may allocate internally. Any thread; memory reads under lock. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown setting: NOT_FOUND; wrong type: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous reads; unload withdraws settings. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_settings_v1.get_int size >= 24; 1.0 sco_result (*get_int)(sco_plugin* self, const char* name, int64_t* out);
SCO_BAD_ARG: not an int setting (a float or enum included).
Caller outputs; host owns settings; no allocation transfer. String/error copy may allocate internally. Any thread; memory reads under lock. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown setting: NOT_FOUND; wrong type: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous reads; unload withdraws settings. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_settings_v1.get_float size >= 32; 1.0 sco_result (*get_float)(sco_plugin* self, const char* name, double* out);
SCO_BAD_ARG: not a float setting.
Caller outputs; host owns settings; no allocation transfer. String/error copy may allocate internally. Any thread; memory reads under lock. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped: UNAVAILABLE; invalid/released self: BAD_ARG; unknown setting: NOT_FOUND; wrong type: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous reads; unload withdraws settings. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_settings_v1.get_string size >= 40; 1.0 sco_result (*get_string)(sco_plugin* self, const char* name, char* out, uint32_t* inout_size);
A string setting’s text, or an enum setting’s choice, with the size handshake.
Caller outputs; host owns settings; no allocation transfer. String/error copy may allocate internally. Any thread; memory reads under lock. Recursive reentrancy unspecified. Common settings errors; TOO_MANY reports required NUL-inclusive bytes without writing string; inout_size reset on other failure. Caller text untouched on failure. No cancellation entrypoint; synchronous reads; unload withdraws settings. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sco_settings_v1.last_error size >= 48; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The message of this plugin’s last failed call (“” if none), NUL-terminated, with the size handshake.
Caller outputs; host owns settings; no allocation transfer. String/error copy may allocate internally. Any thread; memory reads under lock. Recursive reentrancy unspecified. BAD_ARG invalid/released self or buffer; UNAVAILABLE stopped; TOO_MANY required bytes or allocation. Empty string if no recorded failure; diagnostic completeness unspecified. No cancellation entrypoint; synchronous reads; unload withdraws settings. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.

Renderer-neutral retained panels, host-owned service 1.1. Source: include/sco_widgets.h, src/widgets/widgets.cpp; design: widgets. This does not change the frozen sco_api ABI or the legacy sco.ui draw-context/hotkey route. Limits: 64 panels, 256 nodes/panel, 4096 live nodes, 256 items/node, 16 table columns. Strings are copied UTF-8, plain text; callbacks and context are borrowed. All methods/events are game-thread only. Events update retained state then dispatch under the owner guard; replacing/removing a panel invalidates pending generations. C is direct; C++ has scosdk/widgets.hpp; Lua has bounded sco.widgets tables and registry-rooted typed callbacks. C# is unsupported/deferred in #142, a follow-up to #139. The optional ImGui adapter is host-only; plugins never include it.

1.1 appends update_nodes, remove_nodes and capabilities (table 24 -> 48 bytes) and adds opt-in sco_widget_node_1_1 (104 bytes: tooltip, severity, LIST/TABLE paging) and sco_widget_event_1_1 (40 bytes: row). The 80-byte node and 32-byte event are unchanged, so 1.0 strides and size checks stay valid; a node below 104 bytes is a 1.0 node. Panels that hold a 1.1 node receive 1.1 events, including SCO_WIDGET_EVENT_PAGE; other panels keep 32-byte events. Render snapshots are rebuilt at most once per panel render pass, after a change. C# and Lua sco.widgets 1.1 routes are unsupported. Pins: tests/abi_widgets.c; host tests: tests/test_widgets11.cpp.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_widgets_v1.set_panel size >= 16; 1.0 sco_result (*set_panel)(sco_plugin* self, const char* id, const char* title, const sco_widget_node* nodes, uint32_t count, uint32_t node_stride, sco_widget_event_fn fn, void* ctx);
Atomically adds/replaces an owned complete preorder tree. ID/title <=63 bytes; 1..256 nodes, aligned stride >=80 and node size within stride. Unique nonzero node IDs, parent 0 or preceding active ROW/COLUMN; all subtrees contiguous. Copies valid UTF-8 labels/text/items <=255 bytes; 256 items/node and 16 table columns. Zero unused fields; finite/ranged numeric values and valid selections. Failure preserves old tree/callback.
Host deep-copies tree/strings on success; fn/ctx borrowed until successful replacement/removal or ordinary owner release. No allocation transfer. Game thread only; WRONG_THREAD elsewhere. Callbacks game thread under owner callout guard. OK; WRONG_THREAD off game thread; UNAVAILABLE stopped service/host; BAD_ARG malformed owner/ID/title/tree/size/stride/data; TOO_MANY limits or allocation failure. Failure atomic. Successful replacement/removal and ordinary owner release discard stale-generation events and end borrowed callbacks. Fault guard stops delivery; retained-provider faults skip ordinary resource release until restart. No separate cancel token.
sco_widgets_v1.remove_panel size >= 24; 1.0 sco_result (*remove_panel)(sco_plugin* self, const char* id);
Removes an owned panel. Absent ID returns NOT_FOUND; success ends pending callbacks for that generation and permits immediate ctx destruction, including inside its callback. Failure preserves the panel.
Host releases copied tree and borrowed callback registration, never frees plugin ctx; caller may free ctx after success. Game thread only; WRONG_THREAD elsewhere. Callbacks game thread under owner callout guard. OK; WRONG_THREAD off game thread; UNAVAILABLE stopped service/host; BAD_ARG invalid/released owner or malformed ID; NOT_FOUND absent owned panel. Failure leaves registration unchanged. Successful replacement/removal and ordinary owner release discard stale-generation events and end borrowed callbacks. Fault guard stops delivery; retained-provider faults skip ordinary resource release until restart. No separate cancel token.
sco_widgets_v1.update_nodes size >= 32; 1.1 sco_result (*update_nodes)(sco_plugin* self, const char* panel_id, const sco_widget_node* nodes, uint32_t count, uint32_t node_stride);
Atomically replaces or inserts one subtree of an owned panel. nodes[0] is the root and every later node descends from it; node, stride and string rules as set_panel, with 1.0 or 1.1 node sizes. An existing root ID is replaced in place and keeps its parent; a new root ID becomes the last child of parent 0 or an existing ROW/COLUMN. IDs must not collide with nodes outside the replaced subtree; 256 nodes/panel and 4096 live nodes after the change. Failure preserves the tree.
Host deep-copies the subtree on success; the panel’s fn/ctx stay unchanged and borrowed. No allocation transfer. Game thread only; WRONG_THREAD elsewhere. Callbacks game thread under owner callout guard. OK; WRONG_THREAD off game thread; UNAVAILABLE stopped service/host; BAD_ARG malformed owner/ID/tree/size/stride/data or a moved root; NOT_FOUND absent owned panel; TOO_MANY limits or allocation failure. Failure atomic. Success starts a new generation: remaining events of the current pass drop and the change renders next pass. Owner release and fault rules as set_panel. No separate cancel token.
sco_widgets_v1.remove_nodes size >= 40; 1.1 sco_result (*remove_nodes)(sco_plugin* self, const char* panel_id, const uint32_t* node_ids, uint32_t count);
Atomically removes 1..256 listed nodes of an owned panel, each with its subtree. Every ID must be nonzero and present; a removal that would empty the panel is refused (use remove_panel). The ID array is read during the call only. Failure preserves the tree.
Host releases the removed copies; caller keeps the ID array. fn/ctx unchanged. No allocation transfer. Game thread only; WRONG_THREAD elsewhere. Callbacks game thread under owner callout guard. OK; WRONG_THREAD off game thread; UNAVAILABLE stopped service/host; BAD_ARG invalid owner/ID, NULL or empty array, zero ID or emptied panel; NOT_FOUND absent owned panel or node ID; TOO_MANY more than 256 IDs. Failure atomic. Success starts a new generation: remaining events of the current pass drop and the change renders next pass. Owner release and fault rules as set_panel. No separate cancel token.
sco_widgets_v1.capabilities size >= 48; 1.1 sco_result (*capabilities)(sco_plugin* self, uint32_t* caps);
caps[0] is the array length on entry (at least 2) and the number of elements written on success; the host fills the SCO_WIDGETS_CAP_* indices it knows up to that length: feature bits, then the running limits for panels, nodes/panel, live nodes, items, columns, text bytes and events per pass. 1.1 defines 9 elements. Failure writes nothing.
Caller-owned array written in place. No allocation transfer. Game thread only; WRONG_THREAD elsewhere. No callbacks. OK; WRONG_THREAD off game thread; UNAVAILABLE stopped service/host; BAD_ARG invalid/released owner, NULL caps or caps[0] below 2. Synchronous query; nothing to release. No cancellation entrypoint.

Source: sco_ui.h, implementation, layout pin.

IDs/titles at most 63 bytes, badge 15, chord 31, hotkey arguments 16, each stored argument string 255. Tabs sort by order then registration; overlays by registration. The product, not this registry, renders and supplies the frame context (borrowed during draw). Draw faults disable the owning plugin. Unregister on another thread does not wait for current draw: defer ctx deletion with run_on_game_thread. See UI for chord grammar/reserved keys and renderer integration. normalize_chord does not require a live UI service once a pointer was obtained (implementation observation), unlike self-taking mutations.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_ui_v1.register_tab size >= 16; 1.0 sco_result (*register_tab)(sco_plugin* self, const char* id, const char* title, int32_t order, sco_ui_draw_fn draw, void* ctx);
Adds tab id with its title (1-63 bytes) at order: the product shows tabs by ascending order, ties in registration order. SCO_BAD_ARG: a bad or taken id, an id outside this plugin, a bad title, draw NULL. SCO_TOO_MANY: the host’s tab table is full.
Strings/arguments copied; draw/ctx borrowed until unregister/unload. Host owns registry; no allocation transfer. Any thread; draw callbacks game thread. Other recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. unregister_tab/ordinary unload/non-retained crash cleanup ends draws; off-thread unregister does not join an already-running draw. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.unregister_tab size >= 24; 1.0 sco_result (*unregister_tab)(sco_plugin* self, const char* id);
Removes one of this plugin’s tabs, and its badge. SCO_NOT_FOUND: it has none by that id.
Removes own tab and badge. Free ctx immediately on game thread, including inside draw; elsewhere defer freeing via run_on_game_thread. Any thread; allowed inside own draw. Other reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation API; unregister/unbind removes registration; ordinary unload/non-retained crash cleanup withdraws all UI. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.set_badge size >= 32; 1.0 sco_result (*set_badge)(sco_plugin* self, const char* tab_id, const char* text);
Sets the short text the product shows beside the tab title (“3”, “new”; at most 15 bytes); NULL or “” clears it. SCO_NOT_FOUND: this plugin has no tab by that id.
Strings/arguments copied; draw/ctx borrowed until unregister/unload. Host owns registry; no allocation transfer. Any thread; draw callbacks game thread. Other recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation API; unregister/unbind removes registration; ordinary unload/non-retained crash cleanup withdraws all UI. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.register_overlay size >= 40; 1.0 sco_result (*register_overlay)(sco_plugin* self, const char* id, sco_ui_draw_fn draw, void* ctx);
Adds overlay id; overlays draw in registration order. SCO_BAD_ARG / SCO_TOO_MANY as for register_tab.
Strings/arguments copied; draw/ctx borrowed until unregister/unload. Host owns registry; no allocation transfer. Any thread; draw callbacks game thread. Other recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. unregister_overlay/ordinary unload/non-retained crash cleanup ends draws; off-thread unregister does not join an already-running draw. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.unregister_overlay size >= 48; 1.0 sco_result (*unregister_overlay)(sco_plugin* self, const char* id);
SCO_NOT_FOUND: this plugin has no overlay by that id.
Removes own overlay. Free ctx immediately on game thread, including inside draw; elsewhere defer freeing via run_on_game_thread. Any thread; allowed inside own draw. Other reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation API; unregister/unbind removes registration; ordinary unload/non-retained crash cleanup withdraws all UI. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.bind_hotkey size >= 56; 1.0 sco_result (*bind_hotkey)(sco_plugin* self, const char* chord, const char* command, const sco_arg* args, uint32_t nargs);
Binds chord to the command name (“<x>.<y>”; any plugin’s or a host feature’s) with nargs arguments (args may be NULL with 0), which are copied, strings included. When the product sees the chord it invokes the command through the command registry, as invoke would, with this plugin as the caller; the command needn’t exist yet. SCO_BAD_ARG: a bad chord or command name, a bad argument, or the chord taken: bound already (by anyone, this plugin included) or reserved by the product; last_error names the owner. SCO_TOO_MANY: the host’s hotkey table is full.
Strings/arguments copied; draw/ctx borrowed until unregister/unload. Host owns registry; no allocation transfer. Any thread; draw callbacks game thread. Other recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. unbind_hotkey/ordinary unload/non-retained crash cleanup ends binding; cancellation of an already-issued command unspecified. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.unbind_hotkey size >= 64; 1.0 sco_result (*unbind_hotkey)(sco_plugin* self, const char* chord);
SCO_NOT_FOUND: this plugin has no binding on that chord (a bad chord included).
Strings/arguments copied; draw/ctx borrowed until unregister/unload. Host owns registry; no allocation transfer. Any thread; draw callbacks game thread. Other recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation API; unregister/unbind removes registration; ordinary unload/non-retained crash cleanup withdraws all UI. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.normalize_chord size >= 72; 1.0 sco_result (*normalize_chord)(const char* chord, char* out, uint32_t* inout_size);
Writes chord’s normalized form, NUL-terminated, with the raw-handler size handshake (*inout_size: capacity in; bytes written, or needed with SCO_TOO_MANY, out). SCO_BAD_ARG: not a chord. No plugin handle needed; any thread.
Strings/arguments copied; draw/ctx borrowed until unregister/unload. Host owns registry; no allocation transfer. Any thread; draw callbacks game thread. Other recursive reentrancy unspecified. BAD_ARG invalid chord/buffer; TOO_MANY required bytes/allocation. Pure normalization needs no self; stopped-service refusal unspecified (implementation does not test started). No in-flight cancellation API; unregister/unbind removes registration; ordinary unload/non-retained crash cleanup withdraws all UI. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.
sco_ui_v1.last_error size >= 80; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The message of this plugin’s last refused call (“” if none), NUL-terminated, with the size handshake.
Strings/arguments copied; draw/ctx borrowed until unregister/unload. Host owns registry; no allocation transfer. Any thread; draw callbacks game thread. Other recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; stopped self-taking methods: UNAVAILABLE; invalid/released self: BAD_ARG; allocation exceptions: TOO_MANY. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation API; unregister/unbind removes registration; ordinary unload/non-retained crash cleanup withdraws all UI. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Guarded draws stop, but snapshots and chord reservations remain.

Source: sco_ui_surfaces.h, implementation, layout pin; host tests: tests/test_surfaces.cpp. Renderer-neutral placement of sco.widgets panels, host-owned service 1.0: a 2D HUD rectangle, a camera-facing 3D billboard or a world-anchored 3D quad. The host keeps a validated registry (owner, kind, pose, panel id) and draws nothing; the product’s renderer reads it through sco/surfaces.h and projects each surface itself (UI: Surfaces documents the billboard and quad math). Payloads are size-prefixed sco_surface_desc (16 bytes) and sco_surface_pose (112 bytes); sizes must cover the 1.0 structs, larger tails are ignored. Limits: 32 surfaces per plugin, 256 in all, panel id 63 bytes, 3D extent 1000 m, max distance 1e7 m, coordinates 1e12 m, unit-vector tolerance 1e-3. Ids are host-assigned, nonzero and never reused while the host runs. Owner cleanup (unload, crash) rides sco.ui’s release hook, so the host publishes this service only while sco.ui runs. C is direct; C++ has scosdk/ui_surfaces.hpp. C# and Lua sco.ui.surfaces routes are unsupported.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sco_ui_surfaces_v1.register_surface size >= 16; 1.0 sco_result (*register_surface)(sco_plugin* self, const sco_surface_desc* desc, uint32_t* out_id);
Adds a HUD_2D, BILLBOARD_3D or QUAD_3D surface showing one of the caller’s sco.widgets panels and writes its nonzero, never-reused id. desc and pose sizes must cover the 1.0 structs (larger tails ignored); every double finite; per-kind rules: HUD centre and size in viewport fractions with zero normal/up, billboard zero normal and unit up, quad unit normal and unit up perpendicular within 1e-3; 3D extents (0, 1000] m, max_distance [0, 1e7] m (0 = no limit), coordinates within 1e12 m; flags 0 or OCCLUDE_RAYCAST (3D only); panel_id “.” at most 63 bytes. 32 surfaces per plugin, 256 in all. Failure leaves the registry and *out_id unchanged.
Host copies the pose and panel_id on success; caller keeps desc, pose and the string. No allocation transfer. Any thread; registry lock held only for the copy. No callbacks. OK; BAD_ARG invalid/released self, NULL or short desc/pose, unknown kind, any field outside the rules, NULL out_id; TOO_MANY per-plugin or host limit, id space exhausted or allocation failure; UNAVAILABLE stopped service. last_error names the refused field. No cancellation entrypoint; synchronous. Unregister, plugin unload or crash (through the sco.ui release hook) and service Stop withdraw the surface.
sco_ui_surfaces_v1.update_surface_pose size >= 24; 1.0 sco_result (*update_surface_pose)(sco_plugin* self, uint32_t id, const sco_surface_pose* pose);
Replaces the pose and panel of one of the caller’s surfaces, checked against the kind it was registered with (the register_surface rules). Failure leaves the old pose.
Host copies the pose and panel_id on success; caller keeps pose and the string. No allocation transfer. Any thread; registry lock held only for the copy. No callbacks. OK; NOT_FOUND no surface of this plugin by that id; BAD_ARG invalid/released self, NULL or short pose, any field outside the rules for the kind; TOO_MANY allocation failure; UNAVAILABLE stopped service. No cancellation entrypoint; synchronous. The surface keeps its id and kind; unload, crash and Stop withdraw it.
sco_ui_surfaces_v1.unregister_surface size >= 32; 1.0 sco_result (*unregister_surface)(sco_plugin* self, uint32_t id);
Removes one of the caller’s surfaces. Its id is not reused.
Host releases its copy; nothing of the caller is retained. No allocation transfer. Any thread; registry lock held only for the copy. No callbacks. OK; NOT_FOUND no surface of this plugin by that id; BAD_ARG invalid/released self; UNAVAILABLE stopped service. No cancellation entrypoint; synchronous and final.
sco_ui_surfaces_v1.last_error size >= 40; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The message of this plugin’s last refused call (“” if none), NUL-terminated, with the raw-handler size handshake (*inout_size: capacity in; bytes written, or needed with TOO_MANY, out).
Caller-owned buffer written in place. No allocation transfer. Any thread; registry lock held only for the copy. No callbacks. OK; TOO_MANY buffer too small (*inout_size = bytes needed); BAD_ARG invalid/released self, NULL inout_size or NULL out with nonzero capacity; UNAVAILABLE stopped service. Diagnostic completeness unspecified. No cancellation entrypoint; synchronous read. Unload and Stop clear the message.

Source: sc_spatial.h, implementation, layout pin.

All six methods return 1 answered / 0 unavailable or invalid, leaving outputs untouched on 0. Double positions in metres; rotation quaternion x,y,z,w. Zone 0 is world for conversions, not for zone_name; zone IDs are volatile streaming handles. Every query reads game state afresh. Return 0 is not distinguishable as a typed result or diagnostic error through this table.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_spatial_v1.player_pose size >= 16; 1.0 int (*player_pose)(double pos[3], double rot_xyzw[4], uint64_t* zone_id);
Your position (pos, metres) and orientation (rot, a unit quaternion in the game’s (x, y, z, w) order) in the zone you’re in, and that zone’s id.
Caller buffers; IDs are borrowed session values, not pointers. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; wrong thread/missing teleport or unreadable game state: 0. Outputs only written on 1. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.
sc_spatial_v1.zone_of_entity size >= 24; 1.0 int (*zone_of_entity)(uint64_t entity_id, uint64_t* zone_id);
The id of the zone an entity is in (your ship’s, a spawned entity’s).
Caller buffers; IDs are borrowed session values, not pointers. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; wrong thread/missing teleport or unreadable game state: 0. Outputs only written on 1. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.
sc_spatial_v1.local_to_world size >= 32; 1.0 int (*local_to_world)(uint64_t zone_id, const double local[3], double world[3]);
A position in zone zone_id to the world frame, and back.
Caller buffers; IDs are borrowed session values, not pointers. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; wrong thread/missing teleport or unreadable game state: 0. Outputs only written on 1. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.
sc_spatial_v1.world_to_local size >= 40; 1.0 int (*world_to_local)(uint64_t zone_id, const double world[3], double local[3]);
Converts world[3] doubles to zone-local local[3] doubles; zone 0 is world; outputs written only on return 1.
Caller buffers; IDs are borrowed session values, not pointers. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; wrong thread/missing teleport or unreadable game state: 0. Outputs only written on 1. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.
sc_spatial_v1.zone_to_zone size >= 48; 1.0 int (*zone_to_zone)(uint64_t from, uint64_t to, const double in[3], double out[3]);
A position in zone from to zone to (either may be 0, the world).
Caller buffers; IDs are borrowed session values, not pointers. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; wrong thread/missing teleport or unreadable game state: 0. Outputs only written on 1. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.
sc_spatial_v1.zone_name size >= 56; 1.0 int (*zone_name)(uint64_t zone_id, char* out, uint32_t cap);
The zone’s name (“OOC_Stanton_2b_Daymar”), NUL-terminated and cut to fit cap bytes.
Caller buffers; IDs are borrowed session values, not pointers. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; wrong thread/missing teleport or unreadable game state: 0. Outputs only written on 1. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.

Source: sc_spawn.h, implementation, layout pin.

1.0 is 40 bytes; 1.1 appends entity_alive (48); 1.2 appends mover/spawn_as (64). Game-thread failures return 0/ID 0 or a borrowed reason string, not sco_result. Fresh ID exists before streaming completes; alive must be checked on later ticks. spawn_as ownership is movement bookkeeping, not the actor/entity services’ auto-despawn guarantee. Its implementation can spawn successfully and then fail tracking; do not treat every non-NULL reason as “nothing spawned.” Whether a product registers player vehicles is product-specific, not established by this table or older header commentary. See spawn service.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_spawn_service_v1.spawn_near_player size >= 16; 1.0 const char* (*spawn_near_player)(const char* entity_class, const double offset[3], uint64_t* out_id);
Spawns an entity class (a ship, a vehicle, an item) at offset metres from you, in your current zone’s frame. NULL on success with *out_id = the new entity id; else the reason. The id is final at once, but the entity streams in later: a few seconds, up to a minute for a big ship. entity_alive(id) answers 1 once it has. An entity spawned here belongs to no plugin: set_entity_transform refuses it. Use spawn_as for an entity you will move. Implementation initializes out_id to 0 before failure checks.
Spawned entity belongs to no plugin; out ID caller-owned. Failure reason is borrowed; returned string lifetime unspecified; never free. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; requires spawner rows (product gate spawn.ship). Wrong thread or missing readiness: 0 or borrowed reason string. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; asynchronous streaming is not cancelled by this table.
sc_spawn_service_v1.class_exists size >= 24; 1.0 int (*class_exists)(const char* entity_class);
1 if entity_class is a spawnable class on this game build, else 0.
IDs are session values, not pointers; caller outputs. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; requires spawner rows (product gate spawn.ship). Wrong thread or missing readiness: 0 or borrowed reason string. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; asynchronous streaming is not cancelled by this table.
sc_spawn_service_v1.local_player_id size >= 32; 1.0 uint64_t (*local_player_id)(void);
Your entity id, or 0 before you’ve spawned.
IDs are session values, not pointers; caller outputs. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; requires spawner rows (product gate spawn.ship). Wrong thread or missing readiness: 0 or borrowed reason string. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; asynchronous streaming is not cancelled by this table.
sc_spawn_service_v1.player_ship_id size >= 40; 1.0 uint64_t (*player_ship_id)(void);
The ship you’re aboard, or 0.
IDs are session values, not pointers; caller outputs. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; requires spawner rows (product gate spawn.ship). Wrong thread or missing readiness: 0 or borrowed reason string. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; asynchronous streaming is not cancelled by this table.
sc_spawn_service_v1.entity_alive size >= 48; 1.1 int (*entity_alive)(uint64_t entity_id);
1.1. 1 while the entity id resolves in the game (spawned and streamed in), else 0; 0 for id 0. Asked afresh on every call. A 1.0 table ends before this field: call it only when size > offsetof(sc_spawn_service_v1, entity_alive).
IDs are session values, not pointers; caller outputs. No allocation transfer; internal allocation unspecified. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; requires spawner rows (product gate spawn.ship). Wrong thread or missing readiness: 0 or borrowed reason string. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; asynchronous streaming is not cancelled by this table.
sc_spawn_service_v1.set_entity_transform size >= 56; 1.2 int (*set_entity_transform)(sco_plugin* self, uint64_t entity_id, uint64_t zone_id, const double pos[3], const double rot[4]);
1.2. Moves and turns an entity: pos (metres) and rot (a unit quaternion, x y z w, the order of sc_spatial.h’s player_pose) in zone zone_id’s frame. zone_id 0 is the world (root) frame; any other id is that zone’s local frame (ids from teleport.spatial: player_pose, zone_of_entity). The entity stays in the zone it’s in; the pose is converted to that zone’s frame. 1 on success, 0 on failure: wrong thread, a null pointer, rot not finite or of zero length (it is normalized), an id that isn’t streamed in, a zone the game pack can’t place, or an entity you may not move; the game pack logs the reason (“[game] warning: set_entity_transform(<id>) -> 0: <reason>”) once per id and reason. A fresh spawn takes seconds to stream in and answers 0 until then: check entity_alive(id) first, and try again on a later tick while it answers 0. You may move: - an entity spawned through spawn_as with your own self, while your plugin is loaded (unloading forgets them; spawn_near_player and the spawn.ship command count for nobody); - your player’s own vehicle once the product has registered it as retrieved or delivered by ATC (sco::game::services::RegisterPlayerVehicle; registration depends on the product). self is your plugin’s handle, as sco_plugin_load received it. A 1.1 table ends before this field: call it only when the table is non-null, size >= offsetof(sc_spawn_service_v1, set_entity_transform) + sizeof(table->set_entity_transform), and table->set_entity_transform is non-null.
May move only own spawn_as entities or player vehicles registered by product; input arrays borrowed during call; no allocation transfer. Game thread only; recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; requires spawner rows (product gate spawn.ship). Wrong thread or missing readiness: 0 or borrowed reason string. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; asynchronous streaming is not cancelled by this table.
sc_spawn_service_v1.spawn_as size >= 64; 1.2 const char* (*spawn_as)(sco_plugin* self, const char* entity_class, const double offset[3], uint64_t* out_id);
1.2. spawn_near_player, recorded as yours (self, as sco_plugin_load received it), so set_entity_transform lets you move the entity. Same answers as spawn_near_player, plus “bad argument” for a null self. Same size check as set_entity_transform: size > offsetof(sc_spawn_service_v1, spawn_as). Implementation may return tracking-failure reason after successful spawn with out_id nonzero.
Movement ownership recorded for self, forgotten on unload; this is not an automatic despawn promise. Failure reason borrowed; lifetime unspecified; never free. Game thread only; recursive reentrancy unspecified. NULL means spawn and tracking succeeded; non-NULL borrowed reason otherwise. Tracking failure can occur after spawn, with nonzero out ID and live unowned/unmovable entity; failure is not rollback. No cancellation entrypoint; asynchronous streaming is not cancelled by this table.

Source: sc_actors.h, implementation, layout pin.

1.0 ends after last_error at 40 bytes; 1.1 appends health and state (56). Each operation has its named game.actors capability; state remains off pending in-game verification. NPCs owned here are removed on ordinary unload/non-retained crash cleanup; retained-provider faults skip release hooks and require restart. The quota counts alive and being removed (1,024 total). Spawning refuses without a release hook/removal readiness. last_error(NULL) is shared no-self query diagnostic, not per querying plugin. Health maximum is 0 meaning unknown, not zero capacity.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_actors_v1.local_player size >= 16; 1.0 sco_result (*local_player)(uint64_t* out_actor_id, uint64_t* out_entity_id);
Your player: *out_actor_id, the id the game’s client player record names your actor by (the id the game resolves to your actor), and *out_entity_id, your entity’s id (the same as spawn.entities’ local_player_id; use it with teleport.spatial and spawn.entities). Both 0 on failure. Either pointer may be NULL to skip it, not both. SCO_NOT_FOUND: you haven’t spawned yet. Read-only: no self; a failure’s reason is last_error(NULL, …).
Caller buffers; no allocation crosses boundary. Host owns NPC tracking; entity IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; invalid/released self: BAD_ARG. See method detail for game failures. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned NPCs removed on ordinary unload/non-retained crash cleanup; despawn starts deferred removal. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_actors_v1.spawn_npc size >= 24; 1.0 sco_result (*spawn_npc)(sco_plugin* self, const char* archetype_class, uint64_t zone_id, const double pos[3], uint64_t* out_id);
Spawns an NPC of archetype_class (an entity class name, as in sc-offline’s npcs.txt) at pos in zone zone_id’s local frame, facing the zone’s axes. *out_id = the new entity id, 0 on failure. The id is final at once; the NPC streams in a few seconds later. The NPC is yours (see Ownership above). SCO_BAD_ARG: a null or released self, a null class, pos or out_id, zone 0, or a position that isn’t finite. SCO_NOT_FOUND: the zone isn’t streamed in, or the class doesn’t exist on this game build. SCO_TOO_MANY: SC_ACTORS_MAX_NPCS are alive. SCO_FAILED: the game refused or faulted.
Caller buffers; no allocation crosses boundary. Host owns NPC tracking; entity IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; invalid/released self: BAD_ARG. See method detail for game failures. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned NPCs removed on ordinary unload/non-retained crash cleanup; despawn starts deferred removal. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_actors_v1.despawn size >= 32; 1.0 sco_result (*despawn)(sco_plugin* self, uint64_t entity_id);
Removes an NPC you spawned with spawn_npc. SCO_OK starts the removal: the NPC leaves the world within a few seconds (one that hasn’t streamed in yet goes once it has), and the id is no longer yours. SCO_NOT_FOUND: not an NPC you spawned here, or despawned already.
Caller buffers; no allocation crosses boundary. Host owns NPC tracking; entity IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; invalid/released self: BAD_ARG. See method detail for game failures. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned NPCs removed on ordinary unload/non-retained crash cleanup; despawn starts deferred removal. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_actors_v1.last_error size >= 40; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for self’s last failed call (“” if none), NUL-terminated, with the size handshake (*inout_size: capacity in; bytes written, or needed with SCO_TOO_MANY, out). self NULL: the last failure of a call made without a plugin handle (local_player). Any thread.
Caller buffers; no allocation crosses boundary. Host owns NPC tracking; entity IDs are session values. Internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid/released non-NULL self or buffer; TOO_MANY required bytes. NULL self selects no-self failures; stopped-service refusal unspecified (no started check). No in-flight cancellation entrypoint; owned NPCs removed on ordinary unload/non-retained crash cleanup; despawn starts deferred removal. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_actors_v1.health size >= 48; 1.1 sco_result (*health)(uint64_t id, float* out_cur, float* out_max);
1.1. The health pool of the actor whose entity id is id: your player’s (local_player’s entity id) or an NPC’s (spawn_npc’s id), once it has streamed in. *out_cur = the game’s HealthPool stat in its own units. *out_max = 0: the maximum isn’t read yet, 0 means unknown (the field is here so a later game pack can fill it without a new table). Either pointer may be NULL to skip it, not both. Read-only: no self; a failure’s reason is last_error(NULL, …). SCO_NOT_FOUND: id isn’t streamed in or isn’t an actor. SCO_UNAVAILABLE: game.actors.health isn’t ready. SCO_BAD_ARG: both pointers NULL. SCO_FAILED: the game faulted. Implementation: outputs zeroed before failure checks; id 0 BAD_ARG. Maximum 0 is unknown.
Caller buffers; no allocation crosses boundary. Host owns NPC tracking; entity IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; invalid/released self: BAD_ARG. See method detail for game failures. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned NPCs removed on ordinary unload/non-retained crash cleanup; despawn starts deferred removal. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_actors_v1.state size >= 56; 1.1 sco_result (*state)(uint64_t id, uint32_t* out_state);
1.1. *out_state = an sc_actor_state. Not published yet: SCO_UNAVAILABLE until game.actors.state is ready. Implementation: output initialized to 0; NULL out BAD_ARG, wrong thread WRONG_THREAD; valid call still UNAVAILABLE, not an ALIVE answer.
Caller buffers; no allocation crosses boundary. Host owns NPC tracking; entity IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; invalid/released self: BAD_ARG. See method detail for game failures. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned NPCs removed on ordinary unload/non-retained crash cleanup; despawn starts deferred removal. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.

Source: sc_vehicles.h, implementation, layout pin.

Capability seats gates player_ship/seats/seat_occupant; seat gates seat/eject; flight_ready gates power_on. sc_vehicle_seat stride is frozen at 96 bytes; name is 64 bytes including NUL. Missing USABLE_KNOWN means unknown usability, not false; an occupied but undecodable actor can have occupant_id 0. Mutations check permitted actor/vehicle ownership, not arbitrary game objects. Per-method BAD_ARG checks exist, but these implementations do not uniformly test the released-owner marker: do not infer the host API’s post-unload rejection guarantee. Error outputs on WRONG_THREAD are not uniformly zeroed. See vehicles.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_vehicles_v1.player_ship size >= 16; 1.0 sco_result (*player_ship)(uint64_t* out_ship);
The ship you’re aboard (standing or seated in it). SCO_OK and the id; SCO_NOT_FOUND when you’re in no ship; SCO_UNAVAILABLE before you’ve spawned or without the capability. game.vehicles.seats.
Caller outputs; IDs/seat indexes are streaming-session values. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; self validity as checked by implementation; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; game acceptance need not mean action completed.
sc_vehicles_v1.seats size >= 24; 1.0 sco_result (*seats)(uint64_t ship, sc_vehicle_seat* out, uint32_t max, uint32_t* out_count, uint32_t* out_more);
Fills out[0..max) with ship’s seats in the game’s order and sets *out_count to how many were written and *out_more to 1 when the ship has more than that (else 0). out may be NULL when max is 0 (then *out_more says whether the ship has any). SCO_NOT_FOUND: ship isn’t streamed in or isn’t a vehicle. game.vehicles.seats.
Caller outputs; IDs/seat indexes are streaming-session values. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; self validity as checked by implementation; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; game acceptance need not mean action completed.
sc_vehicles_v1.seat_occupant size >= 32; 1.0 sco_result (*seat_occupant)(uint64_t ship, uint32_t seat_index, uint64_t* out_actor);
out_actor = the actor in seat seat_index of ship, or 0 when the seat is empty. SCO_FAILED when the seat is occupied but the game pack can’t tell by whom (last_error has the raw field); SCO_NOT_FOUND for a ship that isn’t streamed in or an index past the last seat. game.vehicles.seats.
Caller outputs; IDs/seat indexes are streaming-session values. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; self validity as checked by implementation; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; game acceptance need not mean action completed.
sc_vehicles_v1.seat size >= 40; 1.0 sco_result (*seat)(sco_plugin* self, uint64_t actor, uint64_t ship, uint32_t seat_index);
Puts actor into seat seat_index of ship, moving it out of any seat it’s in first. You may seat your player’s own actor, or an actor your plugin spawned through spawn.entities’ spawn_as or game.actors’ spawn_npc (while your plugin is loaded); anything else is SCO_BAD_ARG. SCO_FAILED: the seat isn’t usable (no SC_SEAT_USABLE), someone else is in it (nobody is evicted), the actor isn’t streamed in yet or has no seat link, or the game faulted. SCO_OK means the game accepted the link; it takes effect within a second or two: check seat_occupant() on a later tick, and call seat() again if it didn’t take. game.vehicles.seat.
Caller outputs; IDs/seat indexes are streaming-session values. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; self validity as checked by implementation; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; game acceptance need not mean action completed.
sc_vehicles_v1.eject size >= 48; 1.0 sco_result (*eject)(sco_plugin* self, uint64_t actor);
Takes actor out of the seat it’s in (same rule on whose actor as seat()). SCO_FAILED when it isn’t seated. game.vehicles.seat.
Caller outputs; IDs/seat indexes are streaming-session values. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; self validity as checked by implementation; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; game acceptance need not mean action completed.
sc_vehicles_v1.power_on size >= 56; 1.0 sco_result (*power_on)(sco_plugin* self, uint64_t ship);
Sends the game’s Flight Ready event to ship’s pilot dashboard, as pressing R in the pilot seat does. You may power on the ship you’re aboard, your player’s own registered vehicles and ships your plugin spawned through spawn_as; anything else is SCO_BAD_ARG. SCO_FAILED while the ship has no dashboard streamed in yet (a big ship takes up to 20 s): try again on a later tick. game.vehicles.flight_ready.
Caller outputs; IDs/seat indexes are streaming-session values. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; self validity as checked by implementation; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; game acceptance need not mean action completed.
sc_vehicles_v1.last_error size >= 64; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for the last failed call (“” if none), NUL-terminated, with sco.storage’s size handshake: *inout_size is out’s capacity on entry and the bytes written (NUL included) on SCO_OK, or the bytes needed on SCO_TOO_MANY. out may be NULL when *inout_size is 0. On the game thread: the newer of your own last failed call (functions with self) and the last failed query (functions without self, by any plugin); ask right after the call. On another thread: the last refusal on that thread. Any thread.
Caller outputs; IDs/seat indexes are streaming-session values. No allocation transfer; internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid buffer; TOO_MANY required bytes. Game thread selects newer own/shared-query error; other threads their refusal. self validity and stopped-service rejection unspecified; implementation does not enforce them. No in-flight cancellation entrypoint; game acceptance need not mean action completed.

Source: sc_creative.h, implementation, layout pin.

Capabilities: god_mode, fly, ammo, ship_ammo; speed additionally needs the speed-field rows. Toggles are global to the local player but owned by the last plugin to enable them; another plugin can turn them off or take ownership. Enabling refuses without a release hook. Owned speed restores on ordinary release, not on a retained-provider fault; there is no speed-restore method. last_error is any-thread despite the header’s blanket game-thread statement. Implementation chooses newer own/shared-query error on game thread, whereas the header describes own error: diagnostic isolation is unspecified; ask immediately, do not depend on isolation. The released-owner refusal guarantee is not uniformly enforced here either.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_creative_v1.set_god_mode size >= 16; 1.0 sco_result (*set_god_mode)(sco_plugin* self, int on);
God mode on (non-zero) or off (0). SCO_OK also when you haven’t spawned yet: it is applied once you have. SCO_FAILED: the game faulted, or the host can’t turn the toggle off when your plugin unloads (no release hook left). game.creative.god_mode.
Caller outputs; host owns toggle state. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing feature capability: UNAVAILABLE; null/unknown self: BAD_ARG; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned toggles switched off and speed restored on ordinary unload/non-retained crash cleanup. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_creative_v1.set_fly_mode size >= 24; 1.0 sco_result (*set_fly_mode)(sco_plugin* self, int on);
Fly mode (noclip) on or off, for your player. SCO_FAILED: you’re not spawned yet, your actor has no fly handler, the game faulted, or no release hook is left. Switching it off when it isn’t on is SCO_OK and does nothing. game.creative.fly.
Caller outputs; host owns toggle state. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing feature capability: UNAVAILABLE; null/unknown self: BAD_ARG; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned toggles switched off and speed restored on ordinary unload/non-retained crash cleanup. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_creative_v1.set_fly_speed size >= 32; 1.0 sco_result (*set_fly_speed)(sco_plugin* self, float mps);
The fly speed in metres per second: finite, above 0 and at most SC_CREATIVE_FLY_SPEED_MAX (SCO_BAD_ARG otherwise). The game’s own speed comes back when your plugin unloads. SCO_UNAVAILABLE: no fly capability, or the game’s fly speed field wasn’t found on this build. SCO_FAILED: the game’s settings aren’t up yet. game.creative.fly.
Caller outputs; host owns toggle state. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing feature capability: UNAVAILABLE; null/unknown self: BAD_ARG; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned toggles switched off and speed restored on ordinary unload/non-retained crash cleanup. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_creative_v1.set_infinite_ammo size >= 40; 1.0 sco_result (*set_infinite_ammo)(sco_plugin* self, int on);
Infinite ammo for the weapons you carry: a magazine you fire from is topped up to its maximum. SCO_FAILED when the magazine setter can’t be hooked or no release hook is left. game.creative.ammo.
Caller outputs; host owns toggle state. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing feature capability: UNAVAILABLE; null/unknown self: BAD_ARG; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned toggles switched off and speed restored on ordinary unload/non-retained crash cleanup. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_creative_v1.set_infinite_ship_ammo size >= 48; 1.0 sco_result (*set_infinite_ship_ammo)(sco_plugin* self, int on);
The same for every weapon on the ship you’re aboard (including ones that drain their magazine without the setter: topped up twice a second). game.creative.ship_ammo.
Caller outputs; host owns toggle state. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing feature capability: UNAVAILABLE; null/unknown self: BAD_ARG; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned toggles switched off and speed restored on ordinary unload/non-retained crash cleanup. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_creative_v1.state size >= 56; 1.0 sco_result (*state)(sco_plugin* self, uint32_t* out_flags);
out_flags = the sc_creative_flag bits that are on. SCO_UNAVAILABLE only when none of the four capabilities is ready.
Caller outputs; host owns toggle state. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing feature capability: UNAVAILABLE; null/unknown self: BAD_ARG; released-handle refusal unspecified. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned toggles switched off and speed restored on ordinary unload/non-retained crash cleanup. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_creative_v1.last_error size >= 64; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for the last failed call (“” if none), NUL-terminated, with sco.storage’s size handshake: *inout_size is out’s capacity on entry and the bytes written (NUL included) on SCO_OK, or the bytes needed on SCO_TOO_MANY. out may be NULL when *inout_size is 0. On the game thread: your own last failed call; on another thread: the last refusal on that thread. Any thread.
Caller outputs; host owns toggle state. No allocation transfer; internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid buffer; TOO_MANY required bytes. Implementation selects newer own/shared-query error on game thread; otherwise thread refusal. self validity and stopped-service rejection unspecified. No in-flight cancellation entrypoint; owned toggles switched off and speed restored on ordinary unload/non-retained crash cleanup. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.

Source: sc_hangar.h, implementation, engine calls, layout pin, rows.

Capabilities: lift (lift_of_landing_area, lift_request) and atc_cancel (atc_cancel_request), both OFF by default pending an in-game run: while off, every call answers UNAVAILABLE without touching the game. Nothing is owned: a lift request or an ATC cancel is one call into the game, not coordinated with the game pack’s own Store/Retrieve, and nothing is undone at unload. C++ (scosdk::game::Hangar) and C# (Sco.Sdk.Game) wrap game.hangar. Lua game.hangar routes are unsupported.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_hangar_v1.lift_of_landing_area size >= 16; 1.0 sco_result (*lift_of_landing_area)(sco_plugin* self, uint64_t landing_area_id, uint64_t* out_lift_id);
*out_lift_id = the entity id of the ship lift that serves the landing area landing_area_id: the lift whose name matches the landing area’s and that is in the landing area’s zone. SCO_BAD_ARG: an id of 0, out_lift_id NULL, or the entity isn’t a landing area. SCO_NOT_FOUND: the landing area isn’t streamed in, or no lift goes with it. SCO_FAILED: the game faulted. game.hangar.lift.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; game.hangar.lift OFF (the default): UNAVAILABLE without an engine call; null/unknown self: BAD_ARG. Other failures as in the buffer contract. No in-flight cancellation entrypoint; a lift request or ATC cancel is one call and nothing is undone at unload; your last error is forgotten on ordinary owner release.
sc_hangar_v1.lift_request size >= 24; 1.0 sco_result (*lift_request)(sco_plugin* self, uint64_t lift_id, uint32_t op);
Asks the ship lift lift_id (an id from lift_of_landing_area) to open or close (sc_hangar_lift_op). SCO_OK means the request was handed to the game, not that the lift has moved. SCO_BAD_ARG: an id of 0, an unknown op, or the entity isn’t a ship lift. SCO_NOT_FOUND: the lift isn’t streamed in. SCO_FAILED: the game faulted. game.hangar.lift.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; game.hangar.lift OFF (the default): UNAVAILABLE without an engine call; null/unknown self: BAD_ARG. Other failures as in the buffer contract. No in-flight cancellation entrypoint; a lift request or ATC cancel is one call and nothing is undone at unload; your last error is forgotten on ordinary owner release.
sc_hangar_v1.atc_cancel_request size >= 32; 1.0 sco_result (*atc_cancel_request)(sco_plugin* self, uint64_t atc_id);
Withdraws the local player’s pending request at the air traffic controller atc_id (the game’s own request cancel). SCO_BAD_ARG: an id of 0. SCO_NOT_FOUND: that entity has no ATC data. SCO_FAILED: you’re not spawned, or the game faulted. game.hangar.atc_cancel.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; game.hangar.atc_cancel OFF (the default): UNAVAILABLE without an engine call; null/unknown self: BAD_ARG. Other failures as in the buffer contract. No in-flight cancellation entrypoint; a lift request or ATC cancel is one call and nothing is undone at unload; your last error is forgotten on ordinary owner release.
sc_hangar_v1.last_error size >= 40; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for the last failed call (“” if none), NUL-terminated, with sco.storage’s size handshake: *inout_size is out’s capacity on entry and the bytes written (NUL included) on SCO_OK, or the bytes needed on SCO_TOO_MANY. out may be NULL when *inout_size is 0. On the game thread: your own last failed call; on another thread: the last refusal on that thread. Any thread.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid buffer; TOO_MANY required bytes. On the game thread with a loaded self: your own last error; otherwise the thread’s last refusal. No in-flight cancellation entrypoint; a lift request or ATC cancel is one call and nothing is undone at unload; your last error is forgotten on ordinary owner release.

Source: sc_asop.h, implementation, engine reads, layout pin, rows.

Capabilities: claim_timeout (claim_timeout) and shard_persisted (shard_persisted), both OFF by default pending an in-game run: while off, every call answers UNAVAILABLE without touching the game. Both functions are reads: nothing is written to the game and nothing is owned. The game pack’s own ship terminal handling, when the product runs it, shortens the claim timeout; claim_timeout reports the value the game holds at the time of the call. C++, C# and Lua game.asop routes are unsupported.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_asop_v1.claim_timeout size >= 16; 1.0 sco_result (*claim_timeout)(sco_plugin* self, int32_t* out_seconds);
*out_seconds = the request timeout, in seconds, of the game’s insurance component configuration: how long a ship terminal claim request waits for an answer. SCO_BAD_ARG: out_seconds NULL. SCO_NOT_FOUND: the insurance configuration isn’t loaded yet. SCO_FAILED: the game faulted. game.asop.claim_timeout.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; game.asop.claim_timeout OFF (the default): UNAVAILABLE without an engine call; null/unknown self: BAD_ARG. Other failures as in the buffer contract. No in-flight cancellation entrypoint; both functions are reads and nothing is undone at unload; your last error is forgotten on ordinary owner release.
sc_asop_v1.shard_persisted size >= 24; 1.0 sco_result (*shard_persisted)(sco_plugin* self, uint32_t* out_persisted);
*out_persisted = 1 when the game’s IsShardPersisted flag is set, 0 when it is clear: the flag the ship terminal’s open checks before it opens. SCO_BAD_ARG: out_persisted NULL. SCO_FAILED: the game faulted. game.asop.shard_persisted.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; game.asop.shard_persisted OFF (the default): UNAVAILABLE without an engine call; null/unknown self: BAD_ARG. Other failures as in the buffer contract. No in-flight cancellation entrypoint; both functions are reads and nothing is undone at unload; your last error is forgotten on ordinary owner release.
sc_asop_v1.last_error size >= 32; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for the last failed call (“” if none), NUL-terminated, with sco.storage’s size handshake: *inout_size is out’s capacity on entry and the bytes written (NUL included) on SCO_OK, or the bytes needed on SCO_TOO_MANY. out may be NULL when *inout_size is 0. On the game thread: your own last failed call; on another thread: the last refusal on that thread. Any thread.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid buffer; TOO_MANY required bytes. On the game thread with a loaded self: your own last error; otherwise the thread’s last refusal. No in-flight cancellation entrypoint; both functions are reads and nothing is undone at unload; your last error is forgotten on ordinary owner release.

Source: sc_contracts.h, implementation, engine reads, layout pin, rows.

Capability: stream_radius (stream_radius), OFF by default pending an in-game run: while off, the call answers UNAVAILABLE without touching the game. The function is a read: nothing is written to the game and nothing is owned. The service name is new; the host-internal contracts.* capabilities and the game.missions service are separate. A product that runs offline contracts may write the stream radius; stream_radius reports the value the game holds at the time of the call. C++, C# and Lua game.contracts routes are unsupported.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_contracts_v1.stream_radius size >= 16; 1.0 sco_result (*stream_radius)(sco_plugin* self, float* out_radius);
*out_radius = the mission stream radius the game’s mission settings hold (a 32-bit float, in the game’s own units). SCO_BAD_ARG: out_radius NULL. SCO_NOT_FOUND: the mission settings aren’t loaded yet. SCO_FAILED: the game faulted. game.contracts.stream_radius.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; game.contracts.stream_radius OFF (the default): UNAVAILABLE without an engine call; null/unknown self: BAD_ARG. Other failures as in the buffer contract. No in-flight cancellation entrypoint; the function is a read and nothing is undone at unload; your last error is forgotten on ordinary owner release.
sc_contracts_v1.last_error size >= 24; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for the last failed call (“” if none), NUL-terminated, with sco.storage’s size handshake: *inout_size is out’s capacity on entry and the bytes written (NUL included) on SCO_OK, or the bytes needed on SCO_TOO_MANY. out may be NULL when *inout_size is 0. On the game thread: your own last failed call; on another thread: the last refusal on that thread. Any thread.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid buffer; TOO_MANY required bytes. On the game thread with a loaded self: your own last error; otherwise the thread’s last refusal. No in-flight cancellation entrypoint; the function is a read and nothing is undone at unload; your last error is forgotten on ordinary owner release.

Source: sc_reputation.h, implementation, engine reads, layout pin, rows.

Capability: checks (checks), OFF by default pending an in-game run: while off, checks answers UNAVAILABLE without touching the game. Read-only: checks reads the reputation-service check sites and the services global the rows locate; nothing reads or changes a player’s standing, nothing is called or written in the game, and nothing is owned. C++ (scosdk::game::Reputation) and C# (Sco.Sdk.Game) wrap game.reputation. Lua game.reputation routes are unsupported.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_reputation_v1.checks size >= 16; 1.0 sco_result (*checks)(sco_plugin* self, sc_reputation_checks* out);
Fills *out (sc_reputation_checks) from the game’s reputation-service check sites and the services object they load. Reads only; nothing is called or written in the game. SCO_BAD_ARG: out NULL or out->size smaller than sizeof(sc_reputation_checks). SCO_FAILED: the game faulted. game.reputation.checks.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; game.reputation.checks OFF (the default): UNAVAILABLE without an engine read; null/unknown self: BAD_ARG. Other failures as in the buffer contract. No in-flight cancellation entrypoint; checks only reads and nothing is undone at unload; your last error is forgotten on ordinary owner release.
sc_reputation_v1.last_error size >= 24; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for the last failed call (“” if none), NUL-terminated, with sco.storage’s size handshake: *inout_size is out’s capacity on entry and the bytes written (NUL included) on SCO_OK, or the bytes needed on SCO_TOO_MANY. out may be NULL when *inout_size is 0. On the game thread: your own last failed call; on another thread: the last refusal on that thread. Any thread.
Caller outputs; nothing owned, the host keeps only your last error. No allocation transfer; internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid buffer; TOO_MANY required bytes. On the game thread with a loaded self: your own last error; otherwise the thread’s last refusal. No in-flight cancellation entrypoint; checks only reads and nothing is undone at unload; your last error is forgotten on ordinary owner release.

Source: sc_world.h, implementation, layout pin.

Capabilities raycast/camera. Read-only, no entity ownership or game pointers. Ray origin/output use zone frame; camera pose uses world frame plus player’s zone ID. Hit is size-prefixed; in 1.0 entity_id/normal/flags stay zero, not inferred from the game. No field of view. Failure zeroes only an adequately-sized hit; NULL/undersized output is rejected before zeroing, and caller extra tail is not written. last_error is shared across query callers, with no per-plugin isolation. 1.1 appends free_camera_flag (capability game.world.free_camera_flag, OFF by default pending an in-game run): a read of the free-camera flag byte, never a toggle. C++, C# and Lua wrap game.world free_camera_flag, each checking the table size first.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_world_v1.raycast size >= 16; 1.0 sco_result (*raycast)(uint64_t zone_id, const double from[3], const double dir[3], double max_dist, sc_world_hit* out_hit);
Casts a ray from from (metres, in zone zone_id’s local frame) along dir (any non-zero length; it is normalised) for at most max_dist metres, and fills *out_hit (out_hit->size must be sizeof(sc_world_hit)). max_dist must be positive and finite; one over SC_WORLD_RAY_MAX_DISTANCE is clamped to it. The cast tries the zone and then up to two of its parents (never the world’s root zone), as sc-offline’s build mode does, and reports the first hit, in the frame of zone_id. Nothing is skipped: your own player’s body can be hit. SCO_OK: hit. SCO_NOT_FOUND: nothing hit within max_dist (last_error says “no hit”), or the zone isn’t streamed in, or you haven’t spawned. SCO_BAD_ARG: a NULL pointer, zone 0, a non-finite or zero direction, a bad max_dist or a too-small out_hit->size. SCO_UNAVAILABLE: game.world.raycast isn’t ready. SCO_FAILED: the game faulted. *out_hit is zeroed (apart from size) on every failure. Implementation: NULL/undersized hit rejected before zeroing; adequately-sized hit is zeroed excluding size, only known fields written. Unknown caller tail untouched.
Caller buffers; no allocation crosses boundary; queries do not own entities. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; BAD_ARG for invalid required outputs. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.
sc_world_v1.camera size >= 24; 1.0 sco_result (*camera)(double out_pos[3], double out_rot_xyzw[4], uint64_t* out_zone_id);
The camera you see through: *out_pos in the world frame (metres), *out_rot_xyzw the same frame’s rotation (x, y, z, w), *out_zone_id the zone your player is in (so you can convert with teleport.spatial). No fov (see above). Any pointer may be NULL to skip it, not all. SCO_NOT_FOUND: you haven’t spawned yet. SCO_UNAVAILABLE: game.world.camera isn’t ready. SCO_FAILED: the game faulted. Outputs are zeroed on failure.
Caller buffers; no allocation crosses boundary; queries do not own entities. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE; BAD_ARG for invalid required outputs. Additional failures/output state unspecified unless described in the buffer contract. No cancellation entrypoint; synchronous query.
sc_world_v1.last_error size >= 32; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for the last failed call of any plugin (“” if none), NUL-terminated, with the size handshake (*inout_size: capacity in; bytes written, or needed with SCO_TOO_MANY, out). The queries keep no per-plugin state, so self is only checked: NULL or a loaded plugin’s handle (anything else is SCO_BAD_ARG). Any thread.
Caller buffers; no allocation crosses boundary; queries do not own entities. Internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid/released non-NULL self or buffer; TOO_MANY required bytes. Shared error across all query callers; stopped-service refusal unspecified (no started check). No cancellation entrypoint; synchronous query.
sc_world_v1.free_camera_flag size >= 40; 1.1 sco_result (*free_camera_flag)(uint32_t* out_set);
*out_set = 1 when the game’s free-camera flag (the byte its own free-camera disable command tests) is non-zero, else 0. Only reads; it neither turns the free camera on nor off, and nothing pins what the flag shows on screen yet, which is why game.world.free_camera_flag is OFF. SCO_BAD_ARG: out_set is NULL. SCO_UNAVAILABLE: game.world.free_camera_flag isn’t ready. SCO_FAILED: the game faulted. *out_set is 0 on every failure.
Caller output; nothing owned and nothing kept per plugin. No allocation crosses the boundary; internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere); last_error any thread. Recursive reentrancy unspecified. Absent table: query_service NOT_FOUND; a 1.0 table: query_service UNAVAILABLE for SC_WORLD_VERSION_1_1 (or check size); game.world.free_camera_flag OFF (the default): UNAVAILABLE without a game read; NULL out_set: BAD_ARG. Other failures as in the buffer contract. No cancellation entrypoint; synchronous read-only query, nothing to undo at unload.

Source: sc_entities.h, implementation, layout pin.

1.0 is 88 bytes; 1.1 appends keep (96). Capabilities transform, spawn, class_of, watch and query_radius; the last two remain off pending in-game verification. All owners combined: 1,024 owned spawns and 64 watches; filter length at most 63 printable ASCII bytes, exact class or trailing-prefix *. A kept entity is no longer owned; the host does not despawn it at unload/crash. query_radius.out_more is the number of omitted matches, not the Boolean used by vehicle seats. max=0 writes no IDs and reports matches via out_more. Failure-output guarantees differ per method; do not assume all outputs unchanged.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_entities_v1.alive size >= 16; 1.0 int (*alive)(uint64_t entity_id);
1 when the entity is streamed in, else 0 (also when the capability isn’t ready or off the game thread).
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.class_of size >= 24; 1.0 sco_result (*class_of)(uint64_t entity_id, char* out, uint32_t* inout_size);
The entity’s class name (the name spawn takes), NUL-terminated, with the size handshake (*inout_size: capacity in; bytes written, or needed with SCO_TOO_MANY, out). SCO_NOT_FOUND: the entity isn’t streamed in. SCO_UNAVAILABLE: no “game.entities.class_of”. SCO_FAILED: the game faulted or the name isn’t a plausible class name. Read-only: no self; a failure’s reason is last_error(NULL, …). Implementation clears out[0] when capacity > 0 and initializes inout_size to 0 before failure checks.
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.get_transform size >= 32; 1.0 sco_result (*get_transform)(uint64_t entity_id, double out_pos[3], double out_rot_xyzw[4], uint64_t* out_zone_id);
The entity’s position (3 doubles) and rotation (x, y, z, w) in its zone’s local frame, and that zone’s id. Any out pointer may be NULL to skip it, not all of them. Outputs are zeroed on failure. SCO_NOT_FOUND: the entity isn’t streamed in, or isn’t in a zone. SCO_UNAVAILABLE: no “game.entities.transform”. Read-only: last_error(NULL, …). Implementation also FAILED for changed rotation slots or read fault; id 0 BAD_ARG.
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.set_transform size >= 40; 1.0 sco_result (*set_transform)(sco_plugin* self, uint64_t entity_id, uint64_t zone_id, const double pos[3], const double rot_xyzw[4]);
Moves and turns an entity you may move (see Moving above): pos and rot are in zone zone_id’s local frame (any streamed-in zone; the host converts to the entity’s own zone). rot is normalised. SCO_BAD_ARG: a null or released self, id 0, a null pos or rot, a position that isn’t finite or a zero rotation. SCO_NOT_FOUND: not streamed in yet (a fresh spawn takes a few seconds: wait for alive), or a zone that isn’t. SCO_UNAVAILABLE: no “game.entities.transform”. SCO_FAILED: not yours to move, or the game refused.
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.spawn size >= 48; 1.0 sco_result (*spawn)(sco_plugin* self, const char* entity_class, uint64_t zone_id, const double pos[3], const double rot_xyzw[4], uint64_t* out_id);
Spawns an entity of entity_class (a class name, as in sc-offline’s npcs.txt or spawn.entities) at pos, facing rot, in zone zone_id’s local frame: anywhere, not only near the player. *out_id = the new entity id, 0 on failure. The id is final at once; the entity streams in a few seconds later. It is yours (see Ownership above). SCO_BAD_ARG: a null or released self, a null class, pos, rot or out_id, zone 0, or a position that isn’t finite or a zero rotation. SCO_NOT_FOUND: the zone isn’t streamed in, or the class doesn’t exist on this game build. SCO_TOO_MANY: SC_ENTITIES_MAX_OWNED are alive. SCO_UNAVAILABLE: no “game.entities.spawn”, or the host couldn’t remove your entities when you unload. SCO_FAILED: the game refused or faulted.
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.despawn size >= 56; 1.0 sco_result (*despawn)(sco_plugin* self, uint64_t entity_id);
Removes an entity you spawned here. SCO_OK starts the removal: the entity leaves the world within a few seconds (one that hasn’t streamed in yet goes once it has), and the id is no longer yours. SCO_NOT_FOUND: not an entity you spawned here, or despawned already.
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.watch size >= 64; 1.0 sco_result (*watch)(sco_plugin* self, uint32_t what, const char* type, sc_entity_watch_fn fn, void* ctx, uint64_t* out_watch_id);
Calls fn(ctx, what, id, class) on the game thread for every entity of type that streams in or out (what: SC_ENTITY_STREAMED_IN, SC_ENTITY_STREAMED_OUT or both ORed), until unwatch or until your plugin unloads. out_watch_id = the watch’s id (never 0). type: an entity class name (“AEGS_Avenger_Titan”), matched exactly and case-sensitively, or a class prefix ending in one ‘’ (“AEGS_”). The host matches the type before calling you, so you pay only for what you asked about. Refused with SCO_BAD_ARG, and a reason: NULL, empty, a lone “”, a ‘’ that isn’t last (“AB”, “**”), more than SC_ENTITIES_MAX_TYPE_LEN characters, anything but printable ASCII or ‘?’, a what with no known bit, a null self, fn or out_watch_id. SCO_TOO_MANY: SC_ENTITIES_MAX_WATCHES exist. SCO_UNAVAILABLE: no “game.entities.watch” on this build, or while the hooks are unconfirmed; see docs/game-services.md. Events reach fn a tick after they happen, in order; if a plugin can’t keep up, the oldest are dropped.
Filter copied; fn/ctx borrowed until unwatch/unload. Callback class_name borrowed for call only; streamed-out ID already gone. Game thread only; callback runs game thread and may call unwatch/unload; other reentrancy unspecified. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. unwatch/ordinary unload/non-retained crash cleanup ends delivery; callback may unwatch itself or unload without further events. Oldest queued events dropped under overflow (256 held per watch). Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls. Fault quarantine stops guarded delivery without removing the retained watch.
sc_entities_v1.unwatch size >= 72; 1.0 sco_result (*unwatch)(sco_plugin* self, uint64_t watch_id);
Ends a watch you registered; fn isn’t called again once this returns. SCO_NOT_FOUND: not your watch, or ended already.
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only; allowed inside own callback; no further event after return. Other reentrancy unspecified. BAD_ARG invalid/released self; WRONG_THREAD; NOT_FOUND no own active watch; valid watch removed even without capability/started gate (implementation). May be called inside callback; no further event after successful return. Does not interrupt current callback.
sc_entities_v1.query_radius size >= 80; 1.0 sco_result (*query_radius)(uint64_t zone_id, const double pos[3], double radius, const char* class_filter, uint64_t* out_ids, uint32_t max, uint32_t* out_count, uint32_t* out_more);
Ids of streamed-in entities within radius metres of pos in zone zone_id’s frame, whose class matches class_filter (a class name or a “PREFIX*”; NULL or “” = any class). Up to max ids are written to out_ids (max 0 counts only); *out_count = how many were written and *out_more = how many matched but didn’t fit. SCO_BAD_ARG: a null pos, out_count or out_more, a null out_ids with max > 0, zone 0, a radius that isn’t finite and positive, a filter that isn’t a class name or prefix. SCO_NOT_FOUND: the zone isn’t streamed in. SCO_FAILED: the walk faulted or saw more than 65536 entities. SCO_UNAVAILABLE: no “game.entities.query_radius” on this game build, or while its in-game check is pending (docs/game-services.md). Read-only: last_error(NULL, …).
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.last_error size >= 88; 1.0 sco_result (*last_error)(sco_plugin* self, char* out, uint32_t* inout_size);
The reason for self’s last failed call (“” if none), NUL-terminated, with the size handshake (*inout_size: capacity in; bytes written, or needed with SCO_TOO_MANY, out). self NULL: the last failure of a call made without a plugin handle (alive’s neighbours: class_of, get_transform, query_radius). Any thread.
Caller buffers; no allocation crosses boundary. Host owns entity/watch tracking; IDs are session values. Internal allocation unspecified. Any thread; diagnostic scope as described; recursive reentrancy unspecified. BAD_ARG invalid/released non-NULL self or buffer; TOO_MANY required bytes. NULL self selects no-self failures; stopped-service refusal unspecified (no started check). No in-flight cancellation entrypoint; owned entities removed and watches ended on ordinary unload/non-retained crash cleanup, except kept entities. Retained-provider faults skip owner resource-release hooks and require restart; backing resources remain retained, not safe for cached calls.
sc_entities_v1.keep size >= 96; 1.1 sco_result (*keep)(sco_plugin* self, uint64_t entity_id);
1.1. Releases your ownership of an entity you spawned here (see Keeping above): the host no longer despawns it when your plugin unloads or crashes, and set_transform and despawn by you are refused from now on, as for any entity you don’t own. The entity itself is untouched. SCO_OK, once. SCO_BAD_ARG: a null or released self, id 0. SCO_NOT_FOUND: not an entity you spawned here and still own (kept or despawned already, or spawned another way), with a reason for last_error. SCO_UNAVAILABLE: no “game.entities.spawn”. Call it right after spawn succeeds: the id is final at once, the entity needn’t have streamed in. SCO_FAILED: a game.owned retained build cannot relinquish ownership; use remove_build for undo/clear and ordinary unload cleanup.
Relinquishes own game.entities spawn; no allocation transfer. Entity survives unload/crash, no longer counts against ownership quota; no longer movable/despawnable by this ownership. Game thread only (WRONG_THREAD elsewhere, alive returns 0); last_error any thread. Recursive reentrancy unspecified except unwatch in callback. Absent table: query_service NOT_FOUND; missing operation capability: UNAVAILABLE (alive: 0); invalid/released self: BAD_ARG. Additional failures/output state unspecified unless described in the buffer contract. For unretained legacy keep only: entity untouched and survives unload; no SDK undo/removal authority. Retained builds refuse keep and use game.owned removal/unload instead.

Independent table over the existing entity spawner, mover and delayed despawn. Prefab IDs are in the game.entities ledger, including not-yet-streamed spawns; retain_build preserves undo while loaded, not across reload. No keep-based undo. Canonical content-relative paths do not authorize external files or content exports. Native adapter ports existing spawn.prefabs rows and ocFilename writer; production operation is enabled by default for R1 by owner approval. Windows/SEH/streamed cleanup are NOT VERIFIED; readiness/fault refusals remain. C/C++ supported; C# and read-only Lua unsupported. Design.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_prefabs_v1.spawn size >= 16; 1.0 sco_result (*spawn)(sco_plugin* self, const char* content_path, uint64_t zone_id, const double pos[3], const double rot_xyzw[4], uint64_t* out_id);
Canonical ObjectContainers content-relative .socpak path (511 bytes max), finite zone-local pose and normalized quaternion. Caller-owned final entity ID, zero on failure; success means spawn initiation only. Shared 1024 owned quota and 128 own entities maximum, checked before mutation. Pending prefab ownership is never pruned by alive=0. Capability game.entities.prefabs is enabled by default for R1 by owner approval; Windows/SEH/streamed cleanup NOT VERIFIED.
Live caller owns result through existing game.entities ledger. Inputs copied for synchronous provider call, host-session table borrowed; no cross-boundary allocation. Game thread only; WRONG_THREAD otherwise. BAD_ARG invalid handle/path/pose/output; WRONG_THREAD; TOO_MANY quota; NOT_FOUND zone/content/class; UNAVAILABLE disabled capability or cleanup; FAILED provider refusal/fault. Output ID zero on failure. Use existing entities despawn/set_transform and game.owned retention/removal. Ordinary owner unload removes pending/streamed owned prefab via delayed removal primitive; no materialization/removal completion promise. Known ID on provider failure remains tracked for cleanup. Fault-retained native provider follows restart-required lifetime contract.

Game-pack-only composition: explicit retained build ownership while loaded, not across-reload persistence; actors-owned NPC and fresh expected-seat NPC removal are distinct authorities. Receipts prove initiation only, never alive=0 completion. C/C++ direct tables; C#/Lua unsupported. See ownership decision.

Method Since / extent Buffers Ownership Thread Results Cleanup
sc_owned_v1.retain_build size >= 16; 1.0 sco_result (*retain_build)(sco_plugin* self, uint64_t entity_id);
Idempotently mark an existing caller-owned game.entities spawn as retained for loaded-plugin undo/clear; keep refuses it and unload removes it.
Explicit retained entities ownership while loaded; NPC authority is actors-only. Owner-scoped receipts, caller outputs; fixed global bounds of 1024 each, no cross-boundary allocation. Game thread only; WRONG_THREAD elsewhere. No recursive reentry. BAD_ARG invalid/released self or arguments; NOT_FOUND foreign/stale authority; UNAVAILABLE missing/partial/null prerequisite method; FAILED changed seat; TOO_MANY full tracking. Underlying refusal propagates; SCO_OK removal is initiation only. Ordinary unload removes retained placements/NPCs through existing hooks and clears receipts. No across-reload persistence; retained-provider faults require restart and skip resource hooks.
sc_owned_v1.remove_build size >= 24; 1.0 sco_result (*remove_build)(sco_plugin* self, uint64_t entity_id, uint64_t* out_ticket);
Remove a retained caller-owned build placement through existing entities despawn; ticket 0 on refusal, SCO_OK is initiation only.
Explicit retained entities ownership while loaded; NPC authority is actors-only. Owner-scoped receipts, caller outputs; fixed global bounds of 1024 each, no cross-boundary allocation. Game thread only; WRONG_THREAD elsewhere. No recursive reentry. BAD_ARG invalid/released self or arguments; NOT_FOUND foreign/stale authority; UNAVAILABLE missing/partial/null prerequisite method; FAILED changed seat; TOO_MANY full tracking. Underlying refusal propagates; SCO_OK removal is initiation only. Ordinary unload removes retained placements/NPCs through existing hooks and clears receipts. No across-reload persistence; retained-provider faults require restart and skip resource hooks.
sc_owned_v1.remove_npc size >= 32; 1.0 sco_result (*remove_npc)(sco_plugin* self, uint64_t npc_id, uint64_t* out_ticket);
Remove only caller-owned game.actors NPCs through actors despawn; no entity/spawn_as/player ownership union. Ticket 0 on refusal; SCO_OK is initiation only.
Explicit retained entities ownership while loaded; NPC authority is actors-only. Owner-scoped receipts, caller outputs; fixed global bounds of 1024 each, no cross-boundary allocation. Game thread only; WRONG_THREAD elsewhere. No recursive reentry. BAD_ARG invalid/released self or arguments; NOT_FOUND foreign/stale authority; UNAVAILABLE missing/partial/null prerequisite method; FAILED changed seat; TOO_MANY full tracking. Underlying refusal propagates; SCO_OK removal is initiation only. Ordinary unload removes retained placements/NPCs through existing hooks and clears receipts. No across-reload persistence; retained-provider faults require restart and skip resource hooks.
sc_owned_v1.remove_seat_npc size >= 40; 1.0 sco_result (*remove_seat_npc)(sco_plugin* self, uint64_t ship, uint32_t seat_index, uint64_t expected_npc, uint64_t* out_ticket);
Fresh seat occupant must match expected actors-owned NPC; foreign/player/unknown occupants are refused. Ticket 0 on refusal; SCO_OK is initiation only.
Explicit retained entities ownership while loaded; NPC authority is actors-only. Owner-scoped receipts, caller outputs; fixed global bounds of 1024 each, no cross-boundary allocation. Game thread only; WRONG_THREAD elsewhere. No recursive reentry. BAD_ARG invalid/released self or arguments; NOT_FOUND foreign/stale authority; UNAVAILABLE missing/partial/null prerequisite method; FAILED changed seat; TOO_MANY full tracking. Underlying refusal propagates; SCO_OK removal is initiation only. Ordinary unload removes retained placements/NPCs through existing hooks and clears receipts. No across-reload persistence; retained-provider faults require restart and skip resource hooks.
sc_owned_v1.receipt size >= 48; 1.0 sco_result (*receipt)(sco_plugin* self, uint64_t ticket, sc_removal_receipt* out);
Read owner-scoped REQUESTED initiation record, never alive-based completion. A short size-prefixed record is untouched; sufficient output payload clears on failure.
Explicit retained entities ownership while loaded; NPC authority is actors-only. Owner-scoped receipts, caller outputs; fixed global bounds of 1024 each, no cross-boundary allocation. Game thread only; WRONG_THREAD elsewhere. No recursive reentry. BAD_ARG invalid/released self or arguments; NOT_FOUND foreign/stale authority; UNAVAILABLE missing/partial/null prerequisite method; FAILED changed seat; TOO_MANY full tracking. Underlying refusal propagates; SCO_OK removal is initiation only. Ordinary unload removes retained placements/NPCs through existing hooks and clears receipts. No across-reload persistence; retained-provider faults require restart and skip resource hooks.
sc_owned_v1.forget size >= 56; 1.0 sco_result (*forget)(sco_plugin* self, uint64_t ticket);
Forget owner-scoped receipt to reclaim capacity; not cancellation, completion or renewed ownership.
Explicit retained entities ownership while loaded; NPC authority is actors-only. Owner-scoped receipts, caller outputs; fixed global bounds of 1024 each, no cross-boundary allocation. Game thread only; WRONG_THREAD elsewhere. No recursive reentry. BAD_ARG invalid/released self or arguments; NOT_FOUND foreign/stale authority; UNAVAILABLE missing/partial/null prerequisite method; FAILED changed seat; TOO_MANY full tracking. Underlying refusal propagates; SCO_OK removal is initiation only. Ordinary unload removes retained placements/NPCs through existing hooks and clears receipts. No across-reload persistence; retained-provider faults require restart and skip resource hooks.

Independent size-prefixed extension; game.world 1.0 and frozen sco_api are unchanged. Native C/C++ only; C# and sandboxed Lua routes unsupported. Design and evidence limits; header. Production capabilities game.world.raycast_filtered and game.world.free_camera are OFF: no guessed engine adapter. Synthetic policy is not gameplay proof.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_world_control_v1.raycast_filtered size >= 16; 1.0 sco_result (*raycast_filtered)(sco_plugin* self, uint64_t zone_id, const double from[3], const double dir[3], double max_dist, const uint64_t* skip_ids, uint32_t skip_count, sc_world_hit* out_hit);
Zone-local ray; direction normalized, positive finite distance clamped to 20000m. At most 32 unique nonzero current own IDs, copied for call only; foreign/relinquished ID FAILED, malformed input BAD_ARG. Adequately-sized hit zeroed on failure, unknown tail untouched; success position/distance only, entity/normal/flags zero. NULL/short hit rejected before zeroing. Capability game.world.raycast_filtered remains OFF.
Live owner required; call-only copied inputs, host-session borrowed table. No allocation or engine pointers cross boundary. Camera lease exclusive; no steal. Game thread only; WRONG_THREAD without provider access. BAD_ARG invalid owner/input; WRONG_THREAD; UNAVAILABLE absent verified adapter or restart-required; FAILED foreign owner/provider refusal; NOT_FOUND stale lease/no hit. See method-specific output contract. No persisted ray filter. Ordinary owner unload/service stop restores camera before dropping lease; failure retains backing state and requires restart. Fault-retained native provider cleanup not promised.
sc_world_control_v1.camera_acquire size >= 24; 1.0 sco_result (*camera_acquire)(sco_plugin* self, uint64_t* out_lease);
Exclusive owner-scoped camera lease; output token zero on failure. Same owner reacquire returns same token; foreign owner FAILED. Provider captures all camera/input/mode state before mutation; acquire failure atomic. UNAVAILABLE without complete verified offline adapter and cleanup hook. Capability game.world.free_camera remains OFF.
Live owner required; call-only copied inputs, host-session borrowed table. No allocation or engine pointers cross boundary. Camera lease exclusive; no steal. Game thread only; WRONG_THREAD without provider access. BAD_ARG invalid owner/input; WRONG_THREAD; UNAVAILABLE absent verified adapter or restart-required; FAILED foreign owner/provider refusal; NOT_FOUND stale lease/no hit. See method-specific output contract. No persisted ray filter. Ordinary owner unload/service stop restores camera before dropping lease; failure retains backing state and requires restart. Fault-retained native provider cleanup not promised.
sc_world_control_v1.camera_step size >= 32; 1.0 sco_result (*camera_step)(sco_plugin* self, uint64_t lease, const sc_world_camera_step* step);
Only own active lease; copied size-prefixed step, tail ignored, reserved pad zero. Finite world translation norm <=10m and unit quaternion shortest world rotation delta <=0.25rad per call. No absolute pose or FOV. BAD_ARG invalid delta, NOT_FOUND stale/zero token, FAILED foreign owner. Provider failure attempts restoration and permanently latches restart-required.
Live owner required; call-only copied inputs, host-session borrowed table. No allocation or engine pointers cross boundary. Camera lease exclusive; no steal. Game thread only; WRONG_THREAD without provider access. BAD_ARG invalid owner/input; WRONG_THREAD; UNAVAILABLE absent verified adapter or restart-required; FAILED foreign owner/provider refusal; NOT_FOUND stale lease/no hit. See method-specific output contract. No persisted ray filter. Ordinary owner unload/service stop restores camera before dropping lease; failure retains backing state and requires restart. Fault-retained native provider cleanup not promised.
sc_world_control_v1.camera_release size >= 40; 1.0 sco_result (*camera_release)(sco_plugin* self, uint64_t lease);
Restore exact pre-acquire shared camera/input/mode state before relinquishing own lease. Foreign owner FAILED; stale/zero token NOT_FOUND. Restore failure FAILED retains provider state and latches restart-required; owner cleanup/release can retry restoration, never re-enable mutations. Recovery release allowed after service stop.
Live owner required; call-only copied inputs, host-session borrowed table. No allocation or engine pointers cross boundary. Camera lease exclusive; no steal. Game thread only; WRONG_THREAD without provider access. BAD_ARG invalid owner/input; WRONG_THREAD; UNAVAILABLE absent verified adapter or restart-required; FAILED foreign owner/provider refusal; NOT_FOUND stale lease/no hit. See method-specific output contract. No persisted ray filter. Ordinary owner unload/service stop restores camera before dropping lease; failure retains backing state and requires restart. Fault-retained native provider cleanup not promised.

sco.diagnostics.publisher — sco_diagnostics_publisher_v1 1.0

Section titled “sco.diagnostics.publisher — sco_diagnostics_publisher_v1 1.0”

Default-off host-selected source ingress, not an observation endpoint. Fixed advisory health only; no text, identifiers, callbacks, read method or side channel. Extra fields stay internal, not runtime JSON v1. See sources. Native C/C++ only; no C#/Lua binding. Synthetic checked; not run in game.

Method Since Buffer / input contract Ownership Thread affinity Results / refusal Cleanup
sco_diagnostics_publisher_v1.submit size >= 16; 1.0 sco_result (*submit)(sco_plugin* self, const sco_diagnostics_observation_v1* observation);
Copies a size-prefixed 8-byte observation; no pointers retained, output, text, identifiers or arbitrary fields.
Host-owned source buffer; selected live plugin only. Advisory health never establishes host/game readiness or faults. Game thread only; synchronous memory copy, no callbacks or transport. Query NOT_FOUND when default-off/absent; BAD_ARG invalid/released/unselected owner or null/short/unknown record; WRONG_THREAD off game thread; UNAVAILABLE stopped/terminal shutdown; TOO_MANY excess rate or allocation failure. Host Stop clears ingress before shutdown callouts. Release/quarantine suppresses source; new owner starts empty. Borrowed table is process-lifetime; service reopen clears records.

Source: sc_game_spatial.h, provider, shared portable logic, layout/C route, synthetic fixture.

Separate 1.0 table; teleport.spatial remains frozen. Native C and raw C++ only; C# and Lua unsupported. This is bounded observation, not a global memory dump, exhaustive streamed-zone scanner or unloaded-destination catalogue. Player ancestry is copied each tick; explicit ID observations and full-pose queries can add complete readable chains. The strict provider refuses skipped, mirrored, truncated, cyclic or unreadable ancestry; at most 16 frames per game-read chain, 256 admitted IDs, 64 output records per page. IDs are revalidated before metadata/pose calls; unstreaming/reparenting invalidates the observation set. Copied metadata is a historical observation within its epoch, not continuous engine liveness.

Root is not system: no grounded star-system classifier exists in the available reads. root_id describes only confirmed outermost ancestry; system_id is 0 and SC_GAME_ZONE_SYSTEM_UNKNOWN is always set. Do not use it as relocation authorization or infer system identity from a name. That part of G3 remains safely unavailable. No game pointers, memory bytes, player/account identifiers, assets or global scan. Epochs expire at tick refresh, set changes, invalidation and stop; consumers restart paging after refusal and never persist epoch validity across sessions. Synchronous, no callbacks, no ownership mutation or inputs retained. Native service-table fault containment is not certified. Not verified on Windows or in game.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_game_spatial_v1.pose_to_zone size >= 16; 1.0 int (*pose_to_zone)(uint64_t from, uint64_t to, const double pos[3], const double rot_xyzw[4], double out_pos[3], double out_rot_xyzw[4]);
Convert finite position (metres) and nonzero quaternion x/y/z/w between complete readable rigid zone frames, normalizing rotation; world frame is 0. Position conversion stops at the common ancestor. Outputs may alias corresponding inputs; output arrays must not overlap. Null/nonfinite input or norm below 1e-12 refuses. Outputs unchanged on 0.
Caller-owned copied records/buffers; opaque session IDs and epoch tokens, never pointers. Fixed 256-record storage; bounded temporary trees may allocate. No retained caller inputs or allocation transfer. Game thread only; non-reentrant; no callbacks. 1 success; 0 invalid input, wrong thread, missing readiness, unreadable/unstreamed/incomplete ancestry, expired epoch, ambiguous name or quota refusal. All outputs unchanged on 0. Synchronous read; no cancellation. Stop clears observations and expires epochs. Table lives until plugins unload; no calls after shutdown admission.
sc_game_spatial_v1.zone_record size >= 24; 1.0 int (*zone_record)(uint64_t zone_id, sc_game_zone* out);
Observe one nonzero streamed zone ID and its complete ancestry, then copy a size-prefixed 144-byte record. out->size must be at least sizeof(sc_game_zone); preserve size and unknown caller tail. parent_id is direct parent; root_id is the observed outermost zone, not a certified system. system_id remains 0 with SYSTEM_UNKNOWN. Full 95-byte copied names conservatively set NAME_TRUNCATED. Outputs unchanged on 0.
Caller-owned copied records/buffers; opaque session IDs and epoch tokens, never pointers. Fixed 256-record storage; bounded temporary trees may allocate. No retained caller inputs or allocation transfer. Game thread only; non-reentrant; no callbacks. 1 success; 0 invalid input, wrong thread, missing readiness, unreadable/unstreamed/incomplete ancestry, expired epoch, ambiguous name or quota refusal. All outputs unchanged on 0. Synchronous read; no cancellation. Stop clears observations and expires epochs. Table lives until plugins unload; no calls after shutdown admission.
sc_game_spatial_v1.find_zone size >= 32; 1.0 int (*find_zone)(const char* name, sc_game_zone* out);
Exact case-sensitive nonempty name of at most 95 bytes; copy the unique observed match only. Ambiguous, absent or possibly truncated names refuse. Does not discover unseen zones. out->size must be at least sizeof(sc_game_zone); preserve size and unknown caller tail. Outputs unchanged on 0.
Caller-owned copied records/buffers; opaque session IDs and epoch tokens, never pointers. Fixed 256-record storage; bounded temporary trees may allocate. No retained caller inputs or allocation transfer. Game thread only; non-reentrant; no callbacks. 1 success; 0 invalid input, wrong thread, missing readiness, unreadable/unstreamed/incomplete ancestry, expired epoch, ambiguous name or quota refusal. All outputs unchanged on 0. Synchronous read; no cancellation. Stop clears observations and expires epochs. Table lives until plugins unload; no calls after shutdown admission.
sc_game_spatial_v1.list_zones size >= 40; 1.0 int (*list_zones)(uint64_t epoch, uint32_t offset, sc_game_zone* out, uint32_t stride, uint32_t cap, uint32_t* out_count, uint32_t* out_more, uint64_t* out_epoch);
Copied page sorted by zone ID from at most 256 explicitly observed zones, never exhaustive world discovery. epoch=0 selects current set; nonzero epoch must match. Tick refresh, additions/changes, invalidation and stop expire epochs. cap at most 64; stride is aligned to 8 bytes and in [144,4096]; every offered slot has size at least 144. cap=0 allows NULL out and counts remaining entries. offset may equal total. out_count is copied elements; out_more is remaining after this page; out_epoch pins later pages. Validate all slots before writing; preserve caller size and unknown tails. Outputs unchanged on 0.
Caller-owned copied records/buffers; opaque session IDs and epoch tokens, never pointers. Fixed 256-record storage; bounded temporary trees may allocate. No retained caller inputs or allocation transfer. Game thread only; non-reentrant; no callbacks. 1 success; 0 invalid input, wrong thread, missing readiness, unreadable/unstreamed/incomplete ancestry, expired epoch, ambiguous name or quota refusal. All outputs unchanged on 0. Synchronous read; no cancellation. Stop clears observations and expires epochs. Table lives until plugins unload; no calls after shutdown admission.

Typed local-player loadout only, not account inventory. The game pack publishes a session-lifetime table even while its mutation capability is false. Current production composition installs no verified engine backend: every valid request returns UNAVAILABLE without engine access. See loadout for acceptance blockers. C/C++ native routes only; C# and sandboxed Lua mutation are unsupported.

Method Since Buffer / call contract Ownership Thread affinity Results Cleanup
sc_loadout_v1.apply size >= 16; 1.0 sco_result (*apply)(sco_plugin* self, const sc_loadout_request* request, sc_loadout_report* report);
Synchronous typed offline local-player equip: 1..16 unique slots (1.0 body slots 1..7; 1.1 adds weapon and multitool slots 8..21), fixed ASCII item classes, per-slot APPLIED/UNSUPPORTED/ITEM_MISSING/FAILED/UNAVAILABLE and applied count. Entire batch structural validation precedes engine calls; partial apply is not rolled back.
Caller owns full-size request/report and frozen item array (exact item_stride). No allocation transfer; inputs copied to bounded stack storage; pointers borrowed only during call. Only local player is targeted. Game thread only; WRONG_THREAD without output or engine access. BAD_ARG for null/foreign/released self, short structs, zero count, wrong stride, nonzero reserved fields, duplicate slots or malformed class; TOO_MANY above 16. Structural refusals leave report unchanged. UNAVAILABLE for missing engine/verification/capability/offline admission, with per-slot UNAVAILABLE. OK iff all applied; FAILED for partial/slot refusals or guarded backend fault. No pending requests, ownership tickets, persistence or unload rollback. Successful equip survives consumer unload. Table session-lifetime; stop withdraws after consumers unload. Backend fault disables apply until process restart; do not retry cached calls after shutdown.

See offline quantum. Production engine bridge unavailable; synthetic control-state evidence only.

Method Extent / since Buffer contract Ownership Thread Results Cleanup
sc_quantum_v1.enable size >= 16; 1.0 sco_result (*enable)(sco_plugin* self, uint32_t on);
on is 0 or 1. Claim the single controller after offline/drive admission; repeat enable by that owner is idempotent. Disable clears holding and ownership. Competing owner is refused.
Game pack owns one bounded controller lease and hooks; output copied to caller. No allocation or engine pointer transfer. Game thread only; WRONG_THREAD before state access. No recursive calls during bridge operations. OK, BAD_ARG invalid/released self or bounds, WRONG_THREAD, UNAVAILABLE absent bridge/drive/offline admission/stopped session, NOT_FOUND non-owner hold/release, FAILED competing owner or restart-required fault. Release cancels hold; disable/unload clears ownership; tick expires hold or cancels on lost admission. Stop withdraws and rolls back owned hooks. Uncertain bridge cleanup retains backing state/hooks and requires restart.
sc_quantum_v1.hold size >= 24; 1.0 sco_result (*hold)(sco_plugin* self, uint32_t milliseconds);
Refresh the owned hold lease for 1..1000 milliseconds from the latest game tick. No drive or any block refuses holding. Expiry is serviced by the next game tick.
Game pack owns one bounded controller lease and hooks; output copied to caller. No allocation or engine pointer transfer. Game thread only; WRONG_THREAD before state access. No recursive calls during bridge operations. OK, BAD_ARG invalid/released self or bounds, WRONG_THREAD, UNAVAILABLE absent bridge/drive/offline admission/stopped session, NOT_FOUND non-owner hold/release, FAILED competing owner or restart-required fault. Release cancels hold; disable/unload clears ownership; tick expires hold or cancels on lost admission. Stop withdraws and rolls back owned hooks. Uncertain bridge cleanup retains backing state/hooks and requires restart.
sc_quantum_v1.release size >= 32; 1.0 sco_result (*release)(sco_plugin* self);
Cancel holding while retaining enable and ownership. Repeated own release is idempotent. Unclaimed or foreign release is NOT_FOUND.
Game pack owns one bounded controller lease and hooks; output copied to caller. No allocation or engine pointer transfer. Game thread only; WRONG_THREAD before state access. No recursive calls during bridge operations. OK, BAD_ARG invalid/released self or bounds, WRONG_THREAD, UNAVAILABLE absent bridge/drive/offline admission/stopped session, NOT_FOUND non-owner hold/release, FAILED competing owner or restart-required fault. Release cancels hold; disable/unload clears ownership; tick expires hold or cancels on lost admission. Stop withdraws and rolls back owned hooks. Uncertain bridge cleanup retains backing state/hooks and requires restart.
sc_quantum_v1.state size >= 40; 1.0 sco_result (*state)(sco_plugin* self, sc_quantum_state* out);
Caller sets out->size to at least 32. Copy only the known prefix: enabled/held, phase, block, integer-millionth progress and opaque session generation. Unavailable observations return idle/zero and a block; early refusals leave output unchanged.
Game pack owns one bounded controller lease and hooks; output copied to caller. No allocation or engine pointer transfer. Game thread only; WRONG_THREAD before state access. No recursive calls during bridge operations. OK, BAD_ARG invalid/released self or bounds, WRONG_THREAD, UNAVAILABLE absent bridge/drive/offline admission/stopped session, NOT_FOUND non-owner hold/release, FAILED competing owner or restart-required fault. Release cancels hold; disable/unload clears ownership; tick expires hold or cancels on lost admission. Stop withdraws and rolls back owned hooks. Uncertain bridge cleanup retains backing state/hooks and requires restart.

Source: sc_cvars.h, semantics and exact allowlist. Read-only, verified offline game-pack port; production capability OFF until engine ABI/type verification. C/C++ supported; C# and Lua unsupported. No arbitrary console or config file access.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_cvars_v1.get_bool size >= 16; 1.0 sco_result (*get_bool)(sco_plugin* self, const char* name, uint32_t type, uint32_t* out);
Read one exact allowlisted SQ42 bool; copied 0 or 1, output unchanged on failure.
Live caller handle; copied output; host session-lifetime borrowed table; no allocation transfer. Game thread only; WRONG_THREAD elsewhere; non-reentrant (FAILED). BAD_ARG invalid name/type/output/self or released handle; UNAVAILABLE absent capability/admission/adapter/session; FAILED noncanonical backend bool; CRASHED adapter fault latches restart-required. No mutation in this table. Stop withdraws discovery and refuses cached calls; fault retains adapter context and prevents restart.

sc_cvars_write_v1 — game.cvars_write 1.0

Section titled “sc_cvars_write_v1 — game.cvars_write 1.0”

Source: sc_cvars_write.h, lifecycle and safe engine seam. Separate reversible write acceptance; the read table and frozen root ABI are unchanged. C/C++ supported; C# and Lua unsupported. Production requires verified offline read/write ports and cleanup.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_cvars_write_v1.restore_all size >= 24; 1.0 sco_result (*restore_all)(sco_plugin* self);
Restore this live owner’s first prior values; release only successfully verified leases, no-op OK if none.
Per-name exclusive live-owner lease; first prior bool retained before mutation; copied scalar inputs; no allocation transfer. Game thread only; WRONG_THREAD elsewhere; recursive calls refused. BAD_ARG unknown or released handle; UNAVAILABLE stopped/session-ended/terminal/fault admission; FAILED recursive call. Restore bypasses feature capability loss; engine failure or readback mismatch latches restart-required and retains unrestored leases. Explicit owner restore, ordinary release via existing spawn dispatcher, game.exit and stop restore first priors; failed restoration retains outstanding leases/context, no retry or replacement until process restart. Loader-retained provider faults skip owner hooks; host session/stop cleanup is independent.
sc_cvars_write_v1.set_bool size >= 16; 1.0 sco_result (*set_bool)(sco_plugin* self, const char* name, uint32_t type, uint32_t value);
Write a canonical bool to one exact allowlisted name; capture first prior value and verify readback.
Per-name exclusive live-owner lease; first prior bool retained before mutation; copied scalar inputs; no allocation transfer. Game thread only; WRONG_THREAD elsewhere; recursive calls refused. BAD_ARG invalid name/type/noncanonical bool/unknown or released handle; UNAVAILABLE admission/capability/adapter/cleanup missing or name held by another owner; engine failure or readback mismatch latches restart-required and retains unrestored leases. Explicit owner restore, ordinary release via existing spawn dispatcher, game.exit and stop restore first priors; failed restoration retains outstanding leases/context, no retry or replacement until process restart. Loader-retained provider faults skip owner hooks; host session/stop cleanup is independent.

Game-pack only. See offline missions design. No validated engine backend is installed; synthetic checks are not gameplay evidence. C/C++ direct table route; C# and Lua unsupported.

Method size / since buffer contract ownership thread results cleanup
sc_missions_v1.abandon size >= 56; 1.0 sco_result (*abandon)(sco_plugin* self, uint64_t mission_id);
Abandon an owned active mission once; repeated abandonment is a no-op. Completed missions refuse abandonment. Unload cancels local ownership; never retries uncertain native effects.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_missions_v1.accept size >= 32; 1.0 sco_result (*accept)(sco_plugin* self, const sc_mission_offer* offer, uint64_t key, uint64_t* out_mission);
Accept the exact current broker/offer/generation with a nonzero owner/session idempotency key. Duplicate identical requests return the original handle without another effect; changed input with the same key is BAD_ARG. At most 64 retained acceptance receipts per session; no eviction.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_missions_v1.advance size >= 48; 1.0 sco_result (*advance)(sco_plugin* self, uint64_t mission_id, uint32_t expected_phase);
Advance an owned active mission only after all objectives in its current phase. Duplicate old phase is a no-op; last phase becomes completed. This never pays a reward.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_missions_v1.ingest size >= 64; 1.0 sco_result (*ingest)(sco_plugin* self, const sc_mission_script* script);
Copy bounded declarative user-authored mission data for a validated data-relative name. No filesystem/network/executable-script access. Atomic validation; malformed/unknown content fails before backend calls; identical registration is idempotent, changed content needs restart.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_missions_v1.objective size >= 40; 1.0 sco_result (*objective)(sco_plugin* self, uint64_t mission_id, uint32_t phase, uint32_t objective);
Complete exactly the expected current phase/objective for an owned active mission. An already completed step is an idempotent no-op; forward skips, foreign handles and stale sessions are refused.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_missions_v1.offer size >= 16; 1.0 sco_result (*offer)(sco_plugin* self, uint32_t index, sc_mission_offer* out);
Bounded copied offline offer by index (0..255); NOT_FOUND at end. Caller output size must cover the whole record; size and unknown tails are preserved. No mutation authority.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_missions_v1.status size >= 24; 1.0 sco_result (*status)(sco_plugin* self, uint64_t mission_id, sc_mission_status* out);
Copied sanitized mission status for nonzero opaque ID and current session. NOT_FOUND for unknown ID; caller output size must cover the record.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.

Game-pack only. See offline missions design. No validated engine backend is installed; synthetic checks are not gameplay evidence. C/C++ direct table route; C# and Lua unsupported.

Method size / since buffer contract ownership thread results cleanup
sc_economy_v1.apply size >= 24; 1.0 sco_result (*apply)(sco_plugin* self, const sc_economy_request* request, sc_economy_receipt* out);
Apply one bounded signed local-wallet delta with expected-balance compare and nonzero owner/session idempotency key. Identical replay returns the first receipt; changed replay is BAD_ARG. No receipt eviction or automatic save/payout.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_economy_v1.balance size >= 16; 1.0 sco_result (*balance)(sco_plugin* self, sc_economy_balance* out);
Read the admitted offline local wallet as an integer in [0,1000000000000). No accounts or online balances; caller-sized output record is preserved.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.
sc_economy_v1.receipt size >= 32; 1.0 sco_result (*receipt)(sco_plugin* self, uint64_t key, sc_economy_receipt* out);
Read an owned session-local payment receipt by key. NOT_FOUND when absent, stale session or another owner. No persistent once-only guarantee across session restart.
Caller-owned copied buffers; no allocation transfer. Mutations scoped to live plugin and current offline session. Game thread only; WRONG_THREAD before backend access. OK on success; BAD_ARG invalid/short input or released handle; UNAVAILABLE absent backend/unsafe admission; NOT_FOUND unknown IDs; TOO_MANY bounded quota; FAILED refused progression/provider failure; CRASHED latches restart required. Outputs untouched on failure. Consumers unload before Stop. Released owners lose mutation authority. No automatic persistence or replay of uncertain effects. Native faults permanently close admission until process restart.

Source: sc_mining.h, provider, mining contract, C11 layout fixture and synthetic provider/release fixture. Off by default; production adapter unavailable. Accepted intent is not engine acceptance. C and raw C++ use the public table; C inline helpers guard complete callback extents. C# and Lua game.mining routes are unsupported. The fixture uses synthetic engine/admission callbacks and a release-dispatcher stand-in; no Windows SEH, native detour or gameplay execution is established. Process counters are observations, not a transactional snapshot; no game pointers cross the table.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_mining_v1.request size >= 16; 1.0 sco_result (*request)(sco_plugin* self, uint32_t enabled);
enabled is exactly 0 or 1. Accept or remove owner-scoped intent; repeated requests are idempotent. OK accepts intent even when engine/admission/hook is unavailable; read state to distinguish active. Disable also removes intent after a fault latch.
Up to 64 live owners retain independent intent; worker sees only aggregate count. Caller owns copied output; no native pointer or allocation transfer. Game thread only; WRONG_THREAD before owner/state access. Worker promotion never calls plugins. OK accepted intent, not engine acceptance; BAD_ARG invalid/released self or enabled; WRONG_THREAD; UNAVAILABLE stopped/runtime-stopping or reentrant call; FAILED full 64-owner registry. Disable/unload removes only that owner intent. Stop clears all intent and withdraws the service; detour, trampoline and callbacks remain process-retained in pass-through mode. Fault latch requires restart.
sc_mining_v1.state size >= 24; 1.0 sco_result (*state)(sco_plugin* self, sc_mining_state* out);
out.size must cover 40 bytes. Copy owner requested/active, refusal block and process cells/promoted/faults; successful observation can report refusal. Output size becomes 40; unknown tail untouched. OFF=0 is disabled or active without block; promoted counts forwarded bits, not spawned/harvested entities.
Up to 64 live owners retain independent intent; worker sees only aggregate count. Caller owns copied output; no native pointer or allocation transfer. Game thread only; WRONG_THREAD before owner/state access. Worker promotion never calls plugins. OK copied observation; BAD_ARG invalid/released self or null/short output; WRONG_THREAD; UNAVAILABLE stopped/runtime-stopping or reentrant call. Disable/unload removes only that owner intent. Stop clears all intent and withdraws the service; detour, trampoline and callbacks remain process-retained in pass-through mode. Fault latch requires restart.

game.private_session 1.0 (sc_private_session_v1)

Section titled “game.private_session 1.0 (sc_private_session_v1)”

Source: sc_private_session.h, provider, C11 layout pin and synthetic broker/provider fixture. C and raw C++ use the public table; no typed native wrapper is claimed. C# and Lua game.private_session routes are unsupported. Broker enablement is not socket/session enablement: fresh local UI Host/Join consent is mandatory; never synthesize consent from startup, settings, peer replay or retry. Numeric bind, exact private-address allowlist, admission and transport remain host-owned. Default enabled broker is loopback-only and opens no socket until Host/Join. The source-linked fixture uses synthetic transport with socket traps; it does not prove native UDP, real peer authentication or gameplay. ABI pins prove layout only. Request strings are declared UTF-8; byte bounds/NUL checks do not certify Unicode validation.

Method Size / since Inputs, outputs and buffer contract Ownership / allocation Thread / reentrancy Errors / absent capability Cancellation / cleanup
sc_private_session_v1.request_host size >= 16; 1.0 sco_result (*request_host)(sco_plugin* self, const sc_private_session_host_request_v1* request);
Complete 40-byte request; consent=1 only after fresh explicit local UI Host, reserved pad zero. Passphrase 12..256 bytes, player name 1..64 bytes, no embedded NUL; nonzero port and max_peers 2..16. Strings declared UTF-8. Unknown request tail ignored. Host rechecks admission and owns numeric bind/exact peer scope.
Host owns one session and its requesting owner; request strings are borrowed for the call and copied into host storage. Plugins receive no socket/bind/allowlist authority. Caller owns copied state. Game thread only; WRONG_THREAD before state access. OK host operation accepted, not authenticated connection; BAD_ARG malformed/bounds/released self; FAILED absent consent or broker failure; WRONG_THREAD; UNAVAILABLE disabled/stopping/reentrant, failed admission or occupied session; TOO_MANY four-attempts-per-second host-wide limit. Requesting-owner unload, explicit leave, admission loss or host stop leaves session. Stop withdraws service. Credentials are volatile backend state, not plugin-controlled persistent storage.
sc_private_session_v1.request_join size >= 24; 1.0 sco_result (*request_join)(sco_plugin* self, const sc_private_session_join_request_v1* request);
Complete 48-byte request; consent=1 only after fresh explicit local UI Join, reserved pad zero. Numeric IPv4 address 1..15 bytes, passphrase 12..256 bytes, player name 1..64 bytes and nonzero port; no embedded NUL. Strings declared UTF-8. Unknown request tail ignored. Host enforces private-address allowlist and admission.
Host owns one session and its requesting owner; request strings are borrowed for the call and copied into host storage. Plugins receive no socket/bind/allowlist authority. Caller owns copied state. Game thread only; WRONG_THREAD before state access. OK host operation accepted, not authenticated connection; BAD_ARG malformed/bounds/released self; FAILED absent consent or broker failure; WRONG_THREAD; UNAVAILABLE disabled/stopping/reentrant, failed admission or occupied session; TOO_MANY four-attempts-per-second host-wide limit. Requesting-owner unload, explicit leave, admission loss or host stop leaves session. Stop withdraws service. Credentials are volatile backend state, not plugin-controlled persistent storage.
sc_private_session_v1.leave size >= 32; 1.0 sco_result (*leave)(sco_plugin* self);
Leave only the requesting owner session; no owner is an idempotent OK. Another owner cannot leave it. No output buffer.
Host owns one session and its requesting owner; request strings are borrowed for the call and copied into host storage. Plugins receive no socket/bind/allowlist authority. Caller owns copied state. Game thread only; WRONG_THREAD before state access. OK left/already idle; BAD_ARG invalid/released self; WRONG_THREAD; UNAVAILABLE foreign owner, absent broker, runtime stopping or reentrant call. Requesting-owner unload, explicit leave, admission loss or host stop leaves session. Stop withdraws service. Credentials are volatile backend state, not plugin-controlled persistent storage.
sc_private_session_v1.get_state size >= 40; 1.0 sco_result (*get_state)(sc_private_session_state_v1* out);
out.size must cover 16 bytes; copy session state, peer count and configured host max_peers (0 for joiner/idle unknown). No owner handle is required. Output size becomes 16; unknown tail untouched. Admission loss leaves the session and returns UNAVAILABLE without copying output.
Host owns one session and its requesting owner; request strings are borrowed for the call and copied into host storage. Plugins receive no socket/bind/allowlist authority. Caller owns copied state. Game thread only; WRONG_THREAD before state access. OK copied state; BAD_ARG null/short output; WRONG_THREAD; UNAVAILABLE absent broker, runtime stopping, reentrant call or admission loss. Requesting-owner unload, explicit leave, admission loss or host stop leaves session. Stop withdraws service. Credentials are volatile backend state, not plugin-controlled persistent storage.

This is an inventory-complete catalogue, not a claim that the API has a complete behavioral specification. In particular:

  • Recursive reentrancy/depth, lock-acquisition latency, internal allocation bounds and worker-vs-unload quiescence are unspecified for most methods. Any-thread support alone does not establish them.
  • There is no general cancel-token API or promise to interrupt running calls. Queue drop, registration withdrawal, rollback, deferred despawn and a game action’s actual completion are different events; do not conflate them.
  • No universal failure-output, tail-zeroing or diagnostic-isolation rule exists. Some methods zero outputs, some leave them unchanged, some change required sizes and some can fail after producing a game side effect. Buffer-specific conditions above take precedence over broad header prose.
  • DataCore’s allocation-exception translation, concurrent commits/discards on the same patch and ordering of competing saved-file commits are unspecified.
  • spawn.entities failure-reason lifetime is unspecified; copy it during the call’s immediate use and do not free it. Tracking failure may follow a successful spawn.
  • game.vehicles / game.creative do not establish uniform released-self rejection or error-isolation guarantees; their last_error implementations need not enforce handle/service-start checks. Other game diagnostics also have no stopped-service refusal guarantee. Do not use stale handles merely because a table is still mapped.
  • Direct IPC view synchronization with peers/close/unload is unspecified by this service table; a borrowed mapping does not grant safe concurrent unmapping.
  • Watch/query-radius/state reserved behavior remains gated off; event vehicle-seat payload, actor health maximum and camera field of view are not filled from a verified live-game contract. Event payloads are not additional method rows; game services documents delivery and absent capability.

For additions, append a record under sdk/contracts/ and update the corresponding method row and inventory here. Run tools/sdk_catalogue.py check to compare both with compiled header declarations and member extents. A comment, signature or sibling service’s behavior is not evidence for an unstated guarantee on a new method.