OpenFusion/src/lua/EntityWrapper.cpp

174 lines
4.3 KiB
C++

#include "lua/LuaWrapper.hpp"
#include "lua/LuaManager.hpp"
#include "lua/EntityWrapper.hpp"
#include "Entities.hpp"
#define LIBNAME "Entity"
#define SUPERTBL "__entSUPERCLASSES"
#define ENTYGONESTR "Entity doesn't exist anymore!"
EntityRef* grabBaseEntityRef(lua_State *state, int indx) {
// first, make sure its a userdata
luaL_checktype(state, indx, LUA_TUSERDATA);
// grab the super class table
lua_getfield(state, LUA_REGISTRYINDEX, SUPERTBL);
// grab the userdata
EntityRef *data = (EntityRef*)lua_touserdata(state, indx);
// check if it doesn't have a metatable
if (!lua_getmetatable(state, indx)) {
luaL_typerror(state, indx, LIBNAME);
return NULL;
}
// index the super class table
lua_gettable(state, -2);
// if the index was nil, it doesn't exist
if (lua_isnil(state, -1)) {
lua_pop(state, 1);
luaL_typerror(state, indx, LIBNAME);
return NULL;
}
// it's good :)
lua_pop(state, 1);
return data;
}
// check at index
EntityRef* grabEntityRef(lua_State *state, int indx) {
EntityRef *ref = grabBaseEntityRef(state, indx);
if (ref == NULL || !ref->isValid())
return NULL;
return ref;
}
// =============================================== [[ GETTERS ]] ===============================================
static int ent_getX(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
lua_pushnumber(state, ref->getEntity()->x);
return 1;
}
static int ent_getY(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
lua_pushnumber(state, ref->getEntity()->y);
return 1;
}
static int ent_getZ(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
lua_pushnumber(state, ref->getEntity()->z);
return 1;
}
static int ent_getType(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
// push the type string
switch(ref->type) {
case EntityType::PLAYER:
lua_pushstring(state, "Player");
break;
case EntityType::MOB:
lua_pushstring(state, "Mob");
break;
case EntityType::EGG:
lua_pushstring(state, "Egg");
break;
case EntityType::BUS:
lua_pushstring(state, "Bus");
break;
default: // INVALID, COMBAT_NPC, SIMPLE_NPC
lua_pushstring(state, "Entity");
break;
}
return 1;
}
static luaL_Reg ent_getters[] = {
{"x", ent_getX},
{"y", ent_getY},
{"z", ent_getZ},
{"type", ent_getType},
{0, 0}
};
// =============================================== [[ METHODS ]] ===============================================
static int ent_exists(lua_State *state) {
EntityRef *data = (EntityRef*)grabBaseEntityRef(state, 1);
lua_pushboolean(state, !(data == NULL || !data->isValid()));
return 1;
}
static luaL_Reg ent_methods[] = {
{"exists", ent_exists},
{0, 0}
};
void LuaManager::Entity::init(lua_State *state) {
// register our library as a global (and leave it on the stack)
luaL_register(state, LIBNAME, ent_methods);
lua_pop(state, 1); // pop library table
// will hold our super classes
lua_pushstring(state, SUPERTBL);
lua_newtable(state);
lua_rawset(state, LUA_REGISTRYINDEX);
}
void LuaManager::Entity::registerSuper(lua_State *state, const char *tname) {
// grab the super class table
lua_getfield(state, LUA_REGISTRYINDEX, SUPERTBL);
// grab the metatable
lua_getfield(state, LUA_REGISTRYINDEX, tname);
lua_pushboolean(state, 1);
// finally, set the index
lua_rawset(state, -3);
lua_pop(state, 1); // pop the super class table
}
void LuaManager::Entity::addGetters(lua_State *state) {
luaL_register(state, NULL, ent_getters);
}
void LuaManager::Entity::addMethods(lua_State *state) {
luaL_register(state, NULL, ent_methods);
}
void LuaManager::Entity::push(lua_State *state, EntityRef ref, const char *tname) {
// creates the udata and copies the reference to the udata
EntityRef *ent = (EntityRef*)lua_newuserdata(state, sizeof(EntityRef));
*ent = ref;
// attaches our metatable from the registry to the udata
luaL_getmetatable(state, tname);
lua_setmetatable(state, -2);
}