lua content pack environments test
This commit is contained in:
parent
fce77bc896
commit
6fc312b651
@ -8,6 +8,7 @@
|
||||
#include "../items/ItemDef.h"
|
||||
|
||||
#include "ContentPack.h"
|
||||
#include "../logic/scripting/scripting.h"
|
||||
|
||||
ContentBuilder::~ContentBuilder() {
|
||||
}
|
||||
|
||||
@ -255,7 +255,7 @@ void ContentLoader::loadBlock(Block& def, std::string full, std::string name) {
|
||||
|
||||
fs::path scriptfile = folder/fs::path("scripts/"+def.scriptName+".lua");
|
||||
if (fs::is_regular_file(scriptfile)) {
|
||||
scripting::load_block_script(full, scriptfile, def.rt.funcsset);
|
||||
scripting::load_block_script(env, full, scriptfile, def.rt.funcsset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,13 +267,16 @@ void ContentLoader::loadItem(ItemDef& def, std::string full, std::string name) {
|
||||
|
||||
fs::path scriptfile = folder/fs::path("scripts/"+def.scriptName+".lua");
|
||||
if (fs::is_regular_file(scriptfile)) {
|
||||
scripting::load_item_script(full, scriptfile, def.rt.funcsset);
|
||||
scripting::load_item_script(env, full, scriptfile, def.rt.funcsset);
|
||||
}
|
||||
}
|
||||
|
||||
void ContentLoader::load(ContentBuilder& builder) {
|
||||
std::cout << "-- loading pack [" << pack->id << "]" << std::endl;
|
||||
builder.add(new ContentPackRuntime(*pack));
|
||||
|
||||
auto runtime = new ContentPackRuntime(*pack, scripting::create_environment());
|
||||
builder.add(runtime);
|
||||
env = runtime->getEnvironment()->getId();
|
||||
|
||||
fixPackIndices();
|
||||
|
||||
@ -281,7 +284,7 @@ void ContentLoader::load(ContentBuilder& builder) {
|
||||
|
||||
fs::path scriptFile = folder/fs::path("scripts/world.lua");
|
||||
if (fs::is_regular_file(scriptFile)) {
|
||||
scripting::load_world_script(pack->id, scriptFile);
|
||||
scripting::load_world_script(env, pack->id, scriptFile);
|
||||
}
|
||||
|
||||
if (!fs::is_regular_file(pack->getContentFile()))
|
||||
|
||||
@ -17,6 +17,7 @@ namespace dynamic {
|
||||
|
||||
class ContentLoader {
|
||||
const ContentPack* pack;
|
||||
int env = 0;
|
||||
|
||||
void loadBlock(Block& def, std::string full, std::string name);
|
||||
void loadCustomBlockModel(Block& def, dynamic::Map* primitives);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "../files/files.h"
|
||||
#include "../files/engine_paths.h"
|
||||
#include "../data/dynamic.h"
|
||||
#include "../logic/scripting/scripting.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@ -150,5 +151,9 @@ void ContentPack::readPacks(const EnginePaths* paths,
|
||||
}
|
||||
}
|
||||
|
||||
ContentPackRuntime::ContentPackRuntime(ContentPack info) : info(info) {
|
||||
ContentPackRuntime::ContentPackRuntime(
|
||||
ContentPack info,
|
||||
std::unique_ptr<scripting::Environment> env
|
||||
) : info(info), env(std::move(env))
|
||||
{
|
||||
}
|
||||
|
||||
@ -10,6 +10,10 @@ class EnginePaths;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace scripting {
|
||||
class Environment;
|
||||
}
|
||||
|
||||
class contentpack_error : public std::runtime_error {
|
||||
std::string packId;
|
||||
fs::path folder;
|
||||
@ -52,17 +56,25 @@ struct ContentPack {
|
||||
static fs::path findPack(
|
||||
const EnginePaths* paths,
|
||||
fs::path worldDir,
|
||||
std::string name);
|
||||
static void readPacks(const EnginePaths* paths,
|
||||
std::vector<ContentPack>& packs,
|
||||
const std::vector<std::string>& names,
|
||||
fs::path worldDir);
|
||||
std::string name
|
||||
);
|
||||
|
||||
static void readPacks(
|
||||
const EnginePaths* paths,
|
||||
std::vector<ContentPack>& packs,
|
||||
const std::vector<std::string>& names,
|
||||
fs::path worldDir
|
||||
);
|
||||
};
|
||||
|
||||
class ContentPackRuntime {
|
||||
ContentPack info;
|
||||
std::unique_ptr<scripting::Environment> env;
|
||||
public:
|
||||
ContentPackRuntime(ContentPack info);
|
||||
ContentPackRuntime(
|
||||
ContentPack info,
|
||||
std::unique_ptr<scripting::Environment> env
|
||||
);
|
||||
|
||||
inline const std::string& getId() {
|
||||
return info.id;
|
||||
@ -71,6 +83,10 @@ public:
|
||||
inline const ContentPack& getInfo() const {
|
||||
return info;
|
||||
}
|
||||
|
||||
inline scripting::Environment* getEnvironment() const {
|
||||
return env.get();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CONTENT_CONTENT_PACK_H_
|
||||
|
||||
@ -130,6 +130,7 @@ void Engine::mainloop() {
|
||||
|
||||
Engine::~Engine() {
|
||||
screen = nullptr;
|
||||
content.reset();
|
||||
scripting::close();
|
||||
|
||||
Audio::finalize();
|
||||
|
||||
@ -54,7 +54,7 @@ std::unique_ptr<UiDocument> UiDocument::read(std::string namesp, fs::path file)
|
||||
uidocscript script {};
|
||||
auto scriptFile = fs::path(file.u8string()+".lua");
|
||||
if (fs::is_regular_file(scriptFile)) {
|
||||
scripting::load_layout_script(env->getId(), scriptFile, script);
|
||||
scripting::load_layout_script(env->getId(), namesp, scriptFile, script);
|
||||
}
|
||||
return std::make_unique<UiDocument>(namesp, script, view, env.release()->getId());
|
||||
}
|
||||
|
||||
@ -172,6 +172,40 @@ int lua::LuaState::pushstring(const std::string& str) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushenv(int env) {
|
||||
if (getglobal(envName(env))) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushglobals() {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lua::LuaState::pop(int n) {
|
||||
lua_pop(L, n);
|
||||
}
|
||||
|
||||
int lua::LuaState::pushnil() {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool lua::LuaState::getfield(const std::string& name) {
|
||||
lua_getfield(L, -1, name.c_str());
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, -1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void lua::LuaState::setfield(const std::string& name, int idx) {
|
||||
lua_setfield(L, idx, name.c_str());
|
||||
}
|
||||
|
||||
bool lua::LuaState::toboolean(int index) {
|
||||
return lua_toboolean(L, index);
|
||||
}
|
||||
@ -195,16 +229,17 @@ const std::string lua::LuaState::storeAnonymous() {
|
||||
|
||||
int lua::LuaState::createEnvironment() {
|
||||
int id = nextEnvironment++;
|
||||
// globals table
|
||||
|
||||
// local env = {}
|
||||
lua_createtable(L, 0, 1);
|
||||
|
||||
// metatable
|
||||
// setmetatable(env, {__index=_G})
|
||||
lua_createtable(L, 0, 1);
|
||||
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// envname = env
|
||||
setglobal(envName(id));
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -31,6 +31,12 @@ namespace lua {
|
||||
int pushinteger(luaint x);
|
||||
int pushnumber(luanumber x);
|
||||
int pushstring(const std::string& str);
|
||||
int pushenv(int env);
|
||||
int pushnil();
|
||||
int pushglobals();
|
||||
void pop(int n=1);
|
||||
bool getfield(const std::string& name);
|
||||
void setfield(const std::string& name, int idx=-2);
|
||||
bool toboolean(int index);
|
||||
luaint tointeger(int index);
|
||||
int call(int argc);
|
||||
|
||||
@ -205,51 +205,70 @@ bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x,
|
||||
return false;
|
||||
}
|
||||
|
||||
void scripting::load_block_script(std::string prefix, fs::path file, block_funcs_set& funcsset) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
state->execute(0, src, file.u8string());
|
||||
bool register_event(int env, const std::string& name, const std::string& id) {
|
||||
std::cout << "register " << name << " -> " << id << std::endl;
|
||||
if (state->pushenv(env) == 0) {
|
||||
state->pushglobals();
|
||||
}
|
||||
if (state->getfield(name)) {
|
||||
// remove previous name
|
||||
state->pushnil();
|
||||
state->setfield(name, -3);
|
||||
|
||||
funcsset.init=state->rename("init", prefix+".init");
|
||||
funcsset.update=state->rename("on_update", prefix+".update");
|
||||
funcsset.randupdate=state->rename("on_random_update", prefix+".randupdate");
|
||||
funcsset.onbroken=state->rename("on_broken", prefix+".broken");
|
||||
funcsset.onplaced=state->rename("on_placed", prefix+".placed");
|
||||
funcsset.oninteract=state->rename("on_interact", prefix+".oninteract");
|
||||
funcsset.onblockstick=state->rename("on_blocks_tick", prefix+".blockstick");
|
||||
std::cout << id << std::endl;
|
||||
// add new global name
|
||||
state->setglobal(id);
|
||||
state->pop();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void scripting::load_item_script(std::string prefix, fs::path file, item_funcs_set& funcsset) {
|
||||
void scripting::load_block_script(int env, std::string prefix, fs::path file, block_funcs_set& funcsset) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
state->execute(0, src, file.u8string());
|
||||
funcsset.init=state->rename("init", prefix+".init");
|
||||
funcsset.on_use_on_block=state->rename("on_use_on_block", prefix+".useon");
|
||||
funcsset.on_block_break_by=state->rename("on_block_break_by", prefix+".blockbreakby");
|
||||
state->execute(env, src, file.u8string());
|
||||
funcsset.init = register_event(env, "init", prefix+".init");
|
||||
funcsset.update = register_event(env, "on_update", prefix+".update");
|
||||
funcsset.randupdate = register_event(env, "on_random_update", prefix+".randupdate");
|
||||
funcsset.onbroken = register_event(env, "on_broken", prefix+".broken");
|
||||
funcsset.onplaced = register_event(env, "on_placed", prefix+".placed");
|
||||
funcsset.oninteract = register_event(env, "on_interact", prefix+".interact");
|
||||
funcsset.onblockstick = register_event(env, "on_blocks_tick", prefix+".blockstick");
|
||||
}
|
||||
|
||||
void scripting::load_world_script(std::string prefix, fs::path file) {
|
||||
void scripting::load_item_script(int env, std::string prefix, fs::path file, item_funcs_set& funcsset) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
state->execute(env, src, file.u8string());
|
||||
|
||||
funcsset.init = register_event(env, "init", prefix+".init");
|
||||
funcsset.on_use_on_block = register_event(env, "on_use_on_block", prefix+".useon");
|
||||
funcsset.on_block_break_by = register_event(env, "on_block_break_by", prefix+".blockbreakby");
|
||||
}
|
||||
|
||||
void scripting::load_world_script(int env, std::string prefix, fs::path file) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
|
||||
state->loadbuffer(0, src, file.u8string());
|
||||
state->loadbuffer(env, src, file.u8string());
|
||||
state->callNoThrow(0);
|
||||
|
||||
state->rename("init", prefix+".init");
|
||||
state->rename("on_world_open", prefix+".worldopen");
|
||||
state->rename("on_world_save", prefix+".worldsave");
|
||||
state->rename("on_world_quit", prefix+".worldquit");
|
||||
register_event(env, "init", prefix+".init");
|
||||
register_event(env, "on_world_open", prefix+".worldopen");
|
||||
register_event(env, "on_world_save", prefix+".worldsave");
|
||||
register_event(env, "on_world_quit", prefix+".worldquit");
|
||||
}
|
||||
|
||||
void scripting::load_layout_script(int env, fs::path file, uidocscript& script) {
|
||||
void scripting::load_layout_script(int env, std::string prefix, fs::path file, uidocscript& script) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
|
||||
script.environment = env;
|
||||
state->loadbuffer(env, src, file.u8string());
|
||||
state->callNoThrow(0);
|
||||
script.onopen = state->hasglobal("on_open");
|
||||
script.onclose = state->hasglobal("on_close");
|
||||
script.onopen = register_event(env, "on_open", prefix+".open");
|
||||
script.onclose = register_event(env, "on_close", prefix+".close");
|
||||
}
|
||||
|
||||
void scripting::close() {
|
||||
|
||||
@ -62,9 +62,9 @@ namespace scripting {
|
||||
bool on_block_interact(Player* player, const Block* block, int x, int y, int z);
|
||||
bool on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z);
|
||||
bool on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z);
|
||||
void load_block_script(std::string prefix, fs::path file, block_funcs_set& funcsset);
|
||||
void load_item_script(std::string prefix, fs::path file, item_funcs_set& funcsset);
|
||||
void load_world_script(std::string prefix, fs::path file);
|
||||
void load_layout_script(int env, fs::path file, uidocscript& script);
|
||||
void load_block_script(int env, std::string prefix, fs::path file, block_funcs_set& funcsset);
|
||||
void load_item_script(int env, std::string prefix, fs::path file, item_funcs_set& funcsset);
|
||||
void load_world_script(int env, std::string prefix, fs::path file);
|
||||
void load_layout_script(int env, std::string prefix, fs::path file, uidocscript& script);
|
||||
void close();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user