| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
- /*
- * Copyright (C) 2022 The V-Gears Team
- *
- * This file is part of V-Gears
- *
- * V-Gears is free software: you can redistribute it and/or modify it under
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, version 3.0 (GPLv3) of the License.
- *
- * V-Gears is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include "core/ConfigVar.h"
- #include "core/DebugDraw.h"
- #include "core/Logger.h"
- #include "core/ScriptManager.h"
- #include "core/ScriptManagerBinds.h"
- #include "core/ScriptManagerCommands.h"
- #include "core/Timer.h"
- #include "core/Utilites.h"
- #include "core/XmlScriptsFile.h"
- #include "LuaIncludes.h"
- ConfigVar cv_debug_script(
- "debug_script", "Debug script flags. 0x01 - System, 0x02 - Entity, 0x04 - Ui.", "0"
- );
- /**
- * Script manager singleton.
- */
- template<>ScriptManager *Ogre::Singleton<ScriptManager>::msSingleton = nullptr;
- Ogre::String script_entity_type[] = {"SYSTEM", "ENTITY", "UI", "BATTLE"};
- /**
- * Compares the priority of two scripts.
- *
- * @param[in] a The first script to compare.
- * @param[in] b The second script to compare.
- * @return True if the script a has a lower priority number than b, false if a has a higher or
- * equal priority than b.
- */
- bool priority_queue_compare(QueueScript a, QueueScript b){return a.priority < b.priority;}
- ScriptManager::ScriptManager():
- system_table_name_("System"), entity_table_name_("EntityContainer"), ui_table_name_("UiContainer")
- {
- lua_state_ = lua_open();
- sol::register_main_thread(lua_state_);
- luaopen_base(lua_state_);
- luaopen_string(lua_state_);
- luaopen_table(lua_state_);
- luaopen_math(lua_state_);
- luaopen_io(lua_state_);
- InitBinds();
- InitCmd();
- // TODO: Use the one in data/ ?
- RunFile("system/system.lua");
- XmlScriptsFile scripts("./data/scripts/_scripts.xml");
- scripts.LoadScripts();
- }
- ScriptManager::~ScriptManager(){lua_close(lua_state_);}
- void ScriptManager::Input(const VGears::Event& event){
- if (
- event.event != ""
- && (event.type == VGears::ET_KEY_PRESS || event.type == VGears::ET_KEY_REPEAT_WAIT)
- ){
- Ogre::String argument2 = "";
- if (event.type == VGears::ET_KEY_PRESS) argument2 = "Press";
- else if (event.type == VGears::ET_KEY_REPEAT_WAIT) argument2 = "Repeat";
- const Ogre::String source_key = KeyToString(
- static_cast<OIS::KeyCode>(event.param1)
- );
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- ScriptRequest(
- &script_entity_[i], "on_button", 100,
- event.event, argument2, false, false, source_key, true
- );
- }
- return;
- }
- if (
- (event.type == VGears::ET_KEY_PRESS || event.type == VGears::ET_KEY_REPEAT_WAIT)
- && (
- // Only the keys that scripts read by themselves reach them as raw keys: the letters and the
- // space bar, to type in the name menu and for the debug keys of the battle. Everything else
- // goes through the game events of config.cfg, so it can be remapped.
- // TODO: Do this the other way: block keys NOT TO pass to scripts.
- event.param1 == OIS::KC_SPACE
- || event.param1 == OIS::KC_A || event.param1 == OIS::KC_B || event.param1 == OIS::KC_C
- || event.param1 == OIS::KC_D || event.param1 == OIS::KC_E || event.param1 == OIS::KC_F
- || event.param1 == OIS::KC_G || event.param1 == OIS::KC_H || event.param1 == OIS::KC_I
- || event.param1 == OIS::KC_J || event.param1 == OIS::KC_K || event.param1 == OIS::KC_L
- || event.param1 == OIS::KC_M || event.param1 == OIS::KC_N || event.param1 == OIS::KC_O
- || event.param1 == OIS::KC_P || event.param1 == OIS::KC_Q || event.param1 == OIS::KC_R
- || event.param1 == OIS::KC_S || event.param1 == OIS::KC_T || event.param1 == OIS::KC_U
- || event.param1 == OIS::KC_V || event.param1 == OIS::KC_W || event.param1 == OIS::KC_X
- || event.param1 == OIS::KC_Y || event.param1 == OIS::KC_Z || event.param1 == OIS::KC_X
- )
- ){
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- Ogre::String argument2 = "";
- if (event.type == VGears::ET_KEY_PRESS) argument2 = "Press";
- else if (event.type == VGears::ET_KEY_REPEAT_WAIT) argument2 = "Repeat";
- ScriptRequest(
- &script_entity_[i], "on_button", 100,
- KeyToString((OIS::KeyCode) ((int) event.param1)), argument2, false, false
- );
- }
- }
- }
- void ScriptManager::Update(const ScriptManager::Type type){
- // Resort all queue. This will give correct info for debug draw.
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- if (script_entity_[i].type == type){
- if (script_entity_[i].queue.size() > 0){
- if (script_entity_[i].resort == true){
- std::stable_sort(
- script_entity_[i].queue.begin(),
- script_entity_[i].queue.end(), priority_queue_compare
- );
- script_entity_[i].resort = false;
- }
- }
- }
- }
- // Draw debug before update. This way it will be possible to see
- // scripts that run once
- int debug = cv_debug_script.GetI();
- if (debug != 0){
- DEBUG_DRAW.SetTextAlignment(DEBUG_DRAW.LEFT);
- DEBUG_DRAW.SetScreenSpace(true);
- int y = 34;
- for (unsigned int i = 0; i < 3; ++ i){
- if ((debug & (1 << i)) != 0){
- DEBUG_DRAW.SetColour(Ogre::ColourValue(0.8f, 0.8f, 0.0f, 1.0f));
- DEBUG_DRAW.Text(
- 10.0f, static_cast<float>(y), "Script \"" + script_entity_type[i] + "\" entity:"
- );
- y += 16;
- for (unsigned int j = 0; j < script_entity_.size(); ++ j){
- if (script_entity_[j].type == i){
- Ogre::String text = script_entity_[j].name;
- unsigned int queue_size = script_entity_[j].queue.size();
- if (queue_size > 0){
- text += ": ";
- DEBUG_DRAW.SetColour(Ogre::ColourValue(0.8f, 0.8f, 0.0f, 1.0f));
- }
- else DEBUG_DRAW.SetColour(Ogre::ColourValue(0.5, 0.5, 0.5, 1));
- for (unsigned int k = 0; k < queue_size; ++ k){
- if (k > 0) text += ", ";
- text +=
- "("
- + Ogre::StringConverter::toString(script_entity_[j].queue[k].priority)
- + ")" + script_entity_[j].queue[k].function;
- if (script_entity_[j].queue[k].wait == true){
- if (script_entity_[j].queue[k].seconds_to_wait != 0){
- text +=
- ":wait("+ Ogre::StringConverter::toString(
- script_entity_[j].queue[k].seconds_to_wait
- ) + ")";
- }
- }
- }
- DEBUG_DRAW.Text(20.0f, static_cast<float>(y), text);
- y += 16;
- }
- }
- }
- }
- }
- // Before updating entities, call on_update on the system timer.
- RunString("Timer.update()");
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- if (script_entity_[i].type == type){
- if (script_entity_[i].queue.size() > 0){
- current_script_id_.entity = script_entity_[i].name;
- current_script_id_.function = script_entity_[i].queue[0].function;
- if (script_entity_[i].queue[0].wait == false){
- if (script_entity_[i].queue[0].yield == false){
- LOG_TRIVIAL(
- "[SCRIPT] Start script \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity + "\"."
- );
- for (const ScriptId& waiting : script_entity_[i].queue[0].paused_scripts_start)
- ContinueScriptExecution(waiting);
- script_entity_[i].queue[0].paused_scripts_start.clear();
- sol::object table = GetTableByEntityName(
- type, current_script_id_.entity,
- script_entity_[i].queue[0].state
- );
- sol::object function;
- if (table.get_type() == sol::type::table)
- function = table.as<sol::table>()[current_script_id_.function];
- if (
- table.get_type() == sol::type::table
- && function.get_type() == sol::type::function
- ){
- int ret = 0;
- lua_State* thread = script_entity_[i].queue[0].state;
- sol::coroutine coroutine(thread, sol::function(function));
- auto result = coroutine(
- table, script_entity_[i].queue[0].argument1,
- script_entity_[i].queue[0].argument2,
- script_entity_[i].queue[0].argument3
- );
- if (result.valid()){
- // The coroutine yields with the bound function
- // return value on top of the thread stack; a
- // completed script leaves its return value there.
- if (lua_gettop(thread) > 0 && lua_isnumber(thread, -1))
- ret = static_cast<int>(lua_tointeger(thread, -1));
- lua_settop(thread, 0);
- }
- else{
- sol::error error = result;
- std::string msg = "LUA error in entity " + script_entity_[i].name
- + " (" + current_script_id_.entity + ") " + " in function "
- + script_entity_[i].queue[0].function + " ("
- + current_script_id_.function + ")";
- if (lua_tostring(thread, -1) != nullptr){
- msg = msg + ". Details: " + std::string(
- lua_tostring(thread, -1)
- );
- }
- msg = msg + ". Exception: " + error.what();
- LOG_ERROR(msg);
- lua_settop(thread, 0);
- }
- if (ret == 0){
- LOG_TRIVIAL(
- "[SCRIPT] Script \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity + "\" finished."
- );
- if (script_entity_[i].queue[0].function != "on_update")
- RemoveEntityTopScript(script_entity_[i]);
- }
- else if (ret == 1){
- LOG_TRIVIAL(
- "[SCRIPT] Script \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity
- + "\" not paused and will be continued next cycle."
- );
- script_entity_[i].queue[0].yield = true;
- }
- else{
- LOG_TRIVIAL(
- "[SCRIPT] Script \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity
- + "\" not finished yet."
- );
- script_entity_[i].queue[0].yield = true;
- script_entity_[i].queue[0].wait = true;
- }
- }
- else{
- LOG_WARNING(
- "Script \"" + current_script_id_.function + "\" for entity \""
- + current_script_id_.entity + "\" doesn't exist."
- );
- RemoveEntityTopScript(script_entity_[i]);
- }
- }
- else{
- LOG_TRIVIAL(
- "[SCRIPT] Continue function \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity + "\"."
- );
- int ret = 0;
- lua_State* thread = script_entity_[i].queue[0].state;
- // sol.hpp bundles a compat53 shim: on LuaJIT this maps
- // to the native 2-argument lua_resume.
- int status = lua_resume(thread, nullptr, 0);
- if (status == LUA_YIELD || status == 0){
- if (lua_gettop(thread) > 0 && lua_isnumber(thread, -1))
- ret = static_cast<int>(lua_tointeger(thread, -1));
- lua_settop(thread, 0);
- }
- else{
- const char* error = lua_tostring(thread, -1);
- LOG_WARNING(
- Ogre::String(error != nullptr ? error : "unknown lua error")
- );
- lua_settop(thread, 0);
- }
- if (ret == 0){ // Finished.
- LOG_TRIVIAL(
- "[SCRIPT] Script \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity + "\" finished."
- );
- // Stop yield for on_update.
- script_entity_[i].queue[0].yield = false;
- if (script_entity_[i].queue[0].function != "on_update")
- RemoveEntityTopScript(script_entity_[i]);
- }
- else if (ret == 1){
- LOG_TRIVIAL(
- "[SCRIPT] Script \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity
- + "\" not paused and will be continued next cycle."
- );
- }
- else{
- LOG_TRIVIAL(
- "[SCRIPT] Script \"" + current_script_id_.function
- + "\" for entity \"" + current_script_id_.entity
- + "\" not finished yet."
- );
- script_entity_[i].queue[0].wait = true;
- }
- }
- }
- else if (script_entity_[i].queue[0].seconds_to_wait > 0){
- script_entity_[i].queue[0].seconds_to_wait
- -= Timer::getSingleton().GetGameTimeDelta();
- script_entity_[i].queue[0].seconds_to_wait
- = (script_entity_[i].queue[0].seconds_to_wait < 0)
- ? 0 : script_entity_[i].queue[0].seconds_to_wait;
- if (script_entity_[i].queue[0].seconds_to_wait == 0)
- script_entity_[i].queue[0].wait = false;
- }
- }
- }
- }
- }
- void ScriptManager::UpdateDebug(){}
- void ScriptManager::OnResize(){}
- void ScriptManager::ClearField(){}
- void ScriptManager::ClearBattle(){
- // Remove all battle script entities.
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- if (script_entity_[i].type == BATTLE){
- while(script_entity_[i].queue.size() > 0)
- ScriptManager::RemoveEntityTopScript(script_entity_[i]);
- script_entity_.erase(script_entity_.begin() + i);
- i --;
- }
- }
- }
- void ScriptManager::ClearWorld(){}
- void ScriptManager::RunString(const Ogre::String& lua){
- int pre_eval_index = lua_gettop(lua_state_);
- if (luaL_dostring(lua_state_, lua.c_str()) == 1)
- LOG_ERROR("ScriptManager::RunString error: " + Ogre::String(lua_tostring(lua_state_, -1)));
- else{
- int index = lua_gettop(lua_state_);
- if (index > 0 && index != pre_eval_index){
- auto str = lua_tostring(lua_state_, index);
- LOG_CONSOLE(
- str != nullptr ? str : "ScriptManager::RunString: (nullptr; try tostring(...)?)"
- );
- lua_pop(lua_state_, 1);
- }
- }
- }
- void ScriptManager::RunFile(const Ogre::String& file){
- if (luaL_dofile(lua_state_, ("./data/" + file).c_str()) == 1)
- LOG_ERROR(Ogre::String(lua_tostring(lua_state_, -1)));
- }
- void ScriptManager::AddEntity(
- const ScriptManager::Type type, const Ogre::String& entity_name, Entity* entity
- ){
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- if (script_entity_[i].type == type && script_entity_[i].name == entity_name){
- LOG_ERROR(
- "Script \"" + script_entity_type[type] + "\" entity \""
- + entity_name + "\" already exist in script manager."
- );
- return;
- }
- }
- sol::object table = GetTableByEntityName(type, entity_name, lua_state_);
- if (table.get_type() == sol::type::table){
- ScriptEntity script_entity;
- script_entity.name = entity_name;
- script_entity.type = type;
- // Initialize entity field for model entity.
- if (entity != nullptr) table.as<sol::table>()["entity"] = entity;
- // Check the "on_start" script
- sol::object on_start = table.as<sol::table>()["on_start"];
- if (on_start.get_type() == sol::type::function){
- QueueScript script;
- script.function = "on_start";
- script.priority = 1;
- script.state = lua_newthread(lua_state_);
- // The thread must not be garbage collected,
- // so it need to be stored.
- script.state_id = luaL_ref(lua_state_, LUA_REGISTRYINDEX);
- script.seconds_to_wait = 0;
- script.wait = false;
- script.yield = false;
- script_entity.queue.push_back(script);
- }
- // Check the "on_update" script.
- sol::object on_update = table.as<sol::table>()["on_update"];
- if (on_update.get_type() == sol::type::function){
- QueueScript script;
- script.function = "on_update";
- script.priority = 999;
- script.state = lua_newthread(lua_state_);
- // The thread must not be garbage collected,
- // so it need to be stored.
- script.state_id = luaL_ref(lua_state_, LUA_REGISTRYINDEX);
- script.seconds_to_wait = 0;
- script.wait = false;
- script.yield = false;
- script_entity.queue.push_back(script);
- }
- script_entity_.push_back(script_entity);
- }
- }
- void ScriptManager::RemoveEntity(const ScriptManager::Type type, const Ogre::String& entity_name){
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- if (script_entity_[i].type == type && script_entity_[i].name == entity_name){
- while(script_entity_[i].queue.size() > 0)
- ScriptManager::RemoveEntityTopScript(script_entity_[i]);
- script_entity_.erase(script_entity_.begin() + i);
- return;
- }
- }
- }
- void ScriptManager::RemoveEntityTopScript(ScriptEntity& entity){
- if (entity.queue.size() > 0){
- // Delete the thread.
- luaL_unref(lua_state_, LUA_REGISTRYINDEX, entity.queue[0].state_id);
- for (const ScriptId& waiting : entity.queue[0].paused_scripts_end)
- ContinueScriptExecution(waiting);
- entity.queue[0].paused_scripts_end.clear();
- entity.queue.erase(entity.queue.begin());
- }
- }
- sol::object ScriptManager::GetTableByEntityName(
- const ScriptManager::Type type, const Ogre::String& name, lua_State* state
- ) const{
- // Get the real table by name
- Ogre::StringVector table_path = StringTokenise(name, ".");
- sol::state_view lua(state);
- sol::object table = lua.globals();
- switch(type){
- case ScriptManager::SYSTEM:
- table = table.as<sol::table>()[system_table_name_]; break;
- case ScriptManager::ENTITY:
- table = table.as<sol::table>()[entity_table_name_]; break;
- case ScriptManager::UI:
- table = table.as<sol::table>()[ui_table_name_]; break;
- case ScriptManager::BATTLE:
- table = table.as<sol::table>()[battle_table_name_]; break;
- }
- if (table.get_type() != sol::type::table) return sol::make_object(state, sol::nil);
- for (unsigned int i = 0; i < table_path.size(); ++ i){
- table = table.as<sol::table>()[table_path[i]];
- if (table.get_type() != sol::type::table) return sol::make_object(state, sol::nil);
- }
- return table;
- }
- QueueScript* ScriptManager::GetScriptByScriptId(const ScriptId& script) const{
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- if (script.entity == script_entity_[i].name){
- for (unsigned int j = 0; j < script_entity_[i].queue.size(); ++ j){
- if (script.function == script_entity_[i].queue[j].function)
- return (QueueScript*) &(script_entity_[i].queue[j]);
- }
- return nullptr;
- }
- }
- return nullptr;
- }
- ScriptEntity* ScriptManager::GetScriptEntityByName(
- const Type type, const Ogre::String& entity_name
- ) const{
- for (unsigned int i = 0; i < script_entity_.size(); ++ i){
- if (script_entity_[i].type == type && script_entity_[i].name == entity_name)
- return (ScriptEntity*) &(script_entity_[i]);
- }
- return nullptr;
- }
- const ScriptId ScriptManager::GetCurrentScriptId() const{return current_script_id_;}
- void ScriptManager::ContinueScriptExecution(const ScriptId& script){
- QueueScript* script_pointer = GetScriptByScriptId(script);
- if (script_pointer == nullptr){
- LOG_ERROR(
- "There is no script \"" + script.function + "\" for entity \""
- + script.entity + "\". Can't continue script execution."
- );
- return;
- }
- script_pointer->wait = false;
- }
- int ScriptManager::ScriptWait(const float seconds){
- LOG_TRIVIAL(
- "script:wait: We set script wait for "
- + Ogre::StringConverter::toString(seconds) + " seconds."
- );
- QueueScript* script = GetScriptByScriptId(current_script_id_);
- if (script == nullptr){
- LOG_ERROR("script:wait: Currently no any script running.");
- return 1;
- }
- if (seconds == 0) return 1;
- script->seconds_to_wait = seconds;
- return -1;
- }
- void ScriptManager::ScriptRequest(
- const Type type, const char* entity, const char* function, const int priority
- ){
- LOG_TRIVIAL(
- "[SCRIPT] script:request: Request function \"" + Ogre::String(function) + "\" for entity \""
- + Ogre::String(entity) + "\" with priority " + Ogre::StringConverter::toString(priority) + "."
- );
- ScriptEntity* script_entity = GetScriptEntityByName(type, Ogre::String(entity));
- if (script_entity == nullptr){
- LOG_WARNING(
- "[SCRIPT] script:request: Entity \"" + Ogre::String(entity) + "\" doesn't exist."
- );
- return;
- }
- bool added = ScriptRequest(script_entity, function, priority, "", "", false, false);
- if (added == false){
- LOG_WARNING(
- "Script '" + Ogre::String(function) + "' for entity '"
- + Ogre::String(entity) + "' doesn't exist."
- );
- }
- }
- int ScriptManager::ScriptRequestStartSync(
- const Type type, const char* entity, const char* function, const int priority
- ){
- LOG_TRIVIAL(
- "[SCRIPT] script:request_start_sync: Request function \""
- + Ogre::String(function) + "\" for entity \"" + Ogre::String(entity)
- + "\" with priority " + Ogre::StringConverter::toString(priority) + "."
- );
- ScriptEntity* script_entity = GetScriptEntityByName(type, Ogre::String(entity));
- if (script_entity == nullptr){
- LOG_ERROR(
- "[SCRIPT] script:request_start_sync: Entity \"" + Ogre::String(entity)
- + "\" doesn't exist.");
- return 1;
- }
- // A script that already started can't be waited for to start: nothing would resume the caller.
- for (const QueueScript& queued : script_entity->queue){
- if (queued.function == function && queued.yield){
- LOG_TRIVIAL(
- "[SCRIPT] script:request_start_sync: Function \"" + Ogre::String(function)
- + "\" for entity \"" + Ogre::String(entity) + "\" already started."
- );
- return 1;
- }
- }
- bool added = ScriptRequest(script_entity, function, priority, "", "", true, false);
- if (added == false){
- LOG_WARNING(
- "Script '" + Ogre::String(function) + "' for entity '"
- + Ogre::String(entity) + "' doesn't exist."
- );
- return 1;
- }
- return -1;
- }
- int ScriptManager::ScriptRequestEndSync(
- const Type type, const char* entity, const char* function, const int priority
- ){
- LOG_TRIVIAL(
- "[SCRIPT] script:request_end_sync: Request function \""
- + Ogre::String(function) + "\" for entity \"" + Ogre::String(entity)
- + "\" with priority " + Ogre::StringConverter::toString(priority) + "."
- );
- ScriptEntity* script_entity = GetScriptEntityByName(type, Ogre::String(entity));
- if (script_entity == nullptr){
- LOG_ERROR(
- "[SCRIPT] script:request_end_sync: Entity \"" + Ogre::String(entity)
- + "\" doesn't exist."
- );
- return 1;
- }
- bool added = ScriptRequest(script_entity, function, priority, "", "", false, true);
- if (added == false){
- LOG_WARNING(
- "Script '" + Ogre::String(function) + "' for entity '"
- + Ogre::String(entity) + "' doesn't exist."
- );
- return 1;
- }
- return -1;
- }
- bool ScriptManager::ScriptRequest(
- ScriptEntity* script_entity, const Ogre::String& function, const int priority,
- const Ogre::String& argument1, const Ogre::String& argument2, bool start_sync,
- bool end_sync, const Ogre::String& argument3, bool allow_duplicate
- ){
- if (script_entity == nullptr) return false;
- sol::object table
- = GetTableByEntityName(script_entity->type, script_entity->name, lua_state_);
- sol::object table_function;
- if (table.get_type() == sol::type::table)
- table_function = table.as<sol::table>()[function];
- if (table_function.get_type() == sol::type::function){
- QueueScript script;
- script.function = function;
- script.argument1 = argument1;
- script.argument2 = argument2;
- script.argument3 = argument3;
- script.priority = priority;
- script.state = lua_newthread(lua_state_);
- // The thread must not be garbage collected,
- // so it need to be stored.
- script.state_id = luaL_ref(lua_state_, LUA_REGISTRYINDEX);
- script.seconds_to_wait = 0;
- script.wait = false;
- script.yield = false;
- if (start_sync == true) script.paused_scripts_start.push_back(GetCurrentScriptId());
- if (end_sync == true) script.paused_scripts_end.push_back(GetCurrentScriptId());
- // If the script is already queued or running, don't queue it again. Whoever waits for the
- // request must wait for the existing script, because nothing else would resume it.
- if (allow_duplicate == false){
- for (int i = 0; i < script_entity->queue.size(); i ++){
- if (script_entity->queue[i].function == function){
- script_entity->resort = true;
- QueueScript& existing = script_entity->queue[i];
- for (const ScriptId& waiting : script.paused_scripts_end)
- existing.paused_scripts_end.push_back(waiting);
- // A script that already started isn't waited for. See ScriptRequestStartSync.
- if (!existing.yield){
- for (const ScriptId& waiting : script.paused_scripts_start)
- existing.paused_scripts_start.push_back(waiting);
- }
- luaL_unref(lua_state_, LUA_REGISTRYINDEX, script.state_id);
- return true;
- }
- }
- }
- script_entity->queue.push_back(script);
- script_entity->resort = true;
- return true;
- }
- return false;
- }
- void ScriptManager::AddValueToStack(const float value){
- QueueScript* script = GetScriptByScriptId(current_script_id_);
- if (script != nullptr) lua_pushnumber(script->state, value);
- }
- void ScriptManager::UpdateField(){}
- void ScriptManager::UpdateBattle(){}
- void ScriptManager::UpdateWorld(){}
|