Merge pull request #693 from ennorehling/develop

callback refactoring
This commit is contained in:
Enno Rehling 2017-05-12 22:22:43 +02:00 committed by GitHub
commit f0fc37bd69
20 changed files with 109 additions and 283 deletions

View File

@ -1,24 +0,0 @@
<?xml version="1.0"?>
<eressea xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="config://game/familiars.xml"/>
<xi:include href="config://game/equipment.xml"/>
<equipment>
<set name="autoseed_unit">
<item name="log" amount="50"/>
<item name="stone" amount="50"/>
<item name="iron" amount="50"/>
<item name="laen" amount="10"/>
<item name="sword" amount="1"/>
<item name="mallorn" amount="10"/>
<item name="skillpotion" amount="5"/>
<item name="p2" amount="5"/>
<item name="money" amount="20000"/>
<skill name="perception" level="30"/>
<skill name="melee" level="1"/>
</set>
<set name="autoseed_faction">
<item name="adamantium" amount="1"/>
</set>
</equipment>
</eressea>

View File

@ -56,7 +56,7 @@ done
[ -z $INIFILE ] && INIFILE=$TOOLS/inifile
[ -e $INIFILE ] || INIFILE=$TOOLS/iniparser/inifile
[ -e $SOURCE/conf/$rules/config.xml ] || abort "cannot find conf/$rules/config.xml"
[ -e $SOURCE/conf/$rules/config.json ] || abort "cannot find conf/$rules/config.json"
cd $ERESSEA
if [ -d $dir ] ; then

View File

@ -1066,3 +1066,48 @@ function test_give_silver()
assert_equal(21, r:get_resource("money"))
assert_equal(10, u:get_item("money"))
end
function test_give_horses()
local r = region.create(0, 0, "plain")
local f = create_faction('human')
local u = unit.create(f, r, 1)
r:set_resource("horse", 0)
u:add_item("horse", 21)
u:add_item("dolphin", 10)
u:add_order("GIB 0 7 PFERD")
u:add_order("GIB 0 5 DELPHIN")
process_orders()
assert_equal(7, r:get_resource("horse"))
assert_equal(5, u:get_item("dolphin"))
assert_equal(14, u:get_item("horse"))
end
function test_give_silver()
local r = region.create(0, 0, "plain")
local f = create_faction('human')
local u = unit.create(f, r, 1)
r:set_resource("peasant", 0)
r:set_resource("money", 11)
u:clear_orders()
u:add_item("money", 20)
u:add_order("GIB 0 10 SILBER")
process_orders()
assert_equal(21, r:get_resource("money"))
assert_equal(10, u:get_item("money"))
end
function test_build_castle()
local r = region.create(0, 0, "plain")
local f = create_faction('human')
local u = unit.create(f, r, 1)
u:add_item('stone', 1)
u:set_skill('building', 1)
u:add_order("MACHE BURG")
process_orders()
assert_not_nil(u.building)
assert_equal(1, u.building.size)
assert_equal(u.building.name, "Burg")
end

View File

@ -1416,9 +1416,6 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r)
}
}
}
if (r->land) {
print_items(F, r->land->items, f->locale);
}
cr_output_curses_compat(F, f, r, TYP_REGION);
cr_borders(r, f, r->seen.mode, F);
if (r->seen.mode == seen_unit && is_astral(r)

View File

@ -211,43 +211,6 @@ static int lua_callspell(castorder * co, const char *fname)
return result;
}
/** callback to initialize a familiar from lua. */
static int lua_initfamiliar(unit * u)
{
lua_State *L = (lua_State *)global.vm_state;
char fname[64];
int result = -1;
strlcpy(fname, "initfamiliar_", sizeof(fname));
strlcat(fname, u_race(u)->_name, sizeof(fname));
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, u, TOLUA_CAST "unit");
if (lua_pcall(L, 1, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("familiar(%s) calling '%s': %s.\n", unitname(u), fname, error);
lua_pop(L, 1);
}
else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
}
else {
log_warning("familiar(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
}
create_mage(u, M_GRAY);
strlcpy(fname, u_race(u)->_name, sizeof(fname));
strlcat(fname, "_familiar", sizeof(fname));
equip_unit(u, get_equipment(fname));
return result;
}
static int
lua_changeresource(unit * u, const struct resource_type *rtype, int delta)
{
@ -281,127 +244,6 @@ lua_changeresource(unit * u, const struct resource_type *rtype, int delta)
return result;
}
static int lua_getresource(unit * u, const struct resource_type *rtype)
{
lua_State *L = (lua_State *)global.vm_state;
int result = -1;
char fname[64];
strlcpy(fname, rtype->_name, sizeof(fname));
strlcat(fname, "_getresource", sizeof(fname));
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, u, TOLUA_CAST "unit");
if (lua_pcall(L, 1, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("get(%s) calling '%s': %s.\n", unitname(u), fname, error);
lua_pop(L, 1);
}
else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
}
else {
log_error("get(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
}
return result;
}
static int
lua_wage(const region * r, const faction * f, const race * rc, int in_turn)
{
lua_State *L = (lua_State *)global.vm_state;
const char *fname = "wage";
int result = -1;
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)r, TOLUA_CAST "region");
tolua_pushusertype(L, (void *)f, TOLUA_CAST "faction");
tolua_pushstring(L, rc ? rc->_name : 0);
lua_pushinteger(L, in_turn);
if (lua_pcall(L, 3, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("wage(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error);
lua_pop(L, 1);
}
else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
}
else {
log_error("wage(%s) calling '%s': not a function.\n", regionname(r, NULL), fname);
lua_pop(L, 1);
}
return result;
}
static int lua_maintenance(const unit * u)
{
lua_State *L = (lua_State *)global.vm_state;
const char *fname = "maintenance";
int result = -1;
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
if (lua_pcall(L, 1, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("maintenance(%s) calling '%s': %s.\n", unitname(u), fname, error);
lua_pop(L, 1);
}
else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
}
else {
log_error("maintenance(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
}
return result;
}
static int lua_equipmentcallback(const struct equipment *eq, unit * u)
{
lua_State *L = (lua_State *)global.vm_state;
char fname[64];
int result = -1;
strlcpy(fname, "equip_", sizeof(fname));
strlcat(fname, eq->name, sizeof(fname));
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
if (lua_pcall(L, 1, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("equip(%s) calling '%s': %s.\n", unitname(u), fname, error);
lua_pop(L, 1);
}
else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
}
else {
log_error("equip(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
}
return result;
}
/** callback for an item-use function written in lua. */
static int
use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
@ -447,7 +289,6 @@ use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
return result;
}
/* compat code for old data files */
static int caldera_read(trigger *t, struct gamedata *data)
{
@ -469,17 +310,10 @@ void register_tolua_helpers(void)
at_register(&at_building_action);
callbacks.cast_spell = lua_callspell;
callbacks.use_item = use_item_lua;
callbacks.produce_resource = produce_resource_lua;
callbacks.limit_resource = limit_resource_lua;
register_function((pf_generic)lua_initfamiliar, "lua_initfamiliar");
register_function((pf_generic)lua_getresource, "lua_getresource");
register_function((pf_generic)lua_changeresource, "lua_changeresource");
register_function((pf_generic)lua_equipmentcallback, "lua_equip");
register_function((pf_generic)lua_wage, "lua_wage");
register_function((pf_generic)lua_maintenance, "lua_maintenance");
item_use_fun = use_item_lua;
res_produce_fun = produce_resource_lua;
res_limit_fun = limit_resource_lua;
register_item_give(lua_giveitem, "lua_giveitem");
}

View File

@ -196,9 +196,6 @@ const char *buildingtype(const building_type * btype, const building * b, int bs
}
}
}
if (btype->name) {
return btype->name(btype, b, bsize);
}
if (btype->construction && btype->construction->name) {
if (b) {
bsize = adjust_size(b, bsize);
@ -362,9 +359,6 @@ building *new_building(const struct building_type * btype, region * r,
*bptr = b;
update_lighthouse(b);
if (b->type->name) {
bname = LOC(lang, buildingtype(btype, b, 0));
}
if (!bname) {
bname = LOC(lang, btype->_name);
}

View File

@ -68,14 +68,11 @@ extern "C" {
struct maintenance *maintenance; /* array of requirements */
struct construction *construction; /* construction of 1 building-level */
struct resource_mod *modifiers; /* modify production skills */
const char *(*name) (const struct building_type *,
const struct building * b, int size);
struct attrib *attribs;
} building_type;
extern struct selist *buildingtypes;
extern struct attrib_type at_building_action;
extern struct attrib_type at_building_generic_type;
int cmp_castle_size(const struct building *b, const struct building *a);
int building_protection(const struct building_type *btype, int stage);
@ -114,13 +111,13 @@ extern "C" {
int flags;
} building;
extern struct attrib_type at_building_generic_type;
extern const char *buildingtype(const building_type * btype,
const char *buildingtype(const building_type * btype,
const struct building *b, int bsize);
extern const char *write_buildingname(const building * b, char *ibuf,
const char *write_buildingname(const building * b, char *ibuf,
size_t size);
extern int buildingcapacity(const struct building *b);
extern struct building *new_building(const struct building_type *typ,
int buildingcapacity(const struct building *b);
struct building *new_building(const struct building_type *typ,
struct region *r, const struct locale *lang);
int build_building(struct unit *u, const struct building_type *typ,
int id, int size, struct order *ord);
@ -145,9 +142,9 @@ extern "C" {
void bunhash(struct building *b);
int buildingcapacity(const struct building *b);
extern void remove_building(struct building **blist, struct building *b);
extern void free_building(struct building *b);
extern void free_buildings(void);
void remove_building(struct building **blist, struct building *b);
void free_building(struct building *b);
void free_buildings(void);
const struct building_type *findbuildingtype(const char *name,
const struct locale *lang);
@ -155,16 +152,16 @@ extern "C" {
#include "build.h"
#define NOBUILDING NULL
extern int resolve_building(variant data, void *address);
extern void write_building_reference(const struct building *b,
int resolve_building(variant data, void *address);
void write_building_reference(const struct building *b,
struct storage *store);
extern variant read_building_reference(struct gamedata *data);
variant read_building_reference(struct gamedata *data);
extern struct building *findbuilding(int n);
struct building *findbuilding(int n);
extern struct unit *building_owner(const struct building *b);
extern void building_set_owner(struct unit * u);
extern void building_update_owner(struct building * bld);
struct unit *building_owner(const struct building *b);
void building_set_owner(struct unit * u);
void building_update_owner(struct building * bld);
bool buildingtype_exists(const struct region *r,
const struct building_type *bt, bool working);
@ -172,10 +169,10 @@ extern "C" {
bool is_building_type(const struct building_type *btype, const char *name);
struct building *active_building(const struct unit *u, const struct building_type *btype);
extern const char *buildingname(const struct building *b);
const char *buildingname(const struct building *b);
extern const char *building_getname(const struct building *b);
extern void building_setname(struct building *self, const char *name);
const char *building_getname(const struct building *b);
void building_setname(struct building *self, const char *name);
struct region *building_getregion(const struct building *b);
void building_setregion(struct building *bld, struct region *r);

View File

@ -294,9 +294,8 @@ static void test_btype_defaults(CuTest *tc) {
CuAssertStrEquals(tc, "hodor", btype->_name);
CuAssertPtrEquals(tc, 0, btype->maintenance);
CuAssertPtrEquals(tc, 0, btype->construction);
CuAssertTrue(tc, !btype->name);
CuAssertTrue(tc, !btype->taxes);
CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0);
CuAssertIntEquals(tc, 0, btype->taxes);
CuAssertIntEquals(tc, -1, btype->maxsize);
CuAssertIntEquals(tc, 1, btype->capacity);
CuAssertIntEquals(tc, -1, btype->maxcapacity);

View File

@ -24,9 +24,18 @@ extern "C" {
#endif
struct castorder;
struct order;
struct unit;
struct region;
struct item_type;
struct resource_type;
struct callback_struct {
int (*cast_spell)(struct castorder *co, const char *fname);
int (*use_item)(struct unit *u, const struct item_type *itype,
int amount, struct order *ord);
void(*produce_resource)(struct region *, const struct resource_type *, int);
int(*limit_resource)(const struct region *, const struct resource_type *);
};
extern struct callback_struct callbacks;

View File

@ -911,14 +911,15 @@ void read_items(struct storage *store, item ** ilist)
{
for (;;) {
char ibuf[32];
const item_type *itype;
int i;
READ_STR(store, ibuf, sizeof(ibuf));
if (!strcmp("end", ibuf)) {
break;
}
itype = it_find(ibuf);
READ_INT(store, &i);
if (ilist) {
const item_type *itype;
itype = it_find(ibuf);
if (i <= 0) {
log_error("data contains an entry with %d %s", i, ibuf);
}
@ -932,6 +933,7 @@ void read_items(struct storage *store, item ** ilist)
assert(itype && itype->rtype);
}
}
}
}
void write_items(struct storage *store, item * ilist)

View File

@ -339,11 +339,6 @@ static void json_building(cJSON *json, building_type *bt) {
}
break;
case cJSON_String:
if (strcmp(child->string, "name") == 0) {
bt->name = (const char *(*)(const struct building_type *,
const struct building *, int))get_function(child->valuestring);
break;
}
log_error("building %s contains unknown attribute %s", json->string, child->string);
break;
default:

View File

@ -1080,8 +1080,7 @@ void terraform_region(region * r, const terrain_type * terrain)
if (!fval(terrain, LAND_REGION)) {
region_setinfo(r, NULL);
if (r->land != NULL) {
i_freeall(&r->land->items);
if (r->land) {
free_land(r->land);
r->land = NULL;
}
@ -1101,7 +1100,6 @@ void terraform_region(region * r, const terrain_type * terrain)
for (d = 0; d != MAXDIRECTIONS; ++d) {
rsetroad(r, d, 0);
}
i_freeall(&r->land->items);
}
else {
static struct surround {
@ -1176,11 +1174,6 @@ void terraform_region(region * r, const terrain_type * terrain)
if (fval(terrain, LAND_REGION)) {
const item_type *itype = NULL;
char equip_hash[64];
/* TODO: put the equipment in struct terrain, faster */
sprintf(equip_hash, "terrain_%s", terrain->_name);
equip_items(&r->land->items, get_equipment(equip_hash));
if (r->terrain->herbs) {
int len = 0;

View File

@ -105,7 +105,6 @@ extern "C" {
int peasants;
int newpeasants;
int money;
struct item *items; /* items that can be claimed */
struct region_owner *ownership;
} land_region;

View File

@ -11,10 +11,11 @@
*/
#include <platform.h>
#include <kernel/config.h>
#include "resources.h"
/* kernel includes */
#include <kernel/config.h>
#include <kernel/callbacks.h>
#include "build.h"
#include "item.h"
#include "region.h"
@ -213,16 +214,11 @@ struct rawmaterial_type *rmt_create(struct resource_type *rtype)
return rmtype;
}
int(*item_use_fun)(struct unit *u, const struct item_type *itype, int amount,
struct order *ord);
int(*res_limit_fun)(const struct region *, const struct resource_type *);
void(*res_produce_fun)(struct region *, const struct resource_type *, int);
int limit_resource(const struct region *r, const resource_type *rtype)
{
assert(!rtype->raw);
if (res_limit_fun) {
return res_limit_fun(r, rtype);
if (callbacks.limit_resource) {
return callbacks.limit_resource(r, rtype);
}
return -1;
}
@ -230,7 +226,7 @@ int limit_resource(const struct region *r, const resource_type *rtype)
void produce_resource(struct region *r, const struct resource_type *rtype, int amount)
{
assert(!rtype->raw);
if (res_produce_fun) {
res_produce_fun(r, rtype, amount);
if (callbacks.produce_resource) {
callbacks.produce_resource(r, rtype, amount);
}
}

View File

@ -15,8 +15,11 @@
extern "C" {
#endif
#include <util/variant.h>
struct building_type;
struct race;
struct region;
enum {
RM_USED = 1 << 0, /* resource has been used */
@ -71,10 +74,6 @@ extern "C" {
int base, int divisor, const struct resource_type *rtype);
struct rawmaterial_type *rmt_create(struct resource_type *rtype);
extern int(*res_limit_fun)(const struct region *, const struct resource_type *);
extern void(*res_produce_fun)(struct region *, const struct resource_type *, int);
extern int (*item_use_fun)(struct unit *, const struct item_type *, int amount,
struct order *ord);
int limit_resource(const struct region *r, const struct resource_type *rtype);
void produce_resource(struct region *r, const struct resource_type *rtype, int amount);

View File

@ -1021,7 +1021,9 @@ static region *readregion(struct gamedata *data, int x, int y)
if (!r->land->demands) {
fix_demand(r);
}
read_items(data->store, &r->land->items);
if (data->version < NOLANDITEM_VERSION) {
read_items(data->store, NULL);
}
if (data->version >= REGIONOWNER_VERSION) {
READ_INT(data->store, &n);
region_set_morale(r, MAX(0, (short)n), -1);
@ -1095,7 +1097,6 @@ void writeregion(struct gamedata *data, const region * r)
WRITE_INT(data->store, demand->value);
}
WRITE_TOK(data->store, "end");
write_items(data->store, r->land->items);
WRITE_SECTION(data->store);
#if RELEASE_VERSION>=REGIONOWNER_VERSION
WRITE_INT(data->store, region_get_morale(r));

View File

@ -356,14 +356,7 @@ static int parse_buildings(xmlDocPtr doc)
continue;
}
assert(propValue != NULL);
if (strcmp((const char *)propValue, "name") == 0) {
btype->name =
(const char *(*)(const struct building_type *,
const struct building *, int))fun;
}
else {
log_error("unknown function type '%s' for building %s\n", (const char *)propValue, btype->_name);
}
xmlFree(propValue);
}
xmlXPathFreeObject(result);

View File

@ -45,6 +45,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* kernel includes */
#include <kernel/alliance.h>
#include <kernel/ally.h>
#include <kernel/callbacks.h>
#include <kernel/connection.h>
#include <kernel/curse.h>
#include <kernel/building.h>
@ -3218,7 +3219,7 @@ static int use_item(unit * u, const item_type * itype, int amount, struct order
}
if (itype->flags & ITF_CANUSE) {
int result = item_use_fun(u, itype, amount, ord);
int result = callbacks.use_item(u, itype, amount, ord);
if (result > 0) {
use_pooled(u, itype->rtype, GET_DEFAULT, result);
}

View File

@ -4534,12 +4534,7 @@ int sp_icastle(castorder * co)
b->size = ((rng_int() % (int)(power)) + 1) * 5;
}
if (type->name == NULL) {
bname = LOC(mage->faction->locale, type->_name);
}
else {
bname = LOC(mage->faction->locale, buildingtype(type, b, 0));
}
building_setname(b, bname);
/* TODO: Auf timeout und action_destroy umstellen */

View File

@ -33,10 +33,11 @@
#define ATHASH_VERSION 353 /* attribute-type hash, not name */
#define NOWATCH_VERSION 354 /* plane->watchers is gone */
#define KEYVAL_VERSION 355 /* at_keys has values */
#define NOLANDITEM_VERSION 356 /* land_region has no items */
/* unfinished: */
#define CRYPT_VERSION 400 /* passwords are encrypted */
#define RELEASE_VERSION KEYVAL_VERSION /* current datafile */
#define RELEASE_VERSION NOLANDITEM_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 */