From 9a0268ac96d21cfa7712dd131d1f1b0e41cd9449 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 07:52:00 +0100 Subject: [PATCH 1/9] bug 2042, pools not working. --- src/kernel/pool.c | 2 +- src/kernel/pool.test.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/kernel/pool.c b/src/kernel/pool.c index 198387c50..552818871 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -176,7 +176,7 @@ int count) } if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK | GET_RESERVE)) { for (v = r->units; v && use < count; v = v->next) - if (u != v && (u->items || rtype->uget)) { + if (u != v && (v->items || rtype->uget)) { int mask; if ((urace(v)->ec_flags & GIVEITEM) == 0) diff --git a/src/kernel/pool.test.c b/src/kernel/pool.test.c index 9135c0bf8..b82304d25 100644 --- a/src/kernel/pool.test.c +++ b/src/kernel/pool.test.c @@ -87,6 +87,27 @@ void test_pool(CuTest *tc) { CuAssertIntEquals(tc, 300, get_pooled(u1, rtype, GET_ALL, INT_MAX)); } +void test_pool_bug_2042(CuTest *tc) { + unit *u1, *u2; + faction *f; + region *r; + struct resource_type *rtype; + + test_cleanup(); + test_create_world(); + rtype = rt_get_or_create("money"); + it_get_or_create(rtype); + f = test_create_faction(0); + r = findregion(0, 0); + assert(r && f && rtype && rtype->itype); + u1 = test_create_unit(f, r); + u2 = test_create_unit(f, r); + assert(u1 && u2); + i_change(&u2->items, rtype->itype, 100); + + CuAssertIntEquals(tc, 100, get_pooled(u1, rtype, GET_SLACK | GET_POOLED_SLACK, 100)); +} + void test_pool_use(CuTest *tc) { unit *u1, *u2, *u3; faction *f; @@ -165,6 +186,7 @@ CuSuite *get_pool_suite(void) CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_reservation); SUITE_ADD_TEST(suite, test_pool); + SUITE_ADD_TEST(suite, test_pool_bug_2042); SUITE_ADD_TEST(suite, test_pool_use); SUITE_ADD_TEST(suite, test_change_resource); return suite; From 38a0a02565867e6c807ddeb1cf1dc2f4650edfb8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 08:33:07 +0100 Subject: [PATCH 2/9] refactor tests for giving, add test for GIVE HERBS. --- src/economy.c | 6 ++- src/economy.h | 1 + src/economy.test.c | 50 +------------------ src/give.h | 4 ++ src/give.test.c | 117 +++++++++++++++++++++++++++++++++++++++++++++ src/laws.h | 3 ++ src/test_eressea.c | 1 + 7 files changed, 132 insertions(+), 50 deletions(-) create mode 100644 src/give.test.c diff --git a/src/economy.c b/src/economy.c index 240b5712a..295d78ce5 100644 --- a/src/economy.c +++ b/src/economy.c @@ -715,7 +715,7 @@ message *check_give(const unit *u, const unit *u2, order * ord) { return 0; } -static void give_cmd(unit * u, order * ord) +void give_cmd(unit * u, order * ord) { region *r = u->region; unit *u2; @@ -725,8 +725,10 @@ static void give_cmd(unit * u, order * ord) param_t p; plane *pl; message *msg; + keyword_t kwd; - init_order(ord); + kwd = init_order(ord); + assert(kwd == K_GIVE); u2 = getunit(r, u->faction); s = getstrtoken(); n = s ? atoip(s) : 0; diff --git a/src/economy.h b/src/economy.h index 58891f188..da5e8e299 100644 --- a/src/economy.h +++ b/src/economy.h @@ -54,6 +54,7 @@ extern "C" { extern int recruit_archetypes(void); extern int give_control_cmd(struct unit *u, struct order *ord); extern void give_control(struct unit * u, struct unit * u2); + void give_cmd(struct unit * u, struct order * ord); struct message * check_steal(const struct unit * u, struct order *ord); struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord); diff --git a/src/economy.test.c b/src/economy.test.c index 0374d4f45..b43a6d1fc 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -63,7 +63,7 @@ struct steal { struct faction *f; }; -static void setup_steal(struct steal *env, terrain_type *ter, race *rc) { +static void setup_steal(struct steal *env, struct terrain_type *ter, struct race *rc) { env->r = test_create_region(0, 0, ter); env->f = test_create_faction(rc); env->u = test_create_unit(env->f, env->r); @@ -72,7 +72,7 @@ static void setup_steal(struct steal *env, terrain_type *ter, race *rc) { static void test_steal_okay(CuTest * tc) { struct steal env; race *rc; - terrain_type *ter; + struct terrain_type *ter; test_cleanup(); ter = test_create_terrain("plain", LAND_REGION); @@ -114,50 +114,6 @@ static void test_steal_ocean(CuTest * tc) { test_cleanup(); } -struct give { - struct unit *src, *dst; - struct region *r; - struct faction *f1, *f2; -}; - -static void setup_give(struct give *env) { - terrain_type *ter = test_create_terrain("plain", LAND_REGION); - env->r = test_create_region(0, 0, ter); - env->src = test_create_unit(env->f1, env->r); - env->dst = test_create_unit(env->f2, env->r); -} - -static void test_give_okay(CuTest * tc) { - struct give env; - struct race * rc; - - test_cleanup(); - rc = test_create_race("human"); - env.f2 = env.f1 = test_create_faction(rc); - setup_give(&env); - - set_param(&global.parameters, "rules.give", "0"); - CuAssertPtrEquals(tc, 0, check_give(env.src, env.dst, 0)); - test_cleanup(); -} - -static void test_give_denied_by_rules(CuTest * tc) { - struct give env; - struct race * rc; - struct message *msg; - - test_cleanup(); - rc = test_create_race("human"); - env.f1 = test_create_faction(rc); - env.f2 = test_create_faction(rc); - setup_give(&env); - - set_param(&global.parameters, "rules.give", "0"); - CuAssertPtrNotNull(tc, msg=check_give(env.src, env.dst, 0)); - msg_release(msg); - test_cleanup(); -} - CuSuite *get_economy_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -166,7 +122,5 @@ CuSuite *get_economy_suite(void) SUITE_ADD_TEST(suite, test_steal_okay); SUITE_ADD_TEST(suite, test_steal_ocean); SUITE_ADD_TEST(suite, test_steal_nosteal); - SUITE_ADD_TEST(suite, test_give_okay); - SUITE_ADD_TEST(suite, test_give_denied_by_rules); return suite; } diff --git a/src/give.h b/src/give.h index 9d2553e5e..1fec3af81 100644 --- a/src/give.h +++ b/src/give.h @@ -16,6 +16,10 @@ extern "C" { #endif + struct item_type; + struct order; + struct unit; + extern int give_item(int want, const struct item_type *itype, struct unit *src, struct unit *dest, struct order *ord); extern void give_men(int n, struct unit *u, struct unit *u2, diff --git a/src/give.test.c b/src/give.test.c new file mode 100644 index 000000000..ea5237e65 --- /dev/null +++ b/src/give.test.c @@ -0,0 +1,117 @@ +#include + +#include "give.h" +#include "economy.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +struct give { + struct unit *src, *dst; + struct region *r; + struct faction *f1, *f2; + struct item_type * itype; +}; + +static void setup_give(struct give *env) { + struct terrain_type *ter = test_create_terrain("plain", LAND_REGION); + env->r = test_create_region(0, 0, ter); + env->src = test_create_unit(env->f1, env->r); + env->dst = test_create_unit(env->f2, env->r); + env->itype = it_get_or_create(rt_get_or_create("money")); + env->itype->flags |= ITF_HERB; +} + +static void test_give(CuTest * tc) { + struct give env; + + test_cleanup(); + env.f2 = env.f1 = test_create_faction(0); + setup_give(&env); + + i_change(&env.src->items, env.itype, 10); + CuAssertIntEquals(tc, 0, give_item(10, env.itype, env.src, env.dst, 0)); + CuAssertIntEquals(tc, 0, i_get(env.src->items, env.itype)); + CuAssertIntEquals(tc, 10, i_get(env.dst->items, env.itype)); + + CuAssertIntEquals(tc, -1, give_item(10, env.itype, env.src, env.dst, 0)); + CuAssertIntEquals(tc, 0, i_get(env.src->items, env.itype)); + CuAssertIntEquals(tc, 10, i_get(env.dst->items, env.itype)); + test_cleanup(); +} + +static void test_give_herbs(CuTest * tc) { + struct give env; + struct order *ord; + struct locale * lang; + char cmd[32]; + + test_cleanup(); + test_create_world(); + env.f2 = env.f1 = test_create_faction(0); + setup_give(&env); + i_change(&env.src->items, env.itype, 10); + + lang = get_or_create_locale("test"); + env.f1->locale = lang; + locale_setstring(lang, "KRAEUTER", "HERBS"); + init_locale(lang); + _snprintf(cmd, sizeof(cmd), "%s HERBS", itoa36(env.dst->no)); + ord = create_order(K_GIVE, lang, cmd); + assert(ord); + + give_cmd(env.src, ord); + CuAssertIntEquals(tc, 0, i_get(env.src->items, env.itype)); + CuAssertIntEquals(tc, 10, i_get(env.dst->items, env.itype)); + test_cleanup(); +} + +static void test_give_okay(CuTest * tc) { + struct give env; + + test_cleanup(); + env.f2 = env.f1 = test_create_faction(0); + setup_give(&env); + + set_param(&global.parameters, "rules.give", "0"); + CuAssertPtrEquals(tc, 0, check_give(env.src, env.dst, 0)); + test_cleanup(); +} + +static void test_give_denied_by_rules(CuTest * tc) { + struct give env; + struct message *msg; + + test_cleanup(); + env.f1 = test_create_faction(0); + env.f2 = test_create_faction(0); + setup_give(&env); + + set_param(&global.parameters, "rules.give", "0"); + CuAssertPtrNotNull(tc, msg = check_give(env.src, env.dst, 0)); + msg_release(msg); + test_cleanup(); +} + +CuSuite *get_give_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_give); + SUITE_ADD_TEST(suite, test_give_herbs); + SUITE_ADD_TEST(suite, test_give_okay); + SUITE_ADD_TEST(suite, test_give_denied_by_rules); + return suite; +} diff --git a/src/laws.h b/src/laws.h index 02fdc6c09..869534212 100755 --- a/src/laws.h +++ b/src/laws.h @@ -18,6 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef H_GC_LAWS #define H_GC_LAWS + +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/src/test_eressea.c b/src/test_eressea.c index 17958c7b2..0ddfd5c71 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -57,6 +57,7 @@ int RunAllTests(void) /* gamecode */ ADD_TESTS(suite, battle); ADD_TESTS(suite, economy); + ADD_TESTS(suite, give); ADD_TESTS(suite, laws); ADD_TESTS(suite, market); ADD_TESTS(suite, move); From b2140f54fdc4f686e7815be5fa1f28221696da52 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 08:40:58 +0100 Subject: [PATCH 3/9] refactor, move give_cmd into give.c --- scripts/fix1984.lua | 33 +++++ src/CMakeLists.txt | 1 + src/economy.c | 299 ------------------------------------------- src/economy.h | 2 - src/give.c | 303 ++++++++++++++++++++++++++++++++++++++++++++ src/give.h | 8 +- 6 files changed, 342 insertions(+), 304 deletions(-) create mode 100644 scripts/fix1984.lua diff --git a/scripts/fix1984.lua b/scripts/fix1984.lua new file mode 100644 index 000000000..2404d9a6a --- /dev/null +++ b/scripts/fix1984.lua @@ -0,0 +1,33 @@ +function recover(turn) + eressea.free_game() + eressea.read_game(turn .. ".dat") + ships = {} + bldgs = {} + for r in regions() do + for b in r.buildings do + if b.info~=nil and (string.len(b.info)>120) then + bldgs[b.id] = b.info + end + end + for b in r.ships do + if b.info~=nil and (string.len(b.info)>120) then + ships[b.id] = b.info + end + end + end + eressea.free_game() + eressea.read_game((turn+1) .. ".dat") + for k, v in pairs(bldgs) do + b = get_building(k) + if b~=nil then + b.info = v + end + end + for k, v in pairs(ships) do + b = get_ship(k) + if b~=nil then + b.info = v + end + end + eressea.write_game((turn+1) .. ".fixed") +end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 635427916..402e4dc58 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -166,6 +166,7 @@ set(TESTS_SRC economy.test.c json.test.c keyword.test.c + give.test.c laws.test.c magic.test.c market.test.c diff --git a/src/economy.c b/src/economy.c index 295d78ce5..d5cc4eca5 100644 --- a/src/economy.c +++ b/src/economy.c @@ -388,36 +388,6 @@ static int do_recruiting(recruitment * recruits, int available) return recruited; } -static void feedback_give_not_allowed(unit * u, order * ord) -{ - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_give_forbidden", - "")); -} - -static bool can_give(const unit * u, const unit * u2, const item_type * itype, int mask) -{ - if (u2) { - if (u->faction != u2->faction) { - int rule = rule_give(); - if (itype) { - assert(mask == 0); - if (itype->rtype->ltype) - mask |= GIVE_LUXURIES; - else if (fval(itype, ITF_HERB)) - mask |= GIVE_HERBS; - else - mask |= GIVE_GOODS; - } - return (rule & mask) != 0; - } - } - else { - int rule = rule_give(); - return (rule & GIVE_PEASANTS) != 0; - } - return true; -} - void free_recruitments(recruitment * recruits) { while (recruits) { @@ -708,275 +678,6 @@ int give_control_cmd(unit * u, order * ord) return 0; } -message *check_give(const unit *u, const unit *u2, order * ord) { - if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { - return msg_feedback(u, ord, "feedback_give_forbidden", ""); - } - return 0; -} - -void give_cmd(unit * u, order * ord) -{ - region *r = u->region; - unit *u2; - const char *s; - int n; - const item_type *itype; - param_t p; - plane *pl; - message *msg; - keyword_t kwd; - - kwd = init_order(ord); - assert(kwd == K_GIVE); - u2 = getunit(r, u->faction); - s = getstrtoken(); - n = s ? atoip(s) : 0; - p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale); - - /* first, do all the ones that do not require HELP_GIVE or CONTACT */ - if (p == P_CONTROL) { - /* handled in give_control_cmd */ - return; - } - - if (!u2 && !getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - msg = check_give(u, u2, ord); - if (msg) { - ADDMSG(&u->faction->msgs, msg); - return; - } - - /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ - if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) - && !cansee(u->faction, r, u2, 0) && !ucontact(u2, u) - && !fval(u2, UFL_TAKEALL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - if (u == u2) { - cmistake(u, ord, 8, MSG_COMMERCE); - return; - } - - /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht - * wirklich einfach. */ - pl = rplane(r); - if (pl && fval(pl, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { - cmistake(u, ord, 268, MSG_COMMERCE); - return; - } - - if (u2 && u_race(u2) == get_race(RC_SPELL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - else if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { - cmistake(u, ord, 40, MSG_COMMERCE); - return; - } - - else if (p == P_HERBS) { - bool given = false; - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } - if (!can_give(u, u2, NULL, GIVE_HERBS)) { - feedback_give_not_allowed(u, ord); - return; - } - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } - if (!u2) { - if (!getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - return; - } - } - if (u->items) { - item **itmp = &u->items; - while (*itmp) { - item *itm = *itmp; - const item_type *itype = itm->type; - if (fval(itype, ITF_HERB) && itm->number > 0) { - /* give_item ändert im fall,das man alles übergibt, die - * item-liste der unit, darum continue vor pointerumsetzten */ - if (give_item(itm->number, itm->type, u, u2, ord) == 0) { - given = true; - if (*itmp != itm) - continue; - continue; - } - } - itmp = &itm->next; - } - } - if (!given) - cmistake(u, ord, 38, MSG_COMMERCE); - return; - } - - else if (p == P_ZAUBER) { - cmistake(u, ord, 7, MSG_COMMERCE); - /* geht nimmer */ - return; - } - - else if (p == P_UNIT) { /* Einheiten uebergeben */ - if (!(u_race(u)->ec_flags & GIVEUNIT)) { - cmistake(u, ord, 167, MSG_COMMERCE); - return; - } - - give_unit(u, u2, ord); - return; - } - - else if (p == P_ANY) { - const char *s; - - if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { - feedback_give_not_allowed(u, ord); - return; - } - s = getstrtoken(); - if (!s || *s == 0) { /* GIVE ALL items that you have */ - - /* do these checks once, not for each item we have: */ - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } - - /* für alle items einmal prüfen, ob wir mehr als von diesem Typ - * reserviert ist besitzen und diesen Teil dann übergeben */ - if (u->items) { - item **itmp = &u->items; - while (*itmp) { - item *itm = *itmp; - const item_type *itype = itm->type; - if (itm->number > 0 - && itm->number - get_reservation(u, itype->rtype) > 0) { - n = itm->number - get_reservation(u, itype->rtype); - if (give_item(n, itype, u, u2, ord) == 0) { - if (*itmp != itm) - continue; - } - } - itmp = &itm->next; - } - } - } - else { - if (isparam(s, u->faction->locale, P_PERSON)) { - if (!(u_race(u)->ec_flags & GIVEPERSON)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); - } - else { - n = u->number; - give_men(n, u, u2, ord); - } - } - else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - } - else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - } - else { - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) { - item *i = *i_find(&u->items, itype); - if (i != NULL) { - if (can_give(u, u2, itype, 0)) { - n = i->number - get_reservation(u, itype->rtype); - give_item(n, itype, u, u2, ord); - } - else { - feedback_give_not_allowed(u, ord); - } - } - } - } - } - return; - } - else if (p == P_EACH) { - if (u2 == NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "peasants_give_invalid", "")); - return; - } - s = getstrtoken(); /* skip one ahead to get the amount. */ - n = atoip(s); /* n: Anzahl */ - n *= u2->number; - } - s = getstrtoken(); - - if (s == NULL) { - cmistake(u, ord, 113, MSG_COMMERCE); - return; - } - - if (isparam(s, u->faction->locale, P_PERSON)) { - if (!(u_race(u)->ec_flags & GIVEPERSON)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); - return; - } - give_men(n, u, u2, ord); - return; - } - - if (u2 != NULL) { - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } - if (!(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } - } - - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) { - if (can_give(u, u2, itype, 0)) { - give_item(n, itype, u, u2, ord); - } - else { - feedback_give_not_allowed(u, ord); - } - return; - } - cmistake(u, ord, 123, MSG_COMMERCE); -} - static int forget_cmd(unit * u, order * ord) { skill_t sk; diff --git a/src/economy.h b/src/economy.h index da5e8e299..b06ed21c3 100644 --- a/src/economy.h +++ b/src/economy.h @@ -54,10 +54,8 @@ extern "C" { extern int recruit_archetypes(void); extern int give_control_cmd(struct unit *u, struct order *ord); extern void give_control(struct unit * u, struct unit * u2); - void give_cmd(struct unit * u, struct order * ord); struct message * check_steal(const struct unit * u, struct order *ord); - struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord); #ifdef __cplusplus } diff --git a/src/give.c b/src/give.c index 2b3d0ab91..ac928ab9b 100644 --- a/src/give.c +++ b/src/give.c @@ -15,6 +15,7 @@ #include "give.h" #include "economy.h" +#include "laws.h" /* kernel includes */ #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +40,7 @@ #include #include #include +#include /* libc includes */ #include @@ -59,6 +62,36 @@ static int GiveRestriction(void) return value; } +static void feedback_give_not_allowed(unit * u, order * ord) +{ + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_give_forbidden", + "")); +} + +static bool can_give(const unit * u, const unit * u2, const item_type * itype, int mask) +{ + if (u2) { + if (u->faction != u2->faction) { + int rule = rule_give(); + if (itype) { + assert(mask == 0); + if (itype->rtype->ltype) + mask |= GIVE_LUXURIES; + else if (fval(itype, ITF_HERB)) + mask |= GIVE_HERBS; + else + mask |= GIVE_GOODS; + } + return (rule & mask) != 0; + } + } + else { + int rule = rule_give(); + return (rule & GIVE_PEASANTS) != 0; + } + return true; +} + static void add_give(unit * u, unit * u2, int given, int received, const resource_type * rtype, struct order *ord, int error) @@ -456,3 +489,273 @@ void give_unit(unit * u, unit * u2, order * ord) u_setfaction(u, u2->faction); u2->faction->newbies += n; } + +void give_cmd(unit * u, order * ord) +{ + region *r = u->region; + unit *u2; + const char *s; + int n; + const item_type *itype; + param_t p; + plane *pl; + message *msg; + keyword_t kwd; + + kwd = init_order(ord); + assert(kwd == K_GIVE); + u2 = getunit(r, u->faction); + s = getstrtoken(); + n = s ? atoip(s) : 0; + p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale); + + /* first, do all the ones that do not require HELP_GIVE or CONTACT */ + if (p == P_CONTROL) { + /* handled in give_control_cmd */ + return; + } + + if (!u2 && !getunitpeasants) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + + msg = check_give(u, u2, ord); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + return; + } + + /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ + if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) + && !cansee(u->faction, r, u2, 0) && !ucontact(u2, u) + && !fval(u2, UFL_TAKEALL)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + if (u == u2) { + cmistake(u, ord, 8, MSG_COMMERCE); + return; + } + + /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht + * wirklich einfach. */ + pl = rplane(r); + if (pl && fval(pl, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { + cmistake(u, ord, 268, MSG_COMMERCE); + return; + } + + if (u2 && u_race(u2) == get_race(RC_SPELL)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + + else if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { + cmistake(u, ord, 40, MSG_COMMERCE); + return; + } + + else if (p == P_HERBS) { + bool given = false; + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (!can_give(u, u2, NULL, GIVE_HERBS)) { + feedback_give_not_allowed(u, ord); + return; + } + if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; + } + if (!u2) { + if (!getunitpeasants) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, + "feedback_unit_not_found", "")); + return; + } + } + if (u->items) { + item **itmp = &u->items; + while (*itmp) { + item *itm = *itmp; + const item_type *itype = itm->type; + if (fval(itype, ITF_HERB) && itm->number > 0) { + /* give_item ändert im fall,das man alles übergibt, die + * item-liste der unit, darum continue vor pointerumsetzten */ + if (give_item(itm->number, itm->type, u, u2, ord) == 0) { + given = true; + if (*itmp != itm) + continue; + continue; + } + } + itmp = &itm->next; + } + } + if (!given) + cmistake(u, ord, 38, MSG_COMMERCE); + return; + } + + else if (p == P_ZAUBER) { + cmistake(u, ord, 7, MSG_COMMERCE); + /* geht nimmer */ + return; + } + + else if (p == P_UNIT) { /* Einheiten uebergeben */ + if (!(u_race(u)->ec_flags & GIVEUNIT)) { + cmistake(u, ord, 167, MSG_COMMERCE); + return; + } + + give_unit(u, u2, ord); + return; + } + + else if (p == P_ANY) { + const char *s; + + if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { + feedback_give_not_allowed(u, ord); + return; + } + s = getstrtoken(); + if (!s || *s == 0) { /* GIVE ALL items that you have */ + + /* do these checks once, not for each item we have: */ + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; + } + + /* für alle items einmal prüfen, ob wir mehr als von diesem Typ + * reserviert ist besitzen und diesen Teil dann übergeben */ + if (u->items) { + item **itmp = &u->items; + while (*itmp) { + item *itm = *itmp; + const item_type *itype = itm->type; + if (itm->number > 0 + && itm->number - get_reservation(u, itype->rtype) > 0) { + n = itm->number - get_reservation(u, itype->rtype); + if (give_item(n, itype, u, u2, ord) == 0) { + if (*itmp != itm) + continue; + } + } + itmp = &itm->next; + } + } + } + else { + if (isparam(s, u->faction->locale, P_PERSON)) { + if (!(u_race(u)->ec_flags & GIVEPERSON)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); + } + else { + n = u->number; + give_men(n, u, u2, ord); + } + } + else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + } + else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + } + else { + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) { + item *i = *i_find(&u->items, itype); + if (i != NULL) { + if (can_give(u, u2, itype, 0)) { + n = i->number - get_reservation(u, itype->rtype); + give_item(n, itype, u, u2, ord); + } + else { + feedback_give_not_allowed(u, ord); + } + } + } + } + } + return; + } + else if (p == P_EACH) { + if (u2 == NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "peasants_give_invalid", "")); + return; + } + s = getstrtoken(); /* skip one ahead to get the amount. */ + n = atoip(s); /* n: Anzahl */ + n *= u2->number; + } + s = getstrtoken(); + + if (s == NULL) { + cmistake(u, ord, 113, MSG_COMMERCE); + return; + } + + if (isparam(s, u->faction->locale, P_PERSON)) { + if (!(u_race(u)->ec_flags & GIVEPERSON)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); + return; + } + give_men(n, u, u2, ord); + return; + } + + if (u2 != NULL) { + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (!(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; + } + } + + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) { + if (can_give(u, u2, itype, 0)) { + give_item(n, itype, u, u2, ord); + } + else { + feedback_give_not_allowed(u, ord); + } + return; + } + cmistake(u, ord, 123, MSG_COMMERCE); +} + +message *check_give(const unit *u, const unit *u2, order * ord) { + if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { + return msg_feedback(u, ord, "feedback_give_forbidden", ""); + } + return 0; +} + diff --git a/src/give.h b/src/give.h index 1fec3af81..c392ecde8 100644 --- a/src/give.h +++ b/src/give.h @@ -20,11 +20,13 @@ extern "C" { struct order; struct unit; - extern int give_item(int want, const struct item_type *itype, + int give_item(int want, const struct item_type *itype, struct unit *src, struct unit *dest, struct order *ord); - extern void give_men(int n, struct unit *u, struct unit *u2, + void give_men(int n, struct unit *u, struct unit *u2, struct order *ord); - extern void give_unit(struct unit *u, struct unit *u2, struct order *ord); + void give_unit(struct unit *u, struct unit *u2, struct order *ord); + void give_cmd(struct unit * u, struct order * ord); + struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord); #ifdef __cplusplus } From 835b0964efed2c9b0edbe0a7abfb0aad11fa9789 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 09:55:29 +0100 Subject: [PATCH 4/9] fix gcc --- src/economy.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/economy.h b/src/economy.h index b06ed21c3..f07d672e0 100644 --- a/src/economy.h +++ b/src/economy.h @@ -37,11 +37,14 @@ extern "C" { #define TRADE_FRACTION 100 - extern int income(const struct unit *u); - /* Wieviel Fremde eine Partei pro Woche aufnehmen kann */ #define MAXNEWBIES 5 + struct unit; + struct region; + struct faction; + int income(const struct unit *u); + void economics(struct region *r); void produce(struct region *r); void auto_work(struct region *r); From d14a40b7e725671b9fe7d842e4d6399474006f3b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 17:32:55 +0100 Subject: [PATCH 5/9] fix struct declarations. --- src/economy.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/economy.h b/src/economy.h index f07d672e0..92512b8e9 100644 --- a/src/economy.h +++ b/src/economy.h @@ -43,6 +43,9 @@ extern "C" { struct unit; struct region; struct faction; + struct order; + struct message; + int income(const struct unit *u); void economics(struct region *r); From fecf3b04f818b85038f7f6f4a86dd48dd47ff206 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 18:10:05 +0100 Subject: [PATCH 6/9] bug 2041: group alliances are lost. added test coverage, too. --- src/kernel/group.c | 9 ++++----- src/kernel/group.h | 3 ++- src/kernel/group.test.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/kernel/save.c | 2 +- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/kernel/group.c b/src/kernel/group.c index 510c327ac..402ebe9a3 100755 --- a/src/kernel/group.c +++ b/src/kernel/group.c @@ -48,7 +48,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. static group *ghash[GMAXHASH]; static int maxgid; -static group *new_group(faction * f, const char *name, int gid) +group *new_group(faction * f, const char *name, int gid) { group **gp = &f->groups; int index = gid % GMAXHASH; @@ -195,9 +195,10 @@ bool join_group(unit * u, const char *name) return true; } -void write_groups(struct storage *store, group * g) +void write_groups(struct storage *store, const faction * f) { - while (g) { + group *g; + for (g = f->groups; g; g=g->next) { ally *a; WRITE_INT(store, g->gid); WRITE_STR(store, g->name); @@ -210,7 +211,6 @@ void write_groups(struct storage *store, group * g) WRITE_INT(store, 0); a_write(store, g->attribs, g); WRITE_SECTION(store); - g = g->next; } WRITE_INT(store, 0); } @@ -243,7 +243,6 @@ void read_groups(struct storage *store, faction * f) if (!a->faction) ur_add(fid, &a->faction, resolve_faction); } - *pa = 0; a_read(store, &g->attribs, g); } } diff --git a/src/kernel/group.h b/src/kernel/group.h index 076761d98..e4492d4ac 100755 --- a/src/kernel/group.h +++ b/src/kernel/group.h @@ -40,8 +40,9 @@ extern "C" { extern void set_group(struct unit *u, struct group *g); extern struct group * get_group(const struct unit *u); extern void free_group(struct group *g); + struct group *new_group(struct faction * f, const char *name, int gid); - extern void write_groups(struct storage *data, struct group *g); + extern void write_groups(struct storage *data, const struct faction *f); extern void read_groups(struct storage *data, struct faction *f); #ifdef __cplusplus diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index c1bd01d59..d37a3ed41 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -1,14 +1,53 @@ #include #include "types.h" +#include "ally.h" #include "group.h" #include "faction.h" #include "unit.h" #include "region.h" +#include +#include #include #include #include +static void test_group_readwrite(CuTest * tc) +{ + faction * f; + group *g; + ally *al; + storage store; + FILE *F; + + F = fopen("test.dat", "wb"); + binstore_init(&store, F); + test_cleanup(); + test_create_world(); + f = test_create_faction(0); + g = new_group(f, "test", 42); + al = ally_add(&g->allies, f); + al->status = HELP_COMMAND; + write_groups(&store, f); + binstore_done(&store); + fclose(F); + + F = fopen("test.dat", "rb"); + binstore_init(&store, F); + f->groups = 0; + free_group(g); + read_groups(&store, f); + binstore_done(&store); + fclose(F); + + CuAssertPtrNotNull(tc, f->groups); + CuAssertPtrNotNull(tc, f->groups->allies); + CuAssertPtrEquals(tc, 0, f->groups->allies->next); + CuAssertPtrEquals(tc, f, f->groups->allies->faction); + CuAssertIntEquals(tc, HELP_COMMAND, f->groups->allies->status); + test_cleanup(); +} + static void test_group(CuTest * tc) { unit *u; @@ -40,6 +79,7 @@ CuSuite *get_group_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_group); + SUITE_ADD_TEST(suite, test_group_readwrite); return suite; } diff --git a/src/kernel/save.c b/src/kernel/save.c index 6b23bb544..4133f0971 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1439,7 +1439,7 @@ void writefaction(struct gamedata *data, const faction * f) } WRITE_INT(data->store, 0); WRITE_SECTION(data->store); - write_groups(data->store, f->groups); + write_groups(data->store, f); write_spellbook(f->spellbook, data->store); } From 16c03a8e0eddcc2ddaebcdf6e11d4ffc65461c44 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 18:44:49 +0100 Subject: [PATCH 7/9] typo broke gcc build. --- src/kernel/group.test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index d37a3ed41..e2834548f 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -27,7 +27,7 @@ static void test_group_readwrite(CuTest * tc) f = test_create_faction(0); g = new_group(f, "test", 42); al = ally_add(&g->allies, f); - al->status = HELP_COMMAND; + al->status = HELP_GIVE; write_groups(&store, f); binstore_done(&store); fclose(F); @@ -44,7 +44,7 @@ static void test_group_readwrite(CuTest * tc) CuAssertPtrNotNull(tc, f->groups->allies); CuAssertPtrEquals(tc, 0, f->groups->allies->next); CuAssertPtrEquals(tc, f, f->groups->allies->faction); - CuAssertIntEquals(tc, HELP_COMMAND, f->groups->allies->status); + CuAssertIntEquals(tc, HELP_GIVE, f->groups->allies->status); test_cleanup(); } From f62313334490b3d14f28e3cbcf64cbd0cdd93ee8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 19:03:44 +0100 Subject: [PATCH 8/9] storage takes ownership of the FILE* (really need to change this API). --- src/kernel/group.test.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index e2834548f..b248b65d2 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -30,7 +30,6 @@ static void test_group_readwrite(CuTest * tc) al->status = HELP_GIVE; write_groups(&store, f); binstore_done(&store); - fclose(F); F = fopen("test.dat", "rb"); binstore_init(&store, F); @@ -38,7 +37,6 @@ static void test_group_readwrite(CuTest * tc) free_group(g); read_groups(&store, f); binstore_done(&store); - fclose(F); CuAssertPtrNotNull(tc, f->groups); CuAssertPtrNotNull(tc, f->groups->allies); From dbf60a7ce53df3c844f126d1d8825cfd617c5068 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Nov 2014 22:29:04 +0100 Subject: [PATCH 9/9] update to latest version of storage library. --- src/bind_storage.c | 147 +++++++++++++++++++++------------------- src/kernel/group.test.c | 11 ++- src/kernel/save.c | 13 +++- src/kernel/save.h | 3 + storage | 2 +- 5 files changed, 99 insertions(+), 77 deletions(-) diff --git a/src/bind_storage.c b/src/bind_storage.c index 8aa363d43..baf1a67e2 100644 --- a/src/bind_storage.c +++ b/src/bind_storage.c @@ -18,6 +18,8 @@ without prior permission by the authors of Eressea. #include #include +#include +#include #include #include @@ -29,36 +31,37 @@ without prior permission by the authors of Eressea. static int tolua_storage_create(lua_State * L) { - const char *filename = tolua_tostring(L, 1, 0); - const char *type = tolua_tostring(L, 2, "rb"); - gamedata *data = (gamedata *)calloc(1, sizeof(gamedata)); - storage *store = (storage *)calloc(1, sizeof(storage)); - FILE * F; + const char *filename = tolua_tostring(L, 1, 0); + const char *type = tolua_tostring(L, 2, "rb"); + gamedata *data = (gamedata *)calloc(1, sizeof(gamedata)); + storage *store = (storage *)calloc(1, sizeof(storage)); + FILE * F; - data->store = store; + data->store = store; - F = fopen(filename, type); - if (strchr(type, 'r')) { - fread(&data->version, sizeof(int), 1, F); - fseek(F, sizeof(int), SEEK_CUR); - } - else if (strchr(type, 'w')) { - int n = STREAM_VERSION; - data->version = RELEASE_VERSION; - fwrite(&data->version, sizeof(int), 1, F); - fwrite(&n, sizeof(int), 1, F); - } - binstore_init(store, F); - tolua_pushusertype(L, (void *)data, TOLUA_CAST "storage"); - return 1; + F = fopen(filename, type); + if (strchr(type, 'r')) { + fread(&data->version, sizeof(int), 1, F); + fseek(F, sizeof(int), SEEK_CUR); + } + else if (strchr(type, 'w')) { + int n = STREAM_VERSION; + data->version = RELEASE_VERSION; + fwrite(&data->version, sizeof(int), 1, F); + fwrite(&n, sizeof(int), 1, F); + } + fstream_init(&data->strm, F); + binstore_init(store, &data->strm); + tolua_pushusertype(L, (void *)data, TOLUA_CAST "storage"); + return 1; } static int tolua_storage_read_unit(lua_State * L) { - gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); - struct unit *u = read_unit(data); - tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); - return 1; + gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); + struct unit *u = read_unit(data); + tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); + return 1; } static int tolua_storage_write_unit(lua_State * L) @@ -71,76 +74,78 @@ static int tolua_storage_write_unit(lua_State * L) static int tolua_storage_read_float(lua_State * L) { - gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); - float num; - READ_FLT(data->store, &num); - tolua_pushnumber(L, (lua_Number) num); - return 1; + gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); + float num; + READ_FLT(data->store, &num); + tolua_pushnumber(L, (lua_Number)num); + return 1; } static int tolua_storage_read_int(lua_State * L) { - gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); - int num; - READ_INT(data->store, &num); - tolua_pushnumber(L, (lua_Number) num); - return 1; + gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); + int num; + READ_INT(data->store, &num); + tolua_pushnumber(L, (lua_Number)num); + return 1; } static int tolua_storage_write(lua_State * L) { - gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); - if (data->version && tolua_isnumber(L, 2, 0, 0)) { - lua_Number num = tolua_tonumber(L, 2, 0); - double n; - if (modf(num, &n) == 0.0) { - WRITE_INT(data->store, (int)num); - } else { - WRITE_FLT(data->store, (float)num); + gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); + if (data->version && tolua_isnumber(L, 2, 0, 0)) { + lua_Number num = tolua_tonumber(L, 2, 0); + double n; + if (modf(num, &n) == 0.0) { + WRITE_INT(data->store, (int)num); + } + else { + WRITE_FLT(data->store, (float)num); + } } - } - return 0; + return 0; } static int tolua_storage_tostring(lua_State * L) { - gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); - char name[64]; - _snprintf(name, sizeof(name), "", data->encoding, - data->version); - lua_pushstring(L, name); - return 1; + gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); + char name[64]; + _snprintf(name, sizeof(name), "", data->encoding, + data->version); + lua_pushstring(L, name); + return 1; } static int tolua_storage_close(lua_State * L) { - gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); - binstore_done(data->store); - return 0; + gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); + binstore_done(data->store); + fstream_done(&data->strm); + return 0; } void tolua_storage_open(lua_State * L) { - /* register user types */ - tolua_usertype(L, TOLUA_CAST "storage"); + /* register user types */ + tolua_usertype(L, TOLUA_CAST "storage"); - tolua_module(L, NULL, 0); - tolua_beginmodule(L, NULL); - { - tolua_cclass(L, TOLUA_CAST "storage", TOLUA_CAST "storage", TOLUA_CAST "", - NULL); - tolua_beginmodule(L, TOLUA_CAST "storage"); + tolua_module(L, NULL, 0); + tolua_beginmodule(L, NULL); { - tolua_function(L, TOLUA_CAST "__tostring", tolua_storage_tostring); - tolua_function(L, TOLUA_CAST "write", tolua_storage_write); - tolua_function(L, TOLUA_CAST "read_int", tolua_storage_read_int); - tolua_function(L, TOLUA_CAST "read_float", tolua_storage_read_float); - tolua_function(L, TOLUA_CAST "write_unit", tolua_storage_write_unit); - tolua_function(L, TOLUA_CAST "read_unit", tolua_storage_read_unit); - tolua_function(L, TOLUA_CAST "close", tolua_storage_close); - tolua_function(L, TOLUA_CAST "create", tolua_storage_create); + tolua_cclass(L, TOLUA_CAST "storage", TOLUA_CAST "storage", TOLUA_CAST "", + NULL); + tolua_beginmodule(L, TOLUA_CAST "storage"); + { + tolua_function(L, TOLUA_CAST "__tostring", tolua_storage_tostring); + tolua_function(L, TOLUA_CAST "write", tolua_storage_write); + tolua_function(L, TOLUA_CAST "read_int", tolua_storage_read_int); + tolua_function(L, TOLUA_CAST "read_float", tolua_storage_read_float); + tolua_function(L, TOLUA_CAST "write_unit", tolua_storage_write_unit); + tolua_function(L, TOLUA_CAST "read_unit", tolua_storage_read_unit); + tolua_function(L, TOLUA_CAST "close", tolua_storage_close); + tolua_function(L, TOLUA_CAST "create", tolua_storage_create); + } + tolua_endmodule(L); } tolua_endmodule(L); - } - tolua_endmodule(L); } diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index b248b65d2..1272fc493 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -5,6 +5,8 @@ #include "faction.h" #include "unit.h" #include "region.h" +#include +#include #include #include @@ -19,9 +21,11 @@ static void test_group_readwrite(CuTest * tc) ally *al; storage store; FILE *F; + stream strm; F = fopen("test.dat", "wb"); - binstore_init(&store, F); + fstream_init(&strm, F); + binstore_init(&store, &strm); test_cleanup(); test_create_world(); f = test_create_faction(0); @@ -30,13 +34,16 @@ static void test_group_readwrite(CuTest * tc) al->status = HELP_GIVE; write_groups(&store, f); binstore_done(&store); + fstream_done(&strm); F = fopen("test.dat", "rb"); - binstore_init(&store, F); + fstream_init(&strm, F); + binstore_init(&store, &strm); f->groups = 0; free_group(g); read_groups(&store, f); binstore_done(&store); + fstream_done(&strm); CuAssertPtrNotNull(tc, f->groups); CuAssertPtrNotNull(tc, f->groups->allies); diff --git a/src/kernel/save.c b/src/kernel/save.c index 4133f0971..a7d6ce0c2 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -70,6 +70,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include +#include #include #include @@ -1457,6 +1459,7 @@ int readgame(const char *filename, int backup) const struct building_type *bt_lighthouse = bt_find("lighthouse"); gamedata gdata = { 0 }; storage store; + stream strm; FILE *F; init_locales(); @@ -1482,7 +1485,8 @@ int readgame(const char *filename, int backup) assert(gdata.version <= RELEASE_VERSION || !"unsupported data format"); gdata.encoding = enc_gamedata; - binstore_init(&store, F); + fstream_init(&strm, F); + binstore_init(&store, &strm); gdata.store = &store; global.data_version = gdata.version; /* HACK: attribute::read does not have access to gamedata, only storage */ @@ -1733,7 +1737,7 @@ int readgame(const char *filename, int backup) read_borders(&store); binstore_done(&store); - + fstream_done(&strm); /* Unaufgeloeste Zeiger initialisieren */ log_printf(stdout, "fixing unresolved references.\n"); resolve(); @@ -1797,6 +1801,7 @@ int writegame(const char *filename) char path[MAX_PATH]; gamedata gdata; storage store; + stream strm; FILE *F; clear_monster_orders(); @@ -1826,7 +1831,8 @@ int writegame(const char *filename) fwrite(&gdata.version, sizeof(int), 1, F); fwrite(&n, sizeof(int), 1, F); - binstore_init(&store, F); + fstream_init(&strm, F); + binstore_init(&store, &strm); /* globale Variablen */ @@ -1942,6 +1948,7 @@ int writegame(const char *filename) WRITE_SECTION(&store); binstore_done(&store); + fstream_done(&strm); log_printf(stdout, "\nOk.\n"); return 0; diff --git a/src/kernel/save.h b/src/kernel/save.h index 2c119a5eb..512946aca 100644 --- a/src/kernel/save.h +++ b/src/kernel/save.h @@ -18,6 +18,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef H_KRNL_SAVE #define H_KRNL_SAVE + +#include #ifdef __cplusplus extern "C" { #endif @@ -31,6 +33,7 @@ extern "C" { typedef struct gamedata { struct storage *store; + stream strm; int version; int encoding; } gamedata; diff --git a/storage b/storage index c6103e59c..5f0b7095d 160000 --- a/storage +++ b/storage @@ -1 +1 @@ -Subproject commit c6103e59c0938b173c0e08a852ff1cbbc4e284e3 +Subproject commit 5f0b7095d42209762c9eac73c866c614018b440d