#include "lauxlib.h" #include "log.h" #include "lephisto.h" #include "rng.h" #include "land.h" #include "lluadef.h" #include "map.h" #include "llua_space.h" static int planetL_createmetatable(lua_State* L); static int systemL_createmetatable(lua_State* L); /* Space. */ static int planetL_get(lua_State* L); static int systemL_get(lua_State* L); static const luaL_reg space_methods[] = { { "getPlanet", planetL_get }, { "getSystem", systemL_get }, { 0, 0 } }; /* Planet metatable methods. */ static int planetL_eq(lua_State* L); static int planetL_name(lua_State* L); static int planetL_faction(lua_State* L); static int planetL_class(lua_State* L); static int planetL_services(lua_State* L); static const luaL_reg planet_methods[] = { { "__eq", planetL_eq }, { "name", planetL_name }, { "faction", planetL_faction }, { "class", planetL_class }, { "services", planetL_services }, { 0, 0 } }; /* System metatable methods. */ static int systemL_eq(lua_State* L); static int systemL_name(lua_State* L); static int systemL_faction(lua_State* L); static int systemL_jumpdistance(lua_State* L); static const luaL_reg system_methods[] = { { "__eq", systemL_eq }, { "name", systemL_name }, { "faction", systemL_faction }, { "jumpDist", systemL_jumpdistance }, { 0, 0 } }; /* Load the space library. */ int lua_loadSpace(lua_State* L, int readonly) { (void)readonly; /* Register the functions. */ luaL_register(L, "space", space_methods); /* Register the metatables. */ planetL_createmetatable(L); systemL_createmetatable(L); return 0; } /* -- SPACE -- */ /* Create a planet metatable from a planet and put it on top of the stack. */ static int planetL_createmetatable(lua_State* L) { /* Create the metatable. */ luaL_newmetatable(L, PLANET_METATABLE); /* Create the access table. */ lua_pushvalue(L, -1); lua_setfield(L, -2,"__index"); /* Register the values. */ luaL_register(L, NULL, planet_methods); return 0; /* No error. */ } /* Register the system metatable. */ static int systemL_createmetatable(lua_State* L) { /* Create the metatable. */ luaL_newmetatable(L, SYSTEM_METATABLE); /* Create the access table. */ lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); /* Register the values. */ luaL_register(L, NULL, system_methods); return 0; /* No error. */ } /* -- PLANET -- */ /* Get planet at index. */ LuaPlanet* lua_toplanet(lua_State* L, int ind) { if(lua_isuserdata(L, ind)) { return (LuaPlanet*) lua_touserdata(L, ind); } luaL_typerror(L, ind, PLANET_METATABLE); return NULL; } /* Push a planet on the stack. */ LuaPlanet* lua_pushplanet(lua_State* L, LuaPlanet planet) { LuaPlanet* p; p = (LuaPlanet*) lua_newuserdata(L, sizeof(LuaPlanet)); *p = planet; luaL_getmetatable(L, PLANET_METATABLE); lua_setmetatable(L, -2); return p; } /* Check see if ind is a planet. */ int lua_isplanet(lua_State* L, int ind) { int ret; if(lua_getmetatable(L, ind)==0) return 0; lua_getfield(L, LUA_REGISTRYINDEX, PLANET_METATABLE); ret = 0; if(lua_rawequal(L, -1, -2)) /* Does it have the correct mt? */ ret = 1; lua_pop(L, 2); /* Remove both metatables. */ return ret; } /* get a planet. */ static int planetL_get(lua_State* L) { int i; int* factions; int nfactions; char** planets; int nplanets; char* rndplanet; LuaPlanet planet; LuaSystem sys; rndplanet = NULL; nplanets = 0; /* Get the landed planet. */ if(lua_gettop(L) == 0) { if(land_planet != NULL) { planet.p = land_planet; lua_pushplanet(L, planet); sys.s = system_get(planet_getSystem(land_planet->name)); lua_pushsystem(L, sys); return 2; } return 0; /* Not landed. */ } /* Get a planet by faction */ else if(lua_isnumber(L, 1)) { i = lua_tonumber(L, 1); planets = space_getFactionPlanet(&nplanets, &i, 1); } /* Get a planet by name. */ else if(lua_isstring(L, 1)) { rndplanet = (char*) lua_tostring(L, 1); } /* Get a planet from faction list. */ else if(lua_istable(L, 1)) { /* Load up the table. */ lua_pushnil(L); nfactions = (int)lua_gettop(L); factions = malloc(sizeof(int) * nfactions); i = 0; while(lua_next(L, -2) != 0) { factions[i++] = (int)lua_tonumber(L, -1); lua_pop(L,1); } /* Get the planets. */ planets = space_getFactionPlanet(&nplanets, factions, nfactions); free(factions); } else LLUA_INVALID_PARAMETER(); /* Bad parameter. */ /* No suitable planet found. */ if((rndplanet == NULL) && (nplanets == 0)) { free(planets); return 0; } /* Pick random planet. */ else if(rndplanet == NULL) { rndplanet = planets[RNG(0, nplanets-1)]; free(planets); } /* Push the planet. */ planet.p = planet_get(rndplanet); /* The real planet. */ lua_pushplanet(L, planet); sys.s = system_get(planet_getSystem(rndplanet)); lua_pushsystem(L, sys); return 2; } /* __eq (equality) metamethod for planets. */ static int planetL_eq(lua_State* L) { LuaPlanet* a, *b; a = lua_toplanet(L, 1); b = lua_toplanet(L, 2); if(a->p == b->p) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); return 1; } /* Get the planets name. */ static int planetL_name(lua_State* L) { LuaPlanet* p; p = lua_toplanet(L, 1); lua_pushstring(L, p->p->name); return 1; } /* Get the planets faction. */ static int planetL_faction(lua_State* L) { LuaPlanet* p; p = lua_toplanet(L, 1); lua_pushstring(L, faction_name(p->p->faction)); return 1; } /* Get the planets class. */ static int planetL_class(lua_State* L) { char buf[2]; LuaPlanet* p; p = lua_toplanet(L, 1); buf[0] = planet_getClass(p->p); buf[1] = '\0'; lua_pushstring(L, buf); return 1; } /* Get planet services. */ static int planetL_services(lua_State* L) { LuaPlanet* p; p = lua_toplanet(L, 1); lua_pushnumber(L, p->p->services); return 1; } /* -- SYSTEM -- */ /* Get system at index. */ LuaSystem* lua_tosystem(lua_State* L, int ind) { if(lua_isuserdata(L, ind)) { return (LuaSystem*) lua_touserdata(L,ind); } luaL_typerror(L, ind, SYSTEM_METATABLE); return NULL; } /* Pushes a system on the stack. */ LuaSystem* lua_pushsystem(lua_State* L, LuaSystem sys) { LuaSystem* s; s = (LuaSystem*) lua_newuserdata(L, sizeof(LuaSystem)); *s = sys; luaL_getmetatable(L, SYSTEM_METATABLE); lua_setmetatable(L, -2); return s; } /* Check to see if ind is a planet. */ int lua_issystem(lua_State* L, int ind) { int ret; if(lua_getmetatable(L, ind)==0) return 0; lua_getfield(L, LUA_REGISTRYINDEX, SYSTEM_METATABLE); ret = 0; if(lua_rawequal(L, -1, -2)) /* Does it have the correct mt? */ ret = 1; lua_pop(L, 2); /* Remove both metatables. */ return ret; } /* Get a system. */ static int systemL_get(lua_State* L) { LuaSystem sys; LuaPlanet* p; /* Get the current system with no parameters. */ if(lua_gettop(L) == 0) { sys.s = cur_system; } /* Passing a string (systemname) */ else if(lua_isstring(L, 1)) { sys.s = system_get((char*)lua_tostring(L, 1)); } /* Passing a planet */ else if(lua_isplanet(L, 1)) { p = lua_toplanet(L, 1); sys.s = system_get(planet_getSystem(p->p->name)); } else LLUA_INVALID_PARAMETER(); /* Return the system. */ lua_pushsystem(L, sys); return 1; } /* Check system for equality. */ static int systemL_eq(lua_State* L) { LuaSystem* a, *b; a = lua_tosystem(L, 1); b = lua_tosystem(L, 2); if(a->s == b->s) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); return 1; } /* Return the systems name. */ static int systemL_name(lua_State* L) { LuaSystem* sys; sys = lua_tosystem(L, 1); lua_pushstring(L, sys->s->name); return 1; } /* Get system factions. */ static int systemL_faction(lua_State* L) { int i; LuaSystem* sys; sys = lua_tosystem(L, 1); /* Return result in table. */ lua_newtable(L); for(i = 0; i < sys->s->nplanets; i++) { if(sys->s->planets[i].faction > 0) { /* Faction must be valid. */ lua_pushboolean(L, 1); /* Value. */ lua_setfield(L, -2, faction_name(sys->s->planets[i].faction)); /* Key. */ /* Allows syntax foo = space.faction("foo"); if foo["bar"] then ... end */ } } return 1; } /* Get jump distance for current system, or to another. */ static int systemL_jumpdistance(lua_State* L) { LLUA_MIN_ARGS(1); LuaSystem* sys; StarSystem** s; int jumps; char* start, *goal; sys = lua_tosystem(L, 1); start = sys->s->name; if((lua_gettop(L) > 1) && lua_isstring(L, 2)) goal = (char*)lua_tostring(L, 2); else goal = cur_system->name; s = map_getJumpPath(&jumps, start, goal, 1); free(s); lua_pushnumber(L, jumps); return 1; }