diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua index dc394a00c..a8a6700f9 100644 --- a/builtin/game/misc.lua +++ b/builtin/game/misc.lua @@ -272,3 +272,29 @@ function core.get_globals_to_transfer() } return all end + +do + local function valid_object_iterator(objects) + local i = 0 + local function next_valid_object() + i = i + 1 + local obj = objects[i] + if obj == nil then + return + end + if obj:is_valid() then + return obj + end + return next_valid_object() + end + return next_valid_object + end + + function core.objects_inside_radius(center, radius) + return valid_object_iterator(core.get_objects_inside_radius(center, radius)) + end + + function core.objects_in_area(min_pos, max_pos) + return valid_object_iterator(core.get_objects_in_area(min_pos, max_pos)) + end +end diff --git a/doc/lua_api.md b/doc/lua_api.md index 37dfb8004..bad61832f 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -6123,12 +6123,18 @@ Environment access * Items can be added also to unloaded and non-generated blocks. * `minetest.get_player_by_name(name)`: Get an `ObjectRef` to a player * Returns nothing in case of error (player offline, doesn't exist, ...). -* `minetest.get_objects_inside_radius(pos, radius)` - * returns a list of ObjectRefs. +* `minetest.get_objects_inside_radius(center, radius)` + * returns a list of ObjectRefs * `radius`: using a Euclidean metric -* `minetest.get_objects_in_area(pos1, pos2)` - * returns a list of ObjectRefs. - * `pos1` and `pos2` are the min and max positions of the area to search. + * deprecated, use `objects_inside_radius` instead to get only valid objects +* `minetest.objects_inside_radius(center, radius)` + * returns an iterator of valid objects + * example: `for obj in minetest.objects_inside_radius(center, radius) do obj:punch(...) end` +* `minetest.get_objects_in_area(min_pos, max_pos)` + * returns a list of ObjectRefs + * `min_pos` and `max_pos` are the min and max positions of the area to search. +* `minetest.objects_inside_area(min_pos, max_pos)` + * returns an iterator of valid objects * `minetest.set_timeofday(val)`: set time of day * `val` is between `0` and `1`; `0` for midnight, `0.5` for midday * `minetest.get_timeofday()`: get time of day diff --git a/games/devtest/mods/unittests/entity.lua b/games/devtest/mods/unittests/entity.lua index 71f8ec32a..a6ce7c020 100644 --- a/games/devtest/mods/unittests/entity.lua +++ b/games/devtest/mods/unittests/entity.lua @@ -131,7 +131,7 @@ local function test_entity_attach(player, pos) end unittests.register("test_entity_attach", test_entity_attach, {player=true, map=true}) -core.register_entity("unittests:raycastable", { +core.register_entity("unittests:dummy", { initial_properties = { hp_max = 1, visual = "upright_sprite", @@ -141,8 +141,8 @@ core.register_entity("unittests:raycastable", { }) local function test_entity_raycast(_, pos) - local obj1 = core.add_entity(pos, "unittests:raycastable") - local obj2 = core.add_entity(pos:offset(1, 0, 0), "unittests:raycastable") + local obj1 = core.add_entity(pos, "unittests:dummy") + local obj2 = core.add_entity(pos:offset(1, 0, 0), "unittests:dummy") local raycast = core.raycast(pos:offset(-1, 0, 0), pos:offset(2, 0, 0), true, false) for pt in raycast do if pt.type == "object" then @@ -154,3 +154,25 @@ local function test_entity_raycast(_, pos) assert(obj1 == nil) end unittests.register("test_entity_raycast", test_entity_raycast, {map=true}) + +local function test_object_iterator(pos, iterator) + local obj1 = core.add_entity(pos, "unittests:dummy") + local obj2 = core.add_entity(pos, "unittests:dummy") + -- As soon as we find one of the objects, we invalidate the other. + for obj in iterator do + assert(obj:is_valid()) + if obj == obj1 then + obj2:remove() + elseif obj == obj2 then + obj1:remove() + end + end +end + +unittests.register("test_objects_inside_radius", function(_, pos) + test_object_iterator(pos, minetest.objects_inside_radius(pos, 1)) +end, {map=true}) + +unittests.register("test_objects_in_area", function(_, pos) + test_object_iterator(pos, minetest.objects_in_area(pos:offset(-1, -1, -1), pos:offset(1, 1, 1))) +end, {map=true})