diff --git a/library/xml b/library/xml index 851f52d5e..f74eeb5f7 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 851f52d5e9eae6fc81adadd10e53bd2cc42bfd21 +Subproject commit f74eeb5f705afa0d1e766d31090e62d4706126e5 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 468d22e6c..84aa36199 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -165,6 +165,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(3dveins 3dveins.cpp) DFHACK_PLUGIN(strangemood strangemood.cpp) DFHACK_PLUGIN(command-prompt command-prompt.cpp) + DFHACK_PLUGIN(remotefortressreader remotefortressreader.cpp PROTOBUFS RemoteFortressReader) DFHACK_PLUGIN(building-hacks building-hacks.cpp LINK_LIBRARIES lua) endif() diff --git a/plugins/isoworld b/plugins/isoworld index aa3b1bd51..29fad1ef8 160000 --- a/plugins/isoworld +++ b/plugins/isoworld @@ -1 +1 @@ -Subproject commit aa3b1bd51f269c07b3235392fd7ed21fe9171f3f +Subproject commit 29fad1ef8e7e2aceb2e68c93a3993933168fe885 diff --git a/plugins/isoworldremote.cpp b/plugins/isoworldremote.cpp index c25d096c7..8a3bacfd5 100644 --- a/plugins/isoworldremote.cpp +++ b/plugins/isoworldremote.cpp @@ -197,14 +197,12 @@ static command_result GetEmbarkInfo(color_ostream &stream, const MapRequest *in, out->set_available(false); return CR_OK; } - if(!in->has_save_folder()) { //probably should send the stuff anyway, but nah. - out->set_available(false); - return CR_OK; - } - if(!(in->save_folder() == df::global::world->cur_savegame.save_dir)) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them. - out->set_available(false); - return CR_OK; - } + if (in->has_save_folder()) { //If no save folder is given, it means we don't care. + if (!(in->save_folder() == df::global::world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them. + out->set_available(false); + return CR_OK; + } + } out->set_available(true); out->set_current_year(*df::global::cur_year); out->set_current_season(*df::global::cur_season); @@ -346,14 +344,12 @@ static command_result GetRawNames(color_ostream &stream, const MapRequest *in, R out->set_available(false); return CR_OK; } - if(!in->has_save_folder()) { //probably should send the stuff anyway, but nah. - out->set_available(false); - return CR_OK; - } - if(!(in->save_folder() == df::global::world->cur_savegame.save_dir)) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them. - out->set_available(false); - return CR_OK; - } + if (in->has_save_folder()) { //If no save folder is given, it means we don't care. + if (!(in->save_folder() == df::global::world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them. + out->set_available(false); + return CR_OK; + } + } out->set_available(true); for(int i = 0; i < df::global::world->raws.inorganics.size(); i++){ out->add_inorganic(df::global::world->raws.inorganics[i]->id); diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto new file mode 100644 index 000000000..ad630f566 --- /dev/null +++ b/plugins/proto/RemoteFortressReader.proto @@ -0,0 +1,26 @@ +package RemoteFortressReader; + +//Attempts to provide a complete framework for reading everything from a fortress needed for vizualization +option optimize_for = LITE_RUNTIME; + +message MatPair { + required int32 mat_type = 1; + required int32 mat_index = 2; +} + +message ColorDefinition { + required int32 red = 1; + required int32 green = 2; + required int32 blue = 3; +} + +message MaterialDefinition{ + required MatPair mat_pair = 1; + optional string id = 2; + optional string name = 3; + optional ColorDefinition state_color = 4; //Simplifying colors to assume room temperature. +} + +message MaterialList{ + repeated MaterialDefinition material_list = 1; +} \ No newline at end of file diff --git a/plugins/remotefortressreader.cpp b/plugins/remotefortressreader.cpp new file mode 100644 index 000000000..b44827c4f --- /dev/null +++ b/plugins/remotefortressreader.cpp @@ -0,0 +1,177 @@ +// This is a generic plugin that does nothing useful apart from acting as an example... of a plugin that does nothing :D + +// some headers required for a plugin. Nothing special, just the basics. +#include "Core.h" +#include +#include +#include + +// DF data structure definition headers +#include "DataDefs.h" +#include "df/world.h" +#include "df/ui.h" +#include "df/item.h" +#include "df/creature_raw.h" +#include "df/caste_raw.h" +#include "df/body_part_raw.h" +#include "df/historical_figure.h" + +#include "df/job_item.h" +#include "df/job_material_category.h" +#include "df/dfhack_material_category.h" +#include "df/matter_state.h" +#include "df/material_vec_ref.h" +#include "df/builtin_mats.h" + +#include "df/descriptor_color.h" +#include "df/descriptor_pattern.h" +#include "df/descriptor_shape.h" + +#include "df/physical_attribute_type.h" +#include "df/mental_attribute_type.h" +#include + +//DFhack specific headers +#include "modules/Maps.h" +#include "modules/MapCache.h" +#include "modules/Materials.h" + +//Needed for writing the protobuff stuff to a file. +#include +#include +#include + +#include "RemoteFortressReader.pb.h" + +#include "RemoteServer.h" + +using namespace DFHack; +using namespace df::enums; +using namespace RemoteFortressReader; + + +// 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); + + + + +// A plugin must be able to return its name and version. +// The name string provided must correspond to the filename - skeleton.plug.so or skeleton.plug.dll in this case +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) +{ + //// Fill the command list with your commands. + //commands.push_back(PluginCommand( + // "isoworldremote", "Dump north-west embark tile to text file for debug purposes.", + // isoWorldRemote, false, /* true means that the command can't be used from non-interactive user interface */ + // // Extended help string. Used by CR_WRONG_USAGE and the help command: + // " This command does nothing at all.\n" + // "Example:\n" + // " isoworldremote\n" + // " Does nothing.\n" + //)); + return CR_OK; +} + +DFhackCExport RPCService *plugin_rpcconnect(color_ostream &) +{ + RPCService *svc = new RPCService(); + svc->addFunction("GetMaterialList", GetMaterialList); + return svc; +} + +// This is called right before the plugin library is removed from memory. +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 + // in a zombie state, but things won't crash. + 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; +} + +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 = &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->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; +} \ No newline at end of file diff --git a/plugins/stonesense b/plugins/stonesense index 0d41614ff..a3cbb54ef 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 0d41614ff3dae9245e786ad667b0e463fe0dea3e +Subproject commit a3cbb54efd12873f9815ce8133665808566e8560