diff --git a/mapgen.lua b/mapgen.lua index 1b3c07f..630236b 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -12,6 +12,9 @@ local node = setmetatable({}, { loud_walking.node = node +local math_abs = math.abs +local math_floor = math.floor + local cloud_i = 0.5 local glass = {"loud_walking:sky_scrith", "loud_walking:cloud_scrith", "loud_walking:transparent_scrith"} @@ -98,9 +101,9 @@ mushroom_stones[node["loud_walking:stone_with_algae"]] = true mushroom_stones[node["loud_walking:stone_with_lichen"]] = true local function connection(x, y, z) - local min_x = math.floor((x + 32) / csize.x) - local min_y = math.floor((y + 32) / csize.y) - local min_z = math.floor((z + 32) / csize.z) + local min_x = math_floor((x + 32) / csize.x) + local min_y = math_floor((y + 32) / csize.y) + local min_z = math_floor((z + 32) / csize.z) --local seed_noise = minetest.get_perlin({offset = 0, scale = 32768, --seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2, @@ -137,12 +140,12 @@ end local pod_size = {x=300, y=100, z=200} -local half_pod = {x=math.floor(pod_size.x / 2), y=math.floor(pod_size.y / 2), z=math.floor(pod_size.z / 2)} +local half_pod = {x=math_floor(pod_size.x / 2), y=math_floor(pod_size.y / 2), z=math_floor(pod_size.z / 2)} local bridge_size = 50 local fcsize = {x=pod_size.x + bridge_size, y=pod_size.y + bridge_size, z=pod_size.z + bridge_size} local bevel = half_pod.y local room_size = 20 -local control_off = math.floor(room_size / 4) +local control_off = math_floor(room_size / 4) local biome_look = {} local cave_look = {} @@ -157,8 +160,8 @@ local function place_schematic(pos, schem, center) end if center then - pos.x = pos.x - math.floor(schem.size.x / 2) - pos.z = pos.z - math.floor(schem.size.z / 2) + pos.x = pos.x - math_floor(schem.size.x / 2) + pos.z = pos.z - math_floor(schem.size.z / 2) end for z1 = 0, schem.size.z - 1 do @@ -201,9 +204,9 @@ end local function get_biome(x, y, z) - local px = math.floor(x / fcsize.x) - local py = math.floor(y / fcsize.y) - local pz = math.floor(z / fcsize.z) + local px = math_floor(x / fcsize.x) + local py = math_floor(y / fcsize.y) + local pz = math_floor(z / fcsize.z) if px % 10 == 6 and pz % 10 == 6 then return "control" @@ -233,62 +236,32 @@ local function get_biome(x, y, z) end -local function get_height_old(dx, dz, terrain_scale, ocean, index) - local terr - local half = {x=math.floor(csize.x / 2 + 0.5), y=math.floor(csize.y / 2 + 0.5), z=math.floor(csize.z / 2 + 0.5)} - terrain_scale = terrain_scale or 1 - - --if index == true then - -- terr = minetest.get_perlin(terrain_noise):get2d({x=dx, y=dz}) - -- -- Still need csize here... - -- dx = (dx + 32) % 80 - -- dz = (dz + 32) % 80 - if not index then - index = dz * csize.x + dx + 1 - terr = terrain[index] - else - terr = terrain[index] - end - - terr = math.floor(terr * terrain_scale + 0.5) - - local d = half.y - 2 - math.abs(math.abs(dx - (half.x - 0.5)) - math.abs(dz - (half.z - 0.5))) - if math.abs(terr) > d then - if terr > 0 then - terr = math.floor(d + 0.5) - elseif not ocean then - terr = math.floor(0.5 - d) - end - end - - return terr -end - local function get_height(fdx, fdz, y, index, heights, terrain_scale, ocean) - local py = math.floor(y / fcsize.y) + local py = math_floor(y / fcsize.y) if not terrain_scale then return end if not heights[py] then + print('new height') heights[py] = minetest.get_perlin_map(terrain_noise, csize):get2dMap_flat({x=minp.x, y=minp.z}) end - local terr = math.floor(heights[py][index] * terrain_scale + 0.5) + local terr = math_floor(heights[py][index] * terrain_scale + 0.5) - local d = - math.abs(math.abs(fdx - (half_pod.x - 0.5)) - math.abs(fdz - (half_pod.z - 0.5))) - if math.abs(fdx - half_pod.x) > math.abs(fdz - half_pod.z) then + local d = - math_abs(math_abs(fdx - (half_pod.x - 0.5)) - math_abs(fdz - (half_pod.z - 0.5))) + if math_abs(fdx - half_pod.x) > math_abs(fdz - half_pod.z) then d = d + half_pod.x - 2 else d = d + half_pod.z - 2 end - if math.abs(terr) > d then + if math_abs(terr) > d then if terr > 0 then - terr = math.floor(d + 0.5) + terr = math_floor(d + 0.5) elseif not ocean then - terr = math.floor(0.5 - d) + terr = math_floor(0.5 - d) end end @@ -297,6 +270,8 @@ end local function generate(p_minp, p_maxp, seed) + --local ta0, ta1, ta2 = 0, 0, 0 + local t0 = os.clock() minp, maxp = p_minp, p_maxp vm, emin, emax = minetest.get_mapgen_object("voxelmanip") vm:get_data(data) @@ -312,43 +287,58 @@ local function generate(p_minp, p_maxp, seed) cloud = minetest.get_perlin_map(cloud_noise, csize):get2dMap_flat(minp) cave = minetest.get_perlin_map(cave_noise, csize):get3dMap_flat(minp) + local t1 = os.clock() + local index = 0 local index3d = 0 + local last_biome, last_px, last_py, last_pz, node_top, node_filler, node_water_top, node_water, depth_top, depth_water_top, depth_filler, node_stone, ocean, swamp, beach, dunes, height + local biome, cave_lining for z = minp.z, maxp.z do local dz = z - minp.z local fdz = z % fcsize.z + local pz = math_floor(z / fcsize.z) for x = minp.x, maxp.x do index = index + 1 local dx = x - minp.x local fdx = x % fcsize.x + local px = math_floor(x / fcsize.x) local in_cave = false index3d = dz * csize.y * csize.x + dx + 1 local ivm = a:index(x, minp.y, z) local cave_height = 0 + last_py = nil for y = minp.y, maxp.y do local dy = y - minp.y local fdy = y % fcsize.y - local biome, cave_lining = get_biome(x, y, z) - local node_top = biomes[biome].node_top or "default:dirt_with_grass" - local node_filler = biomes[biome].node_filler or "default:dirt" - local node_water_top = biomes[biome].node_water_top or "default:water_source" - local node_water = biomes[biome].node_water or "default:water_source" - local depth_top = biomes[biome].depth_top or 1 - local depth_water_top = biomes[biome].node_water_top or 1 - local depth_filler = biomes[biome].depth_filler or 1 - local node_stone = biomes[biome].node_stone or "default:stone" - local ocean = string.find(biome, "ocean") and true or false - local swamp = string.find(biome, "swamp") and true or false - local beach = string.find(biome, "beach") and true or false - local dunes = string.find(biome, "dunes") and true or false - local height = half_pod.y - 5 - if not (biome == "underground" or biome == 'control') then - height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean) + local py = math_floor(y / fcsize.y) + if py ~= last_py or px ~= last_px or pz ~= last_pz then + biome, cave_lining = get_biome(x, y, z) + end + if biome ~= last_biome then + node_top = biomes[biome].node_top or "default:dirt_with_grass" + node_filler = biomes[biome].node_filler or "default:dirt" + node_water_top = biomes[biome].node_water_top or "default:water_source" + node_water = biomes[biome].node_water or "default:water_source" + depth_top = biomes[biome].depth_top or 1 + depth_water_top = biomes[biome].node_water_top or 1 + depth_filler = biomes[biome].depth_filler or 1 + node_stone = biomes[biome].node_stone or "default:stone" + ocean = string.find(biome, "ocean") and true or false + swamp = string.find(biome, "swamp") and true or false + beach = string.find(biome, "beach") and true or false + dunes = string.find(biome, "dunes") and true or false + end + + if py ~= last_py then + height = half_pod.y - 5 + if not (biome == "underground" or biome == 'control') then + height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean) + end end if not (data[ivm] == node['air'] or data[ivm] == node['ignore']) then -- nop - elseif biome == "control" and math.abs(fdx - half_pod.x) < 3 and math.abs(fdz - half_pod.z) < 3 then + elseif biome == "control" and math_abs(fdx - half_pod.x) < 3 and math_abs(fdz - half_pod.z) < 3 then data[ivm] = node["loud_walking:air_ladder"] elseif fdz >= pod_size.z or fdx >= pod_size.x or fdy >= pod_size.y then if (fdy == half_pod.y and fdx == half_pod.x) or (fdy == half_pod.y and fdz == half_pod.z) then @@ -361,7 +351,7 @@ local function generate(p_minp, p_maxp, seed) lightmap[ivm] = 0 in_cave = false elseif (fdx == 0 or fdx == pod_size.x - 1) or (fdz == 0 or fdz == pod_size.z - 1) or (fdy == 0 or fdy == pod_size.y - 1) or math.min(fdx, pod_size.x - fdx) + math.min(fdy, pod_size.y - fdy) + math.min(fdz, pod_size.z - fdz) < bevel + 1 then - if math.abs(fdy - half_pod.y - 2) < 2 and (fdz == half_pod.z or fdx == half_pod.x) then + if math_abs(fdy - half_pod.y - 2) < 2 and (fdz == half_pod.z or fdx == half_pod.x) then data[ivm] = node["air"] else if biome == "control" then @@ -382,9 +372,9 @@ local function generate(p_minp, p_maxp, seed) data[ivm] = node['loud_walking:scrith'] elseif biome == "control" and fdy % 5 == 0 then data[ivm] = node["loud_walking:control_floor"] - elseif biome == "control" and (math.abs(fdx - half_pod.x) < 3 or math.abs(fdz - half_pod.z) < 3) then + elseif biome == "control" and (math_abs(fdx - half_pod.x) < 3 or math_abs(fdz - half_pod.z) < 3) then data[ivm] = node["air"] - elseif biome == "control" and ((math.abs(fdx - half_pod.x) % room_size == 3 and (math.abs(fdz - half_pod.z) - 12) % room_size > 3) or (math.abs(fdz - half_pod.z) % room_size == 3 and (math.abs(fdx - half_pod.x) - 12) % room_size > 3)) then + elseif biome == "control" and ((math_abs(fdx - half_pod.x) % room_size == 3 and (math_abs(fdz - half_pod.z) - 12) % room_size > 3) or (math_abs(fdz - half_pod.z) % room_size == 3 and (math_abs(fdx - half_pod.x) - 12) % room_size > 3)) then data[ivm] = node["loud_walking:control_wall"] elseif biome == "control" then -- @@ -474,26 +464,41 @@ local function generate(p_minp, p_maxp, seed) cave_height = 0 end + last_biome = biome + last_py = py + ivm = ivm + a.ystride index3d = index3d + csize.x end + last_px = px end + last_pz = pz end + local t2 = os.clock() + local index = 0 for z = minp.z, maxp.z do local fdz = z % fcsize.z + local pz = math_floor(z / fcsize.z) for x = minp.x, maxp.x do local fdx = x % fcsize.x + local px = math_floor(x / fcsize.x) index = index + 1 + last_py = nil for y = minp.y, maxp.y do local fdy = y % fcsize.y + local py = math_floor(y / fcsize.y) if fdz % 5 == 0 and fdx % 5 == 0 then local fdy = y % fcsize.y local pod = fdz < pod_size.z and fdx < pod_size.x and fdy < pod_size.y - local biome, cave_lining = get_biome(x, y, z) + if py ~= last_py or px ~= last_px or pz ~= last_pz then + biome, cave_lining = get_biome(x, y, z) + end local ocean = string.find(biome, "ocean") and true or false - local height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean) + if py ~= last_py then + height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean) + end if biome ~= 'control' and pod and fdy == height + ground and biomes[biome].special_tree_prob and math.random(biomes[biome].special_tree_prob) == 1 then local rx = x + math.random(5) - 1 @@ -521,6 +526,8 @@ local function generate(p_minp, p_maxp, seed) end end + local t3 = os.clock() + if false and pod and biome == "control" then for dy = 0, 15 do for dz = 0, 1 do @@ -561,7 +568,7 @@ local function generate(p_minp, p_maxp, seed) end end elseif sr == 4 then - if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math.abs(z - 10) > 3) or ((z == 1 or z == 19) and math.abs(x - 10) > 3)) then + if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math_abs(z - 10) > 3) or ((z == 1 or z == 19) and math_abs(x - 10) > 3)) then data[ivm + 3 * a.ystride] = node["loud_walking:controls"] end end @@ -574,6 +581,8 @@ local function generate(p_minp, p_maxp, seed) end end + local t4 = os.clock() + vm:set_data(data) minetest.generate_ores(vm, minp, maxp) --vm:set_param2_data(p2data) @@ -581,6 +590,10 @@ local function generate(p_minp, p_maxp, seed) vm:update_liquids() vm:calc_lighting(minp, maxp, false) vm:write_to_map() + + local t5 = os.clock() + print(' times: '..(t1 - t0)..', '..(t2 - t1)..', '..(t3 - t2)..', '..(t5 - t4)..' = '..(t5 - t0)) + --print(' also: '..ta1..', '..ta2) end @@ -593,7 +606,7 @@ local function generate_old(p_minp, p_maxp, seed) csize = vector.add(vector.subtract(maxp, minp), 1) -- Deal with memory issues. This, of course, is supposed to be automatic. - local mem = math.floor(collectgarbage("count")/1024) + local mem = math_floor(collectgarbage("count")/1024) if mem > 300 then print("Loud Walking: Manually collecting garbage...") collectgarbage("collect") @@ -606,8 +619,8 @@ local function generate_old(p_minp, p_maxp, seed) math.randomseed(seed_noise:get2d({x=minp.x, y=minp.z})) -- Keep this first after seeding! - local px = math.floor((minp.x + 32) / csize.x) - local pz = math.floor((minp.z + 32) / csize.z) + local px = math_floor((minp.x + 32) / csize.x) + local pz = math_floor((minp.z + 32) / csize.z) local biome = get_biome(px, pz) local cave_lining = cave_stones[math.random(#cave_stones)] if math.random(3) == 1 then @@ -629,7 +642,7 @@ local function generate_old(p_minp, p_maxp, seed) local swamp = string.find(biome, "swamp") and true or false local beach = string.find(biome, "beach") and true or false local dunes = string.find(biome, "dunes") and true or false - local half = {x=math.floor(csize.x / 2 + 0.5), y=math.floor(csize.y / 2 + 0.5), z=math.floor(csize.z / 2 + 0.5)} + local half = {x=math_floor(csize.x / 2 + 0.5), y=math_floor(csize.y / 2 + 0.5), z=math_floor(csize.z / 2 + 0.5)} local ground = half.y beach = beach or dunes @@ -666,14 +679,14 @@ local function generate_old(p_minp, p_maxp, seed) for y = minp.y, maxp.y do local dy = y - minp.y if pod then - if biome == "control" and math.abs(dx - half.x) < 3 and math.abs(dz - half.z) < 3 then + if biome == "control" and math_abs(dx - half.x) < 3 and math_abs(dz - half.z) < 3 then data[ivm] = node["loud_walking:air_ladder"] elseif math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) < bevel then data[ivm] = node["air"] lightmap[ivm] = 0 in_cave = false elseif (dx == 0 or dx == csize.x - 1) or (dz == 0 or dz == csize.z - 1) or (dy == 0 or dy == csize.y - 1) or math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) < bevel + 1 then - if math.abs(dy - half.y - 2) < 2 and (dz == half.z or dx == half.x) then + if math_abs(dy - half.y - 2) < 2 and (dz == half.z or dx == half.x) then data[ivm] = node["air"] else if biome == "control" then @@ -693,9 +706,9 @@ local function generate_old(p_minp, p_maxp, seed) in_cave = false elseif biome == "control" and dy % 5 == 0 then data[ivm] = node["loud_walking:control_floor"] - elseif biome == "control" and (math.abs(dx - half.x) < 3 or math.abs(dz - half.z) < 3) then + elseif biome == "control" and (math_abs(dx - half.x) < 3 or math_abs(dz - half.z) < 3) then data[ivm] = node["air"] - elseif biome == "control" and ((math.abs(dx - half.x) % 20 == 3 and (math.abs(dz - half.z) - 12) % 20 > 3) or (math.abs(dz - half.z) % 20 == 3 and (math.abs(dx - half.x) - 12) % 20 > 3)) then + elseif biome == "control" and ((math_abs(dx - half.x) % 20 == 3 and (math_abs(dz - half.z) - 12) % 20 > 3) or (math_abs(dz - half.z) % 20 == 3 and (math_abs(dx - half.x) - 12) % 20 > 3)) then data[ivm] = node["loud_walking:control_wall"] elseif biome == "control" then -- @@ -780,7 +793,7 @@ local function generate_old(p_minp, p_maxp, seed) lightmap[ivm] = 0 in_cave = false end - elseif biome == "control" and math.abs(dx - half.x) < 3 and math.abs(dz - half.z) < 3 then + elseif biome == "control" and math_abs(dx - half.x) < 3 and math_abs(dz - half.z) < 3 then data[ivm] = node["loud_walking:air_ladder"] elseif connection and dy == half.y and ((dx == half.x and connection % 4 == 0) or (dz == half.z and connection % 2 == 1)) then data[ivm] = node["loud_walking:scrith"] @@ -863,7 +876,7 @@ local function generate_old(p_minp, p_maxp, seed) end end elseif sr == 4 then - if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math.abs(z - 10) > 3) or ((z == 1 or z == 19) and math.abs(x - 10) > 3)) then + if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math_abs(z - 10) > 3) or ((z == 1 or z == 19) and math_abs(x - 10) > 3)) then data[ivm + 3 * a.ystride] = node["loud_walking:controls"] end end