diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index 6d657899..8d3b07f8 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -119,13 +119,13 @@ block.seek_origin(x: int, y: int, z: int) -> int, int, int Part of a voxel data used for scripting. Size: 8 bit. -```python +```lua block.get_user_bits(x: int, y: int, z: int, offset: int, bits: int) -> int ``` Get specified bits as an unsigned integer. -```python +```lua block.set_user_bits(x: int, y: int, z: int, offset: int, bits: int, value: int) -> int ``` Set specified bits. @@ -151,6 +151,21 @@ The function returns a table with the results or nil if the ray does not hit any The result will use the destination table instead of creating a new one if the optional argument specified. +## Model + +Block model information. + +```lua +-- returns block model type (block/aabb/custom/...) +block.get_model(id: int) -> str + +-- returns block model name +block.model_name(id: int) -> str + +-- returns array of 6 textures assigned to sides of block +block.get_textures(id: int) -> string table +``` + ## Data fields ```lua diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index e5bdbb44..67547909 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -171,6 +171,9 @@ block.get_hitbox(id: int, rotation_index: int) -> {vec3, vec3} -- возвращает тип модели блока (block/aabb/custom/...) block.get_model(id: int) -> str +-- возвращает имя модели блока +block.model_name(id: int) -> str + -- возвращает массив из 6 текстур, назначенных на стороны блока block.get_textures(id: int) -> таблица строк ``` diff --git a/flake.nix b/flake.nix index 2c392d27..bc9ead2b 100644 --- a/flake.nix +++ b/flake.nix @@ -1,16 +1,69 @@ { + description = "VoxelCore – voxel game engine in C++"; + inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem (system: { - devShells.default = with nixpkgs.legacyPackages.${system}; mkShell { - nativeBuildInputs = [ cmake pkg-config ]; - buildInputs = [ glm glfw glew zlib libpng libvorbis openal luajit curl ]; # libglvnd - packages = [ glfw mesa freeglut entt ]; - LD_LIBRARY_PATH = "${wayland}/lib:$LD_LIBRARY_PATH"; + outputs = + { + self, + nixpkgs, + flake-utils, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + voxel-core = pkgs.stdenv.mkDerivation { + name = "voxel-core"; + + src = ./.; + + nativeBuildInputs = with pkgs; [ + cmake + pkg-config + ]; + + buildInputs = with pkgs; [ + glm + glfw + glew + zlib + libpng + libvorbis + openal + luajit + curl + entt + mesa + freeglut + ]; # libglvnd + + packages = with pkgs; [ + glfw + mesa + freeglut + entt + ]; + cmakeFlags = [ + "-DCMAKE_PREFIX_PATH=${pkgs.entt}" + "-DCMAKE_INCLUDE_PATH=${pkgs.entt}/include" + ]; + + installPhase = '' + mkdir -p $out/bin + cp VoxelEngine $out/bin/ + ''; }; - }); + in + { + packages.default = voxel-core; + apps.default = { + type = "app"; + program = "${voxel-core}/bin/VoxelCore"; + }; + } + ); } diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 660b63fc..39271224 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -538,6 +538,7 @@ void Hud::closeInventory() { exchangeSlotInv = nullptr; inventoryOpen = false; inventoryView = nullptr; + secondInvView = nullptr; secondUI = nullptr; for (auto& element : elements) { @@ -597,6 +598,9 @@ void Hud::remove(const std::shared_ptr& node) { } } cleanup(); + if (node == secondUI) { + closeInventory(); + } } void Hud::setDebug(bool flag) { diff --git a/src/graphics/core/Batch3D.cpp b/src/graphics/core/Batch3D.cpp index 8f222a51..df6fdef7 100644 --- a/src/graphics/core/Batch3D.cpp +++ b/src/graphics/core/Batch3D.cpp @@ -126,7 +126,15 @@ void Batch3D::sprite( float scale = 1.0f / static_cast(atlasRes); float u = (index % atlasRes) * scale; float v = 1.0f - ((index / atlasRes) * scale) - scale; - sprite(pos, up, right, w, h, UVRegion(u, v, u+scale, v+scale), tint); + sprite( + pos + right * w + up * h, // revert centering + up, + right, + w, + h, + UVRegion(u, v, u + scale, v + scale), + tint + ); } void Batch3D::sprite( diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index bb816c37..4100e7b2 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -171,6 +171,9 @@ const Mesh* ChunksRenderer::retrieveChunk( if (mesh == nullptr) { return nullptr; } + if (chunk->flags.dirtyHeights) { + chunk->updateHeights(); + } if (culling) { glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); glm::vec3 max( diff --git a/src/graphics/render/TextsRenderer.cpp b/src/graphics/render/TextsRenderer.cpp index 9e4210df..4b905e13 100644 --- a/src/graphics/render/TextsRenderer.cpp +++ b/src/graphics/render/TextsRenderer.cpp @@ -51,6 +51,7 @@ void TextsRenderer::renderNote( glm::vec3 yvec = note.getAxisY(); int width = font.calcWidth(text, text.length()); + int height = font.getLineHeight(); if (preset.displayMode == NoteDisplayMode::Y_FREE_BILLBOARD || preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { xvec = camera.position - pos; @@ -96,8 +97,11 @@ void TextsRenderer::renderNote( pos = screenPos / screenPos.w; } - } else if (!frustum.isBoxVisible(pos - xvec * (width * 0.5f * preset.scale), - pos + xvec * (width * 0.5f * preset.scale))) { + } else if (!frustum.isBoxVisible( + pos - xvec * (width * 0.5f) * preset.scale, + pos + xvec * (width * 0.5f) * preset.scale + + yvec * static_cast(height) * preset.scale + )) { return; } auto color = preset.color; diff --git a/src/logic/scripting/lua/libs/lib__rigidbody.cpp b/src/logic/scripting/lua/libs/lib__rigidbody.cpp index d0e66940..f5558ac4 100644 --- a/src/logic/scripting/lua/libs/lib__rigidbody.cpp +++ b/src/logic/scripting/lua/libs/lib__rigidbody.cpp @@ -54,7 +54,7 @@ static int l_get_gravity_scale(lua::State* L) { static int l_set_gravity_scale(lua::State* L) { if (auto entity = get_entity(L, 1)) { - entity->getRigidbody().hitbox.gravityScale = lua::tonumber(L, 2); + entity->getRigidbody().hitbox.gravityScale = lua::tovec3(L, 2).y; } return 0; } diff --git a/src/logic/scripting/lua/libs/libblock.cpp b/src/logic/scripting/lua/libs/libblock.cpp index bb527c9b..52e2931c 100644 --- a/src/logic/scripting/lua/libs/libblock.cpp +++ b/src/logic/scripting/lua/libs/libblock.cpp @@ -101,12 +101,9 @@ static int l_set(lua::State* L) { if (static_cast(id) >= indices->blocks.count()) { return 0; } - int cx = floordiv(x); - int cz = floordiv(z); - if (!blocks_agent::get_chunk(*level->chunks, cx, cz)) { + if (!blocks_agent::set(*level->chunks, x, y, z, id, int2blockstate(state))) { return 0; } - blocks_agent::set(*level->chunks, x, y, z, id, int2blockstate(state)); auto chunksController = controller->getChunksController(); if (chunksController == nullptr) { @@ -364,6 +361,19 @@ static int l_get_textures(lua::State* L) { return 0; } + +static int l_model_name(lua::State* L) { + if (auto def = require_block(L)) { + // TODO: variant argument + const auto& modelName = def->defaults.model.name; + if (modelName.empty()) { + return lua::pushlstring(L, def->name + ".model"); + } + return lua::pushlstring(L, modelName); + } + return 0; +} + static int l_get_model(lua::State* L) { if (auto def = require_block(L)) { // TODO: variant argument @@ -713,6 +723,7 @@ const luaL_Reg blocklib[] = { {"get_size", lua::wrap}, {"is_segment", lua::wrap}, {"seek_origin", lua::wrap}, + {"model_name", lua::wrap}, {"get_textures", lua::wrap}, {"get_model", lua::wrap}, {"get_hitbox", lua::wrap}, diff --git a/src/logic/scripting/lua/libs/libhud.cpp b/src/logic/scripting/lua/libs/libhud.cpp index 988685cc..432d8eb6 100644 --- a/src/logic/scripting/lua/libs/libhud.cpp +++ b/src/logic/scripting/lua/libs/libhud.cpp @@ -46,7 +46,7 @@ static int l_open(lua::State* L) { } return lua::pushinteger(L, hud->openInventory( layout, - level->inventories->get(invid), + lua::isnoneornil(L, 3) ? nullptr : level->inventories->get(invid), playerInventory )->getId()); } diff --git a/src/voxels/Chunk.cpp b/src/voxels/Chunk.cpp index 2c1f4fd8..e6da850e 100644 --- a/src/voxels/Chunk.cpp +++ b/src/voxels/Chunk.cpp @@ -14,6 +14,7 @@ Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos) { } void Chunk::updateHeights() { + flags.dirtyHeights = false; for (uint i = 0; i < CHUNK_VOL; i++) { if (voxels[i].id != 0) { bottom = i / (CHUNK_D * CHUNK_W); diff --git a/src/voxels/Chunk.hpp b/src/voxels/Chunk.hpp index 3ce6e641..a15907f0 100644 --- a/src/voxels/Chunk.hpp +++ b/src/voxels/Chunk.hpp @@ -37,6 +37,7 @@ public: bool loadedLights : 1; bool entities : 1; bool blocksData : 1; + bool dirtyHeights : 1; } flags {}; /// @brief Block inventories map where key is index of block in voxels array diff --git a/src/voxels/blocks_agent.cpp b/src/voxels/blocks_agent.cpp index a23fa9ef..d56b1838 100644 --- a/src/voxels/blocks_agent.cpp +++ b/src/voxels/blocks_agent.cpp @@ -7,7 +7,7 @@ using namespace blocks_agent; template -static inline void set_block( +static inline bool set_block( Storage& chunks, int32_t x, int32_t y, @@ -16,14 +16,14 @@ static inline void set_block( blockstate state ) { if (y < 0 || y >= CHUNK_H) { - return; + return false; } const auto& indices = chunks.getContentIndices(); int cx = floordiv(x); int cz = floordiv(z); Chunk* chunk = get_chunk(chunks, cx, cz); if (chunk == nullptr) { - return; + return false; } int lx = x - cx * CHUNK_W; int lz = z - cz * CHUNK_D; @@ -60,7 +60,8 @@ static inline void set_block( else if (y + 1 > chunk->top) chunk->top = y + 1; else if (id == 0) - chunk->updateHeights(); + chunk->flags.dirtyHeights = true; + if (lx == 0 && (chunk = get_chunk(chunks, cx - 1, cz))) { chunk->flags.modified = true; @@ -74,9 +75,10 @@ static inline void set_block( if (lz == CHUNK_D - 1 && (chunk = get_chunk(chunks, cx, cz + 1))) { chunk->flags.modified = true; } + return true; } -void blocks_agent::set( +bool blocks_agent::set( Chunks& chunks, int32_t x, int32_t y, @@ -84,10 +86,10 @@ void blocks_agent::set( uint32_t id, blockstate state ) { - set_block(chunks, x, y, z, id, state); + return set_block(chunks, x, y, z, id, state); } -void blocks_agent::set( +bool blocks_agent::set( GlobalChunks& chunks, int32_t x, int32_t y, @@ -95,7 +97,7 @@ void blocks_agent::set( uint32_t id, blockstate state ) { - set_block(chunks, x, y, z, id, state); + return set_block(chunks, x, y, z, id, state); } template diff --git a/src/voxels/blocks_agent.hpp b/src/voxels/blocks_agent.hpp index 34fde035..efecf4e3 100644 --- a/src/voxels/blocks_agent.hpp +++ b/src/voxels/blocks_agent.hpp @@ -119,7 +119,7 @@ inline bool is_replaceable_at(const Storage& chunks, int32_t x, int32_t y, int32 /// @param z block position Z /// @param id new block id /// @param state new block state -void set( +bool set( Chunks& chunks, int32_t x, int32_t y, @@ -135,7 +135,7 @@ void set( /// @param z block position Z /// @param id new block id /// @param state new block state -void set( +bool set( GlobalChunks& chunks, int32_t x, int32_t y,