local node = squaresville.node minetest.register_chatcommand("fixlight", { params = "", description = "attempt to fix light bugs", privs = {}, func = function(player_name, param) if not (player_name and type(player_name) == 'string' and player_name ~= '') then return end local privs = minetest.check_player_privs(player_name, {server=true}) if not privs then return end print('Fun Caves: '..player_name..' used the fixlight command') local player = minetest.get_player_by_name(player_name) if not player then return end local pos = player:getpos() if not pos then return end pos = vector.round(pos) local radius = tonumber(param) or 50 radius = math.floor(radius) local minp = vector.subtract(pos, radius) local maxp = vector.add(pos, radius) local vm = minetest.get_voxel_manip(minp, maxp) if not vm then return end --vm:set_lighting({day = 0, night = 0}, minp, maxp) vm:calc_lighting(minp, maxp) vm:update_liquids() vm:write_to_map() vm:update_map() end, }) minetest.register_chatcommand("flatten", { params = "", description = "flatten terrain", privs = {}, func = function(player_name, param) if not (player_name and type(player_name) == 'string' and player_name ~= '') then return end local privs = minetest.check_player_privs(player_name, {server=true}) if not privs then return end print('Fun Caves: '..player_name..' used the flatten command') local player = minetest.get_player_by_name(player_name) if not player then return end local pos = player:getpos() if not pos then return end pos = vector.round(pos) 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) if not vm then return end 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 minetest.chat_send_player(player_name, 'Terrain altitude exceeds the given 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 minetest.chat_send_player(player_name, 'Terrain altitude exceeds the given 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, })