Map Editor Documentation

Compatibility & Versioning

Every version number a map or mod carries, what the game enforces about each today, and the policy for how formats change without breaking published content.

Page 17 of 22

A map made today should still play next year, and a mod should say clearly when it needs a newer game. This page lists every version number involved, exactly what the game does with each one today, and then the policy for changes going forward.

The two halves are kept apart on purpose. The first section describes code. The second describes a commitment, and is labelled as one.

The version numbers

NumberWhereCurrentWhat the game enforces
Game versionthe game itself0.3.4Mods: compared with minEngineVersion.
Build fingerprintthe game itselfper buildMultiplayer: every player must be on the same build.
Map format vv in a map file2Absent means 1. 1 is migrated on load; higher is refused.
Trigger script versiontriggers.version1The validator rejects anything but 1.
Mod format formatVersion.sosmod2Absent means 1. 1 and 2 load; higher is refused.
Mod version.sosmodyoursUsed by dependencies ranges and the multiplayer checksum.
minEngineVersion.sosmodyoursA game older than this refuses the package.
Save code formatinside every save code1Only format 1 codes load.

Game version

The game's version is the one in its release (0.3.4 at the time of writing). The validator reports it as engineVersion in every response from /api/validate.

Multiplayer is stricter than the version number. Each build of the game carries a fingerprint of its source, and players must match it exactly: a lobby hosted on a different build is greyed out in the game list with "Hosted on build X — you are on Y", because two builds cannot be guaranteed to simulate a match identically. Refreshing the page picks up the latest build.

Map format

A map file carries v. Version 2 changed which player owns neutral creeps. A version 1 map is migrated when it loads, which is how the game's older bundled maps still play.

A map whose v is newer than the game understands is refused rather than guessed at. Playing it shows "This map was made with a newer version of Shards of Stone — update to play it", and the validator reports the same message as an error at $.v, so it can't be published either. A map with no v loads as version 1. The published JSON Schema also restricts v to 1 or 2.

The editor's own draft format (what File → Save stores in your browser) has version: 1. New fields have only ever been added as optional, which is why older drafts still open.

Trigger script version

Every trigger script says "version": 1. The validator treats any other value as an error, which blocks saving and publishing. Every language feature added since (functions, locals, hashtables, camera actions, new events) has been added as new optional fields and new node kinds, so the version has not had to change, and a script written before those features validates today.

Mod format and minEngineVersion

formatVersion says which version of the .sosmod layout a package uses. Version 2 added list operators, deep merging, upgrade and hero overrides, mod: model references, dependencies and minEngineVersion. A version 1 package (or one with no formatVersion) is read with the version 2 rules, which were designed so that every version 1 patch merges exactly as it did.

A package with a higher formatVersion than the game reads is refused with "This package uses mod format N, but this game reads up to format 2".

minEngineVersion is compared with the game version. A package that needs a newer game is refused with "This package needs game version X or newer". Set it to the version you tested on when your mod uses a feature that is new.

Dependencies

A dependency names a mod id and a version range (1.2.3, ^1.2.0, ~1.2.0, >=1.2.0, *; see Mods). A missing dependency, a version outside the range, or a cycle refuses the launch.

Multiplayer map checksum

When a custom map is played in multiplayer, the host sends the map (with any mods already merged in) and a checksum of the map plus the mod's id and version, including its dependencies' versions. Every player checks it before the match starts. A mismatch stops the match with Map integrity check failed, rather than letting it desync later.

Save codes

A save code starts with SOS-9. The 9 is the format version. Codes in any other format are rejected, including an unkeyed format that existed briefly before format 1 and was never used by a published map.

A code is tied to its map through saveCodeSalt. If a map does not set one, the salt is map: plus the map's name, so renaming the map invalidates every save code players hold. Set saveCodeSalt explicitly before your first publish and never change it.

Published maps

Saving a published map from The Forge updates it in place: the same id, so the same share link, and players get the new version next time they load it. The update is refused if the new version has validation errors. There is no version history on the server, so keep your own copies (File → Export Map JSON…) if you want to be able to go back, and use Save As Copy when you want the old version to stay playable alongside the new one.

A match already in progress is unaffected by an update. In multiplayer, every player receives the host's copy of the map, so players can never be on different versions of it within one match.

Policy going forward

This section is a policy: a statement of how the maintainers intend to change the formats. Where it goes beyond what the code above enforces, that is noted.

  1. Additive by default. New features arrive as new optional fields and new node kinds. An existing valid map, trigger script or mod keeps validating and keeps behaving the same.
  2. A version number changes only for a breaking change. A breaking change is one where an existing valid file would be read differently. When that happens, the format's version number goes up, and the game keeps reading the old version, either directly or through a migration on load, as it already does for map format 1.
  3. Unknown newer versions are refused, not guessed at. A file claiming a newer format than the game understands should fail with a clear message. Today maps and mod packages are refused when they load, and trigger scripts are refused by the validator (the match loader does not check the trigger script version).
  4. Balance changes are not format changes. The game's own unit numbers change between releases. A map that patches a unit changes only the fields it names, so a later balance change to other fields still reaches the map. If your map depends on an exact number, set that number in its data overrides.
  5. Ids are stable. Shipped unit, building, item, spell and upgrade ids are not renamed without an alias or a migration, because maps reference them. The validator will tell you if a map names an id that no longer exists.
  6. Save codes stay loadable. A save code format, once used by published maps, is kept readable.
  7. Deprecations are announced in the release notes before removal, and the validator should report a warning for deprecated fields in the meantime. (No field is deprecated at the time of writing, and the validator has no deprecation warnings yet.)

For authors

  • Put $schema and formatVersion in every mod, and set minEngineVersion when you use something new.
  • Follow semantic versioning in your mod's version: bump MAJOR when you rename or remove an id other content may depend on, MINOR when you add, PATCH for fixes. Dependency ranges like ^1.0.0 only protect players if you do.
  • Set saveCodeSalt before first publish.
  • Validate against the current game before every release: npx tsx tools/validate.ts or /tools/validator.

Next: AI Creators.