Cristiano Magro
2020-10-14 d781261523f49191a87f8eda4b8c5ea01272f60d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
-- 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