#pragma once // stockpiles plugin #include "proto/stockpiles.pb.h" // dfhack #include "modules/Materials.h" #include "modules/Items.h" // df #include "df/world.h" #include "df/world_data.h" #include "df/organic_mat_category.h" #include "df/furniture_type.h" #include "df/item_quality.h" #include "df/item_type.h" // stl #include #include #include #include namespace df { struct building_stockpilest; } /** * Null buffer that acts like /dev/null for when debug is disabled */ class NullBuffer : public std::streambuf { public: int overflow ( int c ); }; class NullStream : public std::ostream { public: NullStream(); private: NullBuffer m_sb; }; /** * Class for serializing the stockpile_settings structure into a Google protobuf */ class StockpileSerializer { public: /** * @param out for debugging * @param stockpile stockpile to read or write settings to */ StockpileSerializer ( df::building_stockpilest * stockpile ); ~StockpileSerializer(); void enable_debug ( std::ostream &out ); /** * Since we depend on protobuf-lite, not the full lib, we copy this function from * protobuf message.cc */ bool serialize_to_ostream(std::ostream* output); /** * Will serialize stockpile settings to a file (overwrites existing files) * @return success/failure */ bool serialize_to_file ( const std::string & file ); /** * Again, copied from message.cc */ bool parse_from_istream(std::istream* input); /** * Read stockpile settings from file */ bool unserialize_from_file ( const std::string & file ); private: bool mDebug; std::ostream * mOut; NullStream mNull; df::building_stockpilest * mPile; dfstockpiles::StockpileSettings mBuffer; std::map mOtherMatsFurniture; std::map mOtherMatsFinishedGoods; std::map mOtherMatsBars; std::map mOtherMatsBlocks; std::map mOtherMatsWeaponsArmor; std::ostream & debug(); /** read memory structures and serialize to protobuf */ void write(); // parse serialized data into ui indices void read (); /** * Find an enum's value based off the string label. * @param traits the enum's trait struct * @param token the string value in key_table * @return the enum's value, -1 if not found */ template static typename df::enum_traits::base_type linear_index ( std::ostream & out, df::enum_traits traits, const std::string &token ) { auto j = traits.first_item_value; auto limit = traits.last_item_value; // sometimes enums start at -1, which is bad news for array indexing if ( j < 0 ) { j += abs ( traits.first_item_value ); limit += abs ( traits.first_item_value ); } for ( ; j <= limit; ++j ) { // out << " linear_index("<< token <<") = table["< FuncReadImport; // add the token to the serialized list during export typedef std::function FuncWriteExport; // are item's of item_type allowed? typedef std::function FuncItemAllowed; // is this material allowed? typedef std::function FuncMaterialAllowed; // convenient struct for parsing food stockpile items struct food_pair { // exporting FuncWriteExport set_value; std::vector * stockpile_values; // importing FuncReadImport get_value; size_t serialized_count; bool valid; food_pair ( FuncWriteExport s, std::vector* sp_v, FuncReadImport g, size_t count ) : set_value ( s ) , stockpile_values ( sp_v ) , get_value ( g ) , serialized_count ( count ) , valid ( true ) {} food_pair(): valid( false ) {} }; /** * There are many repeated (un)serialization cases throughout the stockpile_settings structure, * so the most common cases have been generalized into generic functions using lambdas. * * The basic process to serialize a stockpile_settings structure is: * 1. loop through the list * 2. for every element that is TRUE: * 3. map the specific stockpile_settings index into a general material, creature, etc index * 4. verify that type is allowed in the list (e.g., no stone in gems stockpiles) * 5. add it to the protobuf using FuncWriteExport * * The unserialization process is the same in reverse. */ void serialize_list_organic_mat ( FuncWriteExport add_value, const std::vector * list, df::enums::organic_mat_category::organic_mat_category cat ); /** * @see serialize_list_organic_mat */ void unserialize_list_organic_mat ( FuncReadImport get_value, size_t list_size, std::vector *pile_list, df::enums::organic_mat_category::organic_mat_category cat ); /** * @see serialize_list_organic_mat */ void serialize_list_item_type ( FuncItemAllowed is_allowed, FuncWriteExport add_value, const std::vector &list ); /** * @see serialize_list_organic_mat */ void unserialize_list_item_type ( FuncItemAllowed is_allowed, FuncReadImport read_value, int32_t list_size, std::vector *pile_list ); /** * @see serialize_list_organic_mat */ void serialize_list_material ( FuncMaterialAllowed is_allowed, FuncWriteExport add_value, const std::vector &list ); /** * @see serialize_list_organic_mat */ void unserialize_list_material ( FuncMaterialAllowed is_allowed, FuncReadImport read_value, int32_t list_size, std::vector *pile_list ); /** * @see serialize_list_organic_mat */ void serialize_list_quality ( FuncWriteExport add_value, const bool ( &quality_list ) [7] ); /** * Set all values in a bool[7] to false */ void quality_clear ( bool ( &pile_list ) [7] ); /** * @see serialize_list_organic_mat */ void unserialize_list_quality ( FuncReadImport read_value, int32_t list_size, bool ( &pile_list ) [7] ); /** * @see serialize_list_organic_mat */ void serialize_list_other_mats ( const std::map other_mats, FuncWriteExport add_value, std::vector list ); /** * @see serialize_list_organic_mat */ void unserialize_list_other_mats ( const std::map other_mats, FuncReadImport read_value, int32_t list_size, std::vector *pile_list ); /** * @see serialize_list_organic_mat */ void serialize_list_itemdef ( FuncWriteExport add_value, std::vector list, std::vector items, df::enums::item_type::item_type type ); /** * @see serialize_list_organic_mat */ void unserialize_list_itemdef ( FuncReadImport read_value, int32_t list_size, std::vector *pile_list, df::enums::item_type::item_type type ); /** * Given a list of other_materials and an index, return its corresponding token * @return empty string if not found * @see other_mats_token */ std::string other_mats_index ( const std::map other_mats, int idx ); /** * Given a list of other_materials and a token, return its corresponding index * @return -1 if not found * @see other_mats_index */ int other_mats_token ( const std::map other_mats, const std::string & token ); void write_general(); void read_general(); void write_animals(); void read_animals(); food_pair food_map ( df::enums::organic_mat_category::organic_mat_category cat ); void write_food(); void read_food(); void furniture_setup_other_mats(); void write_furniture(); bool furniture_mat_is_allowed ( const DFHack::MaterialInfo &mi ); void read_furniture(); bool refuse_creature_is_allowed ( const df::creature_raw *raw ); void refuse_write_helper ( std::function add_value, const std::vector & list ); bool refuse_type_is_allowed ( df::enums::item_type::item_type type ); void write_refuse(); void refuse_read_helper ( std::function get_value, size_t list_size, std::vector* pile_list ); void read_refuse(); bool stone_is_allowed ( const DFHack::MaterialInfo &mi ); void write_stone(); void read_stone(); bool ammo_mat_is_allowed ( const DFHack::MaterialInfo &mi ); void write_ammo(); void read_ammo(); bool coins_mat_is_allowed ( const DFHack::MaterialInfo &mi ); void write_coins(); void read_coins(); void bars_blocks_setup_other_mats(); bool bars_mat_is_allowed ( const DFHack::MaterialInfo &mi ); bool blocks_mat_is_allowed ( const DFHack::MaterialInfo &mi ); void write_bars_blocks(); void read_bars_blocks(); bool gem_mat_is_allowed ( const DFHack::MaterialInfo &mi ); bool gem_cut_mat_is_allowed ( const DFHack::MaterialInfo &mi ); bool gem_other_mat_is_allowed(DFHack::MaterialInfo &mi ); void write_gems(); void read_gems(); bool finished_goods_type_is_allowed ( df::enums::item_type::item_type type ); void finished_goods_setup_other_mats(); bool finished_goods_mat_is_allowed ( const DFHack::MaterialInfo &mi ); void write_finished_goods(); void read_finished_goods(); void write_leather(); void read_leather(); void write_cloth(); void read_cloth(); bool wood_mat_is_allowed ( const df::plant_raw * plant ); void write_wood(); void read_wood(); bool weapons_mat_is_allowed ( const DFHack::MaterialInfo &mi ); void write_weapons(); void read_weapons(); void weapons_armor_setup_other_mats(); bool armor_mat_is_allowed ( const DFHack::MaterialInfo &mi ); void write_armor(); void read_armor(); };