Merge remote-tracking branch 'dfhack/master' into 0.40.08-r2

develop
expwnent 2014-08-15 10:00:30 -04:00
commit 0df2cc7450
6 changed files with 618 additions and 174 deletions

@ -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 <int SIZE>

@ -747,7 +747,7 @@ void MapExtras::BlockInfo::prepare(Block *mblock)
// 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.
@ -760,10 +760,10 @@ void MapExtras::BlockInfo::prepare(Block *mblock)
// 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))
if (z_diff >= 0)
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)];
else
tile = info->roots[-1 - z_diff][xx + (yy*info->dim_x)];
if (tile.whole && !(tile.bits.blocked))
{
df::coord pos = pp->pos;
@ -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:

@ -1 +1 @@
Subproject commit aa3b1bd51f269c07b3235392fd7ed21fe9171f3f
Subproject commit cc9d48d02b3f1b6e70b8d5687915c7b770d965cc

@ -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 {
@ -114,3 +149,16 @@ message BlockList
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;
}

@ -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();
@ -86,8 +94,11 @@ DFhackCExport RPCService *plugin_rpcconnect(color_ostream &)
{
RPCService *svc = new RPCService();
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;
}
@ -119,12 +130,256 @@ uint16_t fletcher16(uint8_t const *data, size_t bytes)
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;
}
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++)
for (int i = 0; i < df::global::world->map.map_blocks.size(); i++)
{
df::map_block * block = world->map.map_blocks[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();
@ -152,22 +407,22 @@ static command_result GetMaterialList(color_ostream &stream, const EmptyMessage
df::world_raws *raws = &world->raws;
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_index(0);
mat_def->mutable_mat_pair()->set_mat_type(i);
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);
mat_def->mutable_state_color()->set_green(color->green);
mat_def->mutable_state_color()->set_blue(color->blue);
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++)
@ -179,16 +434,16 @@ static command_result GetMaterialList(color_ostream &stream, const EmptyMessage
{
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->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);
mat_def->mutable_state_color()->set_green(color->green);
mat_def->mutable_state_color()->set_blue(color->blue);
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);
}
}
}
@ -199,41 +454,100 @@ static command_result GetMaterialList(color_ostream &stream, const EmptyMessage
{
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->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);
mat_def->mutable_state_color()->set_green(color->green);
mat_def->mutable_state_color()->set_blue(color->blue);
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)
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_tiletype_shapes((RemoteFortressReader::TiletypeShape)tileShape(tile));
NetBlock->add_tiletype_materials((RemoteFortressReader::TiletypeMaterial)tileMaterial(tile));
NetBlock->add_tiletype_specials((RemoteFortressReader::TiletypeSpecial)tileSpecial(tile));
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)
{
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++)
{
@ -245,8 +559,76 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in
if (block == NULL)
continue;
RemoteFortressReader::MapBlock *net_block = out->add_map_blocks();
CopyBlock(block, net_block);
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;

@ -1 +1 @@
Subproject commit 0d19548402932c970c8a0d45404808cbe8fe1bcd
Subproject commit 6ecbe21ac317d86806e501ca8e21f7f0eaf4333d