|
|
@ -31,6 +31,7 @@
|
|
|
|
#include "df/itemdef.h"
|
|
|
|
#include "df/itemdef.h"
|
|
|
|
#include "df/building_def_workshopst.h"
|
|
|
|
#include "df/building_def_workshopst.h"
|
|
|
|
#include "df/building_def_furnacest.h"
|
|
|
|
#include "df/building_def_furnacest.h"
|
|
|
|
|
|
|
|
#include "df/building_wellst.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "df/descriptor_color.h"
|
|
|
|
#include "df/descriptor_color.h"
|
|
|
|
#include "df/descriptor_pattern.h"
|
|
|
|
#include "df/descriptor_pattern.h"
|
|
|
@ -98,6 +99,7 @@ static command_result ResetMapHashes(color_ostream &stream, const EmptyMessage *
|
|
|
|
static command_result GetItemList(color_ostream &stream, const EmptyMessage *in, MaterialList *out);
|
|
|
|
static command_result GetItemList(color_ostream &stream, const EmptyMessage *in, MaterialList *out);
|
|
|
|
static command_result GetBuildingDefList(color_ostream &stream, const EmptyMessage *in, BuildingList *out);
|
|
|
|
static command_result GetBuildingDefList(color_ostream &stream, const EmptyMessage *in, BuildingList *out);
|
|
|
|
static command_result GetWorldMap(color_ostream &stream, const EmptyMessage *in, WorldMap *out);
|
|
|
|
static command_result GetWorldMap(color_ostream &stream, const EmptyMessage *in, WorldMap *out);
|
|
|
|
|
|
|
|
static command_result GetWorldMapCenter(color_ostream &stream, const EmptyMessage *in, WorldMap *out);
|
|
|
|
static command_result GetRegionMaps(color_ostream &stream, const EmptyMessage *in, RegionMaps *out);
|
|
|
|
static command_result GetRegionMaps(color_ostream &stream, const EmptyMessage *in, RegionMaps *out);
|
|
|
|
static command_result GetCreatureRaws(color_ostream &stream, const EmptyMessage *in, CreatureRawList *out);
|
|
|
|
static command_result GetCreatureRaws(color_ostream &stream, const EmptyMessage *in, CreatureRawList *out);
|
|
|
|
|
|
|
|
|
|
|
@ -151,6 +153,7 @@ DFhackCExport RPCService *plugin_rpcconnect(color_ostream &)
|
|
|
|
svc->addFunction("GetWorldMap", GetWorldMap);
|
|
|
|
svc->addFunction("GetWorldMap", GetWorldMap);
|
|
|
|
svc->addFunction("GetRegionMaps", GetRegionMaps);
|
|
|
|
svc->addFunction("GetRegionMaps", GetRegionMaps);
|
|
|
|
svc->addFunction("GetCreatureRaws", GetCreatureRaws);
|
|
|
|
svc->addFunction("GetCreatureRaws", GetCreatureRaws);
|
|
|
|
|
|
|
|
svc->addFunction("GetWorldMapCenter", GetWorldMapCenter);
|
|
|
|
return svc;
|
|
|
|
return svc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -200,6 +203,49 @@ void ConvertDfColor(int16_t in[3], RemoteFortressReader::ColorDefinition * out)
|
|
|
|
ConvertDfColor(index, out);
|
|
|
|
ConvertDfColor(index, out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CopyBuilding(int buildingIndex, RemoteFortressReader::BuildingInstance * remote_build)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
df::building * local_build = df::global::world->buildings.all[buildingIndex];
|
|
|
|
|
|
|
|
remote_build->set_index(buildingIndex);
|
|
|
|
|
|
|
|
int minZ = local_build->z;
|
|
|
|
|
|
|
|
if (local_build->getType() == df::enums::building_type::Well)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
df::building_wellst * well_building = virtual_cast<df::building_wellst>(local_build);
|
|
|
|
|
|
|
|
if (well_building)
|
|
|
|
|
|
|
|
minZ = well_building->bucket_z;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
remote_build->set_pos_x_min(local_build->x1);
|
|
|
|
|
|
|
|
remote_build->set_pos_y_min(local_build->y1);
|
|
|
|
|
|
|
|
remote_build->set_pos_z_min(minZ);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
remote_build->set_pos_x_max(local_build->x2);
|
|
|
|
|
|
|
|
remote_build->set_pos_y_max(local_build->y2);
|
|
|
|
|
|
|
|
remote_build->set_pos_z_max(local_build->z);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto buildingType = remote_build->mutable_building_type();
|
|
|
|
|
|
|
|
buildingType->set_building_type(local_build->getType());
|
|
|
|
|
|
|
|
buildingType->set_building_subtype(local_build->getSubtype());
|
|
|
|
|
|
|
|
buildingType->set_building_custom(local_build->getCustomType());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto material = remote_build->mutable_material();
|
|
|
|
|
|
|
|
material->set_mat_type(local_build->mat_type);
|
|
|
|
|
|
|
|
material->set_mat_index(local_build->mat_index);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
remote_build->set_building_flags(local_build->flags.whole);
|
|
|
|
|
|
|
|
remote_build->set_is_room(local_build->is_room);
|
|
|
|
|
|
|
|
if (local_build->is_room)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto room = remote_build->mutable_room();
|
|
|
|
|
|
|
|
room->set_pos_x(local_build->room.x);
|
|
|
|
|
|
|
|
room->set_pos_y(local_build->room.y);
|
|
|
|
|
|
|
|
room->set_width(local_build->room.width);
|
|
|
|
|
|
|
|
room->set_height(local_build->room.height);
|
|
|
|
|
|
|
|
for (int i = 0; i < (local_build->room.width * local_build->room.height); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
room->add_extents(local_build->room.extents[i]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RemoteFortressReader::TiletypeMaterial TranslateMaterial(df::tiletype_material material)
|
|
|
|
RemoteFortressReader::TiletypeMaterial TranslateMaterial(df::tiletype_material material)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -489,7 +535,7 @@ bool IsTiletypeChanged(DFCoord pos)
|
|
|
|
|
|
|
|
|
|
|
|
map<DFCoord, uint16_t> waterHashes;
|
|
|
|
map<DFCoord, uint16_t> waterHashes;
|
|
|
|
|
|
|
|
|
|
|
|
//check if the tiletypes have changed
|
|
|
|
//check if the designations have changed
|
|
|
|
bool IsDesignationChanged(DFCoord pos)
|
|
|
|
bool IsDesignationChanged(DFCoord pos)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint16_t hash;
|
|
|
|
uint16_t hash;
|
|
|
@ -506,10 +552,32 @@ bool IsDesignationChanged(DFCoord pos)
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map<DFCoord, uint8_t> buildingHashes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//check if the designations have changed
|
|
|
|
|
|
|
|
bool IsBuildingChanged(DFCoord pos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
df::map_block * block = Maps::getBlock(pos);
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
for (int x = 0; x < 16; x++)
|
|
|
|
|
|
|
|
for (int y = 0; y < 16; y++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
DFCoord localPos = DFCoord(pos.x * 16 + x, pos.y * 16 + y, pos.z);
|
|
|
|
|
|
|
|
auto bld = block->occupancy[x][y].bits.building;
|
|
|
|
|
|
|
|
if (buildingHashes[pos] != bld)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
buildingHashes[pos] = bld;
|
|
|
|
|
|
|
|
changed = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static command_result ResetMapHashes(color_ostream &stream, const EmptyMessage *in)
|
|
|
|
static command_result ResetMapHashes(color_ostream &stream, const EmptyMessage *in)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
hashes.clear();
|
|
|
|
hashes.clear();
|
|
|
|
waterHashes.clear();
|
|
|
|
waterHashes.clear();
|
|
|
|
|
|
|
|
buildingHashes.clear();
|
|
|
|
return CR_OK;
|
|
|
|
return CR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -746,6 +814,8 @@ void CopyDesignation(df::map_block * DfBlock, RemoteFortressReader::MapBlock * N
|
|
|
|
NetBlock->set_map_y(DfBlock->map_pos.y);
|
|
|
|
NetBlock->set_map_y(DfBlock->map_pos.y);
|
|
|
|
NetBlock->set_map_z(DfBlock->map_pos.z);
|
|
|
|
NetBlock->set_map_z(DfBlock->map_pos.z);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool hasBuilding = false;
|
|
|
|
|
|
|
|
|
|
|
|
for (int yy = 0; yy < 16; yy++)
|
|
|
|
for (int yy = 0; yy < 16; yy++)
|
|
|
|
for (int xx = 0; xx < 16; xx++)
|
|
|
|
for (int xx = 0; xx < 16; xx++)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -766,6 +836,44 @@ void CopyDesignation(df::map_block * DfBlock, RemoteFortressReader::MapBlock * N
|
|
|
|
NetBlock->add_water_salt(designation.bits.water_salt);
|
|
|
|
NetBlock->add_water_salt(designation.bits.water_salt);
|
|
|
|
NetBlock->add_water_stagnant(designation.bits.water_stagnant);
|
|
|
|
NetBlock->add_water_stagnant(designation.bits.water_stagnant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(hasBuilding)
|
|
|
|
|
|
|
|
for (int i = 0; i < df::global::world->buildings.all.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CopyBuildings(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBlock, MapExtras::MapCache * MC, DFCoord pos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int minX = DfBlock->map_pos.x;
|
|
|
|
|
|
|
|
int minY = DfBlock->map_pos.y;
|
|
|
|
|
|
|
|
int Z = DfBlock->map_pos.z;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int maxX = minX + 15;
|
|
|
|
|
|
|
|
int maxY = minY + 15;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < df::global::world->buildings.all.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
df::building * bld = df::global::world->buildings.all[i];
|
|
|
|
|
|
|
|
if (bld->x1 > maxX || bld->y1 > maxY || bld->x2 < minX || bld->y2 < minY)
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int z2 = bld->z;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bld->getType() == building_type::Well)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
df::building_wellst * well_building = virtual_cast<df::building_wellst>(bld);
|
|
|
|
|
|
|
|
if (well_building)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
z2 = well_building->bucket_z;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bld->z < Z || z2 > Z)
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
auto out_bld = NetBlock->add_buildings();
|
|
|
|
|
|
|
|
CopyBuilding(i, out_bld);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static command_result GetBlockList(color_ostream &stream, const BlockRequest *in, BlockList *out)
|
|
|
|
static command_result GetBlockList(color_ostream &stream, const BlockRequest *in, BlockList *out)
|
|
|
@ -816,14 +924,16 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in
|
|
|
|
for (int yyy = 0; yyy < 16; yyy++)
|
|
|
|
for (int yyy = 0; yyy < 16; yyy++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if ((DFHack::tileShapeBasic(DFHack::tileShape(block->tiletype[xxx][yyy])) != df::tiletype_shape_basic::None &&
|
|
|
|
if ((DFHack::tileShapeBasic(DFHack::tileShape(block->tiletype[xxx][yyy])) != df::tiletype_shape_basic::None &&
|
|
|
|
DFHack::tileShapeBasic(DFHack::tileShape(block->tiletype[xxx][yyy])) != df::tiletype_shape_basic::Open) ||
|
|
|
|
DFHack::tileShapeBasic(DFHack::tileShape(block->tiletype[xxx][yyy])) != df::tiletype_shape_basic::Open)
|
|
|
|
block->designation[xxx][yyy].bits.flow_size > 0)
|
|
|
|
|| block->designation[xxx][yyy].bits.flow_size > 0
|
|
|
|
|
|
|
|
|| block->occupancy[xxx][yyy].bits.building > 0)
|
|
|
|
nonAir++;
|
|
|
|
nonAir++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nonAir > 0)
|
|
|
|
if (nonAir > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bool tileChanged = IsTiletypeChanged(pos);
|
|
|
|
bool tileChanged = IsTiletypeChanged(pos);
|
|
|
|
bool desChanged = IsDesignationChanged(pos);
|
|
|
|
bool desChanged = IsDesignationChanged(pos);
|
|
|
|
|
|
|
|
//bool bldChanged = IsBuildingChanged(pos);
|
|
|
|
RemoteFortressReader::MapBlock *net_block;
|
|
|
|
RemoteFortressReader::MapBlock *net_block;
|
|
|
|
if (tileChanged || desChanged)
|
|
|
|
if (tileChanged || desChanged)
|
|
|
|
net_block = out->add_map_blocks();
|
|
|
|
net_block = out->add_map_blocks();
|
|
|
@ -834,6 +944,10 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (desChanged)
|
|
|
|
if (desChanged)
|
|
|
|
CopyDesignation(block, net_block, &MC, pos);
|
|
|
|
CopyDesignation(block, net_block, &MC, pos);
|
|
|
|
|
|
|
|
if (tileChanged)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
CopyBuildings(block, net_block, &MC, pos);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1223,6 +1337,39 @@ static command_result GetBuildingDefList(color_ostream &stream, const EmptyMessa
|
|
|
|
return CR_OK;
|
|
|
|
return CR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static command_result GetWorldMapCenter(color_ostream &stream, const EmptyMessage *in, WorldMap *out)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!df::global::world->world_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
out->set_world_width(0);
|
|
|
|
|
|
|
|
out->set_world_height(0);
|
|
|
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
df::world_data * data = df::global::world->world_data;
|
|
|
|
|
|
|
|
int width = data->world_width;
|
|
|
|
|
|
|
|
int height = data->world_height;
|
|
|
|
|
|
|
|
out->set_world_width(width);
|
|
|
|
|
|
|
|
out->set_world_height(height);
|
|
|
|
|
|
|
|
int32_t pos_x = 0, pos_y = 0, pos_z = 0;
|
|
|
|
|
|
|
|
if (Maps::IsValid())
|
|
|
|
|
|
|
|
Maps::getPosition(pos_x, pos_y, pos_z);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
for (int i = 0; i < df::global::world->armies.all.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
df::army * thisArmy = df::global::world->armies.all[i];
|
|
|
|
|
|
|
|
if (thisArmy->flags.is_set(df::enums::army_flags::player))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pos_x = (thisArmy->pos.x / 3) - 1;
|
|
|
|
|
|
|
|
pos_y = (thisArmy->pos.y / 3) - 1;
|
|
|
|
|
|
|
|
pos_z = thisArmy->pos.z;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
out->set_center_x(pos_x);
|
|
|
|
|
|
|
|
out->set_center_y(pos_y);
|
|
|
|
|
|
|
|
out->set_center_z(pos_z);
|
|
|
|
|
|
|
|
return CR_OK;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static command_result GetWorldMap(color_ostream &stream, const EmptyMessage *in, WorldMap *out)
|
|
|
|
static command_result GetWorldMap(color_ostream &stream, const EmptyMessage *in, WorldMap *out)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!df::global::world->world_data)
|
|
|
|
if (!df::global::world->world_data)
|
|
|
|