Map Editing (hex)

server_level.dat
(Note: in this example, a default server_level.dat is being used, with the size of 256x256x64. Level files with bigger dimensions may differ in amount of bytes.) The server_level.dat file is where the Minecraft Server dumps the level information for permanent storage. As this file is primarily raw level data, it can be quite large: a regular 256x256x64 sized level is 4 megabytes in size. The file is compressed using gzip, however. Most of the block values are 0 (empty space), so therefore, the size is reduced considerably by the compression, usually down to a few hundred kilobytes.

After un-gzipping the datafile (you may simply decompress the file itself using a tool which can decompress gzipped files), sequentially the datafile consists of the number 656127880 as 32 bit integer (0x27 0x1B 0xB7 0x88 in HEX), followed by the number 2 as a byte (0x02 in HEX), then followed by serialized Level Java classfile instance. The level's block values (material type, such as stone) are stored inside of a byte array inside of this class.

The first 65536 sequential bytes of the array make up the top-most 256 x 256 "sliver" of the level, with the north-most row of bytes, from left to right, being at locations 0 ... 255, the row below that at, from left to right, locations 256 ... 511, and so on. The default maps are 64 "slivers" deep.

Accessing the array of bytes
One generally has two options for accessing the byte array of blocks:

You could deserialize the compressed .dat file directly back into an instance of a Level object inside of Java, thus having access to the instance of the Level object in the exact same way the Minecraft Server does. This would allow you to set the blocks, dimensions, spawn point and other aspects of the map directly by calling the methods on the instantiated Level object. Manual decompression is not needed before loading, because Java can compress and decompress gzipped files on the fly. To load the datafile back into an instance of the Level class, you would need the class definition for the Level class. This is included with the minecraft-server.jar file. An example of this can be seen in the creation and saving class.

Others have read and modified the map's data by simply accessing the raw byte array in the datafile file. To do this, you would decompress it, make changes to the bytes where the byte array is stored, and then compress it again. Since you are editing it raw, you must keep the first 344 (14E in HEX) bytes intact. The next 256x256x64 bytes are where the byte array is stored. Addtionally, it is also possible to alter the spawn location coordinates this way if you know where to look: there are 3 integer values starting at byte 284 and thus overwriting the next 12 bytes (3 integers) will allow you to change the spawn location.

(Disclaimer: This is liable to change as Java changes)

Future-proof map format
Notch has added info on minecraft.net about a new level format, the Named Binary Tag. It is not implemented yet, but for future-proof map editors, implementing this format already may prove very useful.

For Hex values see Blocks,Items & Data values