S1API and S1Interop
Use S1API for gameplay workflows it already owns. Use S1Interop for direct ScheduleOne.* / Il2CppScheduleOne.* access that you do not want to hand-maintain across Mono and IL2CPP.
That direct access can live in a patch mod, an S1API content mod, or a hybrid project with both.
What S1API owns in your mod
S1API is a curated gameplay API. Keep using it when it already models what your mod is doing.
Use S1API for:
- items, products, stations, shops, money, and inventory workflows;
- custom NPCs, dealers, customers, schedules, dialogue, relationships, and appearance defaults;
- quests, phone apps, TV apps, UI helpers, law, cartel state, buildings, delivery locations, parking, and vehicles where the S1API wrapper is enough;
- save/load through
SaveableandSaveableField; - lifecycle events such as
GameLifecycle.OnPreLoad,OnLoadComplete,OnSaveStart, andOnSaveComplete; - packaged player installs where
S1APILoaderchooses the matching Mono or IL2CPP framework build at startup.
S1API owns registration timing, save/load semantics, content builders, loader packaging, and IL2CPP delegate quirks.
What S1Interop owns in a mod
S1Interop is generated interop. It is not an item builder, NPC scheduler, phone app framework, or save system.
Use S1Interop for:
- diagnostics and build hooks when you keep your existing S1API code and manual runtime branches;
- generated facades for direct
ScheduleOne.*andIl2CppScheduleOne.*types; - reducing duplicated
#if MONO/#if IL2CPPcode in direct patch mods, S1API-specific mods, and mixed projects; - backend-neutral Harmony patch targets for mods that patch vanilla Schedule One methods directly;
- moving an existing Mono mod toward IL2CPP support, dual-runtime builds, or backend-neutral builds;
- generating typed fields, properties, enum mirrors, constructors, and simple methods from local metadata when safe;
- diagnostics for missing declarations, bad member bindings, and IL2CPP boundary issues;
- migration, rollback manifests, local path setup, and sandbox verification;
- replacing copied or local reflection helpers when the mod only needs a stable generated member binding.
S1Interop should stay boring: make direct game access portable, then get out of the way.
Why both can exist
S1API makes domain decisions: NPC builder behavior, saveable load order, item ID validation, hidden prefab references, and similar gameplay rules. Generated code should not invent those rules.
S1Interop covers repetitive backend glue: runtime type names, member bindings, direct casts, cached reflection, and Harmony targets that differ between Mono and IL2CPP.
| Situation | Use S1API for | Use S1Interop for |
|---|---|---|
| Adding an item, NPC, quest, phone app, save data, or content workflow | The module that owns the workflow. | Direct game access the module does not expose. |
| Existing Mono and IL2CPP configurations | Gameplay workflows S1API owns. | Shared direct game access that can move behind generated facades while both configurations stay as validation targets. |
| S1API mod with a vanilla Harmony patch | Content registration and lifecycle. | Backend-neutral patch targets and nearby game member reads. |
| S1API mod that already handles both runtimes manually | The gameplay API dependency and loader behavior. | Diagnostics, build hooks, and narrow helper declarations without forcing a full generated SDK. |
Copied reflection helper or cached AccessTools binding |
Higher-level workflow, when one exists. | Generated bindings for Schedule One types and members. |
| One player-facing dependency with content helpers and loader behavior | Runtime packages and S1APILoader. |
Not this use case. The generator package is a build-time tool, not a gameplay framework. |
| Backend-neutral direct game SDK for types S1API does not wrap | Not this use case unless S1API adds that domain. | Type declarations and generated facades from local metadata. |
How to choose
If S1API supports the content workflow, keep that code in S1API. If the same mod needs a direct Schedule One type that S1API does not expose, use S1Interop for that gap instead of adding hand-written Mono/IL2CPP branches.
For an existing mod, start with s1interop analyze .. Keep your MelonLoader entry point, Harmony patches, logging, config, deployment scripts, and any S1API/MAPI/SteamNetworkLib dependencies. The first useful migration is usually one direct game access point, not the whole project.
For native Mono/IL2CPP mods, start with code that reads or invokes the same game member on both backends. For S1API-specific mods, start outside the S1API workflow: a Harmony target lookup, cached FieldInfo, local ReflectionUtils.TryGetFieldOrProperty(...), or direct game-wrapper cast. For hybrid mods, move in small pieces and keep both runtime builds as proof.
Boundary to keep clear
S1Interop works from local reference metadata. Do not commit, package, or redistribute Schedule One assemblies, generated IL2CPP wrappers, decompiled source, prefabs, scenes, textures, or exported Unity projects.
S1API and S1Interop can both inspect local game references during development. Public artifacts should contain mod/API source, generated declarations, and compiled mod libraries only when those libraries do not include proprietary game files.