stockpiles: refactor code into separate files
The file was approaching 3000 lines and contained multiple classes, making it a real PITA to navigate through. upcoming features would only add more LOC, so splitting was necessary.develop
							parent
							
								
									10fa55570e
								
							
						
					
					
						commit
						2e43ea8b38
					
				
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -0,0 +1,44 @@ | |||||||
|  | PROJECT(stockpiles) | ||||||
|  | 
 | ||||||
|  | # add *our* headers here. | ||||||
|  | SET(PROJECT_HDRS | ||||||
|  | StockpileUtils.h | ||||||
|  | OrganicMatLookup.h | ||||||
|  | StockpileSerializer.h | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | SET(PROJECT_SRCS | ||||||
|  | OrganicMatLookup.cpp | ||||||
|  | StockpileSerializer.cpp | ||||||
|  | stockpiles.cpp | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | SET(PROJECT_PROTOS | ||||||
|  | ${CMAKE_CURRENT_SOURCE_DIR}/proto/stockpiles.proto | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | #Create new lists of what sources and headers protoc will output after we invoke it | ||||||
|  | STRING(REPLACE ".proto" ".pb.cc;" PROJECT_PROTO_SRCS ${PROJECT_PROTOS}) | ||||||
|  | STRING(REPLACE ".proto" ".pb.h;" PROJECT_PROTO_HDRS ${PROJECT_PROTOS}) | ||||||
|  | 
 | ||||||
|  | SET_SOURCE_FILES_PROPERTIES( ${PROJECT_PROTO_HDRS} PROPERTIES GENERATED TRUE) | ||||||
|  | SET_SOURCE_FILES_PROPERTIES( ${PROJECT_PROTO_SRCS} PROPERTIES GENERATED TRUE) | ||||||
|  | 
 | ||||||
|  | LIST(APPEND PROJECT_HDRS ${PROJECT_PROTO_HDRS}) | ||||||
|  | LIST(APPEND PROJECT_SRCS ${PROJECT_PROTO_SRCS}) | ||||||
|  | 
 | ||||||
|  | SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) | ||||||
|  | LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) | ||||||
|  | 
 | ||||||
|  | #Generate sources from our proto files and store them in the source tree | ||||||
|  | ADD_CUSTOM_COMMAND( | ||||||
|  | OUTPUT ${PROJECT_PROTO_SRCS} ${PROJECT_PROTO_HDRS} | ||||||
|  | COMMAND protoc-bin -I=${CMAKE_CURRENT_SOURCE_DIR}/proto/ --cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/proto/ ${PROJECT_PROTOS} | ||||||
|  | DEPENDS protoc-bin ${PROJECT_PROTOS} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | IF(WIN32) | ||||||
|  |     DFHACK_PLUGIN(stockpiles ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite) | ||||||
|  | ELSE() | ||||||
|  |     DFHACK_PLUGIN(stockpiles ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite) | ||||||
|  | ENDIF() | ||||||
| @ -0,0 +1,155 @@ | |||||||
|  | #include "OrganicMatLookup.h" | ||||||
|  | 
 | ||||||
|  | #include "StockpileUtils.h" | ||||||
|  | 
 | ||||||
|  | #include "modules/Materials.h" | ||||||
|  | #include "MiscUtils.h" | ||||||
|  | 
 | ||||||
|  | #include "df/world.h" | ||||||
|  | #include "df/world_data.h" | ||||||
|  | 
 | ||||||
|  | #include "df/creature_raw.h" | ||||||
|  | #include "df/caste_raw.h" | ||||||
|  | #include "df/material.h" | ||||||
|  | 
 | ||||||
|  | using namespace DFHack; | ||||||
|  | using namespace df::enums; | ||||||
|  | using df::global::world; | ||||||
|  | 
 | ||||||
|  | using std::endl; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Helper class for mapping the various organic mats between their material indices | ||||||
|  |  * and their index in the stockpile_settings structures. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | void OrganicMatLookup::food_mat_by_idx ( std::ostream &out, organic_mat_category::organic_mat_category mat_category, std::vector<int16_t>::size_type food_idx, FoodMat & food_mat ) | ||||||
|  | { | ||||||
|  |     out << "food_lookup: food_idx(" << food_idx << ") "; | ||||||
|  |     df::world_raws &raws = world->raws; | ||||||
|  |     df::special_mat_table table = raws.mat_table; | ||||||
|  |     int32_t main_idx = table.organic_indexes[mat_category][food_idx]; | ||||||
|  |     int16_t type = table.organic_types[mat_category][food_idx]; | ||||||
|  |     if ( mat_category == organic_mat_category::Fish || | ||||||
|  |             mat_category == organic_mat_category::UnpreparedFish || | ||||||
|  |             mat_category == organic_mat_category::Eggs ) | ||||||
|  |     { | ||||||
|  |         food_mat.creature = raws.creatures.all[type]; | ||||||
|  |         food_mat.caste = food_mat.creature->caste[main_idx]; | ||||||
|  |         out << " special creature type(" << type << ") caste("<< main_idx <<")" <<endl; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         food_mat.material.decode ( type, main_idx ); | ||||||
|  |         out << " type(" << type << ") index("<< main_idx <<") token(" << food_mat.material.getToken() <<  ")" << endl; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | std::string OrganicMatLookup::food_token_by_idx ( std::ostream &out, organic_mat_category::organic_mat_category mat_category, std::vector<int16_t>::size_type idx ) | ||||||
|  | { | ||||||
|  |     FoodMat food_mat; | ||||||
|  |     food_mat_by_idx ( out, mat_category, idx, food_mat ); | ||||||
|  |     if ( food_mat.material.isValid() ) | ||||||
|  |     { | ||||||
|  |         return food_mat.material.getToken(); | ||||||
|  |     } | ||||||
|  |     else if ( food_mat.creature ) | ||||||
|  |     { | ||||||
|  |         return food_mat.creature->creature_id + ":" + food_mat.caste->caste_id; | ||||||
|  |     } | ||||||
|  |     return std::string(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t OrganicMatLookup::food_max_size ( organic_mat_category::organic_mat_category mat_category ) | ||||||
|  | { | ||||||
|  |     return world->raws.mat_table.organic_types[mat_category].size(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void OrganicMatLookup::food_build_map ( std::ostream &out ) | ||||||
|  | { | ||||||
|  |     if ( index_built ) | ||||||
|  |         return; | ||||||
|  |     df::world_raws &raws = world->raws; | ||||||
|  |     df::special_mat_table table = raws.mat_table; | ||||||
|  |     using df::enums::organic_mat_category::organic_mat_category; | ||||||
|  |     df::enum_traits<organic_mat_category> traits; | ||||||
|  |     for ( int32_t mat_category = traits.first_item_value; mat_category <= traits.last_item_value; ++mat_category ) | ||||||
|  |     { | ||||||
|  |         for ( size_t i = 0; i < table.organic_indexes[mat_category].size(); ++i ) | ||||||
|  |         { | ||||||
|  |             int16_t type = table.organic_types[mat_category].at ( i ); | ||||||
|  |             int32_t index = table.organic_indexes[mat_category].at ( i ); | ||||||
|  |             food_index[mat_category].insert ( std::make_pair ( std::make_pair ( type,index ), i ) ); // wtf.. only in c++
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     index_built = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int16_t OrganicMatLookup::food_idx_by_token ( std::ostream &out, organic_mat_category::organic_mat_category mat_category, const std::string & token ) | ||||||
|  | { | ||||||
|  |     int16_t food_idx = -1; | ||||||
|  |     df::world_raws &raws = world->raws; | ||||||
|  |     df::special_mat_table table = raws.mat_table; | ||||||
|  |     out << "food_idx_by_token: "; | ||||||
|  |     if ( mat_category == organic_mat_category::Fish || | ||||||
|  |             mat_category == organic_mat_category::UnpreparedFish || | ||||||
|  |             mat_category == organic_mat_category::Eggs ) | ||||||
|  |     { | ||||||
|  |         std::vector<std::string> tokens; | ||||||
|  |         split_string ( &tokens, token, ":" ); | ||||||
|  |         if ( tokens.size() != 2 ) | ||||||
|  |         { | ||||||
|  |             out << "creature " << "invalid CREATURE:CASTE token: " << token << endl; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             int16_t creature_idx = find_creature ( tokens[0] ); | ||||||
|  |             if ( creature_idx < 0 ) | ||||||
|  |             { | ||||||
|  |                 out << " creature invalid token " << tokens[0]; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 food_idx = linear_index ( table.organic_types[mat_category], creature_idx ); | ||||||
|  |                 if ( tokens[1] ==  "MALE" ) | ||||||
|  |                     food_idx +=  1; | ||||||
|  |                 if ( table.organic_types[mat_category][food_idx] ==  creature_idx ) | ||||||
|  |                     out << "creature " << token << " caste " <<  tokens[1] <<  " creature_idx(" << creature_idx << ") food_idx("<< food_idx << ")" << endl; | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     out << "ERROR creature caste not found: " << token << " caste " <<  tokens[1] <<  " creature_idx(" << creature_idx << ") food_idx("<< food_idx << ")" << endl; | ||||||
|  |                     food_idx = -1; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         if ( !index_built ) | ||||||
|  |             food_build_map ( out ); | ||||||
|  |         MaterialInfo mat_info = food_mat_by_token ( out, token ); | ||||||
|  |         int16_t type = mat_info.type; | ||||||
|  |         int32_t index = mat_info.index; | ||||||
|  |         int16_t food_idx2 = -1; | ||||||
|  |         auto it = food_index[mat_category].find ( std::make_pair ( type, index ) ); | ||||||
|  |         if ( it != food_index[mat_category].end() ) | ||||||
|  |         { | ||||||
|  |             out << "matinfo: " << token << " type(" << mat_info.type << ") idx("  << mat_info.index << ") food_idx(" << it->second << ")" << endl; | ||||||
|  |             food_idx = it->second; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             out << "matinfo: " << token << " type(" << mat_info.type << ") idx("  << mat_info.index << ") food_idx not found :(" <<  endl; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return food_idx; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MaterialInfo OrganicMatLookup::food_mat_by_token ( std::ostream &out, const std::string & token ) | ||||||
|  | { | ||||||
|  |     MaterialInfo mat_info; | ||||||
|  |     mat_info.find ( token ); | ||||||
|  |     return mat_info; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool OrganicMatLookup::index_built = false; | ||||||
|  | std::vector<OrganicMatLookup::FoodMatMap> OrganicMatLookup::food_index = std::vector<OrganicMatLookup::FoodMatMap> ( 37 ); | ||||||
| @ -0,0 +1,47 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "modules/Materials.h" | ||||||
|  | 
 | ||||||
|  | #include "df/organic_mat_category.h" | ||||||
|  | 
 | ||||||
|  | namespace df { | ||||||
|  | struct creature_raw; | ||||||
|  | struct caste_raw; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Helper class for mapping the various organic mats between their material indices | ||||||
|  |  * and their index in the stockpile_settings structures. | ||||||
|  |  */ | ||||||
|  | class OrganicMatLookup | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | //  pair of material type and index
 | ||||||
|  |     typedef std::pair<int16_t, int32_t> FoodMatPair; | ||||||
|  | //  map for using type,index pairs to find the food index
 | ||||||
|  |     typedef std::map<FoodMatPair, size_t> FoodMatMap; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     struct FoodMat | ||||||
|  |     { | ||||||
|  |         DFHack::MaterialInfo material; | ||||||
|  |         df::creature_raw *creature; | ||||||
|  |         df::caste_raw * caste; | ||||||
|  |         FoodMat() : material ( -1 ), creature ( 0 ), caste ( 0 ) {} | ||||||
|  |     }; | ||||||
|  |     static void food_mat_by_idx ( std::ostream &out, df::enums::organic_mat_category::organic_mat_category mat_category, std::vector<int16_t>::size_type food_idx, FoodMat & food_mat ); | ||||||
|  |     static std::string food_token_by_idx ( std::ostream &out, df::enums::organic_mat_category::organic_mat_category mat_category, std::vector<int16_t>::size_type idx ); | ||||||
|  | 
 | ||||||
|  |     static size_t food_max_size ( df::enums::organic_mat_category::organic_mat_category mat_category ); | ||||||
|  |     static void food_build_map ( std::ostream &out ); | ||||||
|  | 
 | ||||||
|  |     static int16_t food_idx_by_token ( std::ostream &out, df::enums::organic_mat_category::organic_mat_category mat_category, const std::string & token ); | ||||||
|  | 
 | ||||||
|  |     static DFHack::MaterialInfo food_mat_by_token ( std::ostream &out, const std::string & token ); | ||||||
|  | 
 | ||||||
|  |     static bool index_built; | ||||||
|  |     static std::vector<FoodMatMap> food_index; | ||||||
|  | private: | ||||||
|  |     OrganicMatLookup(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -0,0 +1,349 @@ | |||||||
|  | #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 <functional> | ||||||
|  | #include <vector> | ||||||
|  | #include <ostream> | ||||||
|  | #include <istream> | ||||||
|  | 
 | ||||||
|  | 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<int, std::string> mOtherMatsFurniture; | ||||||
|  |  std::map<int, std::string> mOtherMatsFinishedGoods; | ||||||
|  |  std::map<int, std::string> mOtherMatsBars; | ||||||
|  |  std::map<int, std::string> mOtherMatsBlocks; | ||||||
|  |  std::map<int, std::string> 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<typename E> | ||||||
|  |  static typename df::enum_traits<E>::base_type linear_index ( std::ostream & out, df::enum_traits<E> 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["<<j<<"/"<<limit<<"]: " <<traits.key_table[j] << endl;
 | ||||||
|  |    if ( token.compare ( traits.key_table[j] ) == 0 ) | ||||||
|  |    return j; | ||||||
|  |   } | ||||||
|  |   return -1; | ||||||
|  |  } | ||||||
|  | 
 | ||||||
|  |  //  read the token from the serailized list during import
 | ||||||
|  |  typedef std::function<std::string ( const size_t& ) > FuncReadImport; | ||||||
|  |  //  add the token to the serialized list during export
 | ||||||
|  |  typedef std::function<void ( const std::string & ) > FuncWriteExport; | ||||||
|  |  //  are item's of item_type allowed?
 | ||||||
|  |  typedef std::function<bool ( df::enums::item_type::item_type ) > FuncItemAllowed; | ||||||
|  |  //  is this material allowed?
 | ||||||
|  |  typedef std::function<bool ( const DFHack::MaterialInfo & ) > FuncMaterialAllowed; | ||||||
|  | 
 | ||||||
|  |  // convenient struct for parsing food stockpile items
 | ||||||
|  |  struct food_pair | ||||||
|  |  { | ||||||
|  |   // exporting
 | ||||||
|  |   FuncWriteExport set_value; | ||||||
|  |   std::vector<char> * stockpile_values; | ||||||
|  |   // importing
 | ||||||
|  |   FuncReadImport get_value; | ||||||
|  |   size_t serialized_count; | ||||||
|  |   bool valid; | ||||||
|  | 
 | ||||||
|  |   food_pair ( FuncWriteExport s, std::vector<char>* 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<char> * 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<char> *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<char> &list ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  /**
 | ||||||
|  |   * @see serialize_list_organic_mat | ||||||
|  |   */ | ||||||
|  |  void unserialize_list_item_type ( FuncItemAllowed is_allowed, FuncReadImport read_value,  int32_t list_size,  std::vector<char> *pile_list ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  /**
 | ||||||
|  |   * @see serialize_list_organic_mat | ||||||
|  |   */ | ||||||
|  |  void serialize_list_material ( FuncMaterialAllowed is_allowed,  FuncWriteExport add_value,  const std::vector<char> &list ); | ||||||
|  | 
 | ||||||
|  |  /**
 | ||||||
|  |   * @see serialize_list_organic_mat | ||||||
|  |   */ | ||||||
|  |  void unserialize_list_material ( FuncMaterialAllowed is_allowed, FuncReadImport read_value,  int32_t list_size,  std::vector<char> *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<int, std::string> other_mats, FuncWriteExport add_value,  std::vector<char> list ); | ||||||
|  | 
 | ||||||
|  |  /**
 | ||||||
|  |   * @see serialize_list_organic_mat | ||||||
|  |   */ | ||||||
|  |  void unserialize_list_other_mats ( const std::map<int, std::string> other_mats, FuncReadImport read_value,  int32_t list_size, std::vector<char> *pile_list ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  /**
 | ||||||
|  |   * @see serialize_list_organic_mat | ||||||
|  |   */ | ||||||
|  |  void serialize_list_itemdef ( FuncWriteExport add_value,  std::vector<char> list,  std::vector<df::itemdef *> 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<char> *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<int, std::string> 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<int, std::string> 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<void ( const std::string & ) > add_value, const std::vector<char> & list ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  bool refuse_type_is_allowed ( df::enums::item_type::item_type type ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  void write_refuse(); | ||||||
|  |  void refuse_read_helper ( std::function<std::string ( const size_t& ) > get_value, size_t list_size, std::vector<char>* 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(); | ||||||
|  | 
 | ||||||
|  | }; | ||||||
| @ -0,0 +1,53 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "MiscUtils.h" | ||||||
|  | 
 | ||||||
|  | #include "df/world.h" | ||||||
|  | #include "df/world_data.h" | ||||||
|  | #include "df/creature_raw.h" | ||||||
|  | #include "df/plant_raw.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Utility Functions {{{
 | ||||||
|  | // A set of convenience functions for doing common lookups
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Retrieve creature raw from index | ||||||
|  |  */ | ||||||
|  | static df::creature_raw* find_creature ( int32_t idx ) | ||||||
|  | { | ||||||
|  |     return df::global::world->raws.creatures.all[idx]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Retrieve creature index from id string | ||||||
|  |  * @return -1 if not found | ||||||
|  |  */ | ||||||
|  | static int16_t find_creature ( const std::string &creature_id ) | ||||||
|  | { | ||||||
|  |     return linear_index ( df::global::world->raws.creatures.all, &df::creature_raw::creature_id, creature_id ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Retrieve plant raw from index | ||||||
|  | */ | ||||||
|  | static df::plant_raw* find_plant ( size_t idx ) | ||||||
|  | { | ||||||
|  |     return df::global::world->raws.plants.all[idx]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Retrieve plant index from id string | ||||||
|  |  * @return -1 if not found | ||||||
|  |  */ | ||||||
|  | static size_t find_plant ( const std::string &plant_id ) | ||||||
|  | { | ||||||
|  |     return linear_index ( df::global::world->raws.plants.all, &df::plant_raw::id, plant_id ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // }}} utility Functions
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,3 @@ | |||||||
|  | *.pb.cc | ||||||
|  | *.pb.cc.rule | ||||||
|  | *.pb.h | ||||||
| @ -0,0 +1,303 @@ | |||||||
|  | #include "Core.h" | ||||||
|  | #include "Console.h" | ||||||
|  | #include "Export.h" | ||||||
|  | #include "PluginManager.h" | ||||||
|  | 
 | ||||||
|  | #include "StockpileSerializer.h" | ||||||
|  | 
 | ||||||
|  | #include "df/world.h" | ||||||
|  | #include "df/world_data.h" | ||||||
|  | 
 | ||||||
|  | #include "df/ui.h" | ||||||
|  | #include "df/building_stockpilest.h" | ||||||
|  | #include "df/stockpile_settings.h" | ||||||
|  | #include "df/global_objects.h" | ||||||
|  | #include "df/viewscreen_dwarfmodest.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //  os
 | ||||||
|  | #include <sys/stat.h> | ||||||
|  | 
 | ||||||
|  | //  stl
 | ||||||
|  | #include <functional> | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | using std::vector; | ||||||
|  | using std::string; | ||||||
|  | using std::endl; | ||||||
|  | using namespace DFHack; | ||||||
|  | using namespace df::enums; | ||||||
|  | using namespace google::protobuf; | ||||||
|  | using namespace dfstockpiles; | ||||||
|  | 
 | ||||||
|  | using df::global::world; | ||||||
|  | using df::global::ui; | ||||||
|  | using df::global::selection_rect; | ||||||
|  | 
 | ||||||
|  | using df::building_stockpilest; | ||||||
|  | using std::placeholders::_1; | ||||||
|  | 
 | ||||||
|  | static command_result copystock ( color_ostream &out, vector <string> & parameters ); | ||||||
|  | static bool copystock_guard ( df::viewscreen *top ); | ||||||
|  | 
 | ||||||
|  | static command_result savestock ( color_ostream &out, vector <string> & parameters ); | ||||||
|  | static bool savestock_guard ( df::viewscreen *top ); | ||||||
|  | 
 | ||||||
|  | static command_result loadstock ( color_ostream &out, vector <string> & parameters ); | ||||||
|  | static bool loadstock_guard ( df::viewscreen *top ); | ||||||
|  | 
 | ||||||
|  | DFHACK_PLUGIN ( "stockpiles" ); | ||||||
|  | 
 | ||||||
|  | DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands ) | ||||||
|  | { | ||||||
|  |     if ( world && ui ) | ||||||
|  |     { | ||||||
|  |         commands.push_back ( | ||||||
|  |             PluginCommand ( | ||||||
|  |                 "copystock", "Copy stockpile under cursor.", | ||||||
|  |                 copystock, copystock_guard, | ||||||
|  |                 "  - In 'q' or 't' mode: select a stockpile and invoke in order\n" | ||||||
|  |                 "    to switch to the 'p' stockpile creation mode, and initialize\n" | ||||||
|  |                 "    the custom settings from the selected stockpile.\n" | ||||||
|  |                 "  - In 'p': invoke in order to switch back to 'q'.\n" | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |         commands.push_back ( | ||||||
|  |             PluginCommand ( | ||||||
|  |                 "savestock", "Save the active stockpile's settings to a file.", | ||||||
|  |                 savestock, savestock_guard, | ||||||
|  |                 "Must be in 'q' mode and have a stockpile selected.\n" | ||||||
|  |                 "example: 'savestock food.dfstock' will save the settings to 'food.dfstock'\n" | ||||||
|  |                 "in your stockpile folder.\n" | ||||||
|  |                 "Omitting the filename will result in text output directly to the console\n\n" | ||||||
|  |                 " -d, --debug: enable debug output\n" | ||||||
|  |                 " <filename>     : filename to save stockpile settings to (will be overwritten!)\n" | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |         commands.push_back ( | ||||||
|  |             PluginCommand ( | ||||||
|  |                 "loadstock", "Load settings from a file and apply them to the active stockpile.", | ||||||
|  |                 loadstock, loadstock_guard, | ||||||
|  |                 "Must be in 'q' mode and have a stockpile selected.\n" | ||||||
|  |                 "example: 'loadstock food.dfstock' will load the settings from 'food.dfstock'\n" | ||||||
|  |                 "in your stockpile folder and apply them to the selected stockpile.\n" | ||||||
|  |                 " -d, --debug: enable debug output\n" | ||||||
|  |                 " <filename>     : filename to load stockpile settings from\n" | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |     std::cerr << "world: " << sizeof ( df::world ) << " ui: " << sizeof ( df::ui ) | ||||||
|  |               << " b_stock: " << sizeof ( building_stockpilest ) << endl; | ||||||
|  |     return CR_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DFhackCExport command_result plugin_shutdown ( color_ostream &out ) | ||||||
|  | { | ||||||
|  |     return CR_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool copystock_guard ( df::viewscreen *top ) | ||||||
|  | { | ||||||
|  |     using namespace ui_sidebar_mode; | ||||||
|  | 
 | ||||||
|  |     if ( !Gui::dwarfmode_hotkey ( top ) ) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     switch ( ui->main.mode ) | ||||||
|  |     { | ||||||
|  |     case Stockpiles: | ||||||
|  |         return true; | ||||||
|  |     case BuildingItems: | ||||||
|  |     case QueryBuilding: | ||||||
|  |         return !!virtual_cast<building_stockpilest> ( world->selected_building ); | ||||||
|  |     default: | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static command_result copystock ( color_ostream &out, vector <string> & parameters ) | ||||||
|  | { | ||||||
|  |     // HOTKEY COMMAND: CORE ALREADY SUSPENDED
 | ||||||
|  | 
 | ||||||
|  |     // For convenience: when used in the stockpiles mode, switch to 'q'
 | ||||||
|  |     if ( ui->main.mode == ui_sidebar_mode::Stockpiles ) | ||||||
|  |     { | ||||||
|  |         world->selected_building = NULL; // just in case it contains some kind of garbage
 | ||||||
|  |         ui->main.mode = ui_sidebar_mode::QueryBuilding; | ||||||
|  |         selection_rect->start_x = -30000; | ||||||
|  | 
 | ||||||
|  |         out << "Switched back to query building." << endl; | ||||||
|  |         return CR_OK; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     building_stockpilest *sp = virtual_cast<building_stockpilest> ( world->selected_building ); | ||||||
|  |     if ( !sp ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "Selected building isn't a stockpile.\n" ); | ||||||
|  |         return CR_WRONG_USAGE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ui->stockpile.custom_settings = sp->settings; | ||||||
|  |     ui->main.mode = ui_sidebar_mode::Stockpiles; | ||||||
|  |     world->selected_stockpile_type = stockpile_category::Custom; | ||||||
|  | 
 | ||||||
|  |     out << "Stockpile options copied." << endl; | ||||||
|  |     return CR_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static bool savestock_guard ( df::viewscreen *top ) | ||||||
|  | { | ||||||
|  |     using namespace ui_sidebar_mode; | ||||||
|  | 
 | ||||||
|  |     if ( !Gui::dwarfmode_hotkey ( top ) ) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     switch ( ui->main.mode ) | ||||||
|  |     { | ||||||
|  |     case Stockpiles: | ||||||
|  |         return true; | ||||||
|  |     case BuildingItems: | ||||||
|  |     case QueryBuilding: | ||||||
|  |         return !!virtual_cast<building_stockpilest> ( world->selected_building ); | ||||||
|  |     default: | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool loadstock_guard ( df::viewscreen *top ) | ||||||
|  | { | ||||||
|  |     using namespace ui_sidebar_mode; | ||||||
|  | 
 | ||||||
|  |     if ( !Gui::dwarfmode_hotkey ( top ) ) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     switch ( ui->main.mode ) | ||||||
|  |     { | ||||||
|  |     case Stockpiles: | ||||||
|  |         return true; | ||||||
|  |     case BuildingItems: | ||||||
|  |     case QueryBuilding: | ||||||
|  |         return !!virtual_cast<building_stockpilest> ( world->selected_building ); | ||||||
|  |     default: | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static bool file_exists ( const std::string& filename ) | ||||||
|  | { | ||||||
|  |     struct stat buf; | ||||||
|  |     if ( stat ( filename.c_str(), &buf ) != -1 ) | ||||||
|  |     { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool is_dfstockfile ( const std::string& filename ) | ||||||
|  | { | ||||||
|  |     return filename.rfind ( ".dfstock" ) !=  std::string::npos; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //  exporting
 | ||||||
|  | static command_result savestock ( color_ostream &out, vector <string> & parameters ) | ||||||
|  | { | ||||||
|  |     building_stockpilest *sp = virtual_cast<building_stockpilest> ( world->selected_building ); | ||||||
|  |     if ( !sp ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "Selected building isn't a stockpile.\n" ); | ||||||
|  |         return CR_WRONG_USAGE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if ( parameters.size() > 2 ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "Invalid parameters\n" ); | ||||||
|  |         return CR_WRONG_USAGE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool debug = false; | ||||||
|  |     std::string file; | ||||||
|  |     for ( size_t i = 0; i < parameters.size(); ++i ) | ||||||
|  |     { | ||||||
|  |         const std::string o = parameters.at ( i ); | ||||||
|  |         if ( o == "--debug"  ||  o ==  "-d" ) | ||||||
|  |             debug =  true; | ||||||
|  |         else  if ( !o.empty() && o[0] !=  '-' ) | ||||||
|  |         { | ||||||
|  |             file = o; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if ( file.empty() ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "You must supply a valid filename.\n" ); | ||||||
|  |         return CR_WRONG_USAGE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     StockpileSerializer cereal ( sp ); | ||||||
|  |     if ( debug ) | ||||||
|  |         cereal.enable_debug ( out ); | ||||||
|  | 
 | ||||||
|  |     if ( !is_dfstockfile ( file ) ) file += ".dfstock"; | ||||||
|  |     if ( !cereal.serialize_to_file ( file ) ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "serialize failed\n" ); | ||||||
|  |         return CR_FAILURE; | ||||||
|  |     } | ||||||
|  |     return CR_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // importing
 | ||||||
|  | static command_result loadstock ( color_ostream &out, vector <string> & parameters ) | ||||||
|  | { | ||||||
|  |     building_stockpilest *sp = virtual_cast<building_stockpilest> ( world->selected_building ); | ||||||
|  |     if ( !sp ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "Selected building isn't a stockpile.\n" ); | ||||||
|  |         return CR_WRONG_USAGE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if ( parameters.size() < 1 ||  parameters.size() > 2 ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "Invalid parameters\n" ); | ||||||
|  |         return CR_WRONG_USAGE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool debug = false; | ||||||
|  |     std::string file; | ||||||
|  |     for ( size_t i = 0; i < parameters.size(); ++i ) | ||||||
|  |     { | ||||||
|  |         const std::string o = parameters.at ( i ); | ||||||
|  |         if ( o == "--debug"  ||  o ==  "-d" ) | ||||||
|  |             debug =  true; | ||||||
|  |         else  if ( !o.empty() && o[0] !=  '-' ) | ||||||
|  |         { | ||||||
|  |             file = o; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if ( !is_dfstockfile ( file ) ) file += ".dfstock"; | ||||||
|  |     if ( file.empty() || !file_exists ( file ) ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "loadstock: a .dfstock file is required to import\n" ); | ||||||
|  |         return CR_WRONG_USAGE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     StockpileSerializer cereal ( sp ); | ||||||
|  |     if ( debug ) | ||||||
|  |         cereal.enable_debug ( out ); | ||||||
|  |     if ( !cereal.unserialize_from_file ( file ) ) | ||||||
|  |     { | ||||||
|  |         out.printerr ( "unserialization failed\n" ); | ||||||
|  |         return CR_FAILURE; | ||||||
|  |     } | ||||||
|  |     return CR_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
		Loading…
	
		Reference in New Issue