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, this one is version 22
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
300 u16 count of metadata
302 u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
305 u8[content_size] (content of metadata)
308 if map format version == 23:
309 u8 unused version (always 0)
310 if map format version == 24: (NOTE: Not released as stable)
312 if nodetimer_version == 0:
314 if nodetimer_version == 1:
316 foreach num_of_timers:
317 u16 timer position (z*16*16 + y*16 + x)
320 if map format version >= 25:
321 -- Nothing right here, node timers are serialized later
323 u8 static object version:
326 u16 static_object_count
328 foreach static_object_count:
329 u8 type (object type-id)
330 s32 pos_x_nodes * 10000
331 s32 pos_y_nodes * 10000
332 s32 pos_z_nodes * 10000
337 - Timestamp when last saved, as seconds from starting the game.
338 - 0xffffffff = invalid/unknown timestamp, nothing should be done with the time
339 difference when loaded
341 u8 name-id-mapping version
344 u16 num_name_id_mappings
346 foreach num_name_id_mappings
352 if map format version == 25:
353 u8 length of the data of a single timer (always 2+4+4=10)
355 foreach num_of_timers:
356 u16 timer position (z*16*16 + y*16 + x)
364 A node is composed of the u8 fields param0, param1 and param2.
366 if map format version <= 23:
367 The content id of a node is determined as so:
371 content_id = (param0<<4) + (param2>>4)
372 if map format version >= 24:
373 The content id of a node is param0.
375 The purpose of param1 and param2 depend on the definition of the node.
379 The mapping maps node content ids to node names.
382 ---------------------
393 u8[len] inventory drawspec
394 u8 allow_text_input (bool)
395 u8 removal_disabled (bool)
396 u8 enforce_owner (bool)
414 17: Locked Chest metadata
421 Static objects are persistent freely moving objects in the world.
427 4: Oerkki (deprecated)
428 5: Firefly (deprecated)
429 6: MobV2 (deprecated)
446 s32 velocity.x * 10000
447 s32 velocity.y * 10000
448 s32 velocity.z * 10000
454 eg. 'default:pick_wood 21323'
455 eg. '"default:apple" 2'
457 - The wear value in tools is 0...65535
458 - There are also a number of older formats that you might stumble upon:
459 eg. 'node "default:dirt" 5'
460 eg. 'NodeItem default:dirt 5'
461 eg. 'ToolItem WPick 21323'
463 Inventory serialization format
464 -------------------------------
465 - The inventory serialization format is line-based
466 - The newline character used is "\n"
467 - The end condition of a serialized inventory is always "EndInventory\n"
468 - All the slots in a list must always be serialized.
470 Example (format does not include "---"):
474 Item default:sword_stone 1 10647
492 ==============================================
493 Minetest World Format used as of 2011-05 or so
494 ==============================================
496 Map data serialization format version 17.
498 0.3.1 does not use this format, but a more recent one. This exists here for
502 sectors/XXXXZZZZ or sectors2/XXX/ZZZ
503 XXXX, ZZZZ, XXX and ZZZ being the hexadecimal X and Z coordinates.
504 Under these, the block files are stored, called YYYY.
506 There also exists files map_meta.txt and chunk_meta, that are used by the
507 generator. If they are not found or invalid, the generator will currently
508 behave quite strangely.
510 The MapBlock file format (sectors2/XXX/ZZZ/YYYY):
511 -------------------------------------------------
513 NOTE: Byte order is MSB first.
516 - map format version number, this one is version 17
520 - 0x01: is_underground: Should be set to 0 if there will be no light
521 obstructions above the block. If/when sunlight of a block is updated and
522 there is no block above it, this value is checked for determining whether
523 sunlight comes from the top.
524 - 0x02: day_night_differs: Whether the lighting of the block is different on
525 day and night. Only blocks that have this bit set are updated when day
527 - 0x04: lighting_expired: If true, lighting is invalid and should be updated.
528 If you can't calculate lighting in your generator properly, you could try
529 setting this 1 to everything and setting the uppermost block in every
530 sector as is_underground=0. I am quite sure it doesn't work properly,
533 zlib-compressed map data:
535 u8[4096]: content types
536 u8[4096]: param1 values
537 u8[4096]: param2 values
539 zlib-compressed node metadata
542 u16 count of metadata
544 u16 position (= p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
547 u8[content_size] misc. stuff contained in the metadata
549 u16 mapblockobject_count
551 - if read != 0, just fail.
553 foreach mapblockobject_count:
554 - deprecated, should not be used. Length of this data can only be known by
555 properly parsing it. Just hope not to run into any of this.
557 u8 static object version:
560 u16 static_object_count
562 foreach static_object_count:
563 u8 type (object type-id)
571 - Timestamp when last saved, as seconds from starting the game.
572 - 0xffffffff = invalid/unknown timestamp, nothing will be done with the time
573 difference when loaded (recommended)
575 Node metadata format:
576 ---------------------
580 u8[string_len] string
588 Locking Chest metadata:
590 u8[string_len] string