Modding:VCDBS format
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.
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 |
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 | Item • Entity • Entity Behaviors • Block • Block Behaviors • Block Classes • Block Entities • Block Entity Behaviors • Collectible Behaviors • World properties |
Workflows & Infrastructure | Modding Efficiency Tips • Mod-engine compatibility • Mod Extensibility • VS Engine |
Additional Resources | Community Resources • Modding API Updates • Programming Languages • List of server commands • List of client commands • Client startup parameters • Server startup parameters Example Mods • API Docs • GitHub Repository |