diff --git a/doc/en/scripting.md b/doc/en/scripting.md index d1fdc645..cf4d0bed 100644 --- a/doc/en/scripting.md +++ b/doc/en/scripting.md @@ -12,6 +12,7 @@ Subsections: - [block](scripting/builtins/libblock.md) - [cameras](scripting/builtins/libcameras.md) - [entities](scripting/builtins/libentities.md) + - [file](scripting/builtins/libfile.md) - [gui](scripting/builtins/libgui.md) - [hud](scripting/builtins/libhud.md) - [inventory](scripting/builtins/libinventory.md) diff --git a/doc/en/scripting/builtins/libfile.md b/doc/en/scripting/builtins/libfile.md new file mode 100644 index 00000000..fe02bed1 --- /dev/null +++ b/doc/en/scripting/builtins/libfile.md @@ -0,0 +1,116 @@ +# *file* library + +Filesystem interaction library. + +```python +file.resolve(path: str) -> str +``` + +Function turns `entry_point:path` (example `user:worlds/house1`) to a regular path. (example `C://Users/user/.voxeng/worlds/house1`) + +> [!NOTE] +> The function should be used for debug only. *entry_point:path* notation is required in all **file** functions. + +Resulting path is not canonical and may be relative. + +```python +file.read(path: str) -> str +``` + +Read whole text file. + +```python +file.read_bytes(path: str) -> array of integers +``` + +Read file into bytes array. + +```python +file.write(path: str, text: str) -> nil +``` + +Overwrite text file. + +```python +file.write_bytes(path: str, data: array of integers) +``` + +Overwrite binary file with bytes array. + +```python +file.length(path: str) -> int +``` + +Get file length (bytes) or 0. + +```python +file.exists(path: str) -> bool +``` + +Check if file or directory exist. + +```python +file.isfile(path: str) -> bool +``` + +Check if the path points to a file. + +```python +file.isdir(path: str) -> bool +``` + +Check if the path points to a directory. + +```python +file.mkdir(path: str) -> bool +``` + +Create directory. Returns true if new directory created + +```python +file.mkdirs(path: str) -> bool +``` + +Create directories chain. Returns true if new directory created. + +```python +file.list(path: str) -> array of strings +``` + +Returns a list of files and directories in the specified. + +```python +file.list_all_res(path: str) -> array of strings +``` + +Returns a list of files and directories in the specified one without specifying an entry point. + +```python +file.find(path: str) -> str +``` + +Searches for a file from the last pack to res. The path is specified without a prefix. Returns the path with the required prefix. If the file is not found, returns nil. + +```python +file.remove(path: str) -> bool +``` + +Deletes a file. Returns **true** if the file exists. Throws an exception on access violation. + +```python +file.remove_tree(path: str) -> int +``` + +Recursively deletes files. Returns the number of files deleted. + +```python +file.read_combined_list(path: str) -> array +``` + +Combines arrays from JSON files of different packs. + +```python +file.read_combined_object(path: str) -> array +``` + +Combines objects from JSON files of different packs. diff --git a/doc/en/scripting/builtins/libworld.md b/doc/en/scripting/builtins/libworld.md index afd8c240..349e9106 100644 --- a/doc/en/scripting/builtins/libworld.md +++ b/doc/en/scripting/builtins/libworld.md @@ -1,6 +1,9 @@ # *world* library ```lua +-- Checks if world is open +world.is_open() -> bool + -- Returns worlds information. world.get_list() -> tables array { -- world name diff --git a/doc/en/scripting/events.md b/doc/en/scripting/events.md index 10b9e3f1..ccc61673 100644 --- a/doc/en/scripting/events.md +++ b/doc/en/scripting/events.md @@ -102,6 +102,12 @@ function on_block_broken(blockid, x, y, z, playerid) Called on block broken by player +```lua +function on_block_interact(blockid, x, y, z, playerid) -> bool +``` + +Called on block RMB click interaction. Prevents block placing if **true** returned. + ## Layout events Script *layouts/layout_name.xml.lua* events. diff --git a/doc/en/scripting/filesystem.md b/doc/en/scripting/filesystem.md index 49a7b273..b37c799f 100644 --- a/doc/en/scripting/filesystem.md +++ b/doc/en/scripting/filesystem.md @@ -2,78 +2,7 @@ ### *file* library -Filesystem interaction library. - -```python -file.resolve(path: str) -> str -``` - -Function turns `entry_point:path` (example `user:worlds/house1`) to a regular path. (example `C://Users/user/.voxeng/worlds/house1`) - -> [!NOTE] -> The function should be used for debug only. *entry_point:path* notation is required in all **file** functions. - -Resulting path is not canonical and may be relative. - -```python -file.read(path: str) -> str -``` - -Read whole text file. - -```python -file.read_bytes(path: str) -> array of integers -``` - -Read file into bytes array. - -```python -file.write(path: str, text: str) -> nil -``` - -Overwrite text file. - -```python -file.write_bytes(path: str, data: array of integers) -``` - -Overwrite binary file with bytes array. - -```python -file.length(path: str) -> int -``` - -Get file length (bytes) or 0. - -```python -file.exists(path: str) -> bool -``` - -Check if file or directory exist. - -```python -file.isfile(path: str) -> bool -``` - -Check if the path points to a file. - -```python -file.isdir(path: str) -> bool -``` - -Check if the path points to a directory. - -```python -file.mkdir(path: str) -> bool -``` - -Create directory. Returns true if new directory created - -```python -file.mkdirs(path: str) -> bool -``` - -Create directories chain. Returns true if new directory created. +See [file library](builtins/libfile.md) ## *json* library diff --git a/doc/ru/scripting.md b/doc/ru/scripting.md index 0900788e..12878e88 100644 --- a/doc/ru/scripting.md +++ b/doc/ru/scripting.md @@ -12,6 +12,7 @@ - [block](scripting/builtins/libblock.md) - [cameras](scripting/builtins/libcameras.md) - [entities](scripting/builtins/libentities.md) + - [file](scripting/builtins/libfile.md) - [gui](scripting/builtins/libgui.md) - [hud](scripting/builtins/libhud.md) - [inventory](scripting/builtins/libinventory.md) diff --git a/doc/ru/scripting/builtins/libfile.md b/doc/ru/scripting/builtins/libfile.md new file mode 100644 index 00000000..a9a9c273 --- /dev/null +++ b/doc/ru/scripting/builtins/libfile.md @@ -0,0 +1,116 @@ +# Библиотека *file* + +Библиотека функций для работы с файлами + +```python +file.resolve(путь: str) -> str +``` + +Функция приводит запись `точка_входа:путь` (например `user:worlds/house1`) к обычному пути. (например `C://Users/user/.voxeng/worlds/house1`) + +> [!NOTE] +> Функцию не нужно использовать в сочетании с другими функциями из библиотеки, так как они делают это автоматически + +Возвращаемый путь не является каноническим и может быть как абсолютным, так и относительным. + +```python +file.read(путь: str) -> str +``` + +Читает весь текстовый файл и возвращает в виде строки + +```python +file.read_bytes(путь: str) -> array of integers +``` + +Читает файл в массив байт. + +```python +file.write(путь: str, текст: str) -> nil +``` + +Записывает текст в файл (с перезаписью) + +```python +file.write_bytes(путь: str, data: array of integers) +``` + +Записывает массив байт в файл (с перезаписью) + +```python +file.length(путь: str) -> int +``` + +Возвращает размер файла в байтах, либо -1, если файл не найден + +```python +file.exists(путь: str) -> bool +``` + +Проверяет, существует ли по данному пути файл или директория + +```python +file.isfile(путь: str) -> bool +``` + +Проверяет, существует ли по данному пути файл + +```python +file.isdir(путь: str) -> bool +``` + +Проверяет, существует ли по данному пути директория + +```python +file.mkdir(путь: str) -> bool +``` + +Создает директорию. Возвращает true если была создана новая директория + +```python +file.mkdirs(путь: str) -> bool +``` + +Создает всю цепочку директорий. Возвращает true если были созданы директории. + +```python +file.list(путь: str) -> массив строк +``` + +Возвращает список файлов и директорий в указанной. + +```python +file.list_all_res(путь: str) -> массив строк +``` + +Возвращает список файлов и директорий в указанной без указания конкретной точки входа. + +```python +file.find(путь: str) -> str +``` + +Ищет файл от последнего пака до res. Путь указывается без префикса. Возвращает путь с нужным префиксом. Если файл не найден, возвращает nil. + +```python +file.remove(путь: str) -> bool +``` + +Удаляет файл. Возращает **true** если файл существовал. Бросает исключение при нарушении доступа. + +```python +file.remove_tree(путь: str) -> int +``` + +Рекурсивно удаляет файлы. Возвращает число удаленных файлов. + +```python +file.read_combined_list(путь: str) -> массив +``` + +Совмещает массивы из JSON файлов разных паков. + +```python +file.read_combined_object(путь: str) -> массив +``` + +Совмещает объекты из JSON файлов разных паков. diff --git a/doc/ru/scripting/builtins/libworld.md b/doc/ru/scripting/builtins/libworld.md index 31806de4..b82f3b53 100644 --- a/doc/ru/scripting/builtins/libworld.md +++ b/doc/ru/scripting/builtins/libworld.md @@ -1,6 +1,9 @@ # Библиотека *world* ```lua +-- Проверяет, открыт ли мир +world.is_open() -> bool + -- Возвращает информацию о мирах. world.get_list() -> массив таблиц { -- название мира diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index d7805d60..31c958fc 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -102,6 +102,12 @@ function on_block_broken(blockid, x, y, z, playerid) Вызывается после разрушения блока игроком +```lua +function on_block_interact(blockid, x, y, z, playerid) -> bool +``` + +Вызывается при нажатии на блок ПКМ. Предотвращает установку блоков, если возвращает `true` + ## События макета События прописываются в файле `layouts/имя_макета.xml.lua`. diff --git a/doc/ru/scripting/filesystem.md b/doc/ru/scripting/filesystem.md index 7e6d658f..faaaf9b7 100644 --- a/doc/ru/scripting/filesystem.md +++ b/doc/ru/scripting/filesystem.md @@ -2,96 +2,7 @@ ## Библиотека *file* -Библиотека функций для работы с файлами - -```python -file.resolve(путь: str) -> str -``` - -Функция приводит запись `точка_входа:путь` (например `user:worlds/house1`) к обычному пути. (например `C://Users/user/.voxeng/worlds/house1`) - -> [!NOTE] -> Функцию не нужно использовать в сочетании с другими функциями из библиотеки, так как они делают это автоматически - -Возвращаемый путь не является каноническим и может быть как абсолютным, так и относительным. - -```python -file.read(путь: str) -> str -``` - -Читает весь текстовый файл и возвращает в виде строки - -```python -file.read_bytes(путь: str) -> array of integers -``` - -Читает файл в массив байт. - -```python -file.write(путь: str, текст: str) -> nil -``` - -Записывает текст в файл (с перезаписью) - -```python -file.write_bytes(путь: str, data: array of integers) -``` - -Записывает массив байт в файл (с перезаписью) - -```python -file.length(путь: str) -> int -``` - -Возвращает размер файла в байтах, либо -1, если файл не найден - -```python -file.exists(путь: str) -> bool -``` - -Проверяет, существует ли по данному пути файл или директория - -```python -file.isfile(путь: str) -> bool -``` - -Проверяет, существует ли по данному пути файл - -```python -file.isdir(путь: str) -> bool -``` - -Проверяет, существует ли по данному пути директория - -```python -file.mkdir(путь: str) -> bool -``` - -Создает директорию. Возвращает true если была создана новая директория - -```python -file.mkdirs(путь: str) -> bool -``` - -Создает всю цепочку директорий. Возвращает true если были созданы директории. - -```python -file.find(путь: str) -> str -``` - -Ищет файл от последнего пака до res. Путь указывается без префикса. Возвращает путь с нужным префиксом. Если файл не найден, возвращает nil. - -```python -file.remove(путь: str) -> bool -``` - -Удаляет файл. Возращает **true** если файл существовал. Бросает исключение при нарушении доступа. - -```python -file.remove_tree(путь: str) -> int -``` - -Рекурсивно удаляет файлы. Возвращает число удаленных файлов. +См. [библиотека file](builtins/libfile.md) ## Библиотека json diff --git a/res/layouts/pages/content.xml.lua b/res/layouts/pages/content.xml.lua index 115e6aed..d03c6e80 100644 --- a/res/layouts/pages/content.xml.lua +++ b/res/layouts/pages/content.xml.lua @@ -91,6 +91,14 @@ function refresh() packs_cur:clear() packs_add:clear() + -- lock pack that contains used generator + if world.is_open() then + local genpack, genname = parse_path(world.get_generator()) + if genpack ~= "core" then + table.insert(base_packs, genpack) + end + end + for i,id in ipairs(packs_installed) do local packinfo = pack.get_info(id) packinfo.index = i diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index 082d2eea..5aa1a22b 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -97,6 +97,7 @@ struct ContentPackStats { struct world_funcs_set { bool onblockplaced : 1; bool onblockbroken : 1; + bool onblockinteract : 1; }; class ContentPackRuntime { diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index cad8ae70..b0362fd9 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -64,7 +64,7 @@ void BlocksController::breakBlock( ); chunks->set(x, y, z, 0, {}); lighting->onBlockSet(x, y, z, 0); - scripting::on_block_broken(player, def, x, y, z); + scripting::on_block_broken(player, def, glm::ivec3(x, y, z)); if (def.rt.extended) { updateSides(x, y, z , def.size.x, def.size.y, def.size.z); } else { @@ -80,7 +80,7 @@ void BlocksController::placeBlock( ); chunks->set(x, y, z, def.rt.id, state); lighting->onBlockSet(x, y, z, def.rt.id); - scripting::on_block_placed(player, def, x, y, z); + scripting::on_block_placed(player, def, glm::ivec3(x, y, z)); if (def.rt.extended) { updateSides(x, y, z , def.size.x, def.size.y, def.size.z); } else { @@ -91,7 +91,7 @@ void BlocksController::placeBlock( void BlocksController::updateBlock(int x, int y, int z) { voxel* vox = chunks->get(x, y, z); if (vox == nullptr) return; - auto& def = level->content->getIndices()->blocks.require(vox->id); + const auto& def = level->content->getIndices()->blocks.require(vox->id); if (def.grounded) { const auto& vec = get_ground_direction(def, vox->state.rotation); if (!chunks->isSolidBlock(x + vec.x, y + vec.y, z + vec.z)) { @@ -100,7 +100,7 @@ void BlocksController::updateBlock(int x, int y, int z) { } } if (def.rt.funcsset.update) { - scripting::update_block(def, x, y, z); + scripting::update_block(def, glm::ivec3(x, y, z)); } } @@ -144,7 +144,10 @@ void BlocksController::randomTick( auto& block = indices->blocks.require(vox.id); if (block.rt.funcsset.randupdate) { scripting::random_update_block( - block, chunk.x * CHUNK_W + bx, by, chunk.z * CHUNK_D + bz + block, + glm::ivec3( + chunk.x * CHUNK_W + bx, by, chunk.z * CHUNK_D + bz + ) ); } } diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index c114f00b..80ce633e 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -23,7 +23,7 @@ static fs::path resolve_path_soft(const std::string& path) { return engine->getPaths()->resolve(path, false); } -static int l_file_find(lua::State* L) { +static int l_find(lua::State* L) { auto path = lua::require_string(L, 1); try { return lua::pushstring(L, engine->getResPaths()->findRaw(path)); @@ -32,12 +32,12 @@ static int l_file_find(lua::State* L) { } } -static int l_file_resolve(lua::State* L) { +static int l_resolve(lua::State* L) { fs::path path = resolve_path(lua::require_string(L, 1)); return lua::pushstring(L, path.u8string()); } -static int l_file_read(lua::State* L) { +static int l_read(lua::State* L) { fs::path path = resolve_path(lua::require_string(L, 1)); if (fs::is_regular_file(path)) { return lua::pushstring(L, files::read_string(path)); @@ -47,7 +47,7 @@ static int l_file_read(lua::State* L) { ); } -static int l_file_write(lua::State* L) { +static int l_write(lua::State* L) { fs::path path = resolve_path(lua::require_string(L, 1)); std::string text = lua::require_string(L, 2); files::write_string(path, text); @@ -58,7 +58,7 @@ static std::set writeable_entry_points { "world", "export", "config" }; -static int l_file_remove(lua::State* L) { +static int l_remove(lua::State* L) { std::string rawpath = lua::require_string(L, 1); fs::path path = resolve_path(rawpath); auto entryPoint = rawpath.substr(0, rawpath.find(':')); @@ -68,7 +68,7 @@ static int l_file_remove(lua::State* L) { return lua::pushboolean(L, fs::remove(path)); } -static int l_file_remove_tree(lua::State* L) { +static int l_remove_tree(lua::State* L) { std::string rawpath = lua::require_string(L, 1); fs::path path = resolve_path(rawpath); auto entryPoint = rawpath.substr(0, rawpath.find(':')); @@ -78,22 +78,22 @@ static int l_file_remove_tree(lua::State* L) { return lua::pushinteger(L, fs::remove_all(path)); } -static int l_file_exists(lua::State* L) { +static int l_exists(lua::State* L) { fs::path path = resolve_path_soft(lua::require_string(L, 1)); return lua::pushboolean(L, fs::exists(path)); } -static int l_file_isfile(lua::State* L) { +static int l_isfile(lua::State* L) { fs::path path = resolve_path_soft(lua::require_string(L, 1)); return lua::pushboolean(L, fs::is_regular_file(path)); } -static int l_file_isdir(lua::State* L) { +static int l_isdir(lua::State* L) { fs::path path = resolve_path_soft(lua::require_string(L, 1)); return lua::pushboolean(L, fs::is_directory(path)); } -static int l_file_length(lua::State* L) { +static int l_length(lua::State* L) { fs::path path = resolve_path(lua::require_string(L, 1)); if (fs::exists(path)) { return lua::pushinteger(L, fs::file_size(path)); @@ -102,17 +102,17 @@ static int l_file_length(lua::State* L) { } } -static int l_file_mkdir(lua::State* L) { +static int l_mkdir(lua::State* L) { fs::path path = resolve_path(lua::require_string(L, 1)); return lua::pushboolean(L, fs::create_directory(path)); } -static int l_file_mkdirs(lua::State* L) { +static int l_mkdirs(lua::State* L) { fs::path path = resolve_path(lua::require_string(L, 1)); return lua::pushboolean(L, fs::create_directories(path)); } -static int l_file_read_bytes(lua::State* L) { +static int l_read_bytes(lua::State* L) { fs::path path = resolve_path(lua::require_string(L, 1)); if (fs::is_regular_file(path)) { size_t length = static_cast(fs::file_size(path)); @@ -154,7 +154,7 @@ static int read_bytes_from_table( } } -static int l_file_write_bytes(lua::State* L) { +static int l_write_bytes(lua::State* L) { int pathIndex = 1; if (!lua::isstring(L, pathIndex)) { @@ -181,7 +181,7 @@ static int l_file_write_bytes(lua::State* L) { } } -static int l_file_list_all_res(lua::State* L, const std::string& path) { +static int l_list_all_res(lua::State* L, const std::string& path) { auto files = engine->getResPaths()->listdirRaw(path); lua::createtable(L, files.size(), 0); for (size_t i = 0; i < files.size(); i++) { @@ -191,10 +191,10 @@ static int l_file_list_all_res(lua::State* L, const std::string& path) { return 1; } -static int l_file_list(lua::State* L) { +static int l_list(lua::State* L) { std::string dirname = lua::require_string(L, 1); if (dirname.find(':') == std::string::npos) { - return l_file_list_all_res(L, dirname); + return l_list_all_res(L, dirname); } fs::path path = resolve_path(dirname); if (!fs::is_directory(path)) { @@ -214,7 +214,7 @@ static int l_file_list(lua::State* L) { return 1; } -static int l_file_gzip_compress(lua::State* L) { +static int l_gzip_compress(lua::State* L) { std::vector bytes; int result = read_bytes_from_table(L, -1, bytes); @@ -233,7 +233,7 @@ static int l_file_gzip_compress(lua::State* L) { } } -static int l_file_gzip_decompress(lua::State* L) { +static int l_gzip_decompress(lua::State* L) { std::vector bytes; int result = read_bytes_from_table(L, -1, bytes); @@ -252,7 +252,7 @@ static int l_file_gzip_decompress(lua::State* L) { } } -static int l_file_read_combined_list(lua::State* L) { +static int l_read_combined_list(lua::State* L) { std::string path = lua::require_string(L, 1); if (path.find(':') != std::string::npos) { throw std::runtime_error("entry point must not be specified"); @@ -260,23 +260,32 @@ static int l_file_read_combined_list(lua::State* L) { return lua::pushvalue(L, engine->getResPaths()->readCombinedList(path)); } +static int l_read_combined_object(lua::State* L) { + std::string path = lua::require_string(L, 1); + if (path.find(':') != std::string::npos) { + throw std::runtime_error("entry point must not be specified"); + } + return lua::pushvalue(L, engine->getResPaths()->readCombinedObject(path)); +} + const luaL_Reg filelib[] = { - {"exists", lua::wrap}, - {"find", lua::wrap}, - {"isdir", lua::wrap}, - {"isfile", lua::wrap}, - {"length", lua::wrap}, - {"list", lua::wrap}, - {"mkdir", lua::wrap}, - {"mkdirs", lua::wrap}, - {"read_bytes", lua::wrap}, - {"read", lua::wrap}, - {"remove", lua::wrap}, - {"remove_tree", lua::wrap}, - {"resolve", lua::wrap}, - {"write_bytes", lua::wrap}, - {"write", lua::wrap}, - {"gzip_compress", lua::wrap}, - {"gzip_decompress", lua::wrap}, - {"read_combined_list", lua::wrap}, + {"exists", lua::wrap}, + {"find", lua::wrap}, + {"isdir", lua::wrap}, + {"isfile", lua::wrap}, + {"length", lua::wrap}, + {"list", lua::wrap}, + {"mkdir", lua::wrap}, + {"mkdirs", lua::wrap}, + {"read_bytes", lua::wrap}, + {"read", lua::wrap}, + {"remove", lua::wrap}, + {"remove_tree", lua::wrap}, + {"resolve", lua::wrap}, + {"write_bytes", lua::wrap}, + {"write", lua::wrap}, + {"gzip_compress", lua::wrap}, + {"gzip_decompress", lua::wrap}, + {"read_combined_list", lua::wrap}, + {"read_combined_object", lua::wrap}, {NULL, NULL}}; diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index 04249299..06da877c 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -20,6 +20,10 @@ static WorldInfo& require_world_info() { return level->getWorld()->getInfo(); } +static int l_is_open(lua::State* L) { + return lua::pushboolean(L, level != nullptr); +} + static int l_get_list(lua::State* L) { auto paths = engine->getPaths(); auto worlds = paths->scanForWorlds(); @@ -98,6 +102,7 @@ static int l_get_generator(lua::State* L) { } const luaL_Reg worldlib[] = { + {"is_open", lua::wrap}, {"get_list", lua::wrap}, {"get_total_time", lua::wrap}, {"get_day_time", lua::wrap}, diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 70a397b4..a8143d24 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -216,82 +216,78 @@ void scripting::on_blocks_tick(const Block& block, int tps) { }); } -void scripting::update_block(const Block& block, int x, int y, int z) { +void scripting::update_block(const Block& block, const glm::ivec3& pos) { std::string name = block.name + ".update"; - lua::emit_event(lua::get_main_state(), name, [x, y, z](auto L) { - return lua::pushivec_stack(L, glm::ivec3(x, y, z)); + lua::emit_event(lua::get_main_state(), name, [pos](auto L) { + return lua::pushivec_stack(L, pos); }); } -void scripting::random_update_block(const Block& block, int x, int y, int z) { +void scripting::random_update_block(const Block& block, const glm::ivec3& pos) { std::string name = block.name + ".randupdate"; - lua::emit_event(lua::get_main_state(), name, [x, y, z](auto L) { - return lua::pushivec_stack(L, glm::ivec3(x, y, z)); + lua::emit_event(lua::get_main_state(), name, [pos](auto L) { + return lua::pushivec_stack(L, pos); }); } void scripting::on_block_placed( - Player* player, const Block& block, int x, int y, int z + Player* player, const Block& block, const glm::ivec3& pos ) { if (block.rt.funcsset.onplaced) { std::string name = block.name + ".placed"; - lua::emit_event(lua::get_main_state(), name, [x, y, z, player](auto L) { - lua::pushivec_stack(L, glm::ivec3(x, y, z)); + lua::emit_event(lua::get_main_state(), name, [pos, player](auto L) { + lua::pushivec_stack(L, pos); lua::pushinteger(L, player ? player->getId() : -1); return 4; }); } - auto world_event_args = [&](lua::State* L) { + auto args = [&](lua::State* L) { lua::pushinteger(L, block.rt.id); - lua::pushivec_stack(L, glm::ivec3(x, y, z)); + lua::pushivec_stack(L, pos); lua::pushinteger(L, player ? player->getId() : -1); return 5; }; for (auto& [packid, pack] : content->getPacks()) { if (pack->worldfuncsset.onblockplaced) { lua::emit_event( - lua::get_main_state(), - packid + ":.blockplaced", - world_event_args + lua::get_main_state(), packid + ":.blockplaced", args ); } } } void scripting::on_block_broken( - Player* player, const Block& block, int x, int y, int z + Player* player, const Block& block, const glm::ivec3& pos ) { if (block.rt.funcsset.onbroken) { std::string name = block.name + ".broken"; lua::emit_event( lua::get_main_state(), name, - [x, y, z, player](auto L) { - lua::pushivec_stack(L, glm::ivec3(x, y, z)); + [pos, player](auto L) { + lua::pushivec_stack(L, pos); lua::pushinteger(L, player ? player->getId() : -1); return 4; } ); } - auto world_event_args = [&](lua::State* L) { + auto args = [&](lua::State* L) { lua::pushinteger(L, block.rt.id); - lua::pushivec_stack(L, glm::ivec3(x, y, z)); + lua::pushivec_stack(L, pos); lua::pushinteger(L, player ? player->getId() : -1); return 5; }; for (auto& [packid, pack] : content->getPacks()) { if (pack->worldfuncsset.onblockbroken) { lua::emit_event( - lua::get_main_state(), - packid + ":.blockbroken", - world_event_args + lua::get_main_state(), packid + ":.blockbroken", args ); } } } bool scripting::on_block_interact( - Player* player, const Block& block, glm::ivec3 pos + Player* player, const Block& block, const glm::ivec3& pos ) { std::string name = block.name + ".interact"; return lua::emit_event(lua::get_main_state(), name, [pos, player](auto L) { @@ -299,6 +295,19 @@ bool scripting::on_block_interact( lua::pushinteger(L, player->getId()); return 4; }); + auto args = [&](lua::State* L) { + lua::pushinteger(L, block.rt.id); + lua::pushivec_stack(L, pos); + lua::pushinteger(L, player ? player->getId() : -1); + return 5; + }; + for (auto& [packid, pack] : content->getPacks()) { + if (pack->worldfuncsset.onblockinteract) { + lua::emit_event( + lua::get_main_state(), packid + ":.blockinteract", args + ); + } + } } bool scripting::on_item_use(Player* player, const ItemDef& item) { @@ -697,6 +706,8 @@ void scripting::load_world_script( register_event(env, "on_block_placed", prefix + ":.blockplaced"); funcsset.onblockbroken = register_event(env, "on_block_broken", prefix + ":.blockbroken"); + funcsset.onblockinteract = + register_event(env, "on_block_interact", prefix + ":.blockinteract"); } void scripting::load_layout_script( diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index af9bb4c2..2b3eab90 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -64,15 +64,15 @@ namespace scripting { void on_world_quit(); void cleanup(); void on_blocks_tick(const Block& block, int tps); - void update_block(const Block& block, int x, int y, int z); - void random_update_block(const Block& block, int x, int y, int z); + void update_block(const Block& block, const glm::ivec3& pos); + void random_update_block(const Block& block, const glm::ivec3& pos); void on_block_placed( - Player* player, const Block& block, int x, int y, int z + Player* player, const Block& block, const glm::ivec3& pos ); void on_block_broken( - Player* player, const Block& block, int x, int y, int z + Player* player, const Block& block, const glm::ivec3& pos ); - bool on_block_interact(Player* player, const Block& block, glm::ivec3 pos); + bool on_block_interact(Player* player, const Block& block, const glm::ivec3& pos); /// @brief Called on RMB click with the item selected /// @return true if prevents default action