Modding:VCDBS format

From Vintage Story Wiki

This page was last verified for Vintage Story version 1.19.8.


The VCDBS file holds the main save game data. At the top level it is a sqlite database, but very few of the sqlite features are used. There are no database constraints and only one secondary index. Most of the data is stored in BLOB fields, which are then protobuf encoded, and thus fields within the protobuf cannot be queried at the SQL level.

ChunkPos

Several of the tables are indexed by a ChunkPos. This is an integer packing of the chunk position. It is similar to, but has a slightly different encoding than the ChunkIndex3D.

ChunkPos fields in most significant bit first order
reserved chunkY dimension high part guard chunkZ dimension low part guard chunkX
1 bit 9 bits 5 bit 1 bit 21 bits 5 bits 1 bit 21 bits

Schema

The tables in the save file can be listed with the .tables sqlite3 command.

sqlite> .tables
chunk       gamedata    mapchunk    mapregion   playerdata

The .schema command shows the schema of a requested table. Although, it does not show the protobuf schema used on the blob fields. The deserializing from the command line page has details on how to install tools such as sqlite to read the database contents from the command line.

sqlite> .schema chunk
CREATE TABLE chunk (position integer PRIMARY KEY, data BLOB);
Table name Each row covers Index column Value column Value column protobuf schema
gamedata Entire save game savegameid (integer) - always 1 data SaveGame
playerdata A player playerid (integer) - autogenerated, required by sqlite3
playeruid (string) - UUID of the player
data Vintagestory.Server.ServerWorldPlayerData
chunk 32x32x32 volume of blocks position (integer) - ChunkPos data Vintagestory.Server.ServerChunk
mapchunk 2D data for a column of chunks position (integer) - ChunkPos with Y set to 0 data Vintagestory.Server.ServerMapChunk
mapregion 2D data for a 16x16 region of chunks position (integer) - ChunkPos of the most northwest covered chunk, with Y set to 0 data Vintagestory.Server.ServerMapRegion

gamedata

There is exactly one gamedata row in each savegame. It contains settings for the world and counters for the global identifiers. There is a tutorial on adding custom moddata to the row.

$ sqlite3 modtestworld.vcdbs "SELECT writefile('gamedata_' || savegameid || '.binpb', data) FROM gamedata;"
436882


$ protoc --decode SaveGame --proto_path=$(dirname ~/schema.proto) ~/schema.proto <gamedata_1.binpb  | less

MapSizeX: 1024000
MapSizeY: 256
MapSizeZ: 1024000
Seed: 1727735926
LastEntityId: 82
ModData {
  key: "BlockIDs"
  value: "\n\007\010\000\022\003air\n\n\010\001\022\006mantle\n\"..."
}
ModData {
  key: "ItemIDs"
  value: "\n\r\010\001\022\tmagicwand\n\014\010\002\022\010backpack..."
}
ModData {
  key: "ambient"
  value: "\000\000\000\000\000\000\000\000\000\000\000\000\n\327\243:\000\000\000\000\003\000\000\000\312\311I?\324\323S?\334\333[?\000\000\000\000\003\000\000\000\000\000\200?\000\000\200?\000\000\200?\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200?\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200?\000\000\000\000\000\000\200?"
}
ModData {
  key: "auctionsData"
  value: ""
}
...
TotalGameSeconds: 4455745
WorldName: "modtestworld"
TotalSecondsPlayed: 5828
LastPlayed: "2024-07-09T21:08:10.5486615-07:00"
CreatedGameVersion: "1.19.8"
LastSavedGameVersion: "1.19.8"
HoursPerDay: 24
LastHerdId: 1
TimeSpeedModifiers {
  key: "baseline"
  value: 60
}
PlayStyle: "creativebuilding"
WorldType: "superflat"
WorldConfigBytes: "\005\014worldClimate\tsuperflat\005\010gameMode\010creative\005\013hoursPerDay\0042400\005\tcloudypos\0030.5\005\021temporalStability\005false\005\016temporalStorms\003off\005\tsnowAccum\005false\005\025colorAccurateWorldmap\004true\000"
PlayStyleLangCode: "creativebuilding"
LastBlockItemMappingVersion: 1
SavegameIdentifier: "eb730bfd-bf0f-4a49-87e2-3e4ccd03b26c"
CalendarSpeedMul: 0.5
RemappingsAppliedByCode {
  key: "game:v1.12clayplanters"
  value: true
}
...
RemappingsAppliedByCode {
  key: "game:v1.19.4-rc.1"
  value: true
}
HighestChunkdataVersion: 2
TotalGameSecondsStart: 4176000
CreatedWorldGenVersion: 2

playerdata

Each player that has logged into the server (or just the one player in single player) has a playerdata row. It stores the player's inventory, their gamemode, and statistics about their playthrough. It is possible to attach server-side only mod data to the player with IServerPlayer.SetModData, but no tutorial has been written yet.

Note that the player privilege information is stored in separate json files in the VintagestoryData_folder#Folder_Structure Playerdata folder.

$ sqlite3 creepy\ kingdom\ lands.vcdbs "SELECT writefile('playerdata_' || playeruid || '.binpb', data) FROM playerdata;"

$ protoc --decode ServerWorldPlayerData --proto_path=$(dirname ~/schema.proto) ~/schema.proto <playerdata_6mkR85hnMVMvGjIY0hSWWj3+.binpb >~/playerdata.txt 

PlayerUID: "6mkR85hnMVMvGjIY0hSWWj3+"
inventoriesSerialized {
  key: "backpack-6mkR85hnMVMvGjIY0hSWWj3+"
  value: "\001\006qslots\004\000\000\000\006\005slots\000\000"
}
inventoriesSerialized {
  key: "character-6mkR85hnMVMvGjIY0hSWWj3+"
  value: "\001\006qslots\017\000\000\000\006\005slots\007\0012\000\001\000\000\000|\n\000\000\001\000\000\000\004\tcondition\025\300\233>\000\007\0013\000\001\000\000\000#\n\000\000\001\000\000\000\004\tcondition\237\372\223>\000\007\0014\000\001\000\000\000\306\t\000\000\001\000\000\000\004\tconditionsXE=\000\007\0015\000\001\000\000\000\354\t\000\000\001\000\000\000\004\tcondition\327\214o>\000\007\00211\000\001\000\000\000\253\n\000\000\001\000\000\000\004\tcondition%%\205>\000\000\000"
}
inventoriesSerialized {
  key: "craftinggrid-6mkR85hnMVMvGjIY0hSWWj3+"
  value: "\001\006qslots\t\000\000\000\006\005slots\000\000"
}
inventoriesSerialized {
  key: "creative-6mkR85hnMVMvGjIY0hSWWj3+"
  value: "\000"
}
inventoriesSerialized {
  key: "ground-6mkR85hnMVMvGjIY0hSWWj3+"
  value: "\000"
}
inventoriesSerialized {
  key: "hotbar-6mkR85hnMVMvGjIY0hSWWj3+"
  value: "\001\006qslots\013\000\000\000\006\005slots\007\0010\000\000\000\000\000}$\000\000\001\000\000\000\000\000\000"
}
inventoriesSerialized {
  key: "mouse-6mkR85hnMVMvGjIY0hSWWj3+"
  value: "\000"
}
EntityPlayerSerialized: "\014EntityPlayer\0061.19.8\3734\000\000\000\000\000\000\006\nanimations\000\006\rextraInfoText\000\005\tplayerUID\0306mkR85hnMVMvGjIY0hSWWj3+\004\006onHurt\000\000\000\000\006\007nametag\005\004name\017bluelightning32\t\027showtagonlywhentargeted\000\001\013renderRange\347\003\000\000\000\006\006health\004\rbasemaxhealth\000\000pA\004\rcurrenthealth\000\000pA\004\tmaxhealth\000\000pA\000\006\006hunger\004\021currentsaturation\000\200;D\004\rmaxsaturation\000\200\273D\004\030saturationlossdelayfruit\000\000pB\004\034saturationlossdelayvegetable\000\000pB\004\030saturationlossdelaygrain\000\000pB\004\032saturationlossdelayprotein\000\000pB\004\030saturationlossdelaydairy\000\000pB\004\nfruitLevel\000\000\000\000\004\016vegetableLevel\000\000\000\000\004\ngrainLevel\000\000\000\000\004\014proteinLevel\000\000\000\000\004\ndairyLevel\000\000\000\000\000\006\006oxygen\004\tmaxoxygen\000@\034G\004\rcurrentoxygen\000@\034G\t\006hasair\001\000\006\ttiredness\004\ttiredness\000\000@A\000\006\010bodyTemp\004\010bodytemp\000\000\024B\003\030bodyTempUpdateTotalHours\260\005[\260\205Z\220@\004\026nearHeatSourceStrength\000\000\000\000\000\003\033lastWetnessUpdateTotalHours\260\005[\260\205Z\220@\006\nskinConfig\006\014appliedParts\005\010baseskin\005skin2\005\010eyecolor\005azure\005\tunderwear\007leotard\005\tvoicetype\004oboe\005\nvoicepitch\004high\005\010hairbase\004afro\005\thairextra\ntieddreads\005\020facialexpression\010very-sad\005\010mustache\004none\005\005beard\004none\005\thaircolor\010sanddune\000\000\005\tvoicetype\004oboe\005\nvoicepitch\004high\003\021temporalStability\000\000\000\000\000\000\360?\003\024lastReviveTotalHours\301\263\241\002\266W\220@\004\007headYaw\372\355\353:\004\theadPitch+\207\226=\006\005stats\006\023healingeffectivness\004\004base\000\000\200?\004\013wearablemod\000\000\000\000\000\006\024maxhealthExtraPoints\004\004base\000\000\200?\000\006\twalkspeed\004\004base\000\000\200?\004\013wearablemod\000\000\000\000\000\006\nhungerrate\004\004base\000\000\200?\004\013wearablemod\000\000\000\000\000\006\020rangedWeaponsAcc\004\004base\000\000\200?\004\013wearablemod\000\000\000\000\000\006\022rangedWeaponsSpeed\004\004base\000\000\200?\004\013wearablemod\000\000\000\000\000\006\023rangedWeaponsDamage\004\004base\000\000\200?\000\006\022meleeWeaponsDamage\004\004base\000\000\200?\000\006\021mechanicalsDamage\004\004base\000\000\200?\000\006\022animalLootDropRate\004\004base\000\000\200?\000\006\016forageDropRate\004\004base\000\000\200?\000\006\020wildCropDropRate\004\004base\000\000\200?\000\006\026vesselContentsDropRate\004\004base\000\000\200?\000\006\013oreDropRate\004\004base\000\000\200?\000\006\021rustyGearDropRate\004\004base\000\000\200?\000\006\016miningSpeedMul\004\004base\000\000\200?\000\006\022animalSeekingRange\004\004base\000\000\200?\000\006\023armorDurabilityLoss\004\004base\000\000\200?\000\006\032armorWalkSpeedAffectedness\004\004base\000\000\200?\000\006\022bowDrawingStrength\004\004base\000\000\200?\000\006\025wholeVesselLootChance\004\004base\000\000\200?\000\006\030temporalGearTLRepairCost\004\004base\000\000\200?\000\006\024animalHarvestingTime\004\004base\000\000\200?\000\000\005\016characterClass\010commoner\t\006canEat\001\004\007wetness\000\000\000\000\004\026freezingEffectStrength\000\000\000\000\001\nentityDead\000\000\000\000\001\013deathReason\006\000\000\000\001\017deathDamageType\000\000\000\000\004\014intoxication\000\000\000\000\001\025positionVersionNumber\017\000\000\000\003\006kbdirX\000\000\000\000\000\000\000\000\003\006kbdirY\000\000\000\000\000\000\000\000\003\006kbdirZ\000\000\000\000\000\000\000\000\004\tonHurtDir\000\300y\304\t\006onFire\000\000\314\35691-@\037A\000\000\000\000\000\200^@\276\301\247sx?\037A\000\000\000\000\275R\252@\233UO@\000\000\000\000\002\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\314\35691-@\037A\000\000\000\000\000\200^@\276\301\247sx?\037A\006player\003\026tempStabChangeVelocityh\255T\375$Iy?\000\006\013activeAnims\000\000\000\000\000\000\314\35691-@\037A\000\000\000\000\000\200^@\276\301\247sx?\037A\000\000\000\000\275R\252@\233UO@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
GameMode: EnumGameMode_Creative
MoveSpeedMultiplier: 1
FreeMove: true
Viewdistance: 160
selectedHotbarslot: 1
PickingRange: 100
ModData {
  key: "createCharacter"
  value: "\010\001"
}
PreviousPickingRange: 100
Deaths: 15

chunk

A row in the chunk table covers a 32x32x32 section of the world. There is a tutorial on adding custom moddata to a chunk.

Each chunk contains the following information:

  • Every block in the solid layer
  • Every block in the fluid layer
  • Sparse map of block positions to block entities
  • List of entities
  • Sparse map of decor blocks. The map is indexed by both the block position and decor index. The decor index includes which face of the parent block the decor is attached to, and optionally a location on a 16x16 grid on that block face (used by caveart).
  • Map of modid to a byte array of custom moddata
  • Format version metadata

The blockentities and entities are further encoded in BinaryWriter format, with another layer of protobuf format under that, which is why they are not fully decoded on the command line.

Sample data:

$ sqlite3 modtestworld.vcdbs "SELECT writefile('chunk_' || position || '.binpb', data) FROM chunk LIMIT 1;"
92

$ protoc --decode ServerChunk --proto_path=$(dirname ~/schema.proto) ~/schema.proto <chunk.binpb 
blocksCompressed: "\360\377\377\377\000\000\000\000r\032\000\000o\014\000\000~\014\000\000(\265/\375`\000\037-\001\000\230\377\377\377\377\000\000\000\377\377\377\000\000\000\377\377\377\000\000\000\006\020\000z\366\207\236\032\372\366\207N\207NGN\211"
lightCompressed: ""
lightSatCompressed: ""
GameVersionCreated: "1.19.8"
DecorsSerialized: ""
savedCompressionVersion: 2
liquidsCompressed: "\000\000\000\000"

$ protoc --decode ServerChunk --proto_path=$(dirname ~/schema.proto) ~/schema.proto <chunk_2147349446271.binpb
blocksCompressed: "\270\377\377\377\000\000\000\000r\032\000\000o\014\000\000~\014\000\000D%\000\000\017%\000\000\023%\000\000\027%\000\000\033%\000\000\037%\000\000#%\000\000\'%\000\000+%\000\000/%\000\0003%\000\000\334$\000\000\r%\000\000\035%\000\000(\265/\375`\000O\225\005\000\204\006\377\377\377\377\000\000\000 \000\000\377\377\377\257\377\377\377\237\377\377\000\000\000 \000\000 \000\000 \000\000 \000\000 \000\000\377\377\377\217 \000\000 \000\000 \000\000 \000\000 \000\000 \000\000 \000\000 \000\000 \000\000 \000\000\004\000\000\004\000\000\000\002\000\000\000\004\000\000\004\000\000\004\000\000\004\000\000\004\000\000\004\000\000\004\000\000( \340\3677\017\366C\306\2156d\334h^\230\342{ \343F\033\302\020PSu\0370\220q\r\002 T\360h?/ \270C\000\002s\r\033\200\364\326\250qi\177\034\343\030\3078\006>&\231\236\343\322\350s\344\024\020\001"
lightCompressed: "(\265/\375`\000/\325\003\000D\005\000\000\000\000p\000\000\000`\000\000\377\377\377\333\377\377\333\377\377\377\375\377\377\377\333\377\377\333\377\377\333\377\377\333\377\377\333\377\377\333\377\377\333\377\377\000\000\000 \000\000$\000\000$\000\000\000\002\000\000\000$\000\000$\000\000$\000\000$\000\000$\000\000$\000\000$\000\000\025\020\000\217\336\207\214\033m\310\270\321\2740T:j\324x\264\0372n\264!\343F\363\302X\216I\206F\021\001"
lightSatCompressed: "(\265/\375 \024\241\000\000\000\000\000\000\026\000\000\000\025\000\000\000\024\000\000\000\023\000\000\000"
EntitiesCount: 3
EntitiesSerialized: "\nEntityItem\0061.19.8Q\000\000\000\000\000\000\000\006\rextraInfoText\000\007\titemstack\000\000\000\000\000\324$\000\000\004\000\000\000\000\006\005stats\000\000\306d1\323\342?\037A\000\000\000\000\000\000\010@\377\372?X\264?\037A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\306d1\323\342?\037A\000\000\000\000\000\000\010@\377\372?X\264?\037A\004item\004\tdeathTime\250\034\337B\000\000"
EntitiesSerialized: "\nEntityItem\0061.19.8R\000\000\000\000\000\000\000\006\rextraInfoText\000\007\titemstack\000\001\000\000\0009\004\000\000\001\000\000\000\000\006\005stats\000\000\000\000\000\000\363?\037A\000\000\000\000\000\000\000@v\3735X\271?\037A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\363?\037A\000\000\000\000\000\000\000@v\3735X\271?\037A\004item\004\tdeathTime\225\303\201B\000\000"
BlockEntitiesCount: 21
BlockEntitiesSerialized: "\017VEBELVGenerator\001\004posx\372\317\007\000\001\004posy\003\000\000\000\001\004posz\352\317\007\000\005\tblockCode\032vinteng:velvgenerator-east\005\014machinestate\010Sleeping\001\010priority\005\000\000\000\002\014currentpower\000\004\000\000\000\000\000\000\010\013connections\022\000\n\020\010\000\022\014\n\n\010\375\237\037\020\003\030\352\237\037\010\nnetworkids\006\000\n\004\010\000\020\001\006\tinventory\001\006qslots\001\000\000\000\006\005slots\007\0010\000\001\000\000\000[\002\000\000\003\000\000\000\000\000\000\006\017faceConnections\t\tfaceNorth\000\t\010faceEast\000\t\tfaceSouth\000\t\010faceWest\000\000\004\007genTemp\000\000\240A\001\007maxTemp\024\005\000\000\004\014fuelBurnTimeWj A\000"
...
BlockEntitiesSerialized: "\017VEBELVGenerator\001\004posx\371\317\007\000\001\004posy\003\000\000\000\001\004posz\355\317\007\000\005\tblockCode\032vinteng:velvgenerator-east\005\014machinestate\002On\001\010priority\005\000\000\000\002\014currentpowers\002\000\000\000\000\000\000\010\013connections\022\000\n\020\010\000\022\014\n\n\010\375\237\037\020\002\030\356\237\037\010\nnetworkids\006\000\n\004\010\000\020\025\006\tinventory\001\006qslots\001\000\000\000\006\005slots\007\0010\000\001\000\000\000[\002\000\000\004\000\000\000\000\000\000\006\017faceConnections\t\tfaceNorth\000\t\010faceEast\000\t\tfaceSouth\000\t\010faceWest\000\000\004\007genTemp\000\200\242D\001\007maxTemp\024\005\000\000\004\014fuelBurnTimeUh\327A\000"
GameVersionCreated: "1.19.8"
DecorsSerialized: ""
savedCompressionVersion: 2
liquidsCompressed: "\000\000\000\000"
BlocksPlaced: 65
BlocksRemoved: 49

mapchunk

Each mapchunk row has 2d data for a column of chunks in the game. Most of the fields in the mapchunk, such as RainHeightMap, are 32x32 arrays that are indexed by the relative X Z block position. Each entry in the RainHeightMap array holds the y coordinate of the highest block in the column that is solid enough to block rain. It is updated as blocks are broken and placed. Whereas, the WorldGenTerrainHeightMap array is not updated after the chunk is generated.

Despite the name, the mapchunk table does not directly store the client's minimap. The client actually generates the minimap by looking getting the Y level for every block from the RainHeightMap, looking up that block from the chunk data (not mapchunks), then converting that block into a pixel.

$ sqlite3 modtestworld.vcdbs "SELECT writefile('mapchunk_' || position || '.binpb', data) FROM mapchunk;"

$ protoc --decode ServerMapChunk --proto_path=$(dirname ~/schema.proto) ~/schema.proto <mapchunk_2146678357627.binpb   >~/mapchunk.txt

Moddata {
  key: "lastSnowAccumUpdateTotalHours"
  value: "\t\000\000\000\000\000P\223@"
}
RainHeightMap: 116
...
RainHeightMap: 119
currentpass: 6
WorldGenTerrainHeightMap: 119
...
WorldGenTerrainHeightMap: 120
YMax: 133
CaveHeightDistort: "py\177\177\210\217\217\213\203\177\177~|\177\177\206\220\227\234\235\234\227\217\203\177\177\177\177\177\202\205\200z\177\200\213\224\231\232\227\222\212\202\177\177\177\204\215\222\225\226\227\224\216\204\177zqnpu{\177~~\177\203\216\225\232\235\236\235\232\223\213\206\207\212\216\216\213\211\206\203\177\177tia_`dhlnz\177\177\205\214\223\232\240\243\242\236\225\216\211\210\205\200\177\177\177\177zqg_ZYZ\\_actu}\177\177\210\224\237\244\245\240\227\214\203\177\177\177xsrsqkd]ZYZ[\\\\\\qnr{\177\201\220\234\242\242\234\221\203\177\177xqkilpsqjc_]^_]ZXsor{\177\204\222\233\237\235\226\211\177\177vqlhgksz{vmgeed`ZV|xz\177\177\214\227\235\236\233\223\207\177\177xtqnkmu~\177\177vmjjic[V\177\177\177\177\206\222\233\237\240\234\226\215\202\177\177\177\177|vsu|\177\177xmhhie^X\200\177\177\203\213\225\235\241\242\240\234\227\216\205\201\201\201\177\177zvy~}ticcee`[\202\201\201\204\212\223\233\240\243\243\241\236\227\220\215\216\217\213\200\177}{}|sga`aa_]\177\177\177\177\204\214\225\235\241\243\243\241\233\225\222\224\226\225\216\202\177\177\177\177|oea_^]^\177\177\177\177\177\200\213\225\234\241\242\241\234\225\221\223\227\231\226\215\204\201\203\202\177\177sib^]a||{{}\177\177\211\223\233\240\240\234\225\217\217\224\230\227\221\211\207\213\215\212\200\177uibagusrqrv\177\177\210\225\236\240\236\230\220\215\220\224\225\220\211\207\213\220\220\213\177\177rjjtrmkjjlt\177\201\223\236\243\243\236\226\220\220\223\225\221\212\205\207\214\217\215\203\177xqu\177rljihjq\177\201\225\241\246\246\243\235\227\226\230\231\226\217\207\204\207\212\211\201\177zw~\177tnmmlnv\177\207\231\244\250\250\246\243\240\237\240\240\236\227\216\207\206\207\206\177\177{z\177\201wssssu|\177\212\232\244\250\251\251\250\246\246\247\246\244\236\225\215\212\211\206\177\177}{\177\177xxyxwvz\177\205\224\237\245\250\252\252\252\252\251\250\246\240\227\216\212\211\207\201\177\177|\177\177wyywsopx\177\207\225\237\246\251\253\252\252\250\247\243\235\221\206\201\202\203\200\177\177|{\177oqpnifejv\177\207\226\240\246\250\250\246\244\241\234\224\207\177\177\177\177\177\177}wvydcaa`_`ckz\177\216\232\240\242\241\236\233\231\225\215\200\177{z}}ytqps[WVX\\^`bht\177\211\225\231\231\227\225\224\224\223\217\204\177|vspmkkmpVRRU[bffju\177\211\224\226\224\222\221\224\227\231\227\217\203\177zpjghkptUQQU^gkjkv\177\213\225\227\226\225\227\232\235\237\236\230\216\200\177tmjlry}VSSXaikiis\177\212\226\233\235\235\237\241\242\242\240\233\221\203\177xrsx\177\177\177[WW\\djhdcl\177\204\224\235\241\242\243\243\242\240\234\226\213\177\177vu{\177\177\201\177b``chje__fw\177\215\231\236\240\240\237\233\226\222\213\200\177wru\177\177\204\207\203jkklljc]\\bp\177\200\215\224\227\226\223\216\211\205\200\177\177uqu\177\177\206\206\200qvwtoia[[_it\177\177\201\206\207\204\200\177\177\177\177\177{wz\177\177\205\202\177v|~ypg^ZY]dkry\177\177\177\177\177\177\177\203\202\177\177\177\177\177\203\206\200\177"
// One for every X, Z block position in the map chunk. The value is unused and always 0.
SedimentaryThicknessMap: 0
...
SedimentaryThicknessMap: 0
TopRockIdMap: 6774
...
TopRockIdMap: 6776
SnowAccum {
  Key {
    X: 511840
    Y: 511808
  }
  Value: -1
}
...
SnowAccum {
  Key {
    X: 511871
    Y: 511839
  }
  Value: -1
}
WorldGenVersion: 2

mapregion

The table mostly contains world generation information. It is the serialized format of IMapRegion. Each row contains 2D data for a 16x16 section of mapchunks. Most of the fields are IntDataMap2Ds. Each IntDataMap2D covers a square section (not rectangle) of the world. The Size field describes the size of one of the sides, such that there are Size*Size entries in the array.

To smooth out world generation at the border of the mapregions, many of the IntDataMap2Ds contain padding, which are entries that belong to neighboring map regions. This way when the neighboring map region is generated, its border is seeded with values that match its neighbor. The TopLeftPadding field indicates both how many extra rows are on the top of the matrix and how many extra columns are to the left. The BottomRightPadding field indicates how many extra rows are on the bottom of the matrix and extra columns on the right. Both paddings are added to the Size field, which is one reason Size can be greater than 16. The InnerSize property is the Size minus the padding.

Even the InnerSize can be larger than 16 (the number of map chunks covered by the map region). The IntDataMap2D is interopolated during the world generation, and a larger InnerSize provides extra resolution. For example, the ore generation maps have 4 entries per chunk for an inner size of 32 (instead of 16).

There are multiple RockStrata IntDataMap2Ds. Each one corresponds to one of the variants in the survival/worldgen/rockstrata.json file.

It is possible to attach server-side only mod data to a map region with IMapRegion.SetModData, but no tutorial has been written yet.

$ sqlite3 'creepy kingdom lands.vcdbs' "SELECT writefile('mapregion_' || position || '.binpb', data) FROM mapregion;"
213896
...

$ protoc --decode ServerMapRegion --proto_path=$(dirname ~/schema.proto) ~/schema.proto <mapregion_134083511272.binpb

LandformMap {
  Data: 32
...
  Data: 43
  Size: 40
  TopLeftPadding: 4
  BottomRightPadding: 4
}
ForestMap {
  Data: 56
...
  Data: 54
  Size: 17
  BottomRightPadding: 1
}
ClimateMap {
  Data: 7887384
...
  Data: 7152388
  Size: 20
  TopLeftPadding: 2
  BottomRightPadding: 2
}
GeologicProvinceMap {
  Data: 0
...
  Data: 5
  Size: 14
  TopLeftPadding: 3
  BottomRightPadding: 3
}
BushMap {
  Data: 255
...
  Data: 39
  Size: 33
  BottomRightPadding: 1
}
FlowerMap {
  Data: 0
...
  Data: 73
  Size: 17
  BottomRightPadding: 1
}
OreMaps {
  key: "alum"
  value {
    Data: 1053
...
    Data: 0
    Size: 33
    BottomRightPadding: 1
  }
}
OreMaps {
  key: "anthracite"
  value {
    Data: 0
...
    Data: 0
    Size: 33
    BottomRightPadding: 1
  }
}
OreMaps {
  key: "bismuthinite"
  value {
    Data: 1115
...
    Data: 0
    Size: 33
    BottomRightPadding: 1
  }
}
...
ModData {
  key: "weatherState"
  value: "\032/\t\206\241`..."
}
GeneratedStructures {
  Code: "buriedtreasurechest/royal.json"
  Location {
    X1: 512009
    Y1: 104
    Z1: 511980
    X2: 512012
    Y2: 108
    Z2: 511984
  }
}
RockStrata {
  Data: 0
...
  Data: 0
  Size: 36
  TopLeftPadding: 2
  BottomRightPadding: 2
}
RockStrata {
  Data: 0
...
  Data: 0
  Size: 36
  TopLeftPadding: 2
  BottomRightPadding: 2
}
RockStrata {
  Data: 7
...
  Data: 0
  Size: 36
  TopLeftPadding: 2
  BottomRightPadding: 2
}
RockStrata {
  Data: 0
...
  Data: 0
  Size: 36
  TopLeftPadding: 2
  BottomRightPadding: 2
}
...
OreMapVerticalDistortTop {
  Data: 14
...
  Data: 20
  Size: 260
  TopLeftPadding: 2
  BottomRightPadding: 2
}
OreMapVerticalDistortBottom {
  Data: 10
...
  Data: 19
  Size: 260
  TopLeftPadding: 2
  BottomRightPadding: 2
}
BeachMap {
  Data: 128
...
  Data: 127
  Size: 33
  BottomRightPadding: 1
}
BlockPatchMaps {
  key: "mush1"
  value {
    Data: 0
...
    Data: 0
    Data: 17
    Size: 17
    BottomRightPadding: 1
  }
}
BlockPatchMaps {
  key: "mush2"
  value {
    Data: 0
...
    Data: 0
    Size: 17
    BottomRightPadding: 1
  }
}
...
UpheavelMap {
  Data: 0
...
  Data: 0
  Size: 22
  TopLeftPadding: 3
  BottomRightPadding: 3
}
OceanMap {
  Data: 0
...
  Data: 0
  Size: 26
  TopLeftPadding: 5
  BottomRightPadding: 5
}


Code Modding
Basics Code Mods Preparing For Code Mods Creating A Code Mod
Tutorials
Advanced Server-Client Considerations Setting up your Development Environment Advanced Blocks Advanced Items Block and Item Interactions Block Behavior Block Entity Particle Effects World Access Inventory Handling Commands GUIs Network API Monkey patching (Harmony)
Data Management VCDBS format Savegame Moddata ModConfig File Chunk Moddata Serialization Formats TreeAttribute
Worldgen WorldGen API NatFloat EvolvingNatFloat
Rendering Shaders and Renderers
Icon Sign.png

Wondering where some links have gone?
The modding navbox is going through some changes! Check out Navigation Box Updates for more info and help finding specific pages.

Modding
Modding Introduction Getting Started Theme Pack
Content Modding Content Mods Developing a Content Mod Basic Tutorials Intermediate Tutorials Advanced Tutorials Content Mod Concepts
Code Modding Code Mods Setting up your Development Environment
Property Overview ItemEntityEntity BehaviorsBlockBlock BehaviorsBlock ClassesBlock EntitiesBlock Entity BehaviorsCollectible BehaviorsWorld properties
Workflows & Infrastructure Modding Efficiency TipsMod-engine compatibilityMod ExtensibilityVS Engine
Additional Resources Community Resources Modding API Updates Programming Languages List of server commandsList of client commandsClient startup parametersServer startup parameters
Example ModsAPI DocsGitHub Repository