forked from github/server
- free_gamedata() is perfect.
- we can now save region uids for references, not x,y
This commit is contained in:
parent
b9fbf06614
commit
43d73a6b45
6 changed files with 99 additions and 66 deletions
|
@ -520,10 +520,8 @@ write_borders(struct storage * store)
|
||||||
if (b->type->valid && !b->type->valid(b)) continue;
|
if (b->type->valid && !b->type->valid(b)) continue;
|
||||||
store->w_tok(store, b->type->__name);
|
store->w_tok(store, b->type->__name);
|
||||||
store->w_int(store, b->id);
|
store->w_int(store, b->id);
|
||||||
store->w_int(store, b->from->x);
|
store->w_int(store, b->from->uid);
|
||||||
store->w_int(store, b->from->y);
|
store->w_int(store, b->to->uid);
|
||||||
store->w_int(store, b->to->x);
|
|
||||||
store->w_int(store, b->to->y);
|
|
||||||
|
|
||||||
if (b->type->write) b->type->write(b, store);
|
if (b->type->write) b->type->write(b, store);
|
||||||
store->w_brk(store);
|
store->w_brk(store);
|
||||||
|
@ -537,7 +535,6 @@ int
|
||||||
read_borders(struct storage * store)
|
read_borders(struct storage * store)
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
short fx, fy, tx, ty;
|
|
||||||
unsigned int bid = 0;
|
unsigned int bid = 0;
|
||||||
char zText[32];
|
char zText[32];
|
||||||
border * b;
|
border * b;
|
||||||
|
@ -547,18 +544,19 @@ read_borders(struct storage * store)
|
||||||
store->r_tok_buf(store, zText, sizeof(zText));
|
store->r_tok_buf(store, zText, sizeof(zText));
|
||||||
if (!strcmp(zText, "end")) break;
|
if (!strcmp(zText, "end")) break;
|
||||||
bid = store->r_int(store);
|
bid = store->r_int(store);
|
||||||
fx = (short)store->r_int(store);
|
if (store->version<UIDHASH_VERSION) {
|
||||||
fy = (short)store->r_int(store);
|
short fx, fy, tx, ty;
|
||||||
tx = (short)store->r_int(store);
|
fx = (short)store->r_int(store);
|
||||||
ty = (short)store->r_int(store);
|
fy = (short)store->r_int(store);
|
||||||
|
tx = (short)store->r_int(store);
|
||||||
from = findregion(fx, fy);
|
ty = (short)store->r_int(store);
|
||||||
if (from==NULL) {
|
from = findregion(fx, fy);
|
||||||
log_error(("border for unknown region %d,%d\n", fx, fy));
|
to = findregion(tx, ty);
|
||||||
}
|
} else {
|
||||||
to = findregion(tx, ty);
|
unsigned int fid = (unsigned int)store->r_int(store);
|
||||||
if (to==NULL) {
|
unsigned int tid = (unsigned int)store->r_int(store);
|
||||||
log_error(("border for unknown region %d,%d\n", tx, ty));
|
from = findregionbyid(fid);
|
||||||
|
to = findregionbyid(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
type = find_bordertype(zText);
|
type = find_bordertype(zText);
|
||||||
|
|
|
@ -389,27 +389,50 @@ attrib_type at_moveblock = {
|
||||||
static region * regionhash[RMAXHASH];
|
static region * regionhash[RMAXHASH];
|
||||||
static int dummy_data;
|
static int dummy_data;
|
||||||
static region * dummy_ptr = (region*)&dummy_data; /* a funny hack */
|
static region * dummy_ptr = (region*)&dummy_data; /* a funny hack */
|
||||||
static unsigned int uidhash[MAXREGIONS];
|
|
||||||
|
typedef struct uidhashentry {
|
||||||
|
unsigned int uid;
|
||||||
|
region * r;
|
||||||
|
} uidhashentry;
|
||||||
|
static uidhashentry uidhash[MAXREGIONS];
|
||||||
|
|
||||||
|
struct region *
|
||||||
|
findregionbyid(unsigned int uid)
|
||||||
|
{
|
||||||
|
int key = uid % MAXREGIONS;
|
||||||
|
while (uidhash[key].uid!=0 && uidhash[key].uid!=uid) ++key;
|
||||||
|
return uidhash[key].r;
|
||||||
|
}
|
||||||
|
|
||||||
#define DELMARKER dummy_ptr
|
#define DELMARKER dummy_ptr
|
||||||
|
|
||||||
unsigned int
|
static void
|
||||||
generate_region_id(void)
|
unhash_uid(region * r)
|
||||||
{
|
{
|
||||||
unsigned int uid;
|
int key = r->uid % MAXREGIONS;
|
||||||
|
assert(r->uid);
|
||||||
|
while (uidhash[key].uid!=0 && uidhash[key].uid!=r->uid) ++key;
|
||||||
|
assert(uidhash[key].r==r);
|
||||||
|
uidhash[key].r = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hash_uid(region * r)
|
||||||
|
{
|
||||||
|
unsigned int uid = r->uid;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int key;
|
if (uid!=0) {
|
||||||
do {
|
int key = uid % MAXREGIONS;
|
||||||
uid = rng_int();
|
while (uidhash[key].uid!=0 && uidhash[key].uid!=uid) ++key;
|
||||||
} while (uid==0);
|
if (uidhash[key].uid==0) {
|
||||||
key = uid % MAXREGIONS;
|
uidhash[key].uid = uid;
|
||||||
while (uidhash[key]!=0 && uidhash[key]!=uid) ++key;
|
uidhash[key].r = r;
|
||||||
if (uidhash[key]==0) {
|
break;
|
||||||
uidhash[key] = uid;
|
}
|
||||||
break;
|
assert(uidhash[key].r!=r || !"duplicate registration");
|
||||||
}
|
}
|
||||||
|
uid = rng_int();
|
||||||
}
|
}
|
||||||
return uid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HASH_STATISTICS 1
|
#define HASH_STATISTICS 1
|
||||||
|
@ -837,11 +860,11 @@ new_region(short x, short y, unsigned int uid)
|
||||||
r = calloc(1, sizeof(region));
|
r = calloc(1, sizeof(region));
|
||||||
r->x = x;
|
r->x = x;
|
||||||
r->y = y;
|
r->y = y;
|
||||||
if (uid==0) uid = generate_region_id();
|
|
||||||
r->uid = uid;
|
r->uid = uid;
|
||||||
r->age = 1;
|
r->age = 1;
|
||||||
r->planep = findplane(x, y);
|
r->planep = findplane(x, y);
|
||||||
rhash(r);
|
rhash(r);
|
||||||
|
hash_uid(r);
|
||||||
if (last)
|
if (last)
|
||||||
addlist(&last, r);
|
addlist(&last, r);
|
||||||
else
|
else
|
||||||
|
@ -865,6 +888,7 @@ remove_region(region ** rlist, region * r)
|
||||||
}
|
}
|
||||||
|
|
||||||
runhash(r);
|
runhash(r);
|
||||||
|
unhash_uid(r);
|
||||||
while (*rlist && *rlist!=r) rlist=&(*rlist)->next;
|
while (*rlist && *rlist!=r) rlist=&(*rlist)->next;
|
||||||
assert(*rlist==r);
|
assert(*rlist==r);
|
||||||
*rlist = r->next;
|
*rlist = r->next;
|
||||||
|
@ -1217,20 +1241,44 @@ production(const region *r)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
resolve_region(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;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
read_region_reference(region ** r, struct storage * store)
|
read_region_reference(region ** r, struct storage * store)
|
||||||
{
|
{
|
||||||
variant coor;
|
if (store->version<UIDHASH_VERSION) {
|
||||||
coor.sa[0] = (short)store->r_int(store);
|
variant coor;
|
||||||
coor.sa[1] = (short)store->r_int(store);
|
coor.sa[0] = (short)store->r_int(store);
|
||||||
if (coor.sa[0]==SHRT_MAX) {
|
coor.sa[1] = (short)store->r_int(store);
|
||||||
*r = NULL;
|
if (coor.sa[0]==SHRT_MAX) {
|
||||||
return AT_READ_FAIL;
|
*r = NULL;
|
||||||
}
|
return AT_READ_FAIL;
|
||||||
*r = findregion(coor.sa[0], coor.sa[1]);
|
}
|
||||||
|
*r = findregion(coor.sa[0], coor.sa[1]);
|
||||||
if (*r==NULL) {
|
if (*r==NULL) {
|
||||||
ur_add(coor, (void**)r, resolve_region);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return AT_READ_OK;
|
return AT_READ_OK;
|
||||||
}
|
}
|
||||||
|
@ -1239,22 +1287,12 @@ void
|
||||||
write_region_reference(const region * r, struct storage * store)
|
write_region_reference(const region * r, struct storage * store)
|
||||||
{
|
{
|
||||||
if (r) {
|
if (r) {
|
||||||
store->w_int(store, r->x);
|
store->w_int(store, r->uid);
|
||||||
store->w_int(store, r->y);
|
} else {
|
||||||
}
|
store->w_int(store, 0);
|
||||||
else {
|
|
||||||
store->w_int(store, SHRT_MAX);
|
|
||||||
store->w_int(store, SHRT_MAX);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
resolve_region(variant id, void * address) {
|
|
||||||
region * r = findregion(id.sa[0], id.sa[1]);
|
|
||||||
*(region**)address = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct message_list *
|
struct message_list *
|
||||||
r_getmessages(const struct region * r, const struct faction * viewer)
|
r_getmessages(const struct region * r, const struct faction * viewer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -146,6 +146,7 @@ int distance(const struct region*, const struct region*);
|
||||||
int koor_distance(int ax, int ay, int bx, int by) ;
|
int koor_distance(int ax, int ay, int bx, int by) ;
|
||||||
extern direction_t reldirection(const struct region * from, const struct region * to);
|
extern direction_t reldirection(const struct region * from, const struct region * to);
|
||||||
extern struct region * findregion(short x, short y);
|
extern struct region * findregion(short x, short y);
|
||||||
|
extern struct region * findregionbyid(unsigned int uid);
|
||||||
|
|
||||||
extern struct attrib_type at_direction;
|
extern struct attrib_type at_direction;
|
||||||
extern struct attrib_type at_moveblock;
|
extern struct attrib_type at_moveblock;
|
||||||
|
@ -219,7 +220,6 @@ extern int r_demand(const struct region * r, const struct luxury_type * ltype);
|
||||||
extern const char * regionname(const struct region * r, const struct faction * f);
|
extern const char * regionname(const struct region * r, const struct faction * f);
|
||||||
extern const char * write_regionname(const struct region * r, const struct faction * f, char * buffer, size_t size);
|
extern const char * write_regionname(const struct region * r, const struct faction * f, char * buffer, size_t size);
|
||||||
|
|
||||||
extern void resolve_region(variant data, void * address);
|
|
||||||
extern struct region * new_region(short x, short y, unsigned int uid);
|
extern struct region * new_region(short x, short y, unsigned int uid);
|
||||||
extern void remove_region(region ** rlist, region * r);
|
extern void remove_region(region ** rlist, region * r);
|
||||||
extern void terraform(struct region * r, terrain_t terrain);
|
extern void terraform(struct region * r, terrain_t terrain);
|
||||||
|
@ -242,8 +242,6 @@ extern struct region * r_connect(const struct region *, direction_t dir);
|
||||||
# define rconnect(r, dir) r_connect(r, dir)
|
# define rconnect(r, dir) r_connect(r, dir)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern unsigned int generate_region_id(void);
|
|
||||||
|
|
||||||
extern void free_regions(void);
|
extern void free_regions(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -926,14 +926,12 @@ readregion(struct storage * store, short x, short y)
|
||||||
|
|
||||||
if (store->version>=UID_VERSION) {
|
if (store->version>=UID_VERSION) {
|
||||||
uid = store->r_int(store);
|
uid = store->r_int(store);
|
||||||
} else {
|
|
||||||
uid = generate_region_id();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r==NULL) {
|
if (r==NULL) {
|
||||||
r = new_region(x, y, uid);
|
r = new_region(x, y, uid);
|
||||||
} else {
|
} else {
|
||||||
r->uid = uid;
|
assert(uid==0 || r->uid==uid);
|
||||||
current_region = r;
|
current_region = r;
|
||||||
while (r->attribs) a_remove(&r->attribs, r->attribs);
|
while (r->attribs) a_remove(&r->attribs, r->attribs);
|
||||||
if (r->land) {
|
if (r->land) {
|
||||||
|
@ -1336,7 +1334,7 @@ writefaction(struct storage * store, const faction * f)
|
||||||
store->w_tok(store, "end");
|
store->w_tok(store, "end");
|
||||||
store->w_brk(store);
|
store->w_brk(store);
|
||||||
store->w_int(store, listlen(f->ursprung));
|
store->w_int(store, listlen(f->ursprung));
|
||||||
for(ur = f->ursprung;ur;ur=ur->next) {
|
for (ur = f->ursprung;ur;ur=ur->next) {
|
||||||
store->w_int(store, ur->id);
|
store->w_int(store, ur->id);
|
||||||
store->w_int(store, ur->x);
|
store->w_int(store, ur->x);
|
||||||
store->w_int(store, ur->y);
|
store->w_int(store, ur->y);
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#define INTPAK_VERSION 329 /* in binary, ints can get packed */
|
#define INTPAK_VERSION 329 /* in binary, ints can get packed */
|
||||||
#define NOZEROIDS_VERSION 330 /* zero is not a valid ID for anything (including factions) */
|
#define NOZEROIDS_VERSION 330 /* zero is not a valid ID for anything (including factions) */
|
||||||
#define NOBORDERATTRIBS_VERSION 331 /* border::attribs has been moved to userdata */
|
#define NOBORDERATTRIBS_VERSION 331 /* border::attribs has been moved to userdata */
|
||||||
|
#define UIDHASH_VERSION 332 /* borders use the region.uid to store */
|
||||||
|
|
||||||
#define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */
|
#define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */
|
||||||
#define RELEASE_VERSION NOBORDERATTRIBS_VERSION /* current datafile */
|
#define RELEASE_VERSION UIDHASH_VERSION /* current datafile */
|
||||||
|
|
|
@ -56,12 +56,12 @@ run_scripts()
|
||||||
local now = os.clock()
|
local now = os.clock()
|
||||||
-- test_free()
|
-- test_free()
|
||||||
read_game("571.dat", "binary")
|
read_game("571.dat", "binary")
|
||||||
write_game("571.txt.1", "text")
|
write_game("571.dat.1", "binary")
|
||||||
free_game()
|
free_game()
|
||||||
read_game("570.dat", "binary")
|
read_game("570.dat", "binary")
|
||||||
free_game()
|
free_game()
|
||||||
read_game("571.dat", "binary")
|
read_game("571.dat", "binary")
|
||||||
write_game("571.txt.2", "text")
|
write_game("571.dat.2", "binary")
|
||||||
local elapsed = os.clock() - now
|
local elapsed = os.clock() - now
|
||||||
print(elapsed)
|
print(elapsed)
|
||||||
-- text: 50.574
|
-- text: 50.574
|
||||||
|
|
Loading…
Reference in a new issue