|
|
@ -1,5 +1,10 @@
|
|
|
|
local mh = worldedit.manip_helpers
|
|
|
|
local mh = worldedit.manip_helpers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(worldedit.register_command,
|
|
|
|
|
|
|
|
"Your WorldEdit installation is out of date, "..
|
|
|
|
|
|
|
|
"please update to the latest version from git"..
|
|
|
|
|
|
|
|
"to run we_env.")
|
|
|
|
|
|
|
|
|
|
|
|
---------------------------------------------
|
|
|
|
---------------------------------------------
|
|
|
|
-- manipulations
|
|
|
|
-- manipulations
|
|
|
|
---------------------------------------------
|
|
|
|
---------------------------------------------
|
|
|
@ -123,7 +128,7 @@ local function ores(pos1, pos2, pretend_y, try)
|
|
|
|
local oreids = {}
|
|
|
|
local oreids = {}
|
|
|
|
for _, def in pairs(minetest.registered_ores) do
|
|
|
|
for _, def in pairs(minetest.registered_ores) do
|
|
|
|
if table.indexof(disallow_oretypes, def.ore_type) == -1 then
|
|
|
|
if table.indexof(disallow_oretypes, def.ore_type) == -1 then
|
|
|
|
oreids[#oreids + 1] = minetest.get_content_id(def.ore)
|
|
|
|
oreids[minetest.get_content_id(def.ore)] = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
@ -153,8 +158,9 @@ local function ores(pos1, pos2, pretend_y, try)
|
|
|
|
local index_y = index_x + (offset.y + y) * stride.y
|
|
|
|
local index_y = index_x + (offset.y + y) * stride.y
|
|
|
|
for z = 0, dim.z-1 do
|
|
|
|
for z = 0, dim.z-1 do
|
|
|
|
local index_z = index_y + (offset.z + z) * stride.z
|
|
|
|
local index_z = index_y + (offset.z + z) * stride.z
|
|
|
|
if table.indexof(oreids, data2[index_z]) ~= -1 then
|
|
|
|
local cid = data2[index_z]
|
|
|
|
data[index_z] = data2[index_z]
|
|
|
|
if oreids[cid] then
|
|
|
|
|
|
|
|
data[index_z] = cid
|
|
|
|
count = count + 1
|
|
|
|
count = count + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -185,43 +191,7 @@ end
|
|
|
|
|
|
|
|
|
|
|
|
local EWMA_alpha = 0.45
|
|
|
|
local EWMA_alpha = 0.45
|
|
|
|
local WEIGHT = {orig=0.2, x=0.4, z=0.4}
|
|
|
|
local WEIGHT = {orig=0.2, x=0.4, z=0.4}
|
|
|
|
local function smooth(pos1, pos2, deadzone)
|
|
|
|
local ewma = function(heightmap, hstride, dim, out)
|
|
|
|
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
|
|
|
|
|
|
|
local dim = vector.add(vector.subtract(pos2, pos1), 1)
|
|
|
|
|
|
|
|
if dim.x < 2 or dim.y < 2 or dim.z < 2 then return 0 end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local manip, area = mh.init(pos1, pos2)
|
|
|
|
|
|
|
|
local data = manip:get_data()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local stride = {x=1, y=area.ystride, z=area.zstride}
|
|
|
|
|
|
|
|
local offset = vector.subtract(pos1, area.MinEdge)
|
|
|
|
|
|
|
|
local c_air = minetest.get_content_id("air")
|
|
|
|
|
|
|
|
local c_dirt = minetest.get_content_id("default:dirt")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- read heightmap from data
|
|
|
|
|
|
|
|
local heightmap = {}
|
|
|
|
|
|
|
|
local hstride = {x=1, z=dim.x}
|
|
|
|
|
|
|
|
for x = 0, dim.x-1 do
|
|
|
|
|
|
|
|
for z = 0, dim.z-1 do
|
|
|
|
|
|
|
|
heightmap[x + (z * hstride.z) + 1] = 0
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
for x = 0, dim.x-1 do
|
|
|
|
|
|
|
|
local index_x = offset.x + x + 1 -- +1 for 1-based indexing
|
|
|
|
|
|
|
|
for z = 0, dim.z-1 do
|
|
|
|
|
|
|
|
local index_z = index_x + (offset.z + z) * stride.z
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local y = dim.y-1
|
|
|
|
|
|
|
|
while y >= 0 do
|
|
|
|
|
|
|
|
if data[index_z + (offset.y + y) * stride.y] ~= c_air then
|
|
|
|
|
|
|
|
heightmap[x + (z * hstride.z) + 1] = y + 1
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
y = y - 1
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- calculate EWMA for each x/z slice
|
|
|
|
-- calculate EWMA for each x/z slice
|
|
|
|
local slice_x, slice_z = {}, {}
|
|
|
|
local slice_x, slice_z = {}, {}
|
|
|
|
for x = 0, dim.x-1 do -- x+
|
|
|
|
for x = 0, dim.x-1 do -- x+
|
|
|
@ -277,7 +247,68 @@ local function smooth(pos1, pos2, deadzone)
|
|
|
|
return slice_z[z+1][x+1]
|
|
|
|
return slice_z[z+1][x+1]
|
|
|
|
end)--]]
|
|
|
|
end)--]]
|
|
|
|
|
|
|
|
|
|
|
|
-- adjust actual heights based on results
|
|
|
|
-- calculate actual heights
|
|
|
|
|
|
|
|
for x = 0, dim.x-1 do
|
|
|
|
|
|
|
|
for z = 0, dim.z-1 do
|
|
|
|
|
|
|
|
local hindex = x + (z * hstride.z) + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local old_height = heightmap[hindex]
|
|
|
|
|
|
|
|
local new_height = math.floor(
|
|
|
|
|
|
|
|
old_height * WEIGHT.orig +
|
|
|
|
|
|
|
|
slice_x[x+1][z+1] * WEIGHT.x +
|
|
|
|
|
|
|
|
slice_z[z+1][x+1] * WEIGHT.z +
|
|
|
|
|
|
|
|
0.5
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
out[hindex] = new_height
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function smooth(pos1, pos2, deadzone, iterations)
|
|
|
|
|
|
|
|
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
|
|
|
|
|
|
|
local dim = vector.add(vector.subtract(pos2, pos1), 1)
|
|
|
|
|
|
|
|
if dim.x < 2 or dim.y < 2 or dim.z < 2 then return 0 end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local manip, area = mh.init(pos1, pos2)
|
|
|
|
|
|
|
|
local data = manip:get_data()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local stride = {x=1, y=area.ystride, z=area.zstride}
|
|
|
|
|
|
|
|
local offset = vector.subtract(pos1, area.MinEdge)
|
|
|
|
|
|
|
|
local c_air = minetest.get_content_id("air")
|
|
|
|
|
|
|
|
local c_dirt = minetest.get_content_id("default:dirt")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- read heightmap from data
|
|
|
|
|
|
|
|
local heightmap = {}
|
|
|
|
|
|
|
|
local hstride = {x=1, z=dim.x}
|
|
|
|
|
|
|
|
for x = 0, dim.x-1 do
|
|
|
|
|
|
|
|
for z = 0, dim.z-1 do
|
|
|
|
|
|
|
|
heightmap[x + (z * hstride.z) + 1] = 0
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
for x = 0, dim.x-1 do
|
|
|
|
|
|
|
|
local index_x = offset.x + x + 1 -- +1 for 1-based indexing
|
|
|
|
|
|
|
|
for z = 0, dim.z-1 do
|
|
|
|
|
|
|
|
local index_z = index_x + (offset.z + z) * stride.z
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local y = dim.y-1
|
|
|
|
|
|
|
|
while y >= 0 do
|
|
|
|
|
|
|
|
if data[index_z + (offset.y + y) * stride.y] ~= c_air then
|
|
|
|
|
|
|
|
heightmap[x + (z * hstride.z) + 1] = y + 1
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
y = y - 1
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- apply algorithm
|
|
|
|
|
|
|
|
local heightmap_new = {}
|
|
|
|
|
|
|
|
ewma(heightmap, hstride, dim, heightmap_new)
|
|
|
|
|
|
|
|
for i = 2, iterations do
|
|
|
|
|
|
|
|
ewma(heightmap_new, hstride, dim, heightmap_new)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- adjust actual heights
|
|
|
|
local count = 0
|
|
|
|
local count = 0
|
|
|
|
for x = 0, dim.x-1 do
|
|
|
|
for x = 0, dim.x-1 do
|
|
|
|
local index_x = offset.x + x + 1 -- +1 for 1-based indexing
|
|
|
|
local index_x = offset.x + x + 1 -- +1 for 1-based indexing
|
|
|
@ -288,13 +319,9 @@ local function smooth(pos1, pos2, deadzone)
|
|
|
|
if x < deadzone.x or x > dim.x-1 - deadzone.x then noop = true end
|
|
|
|
if x < deadzone.x or x > dim.x-1 - deadzone.x then noop = true end
|
|
|
|
if z < deadzone.z or z > dim.z-1 - deadzone.z then noop = true end
|
|
|
|
if z < deadzone.z or z > dim.z-1 - deadzone.z then noop = true end
|
|
|
|
|
|
|
|
|
|
|
|
local old_height = heightmap[x + (z * hstride.z) + 1]
|
|
|
|
local hindex = x + (z * hstride.z) + 1
|
|
|
|
local new_height = math.floor(
|
|
|
|
local old_height = heightmap[hindex]
|
|
|
|
old_height * WEIGHT.orig +
|
|
|
|
local new_height = heightmap_new[hindex]
|
|
|
|
slice_x[x+1][z+1] * WEIGHT.x +
|
|
|
|
|
|
|
|
slice_z[z+1][x+1] * WEIGHT.z +
|
|
|
|
|
|
|
|
0.5
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if noop then
|
|
|
|
if noop then
|
|
|
|
-- do nothing (deadzone)
|
|
|
|
-- do nothing (deadzone)
|
|
|
@ -335,63 +362,64 @@ end
|
|
|
|
-- chat commands
|
|
|
|
-- chat commands
|
|
|
|
---------------------------------------------
|
|
|
|
---------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
minetest.register_chatcommand("/fall", {
|
|
|
|
local check_region = function(name)
|
|
|
|
|
|
|
|
return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name])
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
worldedit.register_command("fall", {
|
|
|
|
params = "",
|
|
|
|
params = "",
|
|
|
|
description = "Apply gravity to all falling nodes in current WorldEdit region",
|
|
|
|
description = "Apply gravity to all falling nodes in selected region",
|
|
|
|
privs = {worldedit=true},
|
|
|
|
privs = {worldedit=true},
|
|
|
|
func = function(name, param)
|
|
|
|
require_pos = 2,
|
|
|
|
|
|
|
|
nodes_needed = check_region,
|
|
|
|
|
|
|
|
func = function(name)
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
if pos1 == nil or pos2 == nil then
|
|
|
|
|
|
|
|
worldedit.player_notify(name, "no region selected")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
local count = fall(pos1, pos2)
|
|
|
|
local count = fall(pos1, pos2)
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
minetest.register_chatcommand("/populate", {
|
|
|
|
worldedit.register_command("populate", {
|
|
|
|
params = "",
|
|
|
|
params = "",
|
|
|
|
description = "Populate dirt in current WorldEdit region",
|
|
|
|
description = "Populate dirt in selected region",
|
|
|
|
privs = {worldedit=true},
|
|
|
|
privs = {worldedit=true},
|
|
|
|
func = function(name, param)
|
|
|
|
require_pos = 2,
|
|
|
|
|
|
|
|
nodes_needed = check_region,
|
|
|
|
|
|
|
|
func = function(name)
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
if pos1 == nil or pos2 == nil then
|
|
|
|
|
|
|
|
worldedit.player_notify(name, "no region selected")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
local count = populate(pos1, pos2)
|
|
|
|
local count = populate(pos1, pos2)
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
minetest.register_chatcommand("/ores", {
|
|
|
|
worldedit.register_command("ores", {
|
|
|
|
params = "",
|
|
|
|
params = "",
|
|
|
|
description = "Generate ores in current WorldEdit region",
|
|
|
|
description = "Generate ores in selected region",
|
|
|
|
privs = {worldedit=true},
|
|
|
|
privs = {worldedit=true},
|
|
|
|
func = function(name, param)
|
|
|
|
require_pos = 2,
|
|
|
|
|
|
|
|
nodes_needed = check_region,
|
|
|
|
|
|
|
|
parse = function(param)
|
|
|
|
|
|
|
|
return true, tonumber(param) or 0
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
func = function(name, depth)
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
if pos1 == nil or pos2 == nil then
|
|
|
|
|
|
|
|
worldedit.player_notify(name, "no region selected")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
local depth = param ~= "" and tonumber(param) or 0
|
|
|
|
|
|
|
|
local count = ores(pos1, pos2, depth)
|
|
|
|
local count = ores(pos1, pos2, depth)
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
minetest.register_chatcommand("/smooth", {
|
|
|
|
worldedit.register_command("smooth", {
|
|
|
|
params = "",
|
|
|
|
params = "[iterations]",
|
|
|
|
description = "Smooth terrain in current WorldEdit region",
|
|
|
|
description = "Smooth terrain in selected region",
|
|
|
|
privs = {worldedit=true},
|
|
|
|
privs = {worldedit=true},
|
|
|
|
func = function(name, param)
|
|
|
|
require_pos = 2,
|
|
|
|
|
|
|
|
nodes_needed = check_region,
|
|
|
|
|
|
|
|
parse = function(param)
|
|
|
|
|
|
|
|
return true, tonumber(param) or 1
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
func = function(name, iterations)
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
|
|
if pos1 == nil or pos2 == nil then
|
|
|
|
local count = smooth(pos1, pos2, {x=0, z=0}, iterations)
|
|
|
|
worldedit.player_notify(name, "no region selected")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
local count = smooth(pos1, pos2, {x=0, z=0})
|
|
|
|
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
worldedit.player_notify(name, count .. " nodes updated")
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
})
|
|
|
@ -410,12 +438,12 @@ if minetest.registered_items["worldedit:brush"] == nil then
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local internal_name = "_smooth_brush_internal_do_not_use"
|
|
|
|
local internal_name = "_smooth_brush_internal_do_not_use"
|
|
|
|
minetest.register_chatcommand("/" .. internal_name, {
|
|
|
|
worldedit.register_command(internal_name, {
|
|
|
|
params = "",
|
|
|
|
params = "",
|
|
|
|
privs = {worldedit=true},
|
|
|
|
privs = {worldedit=true},
|
|
|
|
func = function(name, param)
|
|
|
|
require_pos = 1,
|
|
|
|
|
|
|
|
func = function(name)
|
|
|
|
local pos = worldedit.pos1[name]
|
|
|
|
local pos = worldedit.pos1[name]
|
|
|
|
assert(pos ~= nil)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Only modify an 10*10 area but take heights from 14*14 into consideration
|
|
|
|
-- Only modify an 10*10 area but take heights from 14*14 into consideration
|
|
|
|
local dist, dead = 10, 4
|
|
|
|
local dist, dead = 10, 4
|
|
|
@ -459,18 +487,18 @@ minetest.register_chatcommand("/" .. internal_name, {
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
smooth(pos1, pos2, {x=dead, z=dead})
|
|
|
|
smooth(pos1, pos2, {x=dead, z=dead}, 1)
|
|
|
|
--[[worldedit.pos1[name] = pos1
|
|
|
|
--[[worldedit.pos1[name] = pos1
|
|
|
|
worldedit.pos2[name] = pos2
|
|
|
|
worldedit.pos2[name] = pos2
|
|
|
|
worldedit.mark_region(name)--]]
|
|
|
|
worldedit.marker_update(name)--]]
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
minetest.register_chatcommand("/smoothbrush", {
|
|
|
|
worldedit.register_command("smoothbrush", {
|
|
|
|
privs = {worldedit=true},
|
|
|
|
privs = {worldedit=true},
|
|
|
|
params = "",
|
|
|
|
params = "",
|
|
|
|
description = "Assign smoothing action to WorldEdit brush item",
|
|
|
|
description = "Assign smoothing action to WorldEdit brush item",
|
|
|
|
func = function(name, param)
|
|
|
|
func = function(name)
|
|
|
|
local itemstack = minetest.get_player_by_name(name):get_wielded_item()
|
|
|
|
local itemstack = minetest.get_player_by_name(name):get_wielded_item()
|
|
|
|
if itemstack == nil or itemstack:get_name() ~= "worldedit:brush" then
|
|
|
|
if itemstack == nil or itemstack:get_name() ~= "worldedit:brush" then
|
|
|
|
worldedit.player_notify(name, "Not holding brush item.")
|
|
|
|
worldedit.player_notify(name, "Not holding brush item.")
|
|
|
|