diff --git a/plugins/proto/ItemdefInstrument.proto b/plugins/proto/ItemdefInstrument.proto new file mode 100644 index 000000000..c92491ace --- /dev/null +++ b/plugins/proto/ItemdefInstrument.proto @@ -0,0 +1,104 @@ +package ItemdefInstrument; + +//Attempts to provide a complete framework for reading everything from a fortress needed for vizualization +option optimize_for = LITE_RUNTIME; + +message InstrumentFlags + { + optional bool indefinite_pitch = 1; + optional bool placed_as_building = 2; + optional bool metal_mat = 3; + optional bool stone_mat = 4; + optional bool wood_mat = 5; + optional bool glass_mat = 6; + optional bool ceramic_mat = 7; + optional bool shell_mat = 8; + optional bool bone_mat = 9; +} + +enum PitchChoiceType +{ + MEMBRANE_POSITION = 0; + SUBPART_CHOICE = 1; + KEYBOARD = 2; + STOPPING_FRET = 3; + STOPPING_AGAINST_BODY = 4; + STOPPING_HOLE = 5; + STOPPING_HOLE_KEY = 6; + SLIDE = 7; + HARMONIC_SERIES = 8; + VALVE_ROUTES_AIR = 9; + BP_IN_BELL = 10; + FOOT_PEDALS = 11; +} + +enum SoundProductionType +{ + PLUCKED_BY_BP = 0; + PLUCKED = 1; + BOWED = 2; + STRUCK_BY_BP = 3; + STRUCK = 4; + VIBRATE_BP_AGAINST_OPENING = 5; + BLOW_AGAINST_FIPPLE = 6; + BLOW_OVER_OPENING_SIDE = 7; + BLOW_OVER_OPENING_END = 8; + BLOW_OVER_SINGLE_REED = 9; + BLOW_OVER_DOUBLE_REED = 10; + BLOW_OVER_FREE_REED = 11; + STRUCK_TOGETHER = 12; + SHAKEN = 13; + SCRAPED = 14; + FRICTION = 15; + RESONATOR = 16; + BAG_OVER_REED = 17; + AIR_OVER_REED = 18; + AIR_OVER_FREE_REED = 19; + AIR_AGAINST_FIPPLE = 20; +} + +enum TuningType +{ + PEGS = 0; + ADJUSTABLE_BRIDGES = 1; + CROOKS = 2; + TIGHTENING = 3; + LEVERS = 4; +} + +message InstrumentPiece +{ + optional string type = 1; + optional string id = 2; + optional string name = 3; + optional string name_plural = 4; +} + +message InstrumentRegister +{ + optional int32 pitch_range_min = 1; + optional int32 pitch_range_max = 2; +} + +message InstrumentDef +{ + optional InstrumentFlags flags = 1; + optional int32 size = 2; + optional int32 value = 3; + optional int32 material_size = 4; + repeated InstrumentPiece pieces = 5; + optional int32 pitch_range_min = 6; + optional int32 pitch_range_max = 7; + optional int32 volume_mb_min = 8; + optional int32 volume_mb_max = 9; + repeated SoundProductionType sound_production = 10; + repeated string sound_production_parm1 = 11; + repeated string sound_production_parm2 = 12; + repeated PitchChoiceType pitch_choice = 13; + repeated string pitch_choice_parm1 = 14; + repeated string pitch_choice_parm2 = 15; + repeated TuningType tuning = 16; + repeated string tuning_parm = 17; + repeated InstrumentRegister registers = 18; + optional string description = 19; +} \ No newline at end of file diff --git a/plugins/proto/RemoteFortressReader.proto b/plugins/proto/RemoteFortressReader.proto index 35f5b0abe..3298d42fb 100644 --- a/plugins/proto/RemoteFortressReader.proto +++ b/plugins/proto/RemoteFortressReader.proto @@ -3,6 +3,8 @@ package RemoteFortressReader; //Attempts to provide a complete framework for reading everything from a fortress needed for vizualization option optimize_for = LITE_RUNTIME; +import "ItemdefInstrument.proto"; + //We use shapes, etc, because the actual tiletypes may differ between DF versions. enum TiletypeShape { @@ -311,6 +313,7 @@ message MapBlock repeated bool tile_dig_designation_marker = 27; repeated bool tile_dig_designation_auto = 28; repeated int32 grass_percent = 29; + repeated FlowInfo flows = 30; } message MatPair { @@ -329,6 +332,7 @@ message MaterialDefinition{ optional string id = 2; optional string name = 3; optional ColorDefinition state_color = 4; //Simplifying colors to assume room temperature. + optional ItemdefInstrument.InstrumentDef instrument = 5; } message BuildingType @@ -435,6 +439,7 @@ message BlockList optional int32 map_x = 2; optional int32 map_y = 3; repeated Engraving engravings = 4; + repeated Wave ocean_waves = 5; } message PlantDef @@ -1025,3 +1030,42 @@ enum ArtImageVerb VERB_BEINGMUTILATED = 46; VERB_TRIUMPHANTPOSE = 47; } + +enum FlowType +{ + Miasma = 0; + Steam = 1; + Mist = 2; + MaterialDust = 3; + MagmaMist = 4; + Smoke = 5; + Dragonfire = 6; + Fire = 7; + Web = 8; + MaterialGas = 9; + MaterialVapor = 10; + OceanWave = 11; + SeaFoam = 12; + ItemCloud = 13; + CampFire = -1; +} + +message FlowInfo +{ + optional int32 index = 1; + optional FlowType type = 2; + optional int32 density = 3; + optional Coord pos = 4; + optional Coord dest = 5; + optional bool expanding = 6; + optional bool reuse = 7; + optional int32 guide_id = 8; + optional MatPair material = 9; + optional MatPair item = 10; +} + +message Wave +{ + optional Coord dest = 1; + optional Coord pos = 2; +} \ No newline at end of file diff --git a/plugins/remotefortressreader/CMakeLists.txt b/plugins/remotefortressreader/CMakeLists.txt index 10cc21047..ad61c94ce 100644 --- a/plugins/remotefortressreader/CMakeLists.txt +++ b/plugins/remotefortressreader/CMakeLists.txt @@ -17,6 +17,7 @@ SET(PROJECT_HDRS SET(PROJECT_PROTO ../../proto/RemoteFortressReader ../../proto/AdventureControl + ../../proto/ItemdefInstrument ) SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/plugins/remotefortressreader/item_reader.cpp b/plugins/remotefortressreader/item_reader.cpp index 5bfccbfad..c0170f2c4 100644 --- a/plugins/remotefortressreader/item_reader.cpp +++ b/plugins/remotefortressreader/item_reader.cpp @@ -1,6 +1,7 @@ #include "item_reader.h" #include "Core.h" #include "VersionInfo.h" +#include "ItemdefInstrument.pb.h" #include "df/art_image.h" #include "df/art_image_chunk.h" @@ -16,6 +17,8 @@ #include "df/art_image_property_transitive_verbst.h" #include "df/art_image_ref.h" #include "df/descriptor_shape.h" +#include "df/instrument_piece.h" +#include "df/instrument_register.h" #include "df/item_type.h" #include "df/item_constructed.h" #include "df/item_gemst.h" @@ -23,6 +26,8 @@ #include "df/item_statuest.h" #include "df/item_threadst.h" #include "df/item_toolst.h" +#include "df/itemdef_instrumentst.h" +#include "df/itemdef_toolst.h" #include "df/itemimprovement.h" #include "df/itemimprovement_art_imagest.h" #include "df/itemimprovement_bandsst.h" @@ -46,6 +51,7 @@ using namespace DFHack; using namespace df::enums; using namespace RemoteFortressReader; +using namespace ItemdefInstrument; using namespace std; using namespace df::global; @@ -326,6 +332,10 @@ void CopyItem(RemoteFortressReader::Item * NetItem, df::item * DfItem) if (info.decode(thread->dye_mat_type, thread->dye_mat_index)) ConvertDFColorDescriptor(info.material->powder_dye, NetItem->mutable_dye()); } + if (DfItem->flags.bits.spider_web) + type->set_mat_index(1); + else + type->set_mat_index(0); break; } case df::enums::item_type::CLOTH: @@ -547,13 +557,24 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: mat_def = out->add_material_list(); mat_def->mutable_mat_pair()->set_mat_type((int)it); mat_def->mutable_mat_pair()->set_mat_index(0); - mat_def->set_id("BOX_CHEST"); + mat_def->set_id("BOX/CHEST"); mat_def = out->add_material_list(); mat_def->mutable_mat_pair()->set_mat_type((int)it); mat_def->mutable_mat_pair()->set_mat_index(1); - mat_def->set_id("BOX_BAG"); + mat_def->set_id("BOX/BAG"); break; } + case df::enums::item_type::THREAD: + { + mat_def = out->add_material_list(); + mat_def->mutable_mat_pair()->set_mat_type((int)it); + mat_def->mutable_mat_pair()->set_mat_index(0); + mat_def->set_id("THREAD/NORMAL"); + mat_def = out->add_material_list(); + mat_def->mutable_mat_pair()->set_mat_type((int)it); + mat_def->mutable_mat_pair()->set_mat_index(1); + mat_def->set_id("THREAD/WEB"); + } } int subtypes = Items::getSubtypeCount(it); if (subtypes >= 0) @@ -565,6 +586,85 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: mat_def->mutable_mat_pair()->set_mat_index(i); df::itemdef * item = Items::getSubtypeDef(it, i); mat_def->set_id(ENUM_KEY_STR(item_type, it) + "/" + item->id); + switch (it) + { + case df::enums::item_type::INSTRUMENT: + { + VIRTUAL_CAST_VAR(instrument, df::itemdef_instrumentst, item); + mat_def->set_name(DF2UTF(instrument->name)); + auto send_instrument = mat_def->mutable_instrument(); + auto flags = send_instrument->mutable_flags(); + flags->set_indefinite_pitch(instrument->flags.is_set(instrument_flags::INDEFINITE_PITCH)); + flags->set_placed_as_building(instrument->flags.is_set(instrument_flags::PLACED_AS_BUILDING)); + flags->set_metal_mat(instrument->flags.is_set(instrument_flags::METAL_MAT)); + flags->set_stone_mat(instrument->flags.is_set(instrument_flags::STONE_MAT)); + flags->set_wood_mat(instrument->flags.is_set(instrument_flags::WOOD_MAT)); + flags->set_glass_mat(instrument->flags.is_set(instrument_flags::GLASS_MAT)); + flags->set_ceramic_mat(instrument->flags.is_set(instrument_flags::CERAMIC_MAT)); + flags->set_shell_mat(instrument->flags.is_set(instrument_flags::SHELL_MAT)); + flags->set_bone_mat(instrument->flags.is_set(instrument_flags::BONE_MAT)); + send_instrument->set_size(instrument->size); + send_instrument->set_value(instrument->value); + send_instrument->set_material_size(instrument->material_size); + for (int j = 0; j < instrument->pieces.size(); j++) + { + auto piece = send_instrument->add_pieces(); + piece->set_type(instrument->pieces[j]->type); + piece->set_id(instrument->pieces[j]->id); + piece->set_name(DF2UTF(instrument->pieces[j]->name)); + piece->set_name_plural(DF2UTF(instrument->pieces[j]->name_plural)); + } + send_instrument->set_pitch_range_min(instrument->pitch_range_min); + send_instrument->set_pitch_range_max(instrument->pitch_range_max); + for (int j = 0; j < instrument->sound_production.size(); j++) + { + send_instrument->add_sound_production((SoundProductionType)instrument->sound_production[j]); + } + for (int j = 0; j < instrument->sound_production_parm1.size(); j++) + { + send_instrument->add_sound_production_parm1(*(instrument->sound_production_parm1[j])); + } + for (int j = 0; j < instrument->sound_production_parm2.size(); j++) + { + send_instrument->add_sound_production_parm2(*(instrument->sound_production_parm2[j])); + } + for (int j = 0; j < instrument->pitch_choice.size(); j++) + { + send_instrument->add_pitch_choice((PitchChoiceType)instrument->pitch_choice[j]); + } + for (int j = 0; j < instrument->pitch_choice_parm1.size(); j++) + { + send_instrument->add_pitch_choice_parm1(*(instrument->pitch_choice_parm1[j])); + } + for (int j = 0; j < instrument->pitch_choice_parm2.size(); j++) + { + send_instrument->add_pitch_choice_parm2(*(instrument->pitch_choice_parm2[j])); + } + for (int j = 0; j < instrument->tuning.size(); j++) + { + send_instrument->add_tuning((TuningType)instrument->tuning[j]); + } + for (int j = 0; j < instrument->tuning_parm.size(); j++) + { + send_instrument->add_tuning_parm(*(instrument->tuning_parm[j])); + } + for (int j = 0; j < instrument->registers.size(); j++) + { + auto reg = send_instrument->add_registers(); + reg->set_pitch_range_min(instrument->registers[j]->pitch_range_min); + reg->set_pitch_range_max(instrument->registers[j]->pitch_range_max); + } + send_instrument->set_description(DF2UTF(instrument->description)); + break; + } + case df::enums::item_type::TOOL: + { + VIRTUAL_CAST_VAR(tool, df::itemdef_toolst, item); + mat_def->set_name(DF2UTF(tool->name)); + } + default: + break; + } } } } diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index 197c4bd6a..e1282d600 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -58,6 +58,9 @@ #include "df/dfhack_material_category.h" #include "df/enabler.h" #include "df/engraving.h" +#include "df/flow_info.h" +#include "df/flow_guide.h" +#include "df/flow_guide_item_cloudst.h" #include "df/graphic.h" #include "df/historical_figure.h" @@ -69,6 +72,7 @@ #include "df/material_vec_ref.h" #include "df/matter_state.h" #include "df/mental_attribute_type.h" +#include "df/ocean_wave.h" #include "df/physical_attribute_type.h" #include "df/plant.h" #include "df/plant_raw_flags.h" @@ -397,6 +401,14 @@ void ConvertDFCoord(DFCoord in, RemoteFortressReader::Coord * out) out->set_z(in.z); } +void ConvertDFCoord(int x, int y, int z, RemoteFortressReader::Coord * out) +{ + out->set_x(x); + out->set_y(y); + out->set_z(z); +} + + RemoteFortressReader::TiletypeMaterial TranslateMaterial(df::tiletype_material material) { switch (material) @@ -1395,6 +1407,46 @@ void CopyItems(df::map_block * DfBlock, RemoteFortressReader::MapBlock * NetBloc } } +void CopyFlow(df::flow_info * localFlow, RemoteFortressReader::FlowInfo * netFlow, int index) +{ + netFlow->set_type((FlowType)localFlow->type); + netFlow->set_density(localFlow->density); + ConvertDFCoord(localFlow->pos, netFlow->mutable_pos()); + ConvertDFCoord(localFlow->dest, netFlow->mutable_dest()); + netFlow->set_expanding(localFlow->expanding); + netFlow->set_reuse(localFlow->reuse); + netFlow->set_guide_id(localFlow->guide_id); + auto mat = netFlow->mutable_material(); + mat->set_mat_index(localFlow->mat_index); + mat->set_mat_type(localFlow->mat_type); + if (localFlow->guide_id >= 0 && localFlow->type == flow_type::ItemCloud) + { + auto guide = df::flow_guide::find(localFlow->guide_id); + if (guide) + { + VIRTUAL_CAST_VAR(cloud, df::flow_guide_item_cloudst, guide); + if (cloud) + { + mat->set_mat_index(cloud->matindex); + mat->set_mat_type(cloud->mattype); + auto item = netFlow->mutable_item(); + item->set_mat_index(cloud->item_subtype); + item->set_mat_type(cloud->item_type); + } + } + } +} + +void CopyFlows(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 i = 0; i < DfBlock->flows.size(); i++) + { + CopyFlow(DfBlock->flows[i], NetBlock->add_flows(), i); + } +} static command_result GetBlockList(color_ostream &stream, const BlockRequest *in, BlockList *out) { @@ -1442,7 +1494,7 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in df::map_block * block = DFHack::Maps::getBlock(pos); if (block != NULL) { - int nonAir = 0; + bool nonAir = false; for (int xxx = 0; xxx < 16; xxx++) for (int yyy = 0; yyy < 16; yyy++) { @@ -1450,16 +1502,23 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in DFHack::tileShapeBasic(DFHack::tileShape(block->tiletype[xxx][yyy])) != df::tiletype_shape_basic::Open) || block->designation[xxx][yyy].bits.flow_size > 0 || block->occupancy[xxx][yyy].bits.building > 0) - nonAir++; + { + nonAir = true; + goto ItsAir; + } } - if (nonAir > 0 || firstBlock) + ItsAir: + if (block->flows.size() > 0) + nonAir = true; + if (nonAir || firstBlock) { bool tileChanged = IsTiletypeChanged(pos); bool desChanged = IsDesignationChanged(pos); bool spatterChanged = IsspatterChanged(pos); bool itemsChanged = block->items.size() > 0; + bool flows = block->flows.size() > 0; RemoteFortressReader::MapBlock *net_block; - if (tileChanged || desChanged || spatterChanged || firstBlock || itemsChanged) + if (tileChanged || desChanged || spatterChanged || firstBlock || itemsChanged || flows) net_block = out->add_map_blocks(); if (tileChanged) { @@ -1478,6 +1537,10 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in Copyspatters(block, net_block, &MC, pos); if (itemsChanged) CopyItems(block, net_block, &MC, pos); + if (flows) + { + CopyFlows(block, net_block); + } } } } @@ -1553,6 +1616,13 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in netEngraving->set_southwest(engraving->flags.bits.southwest); netEngraving->set_southeast(engraving->flags.bits.southeast); } + for (int i = 0; i < world->ocean_waves.size(); i++) + { + auto wave = world->ocean_waves[i]; + auto netWave = out->add_ocean_waves(); + ConvertDFCoord(wave->x1, wave->y1, wave->z, netWave->mutable_dest()); + ConvertDFCoord(wave->x2, wave->y2, wave->z, netWave->mutable_pos()); + } MC.trash(); return CR_OK; }