2022-09-18 17:45:08 +02:00
local wea_c = worldeditadditions_core
2022-09-19 18:27:59 +02:00
local Vector3 = wea_c.Vector3
2023-08-03 15:16:14 +02:00
---
-- @module worldeditadditions_core
2020-06-13 03:08:03 +02:00
--- Raycasts to find a node in the direction the given player is looking.
2023-08-03 15:16:14 +02:00
--
-- This function is not currently aware of custom hitboxes.
2020-06-13 03:08:03 +02:00
-- @param player Player The player object to raycast from.
-- @param maxdist number The maximum distance to raycast.
-- @param skip_liquid bool Whether to skip liquids when raycasting.
-- @return position, number nil if nothing was found (or unloaded chunks were hit), or the position as an {x, y, z} table and the node id if something was found.
2022-09-18 17:45:08 +02:00
function wea_c . raycast ( player , maxdist , skip_liquid )
2020-06-13 03:08:03 +02:00
if maxdist == nil then maxdist = 100 end
if skip_liquid == nil then skip_liquid = false end
2022-09-19 18:27:59 +02:00
local look_dir = Vector3.clone ( player : get_look_dir ( ) )
2020-06-13 03:08:03 +02:00
local node_id_ignore = minetest.get_content_id ( " ignore " )
2022-09-19 18:27:59 +02:00
local cur_pos
local player_pos = player : get_pos ( )
2020-06-13 03:08:03 +02:00
player_pos.y = player_pos.y + 1.5 -- Calculate from the eye position
2020-06-13 15:23:14 +02:00
local divisor = 5
2020-06-13 03:08:03 +02:00
for i = 1 , maxdist do
2020-06-13 15:23:14 +02:00
local j = i / divisor
2020-06-13 03:08:03 +02:00
2022-09-19 18:27:59 +02:00
cur_pos = ( look_dir * j ) + player_pos
local node_pos = cur_pos : round ( )
2020-06-13 15:23:14 +02:00
-- Don't bother if this is the same position we were looking at before
if not ( node_pos.x == math.floor ( 0.5 + look_dir.x * ( j - divisor ) )
and node_pos.y == math.floor ( 0.5 + look_dir.y * ( j - divisor ) )
and node_pos.z == math.floor ( 0.5 + look_dir.z * ( j - divisor ) ) ) then
2020-06-13 03:08:03 +02:00
2020-06-13 15:23:14 +02:00
local found_node = false
2020-06-13 03:08:03 +02:00
2020-06-13 15:23:14 +02:00
local node = minetest.get_node_or_nil ( node_pos )
if node ~= nil then
local node_id = minetest.get_content_id ( node.name )
2022-09-19 18:27:59 +02:00
local is_air = wea_c.is_airlike ( node_id )
2020-06-13 15:23:14 +02:00
-- ignore = unloaded chunks, as far as I can tell
if node_id == node_id_ignore then
return nil
end
if is_air == false then
if skip_liquid == false then
return node_pos , node_id
else
2022-09-19 18:27:59 +02:00
local is_liquid = wea_c.is_liquidlike ( node_id )
2020-06-13 15:23:14 +02:00
if is_liquid == false then
return node_pos , node_id
end
end
2020-06-13 03:08:03 +02:00
end
end
2020-06-13 15:23:14 +02:00
2020-06-13 03:08:03 +02:00
end
end
return nil
end