Merge branch 'dev' into more-about-projects

This commit is contained in:
MihailRis 2025-08-16 13:57:51 +03:00
commit dc0e388eec
14 changed files with 134 additions and 29 deletions

View File

@ -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. 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 block.get_user_bits(x: int, y: int, z: int, offset: int, bits: int) -> int
``` ```
Get specified bits as an unsigned integer. 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 block.set_user_bits(x: int, y: int, z: int, offset: int, bits: int, value: int) -> int
``` ```
Set specified bits. 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. 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 ## Data fields
```lua ```lua

View File

@ -171,6 +171,9 @@ block.get_hitbox(id: int, rotation_index: int) -> {vec3, vec3}
-- возвращает тип модели блока (block/aabb/custom/...) -- возвращает тип модели блока (block/aabb/custom/...)
block.get_model(id: int) -> str block.get_model(id: int) -> str
-- возвращает имя модели блока
block.model_name(id: int) -> str
-- возвращает массив из 6 текстур, назначенных на стороны блока -- возвращает массив из 6 текстур, назначенных на стороны блока
block.get_textures(id: int) -> таблица строк block.get_textures(id: int) -> таблица строк
``` ```

View File

@ -1,16 +1,69 @@
{ {
description = "VoxelCore voxel game engine in C++";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
}; };
outputs = { self, nixpkgs, flake-utils }: outputs =
flake-utils.lib.eachDefaultSystem (system: { {
devShells.default = with nixpkgs.legacyPackages.${system}; mkShell { self,
nativeBuildInputs = [ cmake pkg-config ]; nixpkgs,
buildInputs = [ glm glfw glew zlib libpng libvorbis openal luajit curl ]; # libglvnd flake-utils,
packages = [ glfw mesa freeglut entt ]; }:
LD_LIBRARY_PATH = "${wayland}/lib:$LD_LIBRARY_PATH"; 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";
};
}
);
} }

View File

@ -538,6 +538,7 @@ void Hud::closeInventory() {
exchangeSlotInv = nullptr; exchangeSlotInv = nullptr;
inventoryOpen = false; inventoryOpen = false;
inventoryView = nullptr; inventoryView = nullptr;
secondInvView = nullptr;
secondUI = nullptr; secondUI = nullptr;
for (auto& element : elements) { for (auto& element : elements) {
@ -597,6 +598,9 @@ void Hud::remove(const std::shared_ptr<UINode>& node) {
} }
} }
cleanup(); cleanup();
if (node == secondUI) {
closeInventory();
}
} }
void Hud::setDebug(bool flag) { void Hud::setDebug(bool flag) {

View File

@ -126,7 +126,15 @@ void Batch3D::sprite(
float scale = 1.0f / static_cast<float>(atlasRes); float scale = 1.0f / static_cast<float>(atlasRes);
float u = (index % atlasRes) * scale; float u = (index % atlasRes) * scale;
float v = 1.0f - ((index / atlasRes) * scale) - 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( void Batch3D::sprite(

View File

@ -171,6 +171,9 @@ const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(
if (mesh == nullptr) { if (mesh == nullptr) {
return nullptr; return nullptr;
} }
if (chunk->flags.dirtyHeights) {
chunk->updateHeights();
}
if (culling) { if (culling) {
glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D);
glm::vec3 max( glm::vec3 max(

View File

@ -51,6 +51,7 @@ void TextsRenderer::renderNote(
glm::vec3 yvec = note.getAxisY(); glm::vec3 yvec = note.getAxisY();
int width = font.calcWidth(text, text.length()); int width = font.calcWidth(text, text.length());
int height = font.getLineHeight();
if (preset.displayMode == NoteDisplayMode::Y_FREE_BILLBOARD || if (preset.displayMode == NoteDisplayMode::Y_FREE_BILLBOARD ||
preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) { preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) {
xvec = camera.position - pos; xvec = camera.position - pos;
@ -96,8 +97,11 @@ void TextsRenderer::renderNote(
pos = screenPos / screenPos.w; pos = screenPos / screenPos.w;
} }
} else if (!frustum.isBoxVisible(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,
pos + xvec * (width * 0.5f) * preset.scale +
yvec * static_cast<float>(height) * preset.scale
)) {
return; return;
} }
auto color = preset.color; auto color = preset.color;

View File

@ -54,7 +54,7 @@ static int l_get_gravity_scale(lua::State* L) {
static int l_set_gravity_scale(lua::State* L) { static int l_set_gravity_scale(lua::State* L) {
if (auto entity = get_entity(L, 1)) { 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; return 0;
} }

View File

@ -101,12 +101,9 @@ static int l_set(lua::State* L) {
if (static_cast<size_t>(id) >= indices->blocks.count()) { if (static_cast<size_t>(id) >= indices->blocks.count()) {
return 0; return 0;
} }
int cx = floordiv<CHUNK_W>(x); if (!blocks_agent::set(*level->chunks, x, y, z, id, int2blockstate(state))) {
int cz = floordiv<CHUNK_D>(z);
if (!blocks_agent::get_chunk(*level->chunks, cx, cz)) {
return 0; return 0;
} }
blocks_agent::set(*level->chunks, x, y, z, id, int2blockstate(state));
auto chunksController = controller->getChunksController(); auto chunksController = controller->getChunksController();
if (chunksController == nullptr) { if (chunksController == nullptr) {
@ -364,6 +361,19 @@ static int l_get_textures(lua::State* L) {
return 0; 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) { static int l_get_model(lua::State* L) {
if (auto def = require_block(L)) { if (auto def = require_block(L)) {
// TODO: variant argument // TODO: variant argument
@ -713,6 +723,7 @@ const luaL_Reg blocklib[] = {
{"get_size", lua::wrap<l_get_size>}, {"get_size", lua::wrap<l_get_size>},
{"is_segment", lua::wrap<l_is_segment>}, {"is_segment", lua::wrap<l_is_segment>},
{"seek_origin", lua::wrap<l_seek_origin>}, {"seek_origin", lua::wrap<l_seek_origin>},
{"model_name", lua::wrap<l_model_name>},
{"get_textures", lua::wrap<l_get_textures>}, {"get_textures", lua::wrap<l_get_textures>},
{"get_model", lua::wrap<l_get_model>}, {"get_model", lua::wrap<l_get_model>},
{"get_hitbox", lua::wrap<l_get_hitbox>}, {"get_hitbox", lua::wrap<l_get_hitbox>},

View File

@ -46,7 +46,7 @@ static int l_open(lua::State* L) {
} }
return lua::pushinteger(L, hud->openInventory( return lua::pushinteger(L, hud->openInventory(
layout, layout,
level->inventories->get(invid), lua::isnoneornil(L, 3) ? nullptr : level->inventories->get(invid),
playerInventory playerInventory
)->getId()); )->getId());
} }

View File

@ -14,6 +14,7 @@ Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos) {
} }
void Chunk::updateHeights() { void Chunk::updateHeights() {
flags.dirtyHeights = false;
for (uint i = 0; i < CHUNK_VOL; i++) { for (uint i = 0; i < CHUNK_VOL; i++) {
if (voxels[i].id != 0) { if (voxels[i].id != 0) {
bottom = i / (CHUNK_D * CHUNK_W); bottom = i / (CHUNK_D * CHUNK_W);

View File

@ -37,6 +37,7 @@ public:
bool loadedLights : 1; bool loadedLights : 1;
bool entities : 1; bool entities : 1;
bool blocksData : 1; bool blocksData : 1;
bool dirtyHeights : 1;
} flags {}; } flags {};
/// @brief Block inventories map where key is index of block in voxels array /// @brief Block inventories map where key is index of block in voxels array

View File

@ -7,7 +7,7 @@
using namespace blocks_agent; using namespace blocks_agent;
template <class Storage> template <class Storage>
static inline void set_block( static inline bool set_block(
Storage& chunks, Storage& chunks,
int32_t x, int32_t x,
int32_t y, int32_t y,
@ -16,14 +16,14 @@ static inline void set_block(
blockstate state blockstate state
) { ) {
if (y < 0 || y >= CHUNK_H) { if (y < 0 || y >= CHUNK_H) {
return; return false;
} }
const auto& indices = chunks.getContentIndices(); const auto& indices = chunks.getContentIndices();
int cx = floordiv<CHUNK_W>(x); int cx = floordiv<CHUNK_W>(x);
int cz = floordiv<CHUNK_D>(z); int cz = floordiv<CHUNK_D>(z);
Chunk* chunk = get_chunk(chunks, cx, cz); Chunk* chunk = get_chunk(chunks, cx, cz);
if (chunk == nullptr) { if (chunk == nullptr) {
return; return false;
} }
int lx = x - cx * CHUNK_W; int lx = x - cx * CHUNK_W;
int lz = z - cz * CHUNK_D; int lz = z - cz * CHUNK_D;
@ -60,7 +60,8 @@ static inline void set_block(
else if (y + 1 > chunk->top) else if (y + 1 > chunk->top)
chunk->top = y + 1; chunk->top = y + 1;
else if (id == 0) else if (id == 0)
chunk->updateHeights(); chunk->flags.dirtyHeights = true;
if (lx == 0 && (chunk = get_chunk(chunks, cx - 1, cz))) { if (lx == 0 && (chunk = get_chunk(chunks, cx - 1, cz))) {
chunk->flags.modified = true; 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))) { if (lz == CHUNK_D - 1 && (chunk = get_chunk(chunks, cx, cz + 1))) {
chunk->flags.modified = true; chunk->flags.modified = true;
} }
return true;
} }
void blocks_agent::set( bool blocks_agent::set(
Chunks& chunks, Chunks& chunks,
int32_t x, int32_t x,
int32_t y, int32_t y,
@ -84,10 +86,10 @@ void blocks_agent::set(
uint32_t id, uint32_t id,
blockstate state 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, GlobalChunks& chunks,
int32_t x, int32_t x,
int32_t y, int32_t y,
@ -95,7 +97,7 @@ void blocks_agent::set(
uint32_t id, uint32_t id,
blockstate state blockstate state
) { ) {
set_block(chunks, x, y, z, id, state); return set_block(chunks, x, y, z, id, state);
} }
template <class Storage> template <class Storage>

View File

@ -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 z block position Z
/// @param id new block id /// @param id new block id
/// @param state new block state /// @param state new block state
void set( bool set(
Chunks& chunks, Chunks& chunks,
int32_t x, int32_t x,
int32_t y, int32_t y,
@ -135,7 +135,7 @@ void set(
/// @param z block position Z /// @param z block position Z
/// @param id new block id /// @param id new block id
/// @param state new block state /// @param state new block state
void set( bool set(
GlobalChunks& chunks, GlobalChunks& chunks,
int32_t x, int32_t x,
int32_t y, int32_t y,