2014-06-08 07:17:48 +02:00
|
|
|
/* vi: set ts=2:
|
|
|
|
+-------------------+
|
|
|
|
| | Enno Rehling <enno@eressea.de>
|
|
|
|
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
|
|
| (c) 1998 - 2004 | Katja Zedel <katze@felidae.kn-bremen.de>
|
|
|
|
| | Henning Peters <faroul@beyond.kn-bremen.de>
|
|
|
|
+-------------------+
|
|
|
|
|
|
|
|
This program may not be used, modified or distributed
|
|
|
|
without prior permission by the authors of Eressea.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <platform.h>
|
|
|
|
#include <kernel/config.h>
|
|
|
|
#include "jsonconf.h"
|
|
|
|
|
|
|
|
/* kernel includes */
|
|
|
|
#include "building.h"
|
2014-06-16 20:30:23 +02:00
|
|
|
#include "direction.h"
|
|
|
|
#include "keyword.h"
|
2014-06-08 07:17:48 +02:00
|
|
|
#include "equipment.h"
|
|
|
|
#include "item.h"
|
2014-06-09 18:54:48 +02:00
|
|
|
#include "messages.h"
|
2014-06-08 07:17:48 +02:00
|
|
|
#include "race.h"
|
|
|
|
#include "region.h"
|
|
|
|
#include "resources.h"
|
|
|
|
#include "ship.h"
|
|
|
|
#include "terrain.h"
|
|
|
|
#include "skill.h"
|
|
|
|
#include "spell.h"
|
|
|
|
#include "spellbook.h"
|
|
|
|
#include "calendar.h"
|
|
|
|
|
|
|
|
/* util includes */
|
|
|
|
#include <util/attrib.h>
|
|
|
|
#include <util/bsdstring.h>
|
|
|
|
#include <util/crmessage.h>
|
|
|
|
#include <util/functions.h>
|
|
|
|
#include <util/language.h>
|
|
|
|
#include <util/log.h>
|
|
|
|
#include <util/message.h>
|
|
|
|
#include <util/nrmessage.h>
|
|
|
|
#include <util/xml.h>
|
|
|
|
|
|
|
|
/* external libraries */
|
|
|
|
#include <cJSON.h>
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
#include <assert.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <limits.h>
|
2014-06-13 17:04:06 +02:00
|
|
|
#include <stdlib.h>
|
2014-06-08 07:17:48 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static int json_flags(cJSON *json, const char *flags[]) {
|
2014-06-17 07:43:40 +02:00
|
|
|
cJSON *entry;
|
|
|
|
int result = 0;
|
|
|
|
assert(json->type==cJSON_Array);
|
|
|
|
for (entry=json->child;entry;entry=entry->next) {
|
|
|
|
if (entry->type == cJSON_String) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; flags[i]; ++i) {
|
|
|
|
if (strcmp(flags[i], entry->valuestring)==0) {
|
|
|
|
result |= (1<<i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_requirements(cJSON *json, requirement **matp) {
|
2014-06-13 17:04:06 +02:00
|
|
|
cJSON *child;
|
2014-07-01 04:21:28 +02:00
|
|
|
int i;
|
|
|
|
requirement *mat = calloc(sizeof(requirement), 1+cJSON_GetArraySize(json));
|
|
|
|
for (i=0,child=json->child;child;child=child->next,++i) {
|
|
|
|
mat[i].number = child->valueint;
|
|
|
|
mat[i].rtype = rt_get_or_create(child->string);
|
|
|
|
}
|
|
|
|
*matp = mat;
|
|
|
|
}
|
|
|
|
|
2014-07-05 06:48:17 +02:00
|
|
|
static void json_maintenance_i(cJSON *json, maintenance *mt) {
|
|
|
|
cJSON *child;
|
|
|
|
for (child = json->child; child; child = child->next) {
|
|
|
|
switch (child->type) {
|
|
|
|
case cJSON_Number:
|
|
|
|
if (strcmp(child->string, "amount") == 0) {
|
|
|
|
mt->number = child->valueint;
|
|
|
|
}
|
|
|
|
else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("maintenance contains unknown attribute %s", child->string);
|
2014-07-05 06:48:17 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case cJSON_String:
|
|
|
|
if (strcmp(child->string, "type") == 0) {
|
|
|
|
mt->rtype = rt_get_or_create(child->valuestring);
|
|
|
|
}
|
|
|
|
else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("maintenance contains unknown attribute %s", child->string);
|
2014-07-05 06:48:17 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case cJSON_Array:
|
|
|
|
if (strcmp(child->string, "flags") == 0) {
|
|
|
|
const char * flags[] = { "variable", "required", 0 };
|
|
|
|
mt->flags = json_flags(child, flags);
|
|
|
|
}
|
|
|
|
else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("maintenance contains unknown array %s", child->string);
|
2014-07-05 06:48:17 +02:00
|
|
|
}
|
2014-07-06 03:21:20 +02:00
|
|
|
break;
|
2014-07-05 06:48:17 +02:00
|
|
|
default:
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("maintenance contains unknown attribute %s", child->string);
|
2014-07-05 06:48:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void json_maintenance(cJSON *json, maintenance **mtp) {
|
|
|
|
cJSON *child;
|
|
|
|
maintenance *mt;
|
|
|
|
int i, size = 1;
|
|
|
|
|
|
|
|
if (json->type == cJSON_Array) {
|
|
|
|
size = cJSON_GetArraySize(json);
|
|
|
|
}
|
|
|
|
else if (json->type != cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("maintenance is not a json object or array (%d)", json->type);
|
2014-07-05 06:48:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
*mtp = mt = (struct maintenance *) calloc(sizeof(struct maintenance), size + 1);
|
|
|
|
if (json->type == cJSON_Array) {
|
|
|
|
for (i = 0, child = json->child; child; child = child->next, ++i) {
|
|
|
|
if (child->type == cJSON_Object) {
|
|
|
|
json_maintenance_i(child, mt+i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
json_maintenance_i(json, mt);
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_construction(cJSON *json, construction **consp) {
|
|
|
|
cJSON *child;
|
|
|
|
if (json->type==cJSON_Array) {
|
|
|
|
int size = 0;
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
construction *cons = 0;
|
|
|
|
json_construction(child, &cons);
|
|
|
|
if (cons) {
|
|
|
|
cons->maxsize -= size;
|
|
|
|
size += cons->maxsize + size;
|
|
|
|
*consp = cons;
|
|
|
|
consp = &cons->improvement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (json->type != cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("building %s is not a json object: %d", json->string, json->type);
|
2014-06-13 17:04:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
construction * cons = (construction *)calloc(sizeof(construction), 1);
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
switch(child->type) {
|
2014-07-01 04:21:28 +02:00
|
|
|
case cJSON_Object:
|
|
|
|
if (strcmp(child->string, "materials")==0) {
|
|
|
|
json_requirements(child, &cons->materials);
|
|
|
|
}
|
|
|
|
break;
|
2014-06-13 17:04:06 +02:00
|
|
|
case cJSON_Number:
|
|
|
|
if (strcmp(child->string, "maxsize")==0) {
|
|
|
|
cons->maxsize = child->valueint;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "reqsize")==0) {
|
|
|
|
cons->reqsize = child->valueint;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "minskill")==0) {
|
|
|
|
cons->minskill = child->valueint;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("building %s contains unknown attribute %s", json->string, child->string);
|
2014-06-13 17:04:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
*consp = cons;
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_terrain(cJSON *json, terrain_type *ter) {
|
2014-06-14 02:36:05 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("terrain %s is not a json object: %d", json->string, json->type);
|
2014-06-14 02:36:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
2014-06-17 07:19:19 +02:00
|
|
|
switch(child->type) {
|
|
|
|
case cJSON_Array:
|
|
|
|
if (strcmp(child->string, "flags")==0) {
|
|
|
|
const char * flags[] = {
|
|
|
|
"land", "sea", "forest", "arctic", "cavalry", "forbidden", "sail", "fly", "swim", "walk", 0
|
|
|
|
};
|
2014-06-17 07:43:40 +02:00
|
|
|
ter->flags = json_flags(child, flags);
|
2014-06-17 07:19:19 +02:00
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("terrain %s contains unknown attribute %s", json->string, child->string);
|
2014-06-17 07:19:19 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("terrain %s contains unknown attribute %s", json->string, child->string);
|
2014-06-17 07:19:19 +02:00
|
|
|
}
|
2014-06-14 02:36:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_building(cJSON *json, building_type *bt) {
|
2014-06-13 07:14:07 +02:00
|
|
|
cJSON *child;
|
2014-07-28 14:27:30 +02:00
|
|
|
const char *flags[] = {
|
|
|
|
"nodestroy", "nobuild", "unique", "decay", "dynamic", "magic", "oneperturn", "namechange", 0
|
|
|
|
};
|
|
|
|
if (json->type != cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("building %s is not a json object: %d", json->string, json->type);
|
2014-06-13 07:14:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
2014-06-14 02:36:05 +02:00
|
|
|
switch(child->type) {
|
2014-07-01 04:21:28 +02:00
|
|
|
case cJSON_Array:
|
2014-07-05 06:48:17 +02:00
|
|
|
if (strcmp(child->string, "construction") == 0) {
|
2014-07-01 04:21:28 +02:00
|
|
|
json_construction(child, &bt->construction);
|
|
|
|
}
|
2014-07-05 06:48:17 +02:00
|
|
|
else if (strcmp(child->string, "maintenance") == 0) {
|
|
|
|
json_maintenance(child, &bt->maintenance);
|
|
|
|
}
|
2014-07-28 14:27:30 +02:00
|
|
|
else if (strcmp(child->string, "flags") == 0) {
|
|
|
|
json_flags(child, flags);
|
|
|
|
}
|
2014-07-01 04:21:28 +02:00
|
|
|
break;
|
2014-06-14 02:36:05 +02:00
|
|
|
case cJSON_Object:
|
|
|
|
if (strcmp(child->string, "construction")==0) {
|
|
|
|
json_construction(child, &bt->construction);
|
|
|
|
}
|
2014-07-05 06:48:17 +02:00
|
|
|
else if (strcmp(child->string, "maintenance") == 0) {
|
|
|
|
json_maintenance(child, &bt->maintenance);
|
|
|
|
}
|
2014-06-14 02:36:05 +02:00
|
|
|
break;
|
2014-06-29 01:55:28 +02:00
|
|
|
case cJSON_String:
|
|
|
|
if (strcmp(child->string, "name")==0) {
|
|
|
|
bt->name = (const char *(*)(const struct building_type *,
|
|
|
|
const struct building *, int))get_function(child->valuestring);
|
|
|
|
break;
|
|
|
|
}
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("building %s contains unknown attribute %s", json->string, child->string);
|
2014-06-29 01:55:28 +02:00
|
|
|
break;
|
2014-06-14 02:36:05 +02:00
|
|
|
default:
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("building %s contains unknown attribute %s", json->string, child->string);
|
2014-06-14 02:36:05 +02:00
|
|
|
}
|
2014-06-13 07:14:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_item(cJSON *json, item_type *itype) {
|
2014-06-25 07:44:05 +02:00
|
|
|
cJSON *child;
|
2014-06-25 17:00:09 +02:00
|
|
|
const char *flags[] = {
|
|
|
|
"herb", "cursed", "nodrop", "big", "animal", "vehicle", 0
|
|
|
|
};
|
2014-06-25 07:44:05 +02:00
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("ship %s is not a json object: %d", json->string, json->type);
|
2014-06-25 07:44:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
switch(child->type) {
|
2014-06-25 17:00:09 +02:00
|
|
|
case cJSON_Number:
|
|
|
|
if (strcmp(child->string, "weight")==0) {
|
|
|
|
itype->weight = child->valueint;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcmp(child->string, "capacity")==0) {
|
|
|
|
itype->capacity = child->valueint;
|
|
|
|
break;
|
|
|
|
}
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("item %s contains unknown attribute %s", json->string, child->string);
|
2014-06-25 17:00:09 +02:00
|
|
|
break;
|
|
|
|
case cJSON_Array:
|
|
|
|
if (strcmp(child->string, "flags")==0) {
|
|
|
|
itype->flags = json_flags(child, flags);
|
|
|
|
break;
|
|
|
|
}
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("item %s contains unknown attribute %s", json->string, child->string);
|
2014-06-25 07:44:05 +02:00
|
|
|
case cJSON_Object:
|
|
|
|
default:
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("item %s contains unknown attribute %s", json->string, child->string);
|
2014-06-25 07:44:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_ship(cJSON *json, ship_type *st) {
|
2014-06-18 06:33:42 +02:00
|
|
|
cJSON *child, *iter;
|
2014-06-13 07:14:07 +02:00
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("ship %s is not a json object: %d", json->string, json->type);
|
2014-06-13 07:14:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
2014-06-18 06:33:42 +02:00
|
|
|
int i;
|
2014-06-13 17:04:06 +02:00
|
|
|
switch(child->type) {
|
|
|
|
case cJSON_Object:
|
|
|
|
if (strcmp(child->string, "construction")==0) {
|
|
|
|
json_construction(child, &st->construction);
|
2014-06-17 07:19:19 +02:00
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("ship %s contains unknown attribute %s", json->string, child->string);
|
2014-06-17 07:19:19 +02:00
|
|
|
}
|
|
|
|
break;
|
2014-06-18 06:33:42 +02:00
|
|
|
case cJSON_Array:
|
|
|
|
st->coasts = (const terrain_type **)
|
|
|
|
malloc(sizeof(terrain_type *) * (1+cJSON_GetArraySize(child)));
|
|
|
|
for (i=0,iter=child->child;iter;iter=iter->next) {
|
|
|
|
if (iter->type==cJSON_String) {
|
|
|
|
terrain_type *ter = get_or_create_terrain(iter->valuestring);
|
|
|
|
if (ter) {
|
|
|
|
st->coasts[i++] = ter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
st->coasts[i] = 0;
|
|
|
|
break;
|
2014-06-17 07:19:19 +02:00
|
|
|
case cJSON_Number:
|
|
|
|
if (strcmp(child->string, "range")==0) {
|
|
|
|
st->range = child->valueint;
|
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("ship %s contains unknown attribute %s", json->string, child->string);
|
2014-06-13 17:04:06 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("ship %s contains unknown attribute %s", json->string, child->string);
|
2014-06-13 17:04:06 +02:00
|
|
|
}
|
2014-06-13 07:14:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_race(cJSON *json, race *rc) {
|
2014-06-08 07:17:48 +02:00
|
|
|
cJSON *child;
|
2014-06-17 07:43:40 +02:00
|
|
|
const char *flags[] = {
|
2014-07-06 04:29:12 +02:00
|
|
|
"npc", "killpeasants", "scarepeasants",
|
|
|
|
"nosteal", "moverandom", "cannotmove",
|
2014-06-17 07:43:40 +02:00
|
|
|
"learn", "fly", "swim", "walk", "nolearn",
|
|
|
|
"noteach", "horse", "desert",
|
|
|
|
"illusionary", "absorbpeasants", "noheal",
|
|
|
|
"noweapons", "shapeshift", "", "undead", "dragon",
|
2014-07-06 09:29:52 +02:00
|
|
|
"coastal", "", "cansail", 0
|
2014-06-17 07:43:40 +02:00
|
|
|
};
|
2014-07-06 09:53:15 +02:00
|
|
|
const char *ecflags[] = {
|
|
|
|
"", "giveitem", "giveperson",
|
|
|
|
"giveunit", "getitem", 0
|
|
|
|
};
|
|
|
|
if (json->type != cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("race %s is not a json object: %d", json->string, json->type);
|
2014-06-08 07:17:48 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
switch(child->type) {
|
|
|
|
case cJSON_String:
|
|
|
|
if (strcmp(child->string, "damage")==0) {
|
|
|
|
rc->def_damage = _strdup(child->valuestring);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case cJSON_Number:
|
|
|
|
if (strcmp(child->string, "magres")==0) {
|
|
|
|
rc->magres = (float)child->valuedouble;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "maxaura")==0) {
|
|
|
|
rc->maxaura = (float)child->valuedouble;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "regaura")==0) {
|
|
|
|
rc->regaura = (float)child->valuedouble;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "speed")==0) {
|
|
|
|
rc->speed = (float)child->valuedouble;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "recruitcost")==0) {
|
|
|
|
rc->recruitcost = child->valueint;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "maintenance")==0) {
|
|
|
|
rc->maintenance = child->valueint;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "weight")==0) {
|
|
|
|
rc->weight = child->valueint;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "capacity")==0) {
|
|
|
|
rc->capacity = child->valueint;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "hp")==0) {
|
|
|
|
rc->hitpoints = child->valueint;
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "ac")==0) {
|
|
|
|
rc->armor = child->valueint;
|
|
|
|
}
|
|
|
|
// TODO: studyspeed (orcs only)
|
|
|
|
break;
|
2014-06-17 07:43:40 +02:00
|
|
|
case cJSON_Array:
|
|
|
|
if (strcmp(child->string, "flags")==0) {
|
|
|
|
rc->flags = json_flags(child, flags);
|
2014-07-06 09:53:15 +02:00
|
|
|
rc->ec_flags = json_flags(child, ecflags);
|
2014-06-08 07:17:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_terrains(cJSON *json) {
|
2014-06-14 02:36:05 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("terrains is not a json object: %d", json->type);
|
2014-06-14 02:36:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
2014-06-16 06:19:47 +02:00
|
|
|
json_terrain(child, get_or_create_terrain(child->string));
|
2014-06-14 02:36:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_buildings(cJSON *json) {
|
2014-06-13 07:14:07 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("buildings is not a json object: %d", json->type);
|
2014-06-13 07:14:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
json_building(child, bt_get_or_create(child->string));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-03 06:15:22 +02:00
|
|
|
static void json_spells(cJSON *json) {
|
|
|
|
cJSON *child;
|
|
|
|
if (json->type != cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("spells is not a json object: %d", json->type);
|
2014-07-03 06:15:22 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child = json->child; child; child = child->next) {
|
|
|
|
if (child->type == cJSON_Object) {
|
|
|
|
spell *sp;
|
|
|
|
cJSON * item = cJSON_GetObjectItem(child, "index");
|
|
|
|
sp = create_spell(child->string, item ? item->valueint : 0);
|
|
|
|
for (item = child->child; item; item = item->next) {
|
|
|
|
if (strcmp(item->string, "index") == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (strcmp(item->string, "cast") == 0) {
|
|
|
|
sp->cast = (spell_f)get_function(item->valuestring);
|
|
|
|
}
|
|
|
|
else if (strcmp(item->string, "fumble") == 0) {
|
|
|
|
sp->fumble = (fumble_f)get_function(item->valuestring);
|
|
|
|
}
|
|
|
|
else if (strcmp(item->string, "syntax") == 0) {
|
|
|
|
sp->syntax = _strdup(item->valuestring);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_items(cJSON *json) {
|
2014-06-25 07:44:05 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("items is not a json object: %d", json->type);
|
2014-06-25 07:44:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
resource_type *rtype = rt_get_or_create(child->string);
|
|
|
|
item_type *itype = rtype->itype;
|
|
|
|
if (!itype) {
|
|
|
|
rtype->itype = itype = it_get_or_create(rtype);
|
|
|
|
}
|
|
|
|
json_item(child, itype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_ships(cJSON *json) {
|
2014-06-13 07:14:07 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("ships is not a json object: %d", json->type);
|
2014-06-13 07:14:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
json_ship(child, st_get_or_create(child->string));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_locale(cJSON *json, struct locale *lang) {
|
2014-06-28 19:37:40 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("strings is not a json object: %d", json->type);
|
2014-06-28 19:37:40 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
if (child->type==cJSON_String) {
|
|
|
|
locale_setstring(lang, child->string, child->valuestring);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_strings(cJSON *json) {
|
2014-06-28 19:37:40 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("strings is not a json object: %d", json->type);
|
2014-06-28 19:37:40 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
2014-10-14 22:57:02 +02:00
|
|
|
if (child->type==cJSON_Object) {
|
2014-06-28 19:37:40 +02:00
|
|
|
struct locale *lang = get_or_create_locale(child->string);
|
|
|
|
json_locale(child, lang);
|
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("strings for locale `%s` are not a json object: %d", child->string, child->type);
|
2014-06-28 19:37:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-16 07:17:08 +02:00
|
|
|
static void json_direction(cJSON *json, struct locale *lang) {
|
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("directions for locale `%s` not a json object: %d", locale_name(lang), json->type);
|
2014-06-16 07:17:08 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
direction_t dir = finddirection(child->string);
|
|
|
|
if (dir!=NODIRECTION) {
|
|
|
|
if (child->type==cJSON_String) {
|
|
|
|
init_direction(lang, dir, child->valuestring);
|
|
|
|
}
|
|
|
|
else if (child->type==cJSON_Array) {
|
|
|
|
cJSON *entry;
|
|
|
|
for (entry=child->child;entry;entry=entry->next) {
|
|
|
|
init_direction(lang, dir, entry->valuestring);
|
|
|
|
}
|
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("invalid type %d for direction `%s`", child->type, child->string);
|
2014-06-16 07:17:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_directions(cJSON *json) {
|
2014-06-16 07:17:08 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("directions is not a json object: %d", json->type);
|
2014-06-16 07:17:08 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
struct locale * lang = get_or_create_locale(child->string);
|
|
|
|
json_direction(child, lang);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-21 17:53:14 +02:00
|
|
|
static void json_skill(cJSON *json, struct locale *lang) {
|
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("skill for locale `%s` not a json object: %d", locale_name(lang), json->type);
|
2014-06-21 17:53:14 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
skill_t sk = findskill(child->string);
|
|
|
|
if (sk!=NOSKILL) {
|
|
|
|
if (child->type==cJSON_String) {
|
|
|
|
init_skill(lang, sk, child->valuestring);
|
|
|
|
locale_setstring(lang, mkname("skill", skillnames[sk]), child->valuestring);
|
|
|
|
}
|
|
|
|
else if (child->type==cJSON_Array) {
|
|
|
|
cJSON *entry;
|
|
|
|
for (entry=child->child;entry;entry=entry->next) {
|
|
|
|
init_skill(lang, sk, entry->valuestring);
|
2014-10-14 22:57:02 +02:00
|
|
|
if (entry==child->child) {
|
2014-06-21 17:53:14 +02:00
|
|
|
locale_setstring(lang, mkname("skill", skillnames[sk]), entry->valuestring);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("invalid type %d for skill `%s`", child->type, child->string);
|
2014-06-21 17:53:14 +02:00
|
|
|
}
|
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("unknown skill `%s` for locale `%s`", child->string, locale_name(lang));
|
2014-06-21 17:53:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-16 20:30:23 +02:00
|
|
|
static void json_keyword(cJSON *json, struct locale *lang) {
|
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("keywords for locale `%s` not a json object: %d", locale_name(lang), json->type);
|
2014-06-16 20:30:23 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
keyword_t kwd = findkeyword(child->string);
|
|
|
|
if (kwd!=NOKEYWORD) {
|
|
|
|
if (child->type==cJSON_String) {
|
|
|
|
init_keyword(lang, kwd, child->valuestring);
|
2014-06-17 05:41:08 +02:00
|
|
|
locale_setstring(lang, mkname("keyword", keywords[kwd]), child->valuestring);
|
2014-06-16 20:30:23 +02:00
|
|
|
}
|
|
|
|
else if (child->type==cJSON_Array) {
|
|
|
|
cJSON *entry;
|
|
|
|
for (entry=child->child;entry;entry=entry->next) {
|
|
|
|
init_keyword(lang, kwd, entry->valuestring);
|
2014-10-14 22:57:02 +02:00
|
|
|
if (entry==child->child) {
|
2014-06-17 05:41:08 +02:00
|
|
|
locale_setstring(lang, mkname("keyword", keywords[kwd]), entry->valuestring);
|
|
|
|
}
|
2014-06-16 20:30:23 +02:00
|
|
|
}
|
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("invalid type %d for keyword `%s`", child->type, child->string);
|
2014-06-16 20:30:23 +02:00
|
|
|
}
|
2014-06-17 04:12:55 +02:00
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("unknown keyword `%s` for locale `%s`", child->string, locale_name(lang));
|
2014-06-16 20:30:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_skills(cJSON *json) {
|
2014-06-21 17:53:14 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("skills is not a json object: %d", json->type);
|
2014-06-21 17:53:14 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
struct locale * lang = get_or_create_locale(child->string);
|
|
|
|
json_skill(child, lang);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_keywords(cJSON *json) {
|
2014-06-16 20:30:23 +02:00
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("keywords is not a json object: %d", json->type);
|
2014-06-16 20:30:23 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
struct locale * lang = get_or_create_locale(child->string);
|
|
|
|
json_keyword(child, lang);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 04:21:28 +02:00
|
|
|
static void json_races(cJSON *json) {
|
2014-06-08 07:17:48 +02:00
|
|
|
cJSON *child;
|
2014-10-29 07:50:06 +01:00
|
|
|
if (json->type != cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("races is not a json object: %d", json->type);
|
2014-06-08 07:17:48 +02:00
|
|
|
return;
|
|
|
|
}
|
2014-10-29 07:50:06 +01:00
|
|
|
for (child = json->child; child; child = child->next) {
|
2014-06-13 07:14:07 +02:00
|
|
|
json_race(child, rc_get_or_create(child->string));
|
2014-06-08 07:17:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-29 07:50:06 +01:00
|
|
|
static void json_configs(cJSON *json) {
|
|
|
|
cJSON *child;
|
|
|
|
if (json->type != cJSON_Array) {
|
|
|
|
log_error("config is not a json array: %d", json->type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (child = json->child; child; child = child->next) {
|
|
|
|
cJSON *config;
|
|
|
|
char *data;
|
|
|
|
FILE *F = fopen(child->valuestring, "rt");
|
|
|
|
if (F) {
|
|
|
|
size_t sz;
|
|
|
|
fseek(F, 0, SEEK_END);
|
|
|
|
sz = ftell(F);
|
|
|
|
rewind(F);
|
|
|
|
data = malloc(sz);
|
|
|
|
fread(data, 1, sz, F);
|
|
|
|
fclose(F);
|
|
|
|
config = cJSON_Parse(data);
|
|
|
|
free(data);
|
|
|
|
json_config(config);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-08 07:17:48 +02:00
|
|
|
void json_config(cJSON *json) {
|
|
|
|
cJSON *child;
|
|
|
|
if (json->type!=cJSON_Object) {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("config is not a json object: %d", json->type);
|
2014-06-08 07:17:48 +02:00
|
|
|
return;
|
|
|
|
}
|
2014-06-14 02:36:05 +02:00
|
|
|
for (child=json->child;child;child=child->next) {
|
|
|
|
if (strcmp(child->string, "races")==0) {
|
|
|
|
json_races(child);
|
|
|
|
}
|
2014-10-29 07:50:06 +01:00
|
|
|
else if (strcmp(child->string, "items") == 0) {
|
2014-06-25 07:54:10 +02:00
|
|
|
json_items(child);
|
|
|
|
}
|
2014-10-29 07:50:06 +01:00
|
|
|
else if (strcmp(child->string, "config") == 0) {
|
|
|
|
json_configs(child);
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "ships") == 0) {
|
2014-06-14 02:36:05 +02:00
|
|
|
json_ships(child);
|
|
|
|
}
|
2014-06-28 19:37:40 +02:00
|
|
|
else if (strcmp(child->string, "strings")==0) {
|
|
|
|
json_strings(child);
|
|
|
|
}
|
2014-06-16 07:17:08 +02:00
|
|
|
else if (strcmp(child->string, "directions")==0) {
|
|
|
|
json_directions(child);
|
|
|
|
}
|
2014-06-16 20:30:23 +02:00
|
|
|
else if (strcmp(child->string, "keywords")==0) {
|
|
|
|
json_keywords(child);
|
|
|
|
}
|
2014-06-21 17:53:14 +02:00
|
|
|
else if (strcmp(child->string, "skills")==0) {
|
|
|
|
json_skills(child);
|
|
|
|
}
|
2014-07-03 06:15:22 +02:00
|
|
|
else if (strcmp(child->string, "buildings") == 0) {
|
2014-06-14 02:36:05 +02:00
|
|
|
json_buildings(child);
|
|
|
|
}
|
2014-07-03 06:15:22 +02:00
|
|
|
else if (strcmp(child->string, "spells") == 0) {
|
|
|
|
json_spells(child);
|
|
|
|
}
|
|
|
|
else if (strcmp(child->string, "terrains") == 0) {
|
2014-06-14 02:36:05 +02:00
|
|
|
json_terrains(child);
|
|
|
|
} else {
|
2014-08-11 12:02:16 +02:00
|
|
|
log_error("config contains unknown attribute %s", child->string);
|
2014-06-14 02:36:05 +02:00
|
|
|
}
|
2014-06-13 07:14:07 +02:00
|
|
|
}
|
2014-07-17 00:45:45 +02:00
|
|
|
init_locales();
|
2014-06-08 07:17:48 +02:00
|
|
|
}
|
2014-06-09 18:54:48 +02:00
|
|
|
|