From 186abc20f3e58d137949ad462526744a95e564be Mon Sep 17 00:00:00 2001 From: Duane Date: Sat, 9 Jul 2016 04:45:09 -0500 Subject: [PATCH] Add flatten command. --- chat.lua | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++ spec_bomb.lua | 4 +- 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/chat.lua b/chat.lua index 6a4b7ad..79789e5 100644 --- a/chat.lua +++ b/chat.lua @@ -60,3 +60,121 @@ minetest.register_chatcommand("fixlight", { vm:update_map() end, }) + + +minetest.register_chatcommand("flatten", { + params = "", + 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, +}) diff --git a/spec_bomb.lua b/spec_bomb.lua index 7845bb2..967c185 100644 --- a/spec_bomb.lua +++ b/spec_bomb.lua @@ -73,7 +73,7 @@ end -- 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 local node_name = node[1] local comp = node[2] or node_name @@ -106,7 +106,7 @@ end -- 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 local node_name = node[1] local comp = node[2] or node_name