Merge branch 'develop' of github.com:eressea/server into develop

This commit is contained in:
Enno Rehling 2016-02-10 13:41:09 +01:00
commit 3fd7a3c486
47 changed files with 465 additions and 166 deletions

View File

@ -59,11 +59,16 @@ local function write_emails(locales)
end
end
local function join_path(a, b)
if a then return a .. '/' .. b end
return b
end
local function write_addresses()
local file
local faction
file = io.open(config.basepath .. "/adressen", "w")
file = io.open(join_path(config.basepath, "adressen"), "w")
for faction in factions() do
-- print(faction.id .. " - " .. faction.locale)
file:write(tostring(faction) .. ":" .. faction.email .. ":" .. faction.info .. "\n")
@ -76,7 +81,7 @@ local function write_aliases()
local file
local faction
file = io.open(config.basepath .. "/aliases", "w")
file = io.open(join_path(config.basepath, "aliases"), "w")
for faction in factions() do
local unit
if faction.email ~= "" then
@ -90,8 +95,21 @@ local function write_aliases()
file:close()
end
local function write_htpasswd()
local out = io.open(join_path(config.basepath, "htpasswd"), "w")
if out then
for f in factions() do
if f.password then
out:write(itoa36(f.id) .. ":" .. f.password .. "\n")
end
end
out:close()
end
end
local function write_files(locales)
write_passwords()
write_htpasswd()
-- write_passwords()
write_reports()
write_summary()
end

View File

@ -1,6 +1,7 @@
PROJECT(attributes C)
SET(_TEST_FILES
stealth.test.c
key.test.c
otherfaction.test.c
)

View File

@ -125,6 +125,7 @@ void register_attributes(void)
at_register(&at_raceprefix);
at_register(&at_iceberg);
at_register(&at_key);
at_register(&at_keys);
at_register(&at_follow);
at_register(&at_targetregion);
at_register(&at_orcification);

View File

@ -30,6 +30,7 @@ attrib_type at_iceberg = {
NULL,
a_writeint,
a_readint,
NULL,
ATF_UNIQUE
};

View File

@ -22,6 +22,69 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <kernel/save.h>
#include <util/attrib.h>
#include <storage.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static void a_writekeys(const attrib *a, const void *o, storage *store) {
int i, *keys = (int *)a->data.v;
for (i = 0; i <= keys[0]; ++i) {
WRITE_INT(store, keys[i]);
}
}
static int a_readkeys(attrib * a, void *owner, struct storage *store) {
int i, *p = 0;
READ_INT(store, &i);
assert(i < 4096 && i>0);
a->data.v = p = malloc(sizeof(int)*(i + 1));
*p++ = i;
while (i--) {
READ_INT(store, p++);
}
return AT_READ_OK;
}
static int a_readkey(attrib *a, void *owner, struct storage *store) {
int res = a_readint(a, owner, store);
return (res != AT_READ_FAIL) ? AT_READ_DEPR : res;
}
attrib_type at_keys = {
"keys",
NULL,
NULL,
NULL,
a_writekeys,
a_readkeys,
NULL
};
void a_upgradekeys(attrib **alist, attrib *abegin) {
int n = 0, *keys = 0;
int i = 0, val[4];
attrib *a, *ak = a_find(*alist, &at_keys);
if (!ak) {
ak = a_add(alist, a_new(&at_keys));
keys = (int *)ak->data.v;
n = keys ? keys[0] : 0;
}
for (a = abegin; a && a->type == abegin->type; a = a->next) {
val[i++] = a->data.i;
if (i == 4) {
keys = realloc(keys, sizeof(int) * (n + i + 1));
memcpy(keys + n + 1, val, sizeof(int)*i);
n += i;
}
}
if (i > 0) {
keys = realloc(keys, sizeof(int) * (n + i + 1));
memcpy(keys + n + 1, val, sizeof(int)*i);
}
keys[0] = n + i;
}
attrib_type at_key = {
"key",
@ -29,29 +92,61 @@ attrib_type at_key = {
NULL,
NULL,
a_writeint,
a_readint,
a_readkey,
a_upgradekeys
};
attrib *add_key(attrib ** alist, int key)
void key_set(attrib ** alist, int key)
{
attrib *a = find_key(*alist, key);
if (a == NULL)
a = a_add(alist, make_key(key));
return a;
int *keys, n = 1;
attrib *a;
assert(key != 0);
a = a_find(*alist, &at_keys);
if (!a) {
a = a_add(alist, a_new(&at_keys));
}
keys = (int *)a->data.v;
if (keys) {
n = keys[0] + 1;
}
keys = realloc(keys, sizeof(int) *(n + 1));
// TODO: does insertion sort pay off here?
keys[0] = n;
keys[n] = key;
a->data.v = keys;
}
attrib *make_key(int key)
void key_unset(attrib ** alist, int key)
{
attrib *a = a_new(&at_key);
a->data.i = key;
return a;
attrib *a;
assert(key != 0);
a = a_find(*alist, &at_keys);
if (a) {
int i, *keys = (int *)a->data.v;
if (keys) {
for (i = 1; i <= keys[0]; ++i) {
if (keys[i] == key) {
keys[i] = keys[keys[0]];
keys[0]--;
}
}
}
}
}
attrib *find_key(attrib * alist, int key)
{
attrib *a = a_find(alist, &at_key);
while (a && a->type == &at_key && a->data.i != key) {
a = a->next;
bool key_get(attrib *alist, int key) {
attrib *a;
assert(key != 0);
a = a_find(alist, &at_keys);
if (a) {
int i, *keys = (int *)a->data.v;
if (keys) {
for (i = 1; i <= keys[0]; ++i) {
if (keys[i] == key) {
return true;
}
return (a && a->type == &at_key) ? a : NULL;
}
}
}
return false;
}

View File

@ -21,12 +21,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifdef __cplusplus
extern "C" {
#endif
struct attrib;
struct attrib_type;
extern struct attrib_type at_key;
extern struct attrib_type at_keys;
struct attrib *make_key(int key);
struct attrib *find_key(struct attrib *alist, int key);
struct attrib *add_key(struct attrib **alist, int key);
void key_set(struct attrib **alist, int key);
void key_unset(struct attrib **alist, int key);
bool key_get(struct attrib *alist, int key);
#ifdef __cplusplus
}

27
src/attributes/key.test.c Normal file
View File

@ -0,0 +1,27 @@
#include <platform.h>
#include "key.h"
#include <util/attrib.h>
#include <CuTest.h>
static void test_get_set_keys(CuTest *tc) {
attrib *a = 0;
key_set(&a, 42);
key_set(&a, 43);
key_set(&a, 44);
CuAssertTrue(tc, key_get(a, 42));
CuAssertTrue(tc, key_get(a, 43));
CuAssertTrue(tc, key_get(a, 44));
key_unset(&a, 42);
CuAssertTrue(tc, !key_get(a, 42));
CuAssertTrue(tc, key_get(a, 43));
CuAssertTrue(tc, key_get(a, 44));
a_removeall(&a, NULL);
}
CuSuite *get_key_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_get_set_keys);
return suite;
}

View File

@ -28,6 +28,7 @@ attrib_type at_matmod = {
NULL,
NULL,
NULL,
NULL,
ATF_PRESERVE
};

View File

@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
attrib_type at_orcification = {
"orcification", NULL, NULL, NULL, a_writeint, a_readint, ATF_UNIQUE
"orcification", NULL, NULL, NULL, a_writeint, a_readint, NULL, ATF_UNIQUE
};
attrib *make_orcification(int orcification)

View File

@ -53,7 +53,7 @@ int read_of(struct attrib *a, void *owner, struct storage *store)
}
attrib_type at_otherfaction = {
"otherfaction", NULL, NULL, NULL, write_of, read_of, ATF_UNIQUE
"otherfaction", NULL, NULL, NULL, write_of, read_of, NULL, ATF_UNIQUE
};
struct faction *get_otherfaction(const struct attrib *a)

View File

@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdlib.h>
attrib_type at_raceprefix = {
"raceprefix", NULL, a_finalizestring, NULL, a_writestring, a_readstring,
"raceprefix", NULL, a_finalizestring, NULL, a_writestring, a_readstring, NULL,
ATF_UNIQUE
};

View File

@ -49,6 +49,7 @@ attrib_type at_reduceproduction = {
age_reduceproduction,
a_writeshorts,
a_readshorts,
NULL,
ATF_UNIQUE
};

View File

@ -52,6 +52,7 @@ attrib_type at_targetregion = {
NULL,
write_targetregion,
read_targetregion,
NULL,
ATF_UNIQUE
};

View File

@ -542,11 +542,9 @@ static int tolua_region_getkey(lua_State * L)
{
region *self = (region *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
int flag = atoi36(name);
attrib *a = find_key(self->attribs, flag);
lua_pushboolean(L, a != NULL);
lua_pushboolean(L, key_get(self->attribs, flag));
return 1;
}
@ -555,14 +553,13 @@ static int tolua_region_setkey(lua_State * L)
region *self = (region *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
int value = tolua_toboolean(L, 3, 0);
int flag = atoi36(name);
attrib *a = find_key(self->attribs, flag);
if (a == NULL && value) {
add_key(&self->attribs, flag);
if (value) {
key_set(&self->attribs, flag);
}
else if (a != NULL && !value) {
a_remove(&self->attribs, a);
else {
key_unset(&self->attribs, flag);
}
return 0;
}

View File

@ -807,8 +807,7 @@ static int tolua_unit_get_flag(lua_State * L)
unit *self = (unit *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
int flag = atoi36(name);
attrib *a = find_key(self->attribs, flag);
lua_pushboolean(L, (a != NULL));
lua_pushboolean(L, key_get(self->attribs, flag));
return 1;
}
@ -818,12 +817,11 @@ static int tolua_unit_set_flag(lua_State * L)
const char *name = tolua_tostring(L, 2, 0);
int value = (int)tolua_tonumber(L, 3, 0);
int flag = atoi36(name);
attrib *a = find_key(self->attribs, flag);
if (a == NULL && value) {
add_key(&self->attribs, flag);
if (value) {
key_set(&self->attribs, flag);
}
else if (a != NULL && !value) {
a_remove(&self->attribs, a);
else {
key_unset(&self->attribs, flag);
}
return 0;
}

View File

@ -96,7 +96,7 @@ TOLUA_PKG(game);
int log_lua_error(lua_State * L)
{
const char *error = lua_tostring(L, -1);
log_fatal("LUA call failed.\n%s\n", error);
log_fatal("Lua call failed.\n%s\n", error);
lua_pop(L, 1);
return 1;
}
@ -186,8 +186,8 @@ static int tolua_getkey(lua_State * L)
{
const char *name = tolua_tostring(L, 1, 0);
int flag = atoi36(name);
attrib *a = find_key(global.attribs, flag);
lua_pushboolean(L, a != NULL);
lua_pushboolean(L, key_get(global.attribs, flag));
return 1;
}
@ -209,12 +209,11 @@ static int tolua_setkey(lua_State * L)
const char *name = tolua_tostring(L, 1, 0);
int value = tolua_toboolean(L, 2, 0);
int flag = atoi36(name);
attrib *a = find_key(global.attribs, flag);
if (a == NULL && value) {
add_key(&global.attribs, flag);
if (value) {
key_set(&global.attribs, flag);
}
else if (a != NULL && !value) {
a_remove(&global.attribs, a);
else {
key_unset(&global.attribs, flag);
}
return 0;
}
@ -1184,6 +1183,7 @@ int eressea_run(lua_State *L, const char *luafile)
err = lua_pcall(L, 1, 1, -3);
if (err != 0) {
log_lua_error(L);
assert(!"Lua syntax error? check log.");
}
else {
if (lua_isnumber(L, -1)) {

View File

@ -50,6 +50,7 @@ attrib_type at_chaoscount = {
DEFAULT_AGE,
a_writeint,
a_readint,
NULL,
ATF_UNIQUE
};

View File

@ -38,6 +38,7 @@ attrib_type at_guard = {
DEFAULT_AGE,
a_writeint,
a_readint,
NULL,
ATF_UNIQUE
};

View File

@ -480,7 +480,7 @@ int victorycondition(const alliance * al, const char *name)
for (qi = 0; flist; ql_advance(&flist, &qi, 1)) {
faction *f = (faction *)ql_get(flist, qi);
if (find_key(f->attribs, atoi36("phnx"))) {
if (key_get(f->attribs, atoi36("phnx"))) {
return 1;
}
}
@ -509,7 +509,7 @@ int victorycondition(const alliance * al, const char *name)
for (qi = 0; flist; ql_advance(&flist, &qi, 1)) {
faction *f = (faction *)ql_get(flist, qi);
if (find_key(f->attribs, atoi36("pyra"))) {
if (key_get(f->attribs, atoi36("pyra"))) {
return 1;
}
}

View File

@ -121,6 +121,7 @@ attrib_type at_npcfaction = {
NULL,
a_writeint,
a_readint,
NULL,
ATF_UNIQUE
};

View File

@ -141,7 +141,7 @@ int buildingcapacity(const building * b)
}
attrib_type at_building_generic_type = {
"building_generic_type", NULL, NULL, NULL, a_writestring, a_readstring,
"building_generic_type", NULL, NULL, NULL, a_writestring, a_readstring, NULL,
ATF_UNIQUE
};

View File

@ -659,7 +659,7 @@ int read_borders(struct storage *store)
type->read(b, store);
if (global.data_version < NOBORDERATTRIBS_VERSION) {
attrib *a = NULL;
int result = a_read(store, &a, b);
int result = read_attribs(store, &a, b);
if (border_convert_cb) {
border_convert_cb(b, a);
}

View File

@ -285,6 +285,7 @@ attrib_type at_curse = {
curse_age,
curse_write,
curse_read,
NULL,
ATF_CURSE
};

View File

@ -798,6 +798,7 @@ attrib_type at_maxmagicians = {
NULL,
a_writeint,
a_readint,
NULL,
ATF_UNIQUE
};

View File

@ -119,7 +119,7 @@ write_group(const attrib * a, const void *owner, struct storage *store)
attrib_type at_group = { /* attribute for units assigned to a group */
"grp",
DEFAULT_INIT,
DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, ATF_UNIQUE };
DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, NULL, ATF_UNIQUE };
void free_group(group * g)
{
@ -209,7 +209,7 @@ void write_groups(struct storage *store, const faction * f)
}
}
WRITE_INT(store, 0);
a_write(store, g->attribs, g);
write_attribs(store, g->attribs, g);
WRITE_SECTION(store);
}
WRITE_INT(store, 0);
@ -241,6 +241,6 @@ void read_groups(struct storage *store, faction * f)
if (!a->faction)
ur_add(fid, &a->faction, resolve_faction);
}
a_read(store, &g->attribs, g);
read_attribs(store, &g->attribs, g);
}
}

View File

@ -926,14 +926,14 @@ struct order *ord)
"unit item region command", user, itype->rtype, user->region, ord));
return -1;
}
if (!is_mage(user) || find_key(f->attribs, atoi36("mbst")) != NULL) {
if (!is_mage(user) || key_get(f->attribs, atoi36("mbst"))) {
cmistake(user, user->thisorder, 214, MSG_EVENT);
return -1;
}
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
user->number);
a_add(&f->attribs, make_key(atoi36("mbst")));
key_set(&f->attribs, atoi36("mbst"));
set_level(user, SK_MAGIC, 3);
ADDMSG(&user->faction->msgs, msg_message("use_item",

View File

@ -483,6 +483,7 @@ attrib_type at_horseluck = {
DEFAULT_AGE,
NO_WRITE,
NO_READ,
NULL,
ATF_UNIQUE
};
@ -496,6 +497,7 @@ attrib_type at_peasantluck = {
DEFAULT_AGE,
NO_WRITE,
NO_READ,
NULL,
ATF_UNIQUE
};
@ -509,6 +511,7 @@ attrib_type at_deathcount = {
DEFAULT_AGE,
a_writeint,
a_readint,
NULL,
ATF_UNIQUE
};
@ -522,6 +525,7 @@ attrib_type at_woodcount = {
DEFAULT_AGE,
NO_WRITE,
a_readint,
NULL,
ATF_UNIQUE
};

View File

@ -577,6 +577,24 @@ const struct locale *lang)
WRITE_STR(data->store, obuf);
}
int read_attribs(storage *store, attrib **alist, void *owner) {
if (global.data_version < ATHASH_VERSION) {
return a_read_orig(store, alist, owner);
}
else {
return a_read(store, alist, owner);
}
}
void write_attribs(storage *store, attrib *alist, const void *owner)
{
#if RELEASE_VERSION < ATHASH_VERSION
a_write_orig(store, alist, owner);
#else
a_write(store, alist, owner);
#endif
}
unit *read_unit(struct gamedata *data)
{
unit *u;
@ -748,8 +766,7 @@ unit *read_unit(struct gamedata *data)
log_error("Einheit %s hat %u Personen, und %u Trefferpunkte\n", itoa36(u->no), u->number, u->hp);
u->hp = u->number;
}
a_read(data->store, &u->attribs, u);
read_attribs(data->store, &u->attribs, u);
return u;
}
@ -823,7 +840,7 @@ void write_unit(struct gamedata *data, const unit * u)
}
WRITE_INT(data->store, u->hp);
WRITE_SECTION(data->store);
a_write(data->store, u->attribs, u);
write_attribs(data->store, u->attribs, u);
WRITE_SECTION(data->store);
}
@ -982,7 +999,7 @@ static region *readregion(struct gamedata *data, int x, int y)
read_owner(data, &r->land->ownership);
}
}
a_read(data->store, &r->attribs, r);
read_attribs(data->store, &r->attribs, r);
return r;
}
@ -1046,7 +1063,7 @@ void writeregion(struct gamedata *data, const region * r)
WRITE_SECTION(data->store);
#endif
}
a_write(data->store, r->attribs, r);
write_attribs(data->store, r->attribs, r);
WRITE_SECTION(data->store);
}
@ -1253,7 +1270,7 @@ faction *readfaction(struct gamedata * data)
}
}
a_read(data->store, &f->attribs, f);
read_attribs(data->store, &f->attribs, f);
read_items(data->store, &f->items);
for (;;) {
READ_TOK(data->store, name, sizeof(name));
@ -1338,7 +1355,7 @@ void writefaction(struct gamedata *data, const faction * f)
WRITE_INT(data->store, f->magiegebiet);
WRITE_INT(data->store, f->flags & FFL_SAVEMASK);
a_write(data->store, f->attribs, f);
write_attribs(data->store, f->attribs, f);
WRITE_SECTION(data->store);
write_items(data->store, f->items);
WRITE_SECTION(data->store);
@ -1451,7 +1468,7 @@ int readgame(const char *filename, bool backup)
else {
READ_STR(&store, NULL, 0);
}
a_read(&store, &global.attribs, NULL);
read_attribs(&store, &global.attribs, NULL);
READ_INT(&store, &turn);
global.data_turn = turn;
log_debug(" - reading turn %d\n", turn);
@ -1512,7 +1529,7 @@ int readgame(const char *filename, bool backup)
fno = read_faction_reference(&store);
}
}
a_read(&store, &pl->attribs, pl);
read_attribs(&store, &pl->attribs, pl);
if (pl->id != 1094969858) { // Regatta
addlist(&planes, pl);
}
@ -1580,7 +1597,7 @@ int readgame(const char *filename, bool backup)
READ_STR(&store, name, sizeof(name));
b->type = bt_find(name);
b->region = r;
a_read(&store, &b->attribs, b);
read_attribs(&store, &b->attribs, b);
if (b->type == bt_lighthouse) {
r->flags |= RF_LIGHTHOUSE;
}
@ -1627,7 +1644,7 @@ int readgame(const char *filename, bool backup)
if (sh->type->flags & SFL_NOCOAST) {
sh->coast = NODIRECTION;
}
a_read(&store, &sh->attribs, sh);
read_attribs(&store, &sh->attribs, sh);
}
*shp = 0;
@ -1777,7 +1794,7 @@ int writegame(const char *filename)
WRITE_INT(&store, game_id());
WRITE_SECTION(&store);
a_write(&store, global.attribs, NULL);
write_attribs(&store, global.attribs, NULL);
WRITE_SECTION(&store);
WRITE_INT(&store, turn);
@ -1807,7 +1824,7 @@ int writegame(const char *filename)
w = w->next;
}
write_faction_reference(NULL, &store); /* mark the end of the list */
a_write(&store, pl->attribs, pl);
write_attribs(&store, pl->attribs, pl);
WRITE_SECTION(&store);
}
@ -1852,7 +1869,7 @@ int writegame(const char *filename)
WRITE_INT(&store, b->size);
WRITE_TOK(&store, b->type->_name);
WRITE_SECTION(&store);
a_write(&store, b->attribs, b);
write_attribs(&store, b->attribs, b);
WRITE_SECTION(&store);
}
@ -1870,7 +1887,7 @@ int writegame(const char *filename)
assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION);
WRITE_INT(&store, sh->coast);
WRITE_SECTION(&store);
a_write(&store, sh->attribs, sh);
write_attribs(&store, sh->attribs, sh);
WRITE_SECTION(&store);
}

View File

@ -58,6 +58,9 @@ extern "C" {
void read_spellbook(struct spellbook **bookp, struct storage *store, int(*get_level)(const struct spell * sp, void *), void * cbdata);
void write_spellbook(const struct spellbook *book, struct storage *store);
void write_attribs(struct storage *store, struct attrib *alist, const void *owner);
int read_attribs(struct storage *store, struct attrib **alist, void *owner);
void write_unit(struct gamedata *data, const struct unit *u);
struct unit *read_unit(struct gamedata *data);

View File

@ -1,5 +1,7 @@
#include <platform.h>
#include <kernel/config.h>
#include <util/attrib.h>
#include <attributes/key.h>
#include "save.h"
#include "unit.h"
@ -61,9 +63,37 @@ static void test_readwrite_unit(CuTest * tc)
test_cleanup();
}
static void test_readwrite_attrib(CuTest *tc) {
gamedata *data;
attrib *a = NULL;
const char *path = "attrib.dat";
test_cleanup();
global.data_version = RELEASE_VERSION; // FIXME: hack!
data = gamedata_open(path, "wb");
CuAssertPtrNotNull(tc, data);
key_set(&a, 41);
key_set(&a, 42);
write_attribs(data->store, a, NULL);
gamedata_close(data);
a_removeall(&a, NULL);
CuAssertPtrEquals(tc, 0, a);
data = gamedata_open(path, "rb");
CuAssertPtrNotNull(tc, data);
read_attribs(data->store, &a, NULL);
gamedata_close(data);
CuAssertTrue(tc, key_get(a, 41));
CuAssertTrue(tc, key_get(a, 42));
a_removeall(&a, NULL);
CuAssertIntEquals(tc, 0, remove(path));
test_cleanup();
}
CuSuite *get_save_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_readwrite_attrib);
SUITE_ADD_TEST(suite, test_readwrite_data);
SUITE_ADD_TEST(suite, test_readwrite_unit);
return suite;

View File

@ -59,6 +59,7 @@ attrib_type at_skillmod = {
NULL,
NULL, /* can't write function pointers */
NULL, /* can't read function pointers */
NULL,
ATF_PRESERVE
};

View File

@ -34,7 +34,8 @@
#define OWNER_3_VERSION 349 /* regions store last owner, not last alliance */
#define ATTRIBOWNER_VERSION 350 /* all attrib_type functions know who owns the attribute */
#define CRYPT_VERSION 351 /* passwords are encrypted */
#define RELEASE_VERSION CRYPT_VERSION /* current datafile */
#define ATHASH_VERSION 352 /* attribute-type hash, not name */
#define RELEASE_VERSION ATHASH_VERSION /* current datafile */
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */

View File

@ -486,6 +486,7 @@ attrib_type at_germs = {
DEFAULT_AGE,
a_writeshorts,
a_readshorts,
NULL,
ATF_UNIQUE
};
@ -2749,7 +2750,7 @@ void sinkships(struct region * r)
static attrib_type at_number = {
"faction_renum",
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
ATF_UNIQUE
};

View File

@ -335,6 +335,7 @@ attrib_type at_mage = {
NULL,
write_mage,
read_mage,
NULL,
ATF_UNIQUE
};
@ -2416,6 +2417,7 @@ attrib_type at_familiarmage = {
age_unit,
a_write_unit,
read_magician,
NULL,
ATF_UNIQUE
};
@ -2426,6 +2428,7 @@ attrib_type at_familiar = {
age_unit,
a_write_unit,
read_familiar,
NULL,
ATF_UNIQUE
};
@ -2436,6 +2439,7 @@ attrib_type at_clonemage = {
age_unit,
a_write_unit,
read_magician,
NULL,
ATF_UNIQUE
};
@ -2446,6 +2450,7 @@ attrib_type at_clone = {
age_unit,
a_write_unit,
read_clone,
NULL,
ATF_UNIQUE
};

View File

@ -63,7 +63,7 @@ static void free_market(attrib * a)
attrib_type at_market = {
"script",
NULL, free_market, NULL,
NULL, NULL, ATF_UNIQUE
NULL, NULL, NULL, ATF_UNIQUE
};
static int rc_luxury_trade(const struct race *rc)

View File

@ -194,7 +194,7 @@ void warden_add_give(unit * src, unit * u, const item_type * itype, int n)
void create_museum(void)
{
#if 0 /* TODO: move this to LUA. It should be possible. */
#if 0 /* TODO: move this to Lua. It should be possible. */
unsigned int museum_id = hashstring("museum");
plane *museum = getplanebyid(museum_id);
region *r;

View File

@ -96,6 +96,7 @@ static attrib_type at_alp = {
alp_verify,
alp_write,
alp_read,
NULL,
ATF_UNIQUE
};

View File

@ -112,6 +112,7 @@ static attrib_type at_cursewall = {
curse_age,
cw_write,
cw_read,
NULL,
ATF_CURSE
};

View File

@ -157,7 +157,7 @@ static void done_learning(struct attrib *a)
const attrib_type at_learning = {
"learning",
init_learning, done_learning, NULL, NULL, NULL,
init_learning, done_learning, NULL, NULL, NULL, NULL,
ATF_UNIQUE
};

View File

@ -118,6 +118,7 @@ int RunAllTests(int argc, char *argv[])
ADD_SUITE(monsters);
ADD_SUITE(move);
ADD_SUITE(piracy);
ADD_SUITE(key);
ADD_SUITE(stealth);
ADD_SUITE(otherfaction);
ADD_SUITE(upkeep);

View File

@ -209,14 +209,22 @@ int a_remove(attrib ** pa, attrib * a)
void a_removeall(attrib ** pa, const attrib_type * at)
{
attrib **pnexttype = pa;
attrib **pnext = NULL;
if (!at) {
while (*pnexttype) {
attrib *next = *pnexttype;
if (next->type == at)
attrib *a = *pnexttype;
*pnexttype = a->next;
a_free(a);
}
}
else {
attrib **pnext = NULL;
while (*pnexttype) {
attrib *a = *pnexttype;
if (a->type == at)
break;
pnexttype = &next->nexttype;
pnext = &next->next;
pnexttype = &a->nexttype;
pnext = &a->next;
}
if (*pnexttype && (*pnexttype)->type == at) {
attrib *a = *pnexttype;
@ -234,6 +242,7 @@ void a_removeall(attrib ** pa, const attrib_type * at)
}
}
}
}
attrib *a_new(const attrib_type * at)
{
@ -267,28 +276,23 @@ int a_age(attrib ** p, void *owner)
static critbit_tree cb_deprecated = { 0 };
typedef struct deprecated_s {
unsigned int hash;
int(*reader)(attrib *, void *, struct storage *);
} deprecated_t;
void at_deprecate(const char * name, int(*reader)(attrib *, void *, struct storage *))
{
char buffer[64];
size_t len = strlen(name);
len = cb_new_kv(name, len, &reader, sizeof(reader), buffer);
cb_insert(&cb_deprecated, buffer, len);
deprecated_t value;
value.hash = __at_hashkey(name);
value.reader = reader;
cb_insert(&cb_deprecated, &value, sizeof(value));
}
int a_read(struct storage *store, attrib ** attribs, void *owner)
{
int key, retval = AT_READ_OK;
char zText[128];
zText[0] = 0;
key = -1;
READ_TOK(store, zText, sizeof(zText));
if (strcmp(zText, "end") == 0)
return retval;
else
key = __at_hashkey(zText);
while (key != -1) {
static int a_read_i(struct storage *store, attrib ** attribs, void *owner, unsigned int key) {
int retval = AT_READ_OK;
int(*reader)(attrib *, void *, struct storage *) = 0;
attrib_type *at = at_find(key);
attrib * na = 0;
@ -298,25 +302,26 @@ int a_read(struct storage *store, attrib ** attribs, void *owner)
na = a_new(at);
}
else {
void * kv = 0;
cb_find_prefix(&cb_deprecated, zText, strlen(zText) + 1, &kv, 1, 0);
if (kv) {
cb_get_kv(kv, &reader, sizeof(reader));
void *match;
if (cb_find_prefix(&cb_deprecated, &key, sizeof(key), &match, 1, 0)>0) {
deprecated_t *value = (deprecated_t *)match;
reader = value->reader;
}
else {
fprintf(stderr, "attribute hash: %d (%s)\n", key, zText);
log_error("unknown attribute hash: %u\n", key);
assert(at || !"attribute not registered");
}
}
if (reader) {
int i = reader(na, owner, store);
int ret = reader(na, owner, store);
if (na) {
switch (i) {
switch (ret) {
case AT_READ_DEPR:
case AT_READ_OK:
a_add(attribs, na);
retval = ret;
break;
case AT_READ_FAIL:
retval = AT_READ_FAIL;
a_free(na);
break;
default:
@ -328,7 +333,50 @@ int a_read(struct storage *store, attrib ** attribs, void *owner)
else {
assert(!"error: no registered callback can read attribute");
}
return retval;
}
int a_read(struct storage *store, attrib ** attribs, void *owner) {
int key, retval = AT_READ_OK;
key = -1;
READ_INT(store, &key);
while (key > 0) {
int ret = a_read_i(store, attribs, owner, key);
if (ret == AT_READ_DEPR) {
retval = AT_READ_DEPR;
}
READ_INT(store, &key);
}
if (retval == AT_READ_DEPR) {
/* handle deprecated attributes */
attrib *a = *attribs;
while (a) {
if (a->type->upgrade) {
a->type->upgrade(attribs, a);
}
a = a->nexttype;
}
}
return AT_READ_OK;
}
int a_read_orig(struct storage *store, attrib ** attribs, void *owner)
{
int key, retval = AT_READ_OK;
char zText[128];
zText[0] = 0;
key = -1;
READ_TOK(store, zText, sizeof(zText));
if (strcmp(zText, "end") == 0) {
return retval;
}
else {
key = __at_hashkey(zText);
}
while (key > 0) {
retval = a_read_i(store, attribs, owner, key);
READ_TOK(store, zText, sizeof(zText));
if (!strcmp(zText, "end"))
break;
@ -337,7 +385,24 @@ int a_read(struct storage *store, attrib ** attribs, void *owner)
return retval;
}
void a_write(struct storage *store, const attrib * attribs, const void *owner)
void a_write(struct storage *store, const attrib * attribs, const void *owner) {
const attrib *na = attribs;
while (na) {
if (na->type->write) {
assert(na->type->hashkey || !"attribute not registered");
WRITE_INT(store, na->type->hashkey);
na->type->write(na, owner, store);
na = na->next;
}
else {
na = na->nexttype;
}
}
WRITE_INT(store, 0);
}
void a_write_orig(struct storage *store, const attrib * attribs, const void *owner)
{
const attrib *na = attribs;

View File

@ -56,6 +56,7 @@ extern "C" {
/* age returns 0 if the attribute needs to be removed, !=0 otherwise */
void(*write) (const struct attrib *, const void *owner, struct storage *);
int(*read) (struct attrib *, void *owner, struct storage *); /* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */
void(*upgrade) (struct attrib **alist, struct attrib *a);
unsigned int flags;
/* ---- internal data, do not modify: ---- */
struct attrib_type *nexthash;
@ -72,11 +73,13 @@ extern "C" {
extern int a_remove(attrib ** pa, attrib * at);
extern void a_removeall(attrib ** a, const attrib_type * at);
extern attrib *a_new(const attrib_type * at);
int a_age(attrib ** attribs, void *owner);
extern int a_age(attrib ** attribs, void *owner);
extern int a_read(struct storage *store, attrib ** attribs, void *owner);
extern void a_write(struct storage *store, const attrib * attribs,
const void *owner);
int a_read_orig(struct storage *store, attrib ** attribs, void *owner);
void a_write_orig(struct storage *store, const attrib * attribs, const void *owner);
int a_read(struct storage *store, attrib ** attribs, void *owner);
void a_write(struct storage *store, const attrib * attribs, const void *owner);
void free_attribs(void);
@ -88,6 +91,7 @@ extern "C" {
#define AT_READ_OK 0
#define AT_READ_FAIL -1
#define AT_READ_DEPR 1 /* a deprecated attribute was read, should run a_upgrade */
#define AT_AGE_REMOVE 0 /* remove the attribute after calling age() */
#define AT_AGE_KEEP 1 /* keep the attribute for another turn */

View File

@ -51,6 +51,23 @@ static void test_attrib_remove_self(CuTest * tc) {
CuAssertPtrEquals(tc, a, alist);
}
static void test_attrib_removeall(CuTest * tc) {
const attrib_type at_foo = { "foo" };
const attrib_type at_bar = { "bar" };
attrib *alist = 0, *a;
a_add(&alist, a_new(&at_foo));
a = a_add(&alist, a_new(&at_bar));
a_add(&alist, a_new(&at_foo));
a_removeall(&alist, &at_foo);
CuAssertPtrEquals(tc, a, alist);
CuAssertPtrEquals(tc, 0, alist->next);
a_add(&alist, a_new(&at_bar));
a_add(&alist, a_new(&at_foo));
a_removeall(&alist, NULL);
CuAssertPtrEquals(tc, 0, alist);
}
static void test_attrib_remove(CuTest * tc)
{
attrib_type at_foo = { "foo" };
@ -98,6 +115,7 @@ CuSuite *get_attrib_suite(void)
SUITE_ADD_TEST(suite, test_attrib_new);
SUITE_ADD_TEST(suite, test_attrib_add);
SUITE_ADD_TEST(suite, test_attrib_remove);
SUITE_ADD_TEST(suite, test_attrib_removeall);
SUITE_ADD_TEST(suite, test_attrib_remove_self);
SUITE_ADD_TEST(suite, test_attrib_nexttype);
return suite;

View File

@ -134,6 +134,7 @@ static attrib_type at_wormhole = {
wormhole_age,
wormhole_write,
wormhole_read,
NULL,
ATF_UNIQUE
};

View File

@ -1,4 +1,4 @@
NEWFILES="data/185.dat datum parteien parteien.full passwd score turn"
NEWFILES="data/185.dat datum parteien parteien.full htpasswd score turn"
cleanup () {
rm -rf reports $NEWFILES
}
@ -19,6 +19,7 @@ expr=$2
expect=$3
count=`grep -cE $expr $file`
[ $count -eq $expect ] || quit 1 "expected $expect counts of $expr in $file, got $count"
echo "PASS: $expr is $expect"
}
ROOT=`pwd`
@ -34,10 +35,11 @@ VALGRIND=`which valgrind`
SERVER=../Debug/eressea/eressea
if [ -n "$VALGRIND" ]; then
SUPP=../share/ubuntu-12_04.supp
SERVER="$VALGRIND --suppressions=$SUPP --error-exitcode=1 --leak-check=no $SERVER"
SERVER="$VALGRIND --track-origins=yes --gen-suppressions=all --suppressions=$SUPP --error-exitcode=1 --leak-check=no $SERVER"
fi
echo "running $SERVER"
$SERVER -t 184 ../scripts/run-turn.lua
echo "integration tests"
[ -d reports ] || quit 4 "no reports directory created"
CRFILE=185-zvto.cr
for file in $NEWFILES reports/$CRFILE ; do

View File

@ -1 +0,0 @@


View File

@ -1,3 +0,0 @@
# alliance:factions:persons:score
1248287:1:0:0
1490214:1:0:2105