diff --git a/dev/tests/raycast.lua b/dev/tests/raycast.lua new file mode 100644 index 000000000..6016989d8 --- /dev/null +++ b/dev/tests/raycast.lua @@ -0,0 +1,47 @@ +local util = require "core:tests_util" + +-- Create world and prepare settings +util.create_demo_world("core:default") +app.set_setting("chunks.load-distance", 3) +app.set_setting("chunks.load-speed", 1) + +-- Create player +local pid = player.create("Xerxes") +player.set_spawnpoint(pid, 0, 100, 0) +player.set_pos(pid, 0, 100, 0) +app.sleep_until(function () return block.get(0, 0, 0) ~= -1 end) +app.sleep_until(function () return block.get(-5, 8, 2) ~= -1 end) + +local sand_idx = block.index("base:sand") +block.set(0, 1, 0, sand_idx) + +local start = {-5, 8, 2} +local target = {0.5, 1.5, 0.5} +local ray = world.raycast({ + start = start, + dir = vec3.normalize(vec3.sub(target, start)), + distance = 10, +}) +debug.print(ray) + +assert(ray, "ray didn't hit") +util.check_int(sand_idx, ray.block, "ray.block") +util.check_vec3({0, 1, 0}, ray.normal, "ray.normal") +util.check_vec3({0.0769, 2, 0.6153}, ray.endpoint, "ray.endpoint") +util.check_vec3({0, 1, 0}, ray.iendpoint, "ray.iendpoint") +util.check_float(7.9807, ray.length, "ray.length") + +ray = world.raycast({ + start = start, + dir = vec3.normalize(vec3.sub(target, start)), + distance = 10, + filter_blocks = {sand_idx}, +}) +debug.print(ray) + +assert(ray, "ray didn't hit") +util.check_int(block.index("core:obstacle"), ray.block, "ray.block") +util.check_vec3({0, 1, 0}, ray.normal, "ray.normal") +util.check_vec3({0.923, 1, 0.3846}, ray.endpoint, "ray.endpoint") +util.check_vec3({0, 0, 0}, ray.iendpoint, "ray.iendpoint") +util.check_float(9.3108, ray.length, "ray.length") diff --git a/res/modules/tests_util.lua b/res/modules/tests_util.lua index 1e2207c24..e4ab73bc3 100644 --- a/res/modules/tests_util.lua +++ b/res/modules/tests_util.lua @@ -5,4 +5,25 @@ function util.create_demo_world(generator) app.new_world("demo", "2019", generator or "core:default") end +function util.check_vec3(expected, fact, name, delta) + delta = delta or 1e-4 + for i=1,3 do + assert(math.abs(fact[i] - expected[i]) < delta, + name.."["..i.."] expected: "..expected[i]..", fact: "..fact[i]) + end +end + +function util.check_float(expected, fact, name, delta) + delta = delta or 1e-4 + local actual_delta = math.abs(fact - expected) + assert(actual_delta < delta, + name.." expected: "..expected..", fact: "..fact.. + " (delta: "..actual_delta.." > "..delta..")") +end + +function util.check_int(expected, fact, name) + assert(fact == expected, + name.." expected: "..expected..", fact: "..fact) +end + return util diff --git a/src/logic/scripting/lua/libs/libentity.cpp b/src/logic/scripting/lua/libs/libentity.cpp index 7e68ac5ff..64e8e126e 100644 --- a/src/logic/scripting/lua/libs/libentity.cpp +++ b/src/logic/scripting/lua/libs/libentity.cpp @@ -230,10 +230,14 @@ static void load_blocks_filter(lua::State* L, int idx, std::set& dst) int count = lua::objlen(L, idx); for (int i = 0; i < count; i++) { lua::rawgeti(L, i + 1, idx); - auto blockName = std::string(lua::tostring(L, -1)); - const Block* block = content->blocks.find(blockName); - if (block != nullptr) { - dst.insert(block->rt.id); + if (lua::isnumber(L, -1)) { + dst.insert(lua::touinteger(L, -1)); + } else { + auto blockName = std::string(lua::tostring(L, -1)); + const Block* block = content->blocks.find(blockName); + if (block != nullptr) { + dst.insert(block->rt.id); + } } lua::pop(L); } @@ -243,10 +247,14 @@ static void load_entities_filter(lua::State* L, int idx, std::set int count = lua::objlen(L, idx); for (int i = 0; i < count; i++) { lua::rawgeti(L, i + 1, idx); - auto entityName = std::string(lua::tostring(L, -1)); - const EntityDef* entity = content->entities.find(entityName); - if (entity != nullptr) { - dst.insert(entity->rt.id); + if (lua::isnumber(L, -1)) { + dst.insert(lua::touinteger(L, -1)); + } else { + auto entityName = std::string(lua::tostring(L, -1)); + const EntityDef* entity = content->entities.find(entityName); + if (entity != nullptr) { + dst.insert(entity->rt.id); + } } lua::pop(L); } diff --git a/src/voxels/blocks_agent.cpp b/src/voxels/blocks_agent.cpp index 81a752a70..9d1f0cc17 100644 --- a/src/voxels/blocks_agent.cpp +++ b/src/voxels/blocks_agent.cpp @@ -269,7 +269,7 @@ static inline voxel* raycast_blocks( const auto& def = blocks.require(voxel->id); if (voxel->id != BLOCK_AIR && (def.selectable || includeNonSelectable) && - (filter == nullptr || (filter->find(def.rt.id) == filter->end()) == + ((filter == nullptr || filter->find(def.rt.id) == filter->end()) == settings.blocksFilterExcludeMode)) { end = start + t * dir; iend = {ix, iy, iz};