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
|
for k, v in pairs(foo) do
|
||||||
print(bar .. k, v)
|
print(bar .. k, v)
|
||||||
|
|
||||||
if type(v) == 'table' and bar .. k ~= '_G' then
|
--if type(v) == 'table' and bar .. k ~= '_G' then
|
||||||
print_table(v, bar .. k .. '.')
|
-- print_table(v, bar .. k .. '.')
|
||||||
end
|
--end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print_table(_G, '')
|
--print(getmetatable(_G))
|
||||||
|
--setmetatable(_G, {})
|
||||||
|
--print_table(_G, '')
|
||||||
|
|
||||||
print(getmetatable('').__index)
|
print(bar)
|
||||||
print(string)
|
print(getmetatable(bar))
|
||||||
|
|
||||||
|
--print(getmetatable('').bar)
|
||||||
|
--getmetatable('').bar = 'bar'
|
||||||
|
--print(getmetatable('').bar)
|
||||||
|
|
|
@ -5,6 +5,7 @@ add_executable(rpgedit
|
||||||
rpgedit.cpp
|
rpgedit.cpp
|
||||||
control/MapContext.cpp
|
control/MapContext.cpp
|
||||||
control/RPGEdit.cpp
|
control/RPGEdit.cpp
|
||||||
|
control/ScriptContext.cpp
|
||||||
model/Map.cpp
|
model/Map.cpp
|
||||||
model/Scriptable.cpp
|
model/Scriptable.cpp
|
||||||
view/MapView.cpp
|
view/MapView.cpp
|
||||||
|
|
|
@ -31,10 +31,13 @@ namespace RPGEdit {
|
||||||
|
|
||||||
namespace Control {
|
namespace Control {
|
||||||
|
|
||||||
MapContext::MapContext(EventBus *eventBus0, InputHandler *inputHandler0, const std::shared_ptr<View::Window> &window, const Model::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), map(map0) {
|
: eventBus(eventBus0), inputHandler(inputHandler0), scriptContext(scriptContext0), map(map0) {
|
||||||
view = std::unique_ptr<View::MapView>(new View::MapView(window, map.getTileset()));
|
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});
|
playerEntity = map.addEntity("square", Model::Position<int>{8, 8});
|
||||||
|
|
||||||
view->updateEntities(map.getEntities());
|
view->updateEntities(map.getEntities());
|
||||||
|
@ -80,7 +83,12 @@ void MapContext::interact(uint64_t time) {
|
||||||
if (!target)
|
if (!target)
|
||||||
return;
|
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) {
|
void MapContext::keyPressed(uint16_t key, uint64_t time) {
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "EventBus.hpp"
|
#include "EventBus.hpp"
|
||||||
#include "InputHandler.hpp"
|
#include "InputHandler.hpp"
|
||||||
|
#include "ScriptContext.hpp"
|
||||||
#include "../model/Map.hpp"
|
#include "../model/Map.hpp"
|
||||||
#include "../view/MapView.hpp"
|
#include "../view/MapView.hpp"
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ class MapContext {
|
||||||
private:
|
private:
|
||||||
EventBus *const eventBus;
|
EventBus *const eventBus;
|
||||||
InputHandler *const inputHandler;
|
InputHandler *const inputHandler;
|
||||||
|
ScriptContext *const scriptContext;
|
||||||
|
|
||||||
std::unique_ptr<View::MapView> view;
|
std::unique_ptr<View::MapView> view;
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
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) {
|
void render(uint64_t time) {
|
||||||
view->render(&map, getViewPosition(time), time);
|
view->render(&map, getViewPosition(time), time);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
#include "RPGEdit.hpp"
|
#include "RPGEdit.hpp"
|
||||||
#include "MapContext.hpp"
|
#include "MapContext.hpp"
|
||||||
#include "ScriptContext.hpp"
|
|
||||||
#include "../view/MapView.hpp"
|
#include "../view/MapView.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,7 +105,7 @@ void RPGEdit::run() {
|
||||||
|
|
||||||
window = std::make_shared<View::Window>();
|
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(); });
|
eventThread = std::thread([this] { eventLoop(); });
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,8 @@ private:
|
||||||
EventBus eventBus;
|
EventBus eventBus;
|
||||||
InputHandler inputHandler;
|
InputHandler inputHandler;
|
||||||
|
|
||||||
|
ScriptContext scriptContext;
|
||||||
|
|
||||||
std::shared_ptr<View::Window> window;
|
std::shared_ptr<View::Window> window;
|
||||||
|
|
||||||
std::shared_ptr<MapContext> ctx;
|
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 <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
||||||
namespace RPGEdit {
|
namespace RPGEdit {
|
||||||
|
@ -46,43 +47,25 @@ class ScriptContext {
|
||||||
private:
|
private:
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
|
|
||||||
void setupEnv() {
|
std::unordered_set<std::string> loadedScripts;
|
||||||
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) {
|
void setupEnv();
|
||||||
luaL_requiref(L, lib.first, lib.second, 1);
|
void cleanupEnv();
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const char *f : {"dofile", "loadfile", "require"}) {
|
void load(const std::string &script);
|
||||||
lua_pushnil(L);
|
|
||||||
lua_setglobal(L, f);
|
size_t pushArgs() {
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanupEnv() {
|
template<typename... Args>
|
||||||
lua_pushglobaltable(L);
|
size_t pushArgs(Model::ScriptValue *v, Args ...args) {
|
||||||
|
if (v)
|
||||||
lua_pushnil(L);
|
v->push(L);
|
||||||
lua_setmetatable(L, -2);
|
else
|
||||||
|
|
||||||
lua_pushnil(L);
|
|
||||||
while (lua_next(L, -2) != 0) {
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_pushvalue(L, -1);
|
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
|
|
||||||
lua_rawset(L, -4);
|
return pushArgs(args...) + 1;
|
||||||
}
|
|
||||||
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -107,25 +90,21 @@ public:
|
||||||
lua_setglobal(L, key.c_str());
|
lua_setglobal(L, key.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(const std::string &name) {
|
template<typename... Args>
|
||||||
std::string filename = "../resources/script/" + name + ".lua";
|
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();
|
setupEnv();
|
||||||
|
|
||||||
lua_rawgetp(L, LUA_REGISTRYINDEX, this);
|
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_remove(L, -2);
|
||||||
|
|
||||||
lua_call(L, 0, 0);
|
lua_call(L, 0, 0);
|
||||||
|
|
||||||
|
lua_getglobal(L, name.c_str());
|
||||||
|
lua_call(L, pushArgs(args...), 0);
|
||||||
|
|
||||||
cleanupEnv();
|
cleanupEnv();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,19 +28,23 @@
|
||||||
|
|
||||||
|
|
||||||
#include "Direction.hpp"
|
#include "Direction.hpp"
|
||||||
|
#include "Scriptable.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
namespace RPGEdit {
|
namespace RPGEdit {
|
||||||
|
|
||||||
namespace Model {
|
namespace Model {
|
||||||
|
|
||||||
class Entity {
|
class Entity : public Scriptable {
|
||||||
private:
|
private:
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
std::pair<std::string, std::string> scriptInteract;
|
||||||
|
|
||||||
Direction direction;
|
Direction direction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -60,8 +64,13 @@ public:
|
||||||
direction = dir;
|
direction = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void interact(uint64_t time) {
|
const std::pair<std::string, std::string> & getScriptInteract() const {
|
||||||
std::fprintf(stderr, "Tried to interact with `%s' entity at %llu\n", name.c_str(), (unsigned long long)time);
|
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 {
|
class ScriptTable : public ScriptValue {
|
||||||
public:
|
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:
|
private:
|
||||||
MapType value;
|
MapType value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<ScriptValue> & operator[](const std::string &key) {
|
std::shared_ptr<ScriptValue> & operator[](const std::shared_ptr<ScriptValue> &key) {
|
||||||
return value[key];
|
return value[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ public:
|
||||||
lua_createtable(L, 0, value.size());
|
lua_createtable(L, 0, value.size());
|
||||||
|
|
||||||
for (const auto &entry : value) {
|
for (const auto &entry : value) {
|
||||||
lua_pushstring(L, entry.first.c_str());
|
entry.first->push(L);
|
||||||
entry.second->push(L);
|
entry.second->push(L);
|
||||||
|
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
|
|
Reference in a new issue