Add flatten command.
This commit is contained in:
parent
d1fda5aa30
commit
186abc20f3
2 changed files with 120 additions and 2 deletions
118
chat.lua
118
chat.lua
|
@ -60,3 +60,121 @@ minetest.register_chatcommand("fixlight", {
|
||||||
vm:update_map()
|
vm:update_map()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("flatten", {
|
||||||
|
params = "<radius>",
|
||||||
|
description = "flatten terrain",
|
||||||
|
privs = {},
|
||||||
|
func = function(name, param)
|
||||||
|
local privs = minetest.check_player_privs(name, {server=true})
|
||||||
|
if not privs then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
print('Fun Caves: '..name..' used the flatten command')
|
||||||
|
local player = minetest.get_player_by_name(name)
|
||||||
|
local pos = vector.round(player:getpos())
|
||||||
|
local radius = tonumber(param) or 50
|
||||||
|
radius = math.floor(radius)
|
||||||
|
local minp = vector.subtract(pos, radius)
|
||||||
|
minp.y = minp.y - math.ceil(radius / 2)
|
||||||
|
local maxp = vector.add(pos, radius)
|
||||||
|
maxp.y = maxp.y + math.ceil(radius / 2)
|
||||||
|
local air = minetest.get_content_id('air')
|
||||||
|
local stone = minetest.get_content_id('default:stone')
|
||||||
|
local water = minetest.get_content_id('default:water_source')
|
||||||
|
local waters = {}
|
||||||
|
waters[minetest.get_content_id('default:water_source')] = true
|
||||||
|
waters[minetest.get_content_id('default:river_water_source')] = true
|
||||||
|
local stone_types = {'default:stone', 'default:desert_stone', 'default:sandstone', 'default:dirt', 'fun_caves:dirt', 'default:dirt_with_snow', 'default:dirt_with_grass', 'default:dirt_with_dry_grass', 'default:sand', 'default:desert_sand'}
|
||||||
|
local stones = {}
|
||||||
|
for i = 1, #stone_types do
|
||||||
|
stones[minetest.get_content_id(stone_types[i])] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local vm = minetest.get_voxel_manip(minp, maxp)
|
||||||
|
local emin, emax = vm:read_from_map(minp, maxp)
|
||||||
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
||||||
|
local data = vm:get_data()
|
||||||
|
local heightmap = {}
|
||||||
|
local height_avg = 0
|
||||||
|
local count = 0
|
||||||
|
local index = 1
|
||||||
|
for z = minp.z, maxp.z do
|
||||||
|
for x = minp.x, maxp.x do
|
||||||
|
local ivm = area:index(x, maxp.y, z)
|
||||||
|
for y = maxp.y, minp.y, -1 do
|
||||||
|
if stones[data[ivm]] then
|
||||||
|
if y >= maxp.y then
|
||||||
|
print('Terrain altitude exceeds the radius.')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
heightmap[index] = y
|
||||||
|
height_avg = height_avg + heightmap[index]
|
||||||
|
count = count + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
ivm = ivm - area.ystride
|
||||||
|
end
|
||||||
|
|
||||||
|
if not heightmap[index] then
|
||||||
|
print('Terrain altitude exceeds the radius.')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
height_avg = math.floor(height_avg / count + 0.5)
|
||||||
|
|
||||||
|
index = 1
|
||||||
|
for z = minp.z, maxp.z do
|
||||||
|
local dz = z - minp.z
|
||||||
|
for x = minp.x, maxp.x do
|
||||||
|
local dx = x - minp.x
|
||||||
|
local r = math.max(math.abs(radius - dx), math.abs(radius - dz)) / radius
|
||||||
|
local new_y = heightmap[index]
|
||||||
|
if r < 1 then
|
||||||
|
new_y = math.floor(heightmap[index] * r ^ 2 + height_avg * (1 - r ^ 2) + 0.5)
|
||||||
|
end
|
||||||
|
local delta = new_y - heightmap[index]
|
||||||
|
if delta > 0 then
|
||||||
|
local ivm = area:index(x, maxp.y, z)
|
||||||
|
for y = maxp.y - delta, new_y, -1 do
|
||||||
|
data[ivm] = data[ivm - area.ystride * delta]
|
||||||
|
ivm = ivm - area.ystride
|
||||||
|
end
|
||||||
|
elseif delta < 0 then
|
||||||
|
local ivm = area:index(x, new_y - 2, z)
|
||||||
|
for y = new_y - 2, maxp.y + delta do
|
||||||
|
data[ivm] = data[ivm - area.ystride * delta]
|
||||||
|
ivm = ivm + area.ystride
|
||||||
|
end
|
||||||
|
for y = maxp.y + delta + 1, maxp.y do
|
||||||
|
data[ivm] = air
|
||||||
|
ivm = ivm + area.ystride
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ivm = area:index(x, minp.y, z)
|
||||||
|
for y = minp.y, maxp.y do
|
||||||
|
if y <= 1 and data[ivm] == air then
|
||||||
|
data[ivm] = water
|
||||||
|
elseif y > 1 and waters[data[ivm]] then
|
||||||
|
data[ivm] = air
|
||||||
|
end
|
||||||
|
ivm = ivm + area.ystride
|
||||||
|
end
|
||||||
|
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vm:set_data(data)
|
||||||
|
vm:calc_lighting(minp, maxp)
|
||||||
|
vm:update_liquids()
|
||||||
|
vm:write_to_map()
|
||||||
|
vm:update_map()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
|
@ -73,7 +73,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
-- Bombs
|
-- Bombs
|
||||||
local nodes = {{'fun_caves:pyramid_1', 'default:sandstone'}, {'fun_caves:tree', 'fun_caves:tree'},}
|
local nodes = {{'fun_caves:pyramid_1', 'default:sandstone'}, {'fun_caves:tree', 'fun_caves:tree'}, {'default:stone', 'default:cobble'},}
|
||||||
for _, node in pairs(nodes) do
|
for _, node in pairs(nodes) do
|
||||||
local node_name = node[1]
|
local node_name = node[1]
|
||||||
local comp = node[2] or node_name
|
local comp = node[2] or node_name
|
||||||
|
@ -106,7 +106,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
-- Floor bombs
|
-- Floor bombs
|
||||||
local nodes = {{'default:sandstone', 'default:sandstone_block'}, {'default:wood', 'fun_caves:wood_block'},}
|
local nodes = {{'default:sandstone', 'default:sandstone_block'}, {'default:wood', 'fun_caves:wood_block'}, {'default:stone', 'default:stone_block'},}
|
||||||
for _, node in pairs(nodes) do
|
for _, node in pairs(nodes) do
|
||||||
local node_name = node[1]
|
local node_name = node[1]
|
||||||
local comp = node[2] or node_name
|
local comp = node[2] or node_name
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue