@ -13,15 +13,13 @@
# include "dfhack/modules/Materials.h"
typedef int32_t t_materialIndex ;
typedef int16_t t_material Subindex , t_itemType , t_itemSubtype ;
typedef int16_t t_material , t_itemType , t_itemSubtype ;
typedef int8_t t_exclusionType ;
const unsigned int seedLimit = 400 ; // a limit on the limits which can be placed on seeds
const t_itemType seedType = 52 ; // from df.magmawiki.com/index.php/Item_token
const t_itemType plantType = 53 ; // from df.magmawiki.com/index.php/Item_token
const t_itemSubtype organicSubtype = - 1 ; // seems to fixed
const t_exclusionType cookingExclusion = 1 ; // seems to be fixed
const t_itemType limitType = 0 ; // used to store limit as an entry in the exclusion list
const t_itemType limitType = 0 ; // used to store limit as an entry in the exclusion list . 0 = BAR
const t_itemSubtype limitSubtype = 0 ; // used to store limit as an entry in the exclusion list
const t_exclusionType limitExclusion = 4 ; // used to store limit as an entry in the exclusion list
const int buffer = 20 ; // seed number buffer - 20 is reasonable
@ -43,27 +41,27 @@ bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags shoul
f . in_building | |
f . in_job ;
} ;
void updateCountAndSubindices ( DFHack : : Core & core , std : : map < t_materialIndex , unsigned int > & seedCount , std : : map < t_materialIndex , t_material Subindex > & seedSubindices , std : : map < t_materialIndex , t_material Subindex > & plantSubindices ) // fills seedCount, seedSubindices and plantSubindices
void updateCountAndSubindices ( DFHack : : Core & core , std : : map < t_materialIndex , unsigned int > & seedCount , std : : map < t_materialIndex , t_material > & seedSubindices , std : : map < t_materialIndex , t_material > & plantSubindices ) // fills seedCount, seedSubindices and plantSubindices
{
DFHack : : Items & itemsModule = * core . getItems ( ) ;
itemsModule . Start ( ) ;
std : : vector < DFHack : : t _item* > items ;
std : : vector < DFHack : : df _item* > items ;
itemsModule . readItemVector ( items ) ;
DFHack : : dfh_item item ;
DFHack : : df_item * item ;
std : : size_t size = items . size ( ) ;
for ( std : : size_t i = 0 ; i < size ; + + i )
{
itemsModule . readItem ( items [ i ] , item ) ;
t_materialIndex materialIndex = item . matdesc . index ;
switch ( item . matdesc . itemType )
item = items [ i ] ;
t_materialIndex materialIndex = item - > getMaterialIndex ( ) ;
switch ( item - > getType ( ) )
{
case seedType :
seedSubindices [ materialIndex ] = item . matdesc . subIndex ;
if ( ! ignoreSeeds ( item . base - > flags ) ) + + seedCount [ materialIndex ] ;
case DFHack : : Items : : SEEDS :
seedSubindices [ materialIndex ] = item - > getMaterial ( ) ;
if ( ! ignoreSeeds ( item - > flags ) ) + + seedCount [ materialIndex ] ;
break ;
case plantType :
plantSubindices [ materialIndex ] = item . matdesc . subIndex ;
case DFHack : : Items : : PLANT :
plantSubindices [ materialIndex ] = item - > getMaterial ( ) ;
break ;
}
}
@ -72,12 +70,13 @@ void updateCountAndSubindices(DFHack::Core& core, std::map<t_materialIndex, unsi
} ;
void printHelp ( DFHack : : Core & core ) // prints help
{
core . con . print ( " \n e.g. #seedwatch MUSHROOM_HELMET_PLUMP 30 \n " ) ;
core . con . print ( " This is how to add an item to the watch list. \n " ) ;
core . con . print ( " MUSHROOM_HELMET_PLUMP is the plant token for plump helmets (found in raws) \n " ) ;
core . con . print ( " The number of available plump helmet seeds is counted each tick \n " ) ;
core . con . print ( " If it falls below 30, plump helmets and plump helmet seeds will be excluded from cookery. \n " ) ;
core . con . print ( " %i is the buffer, therefore if the number rises above 30 + %i, then cooking will be allowed. \n " , buffer , buffer ) ;
core . con . print (
" \n e.g. #seedwatch MUSHROOM_HELMET_PLUMP 30 \n "
" This is how to add an item to the watch list. \n "
" MUSHROOM_HELMET_PLUMP is the plant token for plump helmets (found in raws) \n "
" The number of available plump helmet seeds is counted each tick \n "
" If it falls below 30, plump helmets and plump helmet seeds will be excluded from cookery. \n "
" %i is the buffer, therefore if the number rises above 30 + %i, then cooking will be allowed. \n " , buffer , buffer ) ;
if ( ! abbreviations . empty ( ) )
{
core . con . print ( " You can use these abbreviations for the plant tokens: \n " ) ;
@ -86,31 +85,42 @@ void printHelp(DFHack::Core& core) // prints help
core . con . print ( " %s -> %s \n " , i - > first . c_str ( ) , i - > second . c_str ( ) ) ;
}
}
core . con . print ( " e.g. #seedwatch ph 30 \n is the same as #seedwatch MUSHROOM_HELMET_PLUMP 30 \n \n " ) ;
core . con . print ( " e.g. #seedwatch all 30 \n Adds all which are in the abbreviation list to the watch list, the limit being 30. \n \n " ) ;
core . con . print ( " e.g. #seedwatch MUSHROOM_HELMET_PLUMP \n Removes MUSHROOM_HELMET_PLUMP from the watch list. \n \n " ) ;
core . con . print ( " #seedwatch all \n Clears the watch list. \n \n " ) ;
core . con . print ( " #seedwatch start \n Start seedwatch watch. \n \n " ) ;
core . con . print ( " #seedwatch stop \n Stop seedwatch watch. \n \n " ) ;
core . con . print ( " #seedwatch info \n Display whether seedwatch is watching, and the watch list. \n \n " ) ;
core . con . print ( " #seedwatch clear \n Clears the watch list. \n " ) ;
core . con . print (
" e.g. #seedwatch ph 30 \n is the same as #seedwatch MUSHROOM_HELMET_PLUMP 30 \n \n "
" e.g. #seedwatch all 30 \n Adds all which are in the abbreviation list to the watch list, the limit being 30. \n \n "
" e.g. #seedwatch MUSHROOM_HELMET_PLUMP \n Removes MUSHROOM_HELMET_PLUMP from the watch list. \n \n "
" #seedwatch all \n Clears the watch list. \n \n "
" #seedwatch start \n Start seedwatch watch. \n \n "
" #seedwatch stop \n Stop seedwatch watch. \n \n "
" #seedwatch info \n Display whether seedwatch is watching, and the watch list. \n \n "
" #seedwatch clear \n Clears the watch list. \n "
) ;
} ;
std : : string searchAbbreviations ( std : : string in ) // searches abbreviations, returns expansion if so, returns original if not
// searches abbreviations, returns expansion if so, returns original if not
std : : string searchAbbreviations ( std : : string in )
{
if ( abbreviations . count ( in ) > 0 )
{
return abbreviations [ in ] ;
}
else
{
if ( abbreviations . count ( in ) > 0 ) return abbreviations [ in ] ;
return in ;
}
} ;
class t_kitchenExclusions // helps to organise access to the cooking exclusions
// helps to organise access to the cooking exclusions
class t_kitchenExclusions
{
public :
t_kitchenExclusions ( DFHack : : Core & core_ ) // constructor
: core ( core_ )
, itemTypes ( * ( ( std : : vector < t_itemType > * ) ( st art ( core_ ) ) ) ) // using the kludge in start
, itemSubtypes ( * ( ( std : : vector < t_itemSubtype > * ) ( start ( core_ ) + 0x10 ) ) ) // further kludge offset
, materialSubindices ( * ( ( std : : vector < t_material Subindex> * ) ( start ( core_ ) + 0x20 ) ) ) // further kludge offset
, materialIndices ( * ( ( std : : vector < t_materialIndex > * ) ( start ( core_ ) + 0x30 ) ) ) // further kludge offset
, exclusionTypes ( * ( ( std : : vector < t_exclusionType > * ) ( start ( core_ ) + 0x40 ) ) ) // further kludge offset
, itemTypes ( * ( ( std : : vector < t_itemType > * ) ( add r( core_ ,0 )) ) )
, itemSubtypes ( * ( ( std : : vector < t_itemSubtype > * ) ( addr ( core_ , 1 ) ) ) )
, materials ( * ( ( std : : vector < t_material > * ) ( addr ( core_ , 2 ) ) ) )
, materialIndices ( * ( ( std : : vector < t_materialIndex > * ) ( addr ( core_ , 3 ) ) ) )
, exclusionTypes ( * ( ( std : : vector < t_exclusionType > * ) ( addr ( core_ , 4 ) ) ) )
{
} ;
void print ( ) // print the exclusion list, with the material index also translated into its token (for organics) - for debug really
@ -120,7 +130,7 @@ public:
materialsModule . ReadOrganicMaterials ( ) ;
for ( std : : size_t i = 0 ; i < size ( ) ; + + i )
{
core . con . print ( " %2u: IT:%2i IS:%i MI:%2i MS:%3i ET:%i %s \n " , i , itemTypes [ i ] , itemSubtypes [ i ] , materialIndices [ i ] , material Subindice s[ i ] , exclusionTypes [ i ] , materialsModule . organic [ materialIndices [ i ] ] . id . c_str ( ) ) ;
core . con . print ( " %2u: IT:%2i IS:%i MI:%2i MS:%3i ET:%i %s \n " , i , itemTypes [ i ] , itemSubtypes [ i ] , materialIndices [ i ] , material s[ i ] , exclusionTypes [ i ] , materialsModule . organic [ materialIndices [ i ] ] . id . c_str ( ) ) ;
}
core . con . print ( " \n " ) ;
} ;
@ -133,7 +143,10 @@ public:
std : : size_t matchIndex = 0 ;
for ( std : : size_t i = 0 ; i < size ( ) ; + + i )
{
if ( materialIndices [ i ] = = materialIndex & & ( itemTypes [ i ] = = seedType | | itemTypes [ i ] = = plantType ) & & exclusionTypes [ i ] = = cookingExclusion )
if ( materialIndices [ i ] = = materialIndex
& & ( itemTypes [ i ] = = DFHack : : Items : : SEEDS | | itemTypes [ i ] = = DFHack : : Items : : PLANT )
& & exclusionTypes [ i ] = = cookingExclusion
)
{
match = true ;
matchIndex = i ;
@ -144,64 +157,74 @@ public:
itemTypes . erase ( itemTypes . begin ( ) + matchIndex ) ;
itemSubtypes . erase ( itemSubtypes . begin ( ) + matchIndex ) ;
materialIndices . erase ( materialIndices . begin ( ) + matchIndex ) ;
materialSubindices . erase ( materialSubindice s. begin ( ) + matchIndex ) ;
materials . erase ( material s. begin ( ) + matchIndex ) ;
exclusionTypes . erase ( exclusionTypes . begin ( ) + matchIndex ) ;
}
} while ( match ) ;
} ;
void denyCookery ( t_materialIndex materialIndex , std : : map < t_materialIndex , t_materialSubindex > & seedSubindices , std : : map < t_materialIndex , t_materialSubindex > & plantSubindices ) // add this material to the exclusion list, if it is not already in it
// add this material to the exclusion list, if it is not already in it
void denyCookery ( t_materialIndex materialIndex , std : : map < t_materialIndex , t_material > & seedMaterials , std : : map < t_materialIndex , t_material > & plantMaterials )
{
if ( seedSubindices . count ( materialIndex ) > 0 )
if ( seedMaterial s. count ( materialIndex ) > 0 )
{
bool alreadyIn = false ;
for ( std : : size_t i = 0 ; i < size ( ) ; + + i )
{
if ( materialIndices [ i ] = = materialIndex & & itemTypes [ i ] = = seedType & & exclusionTypes [ i ] = = cookingExclusion )
if ( materialIndices [ i ] = = materialIndex
& & itemTypes [ i ] = = DFHack : : Items : : SEEDS
& & exclusionTypes [ i ] = = cookingExclusion )
{
alreadyIn = true ;
}
}
if ( ! alreadyIn )
{
itemTypes . push_back ( seedType ) ;
itemTypes . push_back ( DFHack : : Items : : SEEDS ) ;
itemSubtypes . push_back ( organicSubtype ) ;
materials . push_back ( seedMaterials [ materialIndex ] ) ;
materialIndices . push_back ( materialIndex ) ;
materialSubindices . push_back ( seedSubindices [ materialIndex ] ) ;
exclusionTypes . push_back ( cookingExclusion ) ;
}
}
if ( plantSubindice s. count ( materialIndex ) > 0 )
if ( plantMaterial s. count ( materialIndex ) > 0 )
{
bool alreadyIn = false ;
for ( std : : size_t i = 0 ; i < size ( ) ; + + i )
{
if ( materialIndices [ i ] = = materialIndex & & itemTypes [ i ] = = plantType & & exclusionTypes [ i ] = = cookingExclusion )
if ( materialIndices [ i ] = = materialIndex
& & itemTypes [ i ] = = DFHack : : Items : : PLANT
& & exclusionTypes [ i ] = = cookingExclusion )
{
alreadyIn = true ;
}
}
if ( ! alreadyIn )
{
itemTypes . push_back ( plantType ) ;
itemTypes . push_back ( DFHack : : Items : : PLANT ) ;
itemSubtypes . push_back ( organicSubtype ) ;
materials . push_back ( plantMaterials [ materialIndex ] ) ;
materialIndices . push_back ( materialIndex ) ;
materialSubindices . push_back ( plantSubindices [ materialIndex ] ) ;
exclusionTypes . push_back ( cookingExclusion ) ;
}
}
} ;
void fillWatchMap ( std : : map < t_materialIndex , unsigned int > & watchMap ) // fills a map with info from the limit info storage entries in the exclusion list
// fills a map with info from the limit info storage entries in the exclusion list
void fillWatchMap ( std : : map < t_materialIndex , unsigned int > & watchMap )
{
watchMap . clear ( ) ;
for ( std : : size_t i = 0 ; i < size ( ) ; + + i )
{
if ( itemTypes [ i ] = = limitType & & itemSubtypes [ i ] = = limitSubtype & & exclusionTypes [ i ] = = limitExclusion )
{
watchMap [ materialIndices [ i ] ] = ( unsigned int ) material Subindice s[ i ] ;
watchMap [ materialIndices [ i ] ] = ( unsigned int ) material s[ i ] ;
}
}
} ;
void removeLimit ( t_materialIndex materialIndex ) // removes a limit info storage entry from the exclusion list if it is in it
// removes a limit info storage entry from the exclusion list if it is in it
void removeLimit ( t_materialIndex materialIndex )
{
bool match = false ;
do
@ -210,7 +233,10 @@ public:
std : : size_t matchIndex = 0 ;
for ( std : : size_t i = 0 ; i < size ( ) ; + + i )
{
if ( itemTypes [ i ] = = limitType & & itemSubtypes [ i ] = = limitSubtype & & materialIndices [ i ] = = materialIndex & & exclusionTypes [ i ] = = limitExclusion )
if ( itemTypes [ i ] = = limitType
& & itemSubtypes [ i ] = = limitSubtype
& & materialIndices [ i ] = = materialIndex
& & exclusionTypes [ i ] = = limitExclusion )
{
match = true ;
matchIndex = i ;
@ -220,13 +246,14 @@ public:
{
itemTypes . erase ( itemTypes . begin ( ) + matchIndex ) ;
itemSubtypes . erase ( itemSubtypes . begin ( ) + matchIndex ) ;
materials . erase ( materials . begin ( ) + matchIndex ) ;
materialIndices . erase ( materialIndices . begin ( ) + matchIndex ) ;
materialSubindices . erase ( materialSubindices . begin ( ) + matchIndex ) ;
exclusionTypes . erase ( exclusionTypes . begin ( ) + matchIndex ) ;
}
} while ( match ) ;
} ;
void setLimit ( t_materialIndex materialIndex , unsigned int limit ) // add a limit info storage item to the exclusion list, or alters an existing one
// add a limit info storage item to the exclusion list, or alters an existing one
void setLimit ( t_materialIndex materialIndex , unsigned int limit )
{
removeLimit ( materialIndex ) ;
if ( limit > seedLimit ) limit = seedLimit ;
@ -234,7 +261,7 @@ public:
itemTypes . push_back ( limitType ) ;
itemSubtypes . push_back ( limitSubtype ) ;
materialIndices . push_back ( materialIndex ) ;
materialSubindice s. push_back ( ( t_material Subindex ) ( limit < seedLimit ) ? limit : seedLimit ) ;
material s. push_back ( ( t_material ) ( limit < seedLimit ) ? limit : seedLimit ) ;
exclusionTypes . push_back ( limitExclusion ) ;
} ;
void clearLimits ( ) // clears all limit info storage items from the exclusion list
@ -246,7 +273,9 @@ public:
std : : size_t matchIndex ;
for ( std : : size_t i = 0 ; i < size ( ) ; + + i )
{
if ( itemTypes [ i ] = = limitType & & itemSubtypes [ i ] = = limitSubtype & & exclusionTypes [ i ] = = limitExclusion )
if ( itemTypes [ i ] = = limitType
& & itemSubtypes [ i ] = = limitSubtype
& & exclusionTypes [ i ] = = limitExclusion )
{
match = true ;
matchIndex = i ;
@ -257,7 +286,7 @@ public:
itemTypes . erase ( itemTypes . begin ( ) + matchIndex ) ;
itemSubtypes . erase ( itemSubtypes . begin ( ) + matchIndex ) ;
materialIndices . erase ( materialIndices . begin ( ) + matchIndex ) ;
materialSubindices . erase ( materialSubindice s. begin ( ) + matchIndex ) ;
materials . erase ( material s. begin ( ) + matchIndex ) ;
exclusionTypes . erase ( exclusionTypes . begin ( ) + matchIndex ) ;
}
} while ( match ) ;
@ -266,23 +295,31 @@ private:
DFHack : : Core & core ;
std : : vector < t_itemType > & itemTypes ; // the item types vector of the kitchen exclusion list
std : : vector < t_itemSubtype > & itemSubtypes ; // the item subtype vector of the kitchen exclusion list
std : : vector < t_material Subindex > & material Subindice s; // the material subindex vector of the kitchen exclusion list
std : : vector < t_material > & material s; // the material subindex vector of the kitchen exclusion list
std : : vector < t_materialIndex > & materialIndices ; // the material index vector of the kitchen exclusion list
std : : vector < t_exclusionType > & exclusionTypes ; // the exclusion type vector of the kitchen excluions list
std : : size_t size ( ) // the size of the exclusions vectors (they are all the same size - if not, there is a problem!)
{
return itemTypes . size ( ) ;
} ;
static uint32_t start ( const DFHack : : Core & core ) // the kludge for the exclusion position in memory
{
return core . p - > getBase ( ) + 0x014F0BB4 - 0x400000 ;
//FIXME: ugly, ugly hack. Use memory.xml instead.
static uint32_t addr ( const DFHack : : Core & core , int index )
{
# ifdef LINUX_BUILD
return 0x93f2b00 + 0xC * index ;
# else
return core . p - > getBase ( ) + 0x014F0BB4 - 0x400000 + 0x10 * index ;
# endif
} ;
} ;
DFhackCExport DFHack : : command_result df_seedwatch ( DFHack : : Core * pCore , std : : vector < std : : string > & parameters )
{
DFHack : : Core & core = * pCore ;
if ( ! core . isValid ( ) ) return DFHack : : CR_FAILURE ;
if ( ! core . isValid ( ) )
{
return DFHack : : CR_FAILURE ;
}
core . Suspend ( ) ;
DFHack : : Materials & materialsModule = * core . getMaterials ( ) ;
@ -325,12 +362,21 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
else if ( par = = " info " )
{
core . con . print ( " seedwatch Info: \n " ) ;
if ( running ) core . con . print ( " seedwatch is supervising. Use 'seedwatch stop' to stop supervision. \n " ) ;
else core . con . print ( " seedwatch is not supervising. Use 'seedwatch start' to start supervision. \n " ) ;
if ( running )
{
core . con . print ( " seedwatch is supervising. Use 'seedwatch stop' to stop supervision. \n " ) ;
}
else
{
core . con . print ( " seedwatch is not supervising. Use 'seedwatch start' to start supervision. \n " ) ;
}
t_kitchenExclusions kitchenExclusions ( core ) ;
std : : map < t_materialIndex , unsigned int > watchMap ;
kitchenExclusions . fillWatchMap ( watchMap ) ;
if ( watchMap . empty ( ) ) core . con . print ( " The watch list is empty. \n " ) ;
if ( watchMap . empty ( ) )
{
core . con . print ( " The watch list is empty. \n " ) ;
}
else
{
core . con . print ( " The watch list is: \n " ) ;
@ -339,7 +385,13 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
core . con . print ( " %s : %u \n " , organics [ i - > first ] . id . c_str ( ) , i - > second ) ;
}
}
/*kitchenExclusions.print();*/
}
else if ( par = = " debug " )
{
t_kitchenExclusions kitchenExclusions ( core ) ;
std : : map < t_materialIndex , unsigned int > watchMap ;
kitchenExclusions . fillWatchMap ( watchMap ) ;
kitchenExclusions . print ( ) ;
}
else
{
@ -431,8 +483,8 @@ DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore)
{
DFHack : : Core & core = * pCore ;
std : : map < t_materialIndex , unsigned int > seedCount ; // the number of seeds
std : : map < t_materialIndex , t_material Subindex > seedSubindices ; // holds information needed to add entries to the cooking exclusions
std : : map < t_materialIndex , t_material Subindex > plantSubindices ; // holds information need to add entries to the cooking exclusions
std : : map < t_materialIndex , t_material > seedSubindices ; // holds information needed to add entries to the cooking exclusions
std : : map < t_materialIndex , t_material > plantSubindices ; // holds information need to add entries to the cooking exclusions
updateCountAndSubindices ( core , seedCount , seedSubindices , plantSubindices ) ;
t_kitchenExclusions kitchenExclusions ( core ) ;
std : : map < t_materialIndex , unsigned int > watchMap ;