summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2013-02-20 22:46:55 +0100
committerErik Schilling <ablu.erikschilling@googlemail.com>2013-02-21 07:29:13 +0100
commit4559ca444daacfd02ebb05f1657148a2b4cf3d8b (patch)
tree8410fe19f397e70d43a8542c6ba7339d61d9bc0e
parentad1d58b795681cad74642c0f4818b66a3f869794 (diff)
downloadmanaserv-4559ca444daacfd02ebb05f1657148a2b4cf3d8b.tar.gz
manaserv-4559ca444daacfd02ebb05f1657148a2b4cf3d8b.tar.bz2
manaserv-4559ca444daacfd02ebb05f1657148a2b4cf3d8b.tar.xz
manaserv-4559ca444daacfd02ebb05f1657148a2b4cf3d8b.zip
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.
-rw-r--r--src/game-server/being.cpp6
-rw-r--r--src/game-server/character.cpp11
-rw-r--r--src/game-server/item.cpp7
-rw-r--r--src/game-server/mapcomposite.cpp19
-rw-r--r--src/game-server/monster.cpp9
-rw-r--r--src/game-server/npc.cpp6
-rw-r--r--src/game-server/quest.cpp3
-rw-r--r--src/game-server/statuseffect.cpp3
-rw-r--r--src/game-server/trigger.cpp3
-rw-r--r--src/scripting/lua.cpp10
-rw-r--r--src/scripting/luascript.cpp25
-rw-r--r--src/scripting/luascript.h5
-rw-r--r--src/scripting/luautil.cpp2
-rw-r--r--src/scripting/script.cpp25
-rw-r--r--src/scripting/script.h50
-rw-r--r--src/scripting/scriptmanager.cpp2
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<InventoryItem> &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<InventoryItem> &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<T> &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 <list>
#include <string>
#include <vector>
+#include <stack>
#include <sigc++/trackable.h>
@@ -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<Thread*> 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;
}