From 1475ee6e40b61ba2b604ac6dc3ff285df415450f Mon Sep 17 00:00:00 2001
From: ShadowNinja <shadowninja@minetest.net>
Date: Thu, 17 Nov 2016 17:48:19 +0100
Subject: [PATCH] Add trace_node_ray_fat and use it for mining lasers

---
 technic/helpers.lua |   79 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 79 insertions(+), 0 deletions(-)

diff --git a/technic/helpers.lua b/technic/helpers.lua
index f0c2fc6..5780f27 100644
--- a/technic/helpers.lua
+++ b/technic/helpers.lua
@@ -110,3 +110,82 @@
 	end, vector.round(pos)
 end
 
+
+--- Like trace_node_ray, but includes extra positions close to the ray.
+function technic.trace_node_ray_fat(pos, dir, range)
+	local x_step = dir.x > 0 and 1 or -1
+	local y_step = dir.y > 0 and 1 or -1
+	local z_step = dir.z > 0 and 1 or -1
+
+	local next_poses = {}
+
+	local i = 1
+	return function(p)
+		local ni, np = next(next_poses)
+		if np then
+			next_poses[ni] = nil
+			return np
+		end
+
+		-- Approximation of where we should be if we weren't rounding
+		-- to nodes.  This moves forward a bit faster then we do.
+		-- A correction is done below.
+		local real_x = pos.x + (dir.x * i)
+		local real_y = pos.y + (dir.y * i)
+		local real_z = pos.z + (dir.z * i)
+
+		-- How far off we've gotten from where we should be.
+		local dx = math.abs(real_x - p.x)
+		local dy = math.abs(real_y - p.y)
+		local dz = math.abs(real_z - p.z)
+
+		-- If the real position moves ahead too fast, stop it so we
+		-- can catch up.  If it gets too far ahead it will smooth
+		-- out our movement too much and we won't turn fast enough.
+		if dx + dy + dz < 2 then
+			i = i + 1
+		end
+
+		-- Step in whichever direction we're most off course in.
+		local sx, sy, sz  -- Whether we've already stepped along each axis
+		if dx > dy then
+			if dx > dz then
+				sx = true
+				p.x = p.x + x_step
+			else
+				sz = true
+				p.z = p.z + z_step
+			end
+		elseif dy > dz then
+			sy = true
+			p.y = p.y + y_step
+		else
+			sz = true
+			p.z = p.z + z_step
+		end
+
+		if vector.distance(pos, p) > range then
+			return nil
+		end
+
+		-- Add other positions that we're significantly off on.
+		-- We can just use fixed integer keys here because the
+		-- table will be completely cleared before we reach this
+		-- code block again.
+		local dlen = math.sqrt(dx*dx + dy*dy + dz*dz)
+		-- Normalized axis deltas
+		local dxn, dyn, dzn = dx / dlen, dy / dlen, dz / dlen
+		if not sx and dxn > 0.5 then
+			next_poses[1] = vector.new(p.x + x_step, p.y, p.z)
+		end
+		if not sy and dyn > 0.5 then
+			next_poses[2] = vector.new(p.x, p.y + y_step, p.z)
+		end
+		if not sz and dzn > 0.5 then
+			next_poses[3] = vector.new(p.x, p.y, p.z + z_step)
+		end
+
+		return p
+	end, vector.round(pos)
+end
+

--
Gitblit v1.8.0