12 Commits

Author SHA1 Message Date
3228cec1ae Merge remote-tracking branch 'upstream/master' 2024-09-15 13:00:59 +02:00
f400a91e90 Remove functions which are deprecated and which I do not recommend to use
Removing deprecated functionality can help to clean up the code a bit.

I remove the following deprecated functions and values:
* vector.zero
* vector.plane()
* vector.pos_to_string()
* vector.quickadd()
* vector.scalar()
* vector.get_data_from_pos()
* vector.set_data_to_pos()
* vector.set_data_to_pos_optional()
* vector.remove_data_from_pos()
* vector.get_data_pos_table()

Furthermore, I remove the unused, experimental vector_meta.lua file
and make luacheck linting more strict so that it can show accidental
uses of deprecated functions in the code of this mod if there are any.

This change can break compatility with old mods which use vector_extras.
2024-08-27 17:38:30 +02:00
0501920345 Merge remote-tracking branch 'upstream/master' 2021-11-01 10:44:31 +01:00
63edf837d7 depends.txt -> mod.conf 2021-10-10 12:57:57 +02:00
9bf8a890c6 Merge remote-tracking branch 'upstream/master' 2021-09-21 23:13:15 +02:00
ed6b514057 Make vector.zero callable
This is needed to keep compatibility with new minetest builtin code
2021-09-05 19:04:02 +02:00
374735b17f Merge remote-tracking branch 'upstream/master' 2021-03-12 12:41:19 +01:00
f8c12047d5 Add .luacheckrc and some code cleanup 2021-03-01 20:37:59 +01:00
fdbcc2e425 A small comment 2021-03-01 19:26:24 +01:00
2f0ad734d4 Merge remote-tracking branch 'upstream/master' 2020-08-25 20:07:10 +02:00
8c7aaf6c0b Fix a bug in deprecated vector.plane 2020-08-25 11:03:17 +02:00
e826bbd9b9 Replace vector.scalar with vector.dot 2020-08-25 11:03:17 +02:00
6 changed files with 64 additions and 493 deletions

11
.luacheckrc Normal file
View File

@ -0,0 +1,11 @@
read_globals = {
-- Defined by Minetest
"minetest", "PseudoRandom", "VoxelArea", "string", "dump", "math",
vector = {
fields = {
"add", "cross", "direction", "distance", "dot", "multiply",
"new", "normalize", "round", "subtract",
"from_number", "get_max_coord", "twoline", "threeline", "rayIter"
}
}
}

18
doc.md
View File

@ -134,21 +134,3 @@ See e.g. `minetest.line_of_sight`.
* If `time` is omitted, it uses the current time.
* This function does not yet support the moon;
at night it simply returns `nil`.
## Helpers which I don't recommend to use now
* `vector.pos_to_string(pos)`: returns a string
* It is similar to `minetest.pos_to_string`; it uses a different format:
`"("..pos.x.."|"..pos.y.."|"..pos.z..")"`
* `vector.zero`
* The zero vector `{x=0, y=0, z=0}`
* `vector.quickadd(pos, [z],[y],[x])`
* Adds values to the vector components in-place
## Deprecated helpers
* `vector.plane`
* should be removed soon; it should have done the same as vector.triangle

250
init.lua
View File

@ -2,10 +2,6 @@ local path = minetest.get_modpath"vector_extras"
local funcs = {}
function funcs.pos_to_string(pos)
return "("..pos.x.."|"..pos.y.."|"..pos.z..")"
end
local r_corr = 0.25 --remove a bit more nodes (if shooting diagonal) to let it
-- look like a hole (sth like antialiasing)
@ -52,6 +48,7 @@ local function return_line(pos, dir, range) --range ~= length
local num = 1
local t_dir = get_used_dir(dir)
local dir_typ = t_dir[1]
local f_tab
if t_dir[3] == "+" then
f_tab = {0, range, 1}
else
@ -122,7 +119,7 @@ function funcs.rayIter(pos, dir)
for i in pairs(step) do
choose[i] = vector.new(p)
choose[i][i] = choose[i][i] + step[i]
choosefit[i] = vector.scalar(vector.normalize(vector.subtract(choose[i], pos)), dir)
choosefit[i] = vector.dot(vector.normalize(vector.subtract(choose[i], pos)), dir)
end
p = choose[vector.get_max_coord(choosefit)]
@ -269,63 +266,6 @@ function funcs.pnorm(v, p)
return (math.abs(v.x)^p + math.abs(v.y)^p + math.abs(v.z)^p)^(1 / p)
end
--not optimized
--local areas = {}
function funcs.plane(ps)
-- sort positions and imagine the first one (A) as vector.zero
ps = vector.sort_positions(ps)
local pos = ps[1]
local B = vector.subtract(ps[2], pos)
local C = vector.subtract(ps[3], pos)
-- get the positions for the fors
local cube_p1 = {x=0, y=0, z=0}
local cube_p2 = {x=0, y=0, z=0}
for i in pairs(cube_p1) do
cube_p1[i] = math.min(B[i], C[i], 0)
cube_p2[i] = math.max(B[i], C[i], 0)
end
cube_p1 = vector.apply(cube_p1, math.floor)
cube_p2 = vector.apply(cube_p2, math.ceil)
local vn = vector.normalize(vector.cross(B, C))
local nAB = vector.normalize(B)
local nAC = vector.normalize(C)
local angle_BAC = math.acos(vector.scalar(nAB, nAC))
local nBA = vector.multiply(nAB, -1)
local nBC = vector.normalize(vector.subtract(C, B))
local angle_ABC = math.acos(vector.scalar(nBA, nBC))
for z = cube_p1.z, cube_p2.z do
for y = cube_p1.y, cube_p2.y do
for x = cube_p1.x, cube_p2.x do
local p = {x=x, y=y, z=z}
local n = -vector.scalar(p, vn)/vector.scalar(vn, vn)
if math.abs(n) <= 0.5 then
local ep = vector.add(p, vector.multiply(vn, n))
local nep = vector.normalize(ep)
local angle_BAep = math.acos(vector.scalar(nAB, nep))
local angle_CAep = math.acos(vector.scalar(nAC, nep))
local angldif = angle_BAC - (angle_BAep+angle_CAep)
if math.abs(angldif) < 0.001 then
ep = vector.subtract(ep, B)
nep = vector.normalize(ep)
local angle_ABep = math.acos(vector.scalar(nBA, nep))
local angle_CBep = math.acos(vector.scalar(nBC, nep))
local angldif = angle_ABC - (angle_ABep+angle_CBep)
if math.abs(angldif) < 0.001 then
table.insert(ps, vector.add(pos, p))
end
end
end
end
end
end
return ps
end
function funcs.straightdelay(s, v, a)
if not a then
return s/v
@ -333,8 +273,6 @@ function funcs.straightdelay(s, v, a)
return (math.sqrt(v*v+2*a*s)-v)/a
end
vector.zero = vector.new()
function funcs.sun_dir(time)
if not time then
time = minetest.get_timeofday()
@ -358,9 +296,9 @@ function funcs.inside(pos, minp, maxp)
return true
end
function funcs.minmax(p1, p2)
local p1 = vector.new(p1)
local p2 = vector.new(p2)
function funcs.minmax(pos1, pos2)
local p1 = vector.new(pos1)
local p2 = vector.new(pos2)
for _,i in ipairs({"x", "y", "z"}) do
if p1[i] > p2[i] then
p1[i], p2[i] = p2[i], p1[i]
@ -390,7 +328,7 @@ end
local adammil_fill = dofile(path .. "/adammil_flood_fill.lua")
function funcs.search_2d(go_test, x0, y0, allow_revisit, give_map)
marked_places = adammil_fill(go_test, x0, y0, allow_revisit)
local marked_places = adammil_fill(go_test, x0, y0, allow_revisit)
if give_map then
return marked_places
end
@ -406,7 +344,7 @@ end
local fallings_search = dofile(path .. "/fill_3d.lua")
local moves_touch = {
{x = -1, y = 0, z = 0},
{x = 0, y = 0, z = 0},
{x = 0, y = 0, z = 0}, -- FIXME should this be here?
{x = 1, y = 0, z = 0},
{x = 0, y = -1, z = 0},
{x = 0, y = 1, z = 0},
@ -498,7 +436,8 @@ function funcs.explosion_perlin(rmin, rmax, nparams)
nparams.spread = nparams.spread or vector.from_number(r*5)
local pos = {x=math.random(-30000, 30000), y=math.random(-30000, 30000), z=math.random(-30000, 30000)}
local map = minetest.get_perlin_map(nparams, vector.from_number(r+r+1)):get3dMap_flat(pos)
local map = minetest.get_perlin_map(nparams, vector.from_number(r+r+1)
):get3dMap_flat(pos)
local id = 1
@ -513,11 +452,11 @@ function funcs.explosion_perlin(rmin, rmax, nparams)
local tab, n = {}, 1
for z=-r,r do
local bare_dist = z*z
local bare_dist_z = z*z
for y=-r,r do
local bare_dist = bare_dist+y*y
local bare_dist_yz = bare_dist_z + y*y
for x=-r,r do
local bare_dist = bare_dist+x*x
local bare_dist = bare_dist_yz + x*x
local add = bare_dist < bare_mindist
local pval, distdiv
if not add
@ -543,22 +482,19 @@ function funcs.explosion_perlin(rmin, rmax, nparams)
end
end
map = nil
collectgarbage()
-- change strange values
local pval_diff = pval_max - pval_min
pval_min = pval_min/pval_diff
for n,i in pairs(tab) do
for k,i in pairs(tab) do
if i[2] then
local new_pval = math.abs(i[2]/pval_diff - pval_min)
if i[3]+0.33 < new_pval then
tab[n] = {i[1]}
tab[k] = {i[1]}
elseif i[3] < new_pval then
tab[n] = {i[1], true}
tab[k] = {i[1], true}
else
tab[n] = nil
tab[k] = nil
end
end
end
@ -633,67 +569,6 @@ function funcs.ring(r)
return tab2
end
--~ posy(t) = att + bt + c
--~ vely(t) = 2at + b
--~ accy(t) = 2a
--~ a = -0.5gravity
--~ vely(0) = b = vel.y
--~ posy(0) = c = pos.y
--~ posy(t) = -0.5 * gravity * t * t + vel.y * t + pos.y
--~ vely(t) = -gravity*t + vel.y
--~ Scheitel:
--~ vely(t) = 0 = -gravity*t + vel.y
--~ t = vel.y / gravity
--~ 45°
--~ vely(t)^2 = velx(t)^2 + velz(t)^2
--~ (-gravity*t + vel.y)^2 = vel.x * vel.x + vel.z * vel.z
--~ gravity^2 * t^2 + vel.y^2 - -2*gravity*t*vel.y = vel.x * vel.x + vel.z * vel.z
--~ gravity^2 * t^2 - 2*gravity*vel.y * t + (vel.y^2 - vel.x^2 - vel.z^2) = 0
--~ t = (2*gravity*vel.y .. rt((2*gravity*vel.y)^2 - 4*gravity^2*(vel.y^2 - vel.x^2 - vel.z^2))) / (2*gravity^2)
--~ t = (2*gravity*vel.y .. rt(4*gravity^2*vel.y^2 - 4*gravity^2*(vel.y^2) + 4*gravity^2*(vel.x^2 + vel.z^2))) / (2*gravity^2)
--~ t = (2*gravity*vel.y .. 2*gravity*rt(vel.x^2 + vel.z^2)) / (2*gravity^2)
--~ t = (vel.y .. rt(vel.x^2 + vel.z^2)) / gravity
--~ t1 = (vel.y - math.sqrt(vel.x * vel.x + vel.z * vel.z)) / gravity
--~ t2 = (vel.y + math.sqrt(vel.x * vel.x + vel.z * vel.z)) / gravity
--~ yswitch = posy(t1) (= posy(t2)) //links und rechts gleich
--~ yswitch = -0.5 * gravity * ((vel.y + math.sqrt(vel.x * vel.x + vel.z * vel.z)) / gravity)^2 + vel.y * ((vel.y + math.sqrt(vel.x * vel.x + vel.z * vel.z)) / gravity) + pos.y
--~ yswitch = -0.5 * gravity * (vel.y + math.sqrt(vel.x * vel.x + vel.z * vel.z))^2 / gravity^2 + vel.y * ((vel.y + math.sqrt(vel.x * vel.x + vel.z * vel.z)) / gravity) + pos.y
--~ yswitch = -0.5 * (vel.y^2 + 2*vel.y*math.sqrt(vel.x * vel.x + vel.z * vel.z) + vel.x^2 + vel.z^2) / gravity + ((vel.y^2 + vel.y*math.sqrt(vel.x * vel.x + vel.z * vel.z)) / gravity) + pos.y
--~ yswitch = (-0.5 * (vel.y^2 + 2*vel.y*math.sqrt(vel.x * vel.x + vel.z * vel.z) + vel.x^2 + vel.z^2) + ((vel.y^2 + vel.y*math.sqrt(vel.x * vel.x + vel.z * vel.z)))) / gravity + pos.y
--~ yswitch = (-0.5 * vel.y^2 - vel.y*math.sqrt(vel.x * vel.x + vel.z * vel.z) - 0.5 * vel.x^2 - 0.5 * vel.z^2 + vel.y^2 + vel.y*math.sqrt(vel.x * vel.x + vel.z * vel.z)) / gravity + pos.y
--~ yswitch = (-0.5 * vel.y^2 - 0.5 * vel.x^2 - 0.5 * vel.z^2 + vel.y^2) / gravity + pos.y
--~ yswitch = (0.5 * vel.y^2 - 0.5 * vel.x^2 - 0.5 * vel.z^2) / gravity + pos.y
--~ yswitch = -0.5 * (vel.x * vel.x + vel.z * vel.z - vel.y * vel.y) / gravity + pos.y
--~ 45° Zeitpunkte kleineres beim Aufstieg, größeres beim Fall
--~ (-gravity*t + vel.y)^2 = vel.x * vel.x + vel.z * vel.z
--~ -gravity*t + vel.y = ..math.sqrt(vel.x * vel.x + vel.z * vel.z)
--~ t = (..math.sqrt(vel.x * vel.x + vel.z * vel.z) + vel.y) / gravity
--~ t_raise = (-math.sqrt(vel.x * vel.x + vel.z * vel.z) + vel.y) / gravity
--~ t_fall = (math.sqrt(vel.x * vel.x + vel.z * vel.z) + vel.y) / gravity
--~ posy nach t umstellen
--~ y = -0.5 * gravity * t * t + vel.y * t + pos.y
--~ 0 = -0.5 * gravity * t * t + vel.y * t + pos.y - y
--~ t = (-vel.y .. math.sqrt(vel.y^2 + 2 * gravity * (pos.y - y))) / (-gravity)
--~ t = (vel.y .. math.sqrt(vel.y^2 + 2 * gravity * (pos.y - y))) / gravity
--~ t_up = (vel.y - math.sqrt(vel.y^2 + 2 * gravity * (pos.y - y))) / gravity
--~ t_down = (vel.y + math.sqrt(vel.y^2 + 2 * gravity * (pos.y - y))) / gravity
--~ posx(t) = vel.x * t + pos.x
--~ posz(t) = vel.z * t + pos.z
--~ posx nach t umstellen
--~ posx - pos.x = vel.x * t
--~ t = (posx - pos.x) / vel.x
local function get_parabola_points(pos, vel, gravity, waypoints, max_pointcount,
time)
local pointcount = 0
@ -703,9 +578,9 @@ local function get_parabola_points(pos, vel, gravity, waypoints, max_pointcount,
/ gravity + pos.y
-- the times of the 45° angle point
local i = math.sqrt(vel.x^2 + vel.z^2)
local t_raise_end = (-i + vel.y) / gravity
local t_fall_start = (i + vel.y) / gravity
local vel_len = math.sqrt(vel.x^2 + vel.z^2)
local t_raise_end = (-vel_len + vel.y) / gravity
local t_fall_start = (vel_len + vel.y) / gravity
if t_fall_start > 0 then
-- the right 45° angle point wasn't passed yet
if t_raise_end > 0 then
@ -834,11 +709,11 @@ function funcs.throw_parabola(pos, vel, gravity, point_count, time)
-- get a list of possible positions between
local diff = vector.subtract(p2, p)
local possible_positions = {}
for i,v in pairs(diff) do
for c,v in pairs(diff) do
if v ~= 0 then
local p = vector.new(p)
p[i] = p[i] + v
possible_positions[#possible_positions+1] = p
local pos_moved = vector.new(p)
pos_moved[c] = pos_moved[c] + v
possible_positions[#possible_positions+1] = pos_moved
end
end
-- test which one fits best
@ -849,12 +724,12 @@ function funcs.throw_parabola(pos, vel, gravity, point_count, time)
z = vel.z * t + pos.z,
}
local d = math.huge
for i = 1,2 do
local pos = possible_positions[i]
local dist = vector.distance(pos, near_p)
if dist < d then
p = pos
d = dist
for k = 1,2 do
local pos_moved = possible_positions[k]
local dist_current = vector.distance(pos_moved, near_p)
if dist_current < d then
p = pos_moved
d = dist_current
end
end
-- add it
@ -865,11 +740,11 @@ function funcs.throw_parabola(pos, vel, gravity, point_count, time)
-- get a list of possible positions between
local diff = vector.subtract(p2, p)
local possible_positions = {}
for i,v in pairs(diff) do
for c,v in pairs(diff) do
if v ~= 0 then
local p = vector.new(p)
p[i] = p[i] + v
possible_positions[#possible_positions+1] = p
local pos_moved = vector.new(p)
pos_moved[c] = pos_moved[c] + v
possible_positions[#possible_positions+1] = pos_moved
end
end
-- test which one fits best
@ -881,12 +756,12 @@ function funcs.throw_parabola(pos, vel, gravity, point_count, time)
}
local d = math.huge
assert(#possible_positions == 4-k, "how, number positions?")
for i = 1,4-k do
local pos = possible_positions[i]
local dist = vector.distance(pos, near_p)
if dist < d then
p = pos
d = dist
for j = 1,4-k do
local pos_moved = possible_positions[j]
local dist_current = vector.distance(pos_moved, near_p)
if dist_current < d then
p = pos_moved
d = dist_current
end
end
-- add it
@ -907,9 +782,9 @@ function funcs.chunkcorner(pos)
return {x=pos.x-pos.x%16, y=pos.y-pos.y%16, z=pos.z-pos.z%16}
end
function funcs.point_distance_minmax(p1, p2)
local p1 = vector.new(p1)
local p2 = vector.new(p2)
function funcs.point_distance_minmax(pos1, pos2)
local p1 = vector.new(pos1)
local p2 = vector.new(pos2)
local min, max, vmin, vmax, num
for _,i in ipairs({"x", "y", "z"}) do
num = math.abs(p1[i] - p2[i])
@ -926,21 +801,20 @@ function funcs.point_distance_minmax(p1, p2)
end
function funcs.collision(p1, p2)
local clear, node_pos, collision_pos, max, dmax, dcmax, pt
clear, node_pos = minetest.line_of_sight(p1, p2)
local clear, node_pos = minetest.line_of_sight(p1, p2)
if clear then
return false
end
collision_pos = {}
min, max = funcs.point_distance_minmax(node_pos, p2)
local collision_pos = {}
local _, max = funcs.point_distance_minmax(node_pos, p2)
if node_pos[max] > p2[max] then
collision_pos[max] = node_pos[max] - 0.5
else
collision_pos[max] = node_pos[max] + 0.5
end
dmax = p2[max] - node_pos[max]
dcmax = p2[max] - collision_pos[max]
pt = dcmax/dmax
local dmax = p2[max] - node_pos[max]
local dcmax = p2[max] - collision_pos[max]
local pt = dcmax / dmax
for _,i in ipairs({"x", "y", "z"}) do
collision_pos[i] = p2[i] - (p2[i] - node_pos[i]) * pt
@ -955,18 +829,6 @@ function funcs.update_minp_maxp(minp, maxp, pos)
end
end
function funcs.quickadd(pos, z,y,x)
if z then
pos.z = pos.z+z
end
if y then
pos.y = pos.y+y
end
if x then
pos.x = pos.x+x
end
end
function funcs.unpack(pos)
return pos.z, pos.y, pos.x
end
@ -1037,9 +899,9 @@ function funcs.triangle(pos1, pos2, pos3)
end
-- https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage
local function edgefunc(p1, p2, pos)
return (pos[1] - p1[1]) * (p2[2] - p1[2])
- (pos[2] - p1[2]) * (p2[1] - p1[1])
local function edgefunc(vert1, vert2, pos)
return (pos[1] - vert1[1]) * (vert2[2] - vert1[2])
- (pos[2] - vert1[2]) * (vert2[1] - vert1[1])
end
-- eps is used to prevend holes in neighbouring triangles
-- It should be smaller than the smallest possible barycentric value
@ -1075,20 +937,12 @@ function funcs.triangle(pos1, pos2, pos3)
return points, n, barycentric_coords
end
vector_extras_functions = funcs
dofile(path .. "/legacy.lua")
--dofile(minetest.get_modpath("vector_extras").."/vector_meta.lua")
vector_extras_functions = nil
for name,func in pairs(funcs) do
if vector[name] then
minetest.log("error", "[vector_extras] vector."..name..
" already exists.")
else
-- luacheck: globals vector
vector[name] = func
end
end

View File

@ -1,94 +0,0 @@
local funcs = vector_extras_functions
function funcs.scalar(v1, v2)
minetest.log("deprecated", "[vector_extras] vector.scalar is " ..
"deprecated, use vector.dot instead.")
return vector.dot(v1, v2)
end
function funcs.get_data_from_pos(tab, z,y,x)
minetest.log("deprecated", "[vector_extras] get_data_from_pos is " ..
"deprecated, use the minetest pos hash function instead.")
local data = tab[z]
if data then
data = data[y]
if data then
return data[x]
end
end
end
function funcs.set_data_to_pos(tab, z,y,x, data)
minetest.log("deprecated", "[vector_extras] set_data_to_pos is " ..
"deprecated, use the minetest pos hash function instead.")
if tab[z] then
if tab[z][y] then
tab[z][y][x] = data
return
end
tab[z][y] = {[x] = data}
return
end
tab[z] = {[y] = {[x] = data}}
end
function funcs.set_data_to_pos_optional(tab, z,y,x, data)
minetest.log("deprecated", "[vector_extras] set_data_to_pos_optional is " ..
"deprecated, use the minetest pos hash function instead.")
if vector.get_data_from_pos(tab, z,y,x) ~= nil then
return
end
funcs.set_data_to_pos(tab, z,y,x, data)
end
function funcs.remove_data_from_pos(tab, z,y,x)
minetest.log("deprecated", "[vector_extras] remove_data_from_pos is " ..
"deprecated, use the minetest pos hash function instead.")
if vector.get_data_from_pos(tab, z,y,x) == nil then
return
end
tab[z][y][x] = nil
if not next(tab[z][y]) then
tab[z][y] = nil
end
if not next(tab[z]) then
tab[z] = nil
end
end
function funcs.get_data_pos_table(tab)
minetest.log("deprecated", "[vector_extras] get_data_pos_table likely " ..
"is deprecated, use the minetest pos hash function instead.")
local t,n = {},1
local minz, miny, minx, maxz, maxy, maxx
for z,yxs in pairs(tab) do
if not minz then
minz = z
maxz = z
else
minz = math.min(minz, z)
maxz = math.max(maxz, z)
end
for y,xs in pairs(yxs) do
if not miny then
miny = y
maxy = y
else
miny = math.min(miny, y)
maxy = math.max(maxy, y)
end
for x,v in pairs(xs) do
if not minx then
minx = x
maxx = x
else
minx = math.min(minx, x)
maxx = math.max(maxx, x)
end
t[n] = {z,y,x, v}
n = n+1
end
end
end
return t, {x=minx, y=miny, z=minz}, {x=maxx, y=maxy, z=maxz}, n-1
end

1
mod.conf Normal file
View File

@ -0,0 +1 @@
name = vector_extras

View File

@ -1,183 +0,0 @@
vector.meta = vector.meta or {}
vector.meta.nodes = {}
vector.meta.nodes_file = {
load = function()
local nodesfile = io.open(minetest.get_worldpath()..'/vector_nodes.txt', "r")
if nodesfile then
local contents = nodesfile:read('*all')
io.close(nodesfile)
if contents ~= nil then
local lines = string.split(contents, "\n")
for _,entry in ipairs(lines) do
local name, px, py, pz, meta = unpack(string.split(entry, "°"))
vector.meta.set_node({x=px, y=py, z=pz}, name, meta)
end
end
end
end,
save = function() --WRITE CHANGES TO FILE
local output = ''
for x,ys in pairs(vector.meta.nodes) do
for y,zs in pairs(ys) do
for z,names in pairs(zs) do
for name,meta in pairs(names) do
output = name.."°"..x.."°"..y.."°"..z.."°"..dump(meta).."\n"
end
end
end
end
local f = io.open(minetest.get_worldpath()..'/vector_nodes.txt', "w")
f:write(output)
io.close(f)
end
}
local function table_empty(tab) --looks if it's an empty table
if next(tab) == nil then
return true
end
return false
end
function vector.meta.nodes_info() --returns an info string of the node table
local tmp = "[vector] "..dump(vector.meta.nodes).."\n[vector]:\n"
for x,a in pairs(vector.meta.nodes) do
for y,b in pairs(a) do
for z,c in pairs(b) do
for name,meta in pairs(c) do
tmp = tmp..">\t"..name.." "..x.." "..y.." "..z.." "..dump(meta).."\n"
end
end
end
end
return tmp
end
function vector.meta.clean_node_table() --replaces {} with nil
local again = true
while again do
again = false
for x,ys in pairs(vector.meta.nodes) do
if table_empty(ys) then
vector.meta.nodes[x] = nil
again = true
else
for y,zs in pairs(ys) do
if table_empty(zs) then
vector.meta.nodes[x][y] = nil
again = true
else
for z,names in pairs(zs) do
if table_empty(names) then
vector.meta.nodes[x][y][z] = nil
again = true
else
for name,meta in pairs(names) do
if table_empty(meta)
or meta == "" then
vector.meta.nodes[x][y][z][name] = nil
again = true
end
end
end
end
end
end
end
end
end
end
function vector.meta.complete_node_table(pos, name) --neccesary because tab[1] wouldn't work if tab is not a table
local tmp = vector.meta.nodes[pos.x]
if not tmp then
vector.meta.nodes[pos.x] = {}
end
local tmp = vector.meta.nodes[pos.x][pos.y]
if not tmp then
vector.meta.nodes[pos.x][pos.y] = {}
end
local tmp = vector.meta.nodes[pos.x][pos.y][pos.z]
if not tmp then
vector.meta.nodes[pos.x][pos.y][pos.z] = {}
end
local tmp = vector.meta.nodes[pos.x][pos.y][pos.z][name]
if not tmp then
vector.meta.nodes[pos.x][pos.y][pos.z][name] = {}
end
end
function vector.meta.get_node(pos, name)
if not pos then
return false
end
local tmp = vector.meta.nodes[pos.x]
if not tmp
or table_empty(tmp) then
return false
end
local tmp = vector.meta.nodes[pos.x][pos.y]
if not tmp
or table_empty(tmp) then
return false
end
local tmp = vector.meta.nodes[pos.x][pos.y][pos.z]
if not tmp
or table_empty(tmp) then
return false
end
-- if name isn't mentioned, just look if there's a node
if not name then
return true
end
local tmp = vector.meta.nodes[pos.x][pos.y][pos.z][name]
if not tmp
or table_empty(tmp) then
return false
end
return tmp
end
function vector.meta.remove_node(pos)
if not pos then
return false
end
if vector.meta.get_node(pos) then
vector.meta.nodes[pos.x][pos.y][pos.z] = nil
local xarr = vector.meta.nodes[pos.x]
if table_empty(xarr[pos.y]) then
vector.meta.nodes[pos.x][pos.y] = nil
end
if table_empty(xarr) then
vector.meta.nodes[pos.x] = nil
end
else
print("[vector_extras] Warning: The node at "..vector.pos_to_string(pos).." wasn't stored in vector.meta.nodes.")
end
end
function vector.meta.set_node(pos, name, meta)
if not (name or pos) then
return false
end
vector.meta.complete_node_table(pos, name)
meta = meta or true
vector.meta.nodes[pos.x][pos.y][pos.z][name] = meta
end
minetest.register_chatcommand('cleanvectormetatable',{
description = 'Tidy up it.',
params = "",
privs = {},
func = function(name)
vector.meta.clean_node_table()
local tmp = vector.meta.nodes_info()
minetest.chat_send_player(name, tmp)
print("[vector_extras] "..tmp)
end
})
vector.meta.nodes_file.load()