1 =============================
2 Minetest World Format 22...25
3 =============================
5 This applies to a world format carrying the block serialization version
6 22...25, used at least in
7 - 0.4.dev-20120322 ... 0.4.dev-20120606 (22...23)
9 - 24 was never released as stable and existed for ~2 days
11 The block serialization version does not fully specify every aspect of this
12 format; if compliance with this format is to be checked, it needs to be
13 done by detecting if the files and data indeed follows it.
17 Data can, in theory, be contained in the flat file directory structure
18 described below in Version 17, but it is not officially supported. Also you
19 may stumble upon all kinds of oddities in not-so-recent formats.
23 Everything is contained in a directory, the name of which is freeform, but
24 often serves as the name of the world.
26 Currently the authentication and ban data is stored on a per-world basis.
27 It can be copied over from an old world to a newly created world.
30 |-- auth.txt ----- Authentication data
31 |-- env_meta.txt - Environment metadata
32 |-- ipban.txt ---- Banned ips/users
33 |-- map_meta.txt - Map metadata
34 |-- map.sqlite --- Map data
35 |-- players ------ Player directory
36 | |-- player1 -- Player file
37 | '-- Foo ------ Player file
38 `-- world.mt ----- World metadata
42 Contains authentication data, player per line.
43 <name>:<password hash>:<privilege1,...>
45 Legacy format (until 0.4.12) of password hash is <name><password> SHA1'd,
46 in the base64 encoding.
48 Format (since 0.4.13) of password hash is #1#<salt>#<verifier>, with the
49 parts inside <> encoded in the base64 encoding.
50 <verifier> is an RFC 5054 compatible SRP-2048-SHA1 verifier
51 of the given salt, password, and the player's name lowercased.
54 - Player "celeron55", no password, privileges "interact" and "shout":
55 celeron55::interact,shout
56 - Player "Foo", password "bar", privilege "shout", with a legacy password hash:
57 foo:iEPX+SQWIR3p67lj/0zigSWTKHg:shout
58 - Player "Foo", password "bar", privilege "shout", with a 0.4.13 pw hash:
59 foo:#1#hPpy4O3IAn1hsNK00A6wNw#Kpu6rj7McsrPCt4euTb5RA5ltF7wdcWGoYMcRngwDi11cZhPuuR9i5Bo7o6A877TgcEwoc//HNrj9EjR/CGjdyTFmNhiermZOADvd8eu32FYK1kf7RMC0rXWxCenYuOQCG4WF9mMGiyTPxC63VAjAMuc1nCZzmy6D9zt0SIKxOmteI75pAEAIee2hx4OkSXRIiU4Zrxo1Xf7QFxkMY4x77vgaPcvfmuzom0y/fU1EdSnZeopGPvzMpFx80ODFx1P34R52nmVl0W8h4GNo0k8ZiWtRCdrJxs8xIg7z5P1h3Th/BJ0lwexpdK8sQZWng8xaO5ElthNuhO8UQx1l6FgEA:shout
60 - Player "bar", no password, no privileges:
65 Simple global environment variables.
66 Example content (added indentation):
73 Banned IP addresses and usernames.
74 Example content (added indentation):
80 Simple global map variables.
81 Example content (added indentation):
82 seed = 7980462765762429666
88 See Map File Format below.
93 Filename can be anything.
94 See Player File Format below.
99 Example content (added indentation):
105 - Should be pretty self-explanatory.
106 - Note: position is in nodes * 10
108 Example content (added indentation):
112 position = (-5231.97,15,1961.41)
117 Item default:torch 13
118 Item default:pick_steel 1 50112
119 Item experimental:tnt
120 Item default:cobble 99
121 Item default:pick_stone 1 13104
122 Item default:shovel_steel 1 51838
125 Item default:coal_lump 3
126 Item default:cobble 99
127 Item default:leaves 22
128 Item default:gravel 52
129 Item default:axe_steel 1 2045
130 Item default:cobble 98
132 Item default:water_source 94
134 Item default:mossycobble
135 Item default:pick_steel 1 64428
136 Item animalmaterials:bone
137 Item default:sword_steel
139 Item default:sword_stone 1 10647
172 Minetest maps consist of MapBlocks, chunks of 16x16x16 nodes.
174 In addition to the bulk node data, MapBlocks stored on disk also contain
179 We need a bit of history in here. Initially Minetest stored maps in a
180 format called the "sectors" format. It was a directory/file structure like
182 sectors2/XXX/ZZZ/YYYY
183 For example, the MapBlock at (0,1,-2) was this file:
184 sectors2/000/ffd/0001
186 Eventually Minetest outgrow this directory structure, as filesystems were
187 struggling under the amount of files and directories.
189 Large servers seriously needed a new format, and thus the base of the
190 current format was invented, suggested by celeron55 and implemented by
193 SQLite3 was slammed in, and blocks files were directly inserted as blobs
194 in a single table, indexed by integer primary keys, oddly mangled from
197 Today we know that SQLite3 allows multiple primary keys (which would allow
198 storing coordinates separately), but the format has been kept unchanged for
199 that part. So, this is where it has come.
204 map.sqlite is an sqlite3 database, containing a single table, called
205 "blocks". It looks like this:
207 CREATE TABLE `blocks` (`pos` INT NOT NULL PRIMARY KEY,`data` BLOB);
211 "pos" is created from the three coordinates of a MapBlock using this
212 algorithm, defined here in Python:
214 def getBlockAsInteger(p):
215 return int64(p[2]*16777216 + p[1]*4096 + p[0])
224 It can be converted the other way by using this code:
226 def getIntegerAsBlock(i):
227 x = unsignedToSigned(i % 4096, 2048)
228 i = int((i - x) / 4096)
229 y = unsignedToSigned(i % 4096, 2048)
230 i = int((i - y) / 4096)
231 z = unsignedToSigned(i % 4096, 2048)
234 def unsignedToSigned(i, max_positive):
238 return i - 2*max_positive
242 The blob is the data that would have otherwise gone into the file.
244 See below for description.
246 MapBlock serialization format
247 ==============================
248 NOTE: Byte order is MSB first (big-endian).
249 NOTE: Zlib data is in such a format that Python's zlib at least can
253 - map format version number, see serialisation.h for the latest number
257 - 0x01: is_underground: Should be set to 0 if there will be no light
258 obstructions above the block. If/when sunlight of a block is updated
259 and there is no block above it, this value is checked for determining
260 whether sunlight comes from the top.
261 - 0x02: day_night_differs: Whether the lighting of the block is different
262 on day and night. Only blocks that have this bit set are updated when
263 day transforms to night.
264 - 0x04: lighting_expired: If true, lighting is invalid and should be
265 updated. If you can't calculate lighting in your generator properly,
266 you could try setting this 1 to everything and setting the uppermost
267 block in every sector as is_underground=0. I am quite sure it doesn't
268 work properly, though.
269 - 0x08: generated: True if the block has been generated. If false, block
270 is mostly filled with CONTENT_IGNORE and is likely to contain eg. parts
271 of trees of neighboring blocks.
274 - Number of bytes in the content (param0) fields of nodes
275 if map format version <= 23:
277 if map format version >= 24:
281 - Number of bytes used for parameters per node
284 zlib-compressed node data:
285 if content_width == 1:
287 u8[4096]: param0 fields
288 u8[4096]: param1 fields
289 u8[4096]: param2 fields
290 if content_width == 2:
292 u16[4096]: param0 fields
293 u8[4096]: param1 fields
294 u8[4096]: param2 fields
295 - The location of a node in each of those arrays is (z*16*16 + y*16 + x).
297 zlib-compressed node metadata list
299 if map format version <= 22:
301 u16 count of metadata
303 u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
306 u8[content_size] content of metadata. Format depends on type_id, see below.
307 if map format version >= 23:
308 u8 version (=1) -- Note the type is u8, while for map format version <= 22 it's u16
309 u16 count of metadata
311 u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
321 if map format version == 23:
322 u8 unused version (always 0)
323 if map format version == 24: (NOTE: Not released as stable)
325 if nodetimer_version == 0:
327 if nodetimer_version == 1:
329 foreach num_of_timers:
330 u16 timer position (z*16*16 + y*16 + x)
333 if map format version >= 25:
334 -- Nothing right here, node timers are serialized later
336 u8 static object version:
339 u16 static_object_count
341 foreach static_object_count:
342 u8 type (object type-id)
343 s32 pos_x_nodes * 10000
344 s32 pos_y_nodes * 10000
345 s32 pos_z_nodes * 10000
350 - Timestamp when last saved, as seconds from starting the game.
351 - 0xffffffff = invalid/unknown timestamp, nothing should be done with the time
352 difference when loaded
354 u8 name-id-mapping version
357 u16 num_name_id_mappings
359 foreach num_name_id_mappings
365 if map format version == 25:
366 u8 length of the data of a single timer (always 2+4+4=10)
368 foreach num_of_timers:
369 u16 timer position (z*16*16 + y*16 + x)
377 A node is composed of the u8 fields param0, param1 and param2.
379 if map format version <= 23:
380 The content id of a node is determined as so:
384 content_id = (param0<<4) + (param2>>4)
385 if map format version >= 24:
386 The content id of a node is param0.
388 The purpose of param1 and param2 depend on the definition of the node.
392 The mapping maps node content ids to node names.
394 Node metadata format for map format versions <= 22
395 ---------------------------------------------------
396 The node metadata are serialized depending on the type_id field.
407 u8[len] inventory drawspec
408 u8 allow_text_input (bool)
409 u8 removal_disabled (bool)
410 u8 enforce_owner (bool)
428 17: Locked Chest metadata
435 Static objects are persistent freely moving objects in the world.
441 4: Oerkki (deprecated)
442 5: Firefly (deprecated)
443 6: MobV2 (deprecated)
460 s32 velocity.x * 10000
461 s32 velocity.y * 10000
462 s32 velocity.z * 10000
468 eg. 'default:pick_wood 21323'
469 eg. '"default:apple" 2'
471 - The wear value in tools is 0...65535
472 - There are also a number of older formats that you might stumble upon:
473 eg. 'node "default:dirt" 5'
474 eg. 'NodeItem default:dirt 5'
475 eg. 'ToolItem WPick 21323'
477 Inventory serialization format
478 -------------------------------
479 - The inventory serialization format is line-based
480 - The newline character used is "\n"
481 - The end condition of a serialized inventory is always "EndInventory\n"
482 - All the slots in a list must always be serialized.
484 Example (format does not include "---"):
488 Item default:sword_stone 1 10647
506 ==============================================
507 Minetest World Format used as of 2011-05 or so
508 ==============================================
510 Map data serialization format version 17.
512 0.3.1 does not use this format, but a more recent one. This exists here for
516 sectors/XXXXZZZZ or sectors2/XXX/ZZZ
517 XXXX, ZZZZ, XXX and ZZZ being the hexadecimal X and Z coordinates.
518 Under these, the block files are stored, called YYYY.
520 There also exists files map_meta.txt and chunk_meta, that are used by the
521 generator. If they are not found or invalid, the generator will currently
522 behave quite strangely.
524 The MapBlock file format (sectors2/XXX/ZZZ/YYYY):
525 -------------------------------------------------
527 NOTE: Byte order is MSB first.
530 - map format version number, this one is version 17
534 - 0x01: is_underground: Should be set to 0 if there will be no light
535 obstructions above the block. If/when sunlight of a block is updated and
536 there is no block above it, this value is checked for determining whether
537 sunlight comes from the top.
538 - 0x02: day_night_differs: Whether the lighting of the block is different on
539 day and night. Only blocks that have this bit set are updated when day
541 - 0x04: lighting_expired: If true, lighting is invalid and should be updated.
542 If you can't calculate lighting in your generator properly, you could try
543 setting this 1 to everything and setting the uppermost block in every
544 sector as is_underground=0. I am quite sure it doesn't work properly,
547 zlib-compressed map data:
549 u8[4096]: content types
550 u8[4096]: param1 values
551 u8[4096]: param2 values
553 zlib-compressed node metadata
556 u16 count of metadata
558 u16 position (= p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
561 u8[content_size] misc. stuff contained in the metadata
563 u16 mapblockobject_count
565 - if read != 0, just fail.
567 foreach mapblockobject_count:
568 - deprecated, should not be used. Length of this data can only be known by
569 properly parsing it. Just hope not to run into any of this.
571 u8 static object version:
574 u16 static_object_count
576 foreach static_object_count:
577 u8 type (object type-id)
585 - Timestamp when last saved, as seconds from starting the game.
586 - 0xffffffff = invalid/unknown timestamp, nothing will be done with the time
587 difference when loaded (recommended)
589 Node metadata format:
590 ---------------------
594 u8[string_len] string
602 Locking Chest metadata:
604 u8[string_len] string