#include #include "GameData.h" #include "Components.h" #include "GUIModule.h" #include "PhysicsModule.h" #include "CharacterModule.h" #include "CharacterAnimationModule.h" #include "BoatModule.h" #include "EventTriggerModule.h" #include "SlotsModule.h" #include "world-build.h" #include "LuaData.h" #include "luaaa.hpp" extern "C" { int luaopen_lpeg(lua_State *L); } struct FooPosition { Ogre::Vector3 value; Ogre::Vector3 &get() { return value; } }; namespace luaaa { template <> struct LuaStack { inline static FooPosition get(lua_State *L, int idx) { FooPosition result; if (lua_istable(L, idx)) { lua_pushnil(L); while (0 != lua_next(L, idx)) { const int top = lua_gettop(L); const char *name = LuaStack::get(L, top - 1); if (strncmp(name, "x", 1) == 0) result.value.x = LuaStack::get(L, top); else if (strncmp(name, "y", 1) == 0) result.value.y = LuaStack::get(L, top); else if (strncmp(name, "z", 1) == 0) result.value.z = LuaStack::get(L, top); lua_pop(L, 1); } lua_pop(L, 0); } return result; } inline static void put(lua_State *L, const FooPosition &v) { lua_newtable(L); LuaStack::put(L, "x"); LuaStack::put(L, v.value.x); lua_rawset(L, -3); LuaStack::put(L, "y"); LuaStack::put(L, v.value.y); lua_rawset(L, -3); LuaStack::put(L, "z"); LuaStack::put(L, v.value.z); lua_rawset(L, -3); } }; } namespace ECS { struct LuaEcsEntity { int id; flecs::entity e; }; struct idmap { std::unordered_map id2entity; std::unordered_map entity2id; int next_id; idmap() : id2entity({}) , entity2id({}) , next_id(0) { } int get_next_id() { next_id++; return next_id; } int add_entity(flecs::entity e) { if (entity2id.find(e.id()) != entity2id.end()) return entity2id[e.id()]; int id = get_next_id(); id2entity[id] = e; entity2id[e.id()] = id; return id; } flecs::entity get_entity(int id) { OgreAssert(id2entity[id].is_valid(), "Invalid entity"); return id2entity[id]; } }; struct idmap idmap; int LuaData::setup_handler() { luaL_checktype(L, 1, LUA_TFUNCTION); lua_pushvalue(L, 1); int ref = luaL_ref(L, LUA_REGISTRYINDEX); setup_handlers.push_back(ref); return 0; } int LuaData::call_handler(const Ogre::String &event) { int i; for (i = 0; i < setup_handlers.size(); i++) { lua_rawgeti(L, LUA_REGISTRYINDEX, setup_handlers[i]); lua_pushstring(L, event.c_str()); lua_pushinteger(L, -1); lua_pushinteger(L, -1); if (lua_pcall(L, 3, 0, 0)) { Ogre::LogManager::getSingleton().stream() << lua_tostring(L, -1); OgreAssert(false, "Lua error"); } } return 0; } int LuaData::call_handler(const Ogre::String &event, flecs::entity e, flecs::entity o) { int i; for (i = 0; i < setup_handlers.size(); i++) { lua_rawgeti(L, LUA_REGISTRYINDEX, setup_handlers[i]); lua_pushstring(L, event.c_str()); lua_pushinteger(L, idmap.add_entity(e)); lua_pushinteger(L, idmap.add_entity(o)); if (lua_pcall(L, 3, 0, 0)) { Ogre::LogManager::getSingleton().stream() << lua_tostring(L, -1); OgreAssert(false, "Lua error"); } } return 0; } static int luaLibraryLoader(lua_State *L) { int i; if (!lua_isstring(L, 1)) { luaL_error( L, "luaLibraryLoader: Expected string for first parameter"); } std::string libraryFile = lua_tostring(L, 1); std::cout << libraryFile << std::endl; // In order to be compatible with the normal Lua file loader, // translate '.' to the file system seperator character. // In this case (An ogre resource) '/' while (libraryFile.find('.') != std::string::npos) libraryFile.replace(libraryFile.find('.'), 1, "/"); libraryFile += ".lua"; std::cout << libraryFile << std::endl; Ogre::StringVectorPtr scripts = Ogre::ResourceGroupManager::getSingleton().listResourceNames( "LuaScripts", false); std::vector &strings = *scripts; for (i = 0; i < strings.size(); i++) std::cout << strings[i] << std::endl; if (0 && !Ogre::ResourceGroupManager::getSingleton() .resourceExistsInAnyGroup(libraryFile)) { // Could not find the file. std::string errMessage = "\n no file '" + libraryFile + "' found in Ogre resource archives."; lua_pushstring(L, errMessage.c_str()); } else { Ogre::DataStreamList streams = Ogre::ResourceGroupManager::getSingleton().openResources( "*.lua", "LuaScripts"); Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource( libraryFile, "LuaScripts"); Ogre::String script = stream->getAsString(); if (luaL_loadbuffer(L, script.c_str(), script.length(), libraryFile.c_str())) { luaL_error( L, "Error loading library '%s' from resource archive.\n%s", libraryFile.c_str(), lua_tostring(L, -1)); } } return 1; } struct LuaChildEventTrigger { flecs::entity parent_e; Ogre::Vector3 position; float halfheight; float radius; Ogre::String event; }; static void installLibraryLoader(lua_State *L) { // Insert the c++ func 'luaLibraryLoader' into package.loaders. // Inserted at the start of the table in order to take precedence. lua_getglobal(L, "table"); lua_getfield(L, -1, "insert"); lua_remove(L, -2); // table lua_getglobal(L, "package"); lua_getfield(L, -1, "searchers"); lua_remove(L, -2); // package lua_pushnumber(L, 1); // index where to insert into loaders table lua_pushcfunction(L, luaLibraryLoader); if (lua_pcall(L, 3, 0, 0)) Ogre::LogManager::getSingleton().stream() << lua_tostring(L, 1); } LuaData::LuaData() : L(luaL_newstate()) { luaopen_base(L); luaopen_table(L); luaopen_package(L); luaL_requiref(L, "table", luaopen_table, 1); lua_pop(L, 1); luaL_requiref(L, "math", luaopen_math, 1); lua_pop(L, 1); luaL_requiref(L, "package", luaopen_package, 1); lua_pop(L, 1); luaL_requiref(L, "string", luaopen_string, 1); lua_pop(L, 1); luaL_requiref(L, "io", luaopen_io, 1); lua_pop(L, 1); luaL_requiref(L, "lpeg", luaopen_lpeg, 1); lua_pop(L, 1); #if 0 luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); lua_pushcfunction(L, luaopen_lpeg); lua_setfield(L, -2, "lpeg"); lua_pop(L, 1); // remove PRELOAD table #endif installLibraryLoader(L); lua_pop(L, 1); #if 0 luaaa::LuaClass luaVector3(L, "Vector3"); luaVector3.ctor(); luaVector3.get("x", [](Ogre::Vector3 &v) -> float { return v.x; }); luaVector3.set("x", [](Ogre::Vector3 &v, float value) -> void { v.x = value; }); luaVector3.get("y", [](Ogre::Vector3 &v) -> float { return v.y; }); luaVector3.set("y", [](Ogre::Vector3 &v, float value) -> void { v.y = value; }); luaVector3.get("z", [](Ogre::Vector3 &v) -> float { return v.z; }); luaVector3.set("z", [](Ogre::Vector3 &v, float value) -> void { v.z = value; }); luaVector3.fun("squaredLength", &Ogre::Vector3::squaredLength); luaVector3.fun("length", &Ogre::Vector3::length); luaVector3.fun("squaredDistance", &Ogre::Vector3::squaredDistance); luaVector3.fun("distance", &Ogre::Vector3::distance); #endif luaaa::LuaModule luaECS(L, "_ecs"); luaECS.fun("position", [](int id) -> FooPosition { #if 0 flecs::entity e = idmap.get_entity(id); if (e.has()) { const CharacterBase &cb = e.get(); return cb.mBodyNode->_getDerivedPosition(); } else if (e.has()) { const BoatBase &boat = e.get(); return boat.mNode->_getDerivedPosition(); } else if (e.has()) { const EventTrigger &trigger = e.get(); return trigger.position; } else return Ogre::Vector3(0, 0, 0); #endif return FooPosition(); }); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(false, "Crash function called"); return 0; }); lua_setglobal(L, "crash"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TFUNCTION); ECS::get().mLua->setup_handler(); return 0; }); lua_setglobal(L, "setup_handler"); lua_pushcfunction(L, [](lua_State *L) -> int { int args = lua_gettop(L); if (args < 1) return 0; ECS::get_mut().choices.clear(); luaL_checktype(L, 1, LUA_TSTRING); if (args > 1) { luaL_checktype(L, 2, LUA_TTABLE); lua_pushnil(L); /* first key */ while (lua_next(L, 2) != 0) { Ogre::String s = lua_tostring(L, -1); ECS::get_mut().choices.push_back(s); lua_pop(L, 1); /* remove value but keep key */ } } size_t len; Ogre::String message(luaL_tolstring(L, 1, &len)); std::cout << "narrator message: " << message << " length: " << message.length() << std::endl; if (message.length() == 0 && ECS::get_mut().narrationBox) { ECS::get_mut().enabled = false; ECS::get_mut().grab = true; ECS::get_mut().grabChanged = true; ECS::get_mut().narrationText = message; ECS::get_mut().narrationBox = false; ECS::modified(); std::cout << "narration ended\n"; } else if (message.length() > 0) { ECS::get_mut().enabled = true; ECS::get_mut().grab = false; ECS::get_mut().grabChanged = true; ECS::get_mut().narrationText = message; ECS::get_mut().narrationBox = true; ECS::modified(); } return 0; }); lua_setglobal(L, "narrate"); lua_pushcfunction(L, [](lua_State *L) -> int { // ECS::get_mut().mainMenu = true; lua_pushinteger(L, ECS::get().narration_answer); return 1; }); lua_setglobal(L, "narration_get_answer"); lua_pushcfunction(L, [](lua_State *L) -> int { // ECS::get_mut().mainMenu = true; ECS::get_mut().enabled = true; ECS::get_mut().mainMenu = true; ECS::get_mut().grab = false; ECS::get_mut().grabChanged = true; ECS::modified(); return 0; }); lua_setglobal(L, "main_menu"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TSTRING); luaL_checktype(L, 2, LUA_TNUMBER); luaL_checktype(L, 3, LUA_TNUMBER); luaL_checktype(L, 4, LUA_TNUMBER); luaL_checktype(L, 5, LUA_TNUMBER); Ogre::String what = lua_tostring(L, 1); if (what == "boat") { float yaw = lua_tonumber(L, 5); float x = lua_tonumber(L, 2); float y = lua_tonumber(L, 3); float z = lua_tonumber(L, 4); flecs::entity e = ECS::get().entity(); Ogre::Quaternion orientation(Ogre::Radian(yaw), Ogre::Vector3(0, 1, 0)); Ogre::Vector3 position(x, y, z); e.set( { "boat.scene", position, orientation }); int ret = idmap.add_entity(e); lua_pushinteger(L, ret); std::cout << "boat created: " << ret << std::endl; return 1; } else if (what == "raft") { float yaw = lua_tonumber(L, 5); float x = lua_tonumber(L, 2); float y = lua_tonumber(L, 3); float z = lua_tonumber(L, 4); flecs::entity e = ECS::get().entity(); Ogre::Quaternion orientation(Ogre::Radian(yaw), Ogre::Vector3(0, 1, 0)); Ogre::Vector3 position(x, y, z); e.set( { "raft.scene", position, orientation }); int ret = idmap.add_entity(e); lua_pushinteger(L, ret); std::cout << "raft created: " << ret << std::endl; return 1; } lua_pushinteger(L, -1); return 1; }); lua_setglobal(L, "ecs_vehicle_set"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 6, "bad parameters"); luaL_checktype(L, 1, LUA_TSTRING); // event luaL_checktype(L, 2, LUA_TNUMBER); // x luaL_checktype(L, 3, LUA_TNUMBER); // y luaL_checktype(L, 4, LUA_TNUMBER); // z luaL_checktype(L, 5, LUA_TNUMBER); // halfh luaL_checktype(L, 6, LUA_TNUMBER); // radius flecs::entity e = ECS::get().entity(); Ogre::String event = lua_tostring(L, 1); float x = lua_tonumber(L, 2); float y = lua_tonumber(L, 3); float z = lua_tonumber(L, 4); float h = lua_tonumber(L, 5); float r = lua_tonumber(L, 6); Ogre::Vector3 position(x, y, z); e.set({ nullptr, position, h, r, event }); lua_pushinteger(L, idmap.add_entity(e)); return 1; }); lua_setglobal(L, "ecs_character_trigger"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TNUMBER); // object int object = lua_tointeger(L, 1); flecs::entity object_e = idmap.get_entity(object); flecs::entity parent_e = object_e.parent(); lua_pushinteger(L, idmap.add_entity(parent_e)); return 1; }); lua_setglobal(L, "ecs_parent"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 7, "bad parameters"); luaL_checktype(L, 1, LUA_TNUMBER); // parent luaL_checktype(L, 2, LUA_TSTRING); // event luaL_checktype(L, 3, LUA_TNUMBER); // x luaL_checktype(L, 4, LUA_TNUMBER); // y luaL_checktype(L, 5, LUA_TNUMBER); // z luaL_checktype(L, 6, LUA_TNUMBER); // halfh luaL_checktype(L, 7, LUA_TNUMBER); // radius int parent = lua_tointeger(L, 1); std::cout << "parent: " << parent << std::endl; flecs::entity parent_e = idmap.get_entity(parent); Ogre::String event = lua_tostring(L, 2); float x = lua_tonumber(L, 3); float y = lua_tonumber(L, 4); float z = lua_tonumber(L, 5); float h = lua_tonumber(L, 6); float r = lua_tonumber(L, 7); Ogre::Vector3 position(x, y, z); flecs::entity e = ECS::get().entity().child_of(parent_e); e.set( { parent_e, position, h, r, event }); lua_pushinteger(L, idmap.add_entity(e)); return 1; }); lua_setglobal(L, "ecs_child_character_trigger"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TNUMBER); // trigger luaL_checktype(L, 2, LUA_TNUMBER); // object int trigger = lua_tointeger(L, 1); int object = lua_tointeger(L, 2); flecs::entity trigger_e = idmap.get_entity(trigger); flecs::entity object_e = idmap.get_entity(object); Ogre::SceneNode *target_node = nullptr; Ogre::Any targetAny = trigger_e.get() .node->getUserObjectBindings() .getUserAny("target"); OgreAssert(targetAny.has_value(), "need target"); target_node = Ogre::any_cast(targetAny); Ogre::Vector3 position = target_node->_getDerivedPosition(); Ogre::Quaternion orientation = target_node->_getDerivedOrientation(); if (object_e.has()) { object_e.get_mut() .mBodyNode->_setDerivedPosition(position); object_e.get_mut() .mBodyNode->_setDerivedOrientation(orientation); } return 0; }); lua_setglobal(L, "ecs_trigger_set_position"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TNUMBER); // trigger int trigger = lua_tointeger(L, 1); flecs::entity trigger_e = idmap.get_entity(trigger); Ogre::SceneNode *node = trigger_e.get().node; Ogre::Any animationAny = node->getUserObjectBindings().getUserAny( "trigger_animation"); if (animationAny.has_value()) { Ogre::String animation = Ogre::any_cast(animationAny); lua_pushstring(L, animation.c_str()); return 1; } lua_pushnil(L); return 1; }); lua_setglobal(L, "ecs_trigger_get_animation"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 5, "Invalid parameters"); luaL_checktype(L, 1, LUA_TSTRING); // type luaL_checktype(L, 2, LUA_TNUMBER); luaL_checktype(L, 3, LUA_TNUMBER); luaL_checktype(L, 4, LUA_TNUMBER); luaL_checktype(L, 5, LUA_TNUMBER); Ogre::String type = lua_tostring(L, 1); float yaw = lua_tonumber(L, 5); float x = lua_tonumber(L, 2); float y = lua_tonumber(L, 3); float z = lua_tonumber(L, 4); flecs::entity e = ECS::get().entity(); Ogre::Quaternion orientation(Ogre::Radian(yaw), Ogre::Vector3(0, 1, 0)); Ogre::Vector3 npcPos(x, y, z); e.set({ orientation, npcPos }); e.set({ type }); e.add(); lua_pushinteger(L, idmap.add_entity(e)); return 1; }); lua_setglobal(L, "ecs_npc_set"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 1, "Bad parameters"); luaL_checktype(L, 1, LUA_TSTRING); // type const char *fileName = lua_tostring(L, 1); ECS::get().mScnMgr->getRootSceneNode()->saveChildren( fileName); return 0; }); lua_setglobal(L, "ecs_save_scene_debug"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 2, "Bad parameters"); luaL_checktype(L, 1, LUA_TNUMBER); // object luaL_checktype(L, 2, LUA_TSTRING); // name int object = lua_tointeger(L, 1); flecs::entity object_e = idmap.get_entity(object); const char *fileName = lua_tostring(L, 2); Ogre::SceneNode *node = nullptr; if (object_e.has()) node = object_e.get().mBodyNode; else if (object_e.has()) node = object_e.get().mNode; if (node) node->saveChildren(fileName); return 0; }); lua_setglobal(L, "ecs_save_object_debug"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TBOOLEAN); // object ECS::get_mut().enableDbgDraw = lua_toboolean(L, 1); ECS::modified(); return 0; }); lua_setglobal(L, "ecs_set_debug_drawing"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) >= 1, "Bad parameters"); luaL_checktype(L, 1, LUA_TSTRING); Ogre::String command = lua_tostring(L, 1); if (command == "physics-control") { OgreAssert(lua_gettop(L) == 3, "Bad parameters"); luaL_checktype(L, 2, LUA_TNUMBER); // object luaL_checktype(L, 3, LUA_TBOOLEAN); int object = lua_tointeger(L, 2); flecs::entity object_e = idmap.get_entity(object); bool enable = lua_toboolean(L, 3); OgreAssert(object_e.has(), "Not a character"); PhysicsModule::controlPhysics(object_e, enable); object_e.add(); return 0; } else if (command == "is-player") { OgreAssert(lua_gettop(L) == 2, "Bad parameters"); luaL_checktype(L, 2, LUA_TNUMBER); // object int object = lua_tointeger(L, 2); flecs::entity object_e = idmap.get_entity(object); lua_pushboolean(L, object_e.has()); return 1; } else if (command == "set-actuator") { OgreAssert(lua_gettop(L) == 3, "Bad parameters"); luaL_checktype(L, 2, LUA_TNUMBER); // object luaL_checktype(L, 3, LUA_TSTRING); // animation Ogre::String animation = lua_tostring(L, 3); int object = lua_tointeger(L, 2); flecs::entity object_e = idmap.get_entity(object); object_e.set( { { 0, 0, 0 }, { 0, 0, 0 } }); if (animation.length() > 0) object_e.set( { animation, { 0, 0, 0 } }); else object_e.remove(); return 0; } else if (command == "animation-state") { OgreAssert(lua_gettop(L) >= 4, "Bad parameters"); luaL_checktype(L, 2, LUA_TNUMBER); // object luaL_checktype(L, 3, LUA_TSTRING); // node luaL_checktype(L, 4, LUA_TSTRING); // state if (lua_gettop(L) == 5) luaL_checktype(L, 5, LUA_TBOOLEAN); // reset int object = lua_tointeger(L, 2); flecs::entity object_e = idmap.get_entity(object); Ogre::String nodeName = lua_tostring(L, 3); Ogre::String stateName = lua_tostring(L, 4); bool reset = false; if (lua_gettop(L) == 5) reset = lua_toboolean(L, 5); GameWorld::ValueParameter *obj = object_e.world() .get_mut() .allocate_entity(object_e); GameWorld::ValueParameter *obj_node = object_e.world() .get_mut() .allocate_string(nodeName); GameWorld::ValueParameter *obj_state = object_e.world() .get_mut() .allocate_string(stateName); ECS::get_mut().command("set_animation_state", { obj, obj_node, obj_state }); ECS::modified(); return 0; } else if (command == "params-set") { OgreAssert(lua_gettop(L) == 4, "Invalid parameters"); luaL_checktype(L, 2, LUA_TNUMBER); luaL_checktype(L, 3, LUA_TSTRING); luaL_checktype(L, 4, LUA_TBOOLEAN); bool enable = lua_toboolean(L, 4); flecs::entity e = idmap.get_entity(lua_tointeger(L, 2)); Ogre::String what = lua_tostring(L, 3); OgreAssert(e.is_valid(), "Invalid character"); OgreAssert(e.has(), "Not a character"); if (what == "gravity") { /* clear momentum */ if (e.has()) { e.get_mut() .gvelocity.y = 0.0f; e.get_mut() .velocity.y = 0.0f; e.modified(); } if (enable) e.add(); else e.remove(); } else if (what == "buoyancy") { if (enable) e.add(); else e.remove(); } else OgreAssert(false, "Bad parameter " + what); return 0; } else { OgreAssert(false, "bad argument " + command); return 0; } }); lua_setglobal(L, "ecs_character"); lua_pushcfunction(L, [](lua_State *L) -> int { OgreAssert(lua_gettop(L) == 3, "Bad parameters"); luaL_checktype(L, 1, LUA_TNUMBER); // parent luaL_checktype(L, 2, LUA_TNUMBER); // object luaL_checktype(L, 3, LUA_TSTRING); // slot int parent = lua_tointeger(L, 1); int object = lua_tointeger(L, 2); Ogre::String slot = lua_tostring(L, 3); flecs::entity parent_e = idmap.get_entity(parent); flecs::entity object_e = idmap.get_entity(object); PhysicsModule::controlPhysics(object_e, false); object_e.set({ parent_e, slot }); return 0; }); lua_setglobal(L, "ecs_set_slot"); lua_pushcfunction(L, [](lua_State *L) -> int { flecs::entity e = ECS::get().lookup("player"); int result = idmap.add_entity(e); lua_pushinteger(L, result); return result; }); lua_setglobal(L, "ecs_get_player_entity"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TNUMBER); // entity id int id = lua_tointeger(L, 1); flecs::entity e = idmap.get_entity(id); LuaEcsEntity *edata = static_cast( lua_newuserdata(L, sizeof(LuaEcsEntity))); new (edata) LuaEcsEntity(); edata->e = e; edata->id = e; luaL_getmetatable(L, "FlecsEntityMetaTable"); lua_setmetatable(L, -2); return 1; }); lua_setglobal(L, "ecs_get_entity"); luaL_newmetatable(L, "FlecsEntityMetaTable"); lua_pushstring(L, "__index"); lua_pushcfunction(L, [](lua_State *L) -> int { luaL_checktype(L, 1, LUA_TUSERDATA); //metatable luaL_checktype(L, 2, LUA_TSTRING); //function Ogre::String component = lua_tostring(L, 2); if (component == "components") { lua_pushvalue(L, 1); lua_pushcclosure( L, [](lua_State *L) -> int { luaL_checktype(L, lua_upvalueindex(1), LUA_TUSERDATA); LuaEcsEntity *ent = static_cast< LuaEcsEntity *>(lua_touserdata( L, lua_upvalueindex(1))); std::cout << ent->id << " called!!!\n"; ent->e.each([&](flecs::id id) { flecs::entity cmp = ECS::get().entity(id); if (cmp.is_alive()) { const char *name = cmp.name(); if (name) std::cout << "component: " << name << std::endl; } }); return 0; }, 1); } else if (component == "is_trigger") { lua_pushvalue(L, 1); lua_pushcclosure( L, [](lua_State *L) -> int { luaL_checktype(L, lua_upvalueindex(1), LUA_TUSERDATA); LuaEcsEntity *ent = static_cast< LuaEcsEntity *>(lua_touserdata( L, lua_upvalueindex(1))); lua_pushboolean( L, ent->e.has()); return 1; }, 1); } else if (component == "is_character") { lua_pushvalue(L, 1); lua_pushcclosure( L, [](lua_State *L) -> int { luaL_checktype(L, lua_upvalueindex(1), LUA_TUSERDATA); LuaEcsEntity *ent = static_cast< LuaEcsEntity *>(lua_touserdata( L, lua_upvalueindex(1))); lua_pushboolean( L, ent->e.has()); return 1; }, 1); } else if (component == "is_boat") { lua_pushvalue(L, 1); lua_pushcclosure( L, [](lua_State *L) -> int { luaL_checktype(L, lua_upvalueindex(1), LUA_TUSERDATA); LuaEcsEntity *ent = static_cast< LuaEcsEntity *>(lua_touserdata( L, lua_upvalueindex(1))); lua_pushboolean(L, ent->e.has()); return 1; }, 1); } else if (component == "is_player") { lua_pushvalue(L, 1); lua_pushcclosure( L, [](lua_State *L) -> int { luaL_checktype(L, lua_upvalueindex(1), LUA_TUSERDATA); LuaEcsEntity *ent = static_cast< LuaEcsEntity *>(lua_touserdata( L, lua_upvalueindex(1))); lua_pushboolean(L, ent->e.has()); return 1; }, 1); } else lua_pushnil(L); return 1; }); lua_settable(L, -3); } LuaData::~LuaData() { lua_close(L); } void LuaData::lateSetup() { #if 0 Ogre::DataStreamList streams = Ogre::ResourceGroupManager::getSingleton().openResources( "*.lua", "LuaScripts"); while (!streams.empty()) { Ogre::DataStreamPtr s = streams.front(); std::cout << "stream: " << s->getAsString() << "\n"; streams.pop_front(); if (luaL_dostring(L, s->getAsString().c_str()) != LUA_OK) { std::cout << "error: " << lua_tostring(L, -1) << "\n"; OgreAssert(false, "Script failure"); } } #endif Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource( "data.lua", "LuaScripts"); std::cout << "stream: " << stream->getAsString() << "\n"; if (luaL_dostring(L, stream->getAsString().c_str()) != LUA_OK) { std::cout << "error: " << lua_tostring(L, -1) << "\n"; OgreAssert(false, "Script failure"); } const char *lua_code = "\n\ function stuff()\n\ return 4\n\ end\n\ x = stuff()\n\ "; luaL_dostring(L, lua_code); lua_getglobal(L, "x"); int x = lua_tonumber(L, 1); std::cout << "lua: " << x << "\n"; } LuaModule::LuaModule(flecs::world &ecs) { ecs.module(); ecs.import (); ecs.component(); ecs.component() .on_add([](LuaBase &lua) { lua.mLua = new LuaData; lua.setup_called = false; lua.startup_called = false; }) .add(flecs::Singleton); ecs.component().add(flecs::Singleton); if (!ecs.has()) ecs.add(); if (!ecs.has()) ecs.set({}); ecs.system("LuaUpdate") .kind(flecs::OnUpdate) .each([](const EngineData &eng, LuaBase &lua) { if (!lua.setup_called) { lua.mLua->lateSetup(); lua.mLua->call_handler("setup"); lua.setup_called = true; } if (!lua.startup_called) { if (eng.startupDelay <= 0.0f) { lua.mLua->call_handler("startup"); lua.startup_called = true; } } }); ecs.system( "CreateChildTrigger") .kind(flecs::OnUpdate) .without() .write() .each([](flecs::entity e, const EngineData &env, const LuaChildEventTrigger &lct) { Ogre::SceneNode *parentNode = nullptr; flecs::entity parent_e = lct.parent_e; if (parent_e.has()) { parentNode = parent_e.get().mBodyNode; OgreAssert( parent_e.get().mBodyNode, "bad node"); } else if (parent_e.has()) { parentNode = parent_e.get().mNode; OgreAssert(parent_e.get().mNode, "bad node"); } else return; EventTrigger &trigger = e.ensure(); OgreAssert(parentNode, "bad parent"); trigger.position = lct.position; trigger.halfheight = lct.halfheight; trigger.radius = lct.radius; trigger.event = lct.event; trigger.parent = parentNode; e.modified(); }); ecs.system("HandleLuaEvents") .kind(flecs::OnUpdate) .each([](LuaBase &base, LuaEvent &evt) { while (!evt.events.empty()) { LuaEvent::Event &ev = evt.events.front(); base.mLua->call_handler(ev.event, ev.e1, ev.e2); evt.events.pop_front(); } }); } }