From 24dc006e43b1f71998cc16bde6f60a0bd3ed1dab Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 13 Jun 2014 17:36:05 -0700 Subject: [PATCH] fix json config for terrains, some other stuff. --- scripts/tests/config.lua | 2 ++ src/bind_ship.c | 2 +- src/kernel/building.c | 6 ++++ src/kernel/building.h | 1 + src/kernel/jsonconf.c | 62 +++++++++++++++++++++++++++++--------- src/kernel/jsonconf_test.c | 46 +++++++++++++++++++++++++++- src/kernel/terrain.c | 51 ++++++++++++++++++++----------- src/kernel/terrain.h | 4 +-- src/tests.c | 29 ++++++++---------- 9 files changed, 151 insertions(+), 52 deletions(-) diff --git a/scripts/tests/config.lua b/scripts/tests/config.lua index 9e0beae01..b24da72bc 100644 --- a/scripts/tests/config.lua +++ b/scripts/tests/config.lua @@ -8,6 +8,7 @@ end function test_read_race() local f + eressea.free_game() f = faction.create("orc@example.com", "orc", "en") assert_equal(nil, f) assert_not_nil(eressea.config) @@ -18,6 +19,7 @@ end function test_read_ship() local s + eressea.free_game() s = ship.create(nil, "boat") assert_equal(nil, s) assert_not_nil(eressea.config) diff --git a/src/bind_ship.c b/src/bind_ship.c index 820c437ac..88a9427f9 100644 --- a/src/bind_ship.c +++ b/src/bind_ship.c @@ -127,7 +127,7 @@ static int tolua_ship_create(lua_State * L) const ship_type *stype = st_find(sname); if (stype) { ship *sh = new_ship(stype, r, default_locale); - sh->size = stype->construction->maxsize; + sh->size = stype->construction ? stype->construction->maxsize : 1; tolua_pushusertype(L, (void *)sh, TOLUA_CAST "ship"); return 1; } else { diff --git a/src/kernel/building.c b/src/kernel/building.c index 437f6f6a1..8188cbb7a 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -159,6 +159,12 @@ void bt_register(building_type * type) ql_push(&buildingtypes, (void *)type); } +void free_buildingtypes(void) { + ql_foreach(buildingtypes, free); + ql_free(buildingtypes); + buildingtypes = 0; +} + building_type *bt_get_or_create(const char *name) { if (name != NULL) { diff --git a/src/kernel/building.h b/src/kernel/building.h index 7b2eb934a..b0b4df798 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -75,6 +75,7 @@ extern "C" { building_type *bt_get_or_create(const char *name); const building_type *bt_find(const char *name); + void free_buildingtypes(void); void register_buildings(void); void bt_register(struct building_type *type); int bt_effsize(const struct building_type *btype, diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index a5ad197a8..d3f9191e4 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -77,14 +77,33 @@ void json_construction(cJSON *json, construction **consp) { *consp = cons; } -void json_building(cJSON *json, building_type *st) { +void json_terrain(cJSON *json, terrain_type *ter) { + cJSON *child; + if (json->type!=cJSON_Object) { + log_error("terrain %s is not a json object: %d\n", json->string, json->type); + return; + } + for (child=json->child;child;child=child->next) { + log_error("terrain %s contains unknown attribute %s\n", json->string, child->string); + } +} + +void json_building(cJSON *json, building_type *bt) { cJSON *child; if (json->type!=cJSON_Object) { log_error("building %s is not a json object: %d\n", json->string, json->type); return; } for (child=json->child;child;child=child->next) { - log_error("building %s contains unknown attribute %s\n", json->string, child->string); + switch(child->type) { + case cJSON_Object: + if (strcmp(child->string, "construction")==0) { + json_construction(child, &bt->construction); + } + break; + default: + log_error("building %s contains unknown attribute %s\n", json->string, child->string); + } } } @@ -177,10 +196,21 @@ void json_race(cJSON *json, race *rc) { } } +void json_terrains(cJSON *json) { + cJSON *child; + if (json->type!=cJSON_Object) { + log_error("terrains is not a json object: %d\n", json->type); + return; + } + for (child=json->child;child;child=child->next) { + json_terrain(child, terrain_get_or_create(child->string)); + } +} + void json_buildings(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error("ships is not a json object: %d\n", json->type); + log_error("buildings is not a json object: %d\n", json->type); return; } for (child=json->child;child;child=child->next) { @@ -216,17 +246,21 @@ void json_config(cJSON *json) { log_error("config is not a json object: %d\n", json->type); return; } - child = cJSON_GetObjectItem(json, "races"); - if (child && child->type==cJSON_Object) { - json_races(child); - } - child = cJSON_GetObjectItem(json, "ships"); - if (child && child->type==cJSON_Object) { - json_ships(child); - } - child = cJSON_GetObjectItem(json, "buildings"); - if (child && child->type==cJSON_Object) { - json_buildings(child); + for (child=json->child;child;child=child->next) { + if (strcmp(child->string, "races")==0) { + json_races(child); + } + else if (strcmp(child->string, "ships")==0) { + json_ships(child); + } + else if (strcmp(child->string, "buildings")==0) { + json_buildings(child); + } + else if (strcmp(child->string, "terrains")==0) { + json_terrains(child); + } else { + log_error("config contains unknown attribute %s\n", child->string); + } } } diff --git a/src/kernel/jsonconf_test.c b/src/kernel/jsonconf_test.c index 6b5441106..00443b9b3 100644 --- a/src/kernel/jsonconf_test.c +++ b/src/kernel/jsonconf_test.c @@ -1,8 +1,9 @@ #include #include "types.h" #include "jsonconf.h" -#include "race.h" #include "building.h" +#include "race.h" +#include "terrain.h" #include "ship.h" #include #include @@ -100,10 +101,53 @@ static void test_ships(CuTest * tc) test_cleanup(); } +static void test_buildings(CuTest * tc) +{ + const char * data = "{\"buildings\": { \"house\" : { " + "\"construction\" : { \"maxsize\" : 20, \"reqsize\" : 10, \"minskill\" : 1 }" + "}}}"; + + cJSON *json = cJSON_Parse(data); + const building_type *bt; + + test_cleanup(); + + CuAssertPtrNotNull(tc, json); + CuAssertPtrEquals(tc, 0, buildingtypes); + json_config(json); + + CuAssertPtrNotNull(tc, buildingtypes); + bt = bt_find("house"); + CuAssertPtrNotNull(tc, bt); + CuAssertPtrNotNull(tc, bt->construction); + CuAssertIntEquals(tc, 10, bt->construction->reqsize); + CuAssertIntEquals(tc, 20, bt->construction->maxsize); + CuAssertIntEquals(tc, 1, bt->construction->minskill); + test_cleanup(); +} + +static void test_terrains(CuTest * tc) +{ + const char * data = "{\"terrains\": { \"plain\" : {} }}"; + + cJSON *json = cJSON_Parse(data); + + test_cleanup(); + CuAssertPtrNotNull(tc, json); + CuAssertPtrEquals(tc, 0, (void *)get_terrain("plain")); + + json_config(json); + CuAssertPtrNotNull(tc, get_terrain("plain")); + + test_cleanup(); +} + CuSuite *get_jsonconf_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_ships); + SUITE_ADD_TEST(suite, test_buildings); + SUITE_ADD_TEST(suite, test_terrains); SUITE_ADD_TEST(suite, test_races); SUITE_ADD_TEST(suite, test_flags); return suite; diff --git a/src/kernel/terrain.c b/src/kernel/terrain.c index 14c776e14..38d38a671 100644 --- a/src/kernel/terrain.c +++ b/src/kernel/terrain.c @@ -78,33 +78,48 @@ void test_clear_terrains(void) const terrain_type *terrains(void) { - return registered_terrains; + return registered_terrains; } static const char *plain_name(const struct region *r) { - /* TODO: xml defined */ - if (r_isforest(r)) - return "forest"; - return r->terrain->_name; + /* TODO: xml defined */ + if (r_isforest(r)) { + return "forest"; + } + return r->terrain->_name; } -void register_terrain(struct terrain_type *terrain) +static terrain_type *terrain_find_i(const char *name) { - assert(terrain->next == NULL), terrain->next = registered_terrains; - registered_terrains = terrain; - if (strcmp("plain", terrain->_name) == 0) - terrain->name = &plain_name; + terrain_type *terrain; + for (terrain = registered_terrains; terrain; terrain = terrain->next) { + if (strcmp(terrain->_name, name) == 0) { + break; + } + } + return terrain; } -const struct terrain_type *get_terrain(const char *name) -{ - const struct terrain_type *terrain; - for (terrain = registered_terrains; terrain; terrain = terrain->next) { - if (strcmp(terrain->_name, name) == 0) - break; - } - return terrain; +const terrain_type *get_terrain(const char *name) { + return terrain_find_i(name); +} + +terrain_type * terrain_get_or_create(const char *name) { + terrain_type *terrain = terrain_find_i(name); + if (!terrain) { + terrain = (terrain_type *)calloc(sizeof(terrain_type), 1); + if (terrain) { + terrain->_name = _strdup(name); + terrain->next = registered_terrains; + registered_terrains = terrain; + if (strcmp("plain", name) == 0) { + // TODO: this is awful, it belongs in config + terrain->name = &plain_name; + } + } + } + return terrain; } static const terrain_type *newterrains[MAXTERRAINS]; diff --git a/src/kernel/terrain.h b/src/kernel/terrain.h index d4c0cb55b..69c631e4e 100644 --- a/src/kernel/terrain.h +++ b/src/kernel/terrain.h @@ -70,9 +70,9 @@ extern "C" { struct terrain_type *next; } terrain_type; + extern terrain_type *terrain_get_or_create(const char *name); extern const terrain_type *terrains(void); - extern void register_terrain(struct terrain_type *terrain); - extern const struct terrain_type *get_terrain(const char *name); + extern const terrain_type *get_terrain(const char *name); extern const char *terrain_name(const struct region *r); extern void init_terrains(void); diff --git a/src/tests.c b/src/tests.c index 17c3efa1d..7796d063b 100644 --- a/src/tests.c +++ b/src/tests.c @@ -56,29 +56,26 @@ struct unit *test_create_unit(struct faction *f, struct region *r) void test_cleanup(void) { - test_clear_terrains(); - test_clear_resources(); - global.functions.maintenance = NULL; - global.functions.wage = NULL; - default_locale = 0; - free_locales(); - free_spells(); - free_shiptypes(); - free_races(); - free_spellbooks(); - free_gamedata(); + test_clear_terrains(); + test_clear_resources(); + global.functions.maintenance = NULL; + global.functions.wage = NULL; + default_locale = 0; + free_locales(); + free_spells(); + free_buildingtypes(); + free_shiptypes(); + free_races(); + free_spellbooks(); + free_gamedata(); } terrain_type * test_create_terrain(const char * name, unsigned int flags) { - terrain_type * t; - - assert(!get_terrain(name)); - t = (terrain_type*)calloc(1, sizeof(terrain_type)); + terrain_type * t = terrain_get_or_create(name); t->_name = _strdup(name); t->flags = flags; - register_terrain(t); return t; }