"Der strict-aliasing fix zerstoert Referenzen"
- mostly rewrote the whole delayed resolution code.

http://eressea.upb.de/mantis/view.php?id=1431
"buildings and ships are leaking memory"
- made a mistake deleting damaged ships.

also:
- WORMHOLE_MODULE is now a config option
This commit is contained in:
Enno Rehling 2008-05-24 00:20:00 +00:00
parent 0ce94f0f91
commit 186a575c7c
52 changed files with 472 additions and 379 deletions

View File

@ -64,7 +64,7 @@ init_attributes(void)
init_iceberg();
init_key();
init_gm();
init_follow();
init_follow(); /* only for old datafiles */
init_targetregion();
init_orcification();
init_hate();

View File

@ -1,58 +1,48 @@
/* vi: set ts=2:
*
*
* Eressea PB(E)M host Copyright (C) 1998-2003
* Christian Schlittchen (corwin@amber.kn-bremen.de)
* Katja Zedel (katze@felidae.kn-bremen.de)
* Henning Peters (faroul@beyond.kn-bremen.de)
* Enno Rehling (enno@eressea.de)
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
*
* This program may not be used, modified or distributed without
* prior permission by the authors of Eressea.
*/
*
*
* Eressea PB(E)M host Copyright (C) 1998-2003
* Christian Schlittchen (corwin@amber.kn-bremen.de)
* Katja Zedel (katze@felidae.kn-bremen.de)
* Henning Peters (faroul@beyond.kn-bremen.de)
* Enno Rehling (enno@eressea.de)
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
*
* This program may not be used, modified or distributed without
* prior permission by the authors of Eressea.
*/
#include <config.h>
#include "follow.h"
#include <kernel/eressea.h>
#include <kernel/unit.h>
#include <kernel/version.h>
#include <util/attrib.h>
#include <util/resolve.h>
#include <util/storage.h>
#include <util/variant.h>
static int
verify_follow(attrib * a)
{
if (a->data.v==NULL) {
return 0;
}
return 1;
}
static int
read_follow(attrib * a, struct storage * store)
{
return read_unit_reference(NULL, store);
read_unit_reference(store); /* skip it */
return AT_READ_FAIL;
}
attrib_type at_follow = {
"follow", NULL, NULL, verify_follow, NULL, read_follow
"follow", NULL, NULL, NULL, NULL, read_follow
};
attrib *
make_follow(struct unit * u)
{
attrib * a = a_new(&at_follow);
a->data.v = u;
return a;
attrib * a = a_new(&at_follow);
a->data.v = u;
return a;
}
void
init_follow(void)
{
at_register(&at_follow);
at_register(&at_follow);
}

View File

@ -41,10 +41,11 @@ write_hate(const attrib * a, struct storage * store)
static int
read_hate(attrib * a, struct storage * store)
{
unit * u;
int result = read_unit_reference(&u, store);
a->data.v = u;
return result;
int result = read_reference(&a->data.v, store, read_unit_reference, resolve_unit);
if (result==0 && !a->data.v) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
attrib_type at_hate = {

View File

@ -23,9 +23,11 @@
#include <kernel/save.h>
#include <kernel/ship.h>
#include <kernel/unit.h>
#include <kernel/version.h>
/* util includes */
#include <util/attrib.h>
#include <util/resolve.h>
#include <util/storage.h>
/* stdc includes */
@ -90,6 +92,7 @@ static int
object_read(attrib *a, struct storage * store)
{
object_data * data = (object_data *)a->data.v;
int result;
data->name = store->r_str(store);
data->type = (object_type)store->r_int(store);
@ -104,13 +107,29 @@ object_read(attrib *a, struct storage * store)
data->data.str = store->r_str(store);
break;
case TBUILDING:
return read_building_reference(&data->data.b, store);
result = read_reference(&data->data.b, store, read_building_reference, resolve_building);
if (result==0 && !data->data.b) {
return AT_READ_FAIL;
}
break;
case TUNIT:
return read_unit_reference(&data->data.u, store);
result = read_reference(&data->data.u, store, read_unit_reference, resolve_unit);
if (result==0 && !data->data.u) {
return AT_READ_FAIL;
}
break;
case TFACTION:
return read_faction_reference(&data->data.f, store);
result = read_reference(&data->data.f, store, read_faction_reference, resolve_faction);
if (result==0 && !data->data.f) {
return AT_READ_FAIL;
}
break;
case TREGION:
return read_region_reference(&data->data.r, store);
result = read_reference(&data->data.r, store, read_region_reference, RESOLVE_REGION(store->version));
if (result==0 && !data->data.r) {
return AT_READ_FAIL;
}
break;
case TSHIP:
/* return read_ship_reference(&data->data.sh, store); */
assert(!"not implemented");

View File

@ -33,10 +33,9 @@ write_targetregion(const attrib * a, struct storage * store)
static int
read_targetregion(attrib * a, struct storage * store)
{
region * r;
int result = read_region_reference(&r, store);
a->data.v = r;
return result;
int result = read_reference(&a->data.v, store, read_region_reference, RESOLVE_REGION(store->version));
if (result==0 && !a->data.v) return AT_READ_FAIL;
return AT_READ_OK;
}
attrib_type at_targetregion = {

View File

@ -25,9 +25,7 @@
#include <modules/gmcmd.h>
#include <modules/infocmd.h>
#if WORMHOLE_MODULE
#include <modules/wormhole.h>
#endif
/* gamecode includes */
#include "economy.h"
@ -3933,6 +3931,7 @@ processorders (void)
{
static int init = 0;
region *r;
const char * str;
if (!init) {
init_processor();
@ -3947,9 +3946,11 @@ processorders (void)
ageing();
remove_empty_units();
#if WORMHOLE_MODULE
create_wormholes();
#endif
str = get_param(global.parameters, "modules.wormholes");
if (str && atoi(str)) {
create_wormholes();
}
/* immer ausführen, wenn neue Sprüche dazugekommen sind, oder sich
* Beschreibungen geändert haben */
update_spells();

View File

@ -78,9 +78,18 @@ find_border(unsigned int id)
return NULL;
}
void
resolve_borderid(variant id, void * addr) {
*(border**)addr = find_border(id.i);
int
resolve_borderid(variant id, void * addr)
{
border * b = NULL;
if (id.i!=0) {
b = find_border(id.i);
if (b==NULL) {
return -1;
}
}
*(border**)addr = b;
return 0;
}
static border **

View File

@ -88,7 +88,7 @@ extern "C" {
extern border * find_border(unsigned int id);
void resolve_borderid(variant data, void * addr);
int resolve_borderid(variant data, void * addr);
extern void free_borders(void);
extern border * get_borders(const struct region * r1, const struct region * r2);

View File

@ -82,8 +82,7 @@ static int
lc_read(struct attrib * a, struct storage * store)
{
building_action * data = (building_action*)a->data.v;
read_building_reference(&data->b, store);
int result = read_reference(&data->b, store, read_building_reference, resolve_building);
if (store->version<UNICODE_VERSION) {
data->fname = store->r_str(store);
} else {
@ -101,6 +100,9 @@ lc_read(struct attrib * a, struct storage * store)
} else {
data->param = strdup(NULLSTRING);
}
if (result==0 && !data->b) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
@ -369,32 +371,33 @@ register_buildings(void)
#endif
}
void
resolve_building(variant id, void * address) {
building ** b = (building **)address;
*b = findbuilding(id.i);
}
void
write_building_reference(const struct building * b, struct storage * store)
{
store->w_id(store, b?b->no:0);
}
int
read_building_reference(struct building ** b, struct storage * store)
resolve_building(variant id, void * address)
{
variant var;
var.i = store->r_id(store);
if (var.i<=0) {
*b = NULL;
return AT_READ_FAIL;
}
else {
*b = findbuilding(var.i);
if (*b==NULL) ur_add(var, (void**)b, resolve_building);
return AT_READ_OK;
building * b = NULL;
if (id.i!=0) {
b = findbuilding(id.i);
if (b==NULL) {
return -1;
}
}
*(building**)address = b;
return 0;
}
variant
read_building_reference(struct storage * store)
{
variant result;
result.i = store->r_id(store);
return result;
}
void

View File

@ -133,9 +133,9 @@ const struct building_type * findbuildingtype(const char * name, const struct lo
#include "build.h"
#define NOBUILDING NULL
extern void resolve_building(variant data, void * address);
extern int resolve_building(variant data, void * address);
extern void write_building_reference(const struct building * b, struct storage * store);
extern int read_building_reference(struct building ** b, struct storage * store);
extern variant read_building_reference(struct storage * store);
extern struct building *findbuilding(int n);

View File

@ -155,18 +155,17 @@ curse_done(attrib * a) {
destroy_curse((curse *)a->data.v);
}
/* ------------------------------------------------------------- */
int
curse_read(attrib * a, struct storage * store)
{
curse * c = (curse*)a->data.v;
const curse_type * ct;
int ur;
char cursename[64];
unsigned int flags;
c->no = store->r_int(store);
chash(c);
store->r_tok_buf(store, cursename, sizeof(cursename));
flags = store->r_int(store);
c->duration = store->r_int(store);
@ -177,18 +176,9 @@ curse_read(attrib * a, struct storage * store)
c->vigour = vigour;
}
if (store->version<INTPAK_VERSION) {
variant mageid;
mageid.i = store->r_int(store);
if (mageid.i <= 0) {
c->magician = (unit *)NULL;
} else {
c->magician = findunit(mageid.i);
if (!c->magician) {
ur_add(mageid, (void*)&c->magician, resolve_unit);
}
}
ur = read_reference(&c->magician, store, read_int, resolve_unit);
} else {
read_unit_reference(&c->magician, store);
ur = read_reference(&c->magician, store, read_unit_reference, resolve_unit);
}
c->effect.i = store->r_int(store);
ct = ct_find(cursename);
@ -210,11 +200,11 @@ curse_read(attrib * a, struct storage * store)
cc->cursedmen = store->r_int(store);
}
if (c->type->typ == CURSETYP_REGION) {
region * r;
read_region_reference(&r, store);
c->data.v = r;
int rr = read_reference(&c->data.v, store, read_region_reference, RESOLVE_REGION(store->version));
if (ur==0 && rr==0 && !c->data.v) {
return AT_READ_FAIL;
}
}
chash(c);
return AT_READ_OK;
}
@ -689,11 +679,18 @@ is_cursed_with(const attrib *ap, const curse *c)
* } curse_type;
*/
void
int
resolve_curse(variant id, void * address)
{
curse * c = cfindhash(id.i);
curse * c = NULL;
if (id.i!=0) {
c = cfindhash(id.i);
if (c==NULL) {
return -1;
}
}
*(curse**)address = c;
return 0;
}
static const char * oldnames[MAXCURSE] = {

View File

@ -309,7 +309,7 @@ extern int curse_age(struct attrib * a);
extern boolean cmp_curse(const struct attrib * a, const void * data);
extern boolean cmp_cursetype(const struct attrib * a, const void * data);
extern void resolve_curse(variant data, void * address);
extern int resolve_curse(variant data, void * address);
extern boolean is_cursed_with(const struct attrib *ap, const struct curse *c);
extern boolean curse_active(const struct curse * c);

View File

@ -104,9 +104,17 @@ factionname(const faction * f)
return ibuf;
}
void
resolve_faction(variant id, void * addr) {
*(faction**)addr = findfaction(id.i);
int
resolve_faction(variant id, void * address) {
faction * f = NULL;
if (id.i!=0) {
f = findfaction(id.i);
if (f==NULL) {
return -1;
}
}
*(faction**)address = f;
return 0;
}
#define MAX_FACTION_ID (36*36*36*36)
@ -208,18 +216,12 @@ checkpasswd(const faction * f, const char * passwd, boolean shortp)
}
int
read_faction_reference(faction ** f, struct storage * store)
variant
read_faction_reference(struct storage * store)
{
variant id;
id.i = store->r_id(store);
if (id.i<=0 && (store->version>=NOZEROIDS_VERSION || id.i<0)) {
*f = NULL;
return AT_READ_FAIL;
}
*f = findfaction(id.i);
if (*f==NULL) ur_add(id, f, resolve_faction);
return AT_READ_OK;
return id;
}
void

View File

@ -125,7 +125,6 @@ typedef struct faction_list {
extern const struct unit * random_unit_in_faction(const struct faction *f);
extern const char * factionname(const struct faction * f);
extern void resolve_faction(variant data, void * addr);
extern struct unit * addplayer(struct region *r, faction * f);
extern struct faction * addfaction(const char *email, const char* password,
const struct race * frace,
@ -143,7 +142,8 @@ extern void remove_enemy(struct faction * f, struct faction * enemy);
#endif
extern void write_faction_reference(const struct faction * f, struct storage * store);
extern int read_faction_reference(struct faction ** f, struct storage * store);
extern variant read_faction_reference(struct storage * store);
extern int resolve_faction(variant data, void * addr);
extern void renumber_faction(faction * f, int no);

View File

@ -229,6 +229,7 @@ read_groups(struct storage * store, faction * f)
*pa = a;
pa = &a->next;
a->status = store->r_int(store);
a->faction = findfaction(fid.i);
if (!a->faction) ur_add(fid, &a->faction, resolve_faction);
}

View File

@ -2207,27 +2207,29 @@ create_newfamiliar(unit * mage, unit * familiar)
return true;
}
static void
static int
resolve_familiar(variant data, void * addr)
{
unit * familiar;
resolve_unit(data, &familiar);
if (familiar) {
int result = resolve_unit(data, &familiar);
if (result==0 && familiar) {
attrib * a = a_find(familiar->attribs, &at_familiarmage);
if (a!=NULL && a->data.v) {
unit * mage = (unit *)a->data.v;
set_familiar(mage, familiar);
}
*(unit**)addr = familiar;
}
*(unit**)addr = familiar;
return result;
}
static int
read_familiar(attrib * a, struct storage * store)
{
variant id;
id.i = store->r_id(store);
ur_add(id, &a->data.v, resolve_familiar);
int result = read_reference(&a->data.v, store, read_unit_reference, resolve_familiar);
if (result==0 && a->data.v==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
@ -2284,54 +2286,57 @@ has_clone(unit *mage)
return NULL;
}
static void
static int
resolve_clone(variant data, void * addr)
{
unit * clone;
resolve_unit(data, &clone);
if (clone) {
int result = resolve_unit(data, &clone);
if (result==0 && clone) {
attrib * a = a_find(clone->attribs, &at_clonemage);
if (a!=NULL && a->data.v) {
unit * mage = (unit *)a->data.v;
set_clone(mage, clone);
}
*(unit**)addr = clone;
}
*(unit**)addr = clone;
return result;
}
static int
read_clone(attrib * a, struct storage * store)
{
variant id;
id.i = store->r_id(store);
ur_add(id, &a->data.v, resolve_clone);
int result = read_reference(&a->data.v, store, read_unit_reference, resolve_clone);
if (result==0 && a->data.v==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
/* mages */
static void
static int
resolve_mage(variant data, void * addr)
{
unit * mage;
resolve_unit(data, &mage);
if (mage) {
int result = resolve_unit(data, &mage);
if (result==0 && mage) {
attrib * a = a_find(mage->attribs, &at_familiar);
if (a!=NULL && a->data.v) {
unit * familiar = (unit *)a->data.v;
set_familiar(mage, familiar);
}
*(unit **)addr = mage;
}
*(unit **)addr = mage;
return result;
}
static int
read_magician(attrib * a, struct storage * store)
{
variant id;
id.i = store->r_id(store);
ur_add(id, &a->data.v, resolve_mage);
int result = read_reference(&a->data.v, store, read_unit_reference, resolve_mage);
if (result==0 && a->data.v==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}

View File

@ -777,7 +777,7 @@ drifting_ships(region * r)
damage_ship(sh, 0.02);
if (sh->damage>=sh->size * DAMAGE_SCALE) {
remove_ship(shp, sh);
remove_ship(&sh->region->ships, sh);
}
}

View File

@ -232,10 +232,18 @@ rel_to_abs(const struct plane *pl, const struct faction * f, short rel, unsigned
}
void
int
resolve_plane(variant id, void * addr)
{
*(plane**)addr = getplanebyid(id.i);
plane * pl = NULL;
if (id.i!=0) {
pl = getplanebyid(id.i);
if (pl==NULL) {
return -1;
}
}
*(plane**)addr = pl;
return 0;
}
void

View File

@ -73,7 +73,7 @@ plane * create_new_plane(int id, const char *name, short minx, short maxx, short
plane * getplanebyname(const char *);
extern short rel_to_abs(const struct plane *pl, const struct faction * f, short rel, unsigned char index);
extern boolean is_watcher(const struct plane * p, const struct faction * f);
extern void resolve_plane(variant data, void * addr);
extern int resolve_plane(variant data, void * addr);
extern void write_plane_reference(const plane * p, struct storage * store);
extern int read_plane_reference(plane ** pp, struct storage * store);

View File

@ -310,27 +310,27 @@ write_race_reference(const race * rc, struct storage * store)
store->w_tok(store, rc?rc->_name[0]:"none");
}
int
read_race_reference(const struct race ** rp, struct storage * store)
variant
read_race_reference(struct storage * store)
{
variant result;
char zName[20];
if (store->version<NEWRACE_VERSION) {
int i;
i = store->r_int(store);
if (i>=0) {
*rp = new_race[i];
result.v = (void*)new_race[i];
} else {
*rp = NULL;
return AT_READ_FAIL;
result.v = NULL;
}
} else {
store->r_tok_buf(store, zName, sizeof(zName));
if (strcmp(zName, "none")==0) {
*rp = NULL;
return AT_READ_OK;
result.v = NULL;
} else {
result.v = rc_find(zName);
assert(result.v!=NULL);
}
*rp = rc_find(zName);
assert(*rp!=NULL);
}
return AT_READ_OK;
return result;
}

View File

@ -171,7 +171,7 @@ extern void add_raceprefix(const char *);
extern char ** race_prefixes;
extern void write_race_reference(const struct race * rc, struct storage * store);
extern int read_race_reference(const struct race ** rp, struct storage * store);
extern variant read_race_reference(struct storage * store);
extern const char * raceprefix(const struct unit *u);

View File

@ -950,6 +950,7 @@ free_region(region * r)
while (r->buildings) {
building * b = r->buildings;
assert(b->region==r);
r->buildings = b->next;
bunhash(b); /* must be done here, because remove_building does it, and wasn't called */
free_building(b);
@ -957,6 +958,7 @@ free_region(region * r)
while (r->ships) {
ship * s = r->ships;
assert(s->region==r);
r->ships = s->next;
sunhash(s);
free_ship(s);
@ -1237,46 +1239,41 @@ production(const region *r)
return p;
}
static void
resolve_region(variant id, void * address) {
int
resolve_region_coor(variant id, void * address) {
region * r = findregion(id.sa[0], id.sa[1]);
*(region**)address = r;
}
static void
resolve_regionbyid(variant id, void * address) {
region * r = findregionbyid((unsigned int)id.i);
*(region**)address = r;
if (r) {
*(region**)address = r;
return 0;
}
return -1;
}
int
read_region_reference(region ** r, struct storage * store)
resolve_region_id(variant id, void * address)
{
if (store->version<UIDHASH_VERSION) {
variant coor;
coor.sa[0] = (short)store->r_int(store);
coor.sa[1] = (short)store->r_int(store);
if (coor.sa[0]==SHRT_MAX) {
*r = NULL;
return AT_READ_FAIL;
}
*r = findregion(coor.sa[0], coor.sa[1]);
if (*r==NULL) {
ur_add(coor, (void**)r, resolve_region);
}
} else {
variant uid;
uid.i = store->r_int(store);
if (uid.i==0) {
*r = NULL;
} else {
*r = findregionbyid((unsigned int)uid.i);
if (*r==NULL) {
ur_add(uid, (void**)r, resolve_regionbyid);
}
region * r = NULL;
if (id.i!=0) {
r = findregionbyid((unsigned int)id.i);
if (r==NULL) {
return -1;
}
}
return AT_READ_OK;
*(region**)address = r;
return 0;
}
variant
read_region_reference(struct storage * store)
{
variant result;
if (store->version<UIDHASH_VERSION) {
result.sa[0] = (short)store->r_int(store);
result.sa[1] = (short)store->r_int(store);
} else {
result.i = store->r_int(store);
}
return result;
}
void

View File

@ -229,8 +229,6 @@ extern const short delta_x[MAXDIRECTIONS];
extern const short delta_y[MAXDIRECTIONS];
extern direction_t dir_invert(direction_t dir);
extern int production(const struct region *r);
extern int read_region_reference(struct region ** r, struct storage * store);
extern void write_region_reference(const struct region * r, struct storage * store);
void region_setowner(struct region * r, struct faction * owner);
extern struct faction * region_owner(const struct region * r);
@ -244,6 +242,11 @@ extern struct region * r_connect(const struct region *, direction_t dir);
extern void free_regions(void);
extern void write_region_reference(const struct region * r, struct storage * store);
extern variant read_region_reference(struct storage * store);
extern int resolve_region_coor(variant id, void * address);
extern int resolve_region_id(variant id, void * address);
#define RESOLVE_REGION(version) ((version<UIDHASH_VERSION)?resolve_region_coor:resolve_region_id)
#ifdef __cplusplus
}
#endif

View File

@ -198,9 +198,11 @@ remove_ship(ship ** slist, ship * sh)
}
sunhash(sh);
while (*slist && *slist!=sh) slist = &(*slist)->next;
assert(*slist);
*slist = sh->next;
sh->next = deleted_ships;
deleted_ships = sh;
sh->region = NULL;
}
void

View File

@ -523,10 +523,11 @@ a_writesiege(const attrib * a, struct storage * store)
int
a_readsiege(attrib * a, struct storage * store)
{
struct building * b;
int result = read_building_reference(&b, store);
a->data.v = b;
return result;
int result = read_reference(&a->data.v, store, read_building_reference, resolve_building);
if (result==0 && !a->data.v) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
attrib_type at_siege = {
@ -624,27 +625,26 @@ write_unit_reference(const unit * u, struct storage * store)
store->w_id(store, u?u->no:0);
}
void
int
resolve_unit(variant id, void * address)
{
unit * u = ufindhash(id.i);
unit * u = NULL;
if (id.i!=0) {
u = findunit(id.i);
if (u==NULL) {
return -1;
}
}
*(unit**)address = u;
return 0;
}
int
read_unit_reference(unit ** up, struct storage * store)
variant
read_unit_reference(struct storage * store)
{
variant var;
assert(up!=NULL);
var.i = store->r_id(store);
if (var.i<=0) {
*up = NULL;
return AT_READ_FAIL;
}
*up = findunit(var.i);
if (*up==NULL) ur_add(var, (void**)up, resolve_unit);
return AT_READ_OK;
return var;
}
attrib_type at_stealth = {

View File

@ -182,9 +182,9 @@ int gift_items(struct unit * u, int flags);
void make_zombie(unit * u);
/* see resolve.h */
extern void resolve_unit(variant data, void * address);
extern int resolve_unit(variant data, void * address);
extern void write_unit_reference(const struct unit * u, struct storage * store);
extern int read_unit_reference(unit ** up, struct storage * store);
extern variant read_unit_reference(struct storage * store);
extern void leave(struct region * r, struct unit * u);
extern void leave_ship(unit * u);

View File

@ -418,9 +418,10 @@ caldera_write(const trigger * t, struct storage * store)
static int
caldera_read(trigger * t, struct storage * store)
{
building * b;
read_building_reference(&b, store);
t->data.v = b;
int rb = read_reference(&t->data.v, store, read_building_reference, resolve_building);
if (rb==0 && !t->data.v) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}

View File

@ -12,8 +12,8 @@
#include <config.h>
#include <kernel/eressea.h>
#include "settings.h"
#if WORMHOLE_MODULE
#include "wormhole.h"
/* kernel includes */
@ -109,19 +109,33 @@ wormhole_write(const struct attrib * a, storage * store)
write_region_reference(data->exit, store);
}
/** conversion code, turn 573, 2008-05-23 */
static int
resolve_exit(variant id, void * address)
{
building * b = findbuilding(id.i);
region ** rp = address;
if (b) {
*rp = b->region;
return 0;
}
return -1;
}
static int
wormhole_read(struct attrib * a, storage * store)
{
wormhole_data * data = (wormhole_data*)a->data.v;
read_building_reference(&data->entry, store);
if (store->version<UIDHASH_VERSION) {
building * b;
read_building_reference(&b, store);
if (b) data->exit = b->region;
} else {
read_region_reference(&data->exit, store);
resolve_fun resolver = (store->version<UIDHASH_VERSION)?resolve_exit:resolve_region_id;
read_fun reader = (store->version<UIDHASH_VERSION)?read_building_reference:read_region_reference;
int rb = read_reference(&data->entry, store, read_building_reference, resolve_building);
int rr = read_reference(&data->exit, store, reader, resolver);
if (rb==0 && rr==0) {
if (!data->exit || !data->entry) {
return AT_READ_FAIL;
}
}
/* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */
return AT_READ_OK;
}
@ -204,4 +218,3 @@ register_wormholes(void)
{
at_register(&at_wormhole);
}
#endif

View File

@ -15,10 +15,6 @@
#define H_MOD_WORMHOLE
#ifdef __cplusplus
extern "C" {
#endif
#if WORMHOLE_MODULE == 0
#error "must define WORMHOLE_MODULE to use this module"
#endif
extern void create_wormholes(void);

View File

@ -24,10 +24,12 @@
#include <kernel/unit.h>
/* util includes */
#include <util/attrib.h>
#include <util/base36.h>
#include <util/event.h>
#include <util/goodies.h>
#include <util/storage.h>
#include <util/resolve.h>
/* libc includes */
#include <stdlib.h>
@ -48,10 +50,11 @@ xmasgate_write(const trigger * t, struct storage * store)
static int
xmasgate_read(trigger * t, struct storage * store)
{
building * b;
int result =read_building_reference(&b, store);
t->data.v = b;
return result;
int bc = read_reference(&t->data.v, store, read_building_reference, resolve_building);
if (bc==0 && !t->data.v) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
struct trigger_type tt_xmasgate = {

View File

@ -44,7 +44,6 @@
#define SCORE_MODULE 1
#define MUSEUM_MODULE 1
#define ARENA_MODULE 1
#define WORMHOLE_MODULE 1
#define XECMD_MODULE 1
#define KARMA_MODULE 0
#define DUNGEON_MODULE 0

View File

@ -27,6 +27,7 @@
/* util includes */
#include <util/attrib.h>
#include <util/event.h>
#include <util/resolve.h>
#include <util/umlaut.h>
#include <util/storage.h>
@ -61,37 +62,40 @@ alp_done(attrib * a)
static int
alp_verify(attrib * a)
{
alp_data * ad = (alp_data*)a->data.v;
if (ad->mage && ad->target) return 1;
return 0; /* kaputt */
alp_data * ad = (alp_data*)a->data.v;
if (ad->mage && ad->target) return 1;
return 0; /* remove the attribute */
}
static void
alp_write(const attrib * a, struct storage * store)
{
alp_data * ad = (alp_data*)a->data.v;
write_unit_reference(ad->mage, store);
write_unit_reference(ad->target, store);
alp_data * ad = (alp_data*)a->data.v;
write_unit_reference(ad->mage, store);
write_unit_reference(ad->target, store);
}
static int
alp_read(attrib * a, struct storage * store)
{
alp_data * ad = (alp_data*)a->data.v;
int m = read_unit_reference(&ad->mage, store);
int t = read_unit_reference(&ad->target, store);
if (m!=AT_READ_OK || t!=AT_READ_OK) return AT_READ_FAIL;
return AT_READ_OK;
alp_data * ad = (alp_data*)a->data.v;
int rm = read_reference(&ad->mage, store, read_unit_reference, resolve_unit);
int rt = read_reference(&ad->target, store, read_unit_reference, resolve_unit);
if (rt==0 && rm==0 && (!ad->target || !ad->mage)) {
/* the target or mage disappeared. */
return AT_READ_FAIL;
}
return AT_READ_OK;
}
static attrib_type at_alp = {
"alp",
alp_init,
alp_done,
alp_verify,
alp_write,
alp_read,
ATF_UNIQUE
"alp",
alp_init,
alp_done,
alp_verify,
alp_write,
alp_read,
ATF_UNIQUE
};
int

View File

@ -2668,7 +2668,7 @@ typedef struct bresvole {
curse * self;
} bresolve;
static void resolve_buddy(variant data, void * addr);
static int resolve_buddy(variant data, void * addr);
static int
cw_read(attrib * a, storage * store)
@ -2701,40 +2701,47 @@ attrib_type at_cursewall =
ATF_CURSE
};
static void
static int
resolve_buddy(variant data, void * addr)
{
curse * result = NULL;
bresolve * br = (bresolve*)data.v;
border * b = find_border(br->id);
if (b && b->from && b->to) {
attrib * a = a_find(b->from->attribs, &at_cursewall);
while (a && a->data.v!=br->self) {
curse * c = (curse*)a->data.v;
wallcurse * wc = (wallcurse*)c->data.v;
if (wc->wall->id==br->id) break;
a = a->next;
}
if (!a || a->type!=&at_cursewall) {
a = a_find(b->to->attribs, &at_cursewall);
while (a && a->type==&at_cursewall && a->data.v!=br->self) {
if (br->id>=0) {
border * b = find_border(br->id);
if (b && b->from && b->to) {
attrib * a = a_find(b->from->attribs, &at_cursewall);
while (a && a->data.v!=br->self) {
curse * c = (curse*)a->data.v;
wallcurse * wc = (wallcurse*)c->data.v;
if (wc->wall->id==br->id) break;
a = a->next;
}
}
if (a && a->type==&at_cursewall) {
curse * c = (curse*)a->data.v;
free(br);
result = c;
if (!a || a->type!=&at_cursewall) {
a = a_find(b->to->attribs, &at_cursewall);
while (a && a->type==&at_cursewall && a->data.v!=br->self) {
curse * c = (curse*)a->data.v;
wallcurse * wc = (wallcurse*)c->data.v;
if (wc->wall->id==br->id) break;
a = a->next;
}
}
if (a && a->type==&at_cursewall) {
curse * c = (curse*)a->data.v;
free(br);
result = c;
}
} else {
/* fail, object does not exist (but if you're still loading then
* you may want to try again later) */
return -1;
}
}
*(curse**)addr = result;
return 0;
}
static const char *
b_namefirewall(const border * b, const region * r, const faction * f, int gflags)
{
@ -2776,7 +2783,7 @@ wall_read(border * b, storage * store)
ur_add(mno, &fd->mage, resolve_unit);
}
} else {
read_unit_reference(&fd->mage, store);
read_reference(&fd->mage, store, read_unit_reference, resolve_unit);
}
fd->force = store->r_int(store);
if (store->version>=NOBORDERATTRIBS_VERSION) {
@ -3190,8 +3197,8 @@ dc_read_compat(struct attrib * a, storage * store)
u = findunit(var.i);
/* this only affects really old data. no need to change: */
rx = store->r_int(store);
ry = store->r_int(store);
rx = (short)store->r_int(store);
ry = (short)store->r_int(store);
r = findregion(rx, ry);
if (r!=NULL) {

View File

@ -78,19 +78,16 @@ changefaction_write(const trigger * t, struct storage * store)
{
changefaction_data * td = (changefaction_data*)t->data.v;
write_unit_reference(td->unit, store);
write_faction_reference(td->faction, store);
write_faction_reference(td->faction, store);
}
static int
changefaction_read(trigger * t, struct storage * store)
{
changefaction_data * td = (changefaction_data*)t->data.v;
int u = read_unit_reference(&td->unit, store);
int f = read_faction_reference(&td->faction, store);
if (u!=AT_READ_OK || f!=AT_READ_OK) return AT_READ_FAIL;
return AT_READ_OK;
changefaction_data * td = (changefaction_data*)t->data.v;
read_reference(&td->unit, store, read_unit_reference, resolve_unit);
read_reference(&td->faction, store, read_faction_reference, resolve_faction);
return AT_READ_OK;
}
trigger_type tt_changefaction = {

View File

@ -86,12 +86,11 @@ changerace_write(const trigger * t, struct storage * store)
static int
changerace_read(trigger * t, struct storage * store)
{
changerace_data * td = (changerace_data*)t->data.v;
int uc = read_unit_reference(&td->u, store);
int rc = read_race_reference(&td->race, store);
int ic = read_race_reference(&td->irace, store);
if (uc!=AT_READ_OK || rc!=AT_READ_OK || ic!=AT_READ_OK) return AT_READ_FAIL;
return AT_READ_OK;
changerace_data * td = (changerace_data*)t->data.v;
read_reference(&td->u, store, read_unit_reference, resolve_unit);
td->race = (const struct race*)read_race_reference(store).v;
td->irace = (const struct race*)read_race_reference(store).v;
return AT_READ_OK;
}
trigger_type tt_changerace = {

View File

@ -65,10 +65,11 @@ clonedied_write(const trigger * t, struct storage * store)
static int
clonedied_read(trigger * t, struct storage * store)
{
unit * u;
int result = read_unit_reference(&u, store);
t->data.v = u;
return result;
int result = read_reference(&t->data.v, store, read_unit_reference, resolve_unit);
if (result==0 && t->data.v==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
trigger_type tt_clonedied = {

View File

@ -97,31 +97,31 @@ createcurse_write(const trigger * t, struct storage * store)
static int
createcurse_read(trigger * t, struct storage * store)
{
createcurse_data * td = (createcurse_data*)t->data.v;
char zText[128];
createcurse_data * td = (createcurse_data*)t->data.v;
char zText[128];
read_unit_reference(&td->mage, store);
read_unit_reference(&td->target, store);
read_reference(&td->mage, store, read_unit_reference, resolve_unit);
read_reference(&td->target, store, read_unit_reference, resolve_unit);
if (store->version<CURSETYPE_VERSION) {
int id1, id2;
id1 = store->r_int(store);
id2 = store->r_int(store);
assert(id2==0);
td->vigour = store->r_flt(store);
td->duration = store->r_int(store);
td->effect = store->r_int(store);
td->men = store->r_int(store);
td->type = ct_find(oldcursename(id1));
} else {
store->r_tok_buf(store, zText, sizeof(zText));
td->type = ct_find(zText);
td->vigour = store->r_flt(store);
td->duration = store->r_int(store);
td->effect = store->r_int(store);
td->men = store->r_int(store);
}
return AT_READ_OK;
if (store->version<CURSETYPE_VERSION) {
int id1, id2;
id1 = store->r_int(store);
id2 = store->r_int(store);
assert(id2==0);
td->vigour = store->r_flt(store);
td->duration = store->r_int(store);
td->effect = store->r_int(store);
td->men = store->r_int(store);
td->type = ct_find(oldcursename(id1));
} else {
store->r_tok_buf(store, zText, sizeof(zText));
td->type = ct_find(zText);
td->vigour = store->r_flt(store);
td->duration = store->r_int(store);
td->effect = store->r_int(store);
td->men = store->r_int(store);
}
return AT_READ_OK;
}
trigger_type tt_createcurse = {

View File

@ -21,6 +21,7 @@
#include <kernel/unit.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/version.h>
/* util includes */
#include <util/attrib.h>
@ -89,16 +90,18 @@ createunit_write(const trigger * t, struct storage * store)
static int
createunit_read(trigger * t, struct storage * store)
{
createunit_data * td = (createunit_data*)t->data.v;
createunit_data * td = (createunit_data*)t->data.v;
int uc = read_faction_reference(&td->f, store);
int rc = read_region_reference(&td->r, store);
int ic = read_race_reference(&td->race, store);
int uc = read_reference(&td->f, store, read_faction_reference, resolve_faction);
int rc = read_reference(&td->r, store, read_region_reference, RESOLVE_REGION(store->version));
td->race = (const struct race*)read_race_reference(store).v;
td->number = store->r_int(store);
if (uc==0 && rc==0) {
if (!td->f || !td->r) return AT_READ_FAIL;
}
td->number = store->r_int(store);
if (uc!=AT_READ_OK || rc!=AT_READ_OK || ic!=AT_READ_OK) return AT_READ_FAIL;
return AT_READ_OK;
return AT_READ_OK;
}
trigger_type tt_createunit = {

View File

@ -17,11 +17,13 @@
#include <kernel/building.h>
#include <kernel/region.h>
#include <kernel/unit.h>
#include <kernel/version.h>
/* util includes */
#include <util/attrib.h>
#include <util/event.h>
#include <util/log.h>
#include <util/resolve.h>
#include <util/storage.h>
/* libc includes */
@ -73,10 +75,12 @@ gate_read(trigger * t, struct storage * store)
{
gate_data * gd = (gate_data*)t->data.v;
int bc = read_building_reference(&gd->gate, store);
int rc = read_region_reference(&gd->target, store);
int bc = read_reference(&gd->gate, store, read_building_reference, resolve_building);
int rc = read_reference(&gd->target, store, read_region_reference, RESOLVE_REGION(store->version));
if (rc!=AT_READ_OK || bc!=AT_READ_OK) return AT_READ_FAIL;
if (bc==0 && rc==0) {
if (!gd->gate || !gd->target) return AT_READ_FAIL;
}
return AT_READ_OK;
}

View File

@ -83,17 +83,20 @@ giveitem_write(const trigger * t, struct storage * store)
static int
giveitem_read(trigger * t, struct storage * store)
{
giveitem_data * td = (giveitem_data*)t->data.v;
char zText[128];
giveitem_data * td = (giveitem_data*)t->data.v;
char zText[128];
read_unit_reference(&td->u, store);
int result = read_reference(&td->u, store, read_unit_reference, resolve_unit);
td->number = store->r_int(store);
store->r_tok_buf(store, zText, sizeof(zText));
td->itype = it_find(zText);
assert(td->itype);
td->number = store->r_int(store);
store->r_tok_buf(store, zText, sizeof(zText));
td->itype = it_find(zText);
assert(td->itype);
return AT_READ_OK;
if (result==0 && td->u==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
trigger_type tt_giveitem = {

View File

@ -20,6 +20,7 @@
#include <kernel/unit.h>
/* util includes */
#include <util/attrib.h>
#include <util/base36.h>
#include <util/event.h>
#include <util/log.h>
@ -58,10 +59,11 @@ killunit_write(const trigger * t, struct storage * store)
static int
killunit_read(trigger * t, struct storage * store)
{
unit * u;
int result = read_unit_reference(&u, store);
t->data.v = u;
return result;
int result = read_reference(&t->data.v, store, read_unit_reference, resolve_unit);
if (result==0 && t->data.v==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
trigger_type tt_killunit = {

View File

@ -85,15 +85,9 @@ static int
removecurse_read(trigger * t, struct storage * store)
{
removecurse_data * td = (removecurse_data*)t->data.v;
variant var;
read_unit_reference(&td->target, store);
var.i = store->r_int(store);
td->curse = cfindhash(var.i);
if (td->curse==NULL) {
ur_add(var, &td->curse, resolve_curse);
}
read_reference(&td->target, store, read_unit_reference, resolve_unit);
read_reference(&td->curse, store, read_int, resolve_curse);
return AT_READ_OK;
}

View File

@ -26,6 +26,7 @@
#include <kernel/unit.h>
/* util includes */
#include <util/attrib.h>
#include <util/base36.h>
#include <util/event.h>
#include <util/log.h>
@ -120,10 +121,11 @@ shock_write(const trigger * t, struct storage * store)
static int
shock_read(trigger * t, struct storage * store)
{
unit * u;
int result = read_unit_reference(&u, store);
t->data.v = u;
return result;
int result = read_reference(&t->data.v, store, read_unit_reference, resolve_unit);
if (result==0 && t->data.v==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
trigger_type tt_shock = {

View File

@ -14,13 +14,16 @@
#include "unguard.h"
/* kernel includes */
#include <util/attrib.h>
#include <kernel/building.h>
#include <kernel/region.h>
#include <kernel/unit.h>
/* util includes */
#include <util/attrib.h>
#include <util/event.h>
#include <util/log.h>
#include <util/resolve.h>
/* libc includes */
#include <stdlib.h>
@ -49,10 +52,11 @@ unguard_write(const trigger * t, struct storage * store)
static int
unguard_read(trigger * t, struct storage * store)
{
building * b;
int result = read_building_reference(&b, store);
t->data.v = b;
return result;
int rb = read_reference(&t->data.v, store, read_building_reference, resolve_building);
if (rb==0 && !t->data.v) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
struct trigger_type tt_unguard = {

View File

@ -89,13 +89,16 @@ unitmessage_read(trigger * t, struct storage * store)
unitmessage_data * td = (unitmessage_data*)t->data.v;
char zText[256];
read_unit_reference(&td->target, store);
int result = read_reference(&td->target, store, read_unit_reference, resolve_unit);
td->string = store->r_tok(store);
td->type = store->r_int(store);
td->level = store->r_int(store);
td->string = strdup(zText);
if (result==0 && td->target==NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}

View File

@ -77,8 +77,8 @@ extern void a_write(struct storage * store, const attrib * attribs);
#define NO_WRITE NULL
#define NO_READ NULL
#define AT_READ_OK 4711
#define AT_READ_FAIL -4711
#define AT_READ_OK 0
#define AT_READ_FAIL -1
#ifdef __cplusplus
}

View File

@ -23,6 +23,7 @@
#include <assert.h>
#include <stdlib.h>
#include "resolve.h"
#include "storage.h"
#include "variant.h"
typedef struct unresolved {
@ -39,6 +40,25 @@ static unresolved * ur_list;
static unresolved * ur_begin;
static unresolved * ur_current;
variant
read_int(struct storage * store)
{
variant var;
var.i = store->r_int(store);
return var;
}
int
read_reference(void * address, storage * store, read_fun reader, resolve_fun resolver)
{
variant var = reader(store);
int result = resolver(var, address);
if (result!=0) {
ur_add(var, address, resolver);
}
return result;
}
void
ur_add(variant data, void * ptrptr, resolve_fun fun)
{

View File

@ -16,15 +16,21 @@
#define RESOLVE_H
#include "variant.h"
struct storage;
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*resolve_fun)(variant data, void * address);
extern void ur_add(variant data, void * ptrptr, resolve_fun fun);
typedef int (*resolve_fun)(variant data, void * address);
typedef variant (*read_fun)(struct storage* store);
extern int read_reference(void * address, struct storage * store, read_fun reader, resolve_fun resolver);
extern void ur_add(variant data, void * address, resolve_fun fun);
extern void resolve(void);
extern variant read_int(struct storage * store);
#ifdef __cplusplus
}
#endif

View File

@ -27,9 +27,7 @@
#if ARENA_MODULE
#include <modules/arena.h>
#endif
#if WORMHOLE_MODULE
#include <modules/wormhole.h>
#endif
#if DUNGEON_MODULE
#include <modules/dungeon.h>
#endif

View File

@ -41,9 +41,7 @@
#if MUSEUM_MODULE
#include <modules/museum.h>
#endif
#if WORMHOLE_MODULE
#include <modules/wormhole.h>
#endif
#if ARENA_MODULE
#include <modules/arena.h>
#endif
@ -225,9 +223,7 @@ game_init(void)
#if ARENA_MODULE
register_arena();
#endif
#if WORMHOLE_MODULE
register_wormholes();
#endif
register_itemtypes();
register_xmlreader();

View File

@ -61,6 +61,7 @@
<skill name="unarmed" enable="true"/>
<param name="NewbieImmunity" value="8"/>
<param name="modules.wormholes" value="1"/>
<param name="entertain.base" value="0"/>
<param name="entertain.perlevel" value="20"/>
<param name="nmr.timeout" value="4"/>

View File

@ -1,12 +1,12 @@
-- -*- coding: utf-8 -*-
function test_locales()
local skills = { "", "herb", "kraut", "Kräute", "Kraeut", "k", "kra", "MAGIE" }
for k,v in pairs(skills) do
str = test.loc_skill("de", v)
io.stdout:write(v, "\t", tostring(str), " ", tostring(get_string("de", "skill::" .. tostring(str))), "\n")
end
return 0
local skills = { "", "herb", "kraut", "Kräute", "Kraeut", "k", "kra", "MAGIE" }
for k,v in pairs(skills) do
str = test.loc_skill("de", v)
io.stdout:write(v, "\t", tostring(str), " ", tostring(get_string("de", "skill::" .. tostring(str))), "\n")
end
return 0
end
function loadscript(name)
@ -30,38 +30,38 @@ end
--test_locales()
function run_turn()
plan_monsters()
process_orders()
spawn_dragons()
spawn_undead()
spawn_braineaters(0.25)
autoseed(basepath .. "/newfactions", false)
plan_monsters()
process_orders()
spawn_dragons()
spawn_undead()
spawn_braineaters(0.25)
autoseed(basepath .. "/newfactions", false)
end
function test_free()
read_game("571.dat", "binary")
read_orders("orders.571")
run_turn()
free_game()
read_game("570.dat", "binary")
read_orders("orders.570")
run_turn()
free_game()
read_game("571.dat", "binary")
read_orders("orders.571")
run_turn()
free_game()
read_game("570.dat", "binary")
read_orders("orders.570")
run_turn()
free_game()
end
function test_hse()
read_game("50", "text")
write_game("50.dat", "binary")
write_game("50.txt.1", "text")
end
loadscript("default.lua")
run_scripts()
-- go
local now = os.clock()
-- test_free()
read_game("50", "text")
write_game("50.dat", "binary")
write_game("50.txt.1", "text")
free_game()
read_game("50", "test")
write_game("50.txt.2", "text")
free_game()
test_free()
-- test_hse()
local elapsed = os.clock() - now
print(elapsed)
-- text: 50.574