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 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 is ones ending with B* (currently B5, for example saves have .sbsB5 besides .sbs), those are binary caches that allow the game to read them significantly faster, these are usually generated when the file without B* suffix is loaded.
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.
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 we refer as "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?

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?

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

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, the game will automatically append that prefix before checking if it exists.


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
<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 close and re-open the same list-node (<CubeBlocks>, <PhysicalItems>, etc) in the same file because you will override the previous one! -->

</Definitions>

Definitions that get overwritten vs additive vs merged

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

Only a few act differently and those are listed below:

Merged: <Definition xsi:type="EnvironmentDefinition"> (Environment.sbc)

This means you can include only the nodes you wish to change + <Id> node!

An example of an environment definition that only changes ship max speeds:

<?xml version="1.0"?>
<Definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Definition xsi:type="EnvironmentDefinition">
        <Id>
            <TypeId>EnvironmentDefinition</TypeId>
            <SubtypeId>Default</SubtypeId>
        </Id>
        <SmallShipMaxSpeed>100</SmallShipMaxSpeed>
        <LargeShipMaxSpeed>100</LargeShipMaxSpeed>
    </Definition>
</Definitions>
and another mod can change only the skybox in the same manner and both mods will work at the same time.
Additive: <Category xsi:type="MyObjectBuilder_GuiBlockCategoryDefinition"> (BlockCategories.sbc)

This one is a bit special in that the SubtypeId is ignored but instead it looks if the Name node already exists, and if it does it will ignore all other nodes and only append the contents of ItemIds to the existing one.

For example, to add to the vanilla Large Blocks category:

<?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">
    <CategoryClasses>
        <Category xsi:type="MyObjectBuilder_GuiBlockCategoryDefinition">
            <Id>
                <TypeId>GuiBlockCategoryDefinition</TypeId>
                <SubtypeId/>
            </Id>
            <Name>LargeBlocks</Name>
            <ItemIds>
                <string>MotorAdvancedStator/YourVeryGiganticRotor</string>
            </ItemIds>
        </Category>
    </CategoryClasses>
</Definitions>
Additive: <BlueprintClassEntries> (BlueprintClasses.sbc at the end)

The <Class> nodes in that file define the category, those will be overwritten if you declare them. However to pair a blueprint to a blueprint-class you have to use the <BlueprintClassEntries> node which is an additive list.

For example to add your blueprint (which is not shown here) to a vanilla class:

<?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">
    <BlueprintClassEntries>
        <Entry Class="Components" BlueprintSubtypeId="SomeFancyComponentBlueprint" />
    </BlueprintClassEntries>
</Definitions>
No override: <Decals> (Decals.sbc)

Decal definitions cannot be overwritten because the game sends them to a different system without checking if they already exist there, and because of the way they're stored this doesn't cause errors. [1]

This does make it impossible to change anything on a decal (most notably the blacklist). Mod scripts cannot mess with these either because the place they're stored in is not whitelisted.

Quick reference

How are some SBC are 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.
  • MainMenuInventoryScenes.sbc, Scenarios.sbx, Tutorials.sbx - mods only get loaded when a world starts, this would have no effect.
  • WheelModels.sbc - the game code using this is turned off.

Needs to be researched:

  • Game\Game.sbc - specifically explosive stuff at the bottom, if we remove <SessionComponents> does it break stuff? and if we have to include them it will eventually break stuff...
  • Screens\*.gsc - they're XML but are they moddable?

  1. from MyDefinitionManager.PostprocessDecals() ends up in a Dictionary<string, List<MyDecalMaterial>> in MyDecalMaterials