add systems availability checks to block, cameras, world libraries

This commit is contained in:
MihailRis 2026-03-07 11:55:32 +03:00
parent 24b4877551
commit 5304223e95
3 changed files with 131 additions and 59 deletions

View file

@ -20,8 +20,22 @@
using namespace scripting; using namespace scripting;
static inline const Block* get_block_def(lua::State* L) { static const Content& require_content() {
auto indices = content->getIndices(); 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); auto id = lua::tointeger(L, 1);
return indices->blocks.get(id); 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 y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
return lua::pushboolean( 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) { static int l_index(lua::State* L) {
auto name = lua::require_string(L, 1); 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) { 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 x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); 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); 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 x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); 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); auto& def = indices->blocks.require(vox.id);
return lua::pushivec_stack( 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 id = lua::tointeger(L, 4);
auto state = lua::tointeger(L, 5); auto state = lua::tointeger(L, 5);
bool noupdate = lua::toboolean(L, 6); bool noupdate = lua::toboolean(L, 6);
if (static_cast<size_t>(id) >= indices->blocks.count()) { auto& level = require_level();
auto& indices = require_content().getIndices()->blocks;
if (static_cast<size_t>(id) >= indices.count()) {
return 0; 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; return 0;
} }
@ -123,7 +140,7 @@ static int l_get(lua::State* L) {
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); 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; int id = vox == nullptr ? -1 : vox->id;
return lua::pushinteger(L, id); return lua::pushinteger(L, id);
} }
@ -138,8 +155,9 @@ template<int n>
static int get_axis(lua::State* L) { static int get_axis(lua::State* L) {
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto& level = require_level();
if (lua::gettop(L) == 2) { 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<n>(L, def, y); return get_axis<n>(L, def, y);
} }
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
@ -147,11 +165,11 @@ static int get_axis(lua::State* L) {
glm::ivec3 defAxis {}; glm::ivec3 defAxis {};
defAxis[n] = 1; 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) { if (vox == nullptr) {
return lua::pushivec_stack(L, defAxis); 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) { if (!def.rotatable) {
return lua::pushivec_stack(L, defAxis); return lua::pushivec_stack(L, defAxis);
} else { } else {
@ -175,7 +193,7 @@ static int l_get_rotation(lua::State* L) {
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); 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; int rotation = vox == nullptr ? 0 : vox->state.rotation;
return lua::pushinteger(L, 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 y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
auto value = lua::tointeger(L, 4); 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; return 0;
} }
@ -193,7 +211,7 @@ static int l_get_states(lua::State* L) {
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); 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); int states = vox == nullptr ? 0 : blockstate2int(vox->state);
return lua::pushinteger(L, states); return lua::pushinteger(L, states);
} }
@ -208,7 +226,7 @@ static int l_set_states(lua::State* L) {
} }
int cx = floordiv<CHUNK_W>(x); int cx = floordiv<CHUNK_W>(x);
int cz = floordiv<CHUNK_D>(z); int cz = floordiv<CHUNK_D>(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) { if (chunk == nullptr) {
return 0; 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 offset = lua::tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
auto bits = lua::tointeger(L, 5); 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) { if (vox == nullptr) {
return lua::pushinteger(L, 0); 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) { if (def.rt.extended) {
auto origin = blocks_agent::seek_origin( 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) { if (vox == nullptr) {
return lua::pushinteger(L, 0); 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) { 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 x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
@ -255,7 +276,7 @@ static int l_get_variant(lua::State* L) {
if (vox == nullptr) { if (vox == nullptr) {
return lua::pushinteger(L, 0); 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) { if (def.variants == nullptr) {
return lua::pushinteger(L, 0); 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) { 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 x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); 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 lx = x - cx * CHUNK_W;
int lz = z - cz * CHUNK_D; int lz = z - cz * CHUNK_D;
auto vox = &chunk->voxels[vox_index(lx, y, lz)]; 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) { if (def.rt.extended) {
auto origin = blocks_agent::seek_origin(chunks, {x, y, z}, def, vox->state); auto origin = blocks_agent::seek_origin(chunks, {x, y, z}, def, vox->state);
vox = blocks_agent::get(chunks, origin.x, origin.y, origin.z); 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) { 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 x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); 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 lx = x - cx * CHUNK_W;
int lz = z - cz * CHUNK_D; int lz = z - cz * CHUNK_D;
auto vox = &chunk->voxels[vox_index(lx, y, lz)]; 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) { if (def.variants == nullptr) {
return 0; return 0;
@ -358,11 +383,12 @@ static int l_set_variant(lua::State* L) {
} }
static int l_is_replaceable_at(lua::State* L) { static int l_is_replaceable_at(lua::State* L) {
auto& level = require_level();
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
return lua::pushboolean( 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; return 0;
} }
static lua::Integer get_variant_index(lua::State* L, const Block* const block, int argumentIndex) { static lua::Integer get_variant_index(
const auto variantIndex = lua::gettop(L) >= argumentIndex ? lua::tointeger(L, argumentIndex) : 0; lua::State* L, const Block& block, int argumentIndex
const size_t variantsSize = block->variants->variants.size(); ) {
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) { if (variantIndex < 0 || variantIndex >= variantsSize) {
throw std::out_of_range( 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; return variantIndex;
} }
static int l_get_textures(lua::State* L) { static int l_get_textures(lua::State* L) {
if (auto def = get_block_def(L)) { if (auto def = get_block_def(L)) {
const auto& textureFaces = (def->variants ? def->variants->variants[get_variant_index(L, def, 2)].textureFaces : const auto& textureFaces =
def->defaults.textureFaces); (def->variants
? def->variants->variants[get_variant_index(L, *def, 2)]
.textureFaces
: def->defaults.textureFaces);
lua::createtable(L, 6, 0); lua::createtable(L, 6, 0);
for (size_t i = 0; i < 6; i++) { for (size_t i = 0; i < 6; i++) {
lua::pushstring(L, textureFaces[i]); lua::pushstring(L, textureFaces[i]);
@ -397,11 +431,13 @@ static int l_get_textures(lua::State* L) {
return 0; return 0;
} }
static int l_model_name(lua::State* L) { static int l_model_name(lua::State* L) {
if (auto def = get_block_def(L)) { if (auto def = get_block_def(L)) {
const auto& modelName = (def->variants ? def->variants->variants[get_variant_index(L, def, 2)].model.name : const auto& modelName =
def->defaults.model.name); (def->variants
? def->variants->variants[get_variant_index(L, *def, 2)]
.model.name
: def->defaults.model.name);
if (modelName.empty()) { if (modelName.empty()) {
return lua::pushlstring(L, def->name + ".model"); 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) { static int l_get_model(lua::State* L) {
if (auto def = get_block_def(L)) { if (auto def = get_block_def(L)) {
const BlockModelType modelType = (def->variants ? def->variants->variants[get_variant_index(L, def, 2)].model.type : const BlockModelType modelType =
def->defaults.model.type); (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 lua::pushlstring(L, BlockModelTypeMeta.getName(modelType));
} }
return 0; return 0;
@ -422,7 +461,8 @@ static int l_get_model(lua::State* L) {
static int l_get_hitbox(lua::State* L) { static int l_get_hitbox(lua::State* L) {
if (auto def = get_block_def(L)) { if (auto def = get_block_def(L)) {
size_t rotation = lua::tointeger(L, 2); size_t rotation = lua::tointeger(L, 2);
const size_t hitboxIndex = static_cast<size_t>(lua::gettop(L) >= 3 ? lua::tointeger(L, 3) : 0); const size_t hitboxIndex =
static_cast<size_t>(lua::isnumber(L, 3) ? lua::tointeger(L, 3) : 0);
if (def->rotatable) { if (def->rotatable) {
rotation %= def->rotations.MAX_COUNT; rotation %= def->rotations.MAX_COUNT;
} else { } else {
@ -456,25 +496,28 @@ static int l_get_picking_item(lua::State* L) {
} }
static int l_place(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 x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
auto id = lua::tointeger(L, 4); auto id = lua::tointeger(L, 4);
auto state = lua::tointeger(L, 5); auto state = lua::tointeger(L, 5);
auto playerid = lua::gettop(L) >= 6 ? lua::tointeger(L, 6) : -1; auto playerid = lua::gettop(L) >= 6 ? lua::tointeger(L, 6) : -1;
if (static_cast<size_t>(id) >= indices->blocks.count()) { if (static_cast<size_t>(id) >= indices.blocks.count()) {
return 0; return 0;
} }
if (!blocks_agent::get(*level->chunks, x, y, z)) { if (!blocks_agent::get(*level.chunks, x, y, z)) {
return 0; return 0;
} }
const auto def = level->content.getIndices()->blocks.get(id); const auto def = indices.blocks.get(id);
if (def == nullptr) { if (def == nullptr) {
throw std::runtime_error( throw std::runtime_error(
"there is no block with index " + std::to_string(id) "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( controller->getBlocksController()->placeBlock(
player, *def, int2blockstate(state), x, y, z 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) { static int l_destruct(lua::State* L) {
auto& level = require_level();
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
auto playerid = lua::gettop(L) >= 4 ? lua::tointeger(L, 4) : -1; auto playerid = lua::isnumber(L, 4) ? lua::tointeger(L, 4) : -1;
auto vox = blocks_agent::get(*level->chunks, x, y, z);
auto vox = blocks_agent::get(*level.chunks, x, y, z);
if (vox == nullptr) { if (vox == nullptr) {
return 0; return 0;
} }
auto& def = level->content.getIndices()->blocks.require(vox->id); auto& def = level.content.getIndices()->blocks.require(vox->id);
auto player = level->players->get(playerid); auto player = level.players->get(playerid);
controller->getBlocksController()->breakBlock(player, def, x, y, z); controller->getBlocksController()->breakBlock(player, def, x, y, z);
return 0; return 0;
} }
static int l_raycast(lua::State* L) { static int l_raycast(lua::State* L) {
auto& level = require_level();
auto start = lua::tovec<3>(L, 1); auto start = lua::tovec<3>(L, 1);
auto dir = lua::tovec<3>(L, 2); auto dir = lua::tovec<3>(L, 2);
auto maxDistance = lua::tonumber(L, 3); auto maxDistance = lua::tonumber(L, 3);
@ -526,7 +574,7 @@ static int l_raycast(lua::State* L) {
glm::ivec3 normal; glm::ivec3 normal;
glm::ivec3 iend; glm::ivec3 iend;
if (auto voxel = blocks_agent::raycast( if (auto voxel = blocks_agent::raycast(
*level->chunks, *level.chunks,
start, start,
dir, dir,
maxDistance, maxDistance,
@ -620,6 +668,8 @@ static int get_field(
} }
static int l_get_field(lua::State* L) { static int l_get_field(lua::State* L) {
auto& level = require_level();
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
@ -628,9 +678,10 @@ static int l_get_field(lua::State* L) {
if (lua::gettop(L) >= 5) { if (lua::gettop(L) >= 5) {
index = lua::tointeger(L, 5); index = lua::tointeger(L, 5);
} }
auto cx = floordiv(x, CHUNK_W); auto cx = floordiv(x, CHUNK_W);
auto cz = floordiv(z, CHUNK_D); 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) { if (chunk == nullptr || y < 0 || y >= CHUNK_H) {
return 0; return 0;
} }
@ -689,6 +740,8 @@ static int set_field(
} }
static int l_set_field(lua::State* L) { static int l_set_field(lua::State* L) {
auto& level = require_level();
auto x = lua::tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3); auto z = lua::tointeger(L, 3);
@ -698,11 +751,12 @@ static int l_set_field(lua::State* L) {
if (lua::gettop(L) >= 6) { if (lua::gettop(L) >= 6) {
index = lua::tointeger(L, 6); index = lua::tointeger(L, 6);
} }
auto cx = floordiv(x, CHUNK_W); auto cx = floordiv(x, CHUNK_W);
auto cz = floordiv(z, CHUNK_D); auto cz = floordiv(z, CHUNK_D);
auto lx = x - cx * CHUNK_W; auto lx = x - cx * CHUNK_W;
auto lz = z - cz * 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) { if (chunk == nullptr || y < 0 || y >= CHUNK_H) {
return 0; return 0;
} }

View file

@ -7,28 +7,42 @@
using namespace scripting; 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 <int (*getterfunc)(lua::State*, const Camera&)> template <int (*getterfunc)(lua::State*, const Camera&)>
static int l_camera_getter(lua::State* L) { static int l_camera_getter(lua::State* L) {
size_t index = static_cast<size_t>(lua::tointeger(L, 1)); size_t index = static_cast<size_t>(lua::tointeger(L, 1));
return getterfunc(L, *level->cameras.at(index)); return getterfunc(L, *require_level().cameras.at(index));
} }
template <void (*setterfunc)(lua::State*, Camera&, int)> template <void (*setterfunc)(lua::State*, Camera&, int)>
static int l_camera_setter(lua::State* L) { static int l_camera_setter(lua::State* L) {
size_t index = static_cast<size_t>(lua::tointeger(L, 1)); size_t index = static_cast<size_t>(lua::tointeger(L, 1));
setterfunc(L, *level->cameras.at(index), 2); setterfunc(L, *require_level().cameras.at(index), 2);
return 0; return 0;
} }
static int l_index(lua::State* L) { static int l_index(lua::State* L) {
auto name = lua::require_string(L, 1); 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)); return lua::pushinteger(L, indices.indexOf(name));
} }
static int l_name(lua::State* L) { static int l_name(lua::State* L) {
size_t index = static_cast<size_t>(lua::tointeger(L, 1)); size_t index = static_cast<size_t>(lua::tointeger(L, 1));
auto& indices = content->getIndices(ResourceType::CAMERA); auto& indices = require_content().getIndices(ResourceType::CAMERA);
return lua::pushstring(L, indices.getName(index)); 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) { static int l_look_at(lua::State* L) {
size_t index = static_cast<size_t>(lua::tointeger(L, 1)); size_t index = static_cast<size_t>(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 center = lua::tovec<3>(L, 2);
auto matrix = glm::inverse( auto matrix = glm::inverse(
glm::lookAt(glm::vec3(), center - camera.position, glm::vec3(0, 1, 0)) glm::lookAt(glm::vec3(), center - camera.position, glm::vec3(0, 1, 0))

View file

@ -25,11 +25,15 @@
using namespace scripting; using namespace scripting;
namespace fs = std::filesystem; namespace fs = std::filesystem;
static WorldInfo& require_world_info() { static Level& require_level() {
if (level == nullptr) { 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) { static int l_is_open(lua::State* L) {