summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-02-14 23:12:07 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-02-14 23:12:07 +0100
commit0b3e29dea9863c4b5ca0c77958bbcb32a05867ca (patch)
treef96454b1c29d73ee5c083b5b2fdb988bc574542d
parentf05141f1f78d9e0d917b2cc07f0fb09fd7f62801 (diff)
downloadrpgedit-0b3e29dea9863c4b5ca0c77958bbcb32a05867ca.tar
rpgedit-0b3e29dea9863c4b5ca0c77958bbcb32a05867ca.zip
Some work towards scriptable events
-rw-r--r--resources/script/interact.lua3
-rw-r--r--resources/script/test.lua20
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/control/MapContext.cpp14
-rw-r--r--src/control/MapContext.hpp4
-rw-r--r--src/control/RPGEdit.cpp3
-rw-r--r--src/control/RPGEdit.hpp2
-rw-r--r--src/control/ScriptContext.cpp90
-rw-r--r--src/control/ScriptContext.hpp63
-rw-r--r--src/model/Entity.hpp15
-rw-r--r--src/model/ScriptValue.hpp6
11 files changed, 160 insertions, 61 deletions
diff --git a/resources/script/interact.lua b/resources/script/interact.lua
new file mode 100644
index 0000000..98bb34f
--- /dev/null
+++ b/resources/script/interact.lua
@@ -0,0 +1,3 @@
+function interact(entity, time)
+ print('Interact! ' .. time)
+end
diff --git a/resources/script/test.lua b/resources/script/test.lua
index f78cf13..1dc1fc4 100644
--- a/resources/script/test.lua
+++ b/resources/script/test.lua
@@ -1,14 +1,20 @@
-function print_table(foo, bar)
+local function print_table(foo, bar)
for k, v in pairs(foo) do
print(bar .. k, v)
- if type(v) == 'table' and bar .. k ~= '_G' then
- print_table(v, bar .. k .. '.')
- end
+ --if type(v) == 'table' and bar .. k ~= '_G' then
+ -- print_table(v, bar .. k .. '.')
+ --end
end
end
-print_table(_G, '')
+--print(getmetatable(_G))
+--setmetatable(_G, {})
+--print_table(_G, '')
-print(getmetatable('').__index)
-print(string)
+print(bar)
+print(getmetatable(bar))
+
+--print(getmetatable('').bar)
+--getmetatable('').bar = 'bar'
+--print(getmetatable('').bar)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3e7dd61..46eb1a2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,6 +5,7 @@ add_executable(rpgedit
rpgedit.cpp
control/MapContext.cpp
control/RPGEdit.cpp
+ control/ScriptContext.cpp
model/Map.cpp
model/Scriptable.cpp
view/MapView.cpp
diff --git a/src/control/MapContext.cpp b/src/control/MapContext.cpp
index 6ba3b6b..f7ad2fe 100644
--- a/src/control/MapContext.cpp
+++ b/src/control/MapContext.cpp
@@ -31,10 +31,13 @@ namespace RPGEdit {
namespace Control {
-MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const std::shared_ptr<View::Window> &window, const Model::Map &map0)
- : eventBus(eventBus0), inputHandler(inputHandler0), map(map0) {
+MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, ScriptContext *scriptContext0, const std::shared_ptr<View::Window> &window, const Model::Map &map0)
+ : eventBus(eventBus0), inputHandler(inputHandler0), scriptContext(scriptContext0), map(map0) {
view = std::unique_ptr<View::MapView>(new View::MapView(window, map.getTileset()));
+ Model::Entity *square = map.addEntity("square", Model::Position<int>{10, 10});
+ square->setScriptInteract("interact", "interact");
+
playerEntity = map.addEntity("square", Model::Position<int>{8, 8});
view->updateEntities(map.getEntities());
@@ -80,7 +83,12 @@ void MapContext::interact(uint64_t time) {
if (!target)
return;
- target->interact(time);
+ const std::pair<std::string, std::string> &interactScript = target->getScriptInteract();
+ if (interactScript.first.empty())
+ return;
+
+ Model::ScriptNumber scriptTime(time);
+ scriptContext->run(interactScript.first, interactScript.second, nullptr, &scriptTime);
}
void MapContext::keyPressed(uint16_t key, uint64_t time) {
diff --git a/src/control/MapContext.hpp b/src/control/MapContext.hpp
index 18d4cfe..5e17a42 100644
--- a/src/control/MapContext.hpp
+++ b/src/control/MapContext.hpp
@@ -28,6 +28,7 @@
#include "EventBus.hpp"
#include "InputHandler.hpp"
+#include "ScriptContext.hpp"
#include "../model/Map.hpp"
#include "../view/MapView.hpp"
@@ -43,6 +44,7 @@ class MapContext {
private:
EventBus *const eventBus;
InputHandler *const inputHandler;
+ ScriptContext *const scriptContext;
std::unique_ptr<View::MapView> view;
@@ -59,7 +61,7 @@ private:
}
public:
- MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const std::shared_ptr<View::Window> &window, const Model::Map &map0);
+ MapContext(EventBus *eventBus0, InputHandler *inputHandler0, ScriptContext *scriptContext0, const std::shared_ptr<View::Window> &window, const Model::Map &map0);
void render(uint64_t time) {
view->render(&map, getViewPosition(time), time);
diff --git a/src/control/RPGEdit.cpp b/src/control/RPGEdit.cpp
index a1a699f..6068236 100644
--- a/src/control/RPGEdit.cpp
+++ b/src/control/RPGEdit.cpp
@@ -26,7 +26,6 @@
#include "RPGEdit.hpp"
#include "MapContext.hpp"
-#include "ScriptContext.hpp"
#include "../view/MapView.hpp"
@@ -106,7 +105,7 @@ void RPGEdit::run() {
window = std::make_shared<View::Window>();
- ctx = std::make_shared<MapContext>(&eventBus, &inputHandler, window, *map);
+ ctx = std::make_shared<MapContext>(&eventBus, &inputHandler, &scriptContext, window, *map);
eventThread = std::thread([this] { eventLoop(); });
diff --git a/src/control/RPGEdit.hpp b/src/control/RPGEdit.hpp
index 6011ecd..6c6c743 100644
--- a/src/control/RPGEdit.hpp
+++ b/src/control/RPGEdit.hpp
@@ -46,6 +46,8 @@ private:
EventBus eventBus;
InputHandler inputHandler;
+ ScriptContext scriptContext;
+
std::shared_ptr<View::Window> window;
std::shared_ptr<MapContext> ctx;
diff --git a/src/control/ScriptContext.cpp b/src/control/ScriptContext.cpp
new file mode 100644
index 0000000..cc10f74
--- /dev/null
+++ b/src/control/ScriptContext.cpp
@@ -0,0 +1,90 @@
+/*
+ Copyright (c) 2014, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "ScriptContext.hpp"
+
+
+namespace RPGEdit {
+
+namespace Control {
+
+void ScriptContext::setupEnv() {
+ const std::pair<const char *, lua_CFunction> libs[] = {
+ {"_G", luaopen_base},
+ {"bit32", luaopen_bit32},
+ {"math", luaopen_math},
+ {"string", luaopen_string},
+ {"table", luaopen_table},
+ };
+
+ for (auto &lib : libs) {
+ luaL_requiref(L, lib.first, lib.second, 1);
+ lua_pop(L, 1);
+ }
+
+ for (const char *f : {"dofile", "loadfile", "require"}) {
+ lua_pushnil(L);
+ lua_setglobal(L, f);
+ }
+}
+
+void ScriptContext::cleanupEnv() {
+ lua_pushglobaltable(L);
+
+ lua_pushnil(L);
+ lua_setmetatable(L, -2);
+
+ lua_pushnil(L);
+ while (lua_next(L, -2) != 0) {
+ lua_pop(L, 1);
+
+ lua_pushvalue(L, -1);
+ lua_pushnil(L);
+
+ lua_rawset(L, -4);
+ }
+
+ lua_pop(L, 1);
+}
+
+void ScriptContext::load(const std::string &script) {
+ if (loadedScripts.count(script))
+ return;
+
+ std::string filename = "../resources/script/" + script + ".lua";
+
+ lua_rawgetp(L, LUA_REGISTRYINDEX, this);
+ lua_pushstring(L, script.c_str());
+ luaL_loadfile(L, filename.c_str());
+ lua_rawset(L, -3);
+ lua_pop(L, 1);
+
+ loadedScripts.insert(script);
+}
+
+}
+
+}
diff --git a/src/control/ScriptContext.hpp b/src/control/ScriptContext.hpp
index 86c8c0f..f9f8445 100644
--- a/src/control/ScriptContext.hpp
+++ b/src/control/ScriptContext.hpp
@@ -36,6 +36,7 @@ extern "C" {
#include <memory>
#include <string>
+#include <unordered_set>
namespace RPGEdit {
@@ -46,43 +47,25 @@ class ScriptContext {
private:
lua_State *L;
- void setupEnv() {
- const std::pair<const char *, lua_CFunction> libs[] = {
- {"_G", luaopen_base},
- {"bit32", luaopen_bit32},
- {"math", luaopen_math},
- {"string", luaopen_string},
- {"table", luaopen_table},
- };
-
- for (auto &lib : libs) {
- luaL_requiref(L, lib.first, lib.second, 1);
- lua_pop(L, 1);
- }
-
- for (const char *f : {"dofile", "loadfile", "require"}) {
- lua_pushnil(L);
- lua_setglobal(L, f);
- }
- }
+ std::unordered_set<std::string> loadedScripts;
- void cleanupEnv() {
- lua_pushglobaltable(L);
+ void setupEnv();
+ void cleanupEnv();
- lua_pushnil(L);
- lua_setmetatable(L, -2);
+ void load(const std::string &script);
- lua_pushnil(L);
- while (lua_next(L, -2) != 0) {
- lua_pop(L, 1);
+ size_t pushArgs() {
+ return 0;
+ }
- lua_pushvalue(L, -1);
+ template<typename... Args>
+ size_t pushArgs(Model::ScriptValue *v, Args ...args) {
+ if (v)
+ v->push(L);
+ else
lua_pushnil(L);
- lua_rawset(L, -4);
- }
-
- lua_pop(L, 1);
+ return pushArgs(args...) + 1;
}
public:
@@ -107,25 +90,21 @@ public:
lua_setglobal(L, key.c_str());
}
- void load(const std::string &name) {
- std::string filename = "../resources/script/" + name + ".lua";
+ template<typename... Args>
+ void run(const std::string &script, const std::string &name, Args ...args) {
+ load(script);
- lua_rawgetp(L, LUA_REGISTRYINDEX, this);
- lua_pushstring(L, name.c_str());
- luaL_loadfile(L, filename.c_str());
- lua_rawset(L, -3);
- lua_pop(L, 1);
- }
-
- void run(const std::string &name) {
setupEnv();
lua_rawgetp(L, LUA_REGISTRYINDEX, this);
- lua_getfield(L, -1, name.c_str());
+ lua_getfield(L, -1, script.c_str());
lua_remove(L, -2);
lua_call(L, 0, 0);
+ lua_getglobal(L, name.c_str());
+ lua_call(L, pushArgs(args...), 0);
+
cleanupEnv();
}
};
diff --git a/src/model/Entity.hpp b/src/model/Entity.hpp
index fc1debb..b14e122 100644
--- a/src/model/Entity.hpp
+++ b/src/model/Entity.hpp
@@ -28,19 +28,23 @@
#include "Direction.hpp"
+#include "Scriptable.hpp"
#include <string>
+#include <utility>
namespace RPGEdit {
namespace Model {
-class Entity {
+class Entity : public Scriptable {
private:
std::string name;
+ std::pair<std::string, std::string> scriptInteract;
+
Direction direction;
public:
@@ -60,8 +64,13 @@ public:
direction = dir;
}
- void interact(uint64_t time) {
- std::fprintf(stderr, "Tried to interact with `%s' entity at %llu\n", name.c_str(), (unsigned long long)time);
+ const std::pair<std::string, std::string> & getScriptInteract() const {
+ return scriptInteract;
+ }
+
+ void setScriptInteract(const std::string &script, const std::string &name) {
+ scriptInteract.first = script;
+ scriptInteract.second = name;
}
};
diff --git a/src/model/ScriptValue.hpp b/src/model/ScriptValue.hpp
index a82ba8e..04c4e55 100644
--- a/src/model/ScriptValue.hpp
+++ b/src/model/ScriptValue.hpp
@@ -116,13 +116,13 @@ public:
class ScriptTable : public ScriptValue {
public:
- typedef std::unordered_map<std::string, std::shared_ptr<ScriptValue>> MapType;
+ typedef std::unordered_map<std::shared_ptr<ScriptValue>, std::shared_ptr<ScriptValue>> MapType;
private:
MapType value;
public:
- std::shared_ptr<ScriptValue> & operator[](const std::string &key) {
+ std::shared_ptr<ScriptValue> & operator[](const std::shared_ptr<ScriptValue> &key) {
return value[key];
}
@@ -130,7 +130,7 @@ public:
lua_createtable(L, 0, value.size());
for (const auto &entry : value) {
- lua_pushstring(L, entry.first.c_str());
+ entry.first->push(L);
entry.second->push(L);
lua_settable(L, -3);