From 17af84dcec176c670dc5f557d2fb60eb10b82b88 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 13 Jan 2025 20:47:22 +0300 Subject: [PATCH 01/44] update doc/*/main-page.md --- doc/en/main-page.md | 4 +--- doc/ru/main-page.md | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/doc/en/main-page.md b/doc/en/main-page.md index 0daa4729..0a4748b4 100644 --- a/doc/en/main-page.md +++ b/doc/en/main-page.md @@ -1,8 +1,6 @@ # Documentation -Documentation for in-development version 0.26. - -[Documentation for stable release 0.25.x.](https://github.com/MihailRis/VoxelEngine-Cpp/blob/release-0.25/doc/en/main-page.md) +Documentation for release 0.26. ## Sections diff --git a/doc/ru/main-page.md b/doc/ru/main-page.md index 10dff292..52e0faa1 100644 --- a/doc/ru/main-page.md +++ b/doc/ru/main-page.md @@ -1,8 +1,6 @@ # Документация -Документация разрабатываемой версии 0.26. - -[Документация стабильной версии 0.25.x.](https://github.com/MihailRis/VoxelEngine-Cpp/blob/release-0.25/doc/ru/main-page.md) +Документация версии 0.26. ## Разделы From f1f81371affec4e1f5f8fe69c84e8cc50dc1e3f6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Jan 2025 23:36:37 +0300 Subject: [PATCH 02/44] add world.save_chunk_data(...) --- src/logic/scripting/lua/libs/libworld.cpp | 22 ++++++++++++ src/voxels/compressed_chunks.cpp | 44 +++++++++++++++++++---- src/voxels/compressed_chunks.hpp | 2 ++ 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index bbba422d..5db150b0 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -6,6 +6,7 @@ #include "assets/AssetsLoader.hpp" #include "coders/json.hpp" #include "engine/Engine.hpp" +#include "files/WorldFiles.hpp" #include "files/engine_paths.hpp" #include "files/files.hpp" #include "lighting/Lighting.hpp" @@ -158,9 +159,14 @@ static void integrate_chunk_client(Chunk& chunk) { } static int l_set_chunk_data(lua::State* L) { + if (level == nullptr) { + throw std::runtime_error("no open world"); + } + int x = static_cast(lua::tointeger(L, 1)); int z = static_cast(lua::tointeger(L, 2)); auto buffer = lua::require_bytearray(L, 3); + auto chunk = level->chunks->getChunk(x, z); if (chunk == nullptr) { return lua::pushboolean(L, false); @@ -175,6 +181,21 @@ static int l_set_chunk_data(lua::State* L) { return lua::pushboolean(L, true); } +static int l_save_chunk_data(lua::State* L) { + if (level == nullptr) { + throw std::runtime_error("no open world"); + } + + int x = static_cast(lua::tointeger(L, 1)); + int z = static_cast(lua::tointeger(L, 2)); + auto buffer = lua::require_bytearray(L, 3); + + compressed_chunks::save( + x, z, std::move(buffer), level->getWorld()->wfile->getRegions() + ); + return 0; +} + static int l_count_chunks(lua::State* L) { if (level == nullptr) { return 0; @@ -197,6 +218,7 @@ const luaL_Reg worldlib[] = { {"exists", lua::wrap}, {"get_chunk_data", lua::wrap}, {"set_chunk_data", lua::wrap}, + {"save_chunk_data", lua::wrap}, {"count_chunks", lua::wrap}, {NULL, NULL} }; diff --git a/src/voxels/compressed_chunks.cpp b/src/voxels/compressed_chunks.cpp index 0e6772af..64000a79 100644 --- a/src/voxels/compressed_chunks.cpp +++ b/src/voxels/compressed_chunks.cpp @@ -3,6 +3,7 @@ #include "coders/rle.hpp" #include "coders/gzip.hpp" #include "coders/byte_utils.hpp" +#include "files/WorldFiles.hpp" #include "voxels/Chunk.hpp" inline constexpr int HAS_VOXELS = 0x1; @@ -34,6 +35,15 @@ std::vector compressed_chunks::encode(const Chunk& chunk) { return builder.build(); } +static void read_voxel_data(ByteReader& reader, util::Buffer& dst) { + size_t gzipCompressedSize = reader.getInt32(); + + auto rleData = gzip::decompress(reader.pointer(), gzipCompressedSize); + reader.skip(gzipCompressedSize); + + extrle::decode16(rleData.data(), rleData.size(), dst.data()); +} + void compressed_chunks::decode(Chunk& chunk, const ubyte* src, size_t size) { ByteReader reader(src, size); @@ -41,14 +51,9 @@ void compressed_chunks::decode(Chunk& chunk, const ubyte* src, size_t size) { reader.skip(1); // reserved byte if (flags & HAS_VOXELS) { - size_t gzipCompressedSize = reader.getInt32(); - - auto rleData = gzip::decompress(reader.pointer(), gzipCompressedSize); - reader.skip(gzipCompressedSize); - /// world.get_chunk_data is only available in the main Lua state static util::Buffer voxelData (CHUNK_DATA_LEN); - extrle::decode16(rleData.data(), rleData.size(), voxelData.data()); + read_voxel_data(reader, voxelData); chunk.decode(voxelData.data()); chunk.updateHeights(); } @@ -59,3 +64,30 @@ void compressed_chunks::decode(Chunk& chunk, const ubyte* src, size_t size) { } chunk.setModifiedAndUnsaved(); } + +void compressed_chunks::save( + int x, int z, std::vector bytes, WorldRegions& regions +) { + ByteReader reader(bytes.data(), bytes.size()); + + ubyte flags = reader.get(); + reader.skip(1); // reserved byte + if (flags & HAS_VOXELS) { + util::Buffer voxelData (CHUNK_DATA_LEN); + read_voxel_data(reader, voxelData); + regions.put( + x, z, REGION_LAYER_VOXELS, voxelData.release(), CHUNK_DATA_LEN + ); + } + if (flags & HAS_METADATA) { + size_t metadataSize = reader.getInt32(); + regions.put( + x, + z, + REGION_LAYER_BLOCKS_DATA, + util::Buffer(reader.pointer(), metadataSize).release(), + metadataSize + ); + reader.skip(metadataSize); + } +} diff --git a/src/voxels/compressed_chunks.hpp b/src/voxels/compressed_chunks.hpp index dc0bc5b6..2181669c 100644 --- a/src/voxels/compressed_chunks.hpp +++ b/src/voxels/compressed_chunks.hpp @@ -5,8 +5,10 @@ #include class Chunk; +class WorldRegions; namespace compressed_chunks { std::vector encode(const Chunk& chunk); void decode(Chunk& chunk, const ubyte* src, size_t size); + void save(int x, int z, std::vector bytes, WorldRegions& regions); } From 02a93d8bc36ba0ca49c5e9d633c96aac4f92f7db Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Jan 2025 01:25:43 +0300 Subject: [PATCH 03/44] feat: world.get_chunk_data(...) saved chunk data when chunk is not loaded --- src/logic/scripting/lua/libs/libworld.cpp | 16 ++++++++++--- src/voxels/compressed_chunks.cpp | 28 +++++++++++++---------- src/voxels/compressed_chunks.hpp | 8 ++++++- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index 5db150b0..362d08c7 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -126,11 +126,21 @@ static int l_get_chunk_data(lua::State* L) { int x = static_cast(lua::tointeger(L, 1)); int z = static_cast(lua::tointeger(L, 2)); const auto& chunk = level->chunks->getChunk(x, z); + + std::vector chunkData; if (chunk == nullptr) { - lua::pushnil(L); - return 0; + auto& regions = level->getWorld()->wfile->getRegions(); + auto voxelData = regions.getVoxels(x, z); + if (voxelData == nullptr) { + return 0; + } + static util::Buffer rleBuffer(CHUNK_DATA_LEN * 2); + auto metadata = regions.getBlocksData(x, z); + chunkData = + compressed_chunks::encode(voxelData.get(), metadata, rleBuffer); + } else { + chunkData = compressed_chunks::encode(*chunk); } - auto chunkData = compressed_chunks::encode(*chunk); return lua::newuserdata(L, std::move(chunkData)); } diff --git a/src/voxels/compressed_chunks.cpp b/src/voxels/compressed_chunks.cpp index 64000a79..24cc02dd 100644 --- a/src/voxels/compressed_chunks.cpp +++ b/src/voxels/compressed_chunks.cpp @@ -2,28 +2,24 @@ #include "coders/rle.hpp" #include "coders/gzip.hpp" -#include "coders/byte_utils.hpp" + #include "files/WorldFiles.hpp" -#include "voxels/Chunk.hpp" inline constexpr int HAS_VOXELS = 0x1; inline constexpr int HAS_METADATA = 0x2; -std::vector compressed_chunks::encode(const Chunk& chunk) { - auto data = chunk.encode(); - - /// world.get_chunk_data is only available in the main Lua state - static util::Buffer rleBuffer; - if (rleBuffer.size() < CHUNK_DATA_LEN * 2) { - rleBuffer = util::Buffer(CHUNK_DATA_LEN * 2); - } +std::vector compressed_chunks::encode( + const ubyte* data, + const BlocksMetadata& metadata, + util::Buffer& rleBuffer +) { size_t rleCompressedSize = - extrle::encode16(data.get(), CHUNK_DATA_LEN, rleBuffer.data()); + extrle::encode16(data, CHUNK_DATA_LEN, rleBuffer.data()); const auto gzipCompressedData = gzip::compress( rleBuffer.data(), rleCompressedSize ); - auto metadataBytes = chunk.blocksMetadata.serialize(); + auto metadataBytes = metadata.serialize(); ByteBuilder builder(2 + 8 + gzipCompressedData.size() + metadataBytes.size()); builder.put(HAS_VOXELS | HAS_METADATA); // flags @@ -35,6 +31,14 @@ std::vector compressed_chunks::encode(const Chunk& chunk) { return builder.build(); } +std::vector compressed_chunks::encode(const Chunk& chunk) { + auto data = chunk.encode(); + + /// world.get_chunk_data is only available in the main Lua state + static util::Buffer rleBuffer(CHUNK_DATA_LEN * 2); + return encode(data.get(), chunk.blocksMetadata, rleBuffer); +} + static void read_voxel_data(ByteReader& reader, util::Buffer& dst) { size_t gzipCompressedSize = reader.getInt32(); diff --git a/src/voxels/compressed_chunks.hpp b/src/voxels/compressed_chunks.hpp index 2181669c..dd00bc66 100644 --- a/src/voxels/compressed_chunks.hpp +++ b/src/voxels/compressed_chunks.hpp @@ -1,13 +1,19 @@ #pragma once #include "typedefs.hpp" +#include "Chunk.hpp" +#include "coders/byte_utils.hpp" #include -class Chunk; class WorldRegions; namespace compressed_chunks { + std::vector encode( + const ubyte* voxelData, + const BlocksMetadata& metadata, + util::Buffer& rleBuffer + ); std::vector encode(const Chunk& chunk); void decode(Chunk& chunk, const ubyte* src, size_t size); void save(int x, int z, std::vector bytes, WorldRegions& regions); From d113cfa86c6400fbb67e3cd86155f47e5ace703c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Jan 2025 01:33:01 +0300 Subject: [PATCH 04/44] update doc/*/scripting/builtins/libworld.md --- doc/en/scripting/builtins/libworld.md | 11 ++++++++++- doc/ru/scripting/builtins/libworld.md | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/doc/en/scripting/builtins/libworld.md b/doc/en/scripting/builtins/libworld.md index 97c6fdee..b2453b34 100644 --- a/doc/en/scripting/builtins/libworld.md +++ b/doc/en/scripting/builtins/libworld.md @@ -49,10 +49,11 @@ world.is_night() -> bool world.count_chunks() -> int -- Returns the compressed chunk data to send. +-- If the chunk is not loaded, returns the saved data. -- Currently includes: -- 1. Voxel data (id and state) -- 2. Voxel metadata (fields) -world.get_chunk_data(x: int, z: int) -> Bytearray +world.get_chunk_data(x: int, z: int) -> Bytearray or nil -- Modifies the chunk based on the compressed data. -- Returns true if the chunk exists. @@ -61,4 +62,12 @@ world.set_chunk_data( -- compressed chunk data data: Bytearray ) -> bool + +-- Saves chunk data to region. +-- Changes will be written to file only on world save. +world.save_chunk_data( + x: int, z: int, + -- compressed chunk data + data: Bytearray +) ``` diff --git a/doc/ru/scripting/builtins/libworld.md b/doc/ru/scripting/builtins/libworld.md index a7e0e5a6..5713a328 100644 --- a/doc/ru/scripting/builtins/libworld.md +++ b/doc/ru/scripting/builtins/libworld.md @@ -48,10 +48,11 @@ world.is_night() -> bool world.count_chunks() -> int -- Возвращает сжатые данные чанка для отправки. +-- Если чанк не загружен, возвращает сохранённые данные. -- На данный момент включает: -- 1. Данные вокселей (id и состояние) -- 2. Метаданные (поля) вокселей -world.get_chunk_data(x: int, z: int) -> Bytearray +world.get_chunk_data(x: int, z: int) -> Bytearray или nil -- Изменяет чанк на основе сжатых данных. -- Возвращает true если чанк существует. @@ -60,4 +61,12 @@ world.set_chunk_data( -- сжатые данные чанка data: Bytearray ) -> bool + +-- Сохраняет данные чанка в регион. +-- Изменения будет записаны в файл только после сохранения мира. +world.save_chunk_data( + x: int, z: int, + -- сжатые данные чанка + data: Bytearray +) ``` From 92f226cbcf7dda264fcf3472288b772d4d686559 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Jan 2025 04:39:37 +0300 Subject: [PATCH 05/44] miscellaneous fixes --- res/layouts/ingame_chat.xml.lua | 4 +++- res/modules/internal/gui_util.lua | 2 +- res/modules/internal/stdcomp.lua | 3 +++ res/scripts/stdlib.lua | 7 ++++--- src/frontend/screens/LevelScreen.cpp | 4 +++- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/res/layouts/ingame_chat.xml.lua b/res/layouts/ingame_chat.xml.lua index 52f38ce7..ec4e12b0 100644 --- a/res/layouts/ingame_chat.xml.lua +++ b/res/layouts/ingame_chat.xml.lua @@ -9,7 +9,9 @@ local animation_fps = 30 local function remove_line(line) document[line[1]]:destruct() - time.post_runnable(function() document.root:reposition() end) + time.post_runnable(function() + if world.is_open() then document.root:reposition() end + end) end local function update_line(line, uptime) diff --git a/res/modules/internal/gui_util.lua b/res/modules/internal/gui_util.lua index 3cf84a33..294a7c79 100644 --- a/res/modules/internal/gui_util.lua +++ b/res/modules/internal/gui_util.lua @@ -47,7 +47,7 @@ function gui_util.add_page_dispatcher(dispatcher) table.insert(gui_util.local_dispatchers, dispatcher) end -function gui_util.reset_local() +function gui_util.__reset_local() gui_util.local_dispatchers = {} end diff --git a/res/modules/internal/stdcomp.lua b/res/modules/internal/stdcomp.lua index 9e208038..bdb2468f 100644 --- a/res/modules/internal/stdcomp.lua +++ b/res/modules/internal/stdcomp.lua @@ -132,5 +132,8 @@ return { end return values end + end, + __reset = function() + entities = {} end } diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 78228254..9ee20241 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -343,8 +343,8 @@ function __vc_on_hud_open() end) end) input.add_callback("key:escape", function() - if hud.is_paused() then - hud.resume() + if menu.page ~= "" then + menu:reset() elseif hud.is_inventory_open() then hud.close_inventory() else @@ -375,7 +375,8 @@ end function __vc_on_world_quit() _rules.clear() - gui_util:reset_local() + gui_util:__reset_local() + stdcomp.__reset() end local __vc_coroutines = {} diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 0dce2bc0..0e9eb609 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -117,7 +117,9 @@ void LevelScreen::initializePack(ContentPackRuntime* pack) { } LevelScreen::~LevelScreen() { - saveWorldPreview(); + if (!controller->getLevel()->getWorld()->isNameless()) { + saveWorldPreview(); + } scripting::on_frontend_close(); // unblock all bindings Events::enableBindings(); From 57356e1d64d6d9d7e8d59b078543b290e998ad00 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 01:27:53 +0300 Subject: [PATCH 06/44] fix lamp material --- res/content/base/blocks/lamp.json | 1 + 1 file changed, 1 insertion(+) diff --git a/res/content/base/blocks/lamp.json b/res/content/base/blocks/lamp.json index 4a1f1ce7..b8f91100 100644 --- a/res/content/base/blocks/lamp.json +++ b/res/content/base/blocks/lamp.json @@ -2,5 +2,6 @@ "texture": "lamp", "emission": [15, 14, 13], "shadeless": true, + "material": "base:glass", "base:durability": 0.3 } From e247902cc6ffdaa6beab391fcfdaea7f021ab063 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 02:30:59 +0300 Subject: [PATCH 07/44] fix data_buffer:put_number --- res/modules/bit_converter.lua | 4 ++-- res/modules/data_buffer.lua | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/res/modules/bit_converter.lua b/res/modules/bit_converter.lua index c2ada355..b72dc311 100644 --- a/res/modules/bit_converter.lua +++ b/res/modules/bit_converter.lua @@ -313,8 +313,8 @@ function bit_converter.bytes_to_uint16(bytes, order) return bit.bor( - bit.lshift(bytes[1], 8), - bytes[2], 0) + bit.lshift(bytes[2], 8), + bytes[1], 0) end function bit_converter.bytes_to_int64(bytes, order) diff --git a/res/modules/data_buffer.lua b/res/modules/data_buffer.lua index 91dce29c..ad9ad486 100644 --- a/res/modules/data_buffer.lua +++ b/res/modules/data_buffer.lua @@ -144,31 +144,31 @@ function data_buffer:put_number(num) if math.floor(num) ~= num then type = TYPE_FLOAT64 - bytes = bit_converter.float64_to_bytes(num) + bytes = bit_converter.float64_to_bytes(num, self.order) elseif num == 0 then type = TYPE_ZERO bytes = { } elseif num > 0 then if num <= MAX_UINT16 then type = TYPE_UINT16 - bytes = bit_converter.uint16_to_bytes(num) + bytes = bit_converter.uint16_to_bytes(num, self.order) elseif num <= MAX_UINT32 then type = TYPE_UINT32 - bytes = bit_converter.uint32_to_bytes(num) + bytes = bit_converter.uint32_to_bytes(num, self.order) elseif num <= MAX_INT64 then type = TYPE_INT64 - bytes = bit_converter.int64_to_bytes(num) + bytes = bit_converter.int64_to_bytes(num, self.order) end elseif num < 0 then if num >= MIN_INT16 then type = TYPE_SINT16 - bytes = bit_converter.sint16_to_bytes(num) + bytes = bit_converter.sint16_to_bytes(num, self.order) elseif num >= MIN_INT32 then type = TYPE_SINT32 - bytes = bit_converter.sint32_to_bytes(num) + bytes = bit_converter.sint32_to_bytes(num, self.order) elseif num >= MIN_INT64 then type = TYPE_INT64 - bytes = bit_converter.int64_to_bytes(num) + bytes = bit_converter.int64_to_bytes(num, self.order) end end From 266f3059b4ae56a0aed852e942688f85671d81a3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 04:17:29 +0300 Subject: [PATCH 08/44] fix --- src/graphics/ui/GUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 2cc28024..08485201 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -202,7 +202,7 @@ void GUI::act(float delta, const Viewport& vp) { void GUI::postAct() { while (!postRunnables.empty()) { - runnable callback = postRunnables.back(); + runnable callback = postRunnables.front(); postRunnables.pop(); callback(); } From 85600eafea0980acb8ec779a7859495d92ff1073 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 04:31:33 +0300 Subject: [PATCH 09/44] fix in-game chat --- res/layouts/ingame_chat.xml.lua | 19 ++++++------------- src/engine/Engine.cpp | 2 +- src/graphics/ui/elements/Panel.cpp | 1 + 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/res/layouts/ingame_chat.xml.lua b/res/layouts/ingame_chat.xml.lua index ec4e12b0..dce62988 100644 --- a/res/layouts/ingame_chat.xml.lua +++ b/res/layouts/ingame_chat.xml.lua @@ -7,18 +7,11 @@ local initialized = false local max_lines = 15 local animation_fps = 30 -local function remove_line(line) - document[line[1]]:destruct() - time.post_runnable(function() - if world.is_open() then document.root:reposition() end - end) -end - local function update_line(line, uptime) local diff = uptime - line[2] if diff > timeout then - remove_line(line) - table.insert(dead_lines, i) + document[line[1]]:destruct() + table.insert(dead_lines, table.index(lines, line)) elseif diff > timeout-fadeout then local opacity = (timeout - diff) / fadeout document[line[1]].color = {0, 0, 0, opacity * 80} @@ -27,16 +20,16 @@ local function update_line(line, uptime) end events.on("core:chat", function(message) + while #lines >= max_lines do + document[lines[1][1]]:destruct() + table.remove(lines, 1) + end local current_time = time.uptime() local id = 'l'..tostring(nextid) document.root:add(gui.template("chat_line", {id=id})) document.root:reposition() document[id.."L"].text = message nextid = nextid + 1 - if #lines == max_lines then - remove_line(lines[1]) - table.remove(lines, 1) - end table.insert(lines, {id, current_time}) end) diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index ce29e8c1..c9de5a64 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -199,6 +199,7 @@ void Engine::updateFrontend() { audio::update(delta); gui->act(delta, Viewport(Window::width, Window::height)); screen->update(delta); + gui->postAct(); } void Engine::nextFrame() { @@ -217,7 +218,6 @@ void Engine::renderFrame() { Viewport viewport(Window::width, Window::height); DrawContext ctx(nullptr, viewport, nullptr); gui->draw(ctx, *assets); - gui->postAct(); } void Engine::saveSettings() { diff --git a/src/graphics/ui/elements/Panel.cpp b/src/graphics/ui/elements/Panel.cpp index d90b8830..d76866f0 100644 --- a/src/graphics/ui/elements/Panel.cpp +++ b/src/graphics/ui/elements/Panel.cpp @@ -53,6 +53,7 @@ void Panel::cropToContent() { void Panel::fullRefresh() { refresh(); cropToContent(); + reposition(); Container::fullRefresh(); } From 13fde2116d095b9393c4f5804ba23071e5f56ad6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 04:42:08 +0300 Subject: [PATCH 10/44] fix textbox horizontal scroll & fix console log width --- res/layouts/console.xml | 4 ++-- src/graphics/ui/elements/TextBox.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/res/layouts/console.xml b/res/layouts/console.xml index 43e72dd8..18d72163 100644 --- a/res/layouts/console.xml +++ b/res/layouts/console.xml @@ -12,7 +12,7 @@ + size-func="unpack(vec2.add(gui.get_viewport(), {-350,-100}))"> diff --git a/src/graphics/ui/elements/TextBox.cpp b/src/graphics/ui/elements/TextBox.cpp index f1ed6608..12f262f1 100644 --- a/src/graphics/ui/elements/TextBox.cpp +++ b/src/graphics/ui/elements/TextBox.cpp @@ -826,7 +826,7 @@ void TextBox::setCaret(size_t position) { scrolled(-glm::ceil(offset/static_cast(scrollStep)+0.5f)); } uint lcaret = caret - label->getTextLineOffset(line); - int realoffset = font->calcWidth(input, lcaret)-int(textOffset)+2; + int realoffset = font->calcWidth(input, lcaret)-int(textOffset) - padding.x; if (realoffset-width > 0) { setTextOffset(textOffset + realoffset-width); } else if (realoffset < 0) { From f2101f6504a45ea6639c7842760e09a9ac377e73 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 05:31:07 +0300 Subject: [PATCH 11/44] add entity:set_enabled(...) --- doc/en/scripting/builtins/librules.md | 2 +- doc/en/scripting/ecs.md | 3 +++ doc/ru/scripting/ecs.md | 3 +++ res/modules/internal/stdcomp.lua | 20 ++++++++++++++++++-- src/data/dv.cpp | 3 +++ src/logic/scripting/scripting.cpp | 4 ++++ 6 files changed, 32 insertions(+), 3 deletions(-) diff --git a/doc/en/scripting/builtins/librules.md b/doc/en/scripting/builtins/librules.md index c4b1c377..acdf11d8 100644 --- a/doc/en/scripting/builtins/librules.md +++ b/doc/en/scripting/builtins/librules.md @@ -18,7 +18,7 @@ Creates a rule. If a handler is specified, returns the id for deletion. > Rules that have not been created can be used, but resetting via rules.reset will result in setting the value to nil. ```lua - rules.listen( +rules.listen( -- rule name name: str, -- value change handler function diff --git a/doc/en/scripting/ecs.md b/doc/en/scripting/ecs.md index 8763d981..90a64828 100644 --- a/doc/en/scripting/ecs.md +++ b/doc/en/scripting/ecs.md @@ -26,6 +26,9 @@ entity:get_uid() -> int entity:get_component(name: str) -> component or nil -- Checks for the presence of a component by name entity:has_component(name: str) -> bool + +-- Enables/disables the component +entity:set_enabled(name: str, enable: bool) ``` ## Built-in components diff --git a/doc/ru/scripting/ecs.md b/doc/ru/scripting/ecs.md index 3e8e00e5..db44a1ac 100644 --- a/doc/ru/scripting/ecs.md +++ b/doc/ru/scripting/ecs.md @@ -26,6 +26,9 @@ entity:get_uid() -> int entity:get_component(name: str) -> компонент или nil -- Проверяет наличие компонента по имени entity:has_component(name: str) -> bool + +-- Включает/выключает компонент по имени +entity:set_enabled(name: str, enable: bool) ``` ## Встроенные компоненты diff --git a/res/modules/internal/stdcomp.lua b/res/modules/internal/stdcomp.lua index bdb2468f..a62989a9 100644 --- a/res/modules/internal/stdcomp.lua +++ b/res/modules/internal/stdcomp.lua @@ -68,6 +68,22 @@ local Entity = {__index={ def_index=function(self) return entities.get_def(self.eid) end, def_name=function(self) return entities.def_name(entities.get_def(self.eid)) end, get_player=function(self) return entities.get_player(self.eid) end, + set_enabled=function(self, name, flag) + local comp = self.components[name] + if comp then + if flag then + if comp.__disabled and comp.on_enable then + comp.on_enable() + end + comp.__disabled = nil + else + if not comp.__disabled and comp.on_disable then + comp.on_disable() + end + comp.__disabled = true + end + end + end, }} local entities = {} @@ -99,7 +115,7 @@ return { end for _, component in pairs(entity.components) do local callback = component.on_update - if callback then + if not component.__disabled and callback then local result, err = pcall(callback, tps) if err then debug.error(err) @@ -113,7 +129,7 @@ return { for _,entity in pairs(entities) do for _, component in pairs(entity.components) do local callback = component.on_render - if callback then + if not component.__disabled and callback then local result, err = pcall(callback, delta) if err then debug.error(err) diff --git a/src/data/dv.cpp b/src/data/dv.cpp index 5709fd84..cccf348e 100644 --- a/src/data/dv.cpp +++ b/src/data/dv.cpp @@ -104,6 +104,9 @@ namespace dv { } boolean_t value::asBoolean() const { + if (type == value_type::none) { + return false; + } check_type(type, value_type::boolean); return val.boolean; } diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index d58879d3..d9b15490 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -614,6 +614,10 @@ static void process_entity_callback( ) { auto L = lua::get_main_state(); lua::pushenv(L, *env); + if (lua::hasfield(L, "__disabled")) { + lua::pop(L); + return; + } if (lua::getfield(L, name)) { if (args) { lua::call_nothrow(L, args(L), 0); From 23c66654a21c60a0bf22ae87530fde26165bb8d1 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 05:56:14 +0300 Subject: [PATCH 12/44] add ENTITY_NONE, ENTITY_AUTO reserved entity id & update player.set_entity(...) --- src/constants.hpp | 1 + src/logic/scripting/lua/libs/libplayer.cpp | 4 +++- src/objects/Player.cpp | 4 ++-- src/objects/Player.hpp | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/constants.hpp b/src/constants.hpp index 6f4a6ce6..8755331d 100644 --- a/src/constants.hpp +++ b/src/constants.hpp @@ -27,6 +27,7 @@ inline constexpr blockid_t BLOCK_OBSTACLE = 1; inline constexpr blockid_t BLOCK_STRUCT_AIR = 2; inline constexpr itemid_t ITEM_EMPTY = 0; inline constexpr entityid_t ENTITY_NONE = 0; +inline constexpr entityid_t ENTITY_AUTO = std::numeric_limits::max(); inline constexpr int CHUNK_W = 16; inline constexpr int CHUNK_H = 256; diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index 12b78a97..d4e55b77 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -229,7 +229,9 @@ static int l_set_entity(lua::State* L) { if (player == nullptr) { return 0; } - if (auto entity = get_entity(L, 2)) { + if (lua::isnumber(L, 2)) { + player->setEntity(lua::tointeger(L, 2)); + } else if (auto entity = get_entity(L, 2)) { player->setEntity(entity->getUID()); } return 0; diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 777fd8ed..888fce96 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -62,7 +62,7 @@ Player::Player( Player::~Player() = default; void Player::updateEntity() { - if (eid == 0) { + if (eid == ENTITY_AUTO) { auto& def = level.content.entities.require("base:player"); eid = level.entities->spawn(def, getPosition()); if (auto entity = level.entities->get(eid)) { @@ -73,7 +73,7 @@ void Player::updateEntity() { if (auto entity = level.entities->get(eid)) { entity->setPlayer(id); } - } else if (chunks->getChunkByVoxel(position)) { + } else if (chunks->getChunkByVoxel(position) && eid != ENTITY_NONE) { logger.error() << "player entity despawned or deleted; " "will be respawned"; eid = 0; diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index b695c75e..4b9f2449 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -54,7 +54,7 @@ class Player : public Serializable { bool infiniteItems = true; bool instantDestruction = true; bool loadingChunks = true; - entityid_t eid; + entityid_t eid = ENTITY_AUTO; entityid_t selectedEid = 0; glm::vec3 rotation {}; From 94438924067d3a8da81fc5500eb5025e5a5e018c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 06:51:29 +0300 Subject: [PATCH 13/44] fixes --- src/objects/Player.cpp | 2 +- src/objects/Players.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 888fce96..9058717c 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -76,7 +76,7 @@ void Player::updateEntity() { } else if (chunks->getChunkByVoxel(position) && eid != ENTITY_NONE) { logger.error() << "player entity despawned or deleted; " "will be respawned"; - eid = 0; + eid = ENTITY_AUTO; } } diff --git a/src/objects/Players.cpp b/src/objects/Players.cpp index e200a20b..9c0e2603 100644 --- a/src/objects/Players.cpp +++ b/src/objects/Players.cpp @@ -37,7 +37,7 @@ Player* Players::create(int64_t id) { glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), - 0 + ENTITY_AUTO ); auto player = playerPtr.get(); add(std::move(playerPtr)); @@ -92,7 +92,7 @@ void Players::deserialize(const dv::value& src) { glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), - 0 + ENTITY_AUTO ); auto player = playerPtr.get(); player->deserialize(playerMap); From b12982655de6f991852e99330a868afd33ae14ac Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Jan 2025 09:39:06 +0300 Subject: [PATCH 14/44] fix gui.alert --- res/scripts/stdlib.lua | 18 ++++++++++++++++-- src/graphics/ui/gui_util.cpp | 19 ++++++++++--------- src/logic/scripting/lua/lua_wrapper.hpp | 3 +++ src/logic/scripting/scripting.cpp | 13 ++++++++----- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 9ee20241..67cdd0fe 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -37,7 +37,10 @@ local function complete_app_lib(app) app.tick = coroutine.yield app.get_version = core.get_version app.get_setting_info = core.get_setting_info - app.load_content = core.load_content + app.load_content = function() + core.load_content() + app.tick() + end app.reset_content = core.reset_content app.is_content_loaded = core.is_content_loaded @@ -416,7 +419,18 @@ end function start_coroutine(chunk, name) local co = coroutine.create(function() - local status, error = xpcall(chunk, __vc__error) + local status, error = xpcall(chunk, function(...) + gui.alert(debug.traceback(), function() + if world.is_open() then + __vc_app.close_world() + else + __vc_app.reset_content() + menu:reset() + menu.page = "main" + end + end) + return ... + end) if not status then debug.error(error) end diff --git a/src/graphics/ui/gui_util.cpp b/src/graphics/ui/gui_util.cpp index b84dcfd0..04026132 100644 --- a/src/graphics/ui/gui_util.cpp +++ b/src/graphics/ui/gui_util.cpp @@ -34,13 +34,14 @@ void guiutil::alert( auto panel = std::make_shared(glm::vec2(500, 300), glm::vec4(4.0f), 4.0f); panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f)); - auto menu = engine.getGUI()->getMenu(); - runnable on_hidden_final = [on_hidden, menu, &engine]() { - menu->removePage(""); + auto menuPtr = engine.getGUI()->getMenu(); + auto& menu = *menuPtr; + runnable on_hidden_final = [on_hidden, &menu, &engine]() { + menu.removePage(""); if (on_hidden) { on_hidden(); } else { - menu->back(); + menu.back(); } }; @@ -50,21 +51,21 @@ void guiutil::alert( panel->add(label); panel->add(std::make_shared