diff --git a/library/include/Types.h b/library/include/Types.h index 5412b443b..6b175d180 100644 --- a/library/include/Types.h +++ b/library/include/Types.h @@ -38,6 +38,19 @@ namespace DFHack { int16_t type; int32_t index; + bool operator<(const t_matglossPair &b) const + { + if (type != b.type) return (type < b.type); + return (index < b.index); + } + bool operator==(const t_matglossPair &b) const + { + return (type == b.type) && (index == b.index); + } + bool operator!=(const t_matglossPair &b) const + { + return (type != b.type) || (index != b.index); + } }; template diff --git a/library/modules/MapCache.cpp b/library/modules/MapCache.cpp index 4d77ccb35..5fc48789f 100644 --- a/library/modules/MapCache.cpp +++ b/library/modules/MapCache.cpp @@ -728,9 +728,9 @@ void MapExtras::BlockInfo::prepare(Block *mblock) block = mblock->getRaw(); parent = mblock->getParent(); - column = Maps::getBlockColumn((block->map_pos.x/48)*3, (block->map_pos.y/48)*3); + column = Maps::getBlockColumn((block->map_pos.x / 48) * 3, (block->map_pos.y / 48) * 3); - SquashVeins(block,veinmats,veintype); + SquashVeins(block, veinmats, veintype); SquashGrass(block, grass); for (size_t i = 0; i < column->plants.size(); i++) @@ -738,41 +738,41 @@ void MapExtras::BlockInfo::prepare(Block *mblock) auto pp = column->plants[i]; // A plant without tree_info is single tile // TODO: verify that x any y lie inside the block. - if(!pp->tree_info) + if (!pp->tree_info) { - if(pp->pos.z == block->map_pos.z) + if (pp->pos.z == block->map_pos.z) plants[pp->pos] = pp; continue; } // tree_info contains vertical slices of the tree. This ensures there's a slice for our Z-level. df::plant_tree_info * info = pp->tree_info; - if(!((pp->pos.z-1 <= block->map_pos.z) && ((pp->pos.z+info->body_height) > block->map_pos.z))) + if (!((pp->pos.z - info->roots_depth <= block->map_pos.z) && ((pp->pos.z + info->body_height) > block->map_pos.z))) continue; // Parse through a single horizontal slice of the tree. - for(int xx = 0; xx < info->dim_x;xx++) - for(int yy = 0; yy < info->dim_y;yy++) + for (int xx = 0; xx < info->dim_x; xx++) + for (int yy = 0; yy < info->dim_y; yy++) + { + // Any non-zero value here other than blocked means there's some sort of branch here. + // If the block is at or above the plant's base level, we use the body array + // otherwise we use the roots. + // TODO: verify that the tree bounds intersect the block. + df::plant_tree_tile tile; + int z_diff = block->map_pos.z - pp->pos.z; + if (z_diff >= 0) + tile = info->body[z_diff][xx + (yy*info->dim_x)]; + else + tile = info->roots[-1 - z_diff][xx + (yy*info->dim_x)]; + if (tile.whole && !(tile.bits.blocked)) { - // Any non-zero value here other than blocked means there's some sort of branch here. - // If the block is at or above the plant's base level, we use the body array - // otherwise we use the roots. - // TODO: verify that the tree bounds intersect the block. - df::plant_tree_tile tile; - int z_diff = block->map_pos.z-pp->pos.z; - if ((z_diff >= 0) && (z_diff < info->body_height)) - tile = info->body[z_diff][xx+(yy*info->dim_x)]; - else if ((z_diff < 0) && (z_diff >= -info->roots_depth)) - tile = info->roots[0][xx+(yy*info->dim_x)]; - if(tile.whole && !(tile.bits.blocked)) - { - df::coord pos=pp->pos; - pos.x = pos.x - (info->dim_x/2) + xx; - pos.y = pos.y - (info->dim_y/2) + yy; - pos.z = block->map_pos.z; - plants[pos] = pp; - } + df::coord pos = pp->pos; + pos.x = pos.x - (info->dim_x / 2) + xx; + pos.y = pos.y - (info->dim_y / 2) + yy; + pos.z = block->map_pos.z; + plants[pos] = pp; } + } } global_feature = Maps::getGlobalInitFeature(block->global_feature); @@ -843,6 +843,7 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos rv.mat_index = mblock->biomeInfoAt(pos).lava_stone; break; + case MUSHROOM: case ROOT: case TREE: case PLANT: diff --git a/plugins/isoworld b/plugins/isoworld index aa3b1bd51..cc9d48d02 160000 --- a/plugins/isoworld +++ b/plugins/isoworld @@ -1 +1 @@ -Subproject commit aa3b1bd51f269c07b3235392fd7ed21fe9171f3f +Subproject commit cc9d48d02b3f1b6e70b8d5687915c7b770d965cc diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index e6e4a3123..e65345b3e 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -4,7 +4,8 @@ package RemoteFortressReader; option optimize_for = LITE_RUNTIME; //We use shapes, etc, because the actual tiletypes may differ between DF versions. -enum TiletypeShape { +enum TiletypeShape +{ NO_SHAPE = -1; EMPTY = 0; FLOOR = 1; @@ -19,13 +20,17 @@ enum TiletypeShape { RAMP_TOP = 10; BROOK_BED = 11; BROOK_TOP = 12; - TREE = 13; + TREE_SHAPE = 13; SAPLING = 14; SHRUB = 15; ENDLESS_PIT = 16; + BRANCH = 17; + TRUNK_BRANCH = 18; + TWIG = 19; } -enum TiletypeSpecial { +enum TiletypeSpecial +{ NO_SPECIAL = -1; NORMAL = 0; RIVER_SOURCE = 1; @@ -38,8 +43,10 @@ enum TiletypeSpecial { WORN_2 = 8; WORN_3 = 9; TRACK = 10; + SMOOTH_DEAD = 11; }; -enum TiletypeMaterial { +enum TiletypeMaterial +{ NO_MATERIAL = -1; AIR = 0; SOIL = 1; @@ -63,6 +70,35 @@ enum TiletypeMaterial { POOL = 19; BROOK = 20; RIVER = 21; + ROOT = 22; + TREE_MATERIAL = 23; + MUSHROOM = 24; + UNDERWORLD_GATE = 25; +} +enum TiletypeVariant +{ + NO_VARIANT = -1; + VAR_1 = 0; + VAR_2 = 1; + VAR_3 = 2; + VAR_4 = 3; +}; + +message Tiletype +{ + required int32 id = 1; + optional string name = 2; + optional string caption = 3; + optional TiletypeShape shape = 4; + optional TiletypeSpecial special = 5; + optional TiletypeMaterial material = 6; + optional TiletypeVariant variant = 7; + optional uint32 direction = 8; +}; + +message TiletypeList +{ + repeated Tiletype tiletype_list = 1; } message MapBlock @@ -70,9 +106,8 @@ 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; + repeated int32 tiles = 4; + repeated MatPair materials = 5; } message MatPair { @@ -113,4 +148,17 @@ message BlockList repeated MapBlock map_blocks = 1; optional int32 map_x = 2; optional int32 map_y = 3; +} + +message PlantDef +{ + required int32 pos_x = 1; + required int32 pos_y = 2; + required int32 pos_z = 3; + required int32 index = 4; +} + +message PlantList +{ + repeated PlantDef plant_list = 1; } \ No newline at end of file diff --git a/plugins/remotefortressreader.cpp b/plugins/remotefortressreader.cpp index 6254a9ad8..538eb9696 100644 --- a/plugins/remotefortressreader.cpp +++ b/plugins/remotefortressreader.cpp @@ -1,4 +1,7 @@ -// This is a generic plugin that does nothing useful apart from acting as an example... of a plugin that does nothing :D + +//define which version of DF this is being built for. +#define DF_VER_040 +//#define DF_VER_034 // some headers required for a plugin. Nothing special, just the basics. #include "Core.h" @@ -22,6 +25,10 @@ #include "df/matter_state.h" #include "df/material_vec_ref.h" #include "df/builtin_mats.h" +#include "df/map_block_column.h" +#include "df/plant.h" +#include "df/plant_tree_info.h" +#include "df/plant_growth.h" #include "df/descriptor_color.h" #include "df/descriptor_pattern.h" @@ -49,15 +56,16 @@ using namespace df::enums; using namespace RemoteFortressReader; using namespace std; -using df::global::world; - // 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 GetGrowthList(color_ostream &stream, const EmptyMessage *in, MaterialList *out); static command_result GetMaterialList(color_ostream &stream, const EmptyMessage *in, MaterialList *out); +static command_result GetTiletypeList(color_ostream &stream, const EmptyMessage *in, TiletypeList *out); static command_result GetBlockList(color_ostream &stream, const BlockRequest *in, BlockList *out); +static command_result GetPlantList(color_ostream &stream, const BlockRequest *in, PlantList *out); static command_result CheckHashes(color_ostream &stream, const EmptyMessage *in); -void CopyBlock(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBlock); +void CopyBlock(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBlock, MapExtras::MapCache * MC); void FindChangedBlocks(); @@ -67,7 +75,7 @@ void FindChangedBlocks(); DFHACK_PLUGIN("RemoteFortressReader"); // Mandatory init function. If you have some global state, create it here. -DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) +DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) { //// Fill the command list with your commands. //commands.push_back(PluginCommand( @@ -85,14 +93,17 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector addFunction("GetMaterialList", GetMaterialList); - svc->addFunction("GetBlockList", GetBlockList); - svc->addFunction("CheckHashes", CheckHashes); + svc->addFunction("GetMaterialList", GetMaterialList); + svc->addFunction("GetGrowthList", GetGrowthList); + svc->addFunction("GetBlockList", GetBlockList); + svc->addFunction("CheckHashes", CheckHashes); + svc->addFunction("GetTiletypeList", GetTiletypeList); + svc->addFunction("GetPlantList", GetPlantList); return svc; } // This is called right before the plugin library is removed from memory. -DFhackCExport command_result plugin_shutdown ( color_ostream &out ) +DFhackCExport command_result plugin_shutdown(color_ostream &out) { // You *MUST* kill all threads you created before this returns. // If everything fails, just return CR_FAILURE. Your plugin will be @@ -102,152 +113,523 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out ) uint16_t fletcher16(uint8_t const *data, size_t bytes) { - uint16_t sum1 = 0xff, sum2 = 0xff; + 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; +} + +RemoteFortressReader::TiletypeMaterial TranslateMaterial(df::tiletype_material material) +{ + switch (material) + { + case df::enums::tiletype_material::NONE: + return RemoteFortressReader::NO_MATERIAL; + break; + case df::enums::tiletype_material::AIR: + return RemoteFortressReader::AIR; + break; + case df::enums::tiletype_material::SOIL: + return RemoteFortressReader::SOIL; + break; + case df::enums::tiletype_material::STONE: + return RemoteFortressReader::STONE; + break; + case df::enums::tiletype_material::FEATURE: + return RemoteFortressReader::FEATURE; + break; + case df::enums::tiletype_material::LAVA_STONE: + return RemoteFortressReader::LAVA_STONE; + break; + case df::enums::tiletype_material::MINERAL: + return RemoteFortressReader::MINERAL; + break; + case df::enums::tiletype_material::FROZEN_LIQUID: + return RemoteFortressReader::FROZEN_LIQUID; + break; + case df::enums::tiletype_material::CONSTRUCTION: + return RemoteFortressReader::CONSTRUCTION; + break; + case df::enums::tiletype_material::GRASS_LIGHT: + return RemoteFortressReader::GRASS_LIGHT; + break; + case df::enums::tiletype_material::GRASS_DARK: + return RemoteFortressReader::GRASS_DARK; + break; + case df::enums::tiletype_material::GRASS_DRY: + return RemoteFortressReader::GRASS_DRY; + break; + case df::enums::tiletype_material::GRASS_DEAD: + return RemoteFortressReader::GRASS_DEAD; + break; + case df::enums::tiletype_material::PLANT: + return RemoteFortressReader::PLANT; + break; + case df::enums::tiletype_material::HFS: + return RemoteFortressReader::HFS; + break; + case df::enums::tiletype_material::CAMPFIRE: + return RemoteFortressReader::CAMPFIRE; + break; + case df::enums::tiletype_material::FIRE: + return RemoteFortressReader::FIRE; + break; + case df::enums::tiletype_material::ASHES: + return RemoteFortressReader::ASHES; + break; + case df::enums::tiletype_material::MAGMA: + return RemoteFortressReader::MAGMA; + break; + case df::enums::tiletype_material::DRIFTWOOD: + return RemoteFortressReader::DRIFTWOOD; + break; + case df::enums::tiletype_material::POOL: + return RemoteFortressReader::POOL; + break; + case df::enums::tiletype_material::BROOK: + return RemoteFortressReader::BROOK; + break; + case df::enums::tiletype_material::RIVER: + return RemoteFortressReader::RIVER; + break; + case df::enums::tiletype_material::ROOT: + return RemoteFortressReader::ROOT; + break; + case df::enums::tiletype_material::TREE: + return RemoteFortressReader::TREE_MATERIAL; + break; + case df::enums::tiletype_material::MUSHROOM: + return RemoteFortressReader::MUSHROOM; + break; + case df::enums::tiletype_material::UNDERWORLD_GATE: + return RemoteFortressReader::UNDERWORLD_GATE; + break; + default: + return RemoteFortressReader::NO_MATERIAL; + break; + } + return RemoteFortressReader::NO_MATERIAL; +} + +RemoteFortressReader::TiletypeSpecial TranslateSpecial(df::tiletype_special special) +{ + switch (special) + { + case df::enums::tiletype_special::NONE: + return RemoteFortressReader::NO_SPECIAL; + break; + case df::enums::tiletype_special::NORMAL: + return RemoteFortressReader::NORMAL; + break; + case df::enums::tiletype_special::RIVER_SOURCE: + return RemoteFortressReader::RIVER_SOURCE; + break; + case df::enums::tiletype_special::WATERFALL: + return RemoteFortressReader::WATERFALL; + break; + case df::enums::tiletype_special::SMOOTH: + return RemoteFortressReader::SMOOTH; + break; + case df::enums::tiletype_special::FURROWED: + return RemoteFortressReader::FURROWED; + break; + case df::enums::tiletype_special::WET: + return RemoteFortressReader::WET; + break; + case df::enums::tiletype_special::DEAD: + return RemoteFortressReader::DEAD; + break; + case df::enums::tiletype_special::WORN_1: + return RemoteFortressReader::WORN_1; + break; + case df::enums::tiletype_special::WORN_2: + return RemoteFortressReader::WORN_2; + break; + case df::enums::tiletype_special::WORN_3: + return RemoteFortressReader::WORN_3; + break; + case df::enums::tiletype_special::TRACK: + return RemoteFortressReader::TRACK; + break; + case df::enums::tiletype_special::SMOOTH_DEAD: + return RemoteFortressReader::SMOOTH_DEAD; + break; + default: + return RemoteFortressReader::NO_SPECIAL; + break; + } + return RemoteFortressReader::NO_SPECIAL; +} + +RemoteFortressReader::TiletypeShape TranslateShape(df::tiletype_shape shape) +{ + switch (shape) + { + case df::enums::tiletype_shape::NONE: + return RemoteFortressReader::NO_SHAPE; + break; + case df::enums::tiletype_shape::EMPTY: + return RemoteFortressReader::EMPTY; + break; + case df::enums::tiletype_shape::FLOOR: + return RemoteFortressReader::FLOOR; + break; + case df::enums::tiletype_shape::BOULDER: + return RemoteFortressReader::BOULDER; + break; + case df::enums::tiletype_shape::PEBBLES: + return RemoteFortressReader::PEBBLES; + break; + case df::enums::tiletype_shape::WALL: + return RemoteFortressReader::WALL; + break; + case df::enums::tiletype_shape::FORTIFICATION: + return RemoteFortressReader::FORTIFICATION; + break; + case df::enums::tiletype_shape::STAIR_UP: + return RemoteFortressReader::STAIR_UP; + break; + case df::enums::tiletype_shape::STAIR_DOWN: + return RemoteFortressReader::STAIR_DOWN; + break; + case df::enums::tiletype_shape::STAIR_UPDOWN: + return RemoteFortressReader::STAIR_UPDOWN; + break; + case df::enums::tiletype_shape::RAMP: + return RemoteFortressReader::RAMP; + break; + case df::enums::tiletype_shape::RAMP_TOP: + return RemoteFortressReader::RAMP_TOP; + break; + case df::enums::tiletype_shape::BROOK_BED: + return RemoteFortressReader::BROOK_BED; + break; + case df::enums::tiletype_shape::BROOK_TOP: + return RemoteFortressReader::BROOK_TOP; + break; + case df::enums::tiletype_shape::BRANCH: + return RemoteFortressReader::BRANCH; + break; +#ifdef DF_VER_034 + case df::enums::tiletype_shape::TREE: + return RemoteFortressReader::TREE; + break; +#endif + case df::enums::tiletype_shape::TRUNK_BRANCH: + return RemoteFortressReader::TRUNK_BRANCH; + break; + case df::enums::tiletype_shape::TWIG: + return RemoteFortressReader::TWIG; + break; + case df::enums::tiletype_shape::SAPLING: + return RemoteFortressReader::SAPLING; + break; + case df::enums::tiletype_shape::SHRUB: + return RemoteFortressReader::SHRUB; + break; + case df::enums::tiletype_shape::ENDLESS_PIT: + return RemoteFortressReader::EMPTY; + break; + default: + return RemoteFortressReader::NO_SHAPE; + break; + } + return RemoteFortressReader::NO_SHAPE; +} - 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; +RemoteFortressReader::TiletypeVariant TranslateVariant(df::tiletype_variant variant) +{ + switch (variant) + { + case df::enums::tiletype_variant::NONE: + return RemoteFortressReader::NO_VARIANT; + break; + case df::enums::tiletype_variant::VAR_1: + return RemoteFortressReader::VAR_1; + break; + case df::enums::tiletype_variant::VAR_2: + return RemoteFortressReader::VAR_2; + break; + case df::enums::tiletype_variant::VAR_3: + return RemoteFortressReader::VAR_3; + break; + case df::enums::tiletype_variant::VAR_4: + return RemoteFortressReader::VAR_4; + break; + default: + return RemoteFortressReader::NO_VARIANT; + break; + } + return RemoteFortressReader::NO_VARIANT; } static command_result CheckHashes(color_ostream &stream, const EmptyMessage *in) { - clock_t start = clock(); - for (int i = 0; i < world->map.map_blocks.size(); i++) - { - df::map_block * block = world->map.map_blocks[i]; - fletcher16((uint8_t*)(block->tiletype), 16 * 16 * sizeof(df::enums::tiletype::tiletype)); - } - clock_t end = clock(); - double elapsed_secs = double(end - start) / CLOCKS_PER_SEC; - stream.print("Checking all hashes took %f seconds.", elapsed_secs); - return CR_OK; + clock_t start = clock(); + for (int i = 0; i < df::global::world->map.map_blocks.size(); i++) + { + df::map_block * block = df::global::world->map.map_blocks[i]; + fletcher16((uint8_t*)(block->tiletype), 16 * 16 * sizeof(df::enums::tiletype::tiletype)); + } + clock_t end = clock(); + double elapsed_secs = double(end - start) / CLOCKS_PER_SEC; + stream.print("Checking all hashes took %f seconds.", elapsed_secs); + return CR_OK; } df::matter_state GetState(df::material * mat, uint16_t temp = 10015) { - df::matter_state state = matter_state::Solid; - if (temp >= mat->heat.melting_point) - state = df::matter_state::Liquid; - if (temp >= mat->heat.boiling_point) - state = matter_state::Gas; - return state; + df::matter_state state = matter_state::Solid; + if (temp >= mat->heat.melting_point) + state = df::matter_state::Liquid; + if (temp >= mat->heat.boiling_point) + state = matter_state::Gas; + return state; } static command_result GetMaterialList(color_ostream &stream, const EmptyMessage *in, MaterialList *out) { - if (!Core::getInstance().isWorldLoaded()) { - //out->set_available(false); - return CR_OK; - } - - - - df::world_raws *raws = &world->raws; - MaterialInfo mat; - for (int i = 0; i < raws->inorganics.size(); i++) - { - mat.decode(0, i); - MaterialDefinition *mat_def = out->add_material_list(); - mat_def->mutable_mat_pair()->set_mat_index(0); - mat_def->mutable_mat_pair()->set_mat_type(i); - mat_def->set_id(mat.getToken()); - mat_def->set_name(mat.toString()); //find the name at cave temperature; - if (raws->inorganics[i]->material.state_color[GetState(&raws->inorganics[i]->material)] < raws->language.colors.size()) - { - df::descriptor_color *color = raws->language.colors[raws->inorganics[i]->material.state_color[GetState(&raws->inorganics[i]->material)]]; - mat_def->mutable_state_color()->set_red(color->red); - mat_def->mutable_state_color()->set_green(color->green); - mat_def->mutable_state_color()->set_blue(color->blue); - } - } - for (int i = 1; i < 19; i++) - { - int k = 0; - if (i == 7) - k = 1;// for coal. - for (int j = 0; j <= k; j++) - { - mat.decode(i, j); - MaterialDefinition *mat_def = out->add_material_list(); - mat_def->mutable_mat_pair()->set_mat_index(i); - mat_def->mutable_mat_pair()->set_mat_type(j); - mat_def->set_id(mat.getToken()); - mat_def->set_name(mat.toString()); //find the name at cave temperature; - if (raws->mat_table.builtin[i]->state_color[GetState(raws->mat_table.builtin[i])] < raws->language.colors.size()) - { - df::descriptor_color *color = raws->language.colors[raws->mat_table.builtin[i]->state_color[GetState(raws->mat_table.builtin[i])]]; - mat_def->mutable_state_color()->set_red(color->red); - mat_def->mutable_state_color()->set_green(color->green); - mat_def->mutable_state_color()->set_blue(color->blue); - } - } - } - for (int i = 0; i < raws->creatures.all.size(); i++) - { - df::creature_raw * creature = raws->creatures.all[i]; - for (int j = 0; j < creature->material.size(); j++) - { - mat.decode(j + 19, i); - MaterialDefinition *mat_def = out->add_material_list(); - mat_def->mutable_mat_pair()->set_mat_index(j+19); - mat_def->mutable_mat_pair()->set_mat_type(i); - mat_def->set_id(mat.getToken()); - mat_def->set_name(mat.toString()); //find the name at cave temperature; - if (creature->material[j]->state_color[GetState(creature->material[j])] < raws->language.colors.size()) - { - df::descriptor_color *color = raws->language.colors[creature->material[j]->state_color[GetState(creature->material[j])]]; - mat_def->mutable_state_color()->set_red(color->red); - mat_def->mutable_state_color()->set_green(color->green); - mat_def->mutable_state_color()->set_blue(color->blue); - } - } - } - 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)); - } - } + if (!Core::getInstance().isWorldLoaded()) { + //out->set_available(false); + return CR_OK; + } + + + + df::world_raws *raws = &df::global::world->raws; + MaterialInfo mat; + for (int i = 0; i < raws->inorganics.size(); i++) + { + mat.decode(0, i); + MaterialDefinition *mat_def = out->add_material_list(); + mat_def->mutable_mat_pair()->set_mat_type(0); + mat_def->mutable_mat_pair()->set_mat_index(i); + mat_def->set_id(mat.getToken()); + mat_def->set_name(mat.toString()); //find the name at cave temperature; + if (raws->inorganics[i]->material.state_color[GetState(&raws->inorganics[i]->material)] < raws->language.colors.size()) + { + df::descriptor_color *color = raws->language.colors[raws->inorganics[i]->material.state_color[GetState(&raws->inorganics[i]->material)]]; + mat_def->mutable_state_color()->set_red(color->red * 255); + mat_def->mutable_state_color()->set_green(color->green * 255); + mat_def->mutable_state_color()->set_blue(color->blue * 255); + } + } + for (int i = 1; i < 19; i++) + { + int k = 0; + if (i == 7) + k = 1;// for coal. + for (int j = 0; j <= k; j++) + { + mat.decode(i, j); + MaterialDefinition *mat_def = out->add_material_list(); + mat_def->mutable_mat_pair()->set_mat_type(i); + mat_def->mutable_mat_pair()->set_mat_index(j); + mat_def->set_id(mat.getToken()); + mat_def->set_name(mat.toString()); //find the name at cave temperature; + if (raws->mat_table.builtin[i]->state_color[GetState(raws->mat_table.builtin[i])] < raws->language.colors.size()) + { + df::descriptor_color *color = raws->language.colors[raws->mat_table.builtin[i]->state_color[GetState(raws->mat_table.builtin[i])]]; + mat_def->mutable_state_color()->set_red(color->red * 255); + mat_def->mutable_state_color()->set_green(color->green * 255); + mat_def->mutable_state_color()->set_blue(color->blue * 255); + } + } + } + for (int i = 0; i < raws->creatures.all.size(); i++) + { + df::creature_raw * creature = raws->creatures.all[i]; + for (int j = 0; j < creature->material.size(); j++) + { + mat.decode(j + 19, i); + MaterialDefinition *mat_def = out->add_material_list(); + mat_def->mutable_mat_pair()->set_mat_type(j + 19); + mat_def->mutable_mat_pair()->set_mat_index(i); + mat_def->set_id(mat.getToken()); + mat_def->set_name(mat.toString()); //find the name at cave temperature; + if (creature->material[j]->state_color[GetState(creature->material[j])] < raws->language.colors.size()) + { + df::descriptor_color *color = raws->language.colors[creature->material[j]->state_color[GetState(creature->material[j])]]; + mat_def->mutable_state_color()->set_red(color->red * 255); + mat_def->mutable_state_color()->set_green(color->green * 255); + mat_def->mutable_state_color()->set_blue(color->blue * 255); + } + } + } + for (int i = 0; i < raws->plants.all.size(); i++) + { + df::plant_raw * plant = raws->plants.all[i]; + for (int j = 0; j < plant->material.size(); j++) + { + mat.decode(j + 419, i); + MaterialDefinition *mat_def = out->add_material_list(); + mat_def->mutable_mat_pair()->set_mat_type(j + 419); + mat_def->mutable_mat_pair()->set_mat_index(i); + mat_def->set_id(mat.getToken()); + mat_def->set_name(mat.toString()); //find the name at cave temperature; + if (plant->material[j]->state_color[GetState(plant->material[j])] < raws->language.colors.size()) + { + df::descriptor_color *color = raws->language.colors[plant->material[j]->state_color[GetState(plant->material[j])]]; + mat_def->mutable_state_color()->set_red(color->red * 255); + mat_def->mutable_state_color()->set_green(color->green * 255); + mat_def->mutable_state_color()->set_blue(color->blue * 255); + } + } + } + return CR_OK; +} + +static command_result GetGrowthList(color_ostream &stream, const EmptyMessage *in, MaterialList *out) +{ + if (!Core::getInstance().isWorldLoaded()) { + //out->set_available(false); + return CR_OK; + } + + + + df::world_raws *raws = &df::global::world->raws; + for (int i = 0; i < raws->plants.all.size(); i++) + { + df::plant_raw * pp = raws->plants.all[i]; + if (!pp) + continue; + MaterialDefinition * basePlant = out->add_material_list(); + basePlant->set_id(pp->id + ":BASE"); + basePlant->set_name(pp->name); + basePlant->mutable_mat_pair()->set_mat_type(-1); + basePlant->mutable_mat_pair()->set_mat_index(i); + for (int g = 0; g < pp->growths.size(); g++) + { + df::plant_growth* growth = pp->growths[g]; + if (!growth) + continue; + MaterialDefinition * out_growth = out->add_material_list(); + out_growth->set_id(pp->id + ":" + growth->id); + out_growth->set_name(growth->name); + out_growth->mutable_mat_pair()->set_mat_type(g); + out_growth->mutable_mat_pair()->set_mat_index(i); + } + } + return CR_OK; +} + +void CopyBlock(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBlock, MapExtras::MapCache * MC) +{ + NetBlock->set_map_x(DfBlock->map_pos.x); + NetBlock->set_map_y(DfBlock->map_pos.y); + NetBlock->set_map_z(DfBlock->map_pos.z); + + MapExtras::Block * block = MC->BlockAtTile(DfBlock->map_pos); + for (int yy = 0; yy < 16; yy++) + { + for (int xx = 0; xx < 16; xx++) + { + df::tiletype tile = DfBlock->tiletype[xx][yy]; + NetBlock->add_tiles(tile); + RemoteFortressReader::MatPair * material = NetBlock->add_materials(); + material->set_mat_type(block->baseMaterialAt(df::coord2d(xx, yy)).mat_index); + material->set_mat_index(block->baseMaterialAt(df::coord2d(xx, yy)).mat_type); + } + } } static command_result GetBlockList(color_ostream &stream, const BlockRequest *in, BlockList *out) { - //stream.print("Got request for blocks from (%d, %d, %d) to (%d, %d, %d).\n", in->min_x(), in->min_y(), in->min_z(), in->max_x(), in->max_y(), in->max_z()); - for (int zz = in->min_z(); 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; + MapExtras::MapCache MC; + //stream.print("Got request for blocks from (%d, %d, %d) to (%d, %d, %d).\n", in->min_x(), in->min_y(), in->min_z(), in->max_x(), in->max_y(), in->max_z()); + for (int zz = in->min_z(); 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,&MC); + } + } + } + MC.trash(); + return CR_OK; +} + +static command_result GetTiletypeList(color_ostream &stream, const EmptyMessage *in, TiletypeList *out) +{ + int count = 0; + FOR_ENUM_ITEMS(tiletype, tt) + { + Tiletype * type = out->add_tiletype_list(); + type->set_id(tt); + type->set_name(ENUM_KEY_STR(tiletype, tt)); + const char * name = tileName(tt); + if (name != NULL && name[0] != 0) + type->set_caption(name); + type->set_shape(TranslateShape(tileShape(tt))); + type->set_special(TranslateSpecial(tileSpecial(tt))); + type->set_material(TranslateMaterial(tileMaterial(tt))); + type->set_variant(TranslateVariant(tileVariant(tt))); + type->set_direction(tileDirection(tt).whole); + count++; + } + return CR_OK; +} + +static command_result GetPlantList(color_ostream &stream, const BlockRequest *in, PlantList *out) +{ + int min_x = in->min_x() / 3; + int min_y = in->min_y() / 3; + int min_z = in->min_z(); + int max_x = in->max_x() / 3; + int max_y = in->max_y() / 3; + int max_z = in->max_z(); + + for (int xx = min_x; xx < max_x; xx++) + for (int yy = min_y; yy < max_y; yy++) + { + if (xx < 0 || yy < 0 || xx >= df::global::world->map.x_count_block || yy >= df::global::world->map.y_count_block) + continue; + df::map_block_column * column = df::global::world->map.column_index[xx][yy]; + for (int i = 0; i < column->plants.size(); i++) + { + df::plant * plant = column->plants[i]; + if (!plant->tree_info) + { + if (plant->pos.z < min_z || plant->pos.z >= max_z) + continue; + if (plant->pos.x < in->min_x() * 16 || plant->pos.x >= in->max_x() * 16) + continue; + if (plant->pos.y < in->min_y() * 16 || plant->pos.y >= in->max_y() * 16) + continue; + } + else + { + if (plant->pos.z - plant->tree_info->roots_depth < min_z || plant->pos.z + plant->tree_info->body_height > max_z) + continue; + if (plant->pos.x - plant->tree_info->dim_x / 2 < in->min_x() * 16 || plant->pos.x + plant->tree_info->dim_x / 2 >= in->max_x() * 16) + continue; + if (plant->pos.y - plant->tree_info->dim_y / 2 < in->min_y() * 16 || plant->pos.y + plant->tree_info->dim_y / 2 >= in->max_y() * 16) + continue; + } + RemoteFortressReader::PlantDef * out_plant = out->add_plant_list(); + out_plant->set_index(plant->material); + out_plant->set_pos_x(plant->pos.x); + out_plant->set_pos_y(plant->pos.y); + out_plant->set_pos_z(plant->pos.z); + } + } + return CR_OK; } diff --git a/plugins/stonesense b/plugins/stonesense index 0d1954840..6ecbe21ac 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 0d19548402932c970c8a0d45404808cbe8fe1bcd +Subproject commit 6ecbe21ac317d86806e501ca8e21f7f0eaf4333d