350 lines
9.5 KiB
C
350 lines
9.5 KiB
C
|
#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();
|
||
|
|
||
|
};
|