diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index ad630f566..e6e4a3123 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -3,6 +3,78 @@ package RemoteFortressReader; //Attempts to provide a complete framework for reading everything from a fortress needed for vizualization option optimize_for = LITE_RUNTIME; +//We use shapes, etc, because the actual tiletypes may differ between DF versions. +enum TiletypeShape { + NO_SHAPE = -1; + EMPTY = 0; + FLOOR = 1; + BOULDER = 2; + PEBBLES = 3; + WALL = 4; + FORTIFICATION = 5; + STAIR_UP = 6; + STAIR_DOWN = 7; + STAIR_UPDOWN = 8; + RAMP = 9; + RAMP_TOP = 10; + BROOK_BED = 11; + BROOK_TOP = 12; + TREE = 13; + SAPLING = 14; + SHRUB = 15; + ENDLESS_PIT = 16; +} + +enum TiletypeSpecial { + NO_SPECIAL = -1; + NORMAL = 0; + RIVER_SOURCE = 1; + WATERFALL = 2; + SMOOTH = 3; + FURROWED = 4; + WET = 5; + DEAD = 6; + WORN_1 = 7; + WORN_2 = 8; + WORN_3 = 9; + TRACK = 10; +}; +enum TiletypeMaterial { + NO_MATERIAL = -1; + AIR = 0; + SOIL = 1; + STONE = 2; + FEATURE = 3; + LAVA_STONE = 4; + MINERAL = 5; + FROZEN_LIQUID = 6; + CONSTRUCTION = 7; + GRASS_LIGHT = 8; + GRASS_DARK = 9; + GRASS_DRY = 10; + GRASS_DEAD = 11; + PLANT = 12; + HFS = 13; + CAMPFIRE = 14; + FIRE = 15; + ASHES = 16; + MAGMA = 17; + DRIFTWOOD = 18; + POOL = 19; + BROOK = 20; + RIVER = 21; +} + +message MapBlock +{ + required int32 map_x = 1; + required int32 map_y = 2; + required int32 map_z = 3; + repeated TiletypeShape tiletype_shapes = 4; + repeated TiletypeSpecial tiletype_specials = 5; + repeated TiletypeMaterial tiletype_materials = 6; +} + message MatPair { required int32 mat_type = 1; required int32 mat_index = 2; @@ -23,4 +95,22 @@ message MaterialDefinition{ message MaterialList{ repeated MaterialDefinition material_list = 1; +} + +message BlockRequest +{ + optional int32 blocks_needed = 1; + optional int32 min_x = 2; + optional int32 max_x = 3; + optional int32 min_y = 4; + optional int32 max_y = 5; + optional int32 min_z = 6; + optional int32 max_z = 7; +} + +message BlockList +{ + repeated MapBlock map_blocks = 1; + optional int32 map_x = 2; + optional int32 map_y = 3; } \ No newline at end of file diff --git a/plugins/remotefortressreader.cpp b/plugins/remotefortressreader.cpp index b44827c4f..be736eb80 100644 --- a/plugins/remotefortressreader.cpp +++ b/plugins/remotefortressreader.cpp @@ -35,11 +35,10 @@ #include "modules/Maps.h" #include "modules/MapCache.h" #include "modules/Materials.h" +#include "TileTypes.h" //Needed for writing the protobuff stuff to a file. -#include -#include -#include +#include #include "RemoteFortressReader.pb.h" @@ -48,13 +47,15 @@ using namespace DFHack; using namespace df::enums; using namespace RemoteFortressReader; - +using namespace std; // Here go all the command declarations... // mostly to allow having the mandatory stuff on top of the file and commands on the bottom static command_result GetMaterialList(color_ostream &stream, const EmptyMessage *in, MaterialList *out); - +static command_result GetBlockList(color_ostream &stream, const BlockRequest *in, BlockList *out); +void CopyBlock(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBlock); +void FindChangedBlocks(); @@ -82,6 +83,7 @@ DFhackCExport RPCService *plugin_rpcconnect(color_ostream &) { RPCService *svc = new RPCService(); svc->addFunction("GetMaterialList", GetMaterialList); + svc->addFunction("GetBlockList", GetBlockList); return svc; } @@ -94,6 +96,25 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out ) return CR_OK; } +uint16_t fletcher16(uint8_t const *data, size_t bytes) +{ + uint16_t sum1 = 0xff, sum2 = 0xff; + + while (bytes) { + size_t tlen = bytes > 20 ? 20 : bytes; + bytes -= tlen; + do { + sum2 += sum1 += *data++; + } while (--tlen); + sum1 = (sum1 & 0xff) + (sum1 >> 8); + sum2 = (sum2 & 0xff) + (sum2 >> 8); + } + /* Second reduction step to reduce sums to 8 bits */ + sum1 = (sum1 & 0xff) + (sum1 >> 8); + sum2 = (sum2 & 0xff) + (sum2 >> 8); + return sum2 << 8 | sum1; +} + df::matter_state GetState(df::material * mat, uint16_t temp = 10015) { df::matter_state state = matter_state::Solid; @@ -174,4 +195,40 @@ static command_result GetMaterialList(color_ostream &stream, const EmptyMessage } } return CR_OK; +} + +void CopyBlock(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBlock) +{ + NetBlock->set_map_x(DfBlock->map_pos.x); + NetBlock->set_map_y(DfBlock->map_pos.y); + NetBlock->set_map_z(DfBlock->map_pos.z); + for (int yy = 0; yy < 16; yy++) + { + for (int xx = 0; xx < 16; xx++) + { + df::tiletype tile = DfBlock->tiletype[xx][yy]; + NetBlock->add_tiletype_shapes((RemoteFortressReader::TiletypeShape)tileShape(tile)); + NetBlock->add_tiletype_materials((RemoteFortressReader::TiletypeMaterial)tileMaterial(tile)); + NetBlock->add_tiletype_specials((RemoteFortressReader::TiletypeSpecial)tileSpecial(tile)); + } + } +} + +static command_result GetBlockList(color_ostream &stream, const BlockRequest *in, BlockList *out) +{ + for (int zz = in->min_x(); zz < in->max_z(); zz++) + { + for (int yy = in->min_y(); yy < in->max_y(); yy++) + { + for (int xx = in->min_x(); xx < in->max_x(); xx++) + { + df::map_block * block = DFHack::Maps::getBlock(xx, yy, zz); + if (block == NULL) + continue; + RemoteFortressReader::MapBlock *net_block = out->add_map_blocks(); + CopyBlock(block, net_block); + } + } + } + return CR_OK; } \ No newline at end of file