lua content pack environments test

This commit is contained in:
MihailRis 2024-02-09 19:47:22 +03:00
parent fce77bc896
commit 6fc312b651
11 changed files with 131 additions and 44 deletions

View File

@ -8,6 +8,7 @@
#include "../items/ItemDef.h"
#include "ContentPack.h"
#include "../logic/scripting/scripting.h"
ContentBuilder::~ContentBuilder() {
}

View File

@ -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()))

View File

@ -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);

View File

@ -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))
{
}

View File

@ -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_

View File

@ -130,6 +130,7 @@ void Engine::mainloop() {
Engine::~Engine() {
screen = nullptr;
content.reset();
scripting::close();
Audio::finalize();

View File

@ -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());
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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() {

View File

@ -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();
}