From 5304223e9543ebcd341411aca885522ce17599c9 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 7 Mar 2026 11:55:32 +0300 Subject: [PATCH 1/4] add systems availability checks to block, cameras, world libraries --- src/logic/scripting/lua/libs/libblock.cpp | 156 ++++++++++++++------- src/logic/scripting/lua/libs/libcamera.cpp | 24 +++- src/logic/scripting/lua/libs/libworld.cpp | 10 +- 3 files changed, 131 insertions(+), 59 deletions(-) diff --git a/src/logic/scripting/lua/libs/libblock.cpp b/src/logic/scripting/lua/libs/libblock.cpp index 2fa2b1281..f2a615dc0 100644 --- a/src/logic/scripting/lua/libs/libblock.cpp +++ b/src/logic/scripting/lua/libs/libblock.cpp @@ -20,8 +20,22 @@ using namespace scripting; -static inline const Block* get_block_def(lua::State* L) { - auto indices = content->getIndices(); +static const Content& require_content() { + if (content == nullptr) { + throw std::runtime_error("content is not initialized"); + } + return *content; +} + +static Level& require_level() { + if (level == nullptr) { + throw std::runtime_error("level is not initialized"); + } + return *level; +} + +static const Block* get_block_def(lua::State* L) { + auto indices = require_content().getIndices(); auto id = lua::tointeger(L, 1); return indices->blocks.get(id); } @@ -45,7 +59,7 @@ static int l_is_solid_at(lua::State* L) { auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); return lua::pushboolean( - L, blocks_agent::is_solid_at(*level->chunks, x, y, z) + L, blocks_agent::is_solid_at(*require_level().chunks, x, y, z) ); } @@ -55,7 +69,7 @@ static int l_count(lua::State* L) { static int l_index(lua::State* L) { auto name = lua::require_string(L, 1); - return lua::pushinteger(L, content->blocks.require(name).rt.id); + return lua::pushinteger(L, require_content().blocks.require(name).rt.id); } static int l_is_extended(lua::State* L) { @@ -76,7 +90,7 @@ static int l_is_segment(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); - const auto& vox = blocks_agent::require(*level->chunks, x, y, z); + const auto& vox = blocks_agent::require(*require_level().chunks, x, y, z); return lua::pushboolean(L, vox.state.segment); } @@ -84,10 +98,11 @@ static int l_seek_origin(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); - const auto& vox = blocks_agent::require(*level->chunks, x, y, z); + const auto& level = require_level(); + const auto& vox = blocks_agent::require(*level.chunks, x, y, z); auto& def = indices->blocks.require(vox.id); return lua::pushivec_stack( - L, blocks_agent::seek_origin(*level->chunks, {x, y, z}, def, vox.state) + L, blocks_agent::seek_origin(*level.chunks, {x, y, z}, def, vox.state) ); } @@ -98,10 +113,12 @@ static int l_set(lua::State* L) { auto id = lua::tointeger(L, 4); auto state = lua::tointeger(L, 5); bool noupdate = lua::toboolean(L, 6); - if (static_cast(id) >= indices->blocks.count()) { + auto& level = require_level(); + auto& indices = require_content().getIndices()->blocks; + if (static_cast(id) >= indices.count()) { return 0; } - if (!blocks_agent::set(*level->chunks, x, y, z, id, int2blockstate(state))) { + if (!blocks_agent::set(*level.chunks, x, y, z, id, int2blockstate(state))) { return 0; } @@ -123,7 +140,7 @@ static int l_get(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); - auto vox = blocks_agent::get(*level->chunks, x, y, z); + auto vox = blocks_agent::get(*require_level().chunks, x, y, z); int id = vox == nullptr ? -1 : vox->id; return lua::pushinteger(L, id); } @@ -138,8 +155,9 @@ template static int get_axis(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); + auto& level = require_level(); if (lua::gettop(L) == 2) { - const auto& def = level->content.getIndices()->blocks.require(x); + const auto& def = level.content.getIndices()->blocks.require(x); return get_axis(L, def, y); } auto z = lua::tointeger(L, 3); @@ -147,11 +165,11 @@ static int get_axis(lua::State* L) { glm::ivec3 defAxis {}; defAxis[n] = 1; - auto vox = blocks_agent::get(*level->chunks, x, y, z); + auto vox = blocks_agent::get(*level.chunks, x, y, z); if (vox == nullptr) { return lua::pushivec_stack(L, defAxis); } - const auto& def = level->content.getIndices()->blocks.require(vox->id); + const auto& def = level.content.getIndices()->blocks.require(vox->id); if (!def.rotatable) { return lua::pushivec_stack(L, defAxis); } else { @@ -175,7 +193,7 @@ static int l_get_rotation(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); - auto vox = blocks_agent::get(*level->chunks, x, y, z); + auto vox = blocks_agent::get(*require_level().chunks, x, y, z); int rotation = vox == nullptr ? 0 : vox->state.rotation; return lua::pushinteger(L, rotation); } @@ -185,7 +203,7 @@ static int l_set_rotation(lua::State* L) { auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); auto value = lua::tointeger(L, 4); - blocks_agent::set_rotation(*level->chunks, x, y, z, value); + blocks_agent::set_rotation(*require_level().chunks, x, y, z, value); return 0; } @@ -193,7 +211,7 @@ static int l_get_states(lua::State* L) { auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); - auto vox = blocks_agent::get(*level->chunks, x, y, z); + auto vox = blocks_agent::get(*require_level().chunks, x, y, z); int states = vox == nullptr ? 0 : blockstate2int(vox->state); return lua::pushinteger(L, states); } @@ -208,7 +226,7 @@ static int l_set_states(lua::State* L) { } int cx = floordiv(x); int cz = floordiv(z); - auto chunk = blocks_agent::get_chunk(*level->chunks, cx, cz); + auto chunk = blocks_agent::get_chunk(*require_level().chunks, cx, cz); if (chunk == nullptr) { return 0; } @@ -227,16 +245,17 @@ static int l_get_user_bits(lua::State* L) { auto offset = lua::tointeger(L, 4) + VOXEL_USER_BITS_OFFSET; auto bits = lua::tointeger(L, 5); - auto vox = blocks_agent::get(*level->chunks, x, y, z); + auto& level = require_level(); + auto vox = blocks_agent::get(*level.chunks, x, y, z); if (vox == nullptr) { return lua::pushinteger(L, 0); } - const auto& def = content->getIndices()->blocks.require(vox->id); + const auto& def = level.content.getIndices()->blocks.require(vox->id); if (def.rt.extended) { auto origin = blocks_agent::seek_origin( - *level->chunks, {x, y, z}, def, vox->state + *level.chunks, {x, y, z}, def, vox->state ); - vox = blocks_agent::get(*level->chunks, origin.x, origin.y, origin.z); + vox = blocks_agent::get(*level.chunks, origin.x, origin.y, origin.z); if (vox == nullptr) { return lua::pushinteger(L, 0); } @@ -246,7 +265,9 @@ static int l_get_user_bits(lua::State* L) { } static int l_get_variant(lua::State* L) { - auto& chunks = *level->chunks; + auto& level = require_level(); + auto& chunks = *level.chunks; + auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); @@ -255,7 +276,7 @@ static int l_get_variant(lua::State* L) { if (vox == nullptr) { return lua::pushinteger(L, 0); } - const auto& def = content->getIndices()->blocks.require(vox->id); + const auto& def = level.content.getIndices()->blocks.require(vox->id); if (def.variants == nullptr) { return lua::pushinteger(L, 0); } @@ -272,7 +293,9 @@ static int l_get_variant(lua::State* L) { } static int l_set_user_bits(lua::State* L) { - auto& chunks = *level->chunks; + auto& level = require_level(); + auto& chunks = *level.chunks; + auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); @@ -291,7 +314,7 @@ static int l_set_user_bits(lua::State* L) { int lx = x - cx * CHUNK_W; int lz = z - cz * CHUNK_D; auto vox = &chunk->voxels[vox_index(lx, y, lz)]; - const auto& def = content->getIndices()->blocks.require(vox->id); + const auto& def = level.content.getIndices()->blocks.require(vox->id); if (def.rt.extended) { auto origin = blocks_agent::seek_origin(chunks, {x, y, z}, def, vox->state); vox = blocks_agent::get(chunks, origin.x, origin.y, origin.z); @@ -313,7 +336,9 @@ static int l_set_user_bits(lua::State* L) { } static int l_set_variant(lua::State* L) { - auto& chunks = *level->chunks; + auto& level = require_level(); + auto& chunks = *level.chunks; + auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); @@ -327,7 +352,7 @@ static int l_set_variant(lua::State* L) { int lx = x - cx * CHUNK_W; int lz = z - cz * CHUNK_D; auto vox = &chunk->voxels[vox_index(lx, y, lz)]; - const auto& def = content->getIndices()->blocks.require(vox->id); + const auto& def = level.content.getIndices()->blocks.require(vox->id); if (def.variants == nullptr) { return 0; @@ -358,11 +383,12 @@ static int l_set_variant(lua::State* L) { } static int l_is_replaceable_at(lua::State* L) { + auto& level = require_level(); auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); return lua::pushboolean( - L, blocks_agent::is_replaceable_at(*level->chunks, x, y, z) + L, blocks_agent::is_replaceable_at(*level.chunks, x, y, z) ); } @@ -373,20 +399,28 @@ static int l_caption(lua::State* L) { return 0; } -static lua::Integer get_variant_index(lua::State* L, const Block* const block, int argumentIndex) { - const auto variantIndex = lua::gettop(L) >= argumentIndex ? lua::tointeger(L, argumentIndex) : 0; - const size_t variantsSize = block->variants->variants.size(); +static lua::Integer get_variant_index( + lua::State* L, const Block& block, int argumentIndex +) { + const auto variantIndex = + lua::isnumber(L, argumentIndex) ? lua::tointeger(L, argumentIndex) : 0; + const size_t variantsSize = block.variants->variants.size(); if (variantIndex < 0 || variantIndex >= variantsSize) { throw std::out_of_range( - "variant index out of bounds [0, " + std::to_string(variantsSize - 1) + "]"); + "variant index out of bounds [0, " + + std::to_string(variantsSize - 1) + "]" + ); } return variantIndex; } static int l_get_textures(lua::State* L) { if (auto def = get_block_def(L)) { - const auto& textureFaces = (def->variants ? def->variants->variants[get_variant_index(L, def, 2)].textureFaces : - def->defaults.textureFaces); + const auto& textureFaces = + (def->variants + ? def->variants->variants[get_variant_index(L, *def, 2)] + .textureFaces + : def->defaults.textureFaces); lua::createtable(L, 6, 0); for (size_t i = 0; i < 6; i++) { lua::pushstring(L, textureFaces[i]); @@ -397,11 +431,13 @@ static int l_get_textures(lua::State* L) { return 0; } - static int l_model_name(lua::State* L) { if (auto def = get_block_def(L)) { - const auto& modelName = (def->variants ? def->variants->variants[get_variant_index(L, def, 2)].model.name : - def->defaults.model.name); + const auto& modelName = + (def->variants + ? def->variants->variants[get_variant_index(L, *def, 2)] + .model.name + : def->defaults.model.name); if (modelName.empty()) { return lua::pushlstring(L, def->name + ".model"); } @@ -412,8 +448,11 @@ static int l_model_name(lua::State* L) { static int l_get_model(lua::State* L) { if (auto def = get_block_def(L)) { - const BlockModelType modelType = (def->variants ? def->variants->variants[get_variant_index(L, def, 2)].model.type : - def->defaults.model.type); + const BlockModelType modelType = + (def->variants + ? def->variants->variants[get_variant_index(L, *def, 2)] + .model.type + : def->defaults.model.type); return lua::pushlstring(L, BlockModelTypeMeta.getName(modelType)); } return 0; @@ -422,7 +461,8 @@ static int l_get_model(lua::State* L) { static int l_get_hitbox(lua::State* L) { if (auto def = get_block_def(L)) { size_t rotation = lua::tointeger(L, 2); - const size_t hitboxIndex = static_cast(lua::gettop(L) >= 3 ? lua::tointeger(L, 3) : 0); + const size_t hitboxIndex = + static_cast(lua::isnumber(L, 3) ? lua::tointeger(L, 3) : 0); if (def->rotatable) { rotation %= def->rotations.MAX_COUNT; } else { @@ -456,25 +496,28 @@ static int l_get_picking_item(lua::State* L) { } static int l_place(lua::State* L) { + auto& level = require_level(); + auto& indices = *level.content.getIndices(); + auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); auto id = lua::tointeger(L, 4); auto state = lua::tointeger(L, 5); auto playerid = lua::gettop(L) >= 6 ? lua::tointeger(L, 6) : -1; - if (static_cast(id) >= indices->blocks.count()) { + if (static_cast(id) >= indices.blocks.count()) { return 0; } - if (!blocks_agent::get(*level->chunks, x, y, z)) { + if (!blocks_agent::get(*level.chunks, x, y, z)) { return 0; } - const auto def = level->content.getIndices()->blocks.get(id); + const auto def = indices.blocks.get(id); if (def == nullptr) { throw std::runtime_error( "there is no block with index " + std::to_string(id) ); } - auto player = level->players->get(playerid); + auto player = level.players->get(playerid); controller->getBlocksController()->placeBlock( player, *def, int2blockstate(state), x, y, z ); @@ -482,21 +525,26 @@ static int l_place(lua::State* L) { } static int l_destruct(lua::State* L) { + auto& level = require_level(); + auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); - auto playerid = lua::gettop(L) >= 4 ? lua::tointeger(L, 4) : -1; - auto vox = blocks_agent::get(*level->chunks, x, y, z); + auto playerid = lua::isnumber(L, 4) ? lua::tointeger(L, 4) : -1; + + auto vox = blocks_agent::get(*level.chunks, x, y, z); if (vox == nullptr) { return 0; } - auto& def = level->content.getIndices()->blocks.require(vox->id); - auto player = level->players->get(playerid); + auto& def = level.content.getIndices()->blocks.require(vox->id); + auto player = level.players->get(playerid); controller->getBlocksController()->breakBlock(player, def, x, y, z); return 0; } static int l_raycast(lua::State* L) { + auto& level = require_level(); + auto start = lua::tovec<3>(L, 1); auto dir = lua::tovec<3>(L, 2); auto maxDistance = lua::tonumber(L, 3); @@ -526,7 +574,7 @@ static int l_raycast(lua::State* L) { glm::ivec3 normal; glm::ivec3 iend; if (auto voxel = blocks_agent::raycast( - *level->chunks, + *level.chunks, start, dir, maxDistance, @@ -620,6 +668,8 @@ static int get_field( } static int l_get_field(lua::State* L) { + auto& level = require_level(); + auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); @@ -628,9 +678,10 @@ static int l_get_field(lua::State* L) { if (lua::gettop(L) >= 5) { index = lua::tointeger(L, 5); } + auto cx = floordiv(x, CHUNK_W); auto cz = floordiv(z, CHUNK_D); - auto chunk = blocks_agent::get_chunk(*level->chunks, cx, cz); + auto chunk = blocks_agent::get_chunk(*level.chunks, cx, cz); if (chunk == nullptr || y < 0 || y >= CHUNK_H) { return 0; } @@ -689,6 +740,8 @@ static int set_field( } static int l_set_field(lua::State* L) { + auto& level = require_level(); + auto x = lua::tointeger(L, 1); auto y = lua::tointeger(L, 2); auto z = lua::tointeger(L, 3); @@ -698,11 +751,12 @@ static int l_set_field(lua::State* L) { if (lua::gettop(L) >= 6) { index = lua::tointeger(L, 6); } + auto cx = floordiv(x, CHUNK_W); auto cz = floordiv(z, CHUNK_D); auto lx = x - cx * CHUNK_W; auto lz = z - cz * CHUNK_W; - auto chunk = blocks_agent::get_chunk(*level->chunks, cx, cz); + auto chunk = blocks_agent::get_chunk(*level.chunks, cx, cz); if (chunk == nullptr || y < 0 || y >= CHUNK_H) { return 0; } diff --git a/src/logic/scripting/lua/libs/libcamera.cpp b/src/logic/scripting/lua/libs/libcamera.cpp index 6ec6ef96c..c45d2740a 100644 --- a/src/logic/scripting/lua/libs/libcamera.cpp +++ b/src/logic/scripting/lua/libs/libcamera.cpp @@ -7,28 +7,42 @@ using namespace scripting; +static Level& require_level() { + if (level == nullptr) { + throw std::runtime_error("level is not initialized"); + } + return *level; +} + +static const Content& require_content() { + if (content == nullptr) { + throw std::runtime_error("content is not initialized"); + } + return *content; +} + template static int l_camera_getter(lua::State* L) { size_t index = static_cast(lua::tointeger(L, 1)); - return getterfunc(L, *level->cameras.at(index)); + return getterfunc(L, *require_level().cameras.at(index)); } template static int l_camera_setter(lua::State* L) { size_t index = static_cast(lua::tointeger(L, 1)); - setterfunc(L, *level->cameras.at(index), 2); + setterfunc(L, *require_level().cameras.at(index), 2); return 0; } static int l_index(lua::State* L) { auto name = lua::require_string(L, 1); - auto& indices = content->getIndices(ResourceType::CAMERA); + auto& indices = require_content().getIndices(ResourceType::CAMERA); return lua::pushinteger(L, indices.indexOf(name)); } static int l_name(lua::State* L) { size_t index = static_cast(lua::tointeger(L, 1)); - auto& indices = content->getIndices(ResourceType::CAMERA); + auto& indices = require_content().getIndices(ResourceType::CAMERA); return lua::pushstring(L, indices.getName(index)); } @@ -89,7 +103,7 @@ static int getter_up(lua::State* L, const Camera& camera) { static int l_look_at(lua::State* L) { size_t index = static_cast(lua::tointeger(L, 1)); - auto& camera = *level->cameras.at(index); + auto& camera = *require_level().cameras.at(index); auto center = lua::tovec<3>(L, 2); auto matrix = glm::inverse( glm::lookAt(glm::vec3(), center - camera.position, glm::vec3(0, 1, 0)) diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index 30a619788..c2d6be43c 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -25,11 +25,15 @@ using namespace scripting; namespace fs = std::filesystem; -static WorldInfo& require_world_info() { +static Level& require_level() { if (level == nullptr) { - throw std::runtime_error("no world open"); + throw std::runtime_error("world is not open"); } - return level->getWorld()->getInfo(); + return *level; +} + +static WorldInfo& require_world_info() { + return require_level().getWorld()->getInfo(); } static int l_is_open(lua::State* L) { From b49e2106b36a9e5228cee6edd8f1f6084184fff8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 9 Mar 2026 16:46:12 +0300 Subject: [PATCH 2/4] update libitem.cpp --- src/logic/scripting/lua/libs/libitem.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/logic/scripting/lua/libs/libitem.cpp b/src/logic/scripting/lua/libs/libitem.cpp index 3a0f77ec7..4c7ba3983 100644 --- a/src/logic/scripting/lua/libs/libitem.cpp +++ b/src/logic/scripting/lua/libs/libitem.cpp @@ -8,6 +8,9 @@ using namespace scripting; static const ItemDef* get_item_def(lua::State* L, int idx) { + if (content == nullptr) { + throw std::runtime_error("content is not initialized"); + } auto indices = content->getIndices(); auto id = lua::tointeger(L, idx); return indices->items.get(id); From 68ef9740969c4102370f74335993ca6125488456 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 9 Mar 2026 16:51:24 +0300 Subject: [PATCH 3/4] update libplayer.cpp --- src/logic/scripting/lua/libs/libplayer.cpp | 31 +++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index 9f634bddb..a978e5c22 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -14,6 +14,13 @@ using namespace scripting; +static Level& require_level() { + if (level == nullptr) { + throw std::runtime_error("world is not loaded"); + } + return *level; +} + inline Player* get_player(lua::State* L, int idx) { if (!lua::isnumber(L, idx)) { if (engine->isHeadless()) { @@ -22,7 +29,7 @@ inline Player* get_player(lua::State* L, int idx) { ); } } - return level->players->get(lua::tointeger(L, idx)); + return require_level().players->get(lua::tointeger(L, idx)); } static int l_get_pos(lua::State* L) { @@ -304,15 +311,18 @@ static int l_create(lua::State* L) { if (lua::gettop(L) >= 2) { playerId = lua::tointeger(L, 2); } - auto player = level->players->create(playerId); + auto& level = require_level(); + auto player = level.players->create(playerId); player->setName(lua::require_string(L, 1)); return lua::pushinteger(L, player->getId()); } static int l_delete(lua::State* L) { auto id = lua::tointeger(L, 1); - level->players->suspend(id); - level->players->remove(id); + + auto& level = require_level(); + level.players->suspend(id); + level.players->remove(id); return 0; } @@ -324,19 +334,21 @@ static int l_is_suspended(lua::State* L) { } static int l_set_suspended(lua::State* L) { + auto& level = require_level(); if (lua::toboolean(L, 2)) { - level->players->suspend(lua::tointeger(L, 1)); + level.players->suspend(lua::tointeger(L, 1)); } else { - level->players->resume(lua::tointeger(L, 1)); + level.players->resume(lua::tointeger(L, 1)); } return 0; } static int l_get_all_in_radius(lua::State* L) { + auto& level = require_level(); auto center = lua::tovec3(L, 1); auto radius = static_cast(lua::tonumber(L, 2)); - auto players = level->players->getAllInRadius(center, radius); + auto players = level.players->getAllInRadius(center, radius); lua::createtable(L, players.size(), 0); for (size_t i = 0; i < players.size(); i++) { lua::pushinteger(L, players[i]->getId()); @@ -346,7 +358,7 @@ static int l_get_all_in_radius(lua::State* L) { } static int l_get_all(lua::State* L) { - auto players = level->players->getAll(); + auto players = require_level().players->getAll(); lua::createtable(L, players.size(), 0); for (size_t i = 0; i < players.size(); i++) { lua::pushinteger(L, players[i]->getId()); @@ -356,8 +368,9 @@ static int l_get_all(lua::State* L) { } static int l_get_nearest(lua::State* L) { + auto& level = require_level(); auto position = lua::tovec3(L, 1); - if (auto player = level->players->getNearest(position)) { + if (auto player = level.players->getNearest(position)) { lua::pushinteger(L, player->getId()); return 1; } From 068e546a63dfd9468a436d0e711d8f38b86c3f10 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 9 Mar 2026 17:51:56 +0300 Subject: [PATCH 4/4] update libinventory.cpp --- src/logic/scripting/lua/libs/libinventory.cpp | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/logic/scripting/lua/libs/libinventory.cpp b/src/logic/scripting/lua/libs/libinventory.cpp index 7f43ae88b..3ec9d2ca3 100644 --- a/src/logic/scripting/lua/libs/libinventory.cpp +++ b/src/logic/scripting/lua/libs/libinventory.cpp @@ -8,14 +8,28 @@ using namespace scripting; namespace { + Level& require_level() { + if (level == nullptr) { + throw std::runtime_error("world is not open"); + } + return *level; + } + + const Content& require_content() { + if (content == nullptr) { + throw std::runtime_error("content is not initialized"); + } + return *content; + } + void validate_itemid(itemid_t id) { - if (id >= indices->items.count()) { + if (id >= require_content().getIndices()->items.count()) { throw std::runtime_error("invalid item id"); } } Inventory& get_inventory(int64_t id) { - auto inv = level->inventories->get(id); + auto inv = require_level().inventories->get(id); if (inv == nullptr) { throw std::runtime_error("inventory not found: " + std::to_string(id)); } @@ -23,7 +37,7 @@ namespace { } Inventory& get_inventory(int64_t id, int arg) { - auto inv = level->inventories->get(id); + auto inv = require_level().inventories->get(id); if (inv == nullptr) { throw std::runtime_error( "inventory not found: " + std::to_string(id) + " argument " + @@ -137,7 +151,7 @@ static int l_unbind_block(lua::State* L) { static int l_create(lua::State* L) { auto invsize = lua::tointeger(L, 1); - auto inv = level->inventories->create(invsize); + auto inv = require_level().inventories->create(invsize); if (inv == nullptr) { return lua::pushinteger(L, 0); } @@ -146,13 +160,13 @@ static int l_create(lua::State* L) { static int l_remove(lua::State* L) { auto invid = lua::tointeger(L, 1); - level->inventories->remove(invid); + require_level().inventories->remove(invid); return 0; } static int l_clone(lua::State* L) { auto id = lua::tointeger(L, 1); - auto clone = level->inventories->clone(id); + auto clone = require_level().inventories->clone(id); if (clone == nullptr) { return lua::pushinteger(L, 0); }