/* +-------------------+ | | Enno Rehling | Eressea PBEM host | Christian Schlittchen | (c) 1998 - 2008 | Katja Zedel | | Henning Peters +-------------------+ This program may not be used, modified or distributed without prior permission by the authors of Eressea. */ #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct building_action { char *fname; char *param; } building_action; static int lc_age(struct attrib *a, void *owner) { building_action *data = (building_action *)a->data.v; const char *fname = data->fname; const char *fparam = data->param; building *b = (building *)owner; int result = -1; assert(b != NULL); if (fname != NULL) { lua_State *L = (lua_State *)global.vm_state; lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); if (fparam) { tolua_pushstring(L, fparam); } if (lua_pcall(L, fparam ? 2 : 1, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("lc_age(%s) calling '%s': %s.\n", buildingname(b), fname, error); lua_pop(L, 1); } else { result = (int)lua_tonumber(L, -1); lua_pop(L, 1); } } else { log_error("lc_age(%s) calling '%s': not a function.\n", buildingname(b), fname); lua_pop(L, 1); } } return (result != 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } static const char *NULLSTRING = "(null)"; static void lc_init(struct attrib *a) { a->data.v = calloc(1, sizeof(building_action)); } static void lc_done(struct attrib *a) { building_action *data = (building_action *)a->data.v; if (data->fname) free(data->fname); if (data->param) free(data->param); free(data); } static void lc_write(const struct attrib *a, const void *owner, struct storage *store) { building_action *data = (building_action *)a->data.v; const char *fname = data->fname; const char *fparam = data->param; unused_arg(owner); WRITE_TOK(store, fname); WRITE_TOK(store, fparam ? fparam : NULLSTRING); } static int lc_read(struct attrib *a, void *owner, struct storage *store) { char name[NAMESIZE]; building_action *data = (building_action *)a->data.v; building *b = (building *)owner; int result = 0; if (global.data_version < ATTRIBOWNER_VERSION) { result = read_reference(&b, store, read_building_reference, resolve_building); assert(b == owner); } READ_TOK(store, name, sizeof(name)); if (strcmp(name, "tunnel_action") == 0) { /* E2: Weltentor has a new module, doesn't need this any longer */ result = 0; b = 0; } else { data->fname = _strdup(name); } READ_TOK(store, name, sizeof(name)); if (strcmp(name, "tnnL") == 0) { /* tunnel_action was the old Weltentore, their code has changed. ignore this object */ result = 0; b = 0; } if (strcmp(name, NULLSTRING) == 0) data->param = 0; else { data->param = _strdup(name); } if (result == 0 && !b) { return AT_READ_FAIL; } return AT_READ_OK; } attrib_type at_building_action = { "lcbuilding", lc_init, lc_done, lc_age, lc_write, lc_read }; void building_addaction(building * b, const char *fname, const char *param) { attrib *a = a_add(&b->attribs, a_new(&at_building_action)); building_action *data = (building_action *)a->data.v; data->fname = _strdup(fname); if (param) { data->param = _strdup(param); } }