From 958a7065468cf7df2b4a0755eac926e3b3f0134a Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:59:53 +0300 Subject: [PATCH 01/47] add new extensions.lua --- res/scripts/stdmin.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 76df31e2..56b11639 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -51,6 +51,19 @@ function math.rand(low, high) return low + (high - low) * math.random() end +function math.normalize(num, conf) + conf = conf or 10 + + return (num / conf) % 1 +end + +function math.round(num, places) + places = places or 0 + + local mult = 10 ^ places + return math.floor(num * mult + 0.5) / mult +end + ---------------------------------------------- function table.copy(t) @@ -91,6 +104,15 @@ function table.random(t) return t[math.random(1, #t)] end +function table.shuffle(t) + for i = #t, 2, -1 do + local j = math.random(i) + t[i], t[j] = t[j], t[i] + end + + return t +end + ---------------------------------------------- local pattern_escape_replacements = { From 31a2c69c485064c407cd039f779c520e98c64417 Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Fri, 20 Dec 2024 23:11:00 +0300 Subject: [PATCH 02/47] Update extensions.md --- doc/ru/scripting/extensions.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/ru/scripting/extensions.md b/doc/ru/scripting/extensions.md index d0ddd365..d0780af3 100644 --- a/doc/ru/scripting/extensions.md +++ b/doc/ru/scripting/extensions.md @@ -46,6 +46,13 @@ table.remove_value(t: table, x: object) Удаляет элемент **x** из **t**. +```lua +table.shuffle(t: table) -> table +``` + +Перемешивает значения в таблице. + + ```lua table.tostring(t: table) -> string ``` @@ -146,6 +153,18 @@ math.rand(low, high) Возвращает случайное дробное число в диапазоне от **low** до **high**. +```lua +math.normalize(num: number, [опционально] conf: num) -> number +``` + +Возвращает нормализованное значение num относительно conf. + +```lua +math.round(num: number, [опционально] places: num) -> number +``` + +Возвращает округлённое число до указанного количества знаков после запятой places. + ## Дополнительные глобальные функции В этом же скрипте также определены и другие глобальные функции которые доступны для использования. Ниже их список From c4a40d6b804414edf314413197c17df47f9b344d Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Fri, 20 Dec 2024 23:16:25 +0300 Subject: [PATCH 03/47] Update extensions.md --- doc/ru/scripting/extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/scripting/extensions.md b/doc/ru/scripting/extensions.md index d0780af3..ca165b0c 100644 --- a/doc/ru/scripting/extensions.md +++ b/doc/ru/scripting/extensions.md @@ -163,7 +163,7 @@ math.normalize(num: number, [опционально] conf: num) -> number math.round(num: number, [опционально] places: num) -> number ``` -Возвращает округлённое число до указанного количества знаков после запятой places. +Возвращает округлённое значение num до указанного количества знаков после запятой places. ## Дополнительные глобальные функции From 6018db9c286b6993a0bc1a5e944df7a66d5864dd Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Fri, 20 Dec 2024 23:26:59 +0300 Subject: [PATCH 04/47] refact math.normalize --- res/scripts/stdmin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 56b11639..72383dce 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -52,7 +52,7 @@ function math.rand(low, high) end function math.normalize(num, conf) - conf = conf or 10 + conf = conf or 1 return (num / conf) % 1 end From f4ac84daa2ed68d79ef20463affee06bf372bec6 Mon Sep 17 00:00:00 2001 From: Xertis Date: Fri, 20 Dec 2024 23:55:10 +0300 Subject: [PATCH 05/47] fix --- res/scripts/stdmin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 72383dce..56b11639 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -52,7 +52,7 @@ function math.rand(low, high) end function math.normalize(num, conf) - conf = conf or 1 + conf = conf or 10 return (num / conf) % 1 end From f43e378bc02f37ff4d3b9bed0fc5fe5cfa8be1df Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 02:01:52 +0300 Subject: [PATCH 06/47] update leaves --- res/content/base/blocks/leaves.json | 4 +++- res/content/base/textures/blocks/leaves.png | Bin 6541 -> 753 bytes .../base/textures/blocks/leaves_culled.png | Bin 0 -> 6541 bytes 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 res/content/base/textures/blocks/leaves_culled.png diff --git a/res/content/base/blocks/leaves.json b/res/content/base/blocks/leaves.json index cdf9f014..91182bc8 100644 --- a/res/content/base/blocks/leaves.json +++ b/res/content/base/blocks/leaves.json @@ -1,5 +1,7 @@ { "texture": "leaves", "material": "base:grass", - "base:durability": 0.7 + "base:durability": 0.7, + "culling": "optional", + "model": "aabb" } diff --git a/res/content/base/textures/blocks/leaves.png b/res/content/base/textures/blocks/leaves.png index 3beaf7ab9ad7c6304fc4ac43642e7103c425cfa3..9ea91852924b13e86424d2d03df46a5db0f463ea 100644 GIT binary patch delta 730 zcmV<00ww*8Gw}tGBYy(8Nkl+UY>)&Qd@$AX^C%2#BD@AVhue z%{MhB{wv=whF4zH2V$Z^N(2Hz1O=pp7?!e>j$LO;x8wAV9U)fzVCi>zwa`* z3{$idF}y!8o3uW#z)zR!Qy}33g@`?0@QU0}cu_{d(^LxTT&T zVzZOYCPHZ;82E!GL2N6H`pfH?HwV~!*G(pQMKJ@=oxcU_>>@-DDvL51_@%DX<(r(4b)(QOKs@4)6!HN zN9$~)Y6X+vcz@#z)eI4e0;ED2KARy1)h!~iWa|Im!IDArZ9WDdNTo5}AAaehuWt|e zn!7_HW%CS=kFpTkE+A`bk|2bPl#Mtx-FDONyn?zk^YH8)4%+{b1piPatO7;8N4$mnpig86*ONR%Ea{XMX^GPRCJhsW1-JGE`8)!wtZ5f=qHU|#{lGs$$Ul2#Gb{^NFN#A>dibi2K8}ZZgavj5@;UQYp#c=m+%ymxA7Zt~=UI$2lz7b4t3c!U&AmH+?% M07*qoM6N<$f)nLj761SM literal 6541 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 diff --git a/res/content/base/textures/blocks/leaves_culled.png b/res/content/base/textures/blocks/leaves_culled.png new file mode 100644 index 0000000000000000000000000000000000000000..3beaf7ab9ad7c6304fc4ac43642e7103c425cfa3 GIT binary patch literal 6541 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 literal 0 HcmV?d00001 From dc93cac1b92fff5e39fb91a332f27d99e0098797 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 02:34:54 +0300 Subject: [PATCH 07/47] add 'script' entry point --- src/engine.cpp | 3 +++ src/files/engine_paths.cpp | 8 +++++++- src/files/engine_paths.hpp | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/engine.cpp b/src/engine.cpp index 2f8466d6..a3c63035 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -83,6 +83,9 @@ Engine::Engine(CoreParameters coreParameters) paths.setResourcesFolder(params.resFolder); paths.setUserFilesFolder(params.userFolder); paths.prepare(); + if (!params.scriptFile.empty()) { + paths.setScriptFolder(params.scriptFile.parent_path()); + } loadSettings(); auto resdir = paths.getResourcesFolder(); diff --git a/src/files/engine_paths.cpp b/src/files/engine_paths.cpp index 0ecea7b8..2c8cd02c 100644 --- a/src/files/engine_paths.cpp +++ b/src/files/engine_paths.cpp @@ -169,6 +169,10 @@ void EnginePaths::setResourcesFolder(std::filesystem::path folder) { this->resourcesFolder = std::move(folder); } +void EnginePaths::setScriptFolder(std::filesystem::path folder) { + this->scriptFolder = std::move(folder); +} + void EnginePaths::setCurrentWorldFolder(std::filesystem::path folder) { this->currentWorldFolder = std::move(folder); } @@ -211,7 +215,9 @@ std::filesystem::path EnginePaths::resolve( if (prefix == "export") { return userFilesFolder / EXPORT_FOLDER / fs::u8path(filename); } - + if (prefix == "script" && scriptFolder) { + return scriptFolder.value() / fs::u8path(filename); + } if (contentPacks) { for (auto& pack : *contentPacks) { if (pack.id == prefix) { diff --git a/src/files/engine_paths.hpp b/src/files/engine_paths.hpp index 61be1757..5ec34704 100644 --- a/src/files/engine_paths.hpp +++ b/src/files/engine_paths.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,8 @@ public: void setResourcesFolder(std::filesystem::path folder); std::filesystem::path getResourcesFolder() const; + void setScriptFolder(std::filesystem::path folder); + std::filesystem::path getWorldFolderByName(const std::string& name); std::filesystem::path getWorldsFolder() const; std::filesystem::path getConfigFolder() const; @@ -51,6 +54,7 @@ private: std::filesystem::path userFilesFolder {"."}; std::filesystem::path resourcesFolder {"res"}; std::filesystem::path currentWorldFolder; + std::optional scriptFolder; std::vector* contentPacks = nullptr; }; From d021b443dd98b52a24215678b87882917795b0be Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 05:38:30 +0300 Subject: [PATCH 08/47] update leaves texture --- res/content/base/textures/blocks/leaves.png | Bin 753 -> 896 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/res/content/base/textures/blocks/leaves.png b/res/content/base/textures/blocks/leaves.png index 9ea91852924b13e86424d2d03df46a5db0f463ea..a9cd60e3e88fcc465db4b9933f6daf962ae574b8 100644 GIT binary patch delta 874 zcmV-w1C{*o1%L;TBYy)&Nkl>1D4<40mAXJqU)Y+!>B3-~RtV%LJivI`a{PzY5;XrWCT@*paW6E%)aY{%H1u{~pZJaf1n zDdBAHc|X2$uK4a}GqkdzV}9NbB@)E;mX7*{!A5g3_1i8Is(*;stb+CLYD`H-DB`!E z+d*7f3}SQ3f_Ur8f@j#9oJQwH1k|cM z3}q3V-nkma{-KF{-oau{#>QF$qvJ9T*6J+25GB_QU@7CruX_L!1yoN45a43@<0)x#KOo$ddBNI^hLs?duj#QklHcO~J{Wes<4{^PZkyAq{@VPa$5K$0gl@_@eEWJ}AVbkcC} z_f{L}iy?GvK0>A3M^qZXWenFo8mHSg%Ixlq0)LBURC4(?^J@k>9V0O-!-j>zA8mFR z^pi8-YwYZ`Sce-+J0%au;mI-#kXumE?K-%h@0{V_bZktXld#44@wU!LRC-~af1GCwJ5PH2mIXw)E*uSD=c)7m7Gytx_{FWS=%hgmKObE1foL|&%|5lA@&xdJjLO>+qgE(w?nBY17St>;bb+UY>)&Qd@$AX^C%2#BD@AVhue z%{MhB{wv=whF4zH2V$Z^N(2Hz1O=pp7?!e>j$LO;x8wAV9U)fzVCi>zwa`* z3{$idF}y!8o3uW#z)zR!Qy}33g@`?0@QU0}cu_{d(^LxTT&T zVzZOYCPHZ;82E!GL2N6H`pfH?HwV~!*G(pQMKJ@=oxcU_>>@-DDvL51_@%DX<(r(4b)(QOKs@4)6!HN zN9$~)Y6X+vcz@#z)eI4e0;ED2KARy1)h!~iWa|Im!IDArZ9WDdNTo5}AAaehuWt|e zn!7_HW%CS=kFpTkE+A`bk|2bPl#Mtx-FDONyn?zk^YH8)4%+{b1piPatO7;8N4$mnpig86*ONR%Ea{XMX^GPRCJhsW1-JGE`8)!wtZ5f=qHU|#{lGs$$Ul2#Gb{^NFN#A>dibi2K8}ZZgavj5@;UQYp#c=m+%ymxA7Zt~=UI$2lz7b4t3c!U&AmH+?% M07*qoM6N<$f^m3T-2eap From 954724c8378da525fc7349c018e9351c5bdfdf8f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 06:41:03 +0300 Subject: [PATCH 09/47] add 'culling' property & optimize generated chunk meshes & fix faces culling when 'light-passing' is false --- res/content/base/blocks/leaves.json | 4 +-- .../{leaves_culled.png => leaves_opaque.png} | Bin src/content/ContentLoader.cpp | 10 +++++++- src/graphics/render/BlocksRenderer.cpp | 24 +++++++++--------- src/graphics/render/BlocksRenderer.hpp | 8 ++++-- src/voxels/Block.cpp | 24 ++++++++++++++++++ src/voxels/Block.hpp | 12 +++++++++ 7 files changed, 65 insertions(+), 17 deletions(-) rename res/content/base/textures/blocks/{leaves_culled.png => leaves_opaque.png} (100%) diff --git a/res/content/base/blocks/leaves.json b/res/content/base/blocks/leaves.json index 91182bc8..e3ddae22 100644 --- a/res/content/base/blocks/leaves.json +++ b/res/content/base/blocks/leaves.json @@ -1,7 +1,7 @@ { "texture": "leaves", "material": "base:grass", - "base:durability": 0.7, + "draw-group": 5, "culling": "optional", - "model": "aabb" + "base:durability": 0.7 } diff --git a/res/content/base/textures/blocks/leaves_culled.png b/res/content/base/textures/blocks/leaves_opaque.png similarity index 100% rename from res/content/base/textures/blocks/leaves_culled.png rename to res/content/base/textures/blocks/leaves_opaque.png diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index fee559e4..1dc676ea 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -239,10 +239,18 @@ void ContentLoader::loadBlock( } def.model = *model; } else if (!modelTypeName.empty()) { - logger.error() << "unknown model " << modelTypeName; + logger.error() << "unknown model: " << modelTypeName; def.model = BlockModel::none; } + std::string cullingModeName = to_string(def.culling); + root.at("culling").get(cullingModeName); + if (auto mode = CullingMode_from(cullingModeName)) { + def.culling = *mode; + } else { + logger.error() << "unknown culling mode: " << cullingModeName; + } + root.at("material").get(def.material); // rotation profile diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index cb590bcb..f1e8001f 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -342,41 +342,41 @@ void BlocksRenderer::blockCube( } if (ao) { - if (isOpen(coord + Z, group)) { + if (isOpen(coord + Z, block)) { faceAO(coord, X, Y, Z, texfaces[5], lights); } - if (isOpen(coord - Z, group)) { + if (isOpen(coord - Z, block)) { faceAO(coord, -X, Y, -Z, texfaces[4], lights); } - if (isOpen(coord + Y, group)) { + if (isOpen(coord + Y, block)) { faceAO(coord, X, -Z, Y, texfaces[3], lights); } - if (isOpen(coord - Y, group)) { + if (isOpen(coord - Y, block)) { faceAO(coord, X, Z, -Y, texfaces[2], lights); } - if (isOpen(coord + X, group)) { + if (isOpen(coord + X, block)) { faceAO(coord, -Z, Y, X, texfaces[1], lights); } - if (isOpen(coord - X, group)) { + if (isOpen(coord - X, block)) { faceAO(coord, Z, Y, -X, texfaces[0], lights); } } else { - if (isOpen(coord + Z, group)) { + if (isOpen(coord + Z, block)) { face(coord, X, Y, Z, texfaces[5], pickLight(coord + Z), lights); } - if (isOpen(coord - Z, group)) { + if (isOpen(coord - Z, block)) { face(coord, -X, Y, -Z, texfaces[4], pickLight(coord - Z), lights); } - if (isOpen(coord + Y, group)) { + if (isOpen(coord + Y, block)) { face(coord, X, -Z, Y, texfaces[3], pickLight(coord + Y), lights); } - if (isOpen(coord - Y, group)) { + if (isOpen(coord - Y, block)) { face(coord, X, Z, -Y, texfaces[2], pickLight(coord - Y), lights); } - if (isOpen(coord + X, group)) { + if (isOpen(coord + X, block)) { face(coord, -Z, Y, X, texfaces[1], pickLight(coord + X), lights); } - if (isOpen(coord - X, group)) { + if (isOpen(coord - X, block)) { face(coord, Z, Y, -X, texfaces[0], pickLight(coord - X), lights); } } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index c0e0086e..d27f681b 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -118,7 +118,7 @@ class BlocksRenderer { bool isOpenForLight(int x, int y, int z) const; // Does block allow to see other blocks sides (is it transparent) - inline bool isOpen(const glm::ivec3& pos, ubyte group) const { + inline bool isOpen(const glm::ivec3& pos, const Block& def) const { auto id = voxelsBuffer->pickBlockId( chunk->x * CHUNK_W + pos.x, pos.y, chunk->z * CHUNK_D + pos.z ); @@ -126,7 +126,11 @@ class BlocksRenderer { return false; } const auto& block = *blockDefsCache[id]; - if ((block.drawGroup != group && block.lightPassing) || !block.rt.solid) { + if (((block.drawGroup != def.drawGroup) && block.drawGroup) || !block.rt.solid) { + return true; + } + if (def.culling == CullingMode::DISABLED || + (def.culling == CullingMode::OPTIONAL && id == def.rt.id)) { return true; } return !id; diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index 520f9f99..96bca245 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -49,6 +49,30 @@ std::optional BlockModel_from(std::string_view str) { return std::nullopt; } +std::string to_string(CullingMode mode) { + switch (mode) { + case CullingMode::DEFAULT: + return "default"; + case CullingMode::OPTIONAL: + return "optional"; + case CullingMode::DISABLED: + return "disabled"; + default: + return "unknown"; + } +} + +std::optional CullingMode_from(std::string_view str) { + if (str == "default") { + return CullingMode::DEFAULT; + } else if (str == "optional") { + return CullingMode::OPTIONAL; + } else if (str == "disabled") { + return CullingMode::DISABLED; + } + return std::nullopt; +} + CoordSystem::CoordSystem(glm::ivec3 axisX, glm::ivec3 axisY, glm::ivec3 axisZ) : axisX(axisX), axisY(axisY), axisZ(axisZ) { fix = glm::ivec3(0); diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 557bf04c..eb232e8d 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -97,6 +97,15 @@ enum class BlockModel { std::string to_string(BlockModel model); std::optional BlockModel_from(std::string_view str); +enum class CullingMode { + DEFAULT, + OPTIONAL, + DISABLED, +}; + +std::string to_string(CullingMode mode); +std::optional CullingMode_from(std::string_view str); + using BoxModel = AABB; /// @brief Common kit of block properties applied to groups of blocks @@ -142,6 +151,9 @@ public: std::string modelName = ""; + /// @brief Culling mode + CullingMode culling = CullingMode::DEFAULT; + /// @brief Does the block passing lights into itself bool lightPassing = false; From dc8f5e7873de10b966a43e172b070af753f998b8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 08:13:05 +0300 Subject: [PATCH 10/47] add 'graphics.dense-render' setting --- res/layouts/pages/settings_graphics.xml.lua | 1 + res/texts/en_US.txt | 1 + res/texts/ru_RU.txt | 2 + src/files/settings_io.cpp | 1 + src/frontend/ContentGfxCache.cpp | 80 +++++++++++++-------- src/frontend/ContentGfxCache.hpp | 18 ++++- src/frontend/LevelFrontend.cpp | 21 ++++-- src/frontend/LevelFrontend.hpp | 9 ++- src/frontend/screens/LevelScreen.cpp | 8 ++- src/graphics/render/BlocksRenderer.cpp | 3 - src/graphics/render/BlocksRenderer.hpp | 8 ++- src/settings.hpp | 6 ++ 12 files changed, 111 insertions(+), 47 deletions(-) diff --git a/res/layouts/pages/settings_graphics.xml.lua b/res/layouts/pages/settings_graphics.xml.lua index 8a479a1c..c4503e52 100644 --- a/res/layouts/pages/settings_graphics.xml.lua +++ b/res/layouts/pages/settings_graphics.xml.lua @@ -41,4 +41,5 @@ function on_open() create_setting("graphics.fog-curve", "Fog Curve", 0.1) create_setting("graphics.gamma", "Gamma", 0.05, "", "graphics.gamma.tooltip") create_checkbox("graphics.backlight", "Backlight", "graphics.backlight.tooltip") + create_checkbox("graphics.dense-render", "Dense blocks render", "graphics.dense-render.tooltip") end diff --git a/res/texts/en_US.txt b/res/texts/en_US.txt index c19fe00a..e9b23897 100644 --- a/res/texts/en_US.txt +++ b/res/texts/en_US.txt @@ -16,6 +16,7 @@ devtools.traceback=Traceback (most recent call first) # Tooltips graphics.gamma.tooltip=Lighting brightness curve graphics.backlight.tooltip=Backlight to prevent total darkness +graphics.dense-render.tooltip=Enables transparency in blocks like leaves # settings settings.Controls Search Mode=Search by attached button name diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index ae591042..e78b5f72 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -28,6 +28,7 @@ pack.remove-confirm=Удалить весь поставляемый паком/ # Подсказки graphics.gamma.tooltip=Кривая яркости освещения graphics.backlight.tooltip=Подсветка, предотвращающая полную темноту +graphics.dense-render.tooltip=Включает прозрачность блоков, таких как листья. # Меню menu.Apply=Применить @@ -67,6 +68,7 @@ world.delete-confirm=Удалить мир безвозвратно? # Настройки settings.Ambient=Фон settings.Backlight=Подсветка +settings.Dense blocks render=Плотный рендер блоков settings.Camera Shaking=Тряска Камеры settings.Camera Inertia=Инерция Камеры settings.Camera FOV Effects=Эффекты поля зрения diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index d2a85f6a..fe251a11 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -68,6 +68,7 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { builder.section("graphics"); builder.add("fog-curve", &settings.graphics.fogCurve); builder.add("backlight", &settings.graphics.backlight); + builder.add("dense-render", &settings.graphics.denseRender); builder.add("gamma", &settings.graphics.gamma); builder.add("frustum-culling", &settings.graphics.frustumCulling); builder.add("skybox-resolution", &settings.graphics.skyboxResolution); diff --git a/src/frontend/ContentGfxCache.cpp b/src/frontend/ContentGfxCache.cpp index c6ba4e1c..844fd4e6 100644 --- a/src/frontend/ContentGfxCache.cpp +++ b/src/frontend/ContentGfxCache.cpp @@ -6,53 +6,71 @@ #include "assets/Assets.hpp" #include "content/Content.hpp" #include "content/ContentPack.hpp" -#include "core_defs.hpp" #include "graphics/core/Atlas.hpp" #include "maths/UVRegion.hpp" #include "voxels/Block.hpp" +#include "core_defs.hpp" +#include "settings.hpp" -ContentGfxCache::ContentGfxCache(const Content* content, const Assets& assets) - : content(content) { - auto indices = content->getIndices(); + +ContentGfxCache::ContentGfxCache( + const Content& content, + const Assets& assets, + const GraphicsSettings& settings +) + : content(content), assets(assets), settings(settings) { + refresh(); +} + +void ContentGfxCache::refresh(const Block& def, const Atlas& atlas) { + for (uint side = 0; side < 6; side++) { + std::string tex = def.textureFaces[side]; + if (def.culling == CullingMode::OPTIONAL && + !settings.denseRender.get() && atlas.has(tex + "_opaque")) { + tex = tex + "_opaque"; + } + if (atlas.has(tex)) { + sideregions[def.rt.id * 6 + side] = atlas.get(tex); + } else if (atlas.has(TEXTURE_NOTFOUND)) { + sideregions[def.rt.id * 6 + side] = atlas.get(TEXTURE_NOTFOUND); + } + } + if (def.model == BlockModel::custom) { + auto model = assets.require(def.modelName); + // temporary dirty fix tbh + if (def.modelName.find(':') == std::string::npos) { + for (auto& mesh : model.meshes) { + size_t pos = mesh.texture.find(':'); + if (pos == std::string::npos) { + continue; + } + if (auto region = atlas.getIf(mesh.texture.substr(pos+1))) { + for (auto& vertex : mesh.vertices) { + vertex.uv = region->apply(vertex.uv); + } + } + } + } + models[def.rt.id] = std::move(model); + } +} + +void ContentGfxCache::refresh() { + auto indices = content.getIndices(); sideregions = std::make_unique(indices->blocks.count() * 6); const auto& atlas = assets.require("blocks"); const auto& blocks = indices->blocks.getIterable(); for (blockid_t i = 0; i < blocks.size(); i++) { auto def = blocks[i]; - for (uint side = 0; side < 6; side++) { - const std::string& tex = def->textureFaces[side]; - if (atlas.has(tex)) { - sideregions[i * 6 + side] = atlas.get(tex); - } else if (atlas.has(TEXTURE_NOTFOUND)) { - sideregions[i * 6 + side] = atlas.get(TEXTURE_NOTFOUND); - } - } - if (def->model == BlockModel::custom) { - auto model = assets.require(def->modelName); - // temporary dirty fix tbh - if (def->modelName.find(':') == std::string::npos) { - for (auto& mesh : model.meshes) { - size_t pos = mesh.texture.find(':'); - if (pos == std::string::npos) { - continue; - } - if (auto region = atlas.getIf(mesh.texture.substr(pos+1))) { - for (auto& vertex : mesh.vertices) { - vertex.uv = region->apply(vertex.uv); - } - } - } - } - models[def->rt.id] = std::move(model); - } + refresh(*def, atlas); } } ContentGfxCache::~ContentGfxCache() = default; const Content* ContentGfxCache::getContent() const { - return content; + return &content; } const model::Model& ContentGfxCache::getModel(blockid_t id) const { diff --git a/src/frontend/ContentGfxCache.hpp b/src/frontend/ContentGfxCache.hpp index 96d46ea5..739d6c1d 100644 --- a/src/frontend/ContentGfxCache.hpp +++ b/src/frontend/ContentGfxCache.hpp @@ -10,19 +10,29 @@ class Content; class Assets; +class Atlas; +struct Block; struct UVRegion; +struct GraphicsSettings; namespace model { struct Model; } class ContentGfxCache { - const Content* content; + const Content& content; + const Assets& assets; + const GraphicsSettings& settings; + // array of block sides uv regions (6 per block) std::unique_ptr sideregions; std::unordered_map models; public: - ContentGfxCache(const Content* content, const Assets& assets); + ContentGfxCache( + const Content& content, + const Assets& assets, + const GraphicsSettings& settings + ); ~ContentGfxCache(); inline const UVRegion& getRegion(blockid_t id, int side) const { @@ -32,4 +42,8 @@ public: const model::Model& getModel(blockid_t id) const; const Content* getContent() const; + + void refresh(const Block& block, const Atlas& atlas); + + void refresh(); }; diff --git a/src/frontend/LevelFrontend.cpp b/src/frontend/LevelFrontend.cpp index 79784375..d3cbb9e8 100644 --- a/src/frontend/LevelFrontend.cpp +++ b/src/frontend/LevelFrontend.cpp @@ -14,12 +14,17 @@ #include "world/Level.hpp" LevelFrontend::LevelFrontend( - Player* currentPlayer, LevelController* controller, Assets& assets -) : level(*controller->getLevel()), - controller(controller), - assets(assets), - contentCache(std::make_unique(level.content, assets)) -{ + Player* currentPlayer, + LevelController* controller, + Assets& assets, + const EngineSettings& settings +) + : level(*controller->getLevel()), + controller(controller), + assets(assets), + contentCache(std::make_unique( + *level.content, assets, settings.graphics + )) { assets.store( BlocksPreview::build( *contentCache, assets, *level.content->getIndices() @@ -98,6 +103,10 @@ const Assets& LevelFrontend::getAssets() const { return assets; } +ContentGfxCache& LevelFrontend::getContentGfxCache() { + return *contentCache; +} + const ContentGfxCache& LevelFrontend::getContentGfxCache() const { return *contentCache; } diff --git a/src/frontend/LevelFrontend.hpp b/src/frontend/LevelFrontend.hpp index 163fc678..b53d267a 100644 --- a/src/frontend/LevelFrontend.hpp +++ b/src/frontend/LevelFrontend.hpp @@ -7,6 +7,7 @@ class Assets; class Player; class ContentGfxCache; class LevelController; +struct EngineSettings; class LevelFrontend { Level& level; @@ -14,12 +15,18 @@ class LevelFrontend { const Assets& assets; std::unique_ptr contentCache; public: - LevelFrontend(Player* currentPlayer, LevelController* controller, Assets& assets); + LevelFrontend( + Player* currentPlayer, + LevelController* controller, + Assets& assets, + const EngineSettings& settings + ); ~LevelFrontend(); Level& getLevel(); const Level& getLevel() const; const Assets& getAssets() const; const ContentGfxCache& getContentGfxCache() const; + ContentGfxCache& getContentGfxCache(); LevelController* getController() const; }; diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 34d1db67..e38b3bec 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -17,6 +17,7 @@ #include "graphics/render/Decorator.hpp" #include "graphics/ui/elements/Menu.hpp" #include "graphics/ui/GUI.hpp" +#include "frontend/ContentGfxCache.hpp" #include "logic/LevelController.hpp" #include "logic/scripting/scripting_hud.hpp" #include "util/stringutil.hpp" @@ -42,7 +43,7 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr levelPtr) controller = std::make_unique(engine, std::move(levelPtr)); frontend = std::make_unique( - controller->getPlayer(), controller.get(), assets + controller->getPlayer(), controller.get(), assets, settings ); worldRenderer = std::make_unique( engine, *frontend, controller->getPlayer() @@ -57,6 +58,11 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr levelPtr) controller->getLevel()->chunks->saveAndClear(); worldRenderer->clear(); })); + keepAlive(settings.graphics.denseRender.observe([=](bool) { + controller->getLevel()->chunks->saveAndClear(); + worldRenderer->clear(); + frontend->getContentGfxCache().refresh(); + })); keepAlive(settings.camera.fov.observe([=](double value) { controller->getPlayer()->fpCamera->setFov(glm::radians(value)); })); diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index f1e8001f..56f1c4e2 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -8,9 +8,6 @@ #include "voxels/Chunks.hpp" #include "lighting/Lightmap.hpp" #include "frontend/ContentGfxCache.hpp" -#include "settings.hpp" - -#include const glm::vec3 BlocksRenderer::SUN_VECTOR (0.411934f, 0.863868f, -0.279161f); diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index d27f681b..c652b6a0 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -13,6 +13,7 @@ #include "graphics/core/MeshData.hpp" #include "maths/util.hpp" #include "commons.hpp" +#include "settings.hpp" class Content; class Mesh; @@ -22,7 +23,6 @@ class Chunks; class VoxelsVolume; class Chunks; class ContentGfxCache; -struct EngineSettings; struct UVRegion; class BlocksRenderer { @@ -129,8 +129,10 @@ class BlocksRenderer { if (((block.drawGroup != def.drawGroup) && block.drawGroup) || !block.rt.solid) { return true; } - if (def.culling == CullingMode::DISABLED || - (def.culling == CullingMode::OPTIONAL && id == def.rt.id)) { + if ((def.culling == CullingMode::DISABLED || + (def.culling == CullingMode::OPTIONAL && + settings.graphics.denseRender.get())) && + id == def.rt.id) { return true; } return !id; diff --git a/src/settings.hpp b/src/settings.hpp index b0eee035..48d72b27 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -63,16 +63,22 @@ struct GraphicsSettings { NumberSetting gamma {1.0f, 0.4f, 1.0f}; /// @brief Enable blocks backlight to prevent complete darkness FlagSetting backlight {true}; + /// @brief Disable culling with 'optional' mode + FlagSetting denseRender {true}; /// @brief Enable chunks frustum culling FlagSetting frustumCulling {true}; + /// @brief Skybox texture face resolution IntegerSetting skyboxResolution {64 + 32, 64, 128}; + /// @brief Chunk renderer vertices buffer capacity IntegerSetting chunkMaxVertices {200'000, 0, 4'000'000}; + /// @brief Limit of chunk renderers count IntegerSetting chunkMaxRenderers {6, -4, 32}; }; struct DebugSettings { /// @brief Turns off chunks saving/loading FlagSetting generatorTestMode {false}; + /// @brief Write lights cache FlagSetting doWriteLights {true}; }; From a5a72af796d6bb842538ab6b7ab47c4b8ce9e705 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 08:31:58 +0300 Subject: [PATCH 11/47] fix msvc build --- src/frontend/ContentGfxCache.hpp | 2 +- src/graphics/render/Decorator.hpp | 2 +- src/graphics/render/ModelsGenerator.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/ContentGfxCache.hpp b/src/frontend/ContentGfxCache.hpp index 739d6c1d..cb5e2ad7 100644 --- a/src/frontend/ContentGfxCache.hpp +++ b/src/frontend/ContentGfxCache.hpp @@ -11,7 +11,7 @@ class Content; class Assets; class Atlas; -struct Block; +class Block; struct UVRegion; struct GraphicsSettings; diff --git a/src/graphics/render/Decorator.hpp b/src/graphics/render/Decorator.hpp index fbc196aa..422f6f77 100644 --- a/src/graphics/render/Decorator.hpp +++ b/src/graphics/render/Decorator.hpp @@ -14,7 +14,7 @@ class Chunks; class Camera; class Assets; class Player; -struct Block; +class Block; class Engine; class LevelController; class WorldRenderer; diff --git a/src/graphics/render/ModelsGenerator.hpp b/src/graphics/render/ModelsGenerator.hpp index 52bc56d0..c4665118 100644 --- a/src/graphics/render/ModelsGenerator.hpp +++ b/src/graphics/render/ModelsGenerator.hpp @@ -7,7 +7,7 @@ struct ItemDef; class Assets; class Content; -struct Block; +class Block; class ModelsGenerator { public: From 6f6421df53caf4a5a87329806f8af22fbf1f7022 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 08:45:30 +0300 Subject: [PATCH 12/47] update doc/*/block-properties.md --- doc/en/block-properties.md | 7 +++++++ doc/ru/block-properties.md | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/en/block-properties.md b/doc/en/block-properties.md index fb874e0c..6400c910 100644 --- a/doc/en/block-properties.md +++ b/doc/en/block-properties.md @@ -81,6 +81,13 @@ Turns off block model shading Determines the presence of the vertex AO effect. Turned-on by default. +### *culling* + +Face culling mode: +- **default** - normal face culling +- **optional** - face culling among blocks of the same rendering group can be disabled via the `graphics.dense-render` setting. +- **disabled** - face culling among blocks of the same rendering group disabled. + ## Physics ### *obstacle* diff --git a/doc/ru/block-properties.md b/doc/ru/block-properties.md index 1862e659..366cf0fb 100644 --- a/doc/ru/block-properties.md +++ b/doc/ru/block-properties.md @@ -82,7 +82,6 @@ При значении `true` блок не препятствует прохождению вертикального луча солнечного света. - ### Без освещения - *shadeless* Выключает освещение на модели блока. @@ -91,6 +90,13 @@ Определяет наличие эффекта вершинного AO. Включен по-умолчанию. +### Отсечение - *culling* + +Режим отсечения граней: +- **default** - обычное отсечение граней +- **optional** - отсечение граней среди блоков одной группы отрисовки можно отключить через настройку `graphics.dense-render` (Плотный рендер блоков). +- **disabled** - отсечение граней среди блоков одной группы отрисовки отключено. + ## Физика ### Препятствие - *obstacle* From f49feebd5cb0ffaf8fe1b7e721161be1a535ec1a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 09:55:44 +0300 Subject: [PATCH 13/47] refactor --- src/frontend/hud.cpp | 38 +++++++++++++++++++------------------- src/frontend/hud.hpp | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 33f8436b..95fd47dc 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -154,7 +154,7 @@ static constexpr uint WORLDGEN_IMG_SIZE = 128U; Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) : engine(engine), assets(*engine.getAssets()), - gui(engine.getGUI()), + gui(*engine.getGUI()), frontend(frontend), player(player), debugImgWorldGen(std::make_unique( @@ -183,11 +183,11 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) engine, frontend.getLevel(), player, allowDebugCheats ); debugPanel->setZIndex(2); - gui->add(debugPanel); + gui.add(debugPanel); - gui->add(darkOverlay); - gui->add(hotbarView); - gui->add(contentAccessPanel); + gui.add(darkOverlay); + gui.add(hotbarView); + gui.add(contentAccessPanel); auto dplotter = std::make_shared(350, 250, 2000, 16); dplotter->setGravity(Gravity::bottom_right); @@ -208,10 +208,10 @@ Hud::~Hud() { for (auto& element : elements) { onRemove(element); } - gui->remove(hotbarView); - gui->remove(darkOverlay); - gui->remove(contentAccessPanel); - gui->remove(debugPanel); + gui.remove(hotbarView); + gui.remove(darkOverlay); + gui.remove(contentAccessPanel); + gui.remove(debugPanel); } /// @brief Remove all elements marked as removed @@ -322,7 +322,7 @@ void Hud::updateWorldGenDebugVisualization() { void Hud::update(bool visible) { const auto& level = frontend.getLevel(); const auto& chunks = *player.chunks; - auto menu = gui->getMenu(); + const auto& menu = gui.getMenu(); debugPanel->setVisible(player.debug && visible); @@ -333,7 +333,7 @@ void Hud::update(bool visible) { setPause(false); } - if (!gui->isFocusCaught()) { + if (!gui.isFocusCaught()) { processInput(visible); } if ((pause || inventoryOpen) == Events::_cursor_locked) { @@ -460,7 +460,7 @@ void Hud::showExchangeSlot() { exchangeSlot->setColor(glm::vec4()); exchangeSlot->setInteractive(false); exchangeSlot->setZIndex(1); - gui->store(SlotView::EXCHANGE_SLOT_NAME, exchangeSlot); + gui.store(SlotView::EXCHANGE_SLOT_NAME, exchangeSlot); } @@ -494,7 +494,7 @@ void Hud::openPermanent(UiDocument* doc) { void Hud::dropExchangeSlot() { auto slotView = std::dynamic_pointer_cast( - gui->get(SlotView::EXCHANGE_SLOT_NAME) + gui.get(SlotView::EXCHANGE_SLOT_NAME) ); if (slotView == nullptr) { return; @@ -518,7 +518,7 @@ void Hud::dropExchangeSlot() { void Hud::closeInventory() { dropExchangeSlot(); - gui->remove(SlotView::EXCHANGE_SLOT_NAME); + gui.remove(SlotView::EXCHANGE_SLOT_NAME); exchangeSlot = nullptr; exchangeSlotInv = nullptr; inventoryOpen = false; @@ -536,7 +536,7 @@ void Hud::closeInventory() { } void Hud::add(const HudElement& element, const dv::value& argsArray) { - gui->add(element.getNode()); + gui.add(element.getNode()); auto document = element.getDocument(); if (document) { auto invview = std::dynamic_pointer_cast(element.getNode()); @@ -572,7 +572,7 @@ void Hud::onRemove(const HudElement& element) { invview->unbind(); } } - gui->remove(element.getNode()); + gui.remove(element.getNode()); } void Hud::remove(const std::shared_ptr& node) { @@ -681,7 +681,7 @@ void Hud::setPause(bool pause) { closeInventory(); } - auto menu = gui->getMenu(); + const auto& menu = gui.getMenu(); if (pause) { menu->setPage("pause"); } else { @@ -713,10 +713,10 @@ void Hud::setContentAccess(bool flag) { void Hud::setDebugCheats(bool flag) { allowDebugCheats = flag; - gui->remove(debugPanel); + gui.remove(debugPanel); debugPanel = create_debug_panel( engine, frontend.getLevel(), player, allowDebugCheats ); debugPanel->setZIndex(2); - gui->add(debugPanel); + gui.add(debugPanel); } diff --git a/src/frontend/hud.hpp b/src/frontend/hud.hpp index ff518d07..79d183fa 100644 --- a/src/frontend/hud.hpp +++ b/src/frontend/hud.hpp @@ -73,7 +73,7 @@ class Hud : public util::ObjectsKeeper { Engine& engine; Assets& assets; std::unique_ptr uicamera; - gui::GUI* gui; + gui::GUI& gui; LevelFrontend& frontend; Player& player; From 2d7f448d88edcf2e765319506b7d74fb0614de99 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 09:58:49 +0300 Subject: [PATCH 14/47] update leaves texture --- res/content/base/textures/blocks/leaves.png | Bin 896 -> 911 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/res/content/base/textures/blocks/leaves.png b/res/content/base/textures/blocks/leaves.png index a9cd60e3e88fcc465db4b9933f6daf962ae574b8..60b1fe36d2a663765a0b67ba6d17493685c93dbd 100644 GIT binary patch delta 888 zcmV-;1Bd*82agAkB!5;(L_t(|oIO)pZyQAv{${SMBS#1uzxBdIHO?erxH_Q0SdTH z)Os?`FU#28F(KagCgWVB_DzH$HegzK^OFf;k^nPrKo5x6eo)51$4J$fme6Q?NIiYE`D-Zdqoqp$z6)~X zHYP`1P!&S`agEja>FU)8`9c!V1rCo}Fb}%UJMlT<%G)~r{H?-wf}`-iPkI=x&6p2 zXACZC!|M~_l>sfHqLwuv9_*T&l^5qPYPfU##G#c~)hS#zkld;x!h>G8G)}jEIAJSm z!*o`$@ZU}ov2#AOd;AN9d>6X651TQ(_vt9zynmKwcdlia9#_fc*-UTN8J~!*Y80N4 z(1VH0-%WNTyUFTX5L>ARYjM=vUd|D6P_hhtB$iaP+ZOJnTaE^UKy$M)O^kc7!|i;s z!d|-)q8B2nF+a8Y0v4hI6kUNJxzVe25u8`)l||k-PZ{*<>2)XCyB`dtg?w{M8xL9I)*;xp3bzKM(0KZ)T%uU zWf7d-xf;g)p^1Fn!D3Fv###fT<1!A`>MXtxCD#pLDdWeldjJy!R8IyF;9~jXDe@Bh zxY~k9Hq5-qet+jq*FT@7@4q-?LtA~j$;L7g8KyfFas05!F1#8eO<`ESQ-wJFqDDru zi&Q3#M|sn8>gogUO}{Zh90K&n!NGnTT1uwLX$6Tf36-h?<~k5tZ3n6rM7d&N`I8y? z;j02$y;)+>Y=k<7jgIKU`HMk>lQOItp>)(lKmsad7k}B;k`U)+B;=1A1XYIJKifE^ zc-)8SIRzW{S}5+cP4g=&Ykgv4@kA zgVM2uOn+8`Ju6XUOosUOr&F}~OBs*uG;x7fJ>t7hjwq$;fB@f8q$ubO(TTs#MI=G+joZ;YfY)qb$u*LcEMuWY4Jx*sJs_8Iw z2LiGw0ZLSXAp2qKeZ=NedSRY_oM#L>PkQ{81w^?n91URSsq_C9WIuuU#jUUC?CJ+e zdSd*bgCGaX)l?o#2()#aU(|5_R*h-ThiPm=KqTUWIBa>C;5q(TDn$o%&aZx3Wm-Bw zax8=pM}8(1#?N2(*-LN9p6_BdfMM<3XI=aUmJ)WPdMoBE00000NkvXXu0mjfw7RXR From b372286a691f62cbfa36390aac8ac634abb8471c Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Sat, 21 Dec 2024 10:44:25 +0300 Subject: [PATCH 15/47] changing the standard conf to 1 --- res/scripts/stdmin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 56b11639..72383dce 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -52,7 +52,7 @@ function math.rand(low, high) end function math.normalize(num, conf) - conf = conf or 10 + conf = conf or 1 return (num / conf) % 1 end From 17161e5981dc01d8f2909c41303cb57f0544bae2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 12:55:47 +0300 Subject: [PATCH 16/47] fix: on_player_tick not called --- src/logic/LevelController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index 9304d36e..725a8b77 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -83,7 +83,7 @@ void LevelController::update(float delta, bool pause) { playerTickClock.getPart()) { const auto& position = player->getPosition(); - if (!player->chunks->get( + if (player->chunks->get( std::floor(position.x), std::floor(position.y), std::floor(position.z) From c3f22c6854cfc6a0d57c7c8f542eda1562322517 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 13:11:23 +0300 Subject: [PATCH 17/47] rename --- src/content/ContentPack.hpp | 4 ++-- src/items/ItemDef.hpp | 4 ++-- src/logic/scripting/scripting.cpp | 28 ++++++++++++++-------------- src/logic/scripting/scripting.hpp | 12 ++++++------ src/objects/Entities.cpp | 2 +- src/objects/Entities.hpp | 6 +++--- src/voxels/Block.hpp | 4 ++-- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index a3b40211..53d8a6e9 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -95,7 +95,7 @@ struct ContentPackStats { } }; -struct world_funcs_set { +struct WorldFuncsSet { bool onblockplaced : 1; bool onblockreplaced : 1; bool onblockbroken : 1; @@ -108,7 +108,7 @@ class ContentPackRuntime { ContentPackStats stats {}; scriptenv env; public: - world_funcs_set worldfuncsset {}; + WorldFuncsSet worldfuncsset {}; ContentPackRuntime(ContentPack info, scriptenv env); ~ContentPackRuntime(); diff --git a/src/items/ItemDef.hpp b/src/items/ItemDef.hpp index 7a2ef8d1..f6d61208 100644 --- a/src/items/ItemDef.hpp +++ b/src/items/ItemDef.hpp @@ -6,7 +6,7 @@ #include "data/dv.hpp" #include "typedefs.hpp" -struct item_funcs_set { +struct ItemFuncsSet { bool init : 1; bool on_use : 1; bool on_use_on_block : 1; @@ -43,7 +43,7 @@ struct ItemDef { struct { itemid_t id; blockid_t placingBlock; - item_funcs_set funcsset {}; + ItemFuncsSet funcsset {}; bool emissive = false; } rt {}; diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 1732a88a..d330eebf 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -599,7 +599,7 @@ static void process_entity_callback( static void process_entity_callback( const Entity& entity, const std::string& name, - bool entity_funcs_set::*flag, + bool EntityFuncsSet::*flag, std::function args ) { const auto& script = entity.getScripting(); @@ -612,7 +612,7 @@ static void process_entity_callback( void scripting::on_entity_despawn(const Entity& entity) { process_entity_callback( - entity, "on_despawn", &entity_funcs_set::on_despawn, nullptr + entity, "on_despawn", &EntityFuncsSet::on_despawn, nullptr ); auto L = lua::get_main_state(); lua::get_from(L, "stdcomp", "remove_Entity", true); @@ -624,20 +624,20 @@ void scripting::on_entity_grounded(const Entity& entity, float force) { process_entity_callback( entity, "on_grounded", - &entity_funcs_set::on_grounded, + &EntityFuncsSet::on_grounded, [force](auto L) { return lua::pushnumber(L, force); } ); } void scripting::on_entity_fall(const Entity& entity) { process_entity_callback( - entity, "on_fall", &entity_funcs_set::on_fall, nullptr + entity, "on_fall", &EntityFuncsSet::on_fall, nullptr ); } void scripting::on_entity_save(const Entity& entity) { process_entity_callback( - entity, "on_save", &entity_funcs_set::on_save, nullptr + entity, "on_save", &EntityFuncsSet::on_save, nullptr ); } @@ -647,7 +647,7 @@ void scripting::on_sensor_enter( process_entity_callback( entity, "on_sensor_enter", - &entity_funcs_set::on_sensor_enter, + &EntityFuncsSet::on_sensor_enter, [index, oid](auto L) { lua::pushinteger(L, index); lua::pushinteger(L, oid); @@ -662,7 +662,7 @@ void scripting::on_sensor_exit( process_entity_callback( entity, "on_sensor_exit", - &entity_funcs_set::on_sensor_exit, + &EntityFuncsSet::on_sensor_exit, [index, oid](auto L) { lua::pushinteger(L, index); lua::pushinteger(L, oid); @@ -675,7 +675,7 @@ void scripting::on_aim_on(const Entity& entity, Player* player) { process_entity_callback( entity, "on_aim_on", - &entity_funcs_set::on_aim_on, + &EntityFuncsSet::on_aim_on, [player](auto L) { return lua::pushinteger(L, player->getId()); } ); } @@ -684,7 +684,7 @@ void scripting::on_aim_off(const Entity& entity, Player* player) { process_entity_callback( entity, "on_aim_off", - &entity_funcs_set::on_aim_off, + &EntityFuncsSet::on_aim_off, [player](auto L) { return lua::pushinteger(L, player->getId()); } ); } @@ -695,7 +695,7 @@ void scripting::on_attacked( process_entity_callback( entity, "on_attacked", - &entity_funcs_set::on_attacked, + &EntityFuncsSet::on_attacked, [player, attacker](auto L) { lua::pushinteger(L, attacker); lua::pushinteger(L, player->getId()); @@ -708,7 +708,7 @@ void scripting::on_entity_used(const Entity& entity, Player* player) { process_entity_callback( entity, "on_used", - &entity_funcs_set::on_used, + &EntityFuncsSet::on_used, [player](auto L) { return lua::pushinteger(L, player->getId()); } ); } @@ -796,7 +796,7 @@ void scripting::load_content_script( const std::string& prefix, const fs::path& file, const std::string& fileName, - block_funcs_set& funcsset + BlockFuncsSet& funcsset ) { int env = *senv; lua::pop(lua::get_main_state(), load_script(env, "block", file, fileName)); @@ -819,7 +819,7 @@ void scripting::load_content_script( const std::string& prefix, const fs::path& file, const std::string& fileName, - item_funcs_set& funcsset + ItemFuncsSet& funcsset ) { int env = *senv; lua::pop(lua::get_main_state(), load_script(env, "item", file, fileName)); @@ -846,7 +846,7 @@ void scripting::load_world_script( const std::string& prefix, const fs::path& file, const std::string& fileName, - world_funcs_set& funcsset + WorldFuncsSet& funcsset ) { int env = *senv; lua::pop(lua::get_main_state(), load_script(env, "world", file, fileName)); diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index 4ccba2cb..6bb31355 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -21,9 +21,9 @@ class Player; struct ItemDef; class Inventory; class UiDocument; -struct block_funcs_set; -struct item_funcs_set; -struct world_funcs_set; +struct BlockFuncsSet; +struct ItemFuncsSet; +struct WorldFuncsSet; struct UserComponent; struct uidocscript; class BlocksController; @@ -141,7 +141,7 @@ namespace scripting { const std::string& prefix, const std::filesystem::path& file, const std::string& fileName, - block_funcs_set& funcsset + BlockFuncsSet& funcsset ); /// @brief Load script associated with an Item @@ -155,7 +155,7 @@ namespace scripting { const std::string& prefix, const std::filesystem::path& file, const std::string& fileName, - item_funcs_set& funcsset + ItemFuncsSet& funcsset ); /// @brief Load component script @@ -184,7 +184,7 @@ namespace scripting { const std::string& packid, const std::filesystem::path& file, const std::string& fileName, - world_funcs_set& funcsset + WorldFuncsSet& funcsset ); /// @brief Load script associated with an UiDocument diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index 1a27243f..e047fdd4 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -162,7 +162,7 @@ entityid_t Entities::spawn( for (auto& componentName : def.components) { auto component = std::make_unique( - componentName, entity_funcs_set {}, nullptr + componentName, EntityFuncsSet {}, nullptr ); scripting.components.emplace_back(std::move(component)); } diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index 0026d15e..0c93ae74 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -14,7 +14,7 @@ #include #include -struct entity_funcs_set { +struct EntityFuncsSet { bool init; bool on_despawn; bool on_grounded; @@ -77,11 +77,11 @@ struct Rigidbody { struct UserComponent { std::string name; - entity_funcs_set funcsset; + EntityFuncsSet funcsset; scriptenv env; UserComponent( - const std::string& name, entity_funcs_set funcsset, scriptenv env + const std::string& name, EntityFuncsSet funcsset, scriptenv env ) : name(name), funcsset(funcsset), env(env) { } diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index eb232e8d..8ea11bee 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -34,7 +34,7 @@ inline constexpr size_t MAX_USER_BLOCK_FIELDS_SIZE = 240; inline std::string DEFAULT_MATERIAL = "base:stone"; -struct block_funcs_set { +struct BlockFuncsSet { bool init : 1; bool update : 1; bool onplaced : 1; @@ -241,7 +241,7 @@ public: std::vector hitboxes[BlockRotProfile::MAX_COUNT]; /// @brief set of block callbacks flags - block_funcs_set funcsset {}; + BlockFuncsSet funcsset {}; /// @brief picking item integer id itemid_t pickingItem = 0; From 43638837280faec985aec9704c9ee9b8ef508811 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Dec 2024 14:09:17 +0300 Subject: [PATCH 18/47] add 'on_breaking', 'on_block_breaking' events --- src/content/ContentPack.hpp | 11 +-- src/logic/PlayerController.cpp | 1 + src/logic/scripting/scripting.cpp | 126 ++++++++++++------------------ src/logic/scripting/scripting.hpp | 3 + src/voxels/Block.hpp | 1 + 5 files changed, 60 insertions(+), 82 deletions(-) diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index 53d8a6e9..e5d69447 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -96,11 +96,12 @@ struct ContentPackStats { }; struct WorldFuncsSet { - bool onblockplaced : 1; - bool onblockreplaced : 1; - bool onblockbroken : 1; - bool onblockinteract : 1; - bool onplayertick : 1; + bool onblockplaced; + bool onblockreplaced; + bool onblockbreaking; + bool onblockbroken; + bool onblockinteract; + bool onplayertick; }; class ContentPackRuntime { diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index d9bc0065..92face2b 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -544,6 +544,7 @@ void PlayerController::updateInteraction(float delta) { } auto& target = indices->blocks.require(vox->id); if (lclick) { + scripting::on_block_breaking(&player, target, iend); if (player.isInstantDestruction() && target.breakable) { blocksController.breakBlock( &player, target, iend.x, iend.y, iend.z diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index d330eebf..96e9f06e 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -336,16 +336,24 @@ void scripting::random_update_block(const Block& block, const glm::ivec3& pos) { }); } -void scripting::on_block_placed( - Player* player, const Block& block, const glm::ivec3& pos +/// TODO: replace template with index +template +static bool on_block_common( + const std::string& suffix, + bool blockfunc, + 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, [pos, player](auto L) { - lua::pushivec_stack(L, pos); - lua::pushinteger(L, player ? player->getId() : -1); - return 4; - }); + bool result = false; + if (blockfunc) { + std::string name = block.name + "." + suffix; + result = + lua::emit_event(lua::get_main_state(), name, [pos, player](auto L) { + lua::pushivec_stack(L, pos); + lua::pushinteger(L, player->getId()); + return 4; + }); } auto args = [&](lua::State* L) { lua::pushinteger(L, block.rt.id); @@ -354,93 +362,53 @@ void scripting::on_block_placed( return 5; }; for (auto& [packid, pack] : content->getPacks()) { - if (pack->worldfuncsset.onblockplaced) { + if (pack->worldfuncsset.*worldfunc) { lua::emit_event( - lua::get_main_state(), packid + ":.blockplaced", args + lua::get_main_state(), packid + ":.block" + suffix, args ); } } + return result; +} + +void scripting::on_block_placed( + Player* player, const Block& block, const glm::ivec3& pos +) { + on_block_common<&WorldFuncsSet::onblockplaced>( + "placed", block.rt.funcsset.onplaced, player, block, pos + ); } void scripting::on_block_replaced( Player* player, const Block& block, const glm::ivec3& pos ) { - if (block.rt.funcsset.onreplaced) { - std::string name = block.name + ".replaced"; - 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 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.onblockreplaced) { - lua::emit_event( - lua::get_main_state(), packid + ":.blockreplaced", args - ); - } - } + on_block_common<&WorldFuncsSet::onblockreplaced>( + "replaced", block.rt.funcsset.onreplaced, player, block, pos + ); +} + +void scripting::on_block_breaking( + Player* player, const Block& block, const glm::ivec3& pos +) { + on_block_common<&WorldFuncsSet::onblockbreaking>( + "breaking", block.rt.funcsset.onbreaking, player, block, pos + ); } void scripting::on_block_broken( 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, - [pos, player](auto L) { - lua::pushivec_stack(L, pos); - lua::pushinteger(L, player ? player->getId() : -1); - 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.onblockbroken) { - lua::emit_event( - lua::get_main_state(), packid + ":.blockbroken", args - ); - } - } + on_block_common<&WorldFuncsSet::onblockbroken>( + "broken", block.rt.funcsset.onbroken, player, block, pos + ); } bool scripting::on_block_interact( Player* player, const Block& block, const glm::ivec3& pos ) { - std::string name = block.name + ".interact"; - auto result = lua::emit_event(lua::get_main_state(), name, [pos, player](auto L) { - lua::pushivec_stack(L, pos); - 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 - ); - } - } - return result; + return on_block_common<&WorldFuncsSet::onblockinteract>( + "interact", block.rt.funcsset.oninteract, player, block, pos + ); } void scripting::on_player_tick(Player* player, int tps) { @@ -804,6 +772,8 @@ void scripting::load_content_script( funcsset.update = register_event(env, "on_update", prefix + ".update"); funcsset.randupdate = register_event(env, "on_random_update", prefix + ".randupdate"); + funcsset.onbreaking = + register_event(env, "on_breaking", prefix + ".breaking"); funcsset.onbroken = register_event(env, "on_broken", prefix + ".broken"); funcsset.onplaced = register_event(env, "on_placed", prefix + ".placed"); funcsset.onreplaced = @@ -857,6 +827,8 @@ void scripting::load_world_script( register_event(env, "on_world_quit", prefix + ":.worldquit"); funcsset.onblockplaced = register_event(env, "on_block_placed", prefix + ":.blockplaced"); + funcsset.onblockbreaking = + register_event(env, "on_block_breaking", prefix + ":.blockbreaking"); funcsset.onblockbroken = register_event(env, "on_block_broken", prefix + ":.blockbroken"); funcsset.onblockreplaced = diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index 6bb31355..fb552f66 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -77,6 +77,9 @@ namespace scripting { void on_block_replaced( Player* player, const Block& block, const glm::ivec3& pos ); + void on_block_breaking( + Player* player, const Block& block, const glm::ivec3& pos + ); void on_block_broken( Player* player, const Block& block, const glm::ivec3& pos ); diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 8ea11bee..83dafa47 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -38,6 +38,7 @@ struct BlockFuncsSet { bool init : 1; bool update : 1; bool onplaced : 1; + bool onbreaking : 1; bool onbroken : 1; bool onreplaced : 1; bool oninteract : 1; From 2b64128581708c03f34c40d90ff56a4fd6114faa Mon Sep 17 00:00:00 2001 From: Onran <100285264+Onran0@users.noreply.github.com> Date: Sun, 22 Dec 2024 01:54:55 +0900 Subject: [PATCH 19/47] Update stdmin.lua --- res/scripts/stdmin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 72383dce..5b93fa2f 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -1,6 +1,6 @@ -- Check if given table is an array function is_array(x) - if #t > 0 then + if #x > 0 then return true end for k, v in pairs(x) do From 4ce2f3edcaf0cbe5eca144288e5664cf685203e8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 22 Dec 2024 02:14:04 +0300 Subject: [PATCH 20/47] add new Bytearray:append overloads --- src/logic/scripting/lua/libs/libfile.cpp | 27 +++---------------- src/logic/scripting/lua/lua_util.hpp | 22 +++++++++++++++ .../lua/usertypes/lua_type_bytearray.cpp | 13 +++++++-- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index a27ac949..a38081c9 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -149,27 +149,6 @@ static int l_read_bytes(lua::State* L) { ); } -static void read_bytes_from_table( - lua::State* L, int tableIndex, std::vector& bytes -) { - if (!lua::istable(L, tableIndex)) { - throw std::runtime_error("table expected"); - } else { - size_t size = lua::objlen(L, tableIndex); - for (size_t i = 0; i < size; i++) { - lua::rawgeti(L, i + 1, tableIndex); - const int byte = lua::tointeger(L, -1); - lua::pop(L); - if (byte < 0 || byte > 255) { - throw std::runtime_error( - "invalid byte '" + std::to_string(byte) + "'" - ); - } - bytes.push_back(byte); - } - } -} - static int l_write_bytes(lua::State* L) { fs::path path = get_writeable_path(L); @@ -181,7 +160,7 @@ static int l_write_bytes(lua::State* L) { } std::vector bytes; - read_bytes_from_table(L, 2, bytes); + lua::read_bytes_from_table(L, 2, bytes); return lua::pushboolean( L, files::write_bytes(path, bytes.data(), bytes.size()) ); @@ -223,7 +202,7 @@ static int l_list(lua::State* L) { static int l_gzip_compress(lua::State* L) { std::vector bytes; - read_bytes_from_table(L, 1, bytes); + lua::read_bytes_from_table(L, 1, bytes); auto compressed_bytes = gzip::compress(bytes.data(), bytes.size()); int newTable = lua::gettop(L); @@ -237,7 +216,7 @@ static int l_gzip_compress(lua::State* L) { static int l_gzip_decompress(lua::State* L) { std::vector bytes; - read_bytes_from_table(L, 1, bytes); + lua::read_bytes_from_table(L, 1, bytes); auto decompressed_bytes = gzip::decompress(bytes.data(), bytes.size()); int newTable = lua::gettop(L); diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index 983abb39..f9da3b21 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "data/dv.hpp" @@ -698,4 +699,25 @@ namespace lua { } return def; } + + inline void read_bytes_from_table( + lua::State* L, int tableIndex, std::vector& bytes + ) { + if (!lua::istable(L, tableIndex)) { + throw std::runtime_error("table expected"); + } else { + size_t size = lua::objlen(L, tableIndex); + for (size_t i = 0; i < size; i++) { + lua::rawgeti(L, i + 1, tableIndex); + const int byte = lua::tointeger(L, -1); + lua::pop(L); + if (byte < 0 || byte > 255) { + throw std::runtime_error( + "invalid byte '" + std::to_string(byte) + "'" + ); + } + bytes.push_back(byte); + } + } + } } diff --git a/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp b/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp index 0493995b..c982d2d8 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp @@ -2,6 +2,7 @@ #include +#include "util/listutil.hpp" #include "../lua_util.hpp" using namespace lua; @@ -18,8 +19,16 @@ LuaBytearray::~LuaBytearray() { static int l_append(lua::State* L) { if (auto buffer = touserdata(L, 1)) { - auto value = tointeger(L, 2); - buffer->data().push_back(static_cast(value)); + if (lua::isnumber(L, 2)) { + auto value = tointeger(L, 2); + buffer->data().push_back(static_cast(value)); + } else if (lua::istable(L, 2)) { + lua::read_bytes_from_table(L, 2, buffer->data()); + } else if (auto extension = lua::touserdata(L, 2)) { + util::concat(buffer->data(), extension->data()); + } else { + throw std::runtime_error("integer/table/Bytearray expected"); + } } return 0; } From 212cc486d4f2e7aa970cc40c727fb417d192e737 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 22 Dec 2024 02:22:00 +0300 Subject: [PATCH 21/47] optimize data_buffer:put_bytes for Bytearray --- res/modules/data_buffer.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/res/modules/data_buffer.lua b/res/modules/data_buffer.lua index e3d207ff..67214835 100644 --- a/res/modules/data_buffer.lua +++ b/res/modules/data_buffer.lua @@ -72,9 +72,14 @@ function data_buffer:put_byte(byte) end function data_buffer:put_bytes(bytes) - for i = 1, #bytes do - self:put_byte(bytes[i]) - end + if type(self.bytes) == 'table' then + for i = 1, #bytes do + self:put_byte(bytes[i]) + end + else + self.bytes:append(bytes) + self.pos = self.pos + #bytes + end end function data_buffer:put_single(single) @@ -308,4 +313,4 @@ end setmetatable(data_buffer, data_buffer) -return data_buffer \ No newline at end of file +return data_buffer From d6ccdf98717a9152311f580f128d5e3dbb8710de Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 22 Dec 2024 02:27:00 +0300 Subject: [PATCH 22/47] add new Bytearray:insert overloads --- .../lua/usertypes/lua_type_bytearray.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp b/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp index c982d2d8..fc7ecf6f 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_bytearray.cpp @@ -43,8 +43,19 @@ static int l_insert(lua::State* L) { if (static_cast(index) > data.size()) { return 0; } - auto value = tointeger(L, 3); - data.insert(data.begin() + index, static_cast(value)); + if (lua::isnumber(L, 3)) { + auto value = tointeger(L, 3); + data.insert(data.begin() + index, static_cast(value)); + } else if (lua::istable(L, 3)) { + std::vector temp; + lua::read_bytes_from_table(L, 3, temp); + data.insert(data.begin() + index, temp.begin(), temp.end()); + } else if (auto extension = lua::touserdata(L, 3)) { + const std::vector& src = extension->data(); + data.insert(data.begin() + index, src.begin(), src.end()); + } else { + throw std::runtime_error("integer/table/Bytearray expected"); + } return 0; } From c9b69fdfb2b04b66d54ebea2efc57accda512cca Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 22 Dec 2024 02:32:00 +0300 Subject: [PATCH 23/47] fix data_buffer:put_bytes --- res/modules/data_buffer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/modules/data_buffer.lua b/res/modules/data_buffer.lua index 67214835..91dce29c 100644 --- a/res/modules/data_buffer.lua +++ b/res/modules/data_buffer.lua @@ -77,7 +77,7 @@ function data_buffer:put_bytes(bytes) self:put_byte(bytes[i]) end else - self.bytes:append(bytes) + self.bytes:insert(self.pos, bytes) self.pos = self.pos + #bytes end end From 240470f69b2d459cd71a1f6aea080598e2632095 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 22 Dec 2024 02:49:10 +0300 Subject: [PATCH 24/47] add new ore creation to the world-generator docs --- doc/en/world-generator.md | 22 ++++++++++++++++++++++ doc/ru/world-generator.md | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/doc/en/world-generator.md b/doc/en/world-generator.md index b0ab265c..40fd1b37 100644 --- a/doc/en/world-generator.md +++ b/doc/en/world-generator.md @@ -27,6 +27,7 @@ * [Small structures placement](#small-structures-placement) * [Wide structures placement](#wide-structures-placement) - [Structural air](#structural-air) +- [Generator 'Demo' (base:demo)](#generator-demo-basedemo) ## Basic concepts @@ -473,3 +474,24 @@ function place_structures_wide( `core:struct_air` - a block that should be used in chunks to mark empty space that should not be filled with blocks when generated in the world. + +# Generator 'Demo' (base:demo) + +## Adding new ore + +To add a new ore in your pack: +1. In the `generators` folder, create a `demo.files` folder (you don't need to create demo.toml). + +2. In the created folder, create a fragments folder and place the ore fragment file in it. +3. In `demo.files`, create a structures.toml file: +```toml +fragment_name = {} +``` +4. Also in `demo.files`, create an ores.json file: +```json +[ + {"struct": "fragment_name", "rarity": rarity} +] +``` +The higher the rarity value, the less ore generation chance. +You can rely on the rarity of coal ore: 4400. diff --git a/doc/ru/world-generator.md b/doc/ru/world-generator.md index 5c1c6e6e..7f7be5c4 100644 --- a/doc/ru/world-generator.md +++ b/doc/ru/world-generator.md @@ -27,6 +27,7 @@ * [Расстановка малых структур](#расстановка-малых-структур) * [Расстановка 'широких' структур](#расстановка-широких-структур) - [Структурный воздух](#структурный-воздух) +- [Генератор 'Demo' (base:demo)](#генератор-demo-basedemo) ## Основные понятия @@ -478,3 +479,23 @@ function place_structures_wide( `core:struct_air` - блок, которые следует использовать в фрагментах для обозначения пустого пространства, которое не должно заполняться блоками при генерации в мире. + +# Генератор 'Demo' (base:demo) + +## Добавление новой руды + +Чтобы добавить новую руду из своего пака: +1. В папке `generators` создайте папку `demo.files` (demo.toml создавать не нужно). +2. В созданной папке создайте папку fragments и поместите в неё файл фрагмента руды. +3. В `demo.files` создайте файл structures.toml: +```toml +имя_фрагмента = {} +``` +4. Также в `demo.files` создайте файл ores.json: +```json +[ + {"struct": "имя_фрагмента", "rarity": редкость} +] +``` +Чем выше значение редкости, тем меньше вероятность генерации руды. +Опираться можно на редкость угольной руды: 4400. From 22d207ba28c24cc59f93b4f1d4fe0d6e44926d83 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 12:24:29 +0300 Subject: [PATCH 25/47] add player.set_selected_slot, inventory.find_by_item --- doc/en/scripting/builtins/libinventory.md | 15 +++ doc/en/scripting/builtins/libplayer.md | 6 + doc/ru/scripting/builtins/libinventory.md | 15 +++ doc/ru/scripting/builtins/libplayer.md | 6 + src/logic/scripting/lua/libs/libinventory.cpp | 120 ++++++++++-------- src/logic/scripting/lua/libs/libplayer.cpp | 8 ++ 6 files changed, 115 insertions(+), 55 deletions(-) diff --git a/doc/en/scripting/builtins/libinventory.md b/doc/en/scripting/builtins/libinventory.md index ccb7be20..a3f3632f 100644 --- a/doc/en/scripting/builtins/libinventory.md +++ b/doc/en/scripting/builtins/libinventory.md @@ -32,6 +32,21 @@ inventory.size(invid: int) -> int -- Returns remaining count if could not to add fully. inventory.add(invid: int, itemid: int, count: int) -> int +-- Returns the index of the first matching slot in the given range. +-- If no matching slot was found, returns nil +inventory.find_by_item( + -- inventory id + invid: int, + -- item id + itemid: int, + -- [optional] index of the slot range start (from 0) + range_begin: int, + -- [optional] index of the slot range end (from 0) + range_end: int, + -- [optional] minimum item count in the slot + min_count: int = 1 +) -> int + -- Returns block inventory ID or 0. inventory.get_block(x: int, y: int, z: int) -> int diff --git a/doc/en/scripting/builtins/libplayer.md b/doc/en/scripting/builtins/libplayer.md index b43bf860..3bff1547 100644 --- a/doc/en/scripting/builtins/libplayer.md +++ b/doc/en/scripting/builtins/libplayer.md @@ -84,6 +84,12 @@ player.get_name(playerid: int) -> str Player name setter and getter +```lua +player.set_selected_slot(playerid: int, slotid: int) +``` + +Sets the selected slot index + ```lua player.get_selected_block(playerid: int) -> x,y,z ``` diff --git a/doc/ru/scripting/builtins/libinventory.md b/doc/ru/scripting/builtins/libinventory.md index 7f3cf26e..a01bd917 100644 --- a/doc/ru/scripting/builtins/libinventory.md +++ b/doc/ru/scripting/builtins/libinventory.md @@ -38,6 +38,21 @@ inventory.add( count: int ) -> int +-- Возвращает индекс первого подходящего под критерии слота в заданном диапазоне. +-- Если подходящий слот не был найден, возвращает nil +inventory.find_by_item( + -- id инвентаря + invid: int, + -- id предмета + itemid: int, + -- [опционально] индекс начала диапазона слотов (c 0) + range_begin: int, + -- [опционально] индекс конца диапазона слотов (c 0) + range_end: int, + -- [опционально] минимальное количество предмета в слоте + min_count: int = 1 +) -> int + -- Функция возвращает id инвентаря блока. -- Если блок не может иметь инвентарь - возвращает 0. inventory.get_block(x: int, y: int, z: int) -> int diff --git a/doc/ru/scripting/builtins/libplayer.md b/doc/ru/scripting/builtins/libplayer.md index 284f725a..d4912e61 100644 --- a/doc/ru/scripting/builtins/libplayer.md +++ b/doc/ru/scripting/builtins/libplayer.md @@ -84,6 +84,12 @@ player.get_name(playerid: int) -> str Сеттер и геттер имени игрока +```lua +player.set_selected_slot(playerid: int, slotid: int) +``` + +Устанавливает индекс выбранного слота + ```lua player.get_selected_block(playerid: int) -> x,y,z ``` diff --git a/src/logic/scripting/lua/libs/libinventory.cpp b/src/logic/scripting/lua/libs/libinventory.cpp index 8f1f5385..65f0dd7c 100644 --- a/src/logic/scripting/lua/libs/libinventory.cpp +++ b/src/logic/scripting/lua/libs/libinventory.cpp @@ -13,15 +13,15 @@ static void validate_itemid(itemid_t id) { } } -static std::shared_ptr get_inventory(int64_t id) { +static Inventory& get_inventory(int64_t id) { auto inv = level->inventories->get(id); if (inv == nullptr) { throw std::runtime_error("inventory not found: " + std::to_string(id)); } - return inv; + return *inv; } -static std::shared_ptr get_inventory(int64_t id, int arg) { +static Inventory& get_inventory(int64_t id, int arg) { auto inv = level->inventories->get(id); if (inv == nullptr) { throw std::runtime_error( @@ -29,62 +29,62 @@ static std::shared_ptr get_inventory(int64_t id, int arg) { std::to_string(arg) ); } - return inv; + return *inv; } -static void validate_slotid(int slotid, Inventory* inv) { - if (static_cast(slotid) >= inv->size()) { +static void validate_slotid(int slotid, const Inventory& inv) { + if (static_cast(slotid) >= inv.size()) { throw std::runtime_error( "slot index is out of range [0..inventory.size(invid)]" ); } } -static int l_inventory_get(lua::State* L) { +static int l_get(lua::State* L) { auto invid = lua::tointeger(L, 1); auto slotid = lua::tointeger(L, 2); auto inv = get_inventory(invid); - validate_slotid(slotid, inv.get()); - const ItemStack& item = inv->getSlot(slotid); + validate_slotid(slotid, inv); + const ItemStack& item = inv.getSlot(slotid); lua::pushinteger(L, item.getItemId()); lua::pushinteger(L, item.getCount()); return 2; } -static int l_inventory_set(lua::State* L) { +static int l_set(lua::State* L) { auto invid = lua::tointeger(L, 1); auto slotid = lua::tointeger(L, 2); auto itemid = lua::tointeger(L, 3); auto count = lua::tointeger(L, 4); validate_itemid(itemid); - auto inv = get_inventory(invid); + auto& inv = get_inventory(invid); - validate_slotid(slotid, inv.get()); - ItemStack& item = inv->getSlot(slotid); + validate_slotid(slotid, inv); + ItemStack& item = inv.getSlot(slotid); item.set(ItemStack(itemid, count)); return 0; } -static int l_inventory_size(lua::State* L) { +static int l_size(lua::State* L) { auto invid = lua::tointeger(L, 1); - auto inv = get_inventory(invid); - return lua::pushinteger(L, inv->size()); + auto& inv = get_inventory(invid); + return lua::pushinteger(L, inv.size()); } -static int l_inventory_add(lua::State* L) { +static int l_add(lua::State* L) { auto invid = lua::tointeger(L, 1); auto itemid = lua::tointeger(L, 2); auto count = lua::tointeger(L, 3); validate_itemid(itemid); - auto inv = get_inventory(invid); + auto& inv = get_inventory(invid); ItemStack item(itemid, count); - inv->move(item, indices); + inv.move(item, indices); return lua::pushinteger(L, item.getCount()); } -static int l_inventory_get_block(lua::State* L) { +static int l_get_block(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); @@ -92,7 +92,7 @@ static int l_inventory_get_block(lua::State* L) { return lua::pushinteger(L, id); } -static int l_inventory_bind_block(lua::State* L) { +static int l_bind_block(lua::State* L) { auto id = lua::tointeger(L, 1); auto x = lua::tointeger(L, 2); auto y = lua::tointeger(L, 3); @@ -101,7 +101,7 @@ static int l_inventory_bind_block(lua::State* L) { return 0; } -static int l_inventory_unbind_block(lua::State* L) { +static int l_unbind_block(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); @@ -109,7 +109,7 @@ static int l_inventory_unbind_block(lua::State* L) { return 0; } -static int l_inventory_create(lua::State* L) { +static int l_create(lua::State* L) { auto invsize = lua::tointeger(L, 1); auto inv = level->inventories->create(invsize); if (inv == nullptr) { @@ -118,18 +118,13 @@ static int l_inventory_create(lua::State* L) { return lua::pushinteger(L, inv->getId()); } -static int l_inventory_remove(lua::State* L) { +static int l_remove(lua::State* L) { auto invid = lua::tointeger(L, 1); - auto inv = get_inventory(invid); - if (inv == nullptr) { - return 0; - } - level->inventories->remove(invid); return 0; } -static int l_inventory_clone(lua::State* L) { +static int l_clone(lua::State* L) { auto id = lua::tointeger(L, 1); auto clone = level->inventories->clone(id); if (clone == nullptr) { @@ -138,54 +133,69 @@ static int l_inventory_clone(lua::State* L) { return lua::pushinteger(L, clone->getId()); } -static int l_inventory_move(lua::State* L) { +static int l_move(lua::State* L) { auto invAid = lua::tointeger(L, 1); auto slotAid = lua::tointeger(L, 2); - auto invA = get_inventory(invAid, 1); - validate_slotid(slotAid, invA.get()); + auto& invA = get_inventory(invAid, 1); + validate_slotid(slotAid, invA); auto invBid = lua::tointeger(L, 3); auto slotBid = lua::isnil(L, 4) ? -1 : lua::tointeger(L, 4); - auto invB = get_inventory(invBid, 3); - auto& slot = invA->getSlot(slotAid); + auto& invB = get_inventory(invBid, 3); + auto& slot = invA.getSlot(slotAid); if (slotBid == -1) { - invB->move(slot, content->getIndices()); + invB.move(slot, content->getIndices()); } else { - invB->move(slot, content->getIndices(), slotBid, slotBid + 1); + invB.move(slot, content->getIndices(), slotBid, slotBid + 1); } return 0; } -static int l_inventory_move_range(lua::State* L) { +static int l_move_range(lua::State* L) { auto invAid = lua::tointeger(L, 1); auto slotAid = lua::tointeger(L, 2); - auto invA = get_inventory(invAid, 1); - validate_slotid(slotAid, invA.get()); + auto& invA = get_inventory(invAid, 1); + validate_slotid(slotAid, invA); auto invBid = lua::tointeger(L, 3); auto slotBegin = lua::isnoneornil(L, 4) ? -1 : lua::tointeger(L, 4); auto slotEnd = lua::isnoneornil(L, 5) ? -1 : lua::tointeger(L, 5) + 1; auto invB = get_inventory(invBid, 3); - auto& slot = invA->getSlot(slotAid); + auto& slot = invA.getSlot(slotAid); if (slotBegin == -1) { - invB->move(slot, content->getIndices()); + invB.move(slot, content->getIndices()); } else { - invB->move(slot, content->getIndices(), slotBegin, slotEnd); + invB.move(slot, content->getIndices(), slotBegin, slotEnd); } return 0; } +static int l_find_by_item(lua::State* L) { + auto invId = lua::tointeger(L, 1); + auto& inv = get_inventory(invId, 1); + integer_t blockid = lua::tointeger(L, 2); + integer_t begin = lua::isnumber(L, 3) ? lua::tointeger(L, 3) : 0; + integer_t end = lua::isnumber(L, 4) ? lua::tointeger(L, 4) : -1; + integer_t minCount = lua::isnumber(L, 5) ? lua::tointeger(L, 5) : blockid != 0; + size_t index = inv.findSlotByItem(blockid, begin, end, minCount); + if (index == Inventory::npos) { + return 0; + } + return lua::pushinteger(L, index); +} + const luaL_Reg inventorylib[] = { - {"get", lua::wrap}, - {"set", lua::wrap}, - {"size", lua::wrap}, - {"add", lua::wrap}, - {"move", lua::wrap}, - {"move_range", lua::wrap}, - {"get_block", lua::wrap}, - {"bind_block", lua::wrap}, - {"unbind_block", lua::wrap}, - {"create", lua::wrap}, - {"remove", lua::wrap}, - {"clone", lua::wrap}, + {"get", lua::wrap}, + {"set", lua::wrap}, + {"size", lua::wrap}, + {"add", lua::wrap}, + {"move", lua::wrap}, + {"move_range", lua::wrap}, + {"find_by_item", lua::wrap}, + {"get_block", lua::wrap}, + {"bind_block", lua::wrap}, + {"unbind_block", lua::wrap}, + {"create", lua::wrap}, + {"remove", lua::wrap}, + {"clone", lua::wrap}, {NULL, NULL}}; diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index 00c4585d..12905e01 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -101,6 +101,13 @@ static int l_get_inv(lua::State* L) { return 2; } +static int l_set_selected_slot(lua::State* L) { + if (auto player = get_player(L, 1)) { + player->setChosenSlot(lua::tointeger(L, 2) % 10); + } + return 0; +} + static int l_is_flight(lua::State* L) { if (auto player = get_player(L, 1)) { return lua::pushboolean(L, player->isFlight()); @@ -275,6 +282,7 @@ const luaL_Reg playerlib[] = { {"set_infinite_items", lua::wrap}, {"is_instant_destruction", lua::wrap}, {"set_instant_destruction", lua::wrap}, + {"set_selected_slot", lua::wrap}, {"get_selected_block", lua::wrap}, {"get_selected_entity", lua::wrap}, {"set_spawnpoint", lua::wrap}, From 9164edf9714d929a106e15627d950dc66f0eb351 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 12:37:26 +0300 Subject: [PATCH 26/47] move 'player.pick' binding handler to Lua --- res/content/base/scripts/hud.lua | 26 ++++++++++++++++++++++++++ res/scripts/stdlib.lua | 1 - src/core_defs.hpp | 1 - src/items/Inventory.cpp | 7 +++++-- src/items/Inventory.hpp | 4 +++- src/logic/PlayerController.cpp | 26 -------------------------- 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/res/content/base/scripts/hud.lua b/res/content/base/scripts/hud.lua index 31125631..a3df0849 100644 --- a/res/content/base/scripts/hud.lua +++ b/res/content/base/scripts/hud.lua @@ -23,4 +23,30 @@ function on_hud_open() local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL)) drop.rigidbody:set_vel(velocity) end) + input.add_callback("player.pick", function () + if hud.is_paused() or hud.is_inventory_open() then + return + end + local pid = hud.get_player() + local x, y, z = player.get_selected_block(pid) + if x == nil then + return + end + local id = block.get_picking_item(block.get(x, y, z)) + local inv, cur_slot = player.get_inventory(pid) + local slot = inventory.find_by_item(inv, id, 0, 9) + if slot then + player.set_selected_slot(pid, slot) + return + end + if not rules.get("allow-content-access") then + return + end + slot = inventory.find_by_item(inv, 0, 0, 9) + if slot then + cur_slot = slot + end + player.set_selected_slot(pid, cur_slot) + inventory.set(inv, cur_slot, id, 1) + end) end diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index aa56bc31..0a49ccd1 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -320,7 +320,6 @@ function __vc_on_hud_open() _rules.create("allow-content-access", hud._is_content_access(), function(value) hud._set_content_access(value) - input.set_enabled("player.pick", value) end) _rules.create("allow-flight", true, function(value) input.set_enabled("player.flight", value) diff --git a/src/core_defs.hpp b/src/core_defs.hpp index 38160dac..60f9ec79 100644 --- a/src/core_defs.hpp +++ b/src/core_defs.hpp @@ -26,7 +26,6 @@ inline const std::string BIND_PLAYER_FLIGHT = "player.flight"; inline const std::string BIND_PLAYER_ATTACK = "player.attack"; inline const std::string BIND_PLAYER_DESTROY = "player.destroy"; inline const std::string BIND_PLAYER_BUILD = "player.build"; -inline const std::string BIND_PLAYER_PICK = "player.pick"; inline const std::string BIND_PLAYER_FAST_INTERACTOIN = "player.fast_interaction"; inline const std::string BIND_HUD_INVENTORY = "hud.inventory"; diff --git a/src/items/Inventory.cpp b/src/items/Inventory.cpp index 00c5589e..9797a15e 100644 --- a/src/items/Inventory.cpp +++ b/src/items/Inventory.cpp @@ -23,10 +23,13 @@ size_t Inventory::findEmptySlot(size_t begin, size_t end) const { return npos; } -size_t Inventory::findSlotByItem(itemid_t id, size_t begin, size_t end) { +size_t Inventory::findSlotByItem( + itemid_t id, size_t begin, size_t end, size_t minCount +) { end = std::min(slots.size(), end); for (size_t i = begin; i < end; i++) { - if (slots[i].getItemId() == id) { + const auto& stack = slots[i]; + if (stack.getItemId() == id && stack.getCount() >= minCount) { return i; } } diff --git a/src/items/Inventory.hpp b/src/items/Inventory.hpp index 176ad7ee..49560523 100644 --- a/src/items/Inventory.hpp +++ b/src/items/Inventory.hpp @@ -22,7 +22,9 @@ public: ItemStack& getSlot(size_t index); size_t findEmptySlot(size_t begin = 0, size_t end = -1) const; - size_t findSlotByItem(itemid_t id, size_t begin = 0, size_t end = -1); + size_t findSlotByItem( + itemid_t id, size_t begin = 0, size_t end = -1, size_t minCount = 1 + ); inline size_t size() const { return slots.size(); diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 92face2b..f26b5395 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -341,28 +341,6 @@ static int determine_rotation( return 0; } -static void pick_block( - ContentIndices* indices, - const Block& block, - Player& player, - int x, - int y, - int z -) { - itemid_t id = block.rt.pickingItem; - auto inventory = player.getInventory(); - size_t slotid = inventory->findSlotByItem(id, 0, 10); - if (slotid == Inventory::npos) { - slotid = player.getChosenSlot(); - } else { - player.setChosenSlot(slotid); - } - ItemStack& stack = inventory->getSlot(slotid); - if (stack.getItemId() != id) { - stack.set(ItemStack(id, 1)); - } -} - voxel* PlayerController::updateSelection(float maxDistance) { auto indices = level.content->getIndices(); auto& chunks = *player.chunks; @@ -568,10 +546,6 @@ void PlayerController::updateInteraction(float delta) { if (def && rclick) { processRightClick(*def, target); } - if (Events::jactive(BIND_PLAYER_PICK)) { - auto coord = selection.actualPosition; - pick_block(indices, target, player, coord.x, coord.y, coord.z); - } } Player* PlayerController::getPlayer() { From 3d33de502d674bb641b6a6405677b658640a1f1d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 13:51:12 +0300 Subject: [PATCH 27/47] move 'player.noclip' and 'player.flight' handlers to Lua --- res/content/base/scripts/hud.lua | 26 -------------- res/scripts/hud.lua | 58 ++++++++++++++++++++++++++++++++ src/core_defs.hpp | 2 -- src/logic/PlayerController.cpp | 2 -- src/objects/Player.cpp | 11 ------ src/objects/Player.hpp | 2 -- 6 files changed, 58 insertions(+), 43 deletions(-) create mode 100644 res/scripts/hud.lua diff --git a/res/content/base/scripts/hud.lua b/res/content/base/scripts/hud.lua index a3df0849..31125631 100644 --- a/res/content/base/scripts/hud.lua +++ b/res/content/base/scripts/hud.lua @@ -23,30 +23,4 @@ function on_hud_open() local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL)) drop.rigidbody:set_vel(velocity) end) - input.add_callback("player.pick", function () - if hud.is_paused() or hud.is_inventory_open() then - return - end - local pid = hud.get_player() - local x, y, z = player.get_selected_block(pid) - if x == nil then - return - end - local id = block.get_picking_item(block.get(x, y, z)) - local inv, cur_slot = player.get_inventory(pid) - local slot = inventory.find_by_item(inv, id, 0, 9) - if slot then - player.set_selected_slot(pid, slot) - return - end - if not rules.get("allow-content-access") then - return - end - slot = inventory.find_by_item(inv, 0, 0, 9) - if slot then - cur_slot = slot - end - player.set_selected_slot(pid, cur_slot) - inventory.set(inv, cur_slot, id, 1) - end) end diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua new file mode 100644 index 00000000..093d43c3 --- /dev/null +++ b/res/scripts/hud.lua @@ -0,0 +1,58 @@ +function on_hud_open() + input.add_callback("player.pick", function () + if hud.is_paused() or hud.is_inventory_open() then + return + end + local pid = hud.get_player() + local x, y, z = player.get_selected_block(pid) + if x == nil then + return + end + local id = block.get_picking_item(block.get(x, y, z)) + local inv, cur_slot = player.get_inventory(pid) + local slot = inventory.find_by_item(inv, id, 0, 9) + if slot then + player.set_selected_slot(pid, slot) + return + end + if not rules.get("allow-content-access") then + return + end + slot = inventory.find_by_item(inv, 0, 0, 9) + if slot then + cur_slot = slot + end + player.set_selected_slot(pid, cur_slot) + inventory.set(inv, cur_slot, id, 1) + end) + + input.add_callback("player.noclip", function () + if hud.is_paused() or hud.is_inventory_open() then + return + end + local pid = hud.get_player() + if player.is_noclip(pid) then + player.set_flight(pid, false) + player.set_noclip(pid, false) + else + player.set_flight(pid, true) + player.set_noclip(pid, true) + end + end) + + input.add_callback("player.flight", function () + if hud.is_paused() or hud.is_inventory_open() then + return + end + local pid = hud.get_player() + if player.is_noclip(pid) then + return + end + if player.is_flight(pid) then + player.set_flight(pid, false) + else + player.set_flight(pid, true) + player.set_vel(pid, 0, 1, 0) + end + end) +end diff --git a/src/core_defs.hpp b/src/core_defs.hpp index 60f9ec79..8042ca36 100644 --- a/src/core_defs.hpp +++ b/src/core_defs.hpp @@ -21,8 +21,6 @@ inline const std::string BIND_MOVE_CROUCH = "movement.crouch"; inline const std::string BIND_MOVE_CHEAT = "movement.cheat"; inline const std::string BIND_CAM_ZOOM = "camera.zoom"; inline const std::string BIND_CAM_MODE = "camera.mode"; -inline const std::string BIND_PLAYER_NOCLIP = "player.noclip"; -inline const std::string BIND_PLAYER_FLIGHT = "player.flight"; inline const std::string BIND_PLAYER_ATTACK = "player.attack"; inline const std::string BIND_PLAYER_DESTROY = "player.destroy"; inline const std::string BIND_PLAYER_BUILD = "player.build"; diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index f26b5395..44d1a64c 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -288,8 +288,6 @@ void PlayerController::updateKeyboard() { input.jump = Events::active(BIND_MOVE_JUMP); input.zoom = Events::active(BIND_CAM_ZOOM); input.cameraMode = Events::jactive(BIND_CAM_MODE); - input.noclip = Events::jactive(BIND_PLAYER_NOCLIP); - input.flight = Events::jactive(BIND_PLAYER_FLIGHT); } void PlayerController::resetKeyboard() { diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 0a2106ed..d5493a6e 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -135,18 +135,7 @@ void Player::updateInput(PlayerInput& input, float delta) { hitbox->velocity.y = JUMP_FORCE; } - if ((input.flight && !noclip) || (input.noclip && flight == noclip)) { - flight = !flight; - if (flight) { - hitbox->velocity.y += 1.0f; - } - } hitbox->type = noclip ? BodyType::KINEMATIC : BodyType::DYNAMIC; - if (input.noclip) { - noclip = !noclip; - } - input.noclip = false; - input.flight = false; } void Player::updateSelectedEntity() { diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 1f57c6f7..55f824d6 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -27,8 +27,6 @@ struct PlayerInput { bool shift : 1; bool cheat : 1; bool jump : 1; - bool noclip : 1; - bool flight : 1; }; struct CursorSelection { From 6a8afe2795cbd1332367b101f47db6efac1d3823 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 14:01:35 +0300 Subject: [PATCH 28/47] fix --- src/logic/LevelController.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index 725a8b77..6e7fcca6 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -47,9 +47,7 @@ LevelController::LevelController( ); chunks->update(16, 1, 0, *player); if (player->chunks->get( - std::floor(position.x), - std::floor(position.y), - std::floor(position.z) + std::floor(position.x), 0, std::floor(position.z) )) { confirmed++; } From 096092303fc5ec41bcb6bf149c94cc2a817cec76 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 14:07:59 +0300 Subject: [PATCH 29/47] add 'graphics.chunk-max-vertices-dense' setting --- src/files/settings_io.cpp | 1 + src/graphics/render/ChunksRenderer.cpp | 19 +++++++++++++------ src/settings.hpp | 2 ++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index fe251a11..f5f1341b 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -73,6 +73,7 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { builder.add("frustum-culling", &settings.graphics.frustumCulling); builder.add("skybox-resolution", &settings.graphics.skyboxResolution); builder.add("chunk-max-vertices", &settings.graphics.chunkMaxVertices); + builder.add("chunk-max-vertices-dense", &settings.graphics.chunkMaxVerticesDense); builder.add("chunk-max-renderers", &settings.graphics.chunkMaxRenderers); builder.section("ui"); diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index fe955bee..f1406ad1 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -24,15 +24,22 @@ class RendererWorker : public util::Worker, RendererResul BlocksRenderer renderer; public: RendererWorker( - const Level& level, + const Level& level, const Chunks& chunks, const ContentGfxCache& cache, const EngineSettings& settings - ) : level(level), - chunks(chunks), - renderer(settings.graphics.chunkMaxVertices.get(), - *level.content, cache, settings) - {} + ) + : level(level), + chunks(chunks), + renderer( + settings.graphics.denseRender.get() + ? settings.graphics.chunkMaxVerticesDense.get() + : settings.graphics.chunkMaxVertices.get(), + *level.content, + cache, + settings + ) { + } RendererResult operator()(const std::shared_ptr& chunk) override { renderer.build(chunk.get(), &chunks); diff --git a/src/settings.hpp b/src/settings.hpp index 48d72b27..53ebf5f9 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -71,6 +71,8 @@ struct GraphicsSettings { IntegerSetting skyboxResolution {64 + 32, 64, 128}; /// @brief Chunk renderer vertices buffer capacity IntegerSetting chunkMaxVertices {200'000, 0, 4'000'000}; + /// @brief Chunk renderer vertices buffer capacity in dense render mode + IntegerSetting chunkMaxVerticesDense {800'000, 0, 8'000'000}; /// @brief Limit of chunk renderers count IntegerSetting chunkMaxRenderers {6, -4, 32}; }; From 90b1f63406d7d9d2488e6b8c86cdff1fcb939411 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 14:13:45 +0300 Subject: [PATCH 30/47] update leaves texture & update mip-mapping settings --- res/content/base/textures/blocks/leaves.png | Bin 911 -> 899 bytes src/graphics/core/GLTexture.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/res/content/base/textures/blocks/leaves.png b/res/content/base/textures/blocks/leaves.png index 60b1fe36d2a663765a0b67ba6d17493685c93dbd..46b38d224dd95be5feab37d8e7156006c69a4f68 100644 GIT binary patch delta 876 zcmV-y1C#uZ2ZINYB!5atL_t(|oJCVjZyQwM z6hxb<3y=^CgoI#&5F36A8^o@Fija^Hut1=Oq^htAZ9`2yl&ZB;+O$q=*Ky*>`1|AX zJfZ26uI9a&bMHI%o--1}Qb+wfG2w*jSFpNLL?K~PPfX@~qJK)yzMyjVh>E43^MwCb z2mkz}g5{M8q$e+v>lGNGHc)Bd)ei^w>Q`x+c{{+mU&8Xuf}K=O7O5|$aVAlue4oQU z+XXtC@Ogt%sTL+3xA)D@GqY~uqhW-_oz4GX0zP3aoacd=-BCQ)>OjMl^mp@X^qXj8p07j z{!W!`P_@{!pQEn@*dwl}aSQi0ENEew2ZmGxd)>(9TF58sB<))*cr*o>Yz1?l4D)Ya zZqkD2Uyu5^WHwNex^Q${fiEPZl4qnJ?!n~-?kpDQrGF3lSsEL5BlWNa#Y0&C$9mEc z45JG}V=5BY_VH+KADg!dVjkjlFNslkly@ske3%TnE&Dt9Z0%Q;Zqvt@-+L*WwrFauhrODMtzrYC<6f9% z9a1(^hwg5oO@y-__3`D48M=CLlk|v(+d|D$+q_F1>icc)%ce48Up z7)9>(V(ev&hr=%X{&k&BzAkeII~jE${^JgH+WikEx_?p!ZDj2L0000SMBS#1uzxBdIHO?erxH_Q0SdTH z)Os?`FU#28F(KagCgWVB_DzH$HegzK^OFf;k^nPrKo5x6eo)51$4J$fme6Q?NIiYE`D-Zdqoqp$z6)~X zHYP`1P!&S`agEja>FU)8`9c!V1rCo}Fb}%UJMlT<%G)~r{H?-wf}`-iPkI=x&6p2 zXACZC!|M~_l>sfHqLwuv9_*T&l^5qPYPfU##G#c~)hS#zkld;x!h>G8G)}jEIAJSm z!*o`$@ZU}ov2#AOd;AN9d>6X651TQ(_vt9zynmKwcdlia9#_fc*-UTN8J~!*Y80N4 z(1VH0-%WNTyUFTX5L>ARYjM=vUd|D6P_hhtB$iaP+ZOJnTaE^UKy$M)O^kc7!|i;s z!d|-)q8B2nF+a8Y0v4hI6kUNJxzVe25u8`)l||k-PZ{ Date: Mon, 23 Dec 2024 16:04:48 +0300 Subject: [PATCH 31/47] add 'angle_spread' property --- src/graphics/render/Emitter.cpp | 7 ++++++- src/graphics/render/Emitter.hpp | 4 +++- src/graphics/render/ParticlesRenderer.cpp | 17 +++++++++++++++-- src/presets/ParticlesPreset.cpp | 2 ++ src/presets/ParticlesPreset.hpp | 2 ++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 82848a63..09e1ddc8 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -23,8 +23,9 @@ Emitter::Emitter( texture(texture), count(count), preset(std::move(preset)) { + random.setSeed(rand()); this->prototype.emitter = this; - timer = preset.spawnInterval; + timer = preset.spawnInterval * random.randFloat(); } const Texture* Emitter::getTexture() const { @@ -83,6 +84,10 @@ void Emitter::update( Particle particle = prototype; particle.emitter = this; particle.random = random.rand32(); + if (glm::abs(preset.angleSpread) >= 0.005f) { + particle.angle = + random.randFloat() * preset.angleSpread * glm::pi() * 2; + } glm::vec3 spawnOffset = generate_coord(preset.spawnShape); spawnOffset *= preset.spawnSpread; diff --git a/src/graphics/render/Emitter.hpp b/src/graphics/render/Emitter.hpp index c1d6c168..0ad34053 100644 --- a/src/graphics/render/Emitter.hpp +++ b/src/graphics/render/Emitter.hpp @@ -27,6 +27,8 @@ struct Particle { float lifetime; /// @brief UV region UVRegion region; + /// @brief Current rotation angle + float angle; }; class Texture; @@ -39,7 +41,7 @@ class Emitter { EmitterOrigin origin; /// @brief Particle prototype Particle prototype; - /// @brief Particle + /// @brief Particle texture const Texture* texture; /// @brief Number of particles should be spawned before emitter deactivation. /// -1 is infinite. diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 0e2292a5..71ec24c5 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -91,10 +91,23 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { } float scale = 1.0f + ((particle.random ^ 2628172) % 1000) * 0.001f * preset.sizeSpread; + + glm::vec3 localRight = right; + glm::vec3 localUp = preset.globalUpVector ? glm::vec3(0, 1, 0) : up; + float angle = particle.angle; + if (glm::abs(angle) >= 0.005f) { + glm::vec3 rotatedRight(glm::cos(angle), -glm::sin(angle), 0.0f); + glm::vec3 rotatedUp(glm::sin(angle), glm::cos(angle), 0.0f); + + localRight = right * rotatedRight.x + localUp * rotatedRight.y + + camera.front * rotatedRight.z; + localUp = right * rotatedUp.x + localUp * rotatedUp.y + + camera.front * rotatedUp.z; + } batch->quad( particle.position, - right, - preset.globalUpVector ? glm::vec3(0, 1, 0) : up, + localRight, + localUp, preset.size * scale, light, glm::vec3(1.0f), diff --git a/src/presets/ParticlesPreset.cpp b/src/presets/ParticlesPreset.cpp index 181dbeb5..27274442 100644 --- a/src/presets/ParticlesPreset.cpp +++ b/src/presets/ParticlesPreset.cpp @@ -43,6 +43,7 @@ dv::value ParticlesPreset::serialize() const { root["explosion"] = dv::to_value(explosion); root["size"] = dv::to_value(size); root["size_spread"] = sizeSpread; + root["angle_spread"] = angleSpread; root["spawn_spread"] = dv::to_value(size); root["spawn_shape"] = to_string(spawnShape); root["random_sub_uv"] = randomSubUV; @@ -58,6 +59,7 @@ void ParticlesPreset::deserialize(const dv::value& src) { src.at("spawn_interval").get(spawnInterval); src.at("lifetime").get(lifetime); src.at("lifetime_spread").get(lifetimeSpread); + src.at("angle_spread").get(angleSpread); src.at("random_sub_uv").get(randomSubUV); if (src.has("velocity")) { dv::get_vec(src["velocity"], velocity); diff --git a/src/presets/ParticlesPreset.hpp b/src/presets/ParticlesPreset.hpp index f8d5f2b4..67c6c91b 100644 --- a/src/presets/ParticlesPreset.hpp +++ b/src/presets/ParticlesPreset.hpp @@ -44,6 +44,8 @@ struct ParticlesPreset : public Serializable { glm::vec3 size {0.1f}; /// @brief Particles size spread float sizeSpread = 0.2f; + /// @brief Random initial angle spread + float angleSpread = 0.0f; /// @brief Spawn spread shape ParticleSpawnShape spawnShape = BALL; /// @brief Spawn spread From 6be640458d6b4ae46866b342ca0f26e561ead125 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:26:45 +0300 Subject: [PATCH 32/47] fix particles lighting --- src/graphics/render/ParticlesRenderer.cpp | 25 ++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 71ec24c5..a68f56e2 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -82,15 +82,34 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { } update_particle(particle, delta, chunks); + float scale = 1.0f + ((particle.random ^ 2628172) % 1000) * + 0.001f * preset.sizeSpread; + glm::vec4 light(1, 1, 1, 0); if (preset.lighting) { light = MainBatch::sampleLight( - particle.position, chunks, backlight + particle.position, + chunks, + backlight ); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + light = glm::max( + light, + MainBatch::sampleLight( + particle.position - preset.size * scale * + glm::vec3(x, y, z), + chunks, + backlight + ) + ); + } + } + } light *= 0.9f + (particle.random % 100) * 0.001f; } - float scale = 1.0f + ((particle.random ^ 2628172) % 1000) * - 0.001f * preset.sizeSpread; + glm::vec3 localRight = right; glm::vec3 localUp = preset.globalUpVector ? glm::vec3(0, 1, 0) : up; From 6ac088f7b9599dc0950dc4b3d208a13e8b5ae234 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:34:08 +0300 Subject: [PATCH 33/47] set default particles render distance to 32 --- src/graphics/render/ParticlesRenderer.cpp | 5 +++-- src/presets/ParticlesPreset.hpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index a68f56e2..6c3ed73c 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -92,14 +92,15 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { chunks, backlight ); + auto size = glm::max(glm::vec3(0.5f), preset.size * scale); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { for (int z = -1; z <= 1; z++) { light = glm::max( light, MainBatch::sampleLight( - particle.position - preset.size * scale * - glm::vec3(x, y, z), + particle.position - + size * glm::vec3(x, y, z), chunks, backlight ) diff --git a/src/presets/ParticlesPreset.hpp b/src/presets/ParticlesPreset.hpp index 67c6c91b..10b9f088 100644 --- a/src/presets/ParticlesPreset.hpp +++ b/src/presets/ParticlesPreset.hpp @@ -27,7 +27,7 @@ struct ParticlesPreset : public Serializable { /// @brief Use global up vector instead of camera-dependent one bool globalUpVector = false; /// @brief Max distance of actually spawning particles. - float maxDistance = 16.0f; + float maxDistance = 32.0f; /// @brief Particles spawn interval float spawnInterval = 0.1f; /// @brief Particle life time From 7f95306c6525b91765c55ce8b1ada46d5dc77e2b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:48:07 +0300 Subject: [PATCH 34/47] add 'min_angular_vel', 'max_angular_vel' properties --- src/graphics/render/Emitter.cpp | 5 +++++ src/graphics/render/Emitter.hpp | 2 ++ src/graphics/render/ParticlesRenderer.cpp | 2 ++ src/presets/ParticlesPreset.cpp | 4 ++++ src/presets/ParticlesPreset.hpp | 4 ++++ 5 files changed, 17 insertions(+) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 09e1ddc8..76b2f018 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -88,6 +88,11 @@ void Emitter::update( particle.angle = random.randFloat() * preset.angleSpread * glm::pi() * 2; } + particle.angularVelocity = + (preset.minAngularVelocity + + random.randFloat() * + (preset.maxAngularVelocity - preset.minAngularVelocity)) * + ((random.rand() % 2) * 2 - 1); glm::vec3 spawnOffset = generate_coord(preset.spawnShape); spawnOffset *= preset.spawnSpread; diff --git a/src/graphics/render/Emitter.hpp b/src/graphics/render/Emitter.hpp index 0ad34053..b2a371ad 100644 --- a/src/graphics/render/Emitter.hpp +++ b/src/graphics/render/Emitter.hpp @@ -29,6 +29,8 @@ struct Particle { UVRegion region; /// @brief Current rotation angle float angle; + /// @brief Angular velocity + float angularVelocity; }; class Texture; diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 6c3ed73c..f3a30cdd 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -31,12 +31,14 @@ static inline void update_particle( const auto& preset = particle.emitter->preset; auto& pos = particle.position; auto& vel = particle.velocity; + auto& angle = particle.angle; vel += delta * preset.acceleration; if (preset.collision && chunks.isObstacleAt(pos + vel * delta)) { vel *= 0.0f; } pos += vel * delta; + angle += particle.angularVelocity * delta; particle.lifetime -= delta; } diff --git a/src/presets/ParticlesPreset.cpp b/src/presets/ParticlesPreset.cpp index 27274442..8a007076 100644 --- a/src/presets/ParticlesPreset.cpp +++ b/src/presets/ParticlesPreset.cpp @@ -44,6 +44,8 @@ dv::value ParticlesPreset::serialize() const { root["size"] = dv::to_value(size); root["size_spread"] = sizeSpread; root["angle_spread"] = angleSpread; + root["min_angular_vel"] = minAngularVelocity; + root["max_angular_vel"] = maxAngularVelocity; root["spawn_spread"] = dv::to_value(size); root["spawn_shape"] = to_string(spawnShape); root["random_sub_uv"] = randomSubUV; @@ -60,6 +62,8 @@ void ParticlesPreset::deserialize(const dv::value& src) { src.at("lifetime").get(lifetime); src.at("lifetime_spread").get(lifetimeSpread); src.at("angle_spread").get(angleSpread); + src.at("min_angular_vel").get(minAngularVelocity); + src.at("max_angular_vel").get(maxAngularVelocity); src.at("random_sub_uv").get(randomSubUV); if (src.has("velocity")) { dv::get_vec(src["velocity"], velocity); diff --git a/src/presets/ParticlesPreset.hpp b/src/presets/ParticlesPreset.hpp index 10b9f088..2b955d13 100644 --- a/src/presets/ParticlesPreset.hpp +++ b/src/presets/ParticlesPreset.hpp @@ -46,6 +46,10 @@ struct ParticlesPreset : public Serializable { float sizeSpread = 0.2f; /// @brief Random initial angle spread float angleSpread = 0.0f; + /// @brief Minimum angular velocity + float minAngularVelocity = 0.0f; + /// @brief Maximum angular velocity + float maxAngularVelocity = 0.0f; /// @brief Spawn spread shape ParticleSpawnShape spawnShape = BALL; /// @brief Spawn spread From e899575a7ab9a6c9c3ffab020307eedaf4dee434 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:54:25 +0300 Subject: [PATCH 35/47] update Emitter randomizer --- src/graphics/render/Emitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 76b2f018..ff8413d5 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -23,7 +23,7 @@ Emitter::Emitter( texture(texture), count(count), preset(std::move(preset)) { - random.setSeed(rand()); + random.setSeed(reinterpret_cast(this)); this->prototype.emitter = this; timer = preset.spawnInterval * random.randFloat(); } From 78761a445afc14b4839682a2333cd3b2a4dd02f3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:54:39 +0300 Subject: [PATCH 36/47] add leaf texture --- res/content/base/textures/particles/leaf_0.png | Bin 0 -> 5263 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 res/content/base/textures/particles/leaf_0.png diff --git a/res/content/base/textures/particles/leaf_0.png b/res/content/base/textures/particles/leaf_0.png new file mode 100644 index 0000000000000000000000000000000000000000..282fff809871a6043875be914ac134b734754131 GIT binary patch literal 5263 zcmeHLX;>5I77k#cA}AEOxA%QN)QkO5m3YyF_}z4kSt^&fr0{B6$B9q z6e%uP6s3TzTgA0h1?$4%f+z*6pyCP$RxO}+5)kp;{_#H7e@>oBX3lrc`RBATg&FXUet=Obv=k`sL^e>&u%4@k9LG5s|9Jdkv zYhwFLxqa2L2@5Cpm zM_*h|SzgKG-vS-iojkq$ZXiHGd%K16)QD$H#x36sKBB8yfrpbHD z&I{K4=0WLKqO3?w>oWmPq4u}(C08ew(!P{dg@-FgRUYZ7sC;z9ZC81P@s5&Hywgd$ z$JhDY@lACeH_(4LyyR@^XR{8J1;^H@`7y9`-_;AzX%{Y5<$j)$ai^=TxxaVJ@yx}F z+6QMQDy%K{8KF*$t%}ve3V9GVKB2YlT77QOc8ffp4USe{E?!T3a&k*jNxg+na`@xh zf@UL6>!2~eGS?dOEW>Z5?9XyS%!m_>F;5?pg~`SNYivEU#bfK|Ns6mOcYI&rxJI%% zE?UH!%T%nPr^2V7F8gWaj?l6q7nfz66wX4wY!fqk$2C@`nru|<9o(ELf^^&93+Emz zqDF>XEoLngL>FYwP4f$$&vFpYYfqPpneAWgR&;wW7(IOwxTihsPHHx0xz&$DDR{x)mr(B{HkN9>)Smo~dyy}?}jAS7CI3%E)-vKRg}a#zrp5@cRMP313T zEHhSo%(A&N+**EK=n+=$mY8|==>zo8gmVSg(-tQN#NKGk3rzU~e#m?ou%eN$?s{)l zLtWd>#6vQ#>e$WCGBP&@96Sh3FE@Q%5Pe19i z;mqpJ&DH0=_h`M}eB08zIf}X}qH*n4nVaMZ>2^mi385qE^XjwkwON-gXQ!%q*XH{C z*x6WHQLv8Yv}aeddreAl{KFVyXd980oFAA~n0m3qw>I={u%mYU%Jg&Z*)wjXMA z`%AU?q4e|f^2XxLV?u?`T;c|Hy);QZF3mcuY>Xg(8@fSP$rWaonO2>IZ)ys5HH&hh zCNVgFJ>OlK57`H)Ak?GyuAn-B!);&0sEtq^t;{=-_O!Rf9DKC5t>cWD`00%w2Bf#r zO*D3VhodhY6w5E#C+`o;s=KxPT)#ClVihN0)IALCi%@i37Wa?qBl&ln;>GcFIs(CH zjl|1~=jY}1rjg+7qcAax?R$!6^G#r|zqj*PQ=6Exye%&4)0j~c(|AQ!%*&DdW4+@F zsE#vTH>Rwps@is@boGY)6=N$>fEOmWAN^U}L7d+Doz2qIFaCV$QTz2h#m&T|`rYJ< z4{Xh-E%eK&hjT8L&%YJQA$v|II>P7k{dZ<}g-1O9v}?e%dVhcCKxO>ZV`q|*IPT{y zF3)HMwzeLytnE8Zob|hNH>*3}&vN{1Wq9|C3{?Y`EKU>6U;-CGuxe4XQ4)mA~%K4eqrCgwR};2VOKUW2I#%bw0H2-O^$4|yVutgQ}8d(uBnGF zHNT27$$#m1ytQ$MkLOLgBBrG=hyAD0Y)S$}7#zD3$mKZ^I>o(Q*7nzvI>LJHHX=3m zO*R#UO_wLF_F8_x_xeMR&L>X_n@?(&_VgJ!?Np{R#_bEi8~%U$1? z0?bt>Rp5=EKyaU}Q}EFhm>LjZVu_4R>^yps2uOr%VknJE<|@3fNQrN}5(|zG2tngl zpe!MAwuia94#5GWn3@mhq|q`JqGJ;cxCnl&H&NF=RR>#Buap^eaHI^cY`zT#pNO# zIjYg8=f`0a_46Y_IVuq%hD(f0r!io%2oy2tRFI0%L?DwwW`P(>NEI@e5QNgO5m0_I zm6|U@F+CIx?kd4?SVD-;A`2l<#KQCtFa|PdEE*^xGx;zqpfV_A;RuL8r39}^e)Pz! z^iV<^iou5|7{+9QGzx@*R7gkz1t=8;aSQ>5LP8;iG7L~c6qzSiO8NM5N~C--MpDSc zh5^0c$Q+&@n@DjbzqRn9`Dzg!z$Pw`$TYgQ10fPA7Odv$)r1%@l|`ddVTcCPS!DRF z(_&1i!Yfga36WjlL0tW^AUGLZSiZhaaR5UE&IR#OVtln+86uZQvx)kY0DYvPyaD&Y zMe&uWaE~~B#ShhdFcvd-H~0udOAJE*U?^LJj}A_v;>Tixa^i7=Lue#lCdTmRd#Iq^ z*d_n8Sado>XF_}skWOU^Mfeg6XzwQdKU0J#AO#MAXb6Rj!2dzfouqGEZx+>^^k2(9=rE$w z;nED+@D7SMWYTa)9?}dK`9mH<<@O<`0DzB^yqCTo<@zYsdnxc<&L6Amqg?N$zB#=4ft-)RN(K!A-vYVwjVF~7PpL6_=c$ngfSEJrxBr` za0+fTQ~Pnf%{nY5TiDp=%*igpO^6?7PROU%(E1*mzxN6qdbb&w=eM4CRr4!;Y{z~d z*p`eR4IXnIyxv=Pa>}w3{WXB|Z>9^^mVH79>$LKp@x^2OPecO2&pUuqF?V^&zX1YR B Date: Mon, 23 Dec 2024 17:26:22 +0300 Subject: [PATCH 37/47] upgrade emitters garbage collection --- src/graphics/render/Emitter.cpp | 7 ++++++- src/graphics/render/Emitter.hpp | 6 ++++++ src/graphics/render/ParticlesRenderer.cpp | 20 +++++++++----------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index ff8413d5..88951588 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -19,7 +19,7 @@ Emitter::Emitter( ) : level(level), origin(std::move(origin)), - prototype({this, 0, glm::vec3(), preset.velocity, preset.lifetime, region}), + prototype({this, 0, {}, preset.velocity, preset.lifetime, region}), texture(texture), count(count), preset(std::move(preset)) { @@ -113,6 +113,7 @@ void Emitter::update( if (count > 0) { count--; } + refCount++; } } @@ -124,6 +125,10 @@ bool Emitter::isDead() const { return count == 0; } +bool Emitter::isReferred() const { + return refCount > 0; +} + const EmitterOrigin& Emitter::getOrigin() const { return origin; } diff --git a/src/graphics/render/Emitter.hpp b/src/graphics/render/Emitter.hpp index b2a371ad..ce1ec8f4 100644 --- a/src/graphics/render/Emitter.hpp +++ b/src/graphics/render/Emitter.hpp @@ -54,6 +54,9 @@ class Emitter { util::PseudoRandom random; public: + /// @brief Number of references (alive particles) + int refCount = 0; + /// @brief Particle settings ParticlesPreset preset; Emitter( @@ -86,6 +89,9 @@ public: /// @return true if the emitter has spawned all particles bool isDead() const; + /// @return true if there is at least one alive referring particle left + bool isReferred() const; + const EmitterOrigin& getOrigin() const; void setOrigin(const EmitterOrigin& origin); diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index f3a30cdd..e96eb615 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -63,7 +63,8 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { auto iter = vec.begin(); while (iter != vec.end()) { auto& particle = *iter; - auto& preset = particle.emitter->preset; + auto& emitter = *particle.emitter; + auto& preset = emitter.preset; if (!preset.frames.empty()) { float time = preset.lifetime - particle.lifetime; @@ -137,6 +138,7 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { ); if (particle.lifetime <= 0.0f) { iter = vec.erase(iter); + emitter.refCount--; } else { iter++; } @@ -159,19 +161,15 @@ void ParticlesRenderer::render(const Camera& camera, float delta) { auto iter = emitters.begin(); while (iter != emitters.end()) { auto& emitter = *iter->second; + if (emitter.isDead() && !emitter.isReferred()) { + // destruct Emitter only when there is no particles spawned by it + iter = emitters.erase(iter); + continue; + } auto texture = emitter.getTexture(); const auto& found = particles.find(texture); std::vector* vec; - if (found == particles.end()) { - if (emitter.isDead()) { - // destruct Emitter only when there is no particles spawned by it - iter = emitters.erase(iter); - continue; - } - vec = &particles[texture]; - } else { - vec = &found->second; - } + vec = &particles[texture]; emitter.update(delta, camera.position, *vec); iter++; } From 40ac604e58612b76025f7b87d4d6ef46bf9bf6b8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:00:17 +0300 Subject: [PATCH 38/47] many emitters test --- res/content/base/blocks/leaves.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/res/content/base/blocks/leaves.json b/res/content/base/blocks/leaves.json index e3ddae22..4ea4832f 100644 --- a/res/content/base/blocks/leaves.json +++ b/res/content/base/blocks/leaves.json @@ -3,5 +3,24 @@ "material": "base:grass", "draw-group": 5, "culling": "optional", + "particles": { + "lifetime": 4.0, + "spawn_interval": 1000.0, + "acceleration": [0, -0.1, 0], + "velocity": [0.2, -2.5, 0.3], + "explosion": [0, 0, 0], + "collision": false, + "size": [0.3, 0.3, 0.3], + "size_spread": 0.2, + "spawn_shape": "box", + "spawn_spread": [0.2, 0.2, 0.2], + "angle_spread": 1.0, + "min_angular_vel": 0.5, + "max_angular_vel": 2.0, + "lighting": true, + "frames": [ + "particles:leaf_0" + ] + }, "base:durability": 0.7 } From 344df27f611a3090dd1b555fd55c12089522212c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:14:51 +0300 Subject: [PATCH 39/47] minor refactor --- src/graphics/render/Decorator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/graphics/render/Decorator.cpp b/src/graphics/render/Decorator.cpp index b7bd4218..95ccbcc2 100644 --- a/src/graphics/render/Decorator.cpp +++ b/src/graphics/render/Decorator.cpp @@ -99,9 +99,8 @@ void Decorator::update( void Decorator::update(float delta, const Camera& camera) { glm::ivec3 pos = camera.position; - pos -= glm::ivec3(UPDATE_AREA_DIAMETER / 2); for (int i = 0; i < ITERATIONS; i++) { - update(delta, pos, camera.position); + update(delta, pos - glm::ivec3(UPDATE_AREA_DIAMETER / 2), pos); } const auto& chunks = *level.chunks; const auto& indices = *level.content->getIndices(); From faf4cfa735cc60263c71db2ed675c1f8bf2e447b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:25:40 +0300 Subject: [PATCH 40/47] update doc/*/particles.md --- doc/en/particles.md | 4 ++++ doc/ru/particles.md | 3 +++ 2 files changed, 7 insertions(+) diff --git a/doc/en/particles.md b/doc/en/particles.md index 8b7a37e7..47ab8ac3 100644 --- a/doc/en/particles.md +++ b/doc/en/particles.md @@ -16,6 +16,10 @@ Particles are a table, all fields of which are optional. | acceleration | Particles acceleration. | {0, -16, 0} | | explosion | Force of particles explosion on spawn. | {2, 2, 2} | | size | Size of particles. | {0.1, 0.1, 0.1} | +| size_spread | Maximum particle size spread over time. | 0.2 | +| angle_spread | Maximum initial rotation angle spread (0 to 1) | 0.0 | +| min_angular_vel | Minimum angular velocity (radians per sec). Non-negative. | 0.0 | +| max_angular_vel | Maximum angular velocity (radians per sec). Non-negative. | 0.0 | | spawn_shape | Shape of particle spawn area. (ball/sphere/box) | ball | | spawn_spread | Size of particle spawn area. | {0, 0, 0} | | random_sub_uv | Size of random texture subregion (1 - entire texture will be used). | 1.0 | diff --git a/doc/ru/particles.md b/doc/ru/particles.md index 167337f8..90af27f1 100644 --- a/doc/ru/particles.md +++ b/doc/ru/particles.md @@ -18,6 +18,9 @@ | explosion | Сила разлёта частиц при спавне. | {2, 2, 2} | | size | Размер частиц. | {0.1, 0.1, 0.1} | | size_spread | Максимальное отклонение времени размера частиц. | 0.2 | +| angle_spread | Максимальное отклонение начального угла поворота (от 0 до 1) | 0.0 | +| min_angular_vel | Минимальная угловая скорость (радианы в сек.). Неотрицательное. | 0.0 | +| max_angular_vel | Максимальная угловая скорость (радианы в сек.). Неотрицательное. | 0.0 | | spawn_shape | Форма области спавна частиц. (ball/sphere/box) | ball | | spawn_spread | Размер области спавна частиц. | {0, 0, 0} | | random_sub_uv | Размер случайного подрегиона текстуры (1 - будет использована вся текстура). | 1.0 | From f1c7317c5ab2a148e5188e091cd1aa3490dc8b4d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:35:02 +0300 Subject: [PATCH 41/47] fix non-skipping particles --- src/graphics/render/Emitter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 88951588..e908ece8 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -77,6 +77,10 @@ void Emitter::update( count = std::max(0, count - skipped); timer -= skipped * spawnInterval; } + if (count < 0) { + int skipped = timer / spawnInterval; + timer -= skipped * spawnInterval; + } return; } while (count && timer > spawnInterval) { From d55d02ac9da0188aa2618f59c3da6937a3f04b9c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 08:01:16 +0300 Subject: [PATCH 42/47] add dev/tests/filesystem.lua --- dev/tests/filesystem.lua | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 dev/tests/filesystem.lua diff --git a/dev/tests/filesystem.lua b/dev/tests/filesystem.lua new file mode 100644 index 00000000..ac3e5e30 --- /dev/null +++ b/dev/tests/filesystem.lua @@ -0,0 +1,44 @@ +debug.log("check initial state") +assert(file.exists("config:")) + +debug.log("write text file") +assert(file.write("config:text.txt", "example, пример")) +assert(file.exists("config:text.txt")) + +debug.log("read text file") +assert(file.read("config:text.txt") == "example, пример") + +debug.log("delete file") +file.remove("config:text.txt") +assert(not file.exists("config:text.txt")) + +debug.log("create directory") +file.mkdir("config:dir") +assert(file.isdir("config:dir")) + +debug.log("remove directory") +file.remove("config:dir") + +debug.log("create directories") +file.mkdirs("config:dir/subdir/other") +assert(file.isdir("config:dir/subdir/other")) + +debug.log("remove tree") +file.remove_tree("config:dir") +assert(not file.isdir("config:dir")) + +debug.log("write binary file") +local bytes = {0xDE, 0xAD, 0xC0, 0xDE} +file.write_bytes("config:binary", bytes) +assert(file.exists("config:binary")) + +debug.log("read binary file") +local rbytes = file.read_bytes("config:binary") +assert(#rbytes == #bytes) +for i, b in ipairs(bytes) do + assert(rbytes[i] == b) +end + +debug.log("delete file") +file.remove("config:binary") +assert(not file.exists("config:binary")) From bc4aea67c9c7a9be23ecce7b6e71e21b7bb4b258 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 08:08:44 +0300 Subject: [PATCH 43/47] add file.is_writeable --- dev/tests/filesystem.lua | 6 ++++++ doc/en/scripting/builtins/libfile.md | 6 ++++++ doc/ru/scripting/builtins/libfile.md | 6 ++++++ src/logic/scripting/lua/libs/libfile.cpp | 11 +++++++++++ 4 files changed, 29 insertions(+) diff --git a/dev/tests/filesystem.lua b/dev/tests/filesystem.lua index ac3e5e30..a9ff58ce 100644 --- a/dev/tests/filesystem.lua +++ b/dev/tests/filesystem.lua @@ -42,3 +42,9 @@ end debug.log("delete file") file.remove("config:binary") assert(not file.exists("config:binary")) + +debug.log("checking entry points for writeability") +assert(file.is_writeable("config:")) +assert(file.is_writeable("export:")) +assert(not file.is_writeable("user:")) +assert(not file.is_writeable("res:")) diff --git a/doc/en/scripting/builtins/libfile.md b/doc/en/scripting/builtins/libfile.md index fe02bed1..1e683b65 100644 --- a/doc/en/scripting/builtins/libfile.md +++ b/doc/en/scripting/builtins/libfile.md @@ -25,6 +25,12 @@ file.read_bytes(path: str) -> array of integers Read file into bytes array. +```lua +file.is_writeable(path: str) -> bool +``` + +Checks if the specified path is writable. + ```python file.write(path: str, text: str) -> nil ``` diff --git a/doc/ru/scripting/builtins/libfile.md b/doc/ru/scripting/builtins/libfile.md index a9a9c273..d7ed7792 100644 --- a/doc/ru/scripting/builtins/libfile.md +++ b/doc/ru/scripting/builtins/libfile.md @@ -25,6 +25,12 @@ file.read_bytes(путь: str) -> array of integers Читает файл в массив байт. +```lua +file.is_writeable(путь: str) -> bool +``` + +Проверяет, доступно ли право записи по указанному пути. + ```python file.write(путь: str, текст: str) -> nil ``` diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index 940aaa53..6e9cac5c 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -243,6 +243,16 @@ static int l_read_combined_object(lua::State* L) { return lua::pushvalue(L, engine->getResPaths()->readCombinedObject(path)); } +static int l_is_writeable(lua::State* L) { + std::string rawpath = lua::require_string(L, 1); + fs::path path = resolve_path(rawpath); + auto entryPoint = rawpath.substr(0, rawpath.find(':')); + if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) { + return lua::pushboolean(L, false); + } + return lua::pushboolean(L, true); +} + const luaL_Reg filelib[] = { {"exists", lua::wrap}, {"find", lua::wrap}, @@ -263,4 +273,5 @@ const luaL_Reg filelib[] = { {"gzip_decompress", lua::wrap}, {"read_combined_list", lua::wrap}, {"read_combined_object", lua::wrap}, + {"is_writeable", lua::wrap}, {NULL, NULL}}; From 272e41de502c820a49f621bdbd3ded30a181b3b8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 08:13:08 +0300 Subject: [PATCH 44/47] disable writing to read-only entry points --- src/logic/scripting/lua/libs/libfile.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index 6e9cac5c..6b35b11e 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -57,12 +57,7 @@ static fs::path get_writeable_path(lua::State* L) { fs::path path = resolve_path(rawpath); auto entryPoint = rawpath.substr(0, rawpath.find(':')); if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) { - if (lua::getglobal(L, "__vc_warning")) { - lua::pushstring(L, "writing to read-only entry point"); - lua::pushstring(L, entryPoint); - lua::pushinteger(L, 1); - lua::call_nothrow(L, 3); - } + throw std::runtime_error("access denied"); } return path; } From 10491fbb6156695af5a17e7a562b09af736b5747 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 08:49:20 +0300 Subject: [PATCH 45/47] add UVFace --- src/maths/UVFace.hpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/maths/UVFace.hpp diff --git a/src/maths/UVFace.hpp b/src/maths/UVFace.hpp new file mode 100644 index 00000000..538ae210 --- /dev/null +++ b/src/maths/UVFace.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include "UVRegion.hpp" + +struct UVFace { + std::array points; + + UVFace(const UVRegion& region) { + points[0] = {region.u1, region.v1}; + points[1] = {region.u2, region.v1}; + points[2] = {region.u2, region.v2}; + points[3] = {region.u1, region.v2}; + } + + template + inline void rotate(int times) { + int times = n % 4; + if (times < 0) { + times += 4; + } + std::array temp = points; + points[0] = temp[times]; + points[1] = temp[(times + 1) % 4]; + points[2] = temp[(times + 2) % 4]; + points[3] = temp[(times + 3) % 4]; + } +}; From e153e1fbd7fdfbe773a43b480258ea02fbbe939a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 10:35:09 +0300 Subject: [PATCH 46/47] add player.is_loading_chunks, .set_loading_chunks --- doc/en/scripting/builtins/libplayer.md | 7 +++++++ doc/ru/scripting/builtins/libplayer.md | 7 +++++++ src/logic/ChunksController.cpp | 10 +++++++++- src/logic/scripting/lua/libs/libplayer.cpp | 16 ++++++++++++++++ src/objects/Player.cpp | 12 +++++++++++- src/objects/Player.hpp | 4 ++++ 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/doc/en/scripting/builtins/libplayer.md b/doc/en/scripting/builtins/libplayer.md index 3bff1547..52324d30 100644 --- a/doc/en/scripting/builtins/libplayer.md +++ b/doc/en/scripting/builtins/libplayer.md @@ -70,6 +70,13 @@ player.set_instant_destruction(playerid: int, bool) Getter and setter for instant destruction of blocks when the `player.destroy` binding is activated. +```lua +player.is_loading_chunks(playerid: int) -> bool +player.set_loading_chunks(playerid: int, bool) +``` + +Getter and setter of the property that determines whether the player is loading chunks. + ``` lua player.set_spawnpoint(playerid: int, x: number, y: number, z: number) player.get_spawnpoint(playerid: int) -> number, number, number diff --git a/doc/ru/scripting/builtins/libplayer.md b/doc/ru/scripting/builtins/libplayer.md index d4912e61..01a6d581 100644 --- a/doc/ru/scripting/builtins/libplayer.md +++ b/doc/ru/scripting/builtins/libplayer.md @@ -70,6 +70,13 @@ player.set_instant_destruction(playerid: int, bool) Геттер и сеттер мнгновенного разрушения блоков при активации привязки `player.destroy`. +```lua +player.is_loading_chunks(playerid: int) -> bool +player.set_loading_chunks(playerid: int, bool) +``` + +Геттер и сеттер свойства, определяющего, прогружает ли игрок чанки вокруг. + ```lua player.set_spawnpoint(playerid: int, x: number, y: number, z: number) player.get_spawnpoint(playerid: int) -> number, number, number diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index f431efa7..162ca2fe 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -38,7 +38,9 @@ void ChunksController::update( int centerX = floordiv(position.x); int centerY = floordiv(position.z); - generator->update(centerX, centerY, loadDistance); + if (player.isLoadingChunks()) { + generator->update(centerX, centerY, loadDistance); + } int64_t mcstotal = 0; @@ -121,6 +123,12 @@ bool ChunksController::buildLights(const Player& player, const std::shared_ptrfetch(x, z)) { + player.chunks->putChunk(chunk); + } + return; + } auto chunk = level.chunks->create(x, z); player.chunks->putChunk(chunk); auto& chunkFlags = chunk->flags; diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index 12905e01..7c1c11ce 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -164,6 +164,20 @@ static int l_set_instant_destruction(lua::State* L) { return 0; } +static int l_is_loading_chunks(lua::State* L) { + if (auto player = get_player(L, 1)) { + return lua::pushboolean(L, player->isLoadingChunks()); + } + return 0; +} + +static int l_set_loading_chunks(lua::State* L) { + if (auto player = get_player(L, 1)) { + player->setLoadingChunks(lua::toboolean(L, 2)); + } + return 0; +} + static int l_get_selected_block(lua::State* L) { if (auto player = get_player(L, 1)) { if (player->selection.vox.id == BLOCK_VOID) { @@ -282,6 +296,8 @@ const luaL_Reg playerlib[] = { {"set_infinite_items", lua::wrap}, {"is_instant_destruction", lua::wrap}, {"set_instant_destruction", lua::wrap}, + {"is_loading_chunks", lua::wrap}, + {"set_loading_chunks", lua::wrap}, {"set_selected_slot", lua::wrap}, {"get_selected_block", lua::wrap}, {"get_selected_entity", lua::wrap}, diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index d5493a6e..b20b32e9 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -251,6 +251,14 @@ void Player::setInstantDestruction(bool flag) { instantDestruction = flag; } +bool Player::isLoadingChunks() const { + return loadingChunks; +} + +void Player::setLoadingChunks(bool flag) { + loadingChunks = flag; +} + entityid_t Player::getEntity() const { return eid; } @@ -297,6 +305,7 @@ dv::value Player::serialize() const { root["noclip"] = noclip; root["infinite-items"] = infiniteItems; root["instant-destruction"] = instantDestruction; + root["loading-chunks"] = loadingChunks; root["chosen-slot"] = chosenSlot; root["entity"] = eid; root["inventory"] = inventory->serialize(); @@ -329,7 +338,8 @@ void Player::deserialize(const dv::value& src) { noclip = src["noclip"].asBoolean(); src.at("infinite-items").get(infiniteItems); src.at("instant-destruction").get(instantDestruction); - + src.at("loading-chunks").get(loadingChunks); + setChosenSlot(src["chosen-slot"].asInteger()); eid = src["entity"].asNumber(); diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 55f824d6..447b1eab 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -51,6 +51,7 @@ class Player : public Serializable { bool noclip = false; bool infiniteItems = true; bool instantDestruction = true; + bool loadingChunks = true; entityid_t eid; entityid_t selectedEid = 0; public: @@ -97,6 +98,9 @@ public: bool isInstantDestruction() const; void setInstantDestruction(bool flag); + bool isLoadingChunks() const; + void setLoadingChunks(bool flag); + entityid_t getEntity() const; void setEntity(entityid_t eid); From b4abecc764e99268e7d59ca601a069371af66d10 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 11:31:54 +0300 Subject: [PATCH 47/47] refactor --- src/frontend/hud.cpp | 14 +++++++++----- src/frontend/hud.hpp | 3 +++ src/frontend/screens/LevelScreen.cpp | 4 +++- src/frontend/screens/LevelScreen.hpp | 1 + src/graphics/render/WorldRenderer.cpp | 10 +++++++--- src/graphics/render/WorldRenderer.hpp | 3 +++ src/logic/ChunksController.cpp | 1 + src/objects/Player.hpp | 5 ++--- 8 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 95fd47dc..f0535e14 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -324,7 +324,7 @@ void Hud::update(bool visible) { const auto& chunks = *player.chunks; const auto& menu = gui.getMenu(); - debugPanel->setVisible(player.debug && visible); + debugPanel->setVisible(debug && visible); if (!visible && inventoryOpen) { closeInventory(); @@ -359,7 +359,7 @@ void Hud::update(bool visible) { if (visible) { for (auto& element : elements) { - element.update(pause, inventoryOpen, player.debug); + element.update(pause, inventoryOpen, debug); if (element.isRemoved()) { onRemove(element); } @@ -367,8 +367,8 @@ void Hud::update(bool visible) { } cleanup(); - debugMinimap->setVisible(player.debug && showGeneratorMinimap); - if (player.debug && showGeneratorMinimap) { + debugMinimap->setVisible(debug && showGeneratorMinimap); + if (debug && showGeneratorMinimap) { updateWorldGenDebugVisualization(); } } @@ -585,6 +585,10 @@ void Hud::remove(const std::shared_ptr& node) { cleanup(); } +void Hud::setDebug(bool flag) { + debug = flag; +} + void Hud::draw(const DrawContext& ctx){ const Viewport& viewport = ctx.getViewport(); const uint width = viewport.getWidth(); @@ -602,7 +606,7 @@ void Hud::draw(const DrawContext& ctx){ uishader.uniformMatrix("u_projview", uicamera->getProjView()); // Crosshair - if (!pause && !inventoryOpen && !player.debug) { + if (!pause && !inventoryOpen && !debug) { DrawContext chctx = ctx.sub(batch); chctx.setBlendMode(BlendMode::inversion); auto texture = assets.get("gui/crosshair"); diff --git a/src/frontend/hud.hpp b/src/frontend/hud.hpp index 79d183fa..2a537157 100644 --- a/src/frontend/hud.hpp +++ b/src/frontend/hud.hpp @@ -113,6 +113,7 @@ class Hud : public util::ObjectsKeeper { bool showContentPanel = true; /// @brief Provide cheat controllers to the debug panel bool allowDebugCheats = true; + bool debug = false; /// @brief UI element will be dynamicly positioned near to inventory or in screen center std::shared_ptr secondUI; @@ -193,6 +194,8 @@ public: void onRemove(const HudElement& element); void remove(const std::shared_ptr& node); + void setDebug(bool flag); + Player* getPlayer() const; std::shared_ptr getBlockInventory(); diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 8a37b903..5fc073b3 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -157,7 +157,9 @@ void LevelScreen::updateHotkeys() { hudVisible = !hudVisible; } if (Events::jpressed(keycode::F3)) { - player->debug = !player->debug; + debug = !debug; + hud->setDebug(debug); + worldRenderer->setDebug(debug); } } diff --git a/src/frontend/screens/LevelScreen.hpp b/src/frontend/screens/LevelScreen.hpp index c184f816..6a3b4eab 100644 --- a/src/frontend/screens/LevelScreen.hpp +++ b/src/frontend/screens/LevelScreen.hpp @@ -29,6 +29,7 @@ class LevelScreen : public Screen { void saveWorldPreview(); bool hudVisible = true; + bool debug = false; void updateHotkeys(); void initializeContent(); void initializePack(ContentPackRuntime* pack); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e8a75f0c..098cb8e8 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -211,7 +211,7 @@ void WorldRenderer::renderBlockSelection() { lineBatch->box( center, size + glm::vec3(0.01), glm::vec4(0.f, 0.f, 0.f, 0.5f) ); - if (player.debug) { + if (debug) { lineBatch->line( point, point + norm * 0.5f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f) ); @@ -228,7 +228,7 @@ void WorldRenderer::renderLines( if (player.selection.vox.id != BLOCK_VOID) { renderBlockSelection(); } - if (player.debug && showEntitiesDebug) { + if (debug && showEntitiesDebug) { auto ctx = pctx.sub(lineBatch.get()); bool culling = engine.getSettings().graphics.frustumCulling.get(); level.entities->renderDebug( @@ -337,7 +337,7 @@ void WorldRenderer::draw( renderLevel(ctx, camera, settings, delta, pause, hudVisible); // Debug lines if (hudVisible) { - if (player.debug) { + if (debug) { guides->renderDebugLines( ctx, camera, *lineBatch, linesShader, showChunkBorders ); @@ -410,3 +410,7 @@ void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) { void WorldRenderer::clear() { chunks->clear(); } + +void WorldRenderer::setDebug(bool flag) { + debug = flag; +} diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index f8be0177..569858d8 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -45,6 +45,7 @@ class WorldRenderer { std::unique_ptr modelBatch; float timer = 0.0f; + bool debug = false; /// @brief Render block selection lines void renderBlockSelection(); @@ -100,4 +101,6 @@ public: ); void clear(); + + void setDebug(bool flag); }; diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index 162ca2fe..a228de61 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -39,6 +39,7 @@ void ChunksController::update( int centerY = floordiv(position.z); if (player.isLoadingChunks()) { + /// FIXME: one generator for multiple players generator->update(centerX, centerY, loadDistance); } diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 447b1eab..b7ace8ff 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -55,10 +55,9 @@ class Player : public Serializable { entityid_t eid; entityid_t selectedEid = 0; public: - std::unique_ptr chunks; // not in use yet + std::unique_ptr chunks; std::shared_ptr fpCamera, spCamera, tpCamera; - std::shared_ptr currentCamera; - bool debug = false; + std::shared_ptr currentCamera;; glm::vec3 cam {}; CursorSelection selection {};