new attribute "object" allows arbitrary named data to be added to any object (improvement on the "key" attribute)

exported to LUA: x.objects returns the collection of objects, accessible through :get() and :set() functions
This commit is contained in:
Enno Rehling 2005-11-26 15:28:11 +00:00
parent 10b2d08a0a
commit d808de65c8
15 changed files with 482 additions and 234 deletions

View File

@ -51,6 +51,15 @@ object_write(const attrib *a, FILE *F)
int type = (int)data->type;
fprintf(F, "%s %d ", data->name, type);
switch (data->type) {
case TINTEGER:
fprintf(F, "%d ", data->data.i);
break;
case TREAL:
fprintf(F, "%lf ", data->data.real);
break;
case TSTRING:
fwritestr(F, data->data.str);
break;
case TUNIT:
write_unit_reference(data->data.u, F);
break;
@ -79,22 +88,33 @@ object_read(attrib *a, FILE *F)
{
object_data * data = (object_data *)a->data.v;
int type;
char name[64];
fscanf(F, "%s %d", name, &type);
char buffer[128];
fscanf(F, "%s %d", buffer, &type);
data->name = strdup(buffer);
data->type = (object_type)type;
switch (data->type) {
case TINTEGER:
fscanf(F, "%d", &data->data.i);
break;
case TREAL:
fscanf(F, "%lf", &data->data.real);
break;
case TSTRING:
freadstr(F, buffer, sizeof(buffer));
data->data.str = strdup(buffer);
break;
case TBUILDING:
return read_building_reference(&data->data.b, F);
case TUNIT:
return read_unit_reference(&data->data.u, F);
case TFACTION:
return read_faction_reference(&data->data.f, F);
case TBUILDING:
return read_building_reference(&data->data.b, F);
case TREGION:
return read_region_reference(&data->data.r, F);
case TSHIP:
/* return read_ship_reference(&data->data.sh, F); */
assert(!"not implemented");
break;
case TREGION:
return read_region_reference(&data->data.r, F);
case TNONE:
break;
default:
@ -117,6 +137,7 @@ object_done(attrib * a)
{
object_data * data = (object_data *)a->data.v;
if (data->type == TSTRING) free(data->data.str);
free(data->name);
free(a->data.v);
}
@ -137,9 +158,19 @@ object_create(const char * name, object_type type, variant value)
{
attrib * a = a_new(&at_object);
object_data * data = (object_data *)a->data.v;
data->type = type;
data->name = strdup(name);
object_set(a, type, value);
return a;
}
void
object_set(attrib * a, object_type type, variant value)
{
object_data * data = (object_data *)a->data.v;
if (data->type==TSTRING) free(data->data.str);
data->type = type;
switch (type) {
case TSTRING:
data->data.str = strdup(value.v);
@ -171,7 +202,42 @@ object_create(const char * name, object_type type, variant value)
assert(!"invalid object-type");
break;
}
return a;
}
extern void object_get(const struct attrib * a, variant * value, object_type * type);
void
object_get(const struct attrib * a, object_type * type, variant * value)
{
object_data * data = (object_data *)a->data.v;
*type = data->type;
switch (data->type) {
case TSTRING:
value->v = data->data.str;
break;
case TINTEGER:
value->i = data->data.i;
break;
case TREAL:
value->f = (float)data->data.real;
break;
case TREGION:
value->v = data->data.r;
break;
case TBUILDING:
value->v = data->data.b;
break;
case TFACTION:
value->v = data->data.f;
break;
case TUNIT:
value->v = data->data.u;
break;
case TSHIP:
value->v = data->data.sh;
break;
case TNONE:
break;
default:
assert(!"invalid object-type");
break;
}
}

View File

@ -27,7 +27,8 @@ typedef enum {
extern attrib_type at_object;
extern struct attrib * object_create(const char * name, object_type type, variant value);
extern void object_get(const struct attrib * a, variant * value, object_type * type);
extern void object_get(const struct attrib * a, object_type * type, variant * value);
extern void object_set(struct attrib * a, object_type type, variant value);
extern const char * object_name(const struct attrib * a);
#ifdef __cplusplus

View File

@ -247,12 +247,12 @@ parse_buildings(xmlDocPtr doc)
{
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
xmlXPathObjectPtr buildings;
xmlNodeSetPtr nodes;
int i;
/* reading eressea/buildings/building */
buildings = xmlXPathEvalExpression(BAD_CAST "/eressea/buildings/building", xpath);
nodes = buildings->nodesetval;
if (buildings->nodesetval!=NULL) {
xmlNodeSetPtr nodes = buildings->nodesetval;
for (i=0;i!=nodes->nodeNr;++i) {
xmlNodePtr node = nodes->nodeTab[i];
xmlChar * property;
@ -344,6 +344,7 @@ parse_buildings(xmlDocPtr doc)
/* finally, register the new building type */
bt_register(bt);
}
}
xmlXPathFreeObject(buildings);
xmlXPathFreeContext(xpath);
@ -467,12 +468,12 @@ parse_ships(xmlDocPtr doc)
{
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
xmlXPathObjectPtr ships;
xmlNodeSetPtr nodes;
int i;
/* reading eressea/ships/ship */
ships = xmlXPathEvalExpression(BAD_CAST "/eressea/ships/ship", xpath);
nodes = ships->nodesetval;
if (ships->nodesetval!=NULL) {
xmlNodeSetPtr nodes = ships->nodesetval;
for (i=0;i!=nodes->nodeNr;++i) {
xmlNodePtr node = nodes->nodeTab[i];
xmlChar * property;
@ -530,6 +531,7 @@ parse_ships(xmlDocPtr doc)
/* finally, register the new building type */
st_register(st);
}
}
xmlXPathFreeObject(ships);
xmlXPathFreeContext(xpath);
@ -1175,12 +1177,13 @@ parse_spells(xmlDocPtr doc)
{
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
xmlXPathObjectPtr spells;
xmlNodeSetPtr nodes;
int i;
/* reading eressea/spells/spell */
spells = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spell", xpath);
nodes = spells->nodesetval;
if (spells->nodesetval!=NULL) {
xmlNodeSetPtr nodes = spells->nodesetval;
int i;
for (i=0;i!=nodes->nodeNr;++i) {
xmlXPathObjectPtr result;
xmlNodePtr node = nodes->nodeTab[i];
@ -1269,6 +1272,7 @@ parse_spells(xmlDocPtr doc)
sp->id = 0;
register_spell(sp);
}
}
xmlXPathFreeObject(spells);

View File

@ -30,9 +30,8 @@ __at_hashkey(const char* s)
int key = 0;
size_t i = strlen(s);
while (i) {
--i;
key = ((key & 1) << 31) ^ (key >> 1) ^ s[i];
while (i>0) {
key = (s[--i] + key*37);
}
return key & 0x7fffffff;
}

View File

@ -20,6 +20,7 @@ LUASERVER_SOURCES =
<lua>event.cpp
<lua>faction.cpp
<lua>message.cpp
<lua>objects.cpp
<lua>region.cpp
<lua>script.cpp
<lua>ship.cpp

View File

@ -287,6 +287,12 @@
<File
RelativePath=".\lua\message.cpp">
</File>
<File
RelativePath=".\lua\objects.cpp">
</File>
<File
RelativePath=".\lua\objects.h">
</File>
<File
RelativePath=".\lua\region.cpp">
<FileConfiguration

View File

@ -13,5 +13,6 @@ extern void bind_item(struct lua_State * L);
extern void bind_event(struct lua_State * L);
extern void bind_message(struct lua_State * L);
extern void bind_script(struct lua_State * L);
extern void bind_objects(struct lua_State * L);
#endif

View File

@ -2,6 +2,7 @@
#include <cstring>
#include <eressea.h>
#include "list.h"
#include "objects.h"
#include "script.h"
// kernel includes
@ -175,5 +176,6 @@ bind_building(lua_State * L)
.def_readonly("id", &building::no)
.def_readwrite("size", &building::size)
.def("add_action", &building_addaction)
.property("objects", &eressea::get_objects<building>)
];
}

View File

@ -1,6 +1,7 @@
#include <config.h>
#include <eressea.h>
#include "list.h"
#include "objects.h"
// kernel includes
#include <kernel/alliance.h>
@ -298,5 +299,6 @@ bind_faction(lua_State * L)
.property("units", &faction_units, return_stl_iterator)
.property("alliance", &faction_getalliance, &faction_setalliance)
.property("race", &faction_getrace, &faction_setrace)
.property("objects", &eressea::get_objects<faction>)
];
}

117
src/eressea/lua/objects.cpp Normal file
View File

@ -0,0 +1,117 @@
#include <config.h>
#include <eressea.h>
#include "objects.h"
#include <kernel/region.h>
#include <kernel/unit.h>
#include <kernel/faction.h>
#include <kernel/ship.h>
#include <kernel/building.h>
#include <util/attrib.h>
// lua includes
#include <lua.hpp>
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
#include <string>
using namespace luabind;
namespace eressea {
object
objects::get(const char * name) {
attrib * a = a_find(*mAttribPtr, &at_object);
for (;a;a=a->nexttype) {
if (strcmp(object_name(a), name)==0) {
lua_State * L = (lua_State *)global.vm_state;
variant val;
object_type type;
object_get(a, &type, &val);
switch (type) {
case TNONE:
break;
case TINTEGER:
return object(L, val.i);
case TREAL:
return object(L, val.f);
case TREGION:
return object(L, (region*)val.v);
case TBUILDING:
return object(L, (building*)val.v);
case TUNIT:
return object(L, (unit*)val.v);
case TSHIP:
return object(L, (ship*)val.v);
case TSTRING:
return object(L, std::string((const char*)val.v));
default:
assert(!"not implemented");
}
}
}
return object(); // nil
}
static void set_object(attrib **attribs, const char * name, object_type type, variant val) {
attrib * a = a_find(*attribs, &at_object);
for (;a;a=a->nexttype) {
if (strcmp(object_name(a), name)==0) break;
}
if (a==NULL) {
a = a_add(attribs, object_create(name, type, val));
} else {
object_set(a, type, val);
}
}
template<> void
objects::set<int, TINTEGER>(const char * name, int value) {
variant val = { 0 };
val.i = value;
set_object(mAttribPtr, name, TINTEGER, val);
}
template<> void
objects::set<double, TREAL>(const char * name, double value) {
variant val = { 0 };
val.f = (float)value;
set_object(mAttribPtr, name, TREAL, val);
}
template<> void
objects::set<const char *, TSTRING>(const char * name, const char * value) {
variant val = { 0 };
val.v = strdup(value);
set_object(mAttribPtr, name, TSTRING, val);
}
template <class V, object_type T> void
objects::set(const char * name, V value) {
variant val = { 0 };
val.v = &value;
set_object(mAttribPtr, name, T, val);
}
}
void
bind_objects(struct lua_State * L)
{
using namespace eressea;
module(L)[
class_<objects>("objects")
.def("get", &objects::get)
.def("set", (void(objects::*)(const char*, region&))&objects::set<region&, TREGION>)
.def("set", (void(objects::*)(const char*, unit&))&objects::set<unit&, TUNIT>)
.def("set", (void(objects::*)(const char*, faction&))&objects::set<faction&, TFACTION>)
.def("set", (void(objects::*)(const char*, building&))&objects::set<building&, TBUILDING>)
.def("set", (void(objects::*)(const char*, ship&))&objects::set<ship&, TSHIP>)
// POD:
.def("set", (void(objects::*)(const char*, int))&objects::set<int, TINTEGER>)
.def("set", (void(objects::*)(const char*, double))&objects::set<double, TREAL>)
.def("set", (void(objects::*)(const char*, const char *))&objects::set<const char *, TSTRING>)
];
}

36
src/eressea/lua/objects.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef LUA_OBJECTS_H
#define LUA_OBJECTS_H
#include <attributes/object.h>
struct lua_State;
namespace luabind {
class object;
};
namespace eressea {
class objects {
public:
objects(struct attrib ** attribs) : mAttribPtr(attribs) {}
luabind::object get(const char * name);
// void set(const char * name, int type, luabind::object& value);
template <class V, object_type T> void
set(const char * name, V value);
private:
struct attrib ** mAttribPtr;
};
template<class T> eressea::objects
get_objects(const T& parent)
{
return eressea::objects(&const_cast<attrib *>(parent.attribs));
}
};
#endif

View File

@ -1,6 +1,7 @@
#include <config.h>
#include <eressea.h>
#include "list.h"
#include "objects.h"
// kernel includes
#include <kernel/building.h>
@ -242,6 +243,12 @@ region_move(region& r, short x, short y)
rhash(&r);
}
eressea::objects
region_objects(const region& r)
{
return eressea::objects(&const_cast<attrib *>(r.attribs));
}
void
bind_region(lua_State * L)
{
@ -279,5 +286,6 @@ bind_region(lua_State * L)
.property("units", &region_units, return_stl_iterator)
.property("buildings", &region_buildings, return_stl_iterator)
.property("ships", &region_ships, return_stl_iterator)
.property("objects", &eressea::get_objects<region>)
];
}

View File

@ -1,5 +1,6 @@
#include <config.h>
#include <eressea.h>
#include "objects.h"
// kernel includes
#include <build.h>
@ -68,5 +69,6 @@ bind_ship(lua_State * L)
.def_readwrite("damage", &ship::damage)
.def_readwrite("size", &ship::size)
.def_readwrite("coast", &ship::coast)
.property("objects", &eressea::get_objects<ship>)
];
}

View File

@ -1,6 +1,7 @@
#include <config.h>
#include <eressea.h>
#include "list.h"
#include "objects.h"
#include "script.h"
#include "event.h"
@ -578,5 +579,6 @@ bind_unit(lua_State * L)
.property("number", &unit_getnumber, &unit_setnumber)
.property("race", &unit_getrace, &unit_setrace)
.property("hp_max", &unit_hpmax)
.property("objects", &eressea::get_objects<unit>)
];
}

View File

@ -303,6 +303,7 @@ lua_init(void)
luaopen_io(luaState);
luaopen_table(luaState);
luabind::open(luaState);
bind_objects(luaState);
bind_eressea(luaState);
bind_script(luaState);
bind_spell(luaState);