forked from github/server
162 lines
4.4 KiB
C
162 lines
4.4 KiB
C
#include <platform.h>
|
|
#include <kernel/config.h>
|
|
#include "archetype.h"
|
|
|
|
/* kernel includes */
|
|
#include <kernel/equipment.h>
|
|
#include <kernel/building.h>
|
|
#include <kernel/xmlkernel.h>
|
|
#include <kernel/xmlreader.h>
|
|
|
|
/* util includes */
|
|
#include <util/attrib.h>
|
|
#include <util/umlaut.h>
|
|
#include <util/language.h>
|
|
#include <util/xml.h>
|
|
#include <util/functions.h>
|
|
|
|
/* libxml includes */
|
|
#include <libxml/tree.h>
|
|
#include <libxml/xpath.h>
|
|
#include <libxml/encoding.h>
|
|
|
|
/* libc includes */
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
static struct archetype *archetypes;
|
|
|
|
struct attrib_type at_recruit = {
|
|
"recruit", NULL, NULL, NULL, NULL, NULL, ATF_UNIQUE
|
|
};
|
|
|
|
const struct archetype *find_archetype(const char *s, const struct locale *lang)
|
|
{
|
|
void **tokens = get_translations(lang, UT_ARCHETYPES);
|
|
variant token;
|
|
|
|
if (tokens && findtoken(*tokens, s, &token) == E_TOK_SUCCESS) {
|
|
return (const struct archetype *)token.v;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void register_archetype(archetype * arch)
|
|
{
|
|
arch->next = archetypes;
|
|
archetypes = arch;
|
|
}
|
|
|
|
void init_archetypes(void)
|
|
{
|
|
const struct locale *lang = locales;
|
|
for (; lang; lang = nextlocale(lang)) {
|
|
variant var;
|
|
archetype *arch = archetypes;
|
|
void *tokens = get_translations(lang, UT_ARCHETYPES);
|
|
for (; arch; arch = arch->next) {
|
|
const char *s1, *s2;
|
|
var.v = arch;
|
|
|
|
s1 = LOC(lang, arch->name[0]);
|
|
addtoken(tokens, s1, var);
|
|
s2 = LOC(lang, arch->name[1]);
|
|
if (strcmp(s2, s1) != 0) {
|
|
addtoken(tokens, s2, var);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int parse_archetypes(xmlDocPtr doc)
|
|
{
|
|
char zName[64];
|
|
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
|
xmlXPathObjectPtr result =
|
|
xmlXPathEvalExpression(BAD_CAST "/eressea/archetypes/archetype", xpath);
|
|
xmlNodeSetPtr nodes = result->nodesetval;
|
|
|
|
xmlChar *propValue;
|
|
if (nodes) {
|
|
int i;
|
|
for (i = 0; i != nodes->nodeNr; ++i) {
|
|
xmlNodePtr node = nodes->nodeTab[i];
|
|
xmlNodePtr child;
|
|
archetype *arch = calloc(1, sizeof(archetype));
|
|
xmlXPathObjectPtr sub;
|
|
|
|
propValue = xmlGetProp(node, BAD_CAST "name");
|
|
assert(propValue != NULL);
|
|
arch->name[0] = _strdup((const char *)propValue);
|
|
sprintf(zName, "%s_p", arch->name[0]);
|
|
arch->name[1] = _strdup(zName);
|
|
xmlFree(propValue);
|
|
|
|
propValue = xmlGetProp(node, BAD_CAST "equip");
|
|
if (propValue != NULL) {
|
|
arch->equip = get_equipment((const char *)propValue);
|
|
xmlFree(propValue);
|
|
} else {
|
|
arch->equip = get_equipment(arch->name[0]);
|
|
}
|
|
|
|
propValue = xmlGetProp(node, BAD_CAST "building");
|
|
if (propValue != NULL) {
|
|
arch->btype = bt_find((const char *)propValue);
|
|
xmlFree(propValue);
|
|
}
|
|
|
|
arch->size = xml_ivalue(node, "cost", 0);
|
|
|
|
for (child = node->children; child; child = child->next) {
|
|
if (strcmp((const char *)child->name, "function") == 0) {
|
|
xmlChar *propName = xmlGetProp(child, BAD_CAST "name");
|
|
xmlChar *propValue = xmlGetProp(child, BAD_CAST "value");
|
|
if (strcmp((const char *)propName, "create")) {
|
|
pf_generic foo = get_function((const char *)propValue);
|
|
arch->exec = (archetype_function) foo;
|
|
}
|
|
xmlFree(propValue);
|
|
xmlFree(propName);
|
|
}
|
|
}
|
|
xpath->node = node;
|
|
sub = xmlXPathEvalExpression(BAD_CAST "allow|deny", xpath);
|
|
if (sub->nodesetval && sub->nodesetval->nodeNr) {
|
|
int k;
|
|
arch->rules = calloc(sub->nodesetval->nodeNr + 1, sizeof(rule));
|
|
for (k = 0; k != sub->nodesetval->nodeNr; ++k) {
|
|
xmlNodePtr rule = sub->nodesetval->nodeTab[k];
|
|
arch->rules[k].allow = (rule->name[0] == 'a');
|
|
|
|
propValue = xmlGetProp(rule, BAD_CAST "property");
|
|
arch->rules[k].property = _strdup((const char *)propValue);
|
|
xmlFree(propValue);
|
|
|
|
propValue = xmlGetProp(rule, BAD_CAST "value");
|
|
arch->rules[k].value = _strdup((const char *)propValue);
|
|
xmlFree(propValue);
|
|
}
|
|
}
|
|
xmlXPathFreeObject(sub);
|
|
|
|
xpath->node = node;
|
|
sub = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
|
if (sub->nodesetval) {
|
|
xml_readconstruction(xpath, sub->nodesetval, &arch->ctype);
|
|
}
|
|
xmlXPathFreeObject(sub);
|
|
register_archetype(arch);
|
|
}
|
|
}
|
|
xmlXPathFreeObject(result);
|
|
|
|
xmlXPathFreeContext(xpath);
|
|
return 0;
|
|
}
|
|
|
|
void register_archetypes(void)
|
|
{
|
|
xml_register_callback(parse_archetypes);
|
|
}
|