130 lines
4.7 KiB
Lua
130 lines
4.7 KiB
Lua
|
|
if (not kutils) then kutils = { }; end
|
|
|
|
-- Nodes to always ignore in checks. --
|
|
if (not kutils.ignore_nodes) then
|
|
kutils.ignore_nodes = {
|
|
["air"] = true;
|
|
["default:water_source"] = true;
|
|
["default:water_flowing"] = true;
|
|
};
|
|
end
|
|
|
|
-- Entities to always ignore in checks. --
|
|
if (not kutils.ignore_ents) then
|
|
kutils.ignore_ents = {
|
|
["__builtin:item"] = true;
|
|
};
|
|
end
|
|
|
|
--[[
|
|
| Cast a ray from a point in a direction.
|
|
|
|
|
| The `params' argument must be a table with the following fields:
|
|
|
|
|
| pos (required)
|
|
| Point from whihch to cast the ray.
|
|
|
|
|
| delta (required)
|
|
| This controls the direction and step size ofthe check for collision.
|
|
| It must be a table { x=deltax, y=deltay, z=deltaz }
|
|
|
|
|
| range (required)
|
|
| Number of steps to check. The distance checked is delta*range.
|
|
|
|
|
| radius (optional)
|
|
| Radius for the entity checker. Smaller radius may miss some entities
|
|
| on the way; bigger radius may check for objects not really in the
|
|
| ray's path. Default is 1.
|
|
|
|
|
| user (optional)
|
|
| This is the entity that is casting the ray. If not nil, this entity
|
|
| will be ignored in the check.
|
|
|
|
|
| ignore_ents (optional)
|
|
| Table containing entity names to ignore in the check. In addition
|
|
| to the entities listed here, it ignores "__builtin:item". The format
|
|
| must be { ["modname:entname"] = true, ... }
|
|
|
|
|
| solid_only (optional)
|
|
| If false, the ray takes not walkable nodes (e.g. lava) as solid. Air
|
|
| and water are always taken as not solid.
|
|
|
|
|
| return_all (optional)
|
|
| If true, the function returns all nodes found by the ray.
|
|
|
|
|
| Return value:
|
|
| If a node is hit by the ray, returns a table with `pos' and `node'
|
|
| fields. `pos' is the position where collision occurred, and `node' is
|
|
| the node info as returned by `minetest.env:get_node()'.
|
|
| If an entity is hit by the ray, returns a table with `pos' and `entity'
|
|
| fields. `pos' is as above, `entity' is an ObjectRef.
|
|
| If nothing is found, returns nil. Note that unloaded blocks are actual
|
|
| nodes! (check for node.name == "ignore" if you want to distinguish).
|
|
| Also note that if `params.return_all' is true, it will return an array
|
|
| where the items are in this format.
|
|
]]
|
|
if (not kutils.find_pointed_thing) then
|
|
function kutils.find_pointed_thing ( params )
|
|
local p = {x=params.pos.x, y=params.pos.y, z=params.pos.z};
|
|
local dx, dy, dz = params.delta.x, params.delta.y, params.delta.z;
|
|
local radius = params.radius or 0.75;
|
|
local extra_ignore_ents = params.ignore_ents or { };
|
|
local range = params.range;
|
|
local solid_only = params.solid_only;
|
|
local list = { };
|
|
local listn = 1;
|
|
for n = 0, range do
|
|
local node = minetest.env:get_node(p);
|
|
if (not kutils.ignore_nodes[node.name]) then
|
|
if (solid_only) then
|
|
local walkable = minetest.registered_nodes[node.name].walkable;
|
|
if (walkable == false) then
|
|
if (not return_all) then
|
|
return {pos = p; node=node};
|
|
end
|
|
list[listn] = {pos = p; node=node};
|
|
listn = listn + 1;
|
|
end
|
|
else
|
|
if (not return_all) then
|
|
return {pos = p; node=node};
|
|
end
|
|
list[listn] = {pos = p; node=node};
|
|
listn = listn + 1;
|
|
end
|
|
end
|
|
local ents = minetest.env:get_objects_inside_radius(p, radius);
|
|
if (#ents > 0) then
|
|
for _,e in ipairs(ents) do
|
|
if ((e ~= params.user) and (not kutils.ignore_ents[e:get_entity_name()])
|
|
and (not extra_ignore_ents[e:get_entity_name()])) then
|
|
if (not return_all) then
|
|
return {pos=p; entity=e};
|
|
end
|
|
list[listn] = {pos = p; entity=e};
|
|
listn = listn + 1;
|
|
end
|
|
end
|
|
end
|
|
p.x = p.x + dx;
|
|
p.y = p.y + dy;
|
|
p.z = p.z + dz;
|
|
end
|
|
if (listn > 1) then
|
|
return list;
|
|
end
|
|
return nil;
|
|
end
|
|
end
|
|
|
|
if (not kutils.distance3d) then
|
|
function kutils.distance3d ( p1, p2 )
|
|
local lenx = math.abs(p2.x - p1.x);
|
|
local leny = math.abs(p2.y - p1.y);
|
|
local lenz = math.abs(p2.z - p1.z);
|
|
local hypotxz = math.sqrt((lenx * lenx) + (lenz * lenz));
|
|
return math.sqrt((hypotxz * hypotxz) + (leny * leny));
|
|
end
|
|
end
|