diff --git a/src/kernel/save.c b/src/kernel/save.c index 2abd0b93f..528a71808 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1673,9 +1673,68 @@ struct building *read_building(gamedata *data) { return b; } -int read_game(gamedata *data) { +void write_ship(gamedata *data, const ship *sh) +{ + storage *store = data->store; + write_ship_reference(sh, store); + WRITE_STR(store, (const char *)sh->name); + WRITE_STR(store, sh->display ? (const char *)sh->display : ""); + WRITE_TOK(store, sh->type->_name); + WRITE_INT(store, sh->size); + WRITE_INT(store, sh->damage); + WRITE_INT(store, sh->flags & SFL_SAVEMASK); + assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION); + WRITE_INT(store, sh->coast); + write_attribs(store, sh->attribs, sh); +} + +ship *read_ship(struct gamedata *data) +{ char name[DISPLAYSIZE]; - int n, p, nread; + ship *sh; + int n; + storage *store = data->store; + + sh = (ship *)calloc(1, sizeof(ship)); + READ_INT(store, &sh->no); + shash(sh); + READ_STR(store, name, sizeof(name)); + sh->name = _strdup(name); + if (lomem) { + READ_STR(store, NULL, 0); + } + else { + READ_STR(store, name, sizeof(name)); + sh->display = _strdup(name); + } + READ_STR(store, name, sizeof(name)); + sh->type = st_find(name); + if (sh->type == NULL) { + /* old datafiles */ + sh->type = st_find((const char *)LOC(default_locale, name)); + } + assert(sh->type || !"ship_type not registered!"); + + READ_INT(store, &sh->size); + READ_INT(store, &sh->damage); + if (data->version >= FOSS_VERSION) { + READ_INT(store, &sh->flags); + } + + /* Attribute rekursiv einlesen */ + + READ_INT(store, &n); + sh->coast = (direction_t)n; + if (sh->type->flags & SFL_NOCOAST) { + sh->coast = NODIRECTION; + } + read_attribs(data, &sh->attribs, sh); + return sh; +} + + +int read_game(gamedata *data) { + int p, nread; faction *f, **fp; region *r; building **bp; @@ -1755,10 +1814,10 @@ int read_game(gamedata *data) { while (--p >= 0) { building *b = *bp = read_building(data); - b->region = r; if (b->type == bt_lighthouse) { r->flags |= RF_LIGHTHOUSE; } + b->region = r; bp = &b->next; } /* Schiffe */ @@ -1767,43 +1826,9 @@ int read_game(gamedata *data) { shp = &r->ships; while (--p >= 0) { - ship *sh = (ship *)calloc(1, sizeof(ship)); + ship *sh = *shp = read_ship(data); sh->region = r; - READ_INT(store, &sh->no); - *shp = sh; shp = &sh->next; - shash(sh); - READ_STR(store, name, sizeof(name)); - sh->name = _strdup(name); - if (lomem) { - READ_STR(store, NULL, 0); - } - else { - READ_STR(store, name, sizeof(name)); - sh->display = _strdup(name); - } - READ_STR(store, name, sizeof(name)); - sh->type = st_find(name); - if (sh->type == NULL) { - /* old datafiles */ - sh->type = st_find((const char *)LOC(default_locale, name)); - } - assert(sh->type || !"ship_type not registered!"); - - READ_INT(store, &sh->size); - READ_INT(store, &sh->damage); - if (data->version >= FOSS_VERSION) { - READ_INT(store, &sh->flags); - } - - /* Attribute rekursiv einlesen */ - - READ_INT(store, &n); - sh->coast = (direction_t)n; - if (sh->type->flags & SFL_NOCOAST) { - sh->coast = NODIRECTION; - } - read_attribs(data, &sh->attribs, sh); } *shp = 0; @@ -2006,6 +2031,7 @@ int write_game(gamedata *data) { WRITE_INT(store, listlen(r->buildings)); WRITE_SECTION(store); for (b = r->buildings; b; b = b->next) { + assert(b->region == r); write_building(data, b); } @@ -2013,23 +2039,13 @@ int write_game(gamedata *data) { WRITE_SECTION(store); for (sh = r->ships; sh; sh = sh->next) { assert(sh->region == r); - write_ship_reference(sh, store); - WRITE_STR(store, (const char *)sh->name); - WRITE_STR(store, sh->display ? (const char *)sh->display : ""); - WRITE_TOK(store, sh->type->_name); - WRITE_INT(store, sh->size); - WRITE_INT(store, sh->damage); - WRITE_INT(store, sh->flags & SFL_SAVEMASK); - assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION); - WRITE_INT(store, sh->coast); - WRITE_SECTION(store); - write_attribs(store, sh->attribs, sh); - WRITE_SECTION(store); + write_ship(data, sh); } WRITE_INT(store, listlen(r->units)); WRITE_SECTION(store); for (u = r->units; u; u = u->next) { + assert(u->region == r); write_unit(data, u); } } diff --git a/src/kernel/save.h b/src/kernel/save.h index 6854bad3a..d74017f62 100644 --- a/src/kernel/save.h +++ b/src/kernel/save.h @@ -30,6 +30,8 @@ extern "C" { struct spell; struct spellbook; struct unit; + struct building; + struct ship; struct gamedata; #define MAX_INPUT_SIZE DISPLAYSIZE*2 @@ -61,6 +63,9 @@ extern "C" { void write_building(struct gamedata *data, const struct building *b); struct building *read_building(struct gamedata *data); + void write_ship(struct gamedata *data, const struct ship *sh); + struct ship *read_ship(struct gamedata *data); + int a_readint(struct attrib *a, void *owner, struct gamedata *); void a_writeint(const struct attrib *a, const void *owner, struct storage *store); diff --git a/src/kernel/save.test.c b/src/kernel/save.test.c index af7c4c1f4..4f13851cb 100644 --- a/src/kernel/save.test.c +++ b/src/kernel/save.test.c @@ -7,6 +7,7 @@ #include "save.h" #include "version.h" #include "building.h" +#include "ship.h" #include "unit.h" #include "group.h" #include "ally.h" @@ -85,8 +86,8 @@ static void test_readwrite_building(CuTest * tc) { gamedata data; storage store; - struct building *b; - struct region *r; + building *b; + region *r; test_setup(); r = test_create_region(0, 0, 0); @@ -114,6 +115,39 @@ static void test_readwrite_building(CuTest * tc) test_cleanup(); } +static void test_readwrite_ship(CuTest * tc) +{ + gamedata data; + storage store; + ship *sh; + region *r; + + test_setup(); + r = test_create_region(0, 0, 0); + sh = test_create_ship(r, 0); + free(sh->name); + sh->name = _strdup(" Hodor "); + CuAssertStrEquals(tc, " Hodor ", sh->name); + mstream_init(&data.strm); + gamedata_init(&data, &store, RELEASE_VERSION); + write_ship(&data, sh); + + data.strm.api->rewind(data.strm.handle); + free_gamedata(); + r = test_create_region(0, 0, 0); + gamedata_init(&data, &store, RELEASE_VERSION); + sh = read_ship(&data); + CuAssertPtrNotNull(tc, sh); + CuAssertStrEquals(tc, "Hodor", sh->name); + CuAssertPtrEquals(tc, 0, sh->region); + sh->region = r; + r->ships = sh; + + mstream_done(&data.strm); + gamedata_done(&data); + test_cleanup(); +} + static void test_readwrite_attrib(CuTest *tc) { gamedata data; storage store; @@ -364,6 +398,7 @@ CuSuite *get_save_suite(void) SUITE_ADD_TEST(suite, test_readwrite_data); SUITE_ADD_TEST(suite, test_readwrite_unit); SUITE_ADD_TEST(suite, test_readwrite_building); + SUITE_ADD_TEST(suite, test_readwrite_ship); SUITE_ADD_TEST(suite, test_readwrite_dead_faction_createunit); SUITE_ADD_TEST(suite, test_readwrite_dead_faction_changefaction); SUITE_ADD_TEST(suite, test_readwrite_dead_faction_regionowner);