The Simplified importer
The importer turns a player's mod (a .serps package, a zip of game files, a track zip) into an addon, and recognises what the mod is: a livery, a car model, handling, a helmet, an engine sound, a track, a team's identity. It writes those as registry records that other addons can stack on. Everything it doesn't recognise builds exactly as the converter made it.
For example, Macarena Red Bull becomes a livery record for the 2026 Red Bull plus a handling layer. R&D Tyres can then win the handling while the livery still loads.
What changes for one mod
Macarena Red Bull converts into mod.macarena-red-bull-v1-0: one overlay that writes 325 resources into redbull.erp. Two of them are handling files.
The importer writes a registry index next to the converted addon, and leaves the addon's own files alone:
mod.macarena-red-bull-v1-0/
swofty.json unchanged
ops/erp.json unchanged: the overlay, 325 resources
erp/overlay.erp unchanged
registry/content.json the livery record
registry/layers.json point the Red Bull at the livery; the two handling files, as their own layer
registry/raw.json every op, split into slices, each claimed by a record or kept raw// registry/content.json: "redbull_2026" becomes mod.macarena-red-bull-v1-0/redbull_2026
{
"livery": {
"redbull_2026": {
"vehicle": "game/redbull_2026",
"textures": { "erp": "erp/overlay.erp", "prefix": "eaid://f1_2026_vehicle_package/teams/redbull/", "kinds": ["textures", "materials"] },
"picker_name": "Macarena Red Bull"
}
}
}// registry/layers.json: a layer of vehicle "game/redbull_2026" and one of vehicle.handling "game/redbull_2026"
{
"vehicle": { "game/redbull_2026": { "livery": "mod.macarena-red-bull-v1-0/redbull_2026" } },
"vehicle.handling": { "game/redbull_2026": { "vtf": { "erp": "erp/overlay.erp", "resources": [
"eaid://f1_2026_vehicle_package/teams/redbull/handling/redbull.vtf",
"eaid://f1_2026_vehicle_package/teams/fom_car_redbull/handling/fom_car_redbull.vtf" ] } } }
}A file field (a Path) in a data file is usually a string: a file or folder in the addon. An imported mod's files sit inside the overlay archive the converter made, so the importer writes a path into that archive as an object:
{ "erp", "prefix", "kinds" }: every resource in the archiveerpwhose path starts withprefixand sits in one of the folders named inkinds(textures,materials,idf,wep).{ "erp", "resources" }: the named resources in the archiveerp.
erp is a path in the addon's folder, and resource paths are the archive's own eaid:// paths.
The livery and the handling are separate fields. When R&D Tyres layers vehicle.handling and loads after the mod, R&D's handling wins and the livery still loads. When the mod loads after R&D Tyres, the mod's handling wins, and the conflicts view offers the fix in one click:
{
"kind": "field", "registry": "vehicle.handling", "id": "game/redbull_2026", "path": "/vtf",
"addons": ["swofty.rnd-tyres-thermal", "mod.macarena-red-bull-v1-0"], "wins": "mod.macarena-red-bull-v1-0",
"fix": { "label": "Use only Macarena Red Bull's livery",
"choice": { "mod": "mod.macarena-red-bull-v1-0", "drop": ["vehicle.handling"] } }
}Where an import shows
What a player drops in becomes part of the base, the data every Grand Prix and Time Trial box and every career inherits, unless an addon sets its own value for that year:
- A livery (Macarena Red Bull) becomes a livery record and a layer on
game/redbull_2026. It shows in every box whose Red Bull is that base car. - A track zip (Hockenheim) becomes a track record that provides
venue/hockenheimring. It shows in every box's track select that it fits, with its base data. - An engine sound pack (V10) becomes
engine_soundrecords and layers on the base cars. It's heard in every box that uses those base cars. - A car port or a season pack asks once where it goes (see Season packs).
A year addon keeps its own look by setting its own value. Classic Seasons' 2017 Red Bull is a variant of the stock 2025 Red Bull that sets its 2017 livery, and a variant's own value beats layers on its base:
[registry] vehicle swofty.classic-seasons-2017/redbull: /livery set by the variant (2017 livery);
layer on game/redbull_2025 from mod.rb-singapore-by-pf126p not inherited for this field
[registry] vehicle game/redbull_2025: /livery -> mod.rb-singapore-by-pf126p/redbull_2025A year pack whose cars point at a stock file can pin it with stock("..."). The core then gives that year the original file, whatever an import put in its place. With Classic Seasons 2024 pinning the stock 2024 engine bundles, F1 2012's V8 sounds reach the stock cars and not the 2024 box.
To put a drop-in on a year's car too, the player adds that car in Applies to (see Applies to).
Recognisers
Each recogniser lives next to the applier it inverts, in packages/core/src/std/. A recogniser may only claim part of a mod if the applier rebuilds exactly that part, byte for byte. Anything else stays raw.
// packages/core/src/std/vehicle.rs
pub fn apply(id: &RecordId, v: &Vehicle, ctx: &mut ApplyCtx) -> Result<(), ApplyError>; // record -> ops
pub fn recognize(ops: &OpSlices, ctx: &RecognizeCtx) -> Vec<Claim>; // ops -> records
pub struct Claim {
pub record: Option<Record>, // a record under the mod's own key
pub layer: Option<Layer>, // or a layer on a game/ record or another addon's base
pub slices: Vec<SliceRef>, // the raw op slices it stands for
}What each recogniser looks for:
Track: a
track.addop from a track zip becomes trackmod.<id>/<track>. Its venue comes from the track's name in the mod, matched against the core's venue names, or from the player's choice on the importer page ("This track is: Sepang"). It never comes from the track's code:bahrain24is Sepang,hanoiis Valencia andmiami24is Igora Drive.Car archive: overlays of
2025_asset_groups/<pkg>/teams/<t>/wep/<t>.erp, split by resource path:teams/<t>/textures/andmaterials/become a livery;teams/<t>/idf/andwep/become the vehicle'smodel;teams/<t>/handling/*.vtfandfom_car_<t>/handling/*.vtfbecomevehicle.handling;teams/common*.erpandshared/generics/stay raw.
<pkg>/<t>is matched to agame/vehicle through the stock database (entrants.vehicles:asset_filename,vehicle_package), never a hard-coded folder list.Special livery:
se_liveryandunlockable_se_liveryrows plus<t><wep_override>.erpbecome a livery withspecial.Helmet: helmet archives and their item rows become a helmet.
Engine sound:
audio/2025/bundles/<maker>_<year>.bdlbecomes anengine_soundlayer on that maker.Identity: named team and driver rows and their text become
team.identityanddriver.identitylayers.Tyre visuals: slick texture arrays and their mipmaps become a
tyre.visuallayer.Season pack: car archives for 3 or more teams in one vehicle package become one vehicle per team, plus a dormant
content.packagevariant.
Everything else stays raw
Every op the addon has is listed in registry/raw.json, in build order, split into slices. Each slice is claimed by a record or kept, with the reason:
// mod.f1-2020-cars-for-f1-25/registry/raw.json (abridged)
{
"recognizer": 1,
"ops": [
{ "file": "ops/erp.json", "index": 0, "op": "overlay",
"target": "2025_asset_groups/animation_package/scenes/incardriver/2025/incardriver_f1.erp",
"slices": [ { "resources": 708, "claimed": null, "why": "no recognizer: in-car driver animation" } ] },
{ "file": "ops/erp.json", "index": 3, "op": "overlay",
"target": "2025_asset_groups/f1_2025_vehicle_package/teams/ferrari/wep/ferrari.erp",
"slices": [
{ "match": ["teams/ferrari/textures/", "teams/ferrari/materials/"], "claimed": "vehicle game/ferrari_2025 /livery" },
{ "match": ["teams/ferrari/idf/", "teams/ferrari/wep/"], "claimed": "vehicle game/ferrari_2025 /model" },
{ "match": ["teams/ferrari/handling/", "teams/fom_car_ferrari/handling/"], "claimed": "vehicle.handling game/ferrari_2025 /vtf" } ] }
]
}- Raw stays raw. Database drift from an older game build, in-car animation, shared archives, UI flows and tool junk are never claimed, and build exactly as the converter made them.
- Mods that haven't converted yet load through the importer's build hook, and stay raw until they convert.
Order and precedence
A mod's place is its addon's place in the profile's load order. The importer page lists imported addons in that order, and dragging one reorders the profile.
Imports and live layers are ordered by load order, in the game:
- Raw against raw: two imports, or an import and an addon's build operations. Per target (resource, record, text key, file, texture slice), the later one wins.
- A claimed field against a live layer: the core reads each import's claims from its
registry/raw.jsonand resolves them with every other layer, at the import's place in the load order. Per field, the later one wins. A claim that wins is already in the build. A claim that loses gives way: the core applies the winner's value over the built archive, and resources only the losing mod had stay, with a log line. - Two full liveries on one car: the later one replaces the earlier one whole. A partial livery, such as a number decal or a sponsor patch, covers only part of the car's texture set, and partial liveries stack per resource on top of the full one. The importer marks each recognised livery full or partial, and the importer page shows which.
- A player choice (a target, a dropped part, where a season pack goes) counts as a layer at the mod's own place.
[registry] vehicle.handling game/redbull_2026 /vtf: swofty.rnd-tyres-thermal (later) wins over
mod.macarena-red-bull-v1-0 (raw claim); the build's handling files for this field are replaced in game
[registry] livery game/redbull_2026: mod.rb-japan-gp (full, later) replaces mod.macarena-red-bull-v1-0 (full);
mod.redbull-numbers (partial) stacks on topThe launcher masks raw slices only for the player's choices. Masking needs one addition to erp.overlay: an except list of resources that the build skips. When nothing is masked, no except is written, and the build is byte-identical to the converter's.
Targeting another base
Applies to puts an imported part on more cars. It adds a target and keeps the original, so a livery can show on the stock car and on a year's car at once. A target that goes away (its addon turned off) leaves the others in place.
Liveries fit by car model. A livery is made for one car model, the files in cars::Vehicle::model. The picker lists only cars whose effective model is that model. A helmet fits any driver, and an engine sound fits any vehicle.
Macarena Red Bull livery · handling
Livery Applies to [x] Red Bull 2026 (stock)
No other car uses the 2026 Red Bull's model. Classic Seasons' 2016-2024 cars are ports with their own models.
Handling [x] Use the mod's handlingThe picker's list comes from what's installed: each addon's data files and its registry.lock.json, which lists the cars a code addon registers, plus the last session's registry/catalog.json.
An author may declare the target in mod.serps, in a block that older importers skip. The importer uses it as declared: the author knows which car the livery was painted on, even when the files sit in a stock car's folder.
// mod.serps: a livery painted on fanfreluche's F1 2017 Ferrari port, which uses the stock 2025 Ferrari folder
{
"mod_name": "Ferrari 2017 Monza", "author": "someone", "version": "1.0", "game_version": "1.0.141.7865",
"swofty": {
"targets": [ { "kind": "livery", "from": "game/ferrari_2025", "to": "swofty.classic-seasons-2017/ferrari" } ],
"requires": [ { "record": "content.package:swofty.classic-seasons-2017/f1_2017" } ]
}
}[import] livery mod.ferrari-2017-monza/ferrari_2025: target swofty.classic-seasons-2017/ferrari declared by the
author in mod.serps; the files sit in the game/ferrari_2025 folderPlayers pick only from cars that fit. The choice is saved in importer.json, keyed by what it acts on (see A new version of a mod).
Season packs and their own entry
A car pack for a whole season (fanfreluche's F1 2020 cars, F1 2012 Temporada) is recognised team by team. It also provides a dormant content.package variant:
{
"vehicle": {
"ferrari": { "extends": "game/ferrari_2025",
"model": { "erp": "erp/overlay-4.erp", "prefix": "eaid://f1_2025_vehicle_package/teams/ferrari/", "kinds": ["idf", "wep"] },
"livery": "mod.f1-2020-cars-for-f1-25/ferrari", "handling": "mod.f1-2020-cars-for-f1-25/ferrari" }
},
"vehicle.handling": {
"ferrari": { "vtf": { "erp": "erp/overlay-4.erp", "resources": [
"eaid://f1_2025_vehicle_package/teams/ferrari/handling/ferrari.vtf",
"eaid://f1_2025_vehicle_package/teams/fom_car_ferrari/handling/fom_car_ferrari.vtf" ] } }
},
"content.package": {
"f1_2020": { "extends": "game/f1_2025", "title": "F1 2020 cars for F1 25",
"teams": [ { "key": "ferrari", "vehicle": "mod.f1-2020-cars-for-f1-25/ferrari" } ] }
}
}A car port or season pack asks once, when it's imported, where it goes:
F1 2020 cars for F1 25 replaces 10 cars.
Where (o) Grand Prix and Time Trial only ( ) Everywhere, careers included- Grand Prix and Time Trial only is the default. The pack's cars show in Grand Prix and Time Trial, and careers keep their own cars. Swapping car archives between modes within one game run needs reverse engineering of how the game loads them per session.
- Everywhere replaces the cars the pack changes in every mode, careers included: Progressive's 2025 season races the 2020 cars.
- Own GP/TT entry (a switch on the importer page) gives the pack its own cloned vehicle package and an era box, the way Classic Seasons builds
cs_2017_*. Two car packs can then be installed side by side, instead of both writing the same ten team slots. - Raw parts stay global. In-car driver animation,
teams/common.erp, menu flows and tyre textures aren't recognised, and still apply in every mode.
Single liveries, helmets and sounds don't ask: they go everywhere.
A new version of a mod
The importer recognises a new version of an installed mod by its lineage: its mod.serps author and title, or, for a zip, its file name without the version and byline plus the parts it changes.
Macarena Red Bull V1.1 looks like an update of Macarena Red Bull (V1.0).
[Update] keeps its place in the load order and your choices [Install side by side]The player's choices are keyed by what they act on, not by the mod's own record ids, so they carry over to the update:
// importer.json
{ "lineage": "macarena-red-bull", "drop": ["vehicle.handling@game/redbull_2026"],
"targets": { "livery@game/redbull_2026": ["vehicle:game/redbull_2026"] } }- A choice that matches nothing in the new version is dropped, with a notice.
- A target the new version doesn't fit is removed, with a notice. The livery stays on its other targets.
- New parts are listed as "New in this version".
- Tracks: an import with the same track code but a different author or lineage asks the player. It never replaces the installed track silently.
Existing imports
On upgrade, a startup pass indexes every already-imported mod in place:
[import] index mod.macarena-red-bull-v1-0: 325 resources claimed (livery 323, vehicle.handling 2), 0 raw; round trip ok
[import] index mod.f1-2012-season-v1-0-bydanix: 2,114 claimed, 4,312 raw (database drift from an older game build)- Nothing is reconverted. The pass writes only the new files.
ops/, the archives andswofty.jsonkeep their bytes, and the build hash doesn't change. - Two full liveries on one car in an existing profile keep their asset-by-asset mix until the player presses the fix in the conflicts view.
- Car ports and season packs already installed keep reaching every mode until the player changes where they go.
- Launcher 1.5 builds the same profile as before.
swofty.jsonis untouched, and launcher 1.5 never opensregistry/. - The importer itself ships a new major release that needs launcher 1.6. Launchers of 1.5 and earlier keep getting the newest 0.11.x.
What the importer provides
The importer owns three registries under its own id:
teamsimplified.mods.package: one record per imported mod: its source file and hash, its lineage, its parts and variants, the records it provides, its raw count and the player's choices;teamsimplified.mods.raw: each mod'sraw.json, for Send Logs and the triage bot;teamsimplified.mods.rule: path rules other addons provide, so mods made against their files are targeted automatically. Classic Seasons 2017 can say thatcs_2017_vehicle_package/teams/<t>/isvehicle swofty.classic-seasons-2017/<t>.
swofty mods show <id> records and raw slices of one import
swofty mods target <id> <record> <base> add a target to a recognised record
swofty mods recognize --check [<id>] re-run the round trip without writingThe release gate for the importer
- Round-trip tests: for each recogniser, applying the claims of a real mod gives the exact ops the converter made.
- Golden builds: every imported mod in the player bundles the triage bot has, built on 1.5.19 and on 1.6, with byte-identical game files.
- A downgrade build: a 1.6-indexed profile builds on 1.5.19 exactly as before.
- Masking, targeting, lineage updates and where a season pack goes, each with an in-game check.