SUNRISE STUDIO

How projects store edits

A project is a folder with a sunrise.project.json manifest. It holds its changes as differences from the installed game, never as copies of game data. The manifest also holds the optional mod details.

contentstored as
object editsvalues per world object, in the manifest
byte deltasfiles under deltas
added assetsfiles under assets
config bindings and wide-hash aliasesentries in the manifest
object names and object groupsentries in the manifest; the build ignores them
mission scripts and helpersplain Lua under scripts
own SDK modulesplain Lua under sdk

Installation paths and preferences stay outside the project. The build folder and exported working copies are disposable. Undo history lives in memory for the session only.

Byte deltas

A byte delta records how an asset’s bytes differ from the installed original. It holds source hashes, copy ranges and XOR masks. It never stores unchanged byte ranges or an extracted original.

Property edits, byte edits, imports, and material and texture edits save byte deltas. Insertions, deletions, growth and derived copies all rebuild against the matching original. If the installed original’s hash differs, Studio cannot rebuild the asset, and the build stops.

Object edits

An object edit records the values set on one world object: position, rotation, scale or trigger bounds. Rotation is a unit quaternion.

layoutrow
Placementa placement row in a placement table
SlotPlacementa placement row under a type-4 slot of a config
StaticInstancea static instance row
Lighta light transform row
SpawnPointa spawn row
TriggerVolumea trigger volume row; bounds only
CollisionInstancean instance in a static collision compound
DecoratorInstancea SpeedTree decorator record

The placement editor saves them. A collision import, a collision part move and a group move save one for each moved collision instance.

  • One object has one entry. A later edit of the same object replaces the values it sets and keeps the others.
  • A value that was not set keeps its installed bytes.
  • Each entry names its source row and the SHA-256 of that row’s installed bytes. If the installed row changes, Studio refuses to build until the edit is reverted.

Object groups

A group stores an id, a name and its objects. Each object is stored as the same row reference an object edit uses: the source tag, layout, offset, length, index, identity and the hash of the installed row. The row offset alone cannot find some objects again, so the whole reference is kept. Move, rotate and scale objects has the steps.

A group can also store collision parts. Each part is stored as one text key: its entity, its list row, compound instance, shape tag and offset, bone, its place among equal placements, and its smallest shape key. A part number would change when a shape is edited. The shape key does not.

Moving a group saves an object edit for each object. Its collision parts move as a collision edit in the same undo step: instance moves become object edits, shape changes become byte deltas.

How byte deltas and object edits combine

Studio applies byte deltas first, then object edits on top. Where both change the same bytes, the object edit wins, and the Changes panel lists both. The preview, Build packages, Build and install and Update running game all use this one result.

A byte delta that would stop an object edit from compiling is refused when it is saved. Revert the object edit first. A Blender bundle import keeps object edit values out of the byte deltas it saves.

How object edits compile

The object edit compiler knows the row layouts. The project only checks each target row against its installed hash.

  1. The compiler starts from each tag’s byte-delta result.
  2. It writes every edit in key order.
  3. It runs its rules in a fixed order. A rule gets every edit of its layouts in one call.

Some rules run only in a build, because they are slow. The editor compile skips them, so the viewport and the Changes panel do not show what they write. The project caches each kind of result for each saved manifest. The catalog overlay reads the editor result. The build and the mod installer read the build result.

Values that depend on an edit are rebuilt from the installed original every time, so they never go stale.

rulerebuilds
InstanceBoundsRulea static instance’s bounds row and its table’s aggregate box
OcclusionTomeRulethe bubble’s occlusion tomes; build only
InstanceCullRulethe culling data
StaticCollisionRulethe static collision, and moved collision instances
DecoratorInstanceRuleSpeedTree decorator records, their vertex buffer, and the cell and payload boxes

A decorator value outside the block’s stored range re-quantizes the whole block. A decorator payload that shares its instance data with another payload is refused, because an edit would move both. Static collision internals has the collision details. The build receipt lists each object edit and the assets it wrote. A rule that leaves an asset unchanged, such as a tome it cannot edit, adds a note. The build still succeeds; the build message shows the notes and the receipt keeps them under objectEditNotes.

Added assets

An added asset is stored whole under assets, or as a delta of an installed entry when it keeps that entry’s fields. The second kind shows as Derived in the Changes panel.

kindin builds
Addedyes, as a new native entry
Derivedyes, rebuilt from its installed base
Sourceno; kept for external work

An import prepares a copy of its input before it saves one asset group. Cancelling before the save leaves the project unchanged. Undo removes the group. Redo restores the same asset IDs and entry numbers. A changed project or installed source refuses publication and needs a fresh import.

Package IDs

New native assets go into new packages. Use an unused package ID from 0100 to 0CFF. The game refuses higher IDs. A project saved with a higher ID still opens, but its build is refused. Entries with the same ID share one package.

A new entry’s tag is 0x80800000 + (package << 13) + entry.

Manifest versions

Studio writes the lowest manifest version that can store every feature the project uses.

versionneeded for
1byte deltas and added assets only
2object edits
3wide-hash aliases
4config bindings
5object names (objectNames), editor labels the build ignores
6object groups (objectGroups), editor groups the build ignores
7collision parts in object groups (collisionParts)

Removing a feature lowers the version again. An older Studio refuses a newer manifest, so it cannot silently drop edits. Byte deltas in an older project stay byte deltas until they are converted. See Convert placement deltas.

Saving

Changes save on their own. Each save replaces the manifest atomically. Payload edits that belong together publish together.

Limits

  • An object or a collision part is in one group at most.
  • A group holds up to 4096 objects and up to 50,000 collision parts.
  • Trigger volumes and collision instances cannot join a group.
  • Object and group names are one trimmed line of up to 200 characters.