From 3d38d757384579ee62dd2f58594e376a34585bfb Mon Sep 17 00:00:00 2001
From: Cristiano Magro <cristiano.magro@vola.it>
Date: Tue, 13 Oct 2020 20:17:38 +0200
Subject: [PATCH] Collect rubber and tree

---
 technic/tools/xno_tree_tap.lua |  144 +++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 119 insertions(+), 25 deletions(-)

diff --git a/technic/tools/xno_tree_tap.lua b/technic/tools/xno_tree_tap.lua
index d030399..c73c73a 100644
--- a/technic/tools/xno_tree_tap.lua
+++ b/technic/tools/xno_tree_tap.lua
@@ -1,3 +1,105 @@
+-- A simple special-purpose class, this is used for building up sets of three-dimensional points for fast reference
+
+Pointset = {}
+Pointset.__index = Pointset
+
+function Pointset.create()
+  local set = {}
+  setmetatable(set,Pointset)
+  set.points = {}
+  return set
+end
+
+function Pointset:set(x, y, z, value)
+  -- sets a value in the 3D array "points".
+  if self.points[x] == nil then
+    self.points[x] = {}
+  end
+  if self.points[x][y] == nil then
+    self.points[x][y] = {}
+  end
+  self.points[x][y][z] = value  
+end
+
+function Pointset:set_if_not_in(excluded, x, y, z, value)
+  -- If a value is not already set for this point in the 3D array "excluded", set it in "points"
+  if excluded:get(x, y, z) ~= nil then
+    return
+  end
+  self:set(x, y, z, value)
+end
+
+function Pointset:get(x, y, z)
+  -- return a value from the 3D array "points"
+  if self.points[x] == nil or self.points[x][y] == nil then
+    return nil
+  end
+  return self.points[x][y][z]
+end
+
+function Pointset:set_pos(pos, value)
+  self:set(pos.x, pos.y, pos.z, value)
+end
+
+function Pointset:set_pos_if_not_in(excluded, pos, value)
+  self:set_if_not_in(excluded, pos.x, pos.y, pos.z, value)
+end
+
+function Pointset:get_pos(pos)
+  return self:get(pos.x, pos.y, pos.z)
+end
+
+function Pointset:pop()
+  -- returns a point that's in the 3D array, and then removes it.
+  local pos = {}
+  local ytable
+  local ztable
+  local val
+
+  local count = 0
+  for _ in pairs(self.points) do count = count + 1 end
+  if count == 0 then
+    return nil
+  end
+  
+  pos.x, ytable = next(self.points)
+  pos.y, ztable = next(ytable)
+  pos.z, val = next(ztable)
+
+  self.points[pos.x][pos.y][pos.z] = nil
+  
+  count = 0
+  for _ in pairs(self.points[pos.x][pos.y]) do count = count + 1 end
+  if count == 0 then
+    self.points[pos.x][pos.y] = nil
+  end
+  
+  count = 0
+  for _ in pairs(self.points[pos.x]) do count = count + 1 end
+  if count == 0 then
+    self.points[pos.x] = nil
+  end
+  
+  return pos, val
+end
+
+function Pointset:get_pos_list(value)
+  -- Returns a list of all points with the given value in standard Minetest vector format. If no value is provided, returns all points
+  local outlist = {}
+  for x, ytable in ipairs(self.points) do
+    for y, ztable in ipairs(ytable) do
+      for z, val in ipairs(ztable) do
+        if (value == nil and val ~= nil ) or val == value then
+          table.insert(outlist, {x=x, y=y, z=z})
+        end
+      end
+    end
+  end
+  return outlist
+end
+      
+  
+
 -- Configuration
 
 local xnotreetap_max_charge      = 30000 -- Maximum charge of the saw
@@ -16,7 +118,7 @@
 }
 
 -- Remember node visited recursive and not dig twice
-local node_visited = {}
+local nodeVisited = Pointset.create()
 
 local timber_nodenames = {}
 for _, node in pairs(nodes) do
@@ -51,6 +153,10 @@
 
 -- Table for saving what was sawed down
 local produced = {}
+
+local function myString (v)
+  return v.x.." "..v.y.." "..v.z.." "
+end
 
 -- Save the items sawed down so that we can drop them in a nice single stack
 local function handle_drops(drops)
@@ -119,44 +225,32 @@
 
 -- inserisco un valore in tabella
 local function add_table(table, toadd)
-  local i = 1
-  while true do
-    local o = table[i]
-    if o == toadd then return end
-    if o == nil then break end
-    i = i + 1
-  end
-  table[i] = toadd
+  table:set(toadd.x, toadd.y, toadd.z, true)
 end
 
 -- bool controllo se un valore � presente in tabella
-local function in_table(table, value)
-  local i = 1
-  while true do
-    local o = table[i]
-    if o == value then
-      minetest.log("action", "[Xno Tree Tap] "..value.." visited.") --print to log
-      return true
+local function in_table(table, pos)
+  local val = table:get(pos.x, pos.y, pos.z)
+  local visited = 'NO'
+  
+  if val ~= nil then
+    if val then 
+      visited = 'SI'
     end
-    if o == nil then break end
-    i = i + 1
+    minetest.log("action", "[Xno Tree Tap] "..myString(pos).." visited? " .. visited) --print to log
+    return val
   end
   return false
 end
 
 -- verifico se un nodo � nella tabella visitato
 local function check_if_node_visited (pos)
-  return in_table(node_visited, pos)
-end
-
-local function myString (v)
-  return v.x.." "..v.y.." "..v.z.." "
+  return in_table(nodeVisited, pos)
 end
 
 local function set_node_visited (pos)
   minetest.log("action", "[Xno Tree Tap] "..myString(pos).." set node visited.") --print to log
-
-  add_table(node_visited, pos)
+  add_table(nodeVisited, pos)
 end
 
 -- This function does all the hard work. Recursively we dig the node at hand

--
Gitblit v1.8.0