summaryrefslogtreecommitdiff
path: root/src/scripting
diff options
context:
space:
mode:
Diffstat (limited to 'src/scripting')
-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
7 files changed, 74 insertions, 45 deletions
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;
}