diff --git a/plugins/mapexport/CMakeLists.txt b/plugins/mapexport/CMakeLists.txt index c866ebc90..6349b5ad1 100644 --- a/plugins/mapexport/CMakeLists.txt +++ b/plugins/mapexport/CMakeLists.txt @@ -43,4 +43,4 @@ COMMAND protoc-bin -I=${CMAKE_CURRENT_SOURCE_DIR}/proto --cpp_out=${CMAKE_CURREN DEPENDS protoc-bin ${PROJECT_PROTOS} ) -DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite) +DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf) diff --git a/plugins/mapexport/mapexport.cpp b/plugins/mapexport/mapexport.cpp index db32cadac..4fe10c80c 100644 --- a/plugins/mapexport/mapexport.cpp +++ b/plugins/mapexport/mapexport.cpp @@ -1,10 +1,16 @@ #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/MapCache.h" +using namespace DFHack; + +#include + +#include "DataDefs.h" +#include "df/world.h" #include "proto/Map.pb.h" -using namespace DFHack; DFhackCExport command_result mapexport (Core * c, std::vector & parameters); @@ -17,7 +23,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { GOOGLE_PROTOBUF_VERIFY_VERSION; commands.clear(); - commands.push_back(PluginCommand("mapexport", "Starts up and shuts down protobufs.", mapexport, true)); + commands.push_back(PluginCommand("mapexport", "Exports the current map to a file.", mapexport, true)); return CR_OK; } @@ -33,14 +39,151 @@ DFhackCExport command_result mapexport (Core * c, std::vector & pa { if(parameters[i] == "help" || parameters[i] == "?") { - c->con.print("This doesn't do anything at all yet.\n"); + c->con.print("Exports the currently visible map to a file.\n" + "Usage: mapexport \n" + ); return CR_OK; } } + std::string filename; + if (parameters.size() < 1) + { + c->con.printerr("Please supply a filename.\n"); + return CR_OK; + } + filename = parameters[0]; + bool showHidden = true; + + uint32_t x_max=0, y_max=0, z_max=0; c->Suspend(); - dfproto::Tile tile; - c->con.print("Hold on, I'm working on it!\n"); + if (!Maps::IsValid()) + { + c->con.printerr("Map is not available!\n"); + c->Resume(); + return CR_FAILURE; + } + Maps::getSize(x_max, y_max, z_max); + MapExtras::MapCache map; + DFHack::Materials *mats = c->getMaterials(); + if (!mats->df_inorganic) + { + c->con.printerr("Unable to read inorganic material definitons!\n"); + c->Resume(); + return CR_FAILURE; + } + if (!mats->df_organic) + { + c->con.printerr("Unable to read organic material definitons!\n"); + //showPlants = false; + } + + DFHack::Vegetation *veg = c->getVegetation(); + if (veg->Start()) + { + c->con.printerr("Unable to read vegetation; plants won't be listed!\n" ); + } + + dfproto::Map protomap; + protomap.set_x_size(x_max); + protomap.set_y_size(y_max); + protomap.set_z_size(z_max); + + DFHack::t_feature blockFeatureGlobal; + DFHack::t_feature blockFeatureLocal; + + for(uint32_t z = 0; z < z_max; z++) + { + for(uint32_t b_y = 0; b_y < y_max; b_y++) + { + for(uint32_t b_x = 0; b_x < x_max; b_x++) + { + // Get the map block + df::coord2d blockCoord(b_x, b_y); + MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); + if (!b || !b->valid) + { + continue; + } + + dfproto::Block *protoblock = protomap.add_block(); + protoblock->set_x(b_x); + protoblock->set_y(b_y); + protoblock->set_z(z); + + { // Find features + uint32_t index = b->raw.global_feature; + if (index != -1) + Maps::GetGlobalFeature(blockFeatureGlobal, index); + + index = b->raw.local_feature; + if (index != -1) + Maps::GetLocalFeature(blockFeatureLocal, blockCoord, index); + } + + int global_z = df::global::world->map.region_z + z; + + // Iterate over all the tiles in the block + for(uint32_t y = 0; y < 16; y++) + { + for(uint32_t x = 0; x < 16; x++) + { + df::coord2d coord(x, y); + df::tile_designation des = b->DesignationAt(coord); + df::tile_occupancy occ = b->OccupancyAt(coord); + + // Skip hidden tiles + if (!showHidden && des.bits.hidden) + { + continue; + } + + dfproto::Tile *prototile = protoblock->add_tile(); + prototile->set_x(x); + prototile->set_y(y); + + // Check for liquid + if (des.bits.flow_size) + { + //if (des.bits.liquid_type == df::tile_liquid::Magma) + + //else + } + + uint16_t type = b->TileTypeAt(coord); + const DFHack::TileRow *info = DFHack::getTileRow(type); + prototile->set_type((dfproto::Tile::TileType)info->shape); + /*switch (info->shape) + { + case DFHack::WALL: + prototile->set_type(dfproto::Tile::WALL); + break; + default: + break; + }*/ + } + } + } // block x + + // Clean uneeded memory + map.trash(); + } // block y + } // z + + std::ofstream output(filename, std::ios::out | std::ios::trunc | std::ios::binary); + if (!output.is_open()) + { + c->con.printerr("Couldn't open the output file.\n"); + c->Resume(); + return CR_FAILURE; + } + if (!protomap.SerializeToOstream(&output)) + { + c->con.printerr("Failed to save map file.\n"); + c->Resume(); + return CR_FAILURE; + } + c->con.print("Map succesfully exported.\n"); c->Resume(); return CR_OK; } diff --git a/plugins/mapexport/proto/Block.proto b/plugins/mapexport/proto/Block.proto index 7d39fdb37..7a73d33b1 100644 --- a/plugins/mapexport/proto/Block.proto +++ b/plugins/mapexport/proto/Block.proto @@ -1,5 +1,5 @@ package dfproto; -option optimize_for = LITE_RUNTIME; +//option optimize_for = LITE_RUNTIME; import "Tile.proto"; @@ -8,5 +8,5 @@ message Block required uint32 x = 1; required uint32 y = 2; required uint32 z = 3; - repeated Tile tiles = 4; + repeated Tile tile = 4; } diff --git a/plugins/mapexport/proto/Map.proto b/plugins/mapexport/proto/Map.proto index 59b7ad3bd..8801dafa4 100644 --- a/plugins/mapexport/proto/Map.proto +++ b/plugins/mapexport/proto/Map.proto @@ -1,5 +1,5 @@ package dfproto; -option optimize_for = LITE_RUNTIME; +//option optimize_for = LITE_RUNTIME; import "Block.proto"; @@ -8,5 +8,5 @@ message Map required uint32 x_size = 1; required uint32 y_size = 2; required uint32 z_size = 3; - repeated Block blocks = 4; + repeated Block block = 4; } diff --git a/plugins/mapexport/proto/Tile.proto b/plugins/mapexport/proto/Tile.proto index a5039bd27..ecf8c2e5e 100644 --- a/plugins/mapexport/proto/Tile.proto +++ b/plugins/mapexport/proto/Tile.proto @@ -1,10 +1,38 @@ package dfproto; -option optimize_for = LITE_RUNTIME; +//option optimize_for = LITE_RUNTIME; message Tile { required uint32 x = 1; required uint32 y = 2; - required uint32 tiletype = 3; + + enum TileType + { + EMPTY = 0; + WALL = 1; + PILLAR = 2; + BROOK_BED = 3; + FORTIFICATION = 4; + STAIR_UP = 5; + STAIR_DOWN = 6; + STAIR_UPDOWN = 7; + RAMP = 8; + RAMP_TOP = 9; + FLOOR = 10; + BROOK_TOP = 11; + RIVER_BED = 12; + POOL = 13; + TREE_DEAD = 14; + TREE_OK = 15; + SAPLING_DEAD = 16; + SAPLING_OK = 17; + SHRUB_DEAD = 18; + SHRUB_OK = 19; + BOULDER = 20; + PEBLLES = 21; + ENDLESS_PIT = 22; + } + required TileType type = 3; + optional uint32 material = 4; }