From 4559ca444daacfd02ebb05f1657148a2b4cf3d8b Mon Sep 17 00:00:00 2001 From: Erik Schilling Date: Wed, 20 Feb 2013 22:46:55 +0100 Subject: Introduced Script::Context This should allow to finally call functions to lua without having to care about working around situations where a lua call causes a c++ call which needs to call to lua again. Tested against the source of tales repository data. --- src/game-server/being.cpp | 6 ++--- src/game-server/character.cpp | 11 ++++----- src/game-server/item.cpp | 7 +++--- src/game-server/mapcomposite.cpp | 19 +++++++-------- src/game-server/monster.cpp | 9 +++----- src/game-server/npc.cpp | 6 ++--- src/game-server/quest.cpp | 3 +-- src/game-server/statuseffect.cpp | 3 +-- src/game-server/trigger.cpp | 3 +-- src/scripting/lua.cpp | 10 ++------ src/scripting/luascript.cpp | 25 ++++++++++++-------- src/scripting/luascript.h | 5 ++-- src/scripting/luautil.cpp | 2 +- src/scripting/script.cpp | 25 +++++++++++++------- src/scripting/script.h | 50 ++++++++++++++++++++++++++++------------ src/scripting/scriptmanager.cpp | 2 +- 16 files changed, 99 insertions(+), 87 deletions(-) diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 2c334b37..66545ff6 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -603,11 +603,10 @@ void Being::recalculateBaseAttribute(unsigned attr) return; Script *script = ScriptManager::currentState(); - script->setMap(getMap()); script->prepare(mRecalculateBaseAttributeCallback); script->push(this); script->push(attr); - script->execute(); + script->execute(getMap()); } void Being::updateDerivedAttributes(unsigned attr) @@ -632,11 +631,10 @@ void Being::updateDerivedAttributes(unsigned attr) return; Script *script = ScriptManager::currentState(); - script->setMap(getMap()); script->prepare(mRecalculateDerivedAttributesCallback); script->push(this); script->push(attr); - script->execute(); + script->execute(getMap()); } void Being::applyStatusEffect(int id, int timer) diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index cf5415df..b139f121 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -62,10 +62,9 @@ static bool executeCallback(Script::Ref function, Character *character) return false; Script *script = ScriptManager::currentState(); - script->setMap(character->getMap()); script->prepare(function); script->push(character); - script->execute(); + script->execute(character->getMap()); return true; } @@ -161,7 +160,7 @@ void Character::update() script->prepare(s.specialInfo->rechargedCallback); script->push(this); script->push(s.specialInfo->id); - script->execute(); + script->execute(getMap()); } } } @@ -258,12 +257,11 @@ void Character::useSpecialOnBeing(int id, Being *b) //tell script engine to cast the spell Script *script = ScriptManager::currentState(); - script->setMap(getMap()); script->prepare(special.specialInfo->useCallback); script->push(this); script->push(b); script->push(special.specialInfo->id); - script->execute(); + script->execute(getMap()); } void Character::useSpecialOnPoint(int id, int x, int y) @@ -278,13 +276,12 @@ void Character::useSpecialOnPoint(int id, int x, int y) //tell script engine to cast the spell Script *script = ScriptManager::currentState(); - script->setMap(getMap()); script->prepare(special.specialInfo->useCallback); script->push(this); script->push(x); script->push(y); script->push(special.specialInfo->id); - script->execute(); + script->execute(getMap()); } bool Character::giveSpecial(int id, int currentMana) diff --git a/src/game-server/item.cpp b/src/game-server/item.cpp index d568fb29..c6c9d11c 100644 --- a/src/game-server/item.cpp +++ b/src/game-server/item.cpp @@ -71,11 +71,11 @@ bool ItemEffectScript::apply(Being *itemUser) if (function.isValid()) { Script *script = ScriptManager::currentState(); - script->setMap(itemUser->getMap()); script->prepare(function); script->push(itemUser); script->push(mItemClass->getDatabaseID()); - script->execute(); // TODO return depending on script execution success. + script->execute(itemUser->getMap()); + // TODO return depending on script execution success. return true; } return false; @@ -90,11 +90,10 @@ void ItemEffectScript::dispell(Being *itemUser) if (function.isValid()) { Script *script = ScriptManager::currentState(); - script->setMap(itemUser->getMap()); script->prepare(function); script->push(itemUser); script->push(mItemClass->getDatabaseID()); - script->execute(); + script->execute(itemUser->getMap()); } } diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index 4c7dc66a..99d2734f 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -512,9 +512,8 @@ bool MapComposite::activate() else { Script *s = ScriptManager::currentState(); - s->setMap(this); s->prepare(mInitializeCallback); - s->execute(); + s->execute(this); } return true; @@ -628,10 +627,9 @@ void MapComposite::update() if (mUpdateCallback.isValid()) { Script *s = ScriptManager::currentState(); - s->setMap(this); s->prepare(mUpdateCallback); s->push(mID); - s->execute(); + s->execute(this); } // Move objects around and update zones. @@ -703,11 +701,10 @@ static void callVariableCallback(Script::Ref &function, const std::string &key, if (function.isValid()) { Script *s = ScriptManager::currentState(); - s->setMap(map); s->prepare(function); s->push(key); s->push(value); - s->execute(); + s->execute(map); } } @@ -854,11 +851,10 @@ void MapComposite::initializeContent() if (npcId && !scriptText.empty()) { Script *script = ScriptManager::currentState(); - script->setMap(this); script->loadNPC(object->getName(), npcId, ManaServ::getGender(gender), object->getX(), object->getY(), - scriptText.c_str()); + scriptText.c_str(), this); } else { @@ -871,16 +867,17 @@ void MapComposite::initializeContent() std::string scriptText = object->getProperty("TEXT"); Script *script = ScriptManager::currentState(); - script->setMap(this); + Script::Context context; + context.map = this; if (!scriptFilename.empty()) { - script->loadFile(scriptFilename); + script->loadFile(scriptFilename, context); } else if (!scriptText.empty()) { std::string name = "'" + object->getName() + "'' in " + mName; - script->load(scriptText.c_str(), name.c_str()); + script->load(scriptText.c_str(), name.c_str(), context); } else { diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index 47246005..3899c792 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -142,10 +142,9 @@ void Monster::update() if (mSpecy->getUpdateCallback().isValid()) { Script *script = ScriptManager::currentState(); - script->setMap(getMap()); script->prepare(mSpecy->getUpdateCallback()); script->push(this); - script->execute(); + script->execute(getMap()); } refreshTarget(); @@ -276,12 +275,11 @@ void Monster::processAttack(Attack &attack) if (scriptCallback.isValid() && hit > -1) { Script *script = ScriptManager::currentState(); - script->setMap(getMap()); script->prepare(scriptCallback); script->push(this); script->push(mTarget); script->push(hit); - script->execute(); + script->execute(getMap()); } } @@ -403,13 +401,12 @@ int Monster::damage(Actor *source, const Damage &damage) if (mSpecy->getDamageCallback().isValid()) { Script *script = ScriptManager::currentState(); - script->setMap(getMap()); script->prepare(mSpecy->getDamageCallback()); script->push(this); script->push(source); script->push(HPLoss); // TODO: add exact damage parameters as well - script->execute(); + script->execute(getMap()); } return HPLoss; diff --git a/src/game-server/npc.cpp b/src/game-server/npc.cpp index ce6ac32e..2eb73031 100644 --- a/src/game-server/npc.cpp +++ b/src/game-server/npc.cpp @@ -54,11 +54,9 @@ void NPC::update() return; Script *script = ScriptManager::currentState(); - script->setMap(getMap()); - script->prepare(mUpdateCallback); script->push(this); - script->execute(); + script->execute(getMap()); } void NPC::prompt(Character *ch, bool restart) @@ -71,7 +69,7 @@ void NPC::prompt(Character *ch, bool restart) if (restart) { Script::Thread *thread = script->newThread(); - thread->mMap = getMap(); + thread->getContext().map = getMap(); script->prepare(mTalkCallback); script->push(this); script->push(ch); diff --git a/src/game-server/quest.cpp b/src/game-server/quest.cpp index c28a4213..d6d7d92d 100644 --- a/src/game-server/quest.cpp +++ b/src/game-server/quest.cpp @@ -82,12 +82,11 @@ void QuestRefCallback::triggerCallback(Character *ch, return; Script *s = ScriptManager::currentState(); - s->setMap(ch->getMap()); s->prepare(mRef); s->push(ch); s->push(mQuestName); s->push(value); - s->execute(); + s->execute(ch->getMap()); } static void partialRemove(Entity *t) diff --git a/src/game-server/statuseffect.cpp b/src/game-server/statuseffect.cpp index c101bc02..b5b988f4 100644 --- a/src/game-server/statuseffect.cpp +++ b/src/game-server/statuseffect.cpp @@ -37,10 +37,9 @@ void StatusEffect::tick(Being *target, int count) if (mTickCallback.isValid()) { Script *s = ScriptManager::currentState(); - s->setMap(target->getMap()); s->prepare(mTickCallback); s->push(target); s->push(count); - s->execute(); + s->execute(target->getMap()); } } diff --git a/src/game-server/trigger.cpp b/src/game-server/trigger.cpp index 2c007260..10e50ecb 100644 --- a/src/game-server/trigger.cpp +++ b/src/game-server/trigger.cpp @@ -50,11 +50,10 @@ void ScriptAction::process(Actor *obj) LOG_DEBUG("Script trigger area activated: " << "(" << obj << ", " << mArg << ")"); - mScript->setMap(obj->getMap()); mScript->prepare(mCallback); mScript->push(obj); mScript->push(mArg); - mScript->execute(); + mScript->execute(obj->getMap()); } void TriggerArea::update() diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 4e2cd283..e305fcd7 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -1438,17 +1438,11 @@ static int chr_request_quest(lua_State *s) Script::Ref callback; script->assignCallback(callback); - // Backup the map since execute will reset it - MapComposite *map = script->getMap(); - script->prepare(callback); script->push(ch); script->push(name); script->push(value); - script->execute(); - - // Restore map - script->setMap(map); + script->execute(ch->getMap()); return 0; } @@ -2132,7 +2126,7 @@ static int get_map_id(lua_State *s) { Script *script = getScript(s); - if (MapComposite *mapComposite = script->getMap()) + if (MapComposite *mapComposite = script->getContext()->map) lua_pushinteger(s, mapComposite->getID()); else lua_pushnil(s); diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp index f4ea39ac..e9f4492d 100644 --- a/src/scripting/luascript.cpp +++ b/src/scripting/luascript.cpp @@ -118,10 +118,12 @@ void LuaScript::push(const std::list &itemList) ++nbArgs; } -int LuaScript::execute() +int LuaScript::execute(const Context &context) { assert(nbArgs >= 0); + const Context *previousContext = mContext; + mContext = &context; const int tmpNbArgs = nbArgs; nbArgs = -1; @@ -139,7 +141,7 @@ int LuaScript::execute() } res = lua_tointeger(mCurrentState, -1); lua_pop(mCurrentState, 1); - setMap(0); + mContext = previousContext; return res; } @@ -148,7 +150,9 @@ bool LuaScript::resume() assert(nbArgs >= 0); assert(mCurrentThread); - setMap(mCurrentThread->mMap); + const Context *previousContext = mContext; + mContext = &mCurrentThread->getContext(); + const int tmpNbArgs = nbArgs; nbArgs = -1; #if LUA_VERSION_NUM < 502 @@ -156,7 +160,6 @@ bool LuaScript::resume() #else int result = lua_resume(mCurrentState, NULL, tmpNbArgs); #endif - setMap(0); if (result == 0) // Thread is done { @@ -181,6 +184,7 @@ bool LuaScript::resume() } lua_settop(mCurrentState, 0); + mContext = previousContext; const bool done = result != LUA_YIELD; if (done) @@ -215,8 +219,11 @@ void LuaScript::unref(Ref &ref) } } -void LuaScript::load(const char *prog, const char *name) +void LuaScript::load(const char *prog, const char *name, + const Context &context) { + const Context *previousContext = mContext; + mContext = &context; int res = luaL_loadbuffer(mRootState, prog, std::strlen(prog), name); if (res) { @@ -238,19 +245,18 @@ void LuaScript::load(const char *prog, const char *name) << lua_tostring(mRootState, -1)); lua_pop(mRootState, 1); } - setMap(0); + mContext = previousContext; } void LuaScript::processDeathEvent(Being *entity) { if (mDeathNotificationCallback.isValid()) { - setMap(entity->getMap()); prepare(mDeathNotificationCallback); push(entity); //TODO: get and push a list of creatures who contributed to killing the // being. This might be very interesting for scripting quests. - execute(); + Script::execute(entity->getMap()); } } @@ -258,12 +264,11 @@ void LuaScript::processRemoveEvent(Entity *entity) { if (mRemoveNotificationCallback.isValid()) { - setMap(entity->getMap()); prepare(mRemoveNotificationCallback); push(entity); //TODO: get and push a list of creatures who contributed to killing the // being. This might be very interesting for scripting quests. - execute(); + Script::execute(entity->getMap()); } } diff --git a/src/scripting/luascript.h b/src/scripting/luascript.h index 9515bf0e..3bedbc28 100644 --- a/src/scripting/luascript.h +++ b/src/scripting/luascript.h @@ -44,7 +44,8 @@ class LuaScript : public Script ~LuaScript(); - void load(const char *prog, const char *name); + void load(const char *prog, const char *name, + const Context &context = Context()); Thread *newThread(); @@ -60,7 +61,7 @@ class LuaScript : public Script void push(const std::list &itemList); - int execute(); + int execute(const Context &context = Context()); bool resume(); diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp index f7b39e29..6210eda0 100644 --- a/src/scripting/luautil.cpp +++ b/src/scripting/luautil.cpp @@ -267,7 +267,7 @@ MapComposite *checkCurrentMap(lua_State *s, Script *script /* = 0 */) if (!script) script = getScript(s); - MapComposite *mapComposite = script->getMap(); + MapComposite *mapComposite = script->getContext()->map; if (!mapComposite) luaL_error(s, "no current map"); diff --git a/src/scripting/script.cpp b/src/scripting/script.cpp index 63ab7ff4..72943d43 100644 --- a/src/scripting/script.cpp +++ b/src/scripting/script.cpp @@ -40,7 +40,7 @@ Script::Ref Script::mUpdateCallback; Script::Script(): mCurrentThread(0), - mMap(0) + mContext(0) {} Script::~Script() @@ -95,14 +95,14 @@ static char *skipPotentialBom(char *text) return (strncmp(text, utf8Bom, bomLength) == 0) ? text + bomLength : text; } -bool Script::loadFile(const std::string &name) +bool Script::loadFile(const std::string &name, const Context &context) { int size; char *buffer = ResourceManager::loadFile(name, size); if (buffer) { mScriptFile = name; - load(skipPotentialBom(buffer), name.c_str()); + load(skipPotentialBom(buffer), name.c_str(), context); free(buffer); return true; } else { @@ -114,7 +114,8 @@ void Script::loadNPC(const std::string &name, int id, ManaServ::BeingGender gender, int x, int y, - const char *prog) + const char *prog, + MapComposite *map) { if (!mCreateNpcDelayedCallback.isValid()) { @@ -122,14 +123,23 @@ void Script::loadNPC(const std::string &name, "Could not enabled NPC"); return; } - load(prog, name.c_str()); + Context context; + context.map = map; + load(prog, name.c_str(), context); prepare(mCreateNpcDelayedCallback); push(name); push(id); push(gender); push(x); push(y); - execute(); + execute(context); +} + +int Script::execute(MapComposite *map) +{ + Context context; + context.map = map; + return execute(context); } @@ -153,8 +163,7 @@ static void fastRemoveOne(std::vector &vector, T value) Script::Thread::Thread(Script *script) : mScript(script), - mState(ThreadPending), - mMap(0) + mState(ThreadPending) { script->mThreads.push_back(this); } diff --git a/src/scripting/script.h b/src/scripting/script.h index 8dee23a9..574d1b9b 100644 --- a/src/scripting/script.h +++ b/src/scripting/script.h @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -40,6 +41,15 @@ class Entity; class Script : public sigc::trackable { public: + struct Context + { + MapComposite *map; + + Context() + : map(0) + {} + }; + /** * Defines a function that creates a Script instance. */ @@ -87,9 +97,12 @@ class Script : public sigc::trackable Thread(Script *script); virtual ~Thread(); + Context &getContext() + { return mContext; } + Script * const mScript; ThreadState mState; - MapComposite *mMap; + Context mContext; }; Script(); @@ -102,14 +115,18 @@ class Script : public sigc::trackable * * @param prog the program text to load * @param name the name of the text, used for error reporting + * @param context the context that is supposed to be used for loading */ - virtual void load(const char *prog, const char *name) = 0; + virtual void load(const char *prog, + const char *name, + const Context &context = Context()) = 0; /** * Loads a text file into script context and executes its global * statements. */ - virtual bool loadFile(const std::string &); + virtual bool loadFile(const std::string &, + const Context &context = Context()); /** * Loads a chunk of text and considers it as an NPC handler. This @@ -119,7 +136,8 @@ class Script : public sigc::trackable int id, ManaServ::BeingGender gender, int x, int y, - const char *); + const char *, + MapComposite *map); /** * Called every tick for the script to manage its data. @@ -174,9 +192,17 @@ class Script : public sigc::trackable /** * Executes the function being prepared. + * @param context the context that is supposed to be used for executing * @return the value returned by the script. */ - virtual int execute() = 0; + virtual int execute(const Context &context = Context()) = 0; + + /** + * Executes the function being prepared. + * @param the map which is set as context + * @return the value returned by the script. + */ + int execute(MapComposite *map); /** * Starts or resumes the current thread. Deletes the thread when it is @@ -207,16 +233,10 @@ class Script : public sigc::trackable { return mCurrentThread; } /** - * Sets associated map. - */ - void setMap(MapComposite *m) - { mMap = m; } - - /** - * Gets associated map. + * Returns the current context. */ - MapComposite *getMap() const - { return mMap; } + const Context *getContext() const + { return mContext; } virtual void processDeathEvent(Being *entity) = 0; @@ -231,9 +251,9 @@ class Script : public sigc::trackable protected: std::string mScriptFile; Thread *mCurrentThread; + const Context *mContext; private: - MapComposite *mMap; std::vector mThreads; static Ref mCreateNpcDelayedCallback; diff --git a/src/scripting/scriptmanager.cpp b/src/scripting/scriptmanager.cpp index c9d1ce85..39a1a6a5 100644 --- a/src/scripting/scriptmanager.cpp +++ b/src/scripting/scriptmanager.cpp @@ -60,7 +60,7 @@ bool ScriptManager::performCraft(Being *crafter, _currentState->prepare(_craftCallback); _currentState->push(crafter); _currentState->push(recipe); - _currentState->execute(); + _currentState->execute(crafter->getMap()); return true; } -- cgit v1.2.3-60-g2f50