1 =============================
2 Minetest World Format 22...27
3 =============================
5 This applies to a world format carrying the block serialization version
6 22...27, 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
10 - 27 was added in 0.4.15-dev
12 The block serialization version does not fully specify every aspect of this
13 format; if compliance with this format is to be checked, it needs to be
14 done by detecting if the files and data indeed follows it.
18 Data can, in theory, be contained in the flat file directory structure
19 described below in Version 17, but it is not officially supported. Also you
20 may stumble upon all kinds of oddities in not-so-recent formats.
24 Everything is contained in a directory, the name of which is freeform, but
25 often serves as the name of the world.
27 Currently the authentication and ban data is stored on a per-world basis.
28 It can be copied over from an old world to a newly created world.
31 |-- auth.txt ----- Authentication data
32 |-- auth.sqlite -- Authentication data (SQLite alternative)
33 |-- env_meta.txt - Environment metadata
34 |-- ipban.txt ---- Banned ips/users
35 |-- map_meta.txt - Map metadata
36 |-- map.sqlite --- Map data
37 |-- players ------ Player directory
38 | |-- player1 -- Player file
39 | '-- Foo ------ Player file
40 `-- world.mt ----- World metadata
44 Contains authentication data, player per line.
45 <name>:<password hash>:<privilege1,...>
47 Legacy format (until 0.4.12) of password hash is <name><password> SHA1'd,
48 in the base64 encoding.
50 Format (since 0.4.13) of password hash is #1#<salt>#<verifier>, with the
51 parts inside <> encoded in the base64 encoding.
52 <verifier> is an RFC 2945 compatible SRP verifier,
53 of the given salt, password, and the player's name lowercased,
54 using the 2048-bit group specified in RFC 5054 and the SHA-256 hash function.
57 - Player "celeron55", no password, privileges "interact" and "shout":
58 celeron55::interact,shout
59 - Player "Foo", password "bar", privilege "shout", with a legacy password hash:
60 foo:iEPX+SQWIR3p67lj/0zigSWTKHg:shout
61 - Player "Foo", password "bar", privilege "shout", with a 0.4.13 pw hash:
62 foo:#1#hPpy4O3IAn1hsNK00A6wNw#Kpu6rj7McsrPCt4euTb5RA5ltF7wdcWGoYMcRngwDi11cZhPuuR9i5Bo7o6A877TgcEwoc//HNrj9EjR/CGjdyTFmNhiermZOADvd8eu32FYK1kf7RMC0rXWxCenYuOQCG4WF9mMGiyTPxC63VAjAMuc1nCZzmy6D9zt0SIKxOmteI75pAEAIee2hx4OkSXRIiU4Zrxo1Xf7QFxkMY4x77vgaPcvfmuzom0y/fU1EdSnZeopGPvzMpFx80ODFx1P34R52nmVl0W8h4GNo0k8ZiWtRCdrJxs8xIg7z5P1h3Th/BJ0lwexpdK8sQZWng8xaO5ElthNuhO8UQx1l6FgEA:shout
63 - Player "bar", no password, no privileges:
68 Contains authentification data as an SQLite database. This replaces auth.txt
69 above when auth_backend is set to "sqlite3" in world.mt .
71 This database contains two tables "auth" and "user_privileges":
74 `id` INTEGER PRIMARY KEY AUTOINCREMENT,
75 `name` VARCHAR(32) UNIQUE,
76 `password` VARCHAR(512),
79 CREATE TABLE `user_privileges` (
81 `privilege` VARCHAR(32),
82 PRIMARY KEY (id, privilege)
83 CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES auth (id) ON DELETE CASCADE
86 The "name" and "password" fields of the auth table are the same as the auth.txt
87 fields (with modern password hash). The "last_login" field is the last login
88 time as a unix time stamp.
90 The "user_privileges" table contains one entry per privilege and player.
91 A player with "interact" and "shout" privileges will have two entries, one
92 with privilege="interact" and the second with privilege="shout".
96 Simple global environment variables.
97 Example content (added indentation):
104 Banned IP addresses and usernames.
105 Example content (added indentation):
111 Simple global map variables.
112 Example content (added indentation):
113 seed = 7980462765762429666
119 See Map File Format below.
124 Filename can be anything.
125 See Player File Format below.
130 Example content (added indentation and - explanations):
131 gameid = mesetint - name of the game
132 enable_damage = true - whether damage is enabled or not
133 creative_mode = false - whether creative mode is enabled or not
134 backend = sqlite3 - which DB backend to use for blocks (sqlite3, dummy, leveldb, redis, postgresql)
135 player_backend = sqlite3 - which DB backend to use for player data
136 readonly_backend = sqlite3 - optionally readonly seed DB (DB file _must_ be located in "readonly" subfolder)
137 server_announce = false - whether the server is publicly announced or not
138 load_mod_<mod> = false - whether <mod> is to be loaded in this world
139 auth_backend = files - which DB backend to use for authentication data
144 - Should be pretty self-explanatory.
145 - Note: position is in nodes * 10
147 Example content (added indentation):
151 position = (-5231.97,15,1961.41)
156 Item default:torch 13
157 Item default:pick_steel 1 50112
158 Item experimental:tnt
159 Item default:cobble 99
160 Item default:pick_stone 1 13104
161 Item default:shovel_steel 1 51838
164 Item default:coal_lump 3
165 Item default:cobble 99
166 Item default:leaves 22
167 Item default:gravel 52
168 Item default:axe_steel 1 2045
169 Item default:cobble 98
171 Item default:water_source 94
173 Item default:mossycobble
174 Item default:pick_steel 1 64428
175 Item animalmaterials:bone
176 Item default:sword_steel
178 Item default:sword_stone 1 10647
211 Minetest maps consist of MapBlocks, chunks of 16x16x16 nodes.
213 In addition to the bulk node data, MapBlocks stored on disk also contain
218 We need a bit of history in here. Initially Minetest stored maps in a
219 format called the "sectors" format. It was a directory/file structure like
221 sectors2/XXX/ZZZ/YYYY
222 For example, the MapBlock at (0,1,-2) was this file:
223 sectors2/000/ffd/0001
225 Eventually Minetest outgrow this directory structure, as filesystems were
226 struggling under the amount of files and directories.
228 Large servers seriously needed a new format, and thus the base of the
229 current format was invented, suggested by celeron55 and implemented by
232 SQLite3 was slammed in, and blocks files were directly inserted as blobs
233 in a single table, indexed by integer primary keys, oddly mangled from
236 Today we know that SQLite3 allows multiple primary keys (which would allow
237 storing coordinates separately), but the format has been kept unchanged for
238 that part. So, this is where it has come.
243 map.sqlite is an sqlite3 database, containing a single table, called
244 "blocks". It looks like this:
246 CREATE TABLE `blocks` (`pos` INT NOT NULL PRIMARY KEY,`data` BLOB);
250 "pos" is created from the three coordinates of a MapBlock using this
251 algorithm, defined here in Python:
253 def getBlockAsInteger(p):
254 return int64(p[2]*16777216 + p[1]*4096 + p[0])
263 It can be converted the other way by using this code:
265 def getIntegerAsBlock(i):
266 x = unsignedToSigned(i % 4096, 2048)
267 i = int((i - x) / 4096)
268 y = unsignedToSigned(i % 4096, 2048)
269 i = int((i - y) / 4096)
270 z = unsignedToSigned(i % 4096, 2048)
273 def unsignedToSigned(i, max_positive):
277 return i - 2*max_positive
281 The blob is the data that would have otherwise gone into the file.
283 See below for description.
285 MapBlock serialization format
286 ==============================
287 NOTE: Byte order is MSB first (big-endian).
288 NOTE: Zlib data is in such a format that Python's zlib at least can
292 - map format version number, see serialisation.h for the latest number
296 - 0x01: is_underground: Should be set to 0 if there will be no light
297 obstructions above the block. If/when sunlight of a block is updated
298 and there is no block above it, this value is checked for determining
299 whether sunlight comes from the top.
300 - 0x02: day_night_differs: Whether the lighting of the block is different
301 on day and night. Only blocks that have this bit set are updated when
302 day transforms to night.
303 - 0x04: lighting_expired: Not used in version 27 and above. If true,
304 lighting is invalid and should be updated. If you can't calculate
305 lighting in your generator properly, you could try setting this 1 to
306 everything and setting the uppermost block in every sector as
307 is_underground=0. I am quite sure it doesn't work properly, though.
308 - 0x08: generated: True if the block has been generated. If false, block
309 is mostly filled with CONTENT_IGNORE and is likely to contain eg. parts
310 of trees of neighboring blocks.
312 u16 lighting_complete
313 - Added in version 27.
314 - This contains 12 flags, each of them corresponds to a direction.
315 - Indicates if the light is correct at the sides of a map block.
316 Lighting may not be correct if the light changed, but a neighbor
317 block was not loaded at that time.
318 If these flags are false, Minetest will automatically recompute light
319 when both this block and its required neighbor are loaded.
321 nothing, nothing, nothing, nothing,
322 night X-, night Y-, night Z-, night Z+, night Y+, night X+,
323 day X-, day Y-, day Z-, day Z+, day Y+, day X+.
324 Where 'day' is for the day light bank, 'night' is for the night
326 The 'nothing' bits should be always set, as they will be used
327 to indicate if direct sunlight spreading is finished.
328 - Example: if the block at (0, 0, 0) has
329 lighting_complete = 0b1111111111111110,
330 then Minetest will correct lighting in the day light bank when
331 the block at (1, 0, 0) is also loaded.
334 - Number of bytes in the content (param0) fields of nodes
335 if map format version <= 23:
337 if map format version >= 24:
341 - Number of bytes used for parameters per node
344 zlib-compressed node data:
345 if content_width == 1:
347 u8[4096]: param0 fields
348 u8[4096]: param1 fields
349 u8[4096]: param2 fields
350 if content_width == 2:
352 u16[4096]: param0 fields
353 u8[4096]: param1 fields
354 u8[4096]: param2 fields
355 - The location of a node in each of those arrays is (z*16*16 + y*16 + x).
357 zlib-compressed node metadata list
359 if map format version <= 22:
361 u16 count of metadata
363 u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
366 u8[content_size] content of metadata. Format depends on type_id, see below.
367 if map format version >= 23:
368 u8 version (=1) -- Note the type is u8, while for map format version <= 22 it's u16
369 u16 count of metadata
371 u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
381 if map format version == 23:
382 u8 unused version (always 0)
383 if map format version == 24: (NOTE: Not released as stable)
385 if nodetimer_version == 0:
387 if nodetimer_version == 1:
389 foreach num_of_timers:
390 u16 timer position (z*16*16 + y*16 + x)
393 if map format version >= 25:
394 -- Nothing right here, node timers are serialized later
396 u8 static object version:
399 u16 static_object_count
401 foreach static_object_count:
402 u8 type (object type-id)
403 s32 pos_x_nodes * 10000
404 s32 pos_y_nodes * 10000
405 s32 pos_z_nodes * 10000
410 - Timestamp when last saved, as seconds from starting the game.
411 - 0xffffffff = invalid/unknown timestamp, nothing should be done with the time
412 difference when loaded
414 u8 name-id-mapping version
417 u16 num_name_id_mappings
419 foreach num_name_id_mappings
425 if map format version == 25:
426 u8 length of the data of a single timer (always 2+4+4=10)
428 foreach num_of_timers:
429 u16 timer position (z*16*16 + y*16 + x)
437 A node is composed of the u8 fields param0, param1 and param2.
439 if map format version <= 23:
440 The content id of a node is determined as so:
444 content_id = (param0<<4) + (param2>>4)
445 if map format version >= 24:
446 The content id of a node is param0.
448 The purpose of param1 and param2 depend on the definition of the node.
452 The mapping maps node content ids to node names.
454 Node metadata format for map format versions <= 22
455 ---------------------------------------------------
456 The node metadata are serialized depending on the type_id field.
467 u8[len] inventory drawspec
468 u8 allow_text_input (bool)
469 u8 removal_disabled (bool)
470 u8 enforce_owner (bool)
488 17: Locked Chest metadata
495 Static objects are persistent freely moving objects in the world.
501 4: Oerkki (deprecated)
502 5: Firefly (deprecated)
503 6: MobV2 (deprecated)
520 s32 velocity.x * 10000
521 s32 velocity.y * 10000
522 s32 velocity.z * 10000
528 eg. 'default:pick_wood 21323'
529 eg. '"default:apple" 2'
531 - The wear value in tools is 0...65535
532 - There are also a number of older formats that you might stumble upon:
533 eg. 'node "default:dirt" 5'
534 eg. 'NodeItem default:dirt 5'
535 eg. 'ToolItem WPick 21323'
537 Inventory serialization format
538 -------------------------------
539 - The inventory serialization format is line-based
540 - The newline character used is "\n"
541 - The end condition of a serialized inventory is always "EndInventory\n"
542 - All the slots in a list must always be serialized.
544 Example (format does not include "---"):
548 Item default:sword_stone 1 10647
566 ==============================================
567 Minetest World Format used as of 2011-05 or so
568 ==============================================
570 Map data serialization format version 17.
572 0.3.1 does not use this format, but a more recent one. This exists here for
576 sectors/XXXXZZZZ or sectors2/XXX/ZZZ
577 XXXX, ZZZZ, XXX and ZZZ being the hexadecimal X and Z coordinates.
578 Under these, the block files are stored, called YYYY.
580 There also exists files map_meta.txt and chunk_meta, that are used by the
581 generator. If they are not found or invalid, the generator will currently
582 behave quite strangely.
584 The MapBlock file format (sectors2/XXX/ZZZ/YYYY):
585 -------------------------------------------------
587 NOTE: Byte order is MSB first.
590 - map format version number, this one is version 17
594 - 0x01: is_underground: Should be set to 0 if there will be no light
595 obstructions above the block. If/when sunlight of a block is updated and
596 there is no block above it, this value is checked for determining whether
597 sunlight comes from the top.
598 - 0x02: day_night_differs: Whether the lighting of the block is different on
599 day and night. Only blocks that have this bit set are updated when day
601 - 0x04: lighting_expired: If true, lighting is invalid and should be updated.
602 If you can't calculate lighting in your generator properly, you could try
603 setting this 1 to everything and setting the uppermost block in every
604 sector as is_underground=0. I am quite sure it doesn't work properly,
607 zlib-compressed map data:
609 u8[4096]: content types
610 u8[4096]: param1 values
611 u8[4096]: param2 values
613 zlib-compressed node metadata
616 u16 count of metadata
618 u16 position (= p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
621 u8[content_size] misc. stuff contained in the metadata
623 u16 mapblockobject_count
625 - if read != 0, just fail.
627 foreach mapblockobject_count:
628 - deprecated, should not be used. Length of this data can only be known by
629 properly parsing it. Just hope not to run into any of this.
631 u8 static object version:
634 u16 static_object_count
636 foreach static_object_count:
637 u8 type (object type-id)
645 - Timestamp when last saved, as seconds from starting the game.
646 - 0xffffffff = invalid/unknown timestamp, nothing will be done with the time
647 difference when loaded (recommended)
649 Node metadata format:
650 ---------------------
654 u8[string_len] string
662 Locking Chest metadata:
664 u8[string_len] string