046bcc445a
-puzzle privs, puzzle mechanics
223 lines
7.4 KiB
Lua
223 lines
7.4 KiB
Lua
--smoothie robot: smooths selected terrain with slopes: define region with chat c1,c2, smooth with s
|
|
|
|
if not paste then
|
|
_G.minetest.forceload_block(self.pos(),true)
|
|
paste = {};
|
|
round = function(x)
|
|
if x>0 then
|
|
return math.floor(x+0.5)
|
|
else
|
|
return -math.floor(-x+0.5)
|
|
end
|
|
end
|
|
|
|
is_solid = function(i,j,k, is_return)
|
|
local dat = data[i]
|
|
if not is_return then
|
|
if not dat then return false end
|
|
dat = dat[j];
|
|
if not dat then return false end
|
|
dat = dat[k];
|
|
if not dat then return false end
|
|
return true
|
|
else
|
|
if not dat then return 0 end
|
|
dat = dat[j];
|
|
if not dat then return 0 end
|
|
dat = dat[k];
|
|
if not dat then return 0 end
|
|
return dat
|
|
end
|
|
end
|
|
|
|
solidnodes = {
|
|
["default:stone"] = 1,
|
|
["default:dirt"] = 2,
|
|
["default:stone_with_coal"] = 0,
|
|
["default:dirt_with_dry_grass"] = 2,
|
|
["default:silver_sand"] = 0,
|
|
["default:sand"] = 0,
|
|
}
|
|
|
|
solidtypes =
|
|
{
|
|
[1] = "stone",
|
|
[2] = "dirt"
|
|
};
|
|
|
|
data = {};
|
|
self.listen(1)
|
|
self.label("mr. smoothie")
|
|
end
|
|
|
|
|
|
speaker, msg = self.listen_msg()
|
|
|
|
if msg and (true or speaker == "rnd") then
|
|
local player = _G.minetest.get_player_by_name(speaker);
|
|
local p = player:getpos(); p.x = round(p.x); p.y=round(p.y); p.z = round(p.z);
|
|
if msg == "c1" then
|
|
paste.src1 = {x=p.x,y=p.y,z=p.z};say("marker 1 set at " .. p.x .. " " .. p.y .. " " .. p.z)
|
|
elseif msg == "c2" then
|
|
paste.src2 = {x=p.x,y=p.y,z=p.z};say("marker 2 set at " .. p.x .. " " .. p.y .. " " .. p.z)
|
|
|
|
elseif msg == "c" then -- LOAD geometry in memory
|
|
local x1 = math.min(paste.src1.x,paste.src2.x);local y1 = math.min(paste.src1.y,paste.src2.y);local z1 = math.min(paste.src1.z,paste.src2.z);
|
|
local x2 = math.max(paste.src1.x,paste.src2.x);local y2 = math.max(paste.src1.y,paste.src2.y);local z2 = math.max(paste.src1.z,paste.src2.z);
|
|
x1=x1-1;y1=y1-1;z1=z1-1;x2=x2+1;y2=y2+1;z2=z2+1;
|
|
local count = 0; data = {};
|
|
for i = x1,x2 do
|
|
for j = y1,y2 do
|
|
for k = z1,z2 do
|
|
local node = _G.minetest.get_node({x=i,y=j,z=k});
|
|
local typ = solidnodes[node.name];
|
|
if not typ then if string.sub(node.name,1,4) == "more" then typ = 1 end end
|
|
if typ then
|
|
if not data[i] then data[i]= {} end
|
|
if not data[i][j] then data[i][j]= {} end
|
|
data[i][j][k] = -typ
|
|
count = count +1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
say(count .. " nodes copied ");
|
|
elseif msg == "s" then -- SMOOTHING PROCESS
|
|
local x1 = math.min(paste.src1.x,paste.src2.x);local y1 = math.min(paste.src1.y,paste.src2.y);local z1 = math.min(paste.src1.z,paste.src2.z);
|
|
local x2 = math.max(paste.src1.x,paste.src2.x);local y2 = math.max(paste.src1.y,paste.src2.y);local z2 = math.max(paste.src1.z,paste.src2.z);
|
|
local count = 0; local newnode = {};
|
|
for i = x1,x2 do
|
|
for j = y1,y2 do
|
|
for k = z1,z2 do
|
|
local x = i;local y = j; local z = k;
|
|
--say(x .. " " .. y .. " " .. z)
|
|
if is_solid(x,y,z) and not is_solid(x,y+1,z) then -- floor node
|
|
local xs1,xs2,zs1,zs2
|
|
if is_solid(x-1,y,z) then if is_solid(x-1,y+1,z) then xs1 = 1 else xs1 = 0 end else xs1 = -1 end
|
|
if is_solid(x+1,y,z) then if is_solid(x+1,y+1,z) then xs2 = 1 else xs2 = 0 end else xs2 = -1 end
|
|
|
|
if is_solid(x,y,z-1) then if is_solid(x,y+1,z-1) then zs1 = 1 else zs1 = 0 end else zs1 = -1 end
|
|
if is_solid(x,y,z+1) then if is_solid(x,y+1,z+1) then zs2 = 1 else zs2 = 0 end else zs2 = -1 end
|
|
|
|
local dx = xs2 - xs1; local dz = zs2 - zs1; ch = 0;
|
|
if dx > 0 and dz == 0 then
|
|
if xs1<0 then
|
|
newnode[1] = "moreblocks:slope_stone"; newnode[2] = 1; ch = 1
|
|
data[x][y][z] = 2;
|
|
end
|
|
elseif dx<0 and dz == 0 then
|
|
if xs2<0 then
|
|
newnode[1] = "moreblocks:slope_stone"; newnode[2] = 3; ch = 1
|
|
data[x][y][z] = 2;
|
|
end
|
|
elseif dx == 0 and dz < 0 then
|
|
if zs2<0 then
|
|
newnode[1] = "moreblocks:slope_stone"; newnode[2] = 2; ch = 1
|
|
data[x][y][z] = 2;
|
|
end
|
|
elseif dx == 0 and dz > 0 then
|
|
if zs1<0 then
|
|
newnode[1] = "moreblocks:slope_stone"; newnode[2] = 0; ch = 1
|
|
data[x][y][z] = 2;
|
|
end
|
|
|
|
elseif dx<0 and dz>0 then
|
|
newnode[2] = 0; ch = 1
|
|
if xs2 == 0 and zs1 == 0 then
|
|
newnode[1] = "moreblocks:slope_stone_inner";
|
|
data[x][y][z] = 5;
|
|
else
|
|
newnode[1] = "moreblocks:slope_stone_outer_cut"
|
|
data[x][y][z] = 3;
|
|
end
|
|
elseif dx>0 and dz>0 then
|
|
newnode[2] = 1; ch = 1
|
|
if xs1 == 0 and zs1 == 0 then
|
|
newnode[1] = "moreblocks:slope_stone_inner"
|
|
data[x][y][z] = 5;
|
|
else
|
|
newnode[1] = "moreblocks:slope_stone_outer_cut"
|
|
data[x][y][z] = 3;
|
|
end
|
|
elseif dx>0 and dz<0 then
|
|
newnode[2] = 2; ch = 1
|
|
if xs1==0 and zs2 == 0 then
|
|
newnode[1] = "moreblocks:slope_stone_inner"
|
|
data[x][y][z] = 5;
|
|
else
|
|
newnode[1] = "moreblocks:slope_stone_outer_cut"
|
|
data[x][y][z] = 3;
|
|
end
|
|
elseif dx<0 and dz<0 then
|
|
newnode[2] = 3; ch = 1
|
|
if xs2 == 0 and zs2 == 0 then
|
|
newnode[1] = "moreblocks:slope_stone_inner"
|
|
data[x][y][z] = 5;
|
|
else
|
|
newnode[1] = "moreblocks:slope_stone_outer_cut"
|
|
data[x][y][z] = 3;
|
|
end
|
|
end
|
|
if ch == 1 then _G.minetest.swap_node({x=x,y=y,z=z},{name = newnode[1], param2 = newnode[2]}) end
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--2nd pass
|
|
-- smooth stones below slope_stone_outer_cut if there is at least one air in neighbor 4 diag. positions
|
|
-- and set same param2 as above outer_cut
|
|
-- slope = 2, outer cut = 3, inner cut = 4, inner = 5
|
|
|
|
for i = x1,x2 do
|
|
for j = y1,y2 do
|
|
for k = z1,z2 do
|
|
local x = i;local y = j; local z = k;
|
|
|
|
if is_solid(x,y,z) and is_solid(x,y+1,z,true) == 3 then -- fix stone below outer cut
|
|
if not is_solid(x-1,y,z-1) or not is_solid(x+1,y,z-1) or not is_solid(x-1,y,z+1)
|
|
or not is_solid(x+1,y,z+1) then
|
|
-- replace with inner cut to smooth diag. ramps
|
|
local param2 = _G.minetest.get_node({x=x,y=y+1,z=z}).param2;
|
|
_G.minetest.swap_node({x=x,y=y,z=z},{name = "moreblocks:slope_stone_inner_cut", param2 = param2})
|
|
end
|
|
|
|
--fix possible holes
|
|
elseif is_solid(x,y,z,true) == 5 and not is_solid(x,y+1,z) then --hole fix: inner
|
|
if is_solid(x-1,y,z-1) and is_solid(x+1,y,z-1) and is_solid(x-1,y,z+1)
|
|
and is_solid(x+1,y,z+1) then
|
|
_G.minetest.swap_node({x=x,y=y,z=z},{name = "default:stone"})
|
|
end
|
|
elseif is_solid(x,y,z,true) == 4 and not is_solid(x,y+1,z) then -- hole fix: inner cut
|
|
if is_solid(x-1,y,z-1) and is_solid(x+1,y,z-1) and is_solid(x-1,y,z+1)
|
|
and is_solid(x+1,y,z+1) then
|
|
_G.minetest.swap_node({x=x,y=y,z=z},{name = "default:stone"})
|
|
end
|
|
|
|
elseif is_solid(x,y,z,true)<0 and not is_solid(x,y+1,z) then -- attempt to smooth blocky stones near outer cuts
|
|
local x0,z0;
|
|
if is_solid(x-1,y,z,true) == 3 -- outer cut
|
|
then x0 = x-1; z0 = z;
|
|
elseif is_solid(x+1,y,z,true) == 3
|
|
then x0 = x+1; z0 = z;
|
|
elseif is_solid(x-1,y,z-1,true) == 3
|
|
then x0 = x-1; z0 = z-1;
|
|
elseif is_solid(x+1,y,z+1,true) == 3
|
|
then x0 = x+1; z0 = z+1;
|
|
end
|
|
if x0 then
|
|
local param2 = _G.minetest.get_node({x=x0,y=y,z=z0}).param2;
|
|
_G.minetest.swap_node({x=x,y=y,z=z},{name = "moreblocks:slope_stone_inner_cut", param2 = param2})
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
end |