Some work towards scriptable events
This commit is contained in:
parent
f05141f1f7
commit
0b3e29dea9
11 changed files with 160 additions and 61 deletions
3
resources/script/interact.lua
Normal file
3
resources/script/interact.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
function interact(entity, time)
|
||||
print('Interact! ' .. time)
|
||||
end
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(); });
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ private:
|
|||
EventBus eventBus;
|
||||
InputHandler inputHandler;
|
||||
|
||||
ScriptContext scriptContext;
|
||||
|
||||
std::shared_ptr<View::Window> window;
|
||||
|
||||
std::shared_ptr<MapContext> ctx;
|
||||
|
|
90
src/control/ScriptContext.cpp
Normal file
90
src/control/ScriptContext.cpp
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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},
|
||||
};
|
||||
std::unordered_set<std::string> loadedScripts;
|
||||
|
||||
for (auto &lib : libs) {
|
||||
luaL_requiref(L, lib.first, lib.second, 1);
|
||||
lua_pop(L, 1);
|
||||
void setupEnv();
|
||||
void cleanupEnv();
|
||||
|
||||
void load(const std::string &script);
|
||||
|
||||
size_t pushArgs() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const char *f : {"dofile", "loadfile", "require"}) {
|
||||
lua_pushnil(L);
|
||||
lua_setglobal(L, f);
|
||||
}
|
||||
}
|
||||
|
||||
void 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);
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Reference in a new issue