Difference between revisions of "Blueprint File Formats"

From StarMade Wiki
(added smd3 file format)
(smd3.bt)
Line 574: Line 574:
 
     unsigned byte dataByte; // If 1, there is valid data here     
 
     unsigned byte dataByte; // If 1, there is valid data here     
 
     int compressedSize;
 
     int compressedSize;
     byte data[49152-26];  // zlib compressed array of BlockData
+
     byte data[49152-26];  // zlib compressed array of (32x32x32) BlockData
 
} SegmentData;
 
} SegmentData;
  

Revision as of 17:27, 22 August 2016

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.
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.

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.

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
Type 1 Orientation Active Hit Points Block ID
For blocks with an activation status, like a Standard Factory or Activation Module

Type 2 Orientation Hit Points Block ID
For all other blocks except corners

Type 3 Orientation Hit Points Block ID
For corner blocks

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. The bits are interpeted as follows - if the bit is not part of the orientation :

Type Bits Description
Type1 23 22 21 The block facing
Type 2 23 22 The axis of rotation.
  • 00 : +Y
  • 01 : -Y
  • 10 : -Z
  • 11 : +Z
21 20 The amount of clockwise rotation around the axis of rotation, in 90-degree steps
Type 3 19 23 22 The axis of rotation.
  • 000 : +Y
  • 001 : -Y
  • 010 : -Z
  • 011 : +Z
  • 100 : -X
  • 101 : +X
21 20 The amount of clockwise rotation around the axis of rotation, in 90-degree steps

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

//--------------------------------------
//--- 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;

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.
    //       Valid as of 0.199.159, smd file version 1 (RegionHeader.version).
    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[4096];
} 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.