equalpants / pigmap

Minecraft map generator
https://github.com/equalpants/pigmap/wiki/Example-maps
GNU General Public License v3.0
129 stars 43 forks source link

pigmap is a Minecraft map renderer, designed to be fast enough for very large worlds (like the Aporkalypse Now server, hence the name). It was inspired by Minecraft Overviewer and does essentially the same thing, just faster and with fewer fancy options. Features include:

-isometric projection; level of detail on max zoom is user-settable -Google Maps tile output -custom tilesets (supply your own terrain.png) -ability to manually edit the isometric block images generated from terrain.png, for further beautification -incremental map updates, but you must supply your own list of modified chunks (most likely via rsync or something similar) -multithreading -support for Alpha (chunk-based), Beta (.mcr), or Anvil (.mca) world formats -ability to restrict rendering to a certain range of Y-values (heights)

pigmap is free under the GPL (please see the file COPYING). I probably won't add too many more features beyond whatever the Aporkalypse might need in the future, but hopefully it will be useful to someone.

Michael J. Nelson, mike@thinkingpart.com ("equalpants" in Minecraft)

The files template.html and style.css contain code from Minecraft Overviewer (copyright Andrew Brown and contributors).

The official pigmap repository is at: https://github.com/equalpants/pigmap


Supported platforms are Linux and cygwin. OS X should also be fine, but I haven't tried it myself. (I've heard reports of it working, though.)

Dependencies are zlib, libpng, pthreads, and some very basic system stuff: getopt, mkdir, dirent.h. If your platform has a separate development package for libpng (called libpng-dev, libpng-devel, or something like that), you'll need that one, too.

Use supplied makefile to build with g++.


Change log (important stuff only):

1.2 -new blocks up to Minecraft 1.3 -chest.png, etc. now required -some speed improvements -block IDs >= 256 (from mods) now ignored rather than drawn as random blocks -memory requirements increased--should now be just a little lower than pre-Anvil versions (roughly ~250-300 MB per thread)

1.1.2 -added inverted slabs

1.1.1 -fixed a stupid bug preventing incremental updates from working

1.1 -Anvil format support -added -y and -Y params to specify minimum/maximum Y-coords for rendering -memory requirements are about 15-20% lower due to better caching -new blocks up to Minecraft 1.2.4: circle stone brick, new sandstone types, redstone lamps, new plank colors, upside-down stairs -some display fixes for older blocks whose behavior has changed: fences, doors

1.0.1 -new blocks: jungle logs/leaves/saplings

1.0 -NOTE: users of jcornwellshiel's fork will need to regenerate their blocks-B.png -new blocks all the way up through Minecraft 1.0 -endportal.png added; must be placed in images directory alongside terrain.png -fixed some ugliness in the rendering of cross-shaped item blocks (saplings, etc.) -improved rendering of large block sizes (B > 8)

0.7.4 -new blocks for Minecraft Beta 1.6: tall grass, ferns, dead shrubs, trapdoors

0.7.3 -new blocks for Minecraft Beta 1.4 and 1.5: locked chests, boosters, detectors, pine/birch saplings, webs

0.7.2 -support for big-endian platforms (like PowerPC)

0.7.1 -birch and pine leaves -more error/logging messages

0.7 -Minecraft Beta 1.3 support: new region file format, beds, repeaters, slabs

0.6.1 -support for HD texture packs

0.6 -new block types for Minecraft Beta 1.2: lapis, cake, etc. -remaining undrawn blocks from previous versions now drawn: fire, buttons, levers, ascending cart tracks -fire.png added; must be placed in images directory alongside terrain.png -some block image offsets changed; see note below if you have manually edited your blocks-B.png -some drawing improvements; may want to redo all block images from terrain.png

0.5.1 -speed improvements -previously, we would abort if the world was too absurdly large to deal with--i.e. if there were some chunks whose coordinates were well into the billions--but apparently there is a Minecraft bug that can create such chunks way off in space, even if the world is normally-sized, so now we just ignore any chunks that are too far out to handle

0.5 -initial version


Usage examples:

full render:

pigmap -B 6 -T 1 -Z 10 -i input/World1 -o output/World1 -g images -h 3

...builds a map with parameters B = 6, T = 1, baseZoom = 10, reading world data from the path "input/World1", writing tiles out to the path "output/World1", reading terrain images from the path "images", and using 3 threads.

incremental update:

pigmap -i input/World1 -o output/World1 -r regionlist -h 3 -x

...updates an existing map by redrawing any tiles touched by regions listed in the file "regionlist", with the input and output dirs as before. Terrain images are read from the path ".", and 3 threads are used. Map parameters are read from the existing map, and if the existing baseZoom is too small, it will be incremented.


Error messages are written to stderr; normal output to stdout. There isn't much (read: any) of a progress indicator at the moment, but there are some statistics upon completion.


Explanation of command-line options:

  1. Params for both full renders and incremental updates:

a. input path, output path (-i, -o)

The input path should be the top directory of the world data (i.e. where level.dat is). The tile output path should be the top of the Google Maps directory structure (i.e. where base.png is). Tile images will be written to the output path, along with a file "pigmap.params" which remembers what parameters the map was drawn with. For incremental updates, the output path must exist already, and must contain the pigmap.params file.

Three world formats are supported: the current Anvil format (with .mca region files), the .mcr region format that preceded it, and the even older chunk-based format. If the input path contains more than one format, then only the newer format will be used.

b. [optional (kind of)] HTML source path (-m)

This is where pigmap expects to find the files "template.html" and "style.css", which it will use to construct a bare-bones HTML page for viewing the map. These files are not optional, but the -m parameter itself may be omitted, in which case "." is used as the HTML source path.

The map-viewing page is called "pigmap-default.html" and is written to the output path. It doesn't have any fancy capabilities (just plain old markers); it's meant only to demonstrate the JavaScript for converting Minecraft coords to Google Maps latitude/longitude. This file is rewritten with every incremental update; make a copy if you need to add fancier abilities to it.

c. [optional (kind of)] image path (-g)

This is where pigmap expects to find either a copy of your tileset (terrain.png, etc.), or a copy of blocks-B.png (substituting the actual numeric value of B; see below for definition of B), a pigmap-generated file that contains the isometric renderings of each block. These files are not optional, but the -g parameter itself may be omitted, in which case "." is used as the image path.

Each blocks-B.png comes with a corresponding blocks-B.version, which remembers how many block images are stored in blocks-B.png. (As more blocks are added to the game, the version will change.)

The selection of block images works thusly:

-If blocks-B.png does not exist, then the tileset you provide will be used to create it. -If blocks-B.png exists but has an old version, your tileset will be used to fill in any missing (i.e. new) blocks, but the existing portions of blocks-B.png will be preserved. -If blocks-B.png exists and is up-to-date, its block images will be used.

This means that pigmap will need your tileset the first time it runs, so it can generate blocks-B.png; subsequent runs will use the existing blocks-B.png, which can be manually edited if insufficiently pretty, or for special effects, etc.

The following images are required to generate blocks-B.png: -terrain.png, chest.png, largechest.png, enderchest.png: these files come from your tileset or minecraft.jar -fire.png, endportal.png: these files are included with pigmap All of these must be RGBA png files (not just RGB).

High-res tilesets are supported. The textures in terrain.png, fire.png, and endportal.png can be any size, as long as they remain square. The textures in the chest pngs can be scaled up, but their size must be an integer multiple of the original size.

d. [optional] number of threads (-h)

Defaults to 1. Each thread requires around 250-300 MB of RAM (they work in different areas of the map and keep separate caches of chunk data). Returns from extra threads may diminish quickly as the disk becomes a bottleneck.

  1. Params for full renders only:

a. map parameters B, T, [optional] baseZoom (-B, -T, -Z):

B is an integer >= 2 which controls the size (in pixels) of the blocks in the base zoom level. The map projection lays out blocks on a hexagonal grid generated from the distances [+/-2B, +/-B] and [0, +/-2B], and each individual block's bounding box is 4B x 4B.

T is the tile multiplier, an integer >= 1 which controls how many chunks wide a tile is.

The size of each generated tile is 64BT x 64BT.

(To match Minecraft Overviewer's highest zoom level, use B=6 and T=1, for a tile size of 384 x 384. To match its second-highest zoom, use B=3 and T=2.)

baseZoom is the Google Maps zoom level that the base tiles should be placed on. This is important because Google Maps allows only 2^Z by 2^Z tiles for each zoom level Z; if baseZoom is not high enough, some tiles will not fit on the Google Map. (Out-of-bounds tiles will be noticed at the start of a render, and the render aborted.)

If baseZoom is omitted, it will be set to the lowest value that can fit all the required tiles.

b. [optional] minimum/maximum Y-coords (-y, -Y)

By default, pigmap will draw all blocks present in the world data, but these parameters can be used to restrict rendering to blocks within a particular height range. -y is the minimum Y-coord which will be drawn, and -Y is the maximum.

Note that these values, if used, will persist through incremental updates of the map (like B and T do), even if the actual height limit in the game changes in the future. So if you want the map to always render all the way to the top, then don't use -Y, as opposed to using it but passing in the current height limit.

  1. Params for incremental updates only:

a. regionlist file (-r) or chunklist file (-c)

The name of a text file containing the filenames of regions or chunks that should be updated, one per line. Supplied filenames can have a relative or absolute path or can just be the file name; only the name will be examined.

If the input world is in region format (either .mca or .mcr regions), then a regionlist must be used, not a chunklist. However, the extensions on the filenames in a regionlist do not matter--only the coordinates from the filenames will be considered, and pigmap will always read the newest available region.

The current format of the input world does not have to match the format used in the previous map render--an incremental update will work fine even if the world data has been converted since the last render. (Of course it would be trickier to get a meaningful regionlist in such a case--to distinguish the regions which have actually changed from those which have merely been converted-- but if you have such a list, then pigmap can use it.)

b. [optional] expand map if necessary (-x)

This is useful for frequently-updated maps: eventually, as the world expands outwards, it will become too large for the current baseZoom, and an incremental update will fail. If -x has been passed, then if an incremental update fails due to out-of-bounds tiles, the map's baseZoom will be increased by 1, and the update retried. (The baseZoom increase is not undone if the second attempt also fails.)

Note that increasing a map's baseZoom is quick: all the tiles are simply moved one level deeper in the hierarchy, and the top two zoom levels redrawn.


What happens in a full render: the world data is scanned, and every chunk that exists on disk is noted. All tiles that include any chunks are rendered and saved; any tiles that might exist already in the output path are overwritten.

What happens in an incremental update: the chunklist is read and its chunks are considered "required"; the world data is not scanned. (However, the input path must still contain the non-required chunks; that is, you can't just use a partial copy of a world. This is because each tile touches multiple chunks; to render a required chunk, data from its non-required neighbors may be necessary.) All tiles that include required chunks are rendered and saved. Base tiles that exist already in the output path are overwritten, but those at lower zoom levels are merely modified--only the changed portions are redrawn.


Special note for those who choose to manually edit blocks-B.png:

When new block types are introduced, their block images are added on to the end of blocks-B.png, and the existing contents are preserved, so you don't need to worry about previous modifications getting destroyed. However, sometimes it may be necessary to remove existing block images and replace them with new versions; when this happens, the old block image offset will no longer be used, and a new block image will be added to the end of the file.

Example: prior to pigmap 0.6, the furnace block images were located at offsets 68, 69, and 149-152. Starting with 0.6, they are instead located at 183-188. (This is because the furnace graphics were changed in Minecraft Beta 1.2.) So if you modified the furnace block images while using a pre-0.6 version of pigmap, your modified images can still be found at their old locations in your blocks-B.png, but they must be copied to the new locations.

Complete list of block image moves:

--- pigmap 1.2 --- gravel: 21->483 chests: 54->484, 177->485, 297->486, [173-176]->[487,490], [298-301]->[491-494]

--- pigmap 1.0 --- beds: 232->281, 233->282, 234->283, 235->284, 236->285, 237->286, 238->287, 239->288 cake: 228->289

--- pigmap 0.6 --- furnaces: 68->183, 69->186, 149->184, 150->185, 151->187, 152->188 fire: 48->189 buttons: 123->190, 124->191, 125->192, 126->193 levers: 104->194, 105->195, 106->196, 107->197, 108->198, 109->199 ascending tracks: 88->200, 89->201, 90->202, 91->203