mirror of
https://github.com/minetest-mods/technic.git
synced 2024-09-12 08:18:30 +02:00
Replace trace_node_ray algorithm
This is an algorithm that I designed myself. It fixes an issue with the old code where it would be more eager to move in some directions rather than others. This bug resulted in, eg, a lead block on a radiation source's +x side protecting you when you were directly overhead.
This commit is contained in:
parent
cfd4cb7871
commit
e501c4622b
@ -63,64 +63,50 @@ technic.tube_inject_item = pipeworks.tube_inject_item or function(pos, start_pos
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Based on code by Uberi: https://gist.github.com/Uberi/3125280
|
--- Iterates over the node positions along the specified ray.
|
||||||
|
-- The returned positions will not include the starting position.
|
||||||
function technic.trace_node_ray(pos, dir, range)
|
function technic.trace_node_ray(pos, dir, range)
|
||||||
local p = vector.round(pos)
|
local x_step = dir.x > 0 and 1 or -1
|
||||||
local x_step, y_step, z_step = 0, 0, 0
|
local y_step = dir.y > 0 and 1 or -1
|
||||||
local x_component, y_component, z_component = 0, 0, 0
|
local z_step = dir.z > 0 and 1 or -1
|
||||||
local x_intersect, y_intersect, z_intersect = 0, 0, 0
|
|
||||||
|
|
||||||
if dir.x == 0 then
|
local i = 1
|
||||||
x_intersect = math.huge
|
return function(p)
|
||||||
elseif dir.x > 0 then
|
-- Approximation of where we should be if we weren't rounding
|
||||||
x_step = 1
|
-- to nodes. This moves forward a bit faster then we do.
|
||||||
x_component = 1 / dir.x
|
-- A correction is done below.
|
||||||
x_intersect = x_component
|
local real_x = pos.x + (dir.x * i)
|
||||||
else
|
local real_y = pos.y + (dir.y * i)
|
||||||
x_step = -1
|
local real_z = pos.z + (dir.z * i)
|
||||||
x_component = 1 / -dir.x
|
|
||||||
end
|
-- How far off we've gotten from where we should be.
|
||||||
if dir.y == 0 then
|
local dx = math.abs(real_x - p.x)
|
||||||
y_intersect = math.huge
|
local dy = math.abs(real_y - p.y)
|
||||||
elseif dir.y > 0 then
|
local dz = math.abs(real_z - p.z)
|
||||||
y_step = 1
|
|
||||||
y_component = 1 / dir.y
|
-- If the real position moves ahead too fast, stop it so we
|
||||||
y_intersect = y_component
|
-- can catch up. If it gets too far ahead it will smooth
|
||||||
else
|
-- out our movement too much and we won't turn fast enough.
|
||||||
y_step = -1
|
if dx + dy + dz < 2 then
|
||||||
y_component = 1 / -dir.y
|
i = i + 1
|
||||||
end
|
|
||||||
if dir.z == 0 then
|
|
||||||
z_intersect = math.huge
|
|
||||||
elseif dir.z > 0 then
|
|
||||||
z_step = 1
|
|
||||||
z_component = 1 / dir.z
|
|
||||||
z_intersect = z_component
|
|
||||||
else
|
|
||||||
z_step = -1
|
|
||||||
z_component = 1 / -dir.z
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return function()
|
-- Step in whichever direction we're most off course in.
|
||||||
if x_intersect < y_intersect then
|
if dx > dy then
|
||||||
if x_intersect < z_intersect then
|
if dx > dz then
|
||||||
p.x = p.x + x_step
|
p.x = p.x + x_step
|
||||||
x_intersect = x_intersect + x_component
|
|
||||||
else
|
else
|
||||||
p.z = p.z + z_step
|
p.z = p.z + z_step
|
||||||
z_intersect = z_intersect + z_component
|
|
||||||
end
|
end
|
||||||
elseif y_intersect < z_intersect then
|
elseif dy > dz then
|
||||||
p.y = p.y + y_step
|
p.y = p.y + y_step
|
||||||
y_intersect = y_intersect + y_component
|
|
||||||
else
|
else
|
||||||
p.z = p.z + z_step
|
p.z = p.z + z_step
|
||||||
z_intersect = z_intersect + z_component
|
|
||||||
end
|
end
|
||||||
if vector.distance(pos, p) > range then
|
if vector.distance(pos, p) > range then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
return p
|
return p
|
||||||
end
|
end, vector.round(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user