Move a few functions into the core, and add some more.

develop
Alexander Gavrilov 2012-01-08 20:02:12 +04:00
parent 64a9a49ec0
commit ea790f1346
11 changed files with 204 additions and 49 deletions

@ -197,6 +197,16 @@ std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_ite
return res;
}
int DFHack::findBitfieldField(const std::string &name, int size, const bitfield_item_info *items)
{
for (int i = 0; i < size*8; i++) {
if (items[i].name && items[i].name == name)
return i;
}
return -1;
}
#define SIMPLE_GLOBAL(name,tname) \
tname *df::global::name = NULL;
#define GLOBAL(name,tname) SIMPLE_GLOBAL(name,df::tname)

@ -34,6 +34,7 @@ distribution.
#include <ctime>
#endif
#include <ctype.h>
#include <stdarg.h>
std::string stl_sprintf(const char *fmt, ...) {
@ -59,6 +60,45 @@ std::string stl_vsprintf(const char *fmt, va_list args) {
}
}
bool split_string(std::vector<std::string> *out,
const std::string &str, const std::string &separator, bool squash_empty)
{
out->clear();
size_t start = 0, pos;
if (!separator.empty())
{
while ((pos = str.find(separator,start)) != std::string::npos)
{
if (pos > start || !squash_empty)
out->push_back(str.substr(start, pos-start));
start = pos + separator.size();
}
}
if (start < str.size() || !squash_empty)
out->push_back(str.substr(start));
return out->size() > 1;
}
std::string toUpper(const std::string &str)
{
std::string rv(str.size(),' ');
for (unsigned i = 0; i < str.size(); ++i)
rv[i] = toupper(str[i]);
return rv;
}
std::string toLower(const std::string &str)
{
std::string rv(str.size(),' ');
for (unsigned i = 0; i < str.size(); ++i)
rv[i] = tolower(str[i]);
return rv;
}
#ifdef LINUX_BUILD // Linux
uint64_t GetTimeMs64()
{

@ -143,6 +143,12 @@ namespace DFHack
};
DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items);
DFHACK_EXPORT int findBitfieldField(const std::string &name, int size, const bitfield_item_info *items);
template<class T>
inline int findBitfieldField(const T &val, const std::string &name) {
return findBitfieldField(name, sizeof(val.whole), val.get_items());
}
template<class T>
inline std::string bitfieldToString(const T &val) {

@ -163,6 +163,28 @@ inline bool vector_contains(const std::vector<CT*> &vec, FT CT::*field, FT key)
return binsearch_index(vec, field, key) >= 0;
}
template<typename T>
inline T vector_get(const std::vector<T> &vec, unsigned idx, const T &defval = T())
{
if (idx < vec.size())
return vec[idx];
else
return defval;
}
template<typename T>
inline void vector_insert_at(std::vector<T> &vec, unsigned idx, const T &val)
{
vec.insert(vec.begin()+idx, val);
}
template<typename T>
inline void vector_erase_at(std::vector<T> &vec, unsigned idx)
{
if (idx < vec.size())
vec.erase(vec.begin()+idx);
}
template<typename FT>
unsigned insert_into_vector(std::vector<FT> &vec, FT key, bool *inserted = NULL)
{
@ -170,7 +192,7 @@ unsigned insert_into_vector(std::vector<FT> &vec, FT key, bool *inserted = NULL)
bool to_ins = (pos >= vec.size() || vec[pos] != key);
if (inserted) *inserted = to_ins;
if (to_ins)
vec.insert(vec.begin()+pos,key);
vector_insert_at(vec, pos, key);
return pos;
}
@ -181,7 +203,7 @@ unsigned insert_into_vector(std::vector<CT*> &vec, FT CT::*field, CT *obj, bool
bool to_ins = (pos >= vec.size() || vec[pos] != obj);
if (inserted) *inserted = to_ins;
if (to_ins)
vec.insert(vec.begin()+pos,obj);
vector_insert_at(vec, pos, obj);
return pos;
}
@ -213,10 +235,28 @@ Link *linked_list_append(Link *head, Link *tail)
return tail;
}
template<typename Link>
Link *linked_list_insert_after(Link *pos, Link *link)
{
link->next = pos->next;
if (pos->next)
pos->next->prev = link;
link->prev = pos;
pos->next = link;
return link;
}
/*
* MISC
*/
DFHACK_EXPORT bool split_string(std::vector<std::string> *out,
const std::string &str, const std::string &separator,
bool squash_empty = false);
DFHACK_EXPORT std::string toUpper(const std::string &str);
DFHACK_EXPORT std::string toLower(const std::string &str);
/**
* Returns the amount of milliseconds elapsed since the UNIX epoch.
* Works on both windows and linux.

@ -35,6 +35,7 @@ namespace df
struct job;
struct job_item;
struct job_item_filter;
struct building;
}
namespace DFHack
@ -49,6 +50,10 @@ namespace DFHack
DFHACK_EXPORT bool operator== (const df::job &a, const df::job &b);
DFHACK_EXPORT void printJobDetails(Core *c, df::job *job);
DFHACK_EXPORT df::building *getJobHolder(df::job *job);
DFHACK_EXPORT bool linkJobIntoWorld(df::job *job, bool new_id = true);
}
#endif

@ -101,7 +101,8 @@ namespace DFHack
return ptr ? decode(ptr->mat_type, ptr->mat_index) : decode(-1);
}
bool find(const std::string &token, const std::string &subtoken = std::string());
bool find(const std::string &token);
bool findBuiltin(const std::string &token);
bool findInorganic(const std::string &token);
bool findPlant(const std::string &token, const std::string &subtoken);
@ -121,6 +122,8 @@ namespace DFHack
bool matches(const df::job_item &item);
};
DFHACK_EXPORT bool parseJobMaterialCategory(df::job_material_category *cat, const std::string &token);
inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) {
return a.type == b.type && a.index == b.index;
}

@ -33,6 +33,7 @@ using namespace std;
#include "Core.h"
#include "PluginManager.h"
#include "MiscUtils.h"
#include "modules/Job.h"
#include "modules/Materials.h"
@ -45,6 +46,7 @@ using namespace std;
#include <df/job_list_link.h>
#include <df/general_ref.h>
#include <df/general_ref_unit_workerst.h>
#include <df/general_ref_building_holderst.h>
using namespace DFHack;
using namespace df::enums;
@ -69,7 +71,7 @@ df::job *DFHack::cloneJobStruct(df::job *job)
df::general_ref *ref = pnew->references[i];
if (virtual_cast<df::general_ref_unit_workerst>(ref))
pnew->references.erase(pnew->references.begin()+i);
vector_erase_at(pnew->references, i);
else
pnew->references[i] = ref->clone();
}
@ -199,3 +201,44 @@ void DFHack::printJobDetails(Core *c, df::job *job)
for (unsigned i = 0; i < job->job_items.size(); i++)
print_job_item_details(c, job, i, job->job_items[i]);
}
df::building *DFHack::getJobHolder(df::job *job)
{
for (unsigned i = 0; i < job->references.size(); i++)
{
VIRTUAL_CAST_VAR(ref, df::general_ref_building_holderst, job->references[i]);
if (ref)
return ref->getBuilding();
}
return NULL;
}
bool DFHack::linkJobIntoWorld(df::job *job, bool new_id)
{
using df::global::world;
using df::global::job_next_id;
assert(!job->list_link);
if (new_id) {
job->id = (*job_next_id)++;
job->list_link = new df::job_list_link();
job->list_link->item = job;
linked_list_append(&world->job_list, job->list_link);
return true;
} else {
df::job_list_link *ins_pos = &world->job_list;
while (ins_pos->next && ins_pos->next->item->id < job->id)
ins_pos = ins_pos->next;
if (ins_pos->next && ins_pos->next->item->id == job->id)
return false;
job->list_link = new df::job_list_link();
job->list_link->item = job;
linked_list_insert_after(ins_pos, job->list_link);
return true;
}
}

@ -143,27 +143,40 @@ bool MaterialInfo::decode(int16_t type, int32_t index)
return (material != NULL);
}
bool MaterialInfo::find(const std::string &token, const std::string &subtoken)
bool MaterialInfo::find(const std::string &token)
{
if (findBuiltin(token))
return true;
if (subtoken.empty())
std::vector<std::string> items;
split_string(&items, token, ":");
if (items[0] == "INORGANIC")
return findInorganic(vector_get(items,1));
if (items[0] == "CREATURE_MAT" || items[0] == "CREATURE")
return findCreature(vector_get(items,1), vector_get(items,2));
if (items[0] == "PLANT_MAT" || items[0] == "PLANT")
return findPlant(vector_get(items,1), vector_get(items,2));
if (items.size() == 1)
{
if (findInorganic(token))
if (findBuiltin(items[0]))
return true;
if (findInorganic(items[0]))
return true;
}
else
else if (items.size() == 2)
{
if (findPlant(token, subtoken))
if (findPlant(items[0], items[1]))
return true;
if (findCreature(token, subtoken))
if (findCreature(items[0], items[1]))
return true;
}
return false;
}
bool MaterialInfo::findBuiltin(const std::string &token)
{
if (token.empty())
return decode(-1);
df::world_raws &raws = df::global::world->raws;
for (int i = 1; i < NUM_BUILTIN; i++)
if (raws.mat_table.builtin[i]->id == token)
@ -173,6 +186,8 @@ bool MaterialInfo::findBuiltin(const std::string &token)
bool MaterialInfo::findInorganic(const std::string &token)
{
if (token.empty())
return decode(-1);
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.inorganics.size(); i++)
{
@ -185,6 +200,8 @@ bool MaterialInfo::findInorganic(const std::string &token)
bool MaterialInfo::findPlant(const std::string &token, const std::string &subtoken)
{
if (token.empty() || subtoken.empty())
return decode(-1);
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.plants.all.size(); i++)
{
@ -203,6 +220,8 @@ bool MaterialInfo::findPlant(const std::string &token, const std::string &subtok
bool MaterialInfo::findCreature(const std::string &token, const std::string &subtoken)
{
if (token.empty() || subtoken.empty())
return decode(-1);
df::world_raws &raws = df::global::world->raws;
for (unsigned i = 0; i < raws.creatures.all.size(); i++)
{
@ -393,6 +412,25 @@ void MaterialInfo::getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &ma
#undef FLAG
#undef TEST
bool DFHack::parseJobMaterialCategory(df::job_material_category *cat, const std::string &token)
{
cat->whole = 0;
std::vector<std::string> items;
split_string(&items, toLower(token), ",", true);
for (unsigned i = 0; i < items.size(); i++)
{
int id = findBitfieldField(*cat, items[i]);
if (id < 0)
return false;
cat->whole |= (1 << id);
}
return true;
}
Module* DFHack::createMaterials()
{
return new Materials();

@ -265,7 +265,7 @@ PersistentDataItem World::AddPersistentData(const std::string &key)
hfig->id = new_id;
hfig->name.has_name = true;
hfig->name.first_name = key;
memset(hfig->name.words, 0, sizeof(hfig->name.words));
memset(hfig->name.words, 0xFF, sizeof(hfig->name.words));
hfvec.insert(hfvec.begin(), hfig);
return dataFromHFig(hfig);

@ -64,7 +64,7 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
" Print details of the current job.\n"
" job list\n"
" Print details of all jobs in the workshop.\n"
" job item-material <item-idx> <material> [submaterial]\n"
" job item-material <item-idx> <material[:subtoken]>\n"
" Replace the exact material id in the job item.\n"
)
);
@ -249,21 +249,6 @@ static command_result job_material(Core * c, vector <string> & parameters)
/* job-duplicate implementation */
static df::job *clone_job(df::job *job)
{
df::job *pnew = cloneJobStruct(job);
pnew->id = (*job_next_id)++;
// Link the job into the global list
pnew->list_link = new df::job_list_link();
pnew->list_link->item = pnew;
linked_list_append(&world->job_list, pnew->list_link);
return pnew;
}
static command_result job_duplicate(Core * c, vector <string> & parameters)
{
if (!parameters.empty())
@ -287,10 +272,10 @@ static command_result job_duplicate(Core * c, vector <string> & parameters)
}
// Actually clone
df::job *pnew = clone_job(job);
df::job *pnew = cloneJobStruct(job);
int pos = ++*ui_workshop_job_cursor;
building->jobs.insert(building->jobs.begin()+pos, pnew);
linkJobIntoWorld(pnew);
vector_insert_at(building->jobs, ++*ui_workshop_job_cursor, pnew);
return CR_OK;
}
@ -336,9 +321,8 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
df::job_item *item = job->job_items[v-1];
std::string subtoken = (parameters.size()>3 ? parameters[3] : "");
MaterialInfo info;
if (!info.find(parameters[2], subtoken)) {
if (!info.find(parameters[2])) {
c->con.printerr("Could not find the specified material.\n");
return CR_FAILURE;
}

@ -98,18 +98,6 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev
/*******************************/
static df::building *getJobHolder(df::job *job)
{
for (unsigned i = 0; i < job->references.size(); i++)
{
VIRTUAL_CAST_VAR(ref, df::general_ref_building_holderst, job->references[i]);
if (ref)
return ref->getBuilding();
}
return NULL;
};
struct ProtectedJob {
int id;
int building_id;
@ -253,8 +241,6 @@ static int *find_protected_id_slot(Core *c, int key)
if (key == -1) {
protected_cfg.push_back(c->getWorld()->AddPersistentData("workflow/protected-jobs"));
PersistentDataItem &item = protected_cfg.back();
for (int j = 0; j < PersistentDataItem::NumInts; j++)
item.ival(j) = -1;
return &item.ival(0);
}
@ -408,7 +394,7 @@ DFhackCExport command_result plugin_onupdate(Core* c)
{
for (int i = pending_recover.size()-1; i >= 0; i--)
if (recover_job(c, pending_recover[i]))
pending_recover.erase(pending_recover.begin()+i);
vector_erase_at(pending_recover, i);
check_lost_jobs(c);
}