Blueprint File Formats

From StarMade Wiki

Revision as of 23:04, 16 February 2017 by SgSkallagrim (talk | contribs) (Metadata)

Below are the details of the blueprint data files. This information is intended for those who are interested in writing external tools to inspect and modify blueprints.

Versions

As StarMade is under active development, file formats and layouts could change with each version. As a result, the information on this page may become inaccurate over time. If you find errors in this information, please provide corrections and note the version and changes in the Changelog section at the bottom of this page.

File Layout

Blueprints are comprised of several files arranged in the blueprints directories in the StarMade installation directory. There are three such directories:

Directory Purpose
blueprints Player-saved blueprints (the local catalog) as well as the initial pirate ship blueprints
blueprints-default Also contains pirate blueprints
blueprints-stations Station blueprints, organized into directories for each of the NPC factions.

Within each blueprint directory are directories for each ship or station. Within each of those directories are the following files:

File Name Purpose
header.smbph The header file.
meta.smbpm The metadata file.
logic.smbpl The logic file.
DATA/ A directory containing the *.smd2 block chunk data files.

Header

The header file describes the following basic bits of information about the blueprint:

Entity Type 
Indicates whether the blueprint is for a Ship, Shop, Space Station, Asteroid or Planet.
Entity Class 
Indicates the class of an entity. Like General, Mining, Attack or Defense and so on. Part of header since header version 2.
Bounding Box 
A pair of three-dimensional coordinates providing the minimum and maximum block coordinates for the blueprint. These are relative to a 0,0,0 base, so the minimum coordinates will be negative and the maximum coordinates will be positive. The size of the blueprint is determined by subtracting the minimum coordinates from the maximum ones in each dimension.
Element Map
An array of structures describing the number and types of each block in the blueprint.
Statistical data of an entity
Offensive, Defensive, Power, Mobility, Danger, Survivability and Support. Part of header since header version 1.

With the information from the header, it's possible to calculate the size and composition of the blueprint to, for example, produce a list of materials needed for construction or determine if a ship can fit in a particular space.

Metadata

The metadata file contains all the other information about a blueprint except for block positions. This includes things like docked turrets, contents of storage boxes on the ship, etc. It is arranged in two sections: docking and Tags.

Docking 
This section contains an array of structures describing the name of the blueprint for the docked entity, its size and position, the docking style and its docked orientation.
Tags 
This is a hierarchical data format which may contain binary information of several types, optionally named. See the file format section for additional details.

The Tags section may be compressed, requiring zlib compression functionality to work with. Each Tag contains the following information:

Type 
The type of data contained in the payload.
Name (optional)
If present this is the name of this tag
Payload 
A variable format data structure which describes one of the following values:
  • Byte (8-bit value)
  • Short (16-bit value)
  • Int (32-bit value)
  • Long (64-bit value)
  • Float (32-bit single-precision value)
  • Double (64-bit double-precision value)
  • Byte Array
  • String (UTF-encoded with a length prefix)
  • Vector3f (a vector of 3 floats)
  • Vector3i (a vector of 3 integers)
  • Vector3b (a vector of 3 bytes)
  • List (A list of Payloads which all contain the same type of data)
  • Structure (A list of Tags of varying types)
  • FactoryId (a 8-bit value used for factory registration)
  • Vector4f (A vector of 4 floats)

Logic

The logic file describes all of the linked module groups in the ship. It is structured as an array or arrays of block information.

Controller Map 
An array of Controller Entity structures, one for each linked master.
Controller Entity 
Contains the position of the controller (master) block and an array of Controller Group structures describing the master and slaved blocks.
Controller Group 
Contains the type of block and an array of positions of each slaved block of that type

There is a hierarchy of groups, starting with the Controller Entity with controller position 8, 8, 8 (corresponding to the Ship Core) which will contain a list of Controller Groups containing the master blocks (such as the various computers.) Within each of these groups will be the positions of those master blocks, and those positions will correspond to the Controller Entity positions of the other Entities in the Controller Map.

Data

Data files are contained within the DATA directory for a given blueprint. These files contain the actual block data - types, positions and orientations, organized into segments and further organized into regions. Each region will be in its own file named with the following format <blueprintname>.<regionX>.<regionY>.<regionZ>.smd2. For a blueprint called Alpha, the data file for region 0, 0, 0 would be called Alpha.0.0.0.smd2.

The region file contains the following information:

Segment Index 
A 16x16x16 array of segment indexes, pointing to Segment Data in the data array
Segment Timestamps 
A 16x16x16 array of timestamps.
Segment Data 
An array of up to 16x16x16 (4096) entries containing the data pointed to by the Segment Index. Each Segment Data contains the segment timestamp, the segment position within the region, the type of segment and a compressed array of Block Data.
Block Data 
A bit-packed structure describing the block id, orientation, hitpoints and whether the block is active.

Block Data

The Block Data structure consists of three bytes which contain a bit-packed representation of each block in the blueprint. More info

MSB Bit Offsets LSB
Type 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
All Orientation Active Hit Points Block ID

The Orientation field represents how the block is facing in the blueprint. When all the bits in this field are zero, the block will be in its default orientation.
Blocks than can be active have 1 for 'inaktive' and 0 for 'active'.Others have 0 as Active-bit.

Additional Resources

In order to assist developers, the following files are provided to help understand and work with blueprint files.

010 Editor

The following *.bt files are format definitions for the 010 Hex Editor. Their format is largely similar to C structures and should be easily translatable to your language of choice.

smbph.bt

//--------------------------------------
//--- 010 Editor v6.0 Binary Template
//
// File: smbph.bt
// Author: Cliff Hudson
// Revision: 0.1867
// Purpose: StarMade Blueprint Header file
//--------------------------------------

struct Vector3f
{
    float x;
    float y;
    float z;
};

enum <unsigned int> EntityType
{
    Ship = 0,
    Shop = 1,
    SpaceStatiion = 2,
    Asteroid = 3,
    Planet = 4
};

typedef struct
{
    Vector3f min;
    Vector3f max;
} BoundingBox;

typedef struct
{
    short blockId;
    int blockCount;
} Element;

typedef struct
{
    int numElements;
    Element elements[numElements];
} ElementCountMap;

typedef struct
{
    int version; 
    EntityType entityType;
    BoundingBox boundingBox;
    ElementCountMap elementCountMap;
} Header;

Header header;

smbpl.bt

For a logic file with chunk 16 positions. The core/center is at (8, 8, 8).

//--------------------------------------
//--- 010 Editor v6.0 Binary Template
//
// File: smbpl.bt
// Author: Cliff Hudson
// Revision: 0.1867
// Purpose: StarMade Blueprint Logic file
//--------------------------------------

struct Vector3s
{
    short x;
    short y;
    short z;
};

typedef struct
{
    short blockId;
    int numBlocks;
    Vector3s blockPositions[numBlocks];
} ControllerGroup <optimize=false>;

typedef struct
{
    Vector3s controllerPosition;
    int numGroups;
    ControllerGroup groups[numGroups];
} ControllerEntity <optimize=false>;

typedef struct
{
    int version;
    int numControllers;
    ControllerEntity entities[numControllers];
} ControllerMap <optimize=false>;

ControllerMap controllerMap;

For a logic file with chunk 32 positions. The core/center is at (16, 16, 16).

//--------------------------------------
//--- 010 Editor v6.0 Binary Template
//
// File: smbpl.bt
// Purpose: StarMade Blueprint Logic file
//--------------------------------------

struct Vector3s
{
    short x;
    short y;
    short z;
};

typedef struct
{
    short blockId;
    int numBlocks;
    Vector3s blockPositions[numBlocks];
} ControllerGroup <optimize=false>;

typedef struct
{
    Vector3s controllerPosition;
    int numGroups;
    ControllerGroup groups[numGroups];
} ControllerEntity <optimize=false>;

typedef struct
{
    int version;
    int controllerVersion;  //  A number smaller than -1024.
    int numControllers;
    ControllerEntity entities[numControllers];
} ControllerMap <optimize=false>;

ControllerMap controllerMap;

smbpm.bt

//--------------------------------------
//--- 010 Editor v6.0 Binary Template
//
// File: smbpm.bt
// Author: Cliff Hudson
// Revision: 0.1867
// Purpose: StarMade Blueprint Meta file
//--------------------------------------
enum <byte> TagType
{
    Finish = 1,
    SegManager = 2,
    Docking = 3
};

struct TagList;
struct TagStructure;
struct Payload;

typedef struct
{
    byte x;
    byte y;
    byte z;
} Vector3b;

typedef struct
{
    int x;
    int y;
    int z;
} Vector3i;

typedef struct
{
    float x;
    float y;
    float z;
} Vector3f;

typedef struct
{
    float x;
    float y;
    float z;
    float w;
} Vector4f;

typedef struct
{
    short nameLen;
    char name[nameLen];
    Vector3i dockingPos;
    Vector3f dockingSize;
    short dockingStyle;
    byte dockingOrientation;
} DockedEntry <optimize=false>;

typedef struct
{
    int dockedCount;
    DockedEntry dockedEntry[dockedCount];
} DockedBlueprints <optimize=false>;

typedef struct
{
    unsigned short stringLen;
    char str[stringLen];
} String <optimize=false>;

typedef struct
{
    int length;
    byte data[length];
} ByteArray <optimize=false>;

typedef struct (byte type)
{
    switch(type)
    {
        case 0:
            break;
        case 1: // Byte
            byte dataByte;
            break;
        case 2: // Short
            short dataShort;
            break;
        case 3: // Int
            int dataInt;
            break;
        case 4: //Long
            int64 dataLong;
            break;
        case 5: // Float
            float dataFloat;
            break;
        case 6: // Double
            double dataDouble;
            break;
        case 7: // Byte array
            ByteArray byteArray;
            break;
        case 8: // String
            String dataString;
            break;
        case 9: // Float vector
            Vector3f floatVector;
            break; 
        case 10: // int vector
            Vector3i intVector;
            break;
        case 11: // Byte vector
            Vector3b byteVector;
            break;
        case 12: // List
            TagList list;
            break;
        case 13: // Struct
            TagStructure structure;
            break;
        case 14: // Factory registration
            byte factoryId;
            break;
        case 15: // Float4 vector
            Vector4f float4Vector;
            break;
    }
} Payload <optimize=false>;

typedef struct
{
    byte type;
    if(type > 0)
    {
        String name;
    }
    if(type != 0)
    {
        Payload payload(Abs(type));
    }
} Tag <optimize=false>;

typedef struct
{
    byte listType;
    int listLength;
    Payload payload(listType)[listLength]; 
} TagList <optimize=false>;

typedef struct
{    
    do
    {
        Tag tag;
    }
    while(tag.type != 0);    
} TagStructure<optimize=false>;

typedef struct
{    
    short version; // Current unused.  If this value is 0x1f8b, then from here 
                   // forward - including these bytes - is a gzip compressed stream 
                   // whose contents follow the same structure as the uncompressed 
                   // version.
    Tag tag;
} TagRoot <optimize=false>;

typedef struct
{
    unsigned int version;
    do
    {
        byte tagType;
        switch(tagType)
        {
            case Finish:
                break;

            case SegManager:
                TagRoot segmentManager;
                return;                

            case Docking:
                DockedBlueprints dockedBlueprints;
                break;
        }
    } while(tagType != Finish);    
} Metadata;

Metadata metadata;

smd2.bt

//--------------------------------------
//--- 010 Editor v6.0 Binary Template
//
// File: smd2.bt
// Author: Cliff Hudson
// Revision: 0.1867
// Purpose: Starmade Region Data file
//--------------------------------------

typedef struct
{
    BitfieldDisablePadding();
    BitfieldLeftToRight();
    byte orientation : 3;
    byte hitpoints: 8;        
    byte isActive: 1;
    ushort blockId: 12;   
} BlockData;

typedef struct
{
    int x;
    int y;
    int z;
} Vector3i;

typedef struct
{
    int segmentId;
    int segmentSize;
} SegmentIndex;

typedef struct
{
    int version;
    SegmentIndex indices[16*16*16];
    int64 timestamps[16*16*16];
} RegionHeader;

typedef struct
{
    // NOTE: This struct will always come out to 5120 bytes total, even if the 
    //       data field ends up being shorter (it will simply be padded out.)
    //       This allows the SegmentIndex to trivially find the data on disk without
    //       loading the entire file.
    //       No longer the newest format, though this format may apply to blueprints with
    //       an SMD file version of 0.
    int64 timestamp;
    Vector3i segmentPosition;
    int dataLength;  
    unsigned byte segmentType;    
    byte data[5120-25];  // zlib compressed array of BlockData
} SegmentDataOld;

typedef struct
{
    byte version;
    // NOTE: This struct will always come out to 5120 bytes total, even if the 
    //       data field ends up being shorter (it will simply be padded out.)
    //       This allows the SegmentIndex to trivially find the data on disk without
    //       loading the entire file.
    //       Valid as of 0.1867, smd file version 1 (RegionHeader.version).
    int64 timestamp;
    Vector3i segmentPosition;   
    unsigned byte dataByte; // If 1, there is valid data here    
    int compressedSize;
    byte data[5120-26];  // zlib compressed array of BlockData
} SegmentData;

typedef struct
{
    RegionHeader header;
    SegmentData data[4096];
} Region;

Region region;

smd3.bt

//--------------------------------------
//--- 010 Editor v6.0 Binary Template
//
// File: smd3.bt
// Revision: 0.199.159
// Purpose: Starmade Region Data file
//--------------------------------------

typedef struct
{
    BitfieldDisablePadding();
    BitfieldLeftToRight();
    byte orientation : 3;
    byte isActive: 1;
    byte hitpoints: 9;
    ushort blockId: 11;   
} BlockData;

typedef struct
{
    int32 x;
    int32 y;
    int32 z;
} Vector3i;

typedef struct
{
    int16 segmentId;
    int16 segmentSize;
} SegmentIndex;

typedef struct
{
    int32 version;
    SegmentIndex indices[16*16*16];
} RegionHeader;

typedef struct
{
    // NOTE: This struct will always come out to 49152 bytes total, even if the 
    //       data field ends up being shorter (it will simply be padded out.)
    //       This allows the SegmentIndex to trivially find the data on disk without
    //       loading the entire file.
    byte version;
    int64 timestamp;
    Vector3i segmentPosition;   
    unsigned byte dataByte; // If 1, there is valid data here    
    int compressedSize;
    byte data[49152-26];  // zlib compressed array of (32x32x32) BlockData
} SegmentData;

typedef struct
{
    RegionHeader header;
    SegmentData data[ ( FileSize() - 16388 ) / 49152 ];
} Region;

Region region;

Changelog

Added SegmentDataOld to smd2 format, reflecting the previous format for block data for this file. It changed somewhere prior to v0.1867, but this is verified correct on 0.1867. Initial creation for version 0.1867.

Added block data format for smd3 used by StarMade v0.199.257.