SBC

From Space Engineers Wiki
Jump to navigation Jump to search

Things to know

This is all the things one should know about SBC before proceeding to mod them.

Click the boxes for more details on that subject.

The .sbc extension must be lower case letters!
The .sbc extension must be lower case letters!
The game will simply not load your file if it's .SBC or .Sbc or etc.
The contents of .sbc files is in XML format.
The contents of .sbc files is in XML format.
If you've never used XML (or HTML or any other markup language that uses <node>stuff</node> format) then you should look up tutorials on the internet on how the syntax works.
If you find some other sb* file (.sbx, .sbs, etc) then those are also likely to be XML format. One exception are the sbcB5/sbsB5 files which are in binary.
Copy .sbc files from the game folder to your local mod.
Copy .sbc files from the game folder to your local mod.
In the <Game>\Content\Data folder and copy them to your local mod where you can edit them.

If you don't know what a local mod is, you've skipped an important step: Setting up a modding environment

Once you copied a .sbc file from the game, should only keep the definitions you want to override! For example if you copy Content\Data\CubeBlocks\CubeBlocks_Production.sbc and you only want to change reactors, then delete the other blocks from the file.

Refer below on what definitions are to know what to delete.
Game will load all .sbc files from your mod's Data folder and any subfolders.
Game will load all .sbc files from your mod's Data folder and any subfolders.
That means the names of the .sbc files do not matter, only that they end with .sbc and their contents is important.
What are 'definitions' and how are they stored in game memory?
What are 'definitions' and how are they stored in game memory?
In sbc files in particular, a definition is a chunk of XML that defines one thing, for example a block or a component or a character or anything that has the <Id> node.

The individual nodes for CubeBlocks are even called Definition.

See the example XML at the end of this section.
How does the game decide which to override and which to add as new?
How does the game decide which to override and which to add as new?
The <Id> node that is present on all definitions is what defines how it's stored (one exception is BlockCategories which ignores SubtypeId in Id node and instead uses the Name node to determine what to merge to).


If you use the same TypeId+SubtypeId that already exists then you're overriding that definition.
However if you use a unique combination of those (SubtypeId can be invented) then it's added as a new definition.

NOTE: TypeId cannot be invented and also usually requires to be paired with an xsi:type="..." for it to be properly loaded.
Highly recommended to not change TypeId on something and instead copy the definition from a vanilla file for that type instead, and then modify the subtype and other nodes on that.

NOTE: Definitions are generally fully overwritten, meaning if you don't declare a node (for example <Model>) then it will use the default value hardcoded in the game code.
For more details see below at Definitions that get overwritten vs additive vs merged

SubtypeIds as you may have noticed are not globally unique, only when paired with a TypeId it becomes a full ID and that is what makes it unique.

For example, the game itself uses the empty SubtypeId in 5 different blocks (which is also a valid one but not recommended to use in mods), but they're all different types so it works without a problem.
How are assets (models, textures, sounds) used?
How are assets (models, textures, sounds) used?
All assets require something to reference them, usually .sbc and sometimes models or even scripts.
See the Assets page for more details.
Definitions that reference other definitions
Definitions that reference other definitions
Most of the time they will only ask for a SubtypeId, but some will ask for a full Id, and some will even require the MyObjectBuilder_ prefix of the TypeId, which will often lead to confusion with the xsi:type.

NOTE Never input the value from xsi:type anywhere else that requires an ID. The xsi:type is only used by the game to know what object to deserialize it as.

For example:

<Definition xsi:type="MyObjectBuilder_LargeTurretBaseDefinition">
    <Id>
        <TypeId>LargeGatlingTurret</TypeId>
        <SubtypeId>SmallGatlingTurret</SubtypeId>
    </Id>
    <!-- other nodes not relevant to the example -->
</Definition>

And when you see BlockVariantsGroups being like this:

<?xml version="1.0" encoding="utf-8"?>
<Definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <BlockVariantGroups>
        <BlockVariantGroup>
            <Id Type="MyObjectBuilder_BlockVariantGroup" Subtype="TurretGroup" />
            <Icon>Textures\GUI\Icons\Cubes\gatling_turret.dds</Icon>
            <DisplayName>DisplayName_BlockGroup_TurretGroup</DisplayName>
            <Description>Description_BlockGroup_TurretGroup</Description>
            <Blocks>
                <Block Type="MyObjectBuilder_LargeGatlingTurret" Subtype="" />
                <Block Type="MyObjectBuilder_LargeGatlingTurret" Subtype="SmallGatlingTurret" />
                <Block Type="MyObjectBuilder_LargeMissileTurret" Subtype="" />
                <Block Type="MyObjectBuilder_LargeMissileTurret" Subtype="SmallMissileTurret" />
                <Block Type="MyObjectBuilder_LargeMissileTurret" Subtype="LargeCalibreTurret" />
                <Block Type="MyObjectBuilder_LargeMissileTurret" Subtype="LargeBlockMediumCalibreTurret" />
                <Block Type="MyObjectBuilder_LargeMissileTurret" Subtype="SmallBlockMediumCalibreTurret" />
                <Block Type="MyObjectBuilder_InteriorTurret" Subtype="LargeInteriorTurret" />
                <Block Type="MyObjectBuilder_LargeGatlingTurret" Subtype="AutoCannonTurret" />
            </Blocks>
        </BlockVariantGroup>
    </BlockVariantGroups>
</Definitions>

Your immediate reaction is to use the big name that starts with MyObjectBuilder_ from xsi:type, which as mentioned in the note before is not the right one.

These are the ones you need to focus on:

<TypeId>LargeGatlingTurret</TypeId>
<SubtypeId>SmallGatlingTurret</SubtypeId>
LargeGatlingTurret is the same as MyObjectBuilder_LargeGatlingTurret because the game will often accept either.
The sbcB5/sbsB5/etc files are binary caches
The sbcB5/sbsB5/etc files are binary caches

The sbc/sbs files with a B5 suffix in their extension are binary caches that allow the game to read them significantly faster compared to parsing XML.

These binary files will be automatically generated for files that use a cache like this: prefabs, saves, and blueprints to name a few.

Changes to a sbc file that has a binary cache requires that the binary cache is deleted for the game to read the changes.

Here's an example .sbc contents that defines a block and an item in the same file:

Example .sbc to identify what are the definitions
Example .sbc to identify what are the definitions
<Definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <CubeBlocks>
    
        <Definition> <!-- this is a definition from here to its end-node (</Definition>) -->
            <Id>
                <TypeId>CubeBlock</TypeId>
                <SubtypeId>LargeBlockArmorCornerSquare</SubtypeId>
            </Id>
            <!-- some other nodes that are not relevant to the example -->
        </Definition>
        
    </CubeBlocks>

    <PhysicalItems>
    
        <PhysicalItem> <!-- this is also a definition from here to its end-node (</PhysicalItem>) -->
            <Id> <!-- this is what defines what it's indexed as -->
                <TypeId>Ore</TypeId>
                <SubtypeId>ExampleItemA</SubtypeId>
            </Id>
            <!-- some other nodes that are not relevant to the example -->
        </PhysicalItem>
        
        <PhysicalItem>
            <Id>
                <TypeId>Ore</TypeId>
                <SubtypeId>ExampleItemB</SubtypeId>
            </Id>
            <!-- some other nodes that are not relevant to the example -->
        </PhysicalItem>
        
    </PhysicalItems>

    <!-- WARNING: do not open a list-node (<CubeBlocks>, <PhysicalItems>, etc) twice or more in the same file, because you will override the previous declaration -->

</Definitions>

Advanced topics

Default values
Default values

The defaults you see in the various definition pages are the defaults from the game code, not the vanilla sbc!

It's the value that it will have if you don't write it in your sbc, with some exceptions for definitions that are additive or merged as opposed to the regular override.
TypeId vs xsi:type
TypeId vs xsi:type

The data in TypeId is what the object will become (some TypeIds will use the *Definition stuff, just follow whatever the game does).

While the xsi:type is the template for deserializing the XML data for this specific element. This is used when the element is of a base type but the higher element needs an inherited type.

For example:
<Definitions ...>
    <CubeBlocks>
        <Definition xsi:type="MyObjectBuilder_LightingBlockDefinition">
            <Id>
                <TypeId>InteriorLight</TypeId>
                <SubtypeId>SmallLight</SubtypeId>
            </Id>
            ...

In this the <CubeBlocks> is a list of MyObjectBuilder_CubeBlockDefinition but in order to have special light stuff it uses the xsi:type for MyObjectBuilder_LightingBlockDefinition.

All this only means the definition will end up being a lighting block definition, that however doesn't affect the spawned block in any way without it also being a <TypeId> that even cares to read the definition as lighting block one.

That's where the <TypeId>InteriorLight</TypeId> comes in and as you may've noticed it's not named in a similar way, and unfortunately there's no direct mapping in the game code, it's only that the InteriorLight is the one that looks for the lighting block definition stuff and uses them, and that happens in its actual code.

The CubeBlocks page has all the block types and their known xsi:type listed so you do not have to guess.
Why some vectors are inline and others are not?
Why some vectors are inline and others are not?
For context:

The difference is in the type used in the back-end:

  • SerializableVector3 has support for both x/y/z attributes and X/Y/Z elements.
  • Vector3 only has X/Y/Z elements.

The same applies to other elements where you see them inline and others have elements, it's just how the programmer felt to define those at the time.

More about XML elements vs attributes.

Important: Attributes and elements are not interchangeable, do not change their format or letter case.

Definitions that get overwritten vs additive vs merged

Vast majority of definitions get fully overwritten when the same TypeId+SubtypeId already exists.

A few definition types act differently:

Quick reference

How are some definitions linked

  • Blocks: CubeBlock is essential, Components is what can be used to build them, BlueprintClassEntries to add them to assemblers, BlockCategories for Build Menu categories on the left and BlockVariantGroups to combine more blocks into one icon that can be scrolled through.
  • Weapons: CubeBlock -> WeaponDefinition -> AmmoMagazine -> Ammo.
  • Production: CubeBlock -> BlueprintClass -> BlueprintClassEntries -> Blueprints.
  • Inventory and more: EntityContainers links entity(block) to EntityComponent, then EntityComponents defines the component data.
  • In various definitions there's <PhysicalMaterial>SubtypeHere</PhyiscalMaterial> which point to PhysicalMaterials.sbc and then MaterialProperties.sbc defines how they react when they interact.
  • Hand weapons/tools: HandItems, PhysicalItems, AnimationControllers, Blueprints.
  • Random loot in containers: ContainerTypes.sbc and then <ContainerType>SomeSubtypeId</ContainerType> in the prefab at the container block (search vanilla prefabs for ContainerType to see an example).
  • NPC ships: CargoShips/Encounters/SpawnGroups, PirateAntennas, PirateDrones, DroneBehaviors, GlobalEvents

For more details see Tutorials and Reference

Definitions that are not designed to be modded

  • AssetModifiers\AssetModifiers.sbc & ArmorModifiers.sbc
    • Adding new ones won't show up in the picker GUIs because those that show up there are tied to Steam items or DLCs.
    • Does not look in mod folder for textures.
    • Is not additive so you have to copy the entire definition meaning you'd be undoing any additions Keen makes to skins after the release (which they have done).
  • GuiTextures.sbc - broken modding support, cannot use textures from mods (BugReport).
  • ControllerSchemes.sbc - no reason to do this except for singleplayer, also seems to to not work to add new ones to select from controls GUI.
  • MainMenuInventoryScenes.sbc - mods only get loaded when a world starts, this would have no effect.
  • WheelModels.sbc - the game code using this is turned off.
  • Game\DLCs.sbc - mostly informational, not useful to mod at all.
  • RadialMenu.sbc - see page for details.

Other files:

  • Screens\*.gsc - they're also XML but the game only looks for them in the game folder and with the exact names.
  • Scenarios.sbx - only sbx that gets loaded, and only this particular name from the game folder, therefore cannot be modded; a mod script might be able to edit the resulting definition object though.
  • Tutorials.sbx - not used at all.