| 1 | |
|---|
| 2 | #include "scriptable_controller.h" |
|---|
| 3 | #include "luatb.h" |
|---|
| 4 | |
|---|
| 5 | namespace orxonox |
|---|
| 6 | { |
|---|
| 7 | |
|---|
| 8 | // Used https://csl.name/post/lua-and-cpp/ as a reference |
|---|
| 9 | int ScriptableController::runScript(const std::string &file_path) |
|---|
| 10 | { |
|---|
| 11 | int ret; |
|---|
| 12 | |
|---|
| 13 | // Create a lua object |
|---|
| 14 | lua_State *lua = luaL_newstate(); |
|---|
| 15 | if(lua == nullptr) |
|---|
| 16 | { |
|---|
| 17 | orxout(internal_warning) << "ScriptableController: Falied to load script " << file_path << std::endl; |
|---|
| 18 | return LUA_ERRMEM; |
|---|
| 19 | } |
|---|
| 20 | |
|---|
| 21 | // Make standard libraries available in the Lua object |
|---|
| 22 | luaL_openlibs(lua); |
|---|
| 23 | |
|---|
| 24 | // Register the API |
|---|
| 25 | ScriptableControllerAPI *api = new ScriptableControllerAPI(lua, this); |
|---|
| 26 | |
|---|
| 27 | // Load the program; this supports both source code and bytecode files. |
|---|
| 28 | if((ret = luaL_loadfile(lua, file_path.c_str())) != 0) |
|---|
| 29 | { |
|---|
| 30 | this->printLuaError(lua); |
|---|
| 31 | delete api; |
|---|
| 32 | return ret; |
|---|
| 33 | } |
|---|
| 34 | |
|---|
| 35 | // Execute the script |
|---|
| 36 | if((ret = lua_pcall(lua, 0, LUA_MULTRET, 0)) != 0) |
|---|
| 37 | { |
|---|
| 38 | this->printLuaError(lua); |
|---|
| 39 | delete api; |
|---|
| 40 | return ret; |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | // Remeber the api |
|---|
| 44 | this->apis_.push_back(std::unique_ptr<ScriptableControllerAPI>(api)); |
|---|
| 45 | |
|---|
| 46 | // Only the caller knows, when the end-of-life of the script is reached, |
|---|
| 47 | // so we give him control over when to destroy it. |
|---|
| 48 | return 0; |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | void ScriptableController::registerWorldEntity(int id, WorldEntity *obj) |
|---|
| 52 | { |
|---|
| 53 | this->worldEntities_[id] = obj; |
|---|
| 54 | } |
|---|
| 55 | |
|---|
| 56 | void ScriptableController::registerControllableEntity(int id, ControllableEntity *obj) |
|---|
| 57 | { |
|---|
| 58 | this->worldEntities_[id] = obj; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | WorldEntity *ScriptableController::getWorldEntityByID(int id) const |
|---|
| 62 | { |
|---|
| 63 | auto obj = this->worldEntities_.find(id); |
|---|
| 64 | return obj != this->worldEntities_.end() ? obj->second : nullptr; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | ControllableEntity *ScriptableController::getControllableEntityByID(int id) const |
|---|
| 68 | { |
|---|
| 69 | auto obj = this->controllabelEntities_.find(id); |
|---|
| 70 | return obj != this->controllabelEntities_.end() ? obj->second : nullptr; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | void ScriptableController::printLuaError(lua_State *lua) |
|---|
| 74 | { |
|---|
| 75 | // The error message is on top of the stack. |
|---|
| 76 | // Fetch it, print it and then pop it off the stack. |
|---|
| 77 | // Yes, this is 'const char*' and not 'std::string' because that's what lua gives us. |
|---|
| 78 | const char* message = lua_tostring(lua, -1); |
|---|
| 79 | std::cout << message << std::endl; |
|---|
| 80 | lua_pop(lua, 1); |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | } |
|---|