From 0c6defad91656f1dfd31983ce79fa5ae0467c2b6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 18 Aug 2016 18:59:30 +0200 Subject: [PATCH 1/6] extract read_planes into a separate function. --- src/kernel/faction.h | 2 +- src/kernel/save.c | 163 ++++++++++++++++++++++--------------------- 2 files changed, 84 insertions(+), 81 deletions(-) diff --git a/src/kernel/faction.h b/src/kernel/faction.h index c7578cc47..5f7e1f91f 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -134,7 +134,7 @@ extern "C" { void write_faction_reference(const struct faction *f, struct storage *store); - variant read_faction_reference(struct gamedata *store); + variant read_faction_reference(struct gamedata *data); int resolve_faction(variant data, void *addr); void renumber_faction(faction * f, int no); diff --git a/src/kernel/save.c b/src/kernel/save.c index 2379db877..e5ea1f400 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -452,6 +452,88 @@ static void read_alliances(struct gamedata *data) } } +void read_planes(gamedata *data) { + struct storage *store = data->store; + int nread; + char name[32]; + + /* Planes */ + planes = NULL; + READ_INT(store, &nread); + while (--nread >= 0) { + int id; + variant fno; + plane *pl; + + READ_INT(store, &id); + pl = getplanebyid(id); + + if (pl == NULL) { + pl = calloc(1, sizeof(plane)); + } + else { + log_warning("the plane with id=%d already exists.", id); + } + pl->id = id; + READ_STR(store, name, sizeof(name)); + pl->name = _strdup(name); + READ_INT(store, &pl->minx); + READ_INT(store, &pl->maxx); + READ_INT(store, &pl->miny); + READ_INT(store, &pl->maxy); + READ_INT(store, &pl->flags); + + /* read watchers */ + if (data->version < FIX_WATCHERS_VERSION) { + char rname[64]; + /* before this version, watcher storage was pretty broken. we are incompatible and don't read them */ + for (;;) { + READ_TOK(store, rname, sizeof(rname)); + if (strcmp(rname, "end") == 0) { + break; /* this is most likely the end of the list */ + } + else { + log_error( + ("This datafile contains watchers, but we are unable to read them.")); + } + } + } + else { + /* WATCHERS - eliminated in February 2016, ca. turn 966 */ + if (data->version < NOWATCH_VERSION) { + fno = read_faction_reference(data); + while (fno.i) { + fno = read_faction_reference(data); + } + } + } + read_attribs(data, &pl->attribs, pl); + if (pl->id != 1094969858) { // Regatta + addlist(&planes, pl); + } + } +} + +void write_planes(storage *store) { + plane *pl; + /* Write planes */ + WRITE_INT(store, listlen(planes)); + for (pl = planes; pl; pl = pl->next) { + WRITE_INT(store, pl->id); + WRITE_STR(store, pl->name); + WRITE_INT(store, pl->minx); + WRITE_INT(store, pl->maxx); + WRITE_INT(store, pl->miny); + WRITE_INT(store, pl->maxy); + WRITE_INT(store, pl->flags); +#if RELEASE_VERSION < NOWATCH_VERSION + write_faction_reference(NULL, store); /* mark the end of pl->watchers (gone since T966) */ +#endif + a_write(store, pl->attribs, pl); + WRITE_SECTION(store); + } +} + void write_alliances(struct gamedata *data) { alliance *al = alliances; @@ -1554,63 +1636,7 @@ int read_game(gamedata *data) { READ_INT(store, NULL); /* max_unique_id = ignore */ READ_INT(store, &nextborder); - /* Planes */ - planes = NULL; - READ_INT(store, &nread); - while (--nread >= 0) { - int id; - variant fno; - plane *pl; - - READ_INT(store, &id); - pl = getplanebyid(id); - - if (pl == NULL) { - pl = calloc(1, sizeof(plane)); - } - else { - log_warning("the plane with id=%d already exists.", id); - } - pl->id = id; - READ_STR(store, name, sizeof(name)); - pl->name = _strdup(name); - READ_INT(store, &pl->minx); - READ_INT(store, &pl->maxx); - READ_INT(store, &pl->miny); - READ_INT(store, &pl->maxy); - READ_INT(store, &pl->flags); - - /* read watchers */ - if (data->version < FIX_WATCHERS_VERSION) { - char rname[64]; - /* before this version, watcher storage was pretty broken. we are incompatible and don't read them */ - for (;;) { - READ_TOK(store, rname, sizeof(rname)); - if (strcmp(rname, "end") == 0) { - break; /* this is most likely the end of the list */ - } - else { - log_error( - ("This datafile contains watchers, but we are unable to read them.")); - } - } - } - else { - /* WATCHERS - eliminated in February 2016, ca. turn 966 */ - if (data->version < NOWATCH_VERSION) { - fno = read_faction_reference(data); - while (fno.i) { - fno = read_faction_reference(data); - } - } - } - read_attribs(data, &pl->attribs, pl); - if (pl->id != 1094969858) { // Regatta - addlist(&planes, pl); - } - } - - /* Read factions */ + read_planes(data); read_alliances(data); READ_INT(store, &nread); log_debug(" - Einzulesende Parteien: %d\n", nread); @@ -1866,24 +1892,6 @@ int writegame(const char *filename) return n; } -void write_planes(storage *store) { - plane *pl; - for (pl = planes; pl; pl = pl->next) { - WRITE_INT(store, pl->id); - WRITE_STR(store, pl->name); - WRITE_INT(store, pl->minx); - WRITE_INT(store, pl->maxx); - WRITE_INT(store, pl->miny); - WRITE_INT(store, pl->maxy); - WRITE_INT(store, pl->flags); -#if RELEASE_VERSION < NOWATCH_VERSION - write_faction_reference(NULL, store); /* mark the end of pl->watchers (gone since T966) */ -#endif - a_write(store, pl->attribs, pl); - WRITE_SECTION(store); - } -} - int write_game(gamedata *data) { storage * store = data->store; region *r; @@ -1903,11 +1911,6 @@ int write_game(gamedata *data) { WRITE_INT(store, 0 /* max_unique_id */); WRITE_INT(store, nextborder); - /* Write planes */ - WRITE_SECTION(store); - WRITE_INT(store, listlen(planes)); - WRITE_SECTION(store); - write_planes(store); write_alliances(data); n = listlen(factions); From a3ff8781c45dec1fd215a33ae8a8df9388b24132 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 18 Aug 2016 19:04:48 +0200 Subject: [PATCH 2/6] setting herbs will warn if they are the wrong herbs. planes can be erased. add a script that erases unused planes from E2. --- scripts/kill-planes.lua | 23 +++++++++++++++++++++++ scripts/run-turn.lua | 1 - src/bind_region.c | 8 ++++++++ src/kernel/config.c | 3 +-- src/kernel/plane.c | 30 ++++++++++++++++++++++++++++++ src/kernel/plane.h | 13 ++++++++----- src/kernel/region.c | 27 +++++++++++++++++++++++---- src/kernel/region.h | 6 ++++-- src/kernel/save.c | 2 +- 9 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 scripts/kill-planes.lua diff --git a/scripts/kill-planes.lua b/scripts/kill-planes.lua new file mode 100644 index 000000000..182415e2b --- /dev/null +++ b/scripts/kill-planes.lua @@ -0,0 +1,23 @@ +path = 'scripts' +if config.install then + path = config.install .. '/' .. path + package.path = package.path .. ';' .. config.install .. '/lunit/?.lua' + --needed to find lunit if not run from eressea root. Needs right [lua] install setting in eressea.ini (point to eressea root from the start folder) +end +package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' + +config.rules = 'e2' + +require 'eressea' +require 'eressea.xmlconf' +require 'eressea.path' + +eressea.read_game(get_turn() .. '.dat') +ids = {2081501646, 1967748303, 1137, 2000, 1456894557, 1580742069, 1143084084, 285224813, 604912520, 296884068, 50} + +for k,v in ipairs(ids) do + p = plane.get(v) + print(v, p) + p:erase() +end +eressea.write_game(get_turn() .. '.new') diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index fc5eebbbf..7ee9165ca 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -3,7 +3,6 @@ function nmr_check(maxnmrs) if nmrs >= maxnmrs then eressea.log.error("Shit. More than " .. maxnmrs .. " factions with 1 NMR (" .. nmrs .. ")") write_summary() - eressea.write_game("aborted.dat") return -1 end print (nmrs .. " Factions with 1 NMR") diff --git a/src/bind_region.c b/src/bind_region.c index a28b94c07..24c2fb08d 100644 --- a/src/bind_region.c +++ b/src/bind_region.c @@ -582,6 +582,13 @@ static int tolua_plane_get(lua_State * L) return 1; } +static int tolua_plane_erase(lua_State *L) +{ + plane *self = (plane *)tolua_tousertype(L, 1, 0); + remove_plane(self); + return 0; +} + static int tolua_plane_create(lua_State * L) { int id = (int)tolua_tonumber(L, 1, 0); @@ -739,6 +746,7 @@ void tolua_region_open(lua_State * L) tolua_beginmodule(L, TOLUA_CAST "plane"); { tolua_function(L, TOLUA_CAST "create", tolua_plane_create); + tolua_function(L, TOLUA_CAST "erase", tolua_plane_erase); tolua_function(L, TOLUA_CAST "get", tolua_plane_get); tolua_function(L, TOLUA_CAST "__tostring", tolua_plane_tostring); diff --git a/src/kernel/config.c b/src/kernel/config.c index 56d995bdc..cda449a23 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1104,8 +1104,7 @@ void free_gamedata(void) while (planes) { plane *pl = planes; planes = planes->next; - free(pl->name); - free(pl); + free_plane(pl); } while (global.attribs) { diff --git a/src/kernel/plane.c b/src/kernel/plane.c index 2542a053d..7e9650d13 100644 --- a/src/kernel/plane.c +++ b/src/kernel/plane.c @@ -290,3 +290,33 @@ int read_plane_reference(plane ** pp, struct storage *store) ur_add(id, pp, resolve_plane); return AT_READ_OK; } + +void free_plane(plane *pl) { + free(pl->name); + free(pl); +} + +void remove_plane(plane *pl) { + region **rp = ®ions; + plane **pp = &planes; + assert(pl); + while (*rp) { + region *r = *rp; + if (r->_plane == pl) { + remove_region(rp, r); + } + else { + rp = &r->next; + } + } + while (*pp) { + if (pl==*pp) { + *pp = pl->next; + free_plane(pl); + break; + } + else { + pp = &(*pp)->next; + } + } +} diff --git a/src/kernel/plane.h b/src/kernel/plane.h index 051c05b69..85c38cf9f 100644 --- a/src/kernel/plane.h +++ b/src/kernel/plane.h @@ -68,13 +68,16 @@ extern "C" { int miny, int maxy, int flags); struct plane *getplanebyname(const char *); struct plane *get_homeplane(void); - extern int rel_to_abs(const struct plane *pl, const struct faction *f, + int rel_to_abs(const struct plane *pl, const struct faction *f, int rel, unsigned char index); - extern void write_plane_reference(const plane * p, struct storage *store); - extern int read_plane_reference(plane ** pp, struct storage *store); - extern int plane_width(const plane * pl); - extern int plane_height(const plane * pl); + void write_plane_reference(const plane * p, struct storage *store); + int read_plane_reference(plane ** pp, struct storage *store); + int plane_width(const plane * pl); + int plane_height(const plane * pl); void adjust_coordinates(const struct faction *f, int *x, int *y, const struct plane *pl); + + void free_plane(struct plane *pl); + void remove_plane(struct plane *pl); #ifdef __cplusplus } #endif diff --git a/src/kernel/region.c b/src/kernel/region.c index c4e2042e4..54e78ec06 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -645,20 +645,39 @@ void rsetmoney(region * r, int value) } } -int rherbs(const struct region *r) +int rherbs(const region *r) { return r->land?r->land->herbs:0; } -void rsetherbs(const struct region *r, int value) +void rsetherbs(region *r, int value) { assert(r->land || value==0); - assert(value >= 0); + assert(value >= 0 && value<=SHRT_MAX); if (r->land) { - r->land->herbs = (short)(value); + r->land->herbs = (short)value; } } +void rsetherbtype(region *r, const struct item_type *itype) { + assert(r->land && r->terrain); + if (itype == NULL) { + r->land->herbtype = NULL; + } + else { + if (r->terrain->herbs) { + int i; + for (i = 0; r->terrain->herbs[i]; ++i) { + if (r->terrain->herbs[i] == itype) { + r->land->herbtype = itype; + return; + } + } + } + log_debug("attempt to set herbtype=%s for terrain=%s in %s", itype->rtype->_name, r->terrain->_name, regionname(r, 0)); + r->land->herbtype = itype; + } +} void r_setdemand(region * r, const luxury_type * ltype, int value) { diff --git a/src/kernel/region.h b/src/kernel/region.h index 70d998a0e..bbc5282b0 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -202,12 +202,12 @@ extern "C" { void rsethorses(const struct region *r, int value); int rherbs(const struct region *r); - void rsetherbs(const struct region *r, int value); + void rsetherbs(struct region *r, int value); + void rsetherbtype(struct region *r, const struct item_type *itype); #define rbuildings(r) ((r)->buildings) #define rherbtype(r) ((r)->land?(r)->land->herbtype:0) -#define rsetherbtype(r, value) if ((r)->land) (r)->land->herbtype=(value) bool r_isforest(const struct region *r); @@ -276,6 +276,8 @@ extern "C" { struct faction *update_owners(struct region *r); + void region_erase(struct region *r); + #ifdef __cplusplus } #endif diff --git a/src/kernel/save.c b/src/kernel/save.c index e5ea1f400..bf0969545 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1066,7 +1066,7 @@ static region *readregion(struct gamedata *data, int x, int y) rsetherbtype(r, NULL); } READ_INT(data->store, &n); - rsetherbs(r, (short)n); + rsetherbs(r, n); READ_INT(data->store, &n); if (n < 0) { /* bug 2182 */ From abd6600cfe25a0b08bfb67f5c700472028f505c9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 17 Aug 2016 21:22:50 +0200 Subject: [PATCH 3/6] when reading alliances, duplicate ids are impossible. makealliance does too much work, new_alliance is simpler. --- src/kernel/alliance.c | 9 ++++++++- src/kernel/alliance.h | 13 +++++++------ src/kernel/save.c | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/kernel/alliance.c b/src/kernel/alliance.c index 08f93b626..c9bd26f40 100644 --- a/src/kernel/alliance.c +++ b/src/kernel/alliance.c @@ -58,7 +58,7 @@ void free_alliances(void) alliance *makealliance(int id, const char *name) { - alliance *al;; + alliance *al; for (;;) { if (id > 0) { @@ -73,6 +73,13 @@ alliance *makealliance(int id, const char *name) } id = id ? id : (1 + (rng_int() % MAX_UNIT_NR)); } + return new_alliance(id, name); +} + +alliance *new_alliance(int id, const char *name) { + alliance *al; + assert(id>0); + al = calloc(1, sizeof(alliance)); al->id = id; if (name) { diff --git a/src/kernel/alliance.h b/src/kernel/alliance.h index 2c5b0d677..907fc65f7 100644 --- a/src/kernel/alliance.h +++ b/src/kernel/alliance.h @@ -54,13 +54,14 @@ extern "C" { } alliance; extern alliance *alliances; - extern alliance *findalliance(int id); - extern alliance *makealliance(int id, const char *name); - extern const char *alliancename(const struct alliance *al); - extern void setalliance(struct faction *f, alliance * al); + alliance *findalliance(int id); + alliance *new_alliance(int id, const char *name); + alliance *makealliance(int id, const char *name); + const char *alliancename(const struct alliance *al); + void setalliance(struct faction *f, alliance * al); void free_alliances(void); - extern struct faction *alliance_get_leader(struct alliance *al); - extern void alliance_cmd(void); + struct faction *alliance_get_leader(struct alliance *al); + void alliance_cmd(void); bool is_allied(const struct faction *f1, const struct faction *f2); void alliance_setname(alliance * self, const char *name); diff --git a/src/kernel/save.c b/src/kernel/save.c index bf0969545..b3bdd2c17 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -436,7 +436,7 @@ static void read_alliances(struct gamedata *data) char aname[128]; alliance *al; READ_STR(store, aname, sizeof(aname)); - al = makealliance(id, aname); + al = new_alliance(id, aname); if (data->version >= OWNER_2_VERSION) { READ_INT(store, &al->flags); } From e5f5dc6aa4d8d07fdabf7ad94fdd2e47e9c3ff0b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 14 Aug 2016 15:46:27 +0200 Subject: [PATCH 4/6] fail when there are borders that can't be read because their endpoints are missing --- scripts/kill-planes.lua | 2 ++ src/kernel/connection.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/kill-planes.lua b/scripts/kill-planes.lua index 182415e2b..814585ce7 100644 --- a/scripts/kill-planes.lua +++ b/scripts/kill-planes.lua @@ -21,3 +21,5 @@ for k,v in ipairs(ids) do p:erase() end eressea.write_game(get_turn() .. '.new') +eressea.free_game() +eressea.read_game(get_turn() .. '.new') diff --git a/src/kernel/connection.c b/src/kernel/connection.c index f1e5c4b6d..dad2da8ac 100644 --- a/src/kernel/connection.c +++ b/src/kernel/connection.c @@ -633,8 +633,8 @@ int read_borders(gamedata *data) from = findregionbyid(fid); to = findregionbyid(tid); if (!to || !from) { - log_warning("%s connection between incomplete regions %d and %d", zText, fid, tid); - continue; + log_error("%s connection between missing regions %d and %d", zText, fid, tid); + assert((to && from) || !"connection between missing regions"); } } From ecffed05773ef210298a5daf59a58d9a456706d9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 14 Aug 2016 16:51:25 +0200 Subject: [PATCH 5/6] verify data after deleting planes, do not delete plane 50 (yet) --- scripts/kill-planes.lua | 3 +++ src/kernel/connection.c | 26 +++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/scripts/kill-planes.lua b/scripts/kill-planes.lua index 814585ce7..3919f3fda 100644 --- a/scripts/kill-planes.lua +++ b/scripts/kill-planes.lua @@ -14,6 +14,7 @@ require 'eressea.path' eressea.read_game(get_turn() .. '.dat') ids = {2081501646, 1967748303, 1137, 2000, 1456894557, 1580742069, 1143084084, 285224813, 604912520, 296884068, 50} +p=plane.create(50, -7280, -4494, 83, 83, "Regatta") for k,v in ipairs(ids) do p = plane.get(v) @@ -23,3 +24,5 @@ end eressea.write_game(get_turn() .. '.new') eressea.free_game() eressea.read_game(get_turn() .. '.new') +write_reports() +eressea.write_game(get_turn() .. '.fix') diff --git a/src/kernel/connection.c b/src/kernel/connection.c index dad2da8ac..f31a87fe7 100644 --- a/src/kernel/connection.c +++ b/src/kernel/connection.c @@ -616,6 +616,13 @@ int read_borders(gamedata *data) READ_TOK(store, zText, sizeof(zText)); if (!strcmp(zText, "end")) break; + type = find_bordertype(zText); + if (type == NULL) { + log_error("[read_borders] connection %d type %s is not registered", bid, zText); + assert(type || !"connection type not registered"); + } + + READ_INT(store, &bid); if (data->version < UIDHASH_VERSION) { int fx, fy, tx, ty; @@ -632,16 +639,17 @@ int read_borders(gamedata *data) READ_INT(store, &tid); from = findregionbyid(fid); to = findregionbyid(tid); - if (!to || !from) { - log_error("%s connection between missing regions %d and %d", zText, fid, tid); - assert((to && from) || !"connection between missing regions"); - } } - - type = find_bordertype(zText); - if (type == NULL) { - log_error("[read_borders] unknown connection type '%s' in %s\n", zText, regionname(from, NULL)); - assert(type || !"connection type not registered"); + if (!to || !from) { + if (!to || !from) { + log_error("%s connection %d has missing regions", zText, bid); + } + if (type->read) { + // skip ahead + connection dummy; + type->read(&dummy, store); + } + continue; } if (to == from && type && from) { From 3be627d6effb4537893a40f010ab9643988f8169 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 14 Aug 2016 19:56:20 +0200 Subject: [PATCH 6/6] fix compilation --- src/kernel/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/connection.c b/src/kernel/connection.c index f31a87fe7..ef86f9a3a 100644 --- a/src/kernel/connection.c +++ b/src/kernel/connection.c @@ -647,7 +647,7 @@ int read_borders(gamedata *data) if (type->read) { // skip ahead connection dummy; - type->read(&dummy, store); + type->read(&dummy, data); } continue; }