Petr Mrázek 2012-02-05 04:28:53 +01:00
commit ebeae664d7
12 changed files with 259 additions and 86 deletions

@ -199,6 +199,7 @@ google/protobuf/compiler/zip_writer.cc
LIST(APPEND LIBPROTOBUF_FULL_SRCS ${LIBPROTOBUF_LITE_SRCS}) LIST(APPEND LIBPROTOBUF_FULL_SRCS ${LIBPROTOBUF_LITE_SRCS})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${dfhack_SOURCE_DIR}/library/depends/zlib)
ADD_LIBRARY(protobuf-lite ${LIBPROTOBUF_LITE_SRCS} ${LIBPROTOBUF_LITE_HDRS}) ADD_LIBRARY(protobuf-lite ${LIBPROTOBUF_LITE_SRCS} ${LIBPROTOBUF_LITE_HDRS})
ADD_LIBRARY(protobuf ${LIBPROTOBUF_FULL_SRCS} ${LIBPROTOBUF_FULL_HDRS}) ADD_LIBRARY(protobuf ${LIBPROTOBUF_FULL_SRCS} ${LIBPROTOBUF_FULL_HDRS})

@ -9,4 +9,4 @@
/* define if you want to use zlib. See readme.txt for additional /* define if you want to use zlib. See readme.txt for additional
* requirements. */ * requirements. */
// #define HAVE_ZLIB 1 #define HAVE_ZLIB 1

@ -1 +1 @@
Subproject commit 03b768f1158e675f2a4937ce857f2cd5acb58103 Subproject commit 64a7aeb6a87b7b5067ace8f6a869b7b4fe6561a4

@ -1 +1 @@
Subproject commit 23fbb78edaff35a62887803e178a24f9148ffc84 Subproject commit c114ec5f995aec69631187212254309464f82775

@ -1,8 +1,13 @@
PROJECT(mapexport) PROJECT(mapexport)
include_directories ( INCLUDE_DIRECTORIES (
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${dfhack_SOURCE_DIR}/library/depends/protobuf/ ${dfhack_SOURCE_DIR}/library/depends/protobuf/
${dfhack_SOURCE_DIR}/library/depends/zlib/
)
LINK_DIRECTORIES(
${dfhack_SOURCE_DIR}/library/depends/zlib/
) )
#The protobuf sources we generate will require these headers #The protobuf sources we generate will require these headers
@ -22,7 +27,9 @@ mapexport.cpp
SET(PROJECT_PROTOS SET(PROJECT_PROTOS
${CMAKE_CURRENT_SOURCE_DIR}/proto/Tile.proto ${CMAKE_CURRENT_SOURCE_DIR}/proto/Tile.proto
${CMAKE_CURRENT_SOURCE_DIR}/proto/Plant.proto
${CMAKE_CURRENT_SOURCE_DIR}/proto/Block.proto ${CMAKE_CURRENT_SOURCE_DIR}/proto/Block.proto
${CMAKE_CURRENT_SOURCE_DIR}/proto/Material.proto
${CMAKE_CURRENT_SOURCE_DIR}/proto/Map.proto ${CMAKE_CURRENT_SOURCE_DIR}/proto/Map.proto
) )
@ -43,4 +50,8 @@ COMMAND protoc-bin -I=${CMAKE_CURRENT_SOURCE_DIR}/proto/ --cpp_out=${CMAKE_CURRE
DEPENDS protoc-bin ${PROJECT_PROTOS} DEPENDS protoc-bin ${PROJECT_PROTOS}
) )
DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf) IF(WIN32)
DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf zlib)
ELSE()
DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf z)
ENDIF()

@ -6,13 +6,22 @@
using namespace DFHack; using namespace DFHack;
#include <fstream> #include <fstream>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/gzip_stream.h>
using namespace google::protobuf::io;
#include "DataDefs.h" #include "DataDefs.h"
#include "df/world.h" #include "df/world.h"
#include "modules/Constructions.h"
#include "proto/Map.pb.h" #include "proto/Map.pb.h"
#include "proto/Block.pb.h"
using namespace DFHack::Simple; using namespace DFHack;
using df::global::world;
typedef std::vector<df::plant *> PlantList;
DFhackCExport command_result mapexport (Core * c, std::vector <std::string> & parameters); DFhackCExport command_result mapexport (Core * c, std::vector <std::string> & parameters);
@ -37,25 +46,29 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
DFhackCExport command_result mapexport (Core * c, std::vector <std::string> & parameters) DFhackCExport command_result mapexport (Core * c, std::vector <std::string> & parameters)
{ {
bool showHidden = false;
int filenameParameter = 1;
for(size_t i = 0; i < parameters.size();i++) for(size_t i = 0; i < parameters.size();i++)
{ {
if(parameters[i] == "help" || parameters[i] == "?") if(parameters[i] == "help" || parameters[i] == "?")
{ {
c->con.print("Exports the currently visible map to a file.\n" c->con.print("Exports the currently visible map to a file.\n"
"Usage: mapexport <filename>\n" "Usage: mapexport [options] <filename>\n"
"Example: mapexport all embark.dfmap\n"
"Options:\n"
" all - Export the entire map, not just what's revealed."
); );
return CR_OK; return CR_OK;
} }
} if (parameters[i] == "all")
std::string filename;
if (parameters.size() < 1)
{ {
c->con.printerr("Please supply a filename.\n"); showHidden = true;
return CR_OK; filenameParameter++;
}
} }
filename = parameters[0];
bool showHidden = true;
uint32_t x_max=0, y_max=0, z_max=0; uint32_t x_max=0, y_max=0, z_max=0;
c->Suspend(); c->Suspend();
@ -65,29 +78,83 @@ DFhackCExport command_result mapexport (Core * c, std::vector <std::string> & pa
c->Resume(); c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
if (parameters.size() < filenameParameter)
{
c->con.printerr("Please supply a filename.\n");
c->Resume();
return CR_FAILURE;
}
std::string filename = parameters[filenameParameter-1];
if (filename.rfind(".dfmap") == std::string::npos) filename += ".dfmap";
c->con << "Writing to " << filename << "..." << std::endl;
std::ofstream output_file(filename, std::ios::out | std::ios::trunc | std::ios::binary);
if (!output_file.is_open())
{
c->con.printerr("Couldn't open the output file.\n");
c->Resume();
return CR_FAILURE;
}
ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&output_file);
GzipOutputStream *zip_output = new GzipOutputStream(raw_output);
CodedOutputStream *coded_output = new CodedOutputStream(zip_output);
coded_output->WriteLittleEndian32(0x50414DDF); //Write our file header
Maps::getSize(x_max, y_max, z_max); Maps::getSize(x_max, y_max, z_max);
MapExtras::MapCache map; MapExtras::MapCache map;
DFHack::Materials *mats = c->getMaterials(); DFHack::Materials *mats = c->getMaterials();
if (!Vegetation::isValid()) c->con << "Writing map info..." << std::endl;
{
c->con.printerr("Unable to read vegetation; plants won't be listed!\n" );
}
dfproto::Map protomap; dfproto::Map protomap;
protomap.set_x_size(x_max); protomap.set_x_size(x_max);
protomap.set_y_size(y_max); protomap.set_y_size(y_max);
protomap.set_z_size(z_max); protomap.set_z_size(z_max);
c->con << "Writing material dictionary..." << std::endl;
for (size_t i = 0; i < world->raws.inorganics.size(); i++)
{
dfproto::Material *protomaterial = protomap.add_inorganic_material();
protomaterial->set_type(i);
protomaterial->set_name(world->raws.inorganics[i]->id);
}
for (size_t i = 0; i < world->raws.plants.all.size(); i++)
{
dfproto::Material *protomaterial = protomap.add_organic_material();
protomaterial->set_type(i);
protomaterial->set_name(world->raws.plants.all[i]->id);
}
std::map<df::coord,std::pair<uint32_t,uint16_t> > constructionMaterials;
if (Constructions::isValid())
{
for (uint32_t i = 0; i < Constructions::getCount(); i++)
{
df::construction *construction = Constructions::getConstruction(i);
constructionMaterials[construction->pos] = std::make_pair(construction->mat_index, construction->mat_type);
}
}
coded_output->WriteVarint32(protomap.ByteSize());
protomap.SerializeToCodedStream(coded_output);
DFHack::t_feature blockFeatureGlobal; DFHack::t_feature blockFeatureGlobal;
DFHack::t_feature blockFeatureLocal; DFHack::t_feature blockFeatureLocal;
c->con.print("Writing map block information");
for(uint32_t z = 0; z < z_max; z++) 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_y = 0; b_y < y_max; b_y++)
{ {
for(uint32_t b_x = 0; b_x < x_max; b_x++) for(uint32_t b_x = 0; b_x < x_max; b_x++)
{ {
if (b_x == 0 && b_y == 0 && z % 10 == 0) c->con.print(".");
// Get the map block // Get the map block
df::coord2d blockCoord(b_x, b_y); df::coord2d blockCoord(b_x, b_y);
MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z));
@ -96,10 +163,10 @@ DFhackCExport command_result mapexport (Core * c, std::vector <std::string> & pa
continue; continue;
} }
dfproto::Block *protoblock = protomap.add_block(); dfproto::Block protoblock;
protoblock->set_x(b_x); protoblock.set_x(b_x);
protoblock->set_y(b_y); protoblock.set_y(b_y);
protoblock->set_z(z); protoblock.set_z(z);
{ // Find features { // Find features
uint32_t index = b->raw.global_feature; uint32_t index = b->raw.global_feature;
@ -128,52 +195,96 @@ DFhackCExport command_result mapexport (Core * c, std::vector <std::string> & pa
continue; continue;
} }
dfproto::Tile *prototile = protoblock->add_tile(); dfproto::Tile *prototile = protoblock.add_tile();
prototile->set_x(x); prototile->set_x(x);
prototile->set_y(y); prototile->set_y(y);
// Check for liquid // Check for liquid
if (des.bits.flow_size) if (des.bits.flow_size)
{ {
//if (des.bits.liquid_type == df::tile_liquid::Magma) prototile->set_liquid_type((dfproto::Tile::LiquidType)des.bits.liquid_type);
prototile->set_flow_size(des.bits.flow_size);
//else
} }
uint16_t type = b->TileTypeAt(coord); uint16_t type = b->TileTypeAt(coord);
const DFHack::TileRow *info = DFHack::getTileRow(type); const DFHack::TileRow *info = DFHack::getTileRow(type);
prototile->set_type((dfproto::Tile::TileType)info->shape); prototile->set_type((dfproto::Tile::TileType)info->shape);
/*switch (info->shape)
prototile->set_material_type((dfproto::Tile::MaterialType)info->material);
df::coord map_pos = df::coord(b_x*16+x,b_y*16+y,z);
switch (info->material)
{
case DFHack::SOIL:
case DFHack::STONE:
prototile->set_material_index(0);
prototile->set_material(b->baseMaterialAt(coord));
break;
case DFHack::VEIN:
prototile->set_material_index(0);
prototile->set_material(b->veinMaterialAt(coord));
break;
case DFHack::FEATSTONE:
if (blockFeatureLocal.type != -1 && des.bits.feature_local)
{ {
case DFHack::WALL: if (blockFeatureLocal.type == df::feature_type::deep_special_tube
prototile->set_type(dfproto::Tile::WALL); && blockFeatureLocal.main_material == 0) // stone
{
prototile->set_material_index(0);
prototile->set_material(blockFeatureLocal.sub_material);
}
if (blockFeatureGlobal.type != -1 && des.bits.feature_global
&& blockFeatureGlobal.type == df::feature_type::feature_underworld_from_layer
&& blockFeatureGlobal.main_material == 0) // stone
{
prototile->set_material_index(0);
prototile->set_material(blockFeatureGlobal.sub_material);
}
}
break; break;
default: case DFHack::CONSTRUCTED:
if (constructionMaterials.find(map_pos) != constructionMaterials.end())
{
prototile->set_material_index(constructionMaterials[map_pos].first);
prototile->set_material(constructionMaterials[map_pos].second);
}
break; break;
}*/
} }
} }
} // block x }
PlantList *plants;
if (Maps::ReadVegetation(b_x, b_y, z, plants))
{
for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++)
{
dfproto::Plant *protoplant = protoblock.add_plant();
const df::plant & plant = *(*it);
df::coord2d loc(plant.pos.x, plant.pos.y);
loc = loc % 16;
if (showHidden || !b->DesignationAt(loc).bits.hidden)
{
protoplant->set_is_shrub(plant.flags.bits.is_shrub);
protoplant->set_material(plant.material);
}
}
}
coded_output->WriteVarint32(protoblock.ByteSize());
protoblock.SerializeToCodedStream(coded_output);
} // block x
// Clean uneeded memory // Clean uneeded memory
map.trash(); map.trash();
} // block y } // block y
} // z } // z
std::ofstream output(filename, std::ios::out | std::ios::trunc | std::ios::binary); delete coded_output;
if (!output.is_open()) delete zip_output;
{ delete raw_output;
c->con.printerr("Couldn't open the output file.\n");
c->Resume(); mats->Finish();
return CR_FAILURE; c->con.print("\nMap succesfully exported!\n");
}
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(); c->Resume();
return CR_OK; return CR_OK;
} }

@ -1,7 +1,8 @@
package dfproto; package dfproto;
//option optimize_for = LITE_RUNTIME; option optimize_for = LITE_RUNTIME;
import "Tile.proto"; import "Tile.proto";
import "Plant.proto";
message Block message Block
{ {
@ -9,4 +10,5 @@ message Block
required uint32 y = 2; required uint32 y = 2;
required uint32 z = 3; required uint32 z = 3;
repeated Tile tile = 4; repeated Tile tile = 4;
repeated Plant plant = 5;
} }

@ -1,12 +1,13 @@
package dfproto; package dfproto;
//option optimize_for = LITE_RUNTIME; option optimize_for = LITE_RUNTIME;
import "Block.proto"; import "Material.proto";
message Map message Map
{ {
required uint32 x_size = 1; required uint32 x_size = 1;
required uint32 y_size = 2; required uint32 y_size = 2;
required uint32 z_size = 3; required uint32 z_size = 3;
repeated Block block = 4; repeated Material inorganic_material = 4;
repeated Material organic_material = 5;
} }

@ -0,0 +1,8 @@
package dfproto;
option optimize_for = LITE_RUNTIME;
message Material
{
required uint32 type = 1;
required string name = 2;
}

@ -0,0 +1,10 @@
package dfproto;
option optimize_for = LITE_RUNTIME;
message Plant
{
required uint32 x = 1;
required uint32 y = 2;
required bool is_shrub = 3;
optional uint32 material = 4;
}

@ -1,11 +1,8 @@
package dfproto; package dfproto;
//option optimize_for = LITE_RUNTIME; option optimize_for = LITE_RUNTIME;
message Tile message Tile
{ {
required uint32 x = 1;
required uint32 y = 2;
enum TileType enum TileType
{ {
EMPTY = 0; EMPTY = 0;
@ -32,7 +29,39 @@ message Tile
PEBLLES = 21; PEBLLES = 21;
ENDLESS_PIT = 22; ENDLESS_PIT = 22;
} }
enum LiquidType
{
WATER = 0;
MAGMA = 1;
}
enum MaterialType
{
AIR = 0;
SOIL = 1;
STONE = 2;
FEATSTONE = 3;
OBSIDIAN = 4;
VEIN = 5;
ICE = 6;
GRASS = 7;
GRASS2 = 8;
GRASS_DEAD = 9;
GRASS_DRY = 10;
DRIFTWOOD = 11;
HFS = 12;
MAGMA_TYPE = 13;
CAMPFIRE = 14;
FIRE = 15;
ASHES = 16;
CONSTRUCTED = 17;
CYAN_GLOW = 18;
}
required uint32 x = 1;
required uint32 y = 2;
required TileType type = 3; required TileType type = 3;
optional MaterialType material_type = 4;
optional uint32 material = 4; optional uint32 material_index = 5;
optional uint32 material = 6;
optional LiquidType liquid_type = 7;
optional uint32 flow_size = 8;
} }

@ -1 +1 @@
Subproject commit f824e83b5c4f4dfc1bbe60681d8dc6ed88f3f4f9 Subproject commit 92627e39cb3502812cd5a131716d3d1da8ef625a