mg = {} local ENABLE_SNOW = false local DMAX = 60 local AREA_SIZE = 256 dofile(minetest.get_modpath(minetest.get_current_modname()).."/nodes.lua") c_air = minetest.get_content_id("air") c_grass = minetest.get_content_id("default:dirt_with_grass") c_dry_grass = minetest.get_content_id("mg:dirt_with_dry_grass") c_dirt_snow = minetest.get_content_id("default:dirt_with_snow") c_snow = minetest.get_content_id("default:snow") c_sapling = minetest.get_content_id("default:sapling") c_tree = minetest.get_content_id("default:tree") c_leaves = minetest.get_content_id("default:leaves") c_junglesapling = minetest.get_content_id("default:junglesapling") c_jungletree = minetest.get_content_id("default:jungletree") c_jungleleaves = minetest.get_content_id("default:jungleleaves") c_savannasapling = minetest.get_content_id("mg:savannasapling") c_savannatree = minetest.get_content_id("mg:savannatree") c_savannaleaves = minetest.get_content_id("mg:savannaleaves") c_pinesapling = minetest.get_content_id("mg:pinesapling") c_pinetree = minetest.get_content_id("mg:pinetree") c_pineleaves = minetest.get_content_id("mg:pineleaves") c_dirt = minetest.get_content_id("default:dirt") c_stone = minetest.get_content_id("default:stone") c_water = minetest.get_content_id("default:water_source") c_ice = minetest.get_content_id("default:ice") c_sand = minetest.get_content_id("default:sand") c_sandstone = minetest.get_content_id("default:sandstone") c_desert_sand = minetest.get_content_id("default:desert_sand") c_desert_stone = minetest.get_content_id("default:desert_stone") c_snowblock = minetest.get_content_id("default:snowblock") c_cactus = minetest.get_content_id("default:cactus") c_grass_1 = minetest.get_content_id("default:grass_1") c_grass_2 = minetest.get_content_id("default:grass_2") c_grass_3 = minetest.get_content_id("default:grass_3") c_grass_4 = minetest.get_content_id("default:grass_4") c_grass_5 = minetest.get_content_id("default:grass_5") c_grasses = {c_grass_1, c_grass_2, c_grass_3, c_grass_4, c_grass_5} c_jungle_grass = minetest.get_content_id("default:junglegrass") c_dry_shrub = minetest.get_content_id("default:dry_shrub") c_papyrus = minetest.get_content_id("default:papyrus") minetest.register_on_mapgen_init(function(mgparams) minetest.set_mapgen_params({mgname="singlenode", flags="nolight"}) end) local cache = {} local function cliff(x, n) return 0.2*x*x - x + n*x - n*n*x*x - 0.01 * math.abs(x*x*x) + math.abs(x)*100*n*n*n*n end local function get_base_surface_at_point(x, z, vn, vh, ni, noise1, noise2, noise3, noise4) local index = 65536*x+z if cache[index] ~= nil then return cache[index] end cache[index] = 25*noise1[ni]+noise2[ni]*noise3[ni]/3 if noise4[ni] > 0.8 then cache[index] = cliff(cache[index], noise4[ni]-0.8) end if vn<40 then cache[index] = vh elseif vn<200 then cache[index] = (vh*(200-vn) + cache[index]*(vn-40))/160 end return cache[index] end local function surface_at_point(x, z, ...) return get_base_surface_at_point(x, z, unpack({...})) end local SMOOTHED = AREA_SIZE+2*DMAX local HSMOOTHED = AREA_SIZE+DMAX local INSIDE = AREA_SIZE-DMAX local function smooth(x, z, ...) local s=0 local w=0 for xi=-DMAX, DMAX do for zi=-DMAX, DMAX do local d2=xi*xi+zi*zi if d2=yy then add_leaves(data, a:index(xx, yy, zz), c_savannaleaves) end end end end end function add_savannabush(data, a, x, y, z, minp, maxp, pr) local bh = pr:next(1, 2) local bw = pr:next(2, 4) for xx=math.max(minp.x, x-bw), math.min(maxp.x, x+bw) do for zz=math.max(minp.z, z-bw), math.min(maxp.z, z+bw) do for yy=math.max(minp.y, y-bh), math.min(maxp.y, y+bh) do if pr:next(1, 100) < 95 and math.abs(xx-x) < pr:next(bh, bh+2)-math.abs(y-yy) and math.abs(zz-z) < pr:next(bh, bh+2)-math.abs(y-yy) then add_leaves(data, a:index(xx, yy, zz), c_savannaleaves) for yyy=math.max(minp.y, yy-2), yy do add_leaves(data, a:index(xx, yyy, zz), c_savannaleaves) end end end end end if x<=maxp.x and x>=minp.x and y<=maxp.y and y>=minp.y and z<=maxp.z and z>=minp.z then local vi = a:index(x, y, z) data[vi] = c_savannatree end end function add_pinetree(data, a, x, y, z, minp, maxp, pr, snow) if snow == nil then snow = c_snow end local th = pr:next(9, 13) for yy=math.max(minp.y, y), math.min(maxp.y, y+th) do local vi = a:index(x, yy, z) data[vi] = c_pinetree end local maxy = y+th for xx=math.max(minp.x, x-3), math.min(maxp.x, x+3) do for yy=math.max(minp.y, maxy-1), math.min(maxp.y, maxy-1) do for zz=math.max(minp.z, z-3), math.min(maxp.z, z+3) do if pr:next(1, 100) < 80 then add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow) add_leaves(data, a:index(xx, yy+1, zz), snow) end end end end for xx=math.max(minp.x, x-2), math.min(maxp.x, x+2) do for yy=math.max(minp.y, maxy), math.min(maxp.y, maxy) do for zz=math.max(minp.z, z-2), math.min(maxp.z, z+2) do if pr:next(1, 100) < 85 then add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow) add_leaves(data, a:index(xx, yy+1, zz), snow) end end end end for xx=math.max(minp.x, x-1), math.min(maxp.x, x+1) do for yy=math.max(minp.y, maxy+1), math.min(maxp.y, maxy+1) do for zz=math.max(minp.z, z-1), math.min(maxp.z, z+1) do if pr:next(1, 100) < 90 then add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow) add_leaves(data, a:index(xx, yy+1, zz), snow) end end end end if maxy+1<=maxp.y and maxy+1>=minp.y then add_leaves(data, a:index(x, maxy+1, z), c_pineleaves, snow) add_leaves(data, a:index(x, maxy+2, z), snow) end local my = 0 for i=1,20 do local xi = pr:next(x-3, x+2) local yy = pr:next(maxy-6, maxy-5) local zi = pr:next(z-3, z+2) if yy > my then my = yy end for xx=math.max(minp.x, xi), math.min(maxp.x, xi+1) do for zz=math.max(minp.z, zi), math.min(maxp.z, zi+1) do if minp.y<=yy and maxp.y>=yy then add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow) add_leaves(data, a:index(xx, yy+1, zz), snow) end end end end for xx=math.max(minp.x, x-2), math.min(maxp.x, x+2) do for yy=math.max(minp.y, my+1), math.min(maxp.y, my+1) do for zz=math.max(minp.z, z-2), math.min(maxp.z, z+2) do if pr:next(1, 100) < 85 then add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow) add_leaves(data, a:index(xx, yy+1, zz), snow) end end end end for xx=math.max(minp.x, x-1), math.min(maxp.x, x+1) do for yy=math.max(minp.y, my+2), math.min(maxp.y, my+2) do for zz=math.max(minp.z, z-1), math.min(maxp.z, z+1) do if pr:next(1, 100) < 90 then add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow) add_leaves(data, a:index(xx, yy+1, zz), snow) end end end end end dofile(minetest.get_modpath(minetest.get_current_modname()).."/we.lua") dofile(minetest.get_modpath(minetest.get_current_modname()).."/rotate.lua") dofile(minetest.get_modpath(minetest.get_current_modname()).."/buildings.lua") dofile(minetest.get_modpath(minetest.get_current_modname()).."/villages.lua") dofile(minetest.get_modpath(minetest.get_current_modname()).."/ores.lua") function get_biome_table(minp, humidity, temperature, range) if range == nil then range = 1 end local l = {} for xi = -range, range do for zi = -range, range do local mnp, mxp = {x=minp.x+xi*80,z=minp.z+zi*80}, {x=minp.x+xi*80+80,z=minp.z+zi*80+80} local pr = PseudoRandom(get_bseed(mnp)) local bxp, bzp = pr:next(mnp.x, mxp.x), pr:next(mnp.z, mxp.z) local h, t = humidity:get2d({x=bxp, y=bzp}), temperature:get2d({x=bxp, y=bzp}) l[#l+1] = {x=bxp, z=bzp, h=h, t=t} end end return l end local function get_distance(x1, x2, z1, z2) return (x1-x2)*(x1-x2)+(z1-z2)*(z1-z2) end function get_nearest_biome(biome_table, x, z) local m = math.huge local k = 0 for key, bdef in ipairs(biome_table) do local dist = get_distance(bdef.x, x, bdef.z, z) if dist0.4 then if biome_humidity<-0.4 then top = c_desert_sand top_layer = c_desert_sand second_layer = c_desert_stone elseif biome_humidity<0.4 then top = c_dry_grass top_layer = c_dirt second_layer = c_stone else top = c_grass top_layer = c_dirt second_layer = c_stone end elseif biome_temperature<-0.4 then above_top = c_snow top = c_dirt_snow top_layer = c_dirt second_layer = c_stone else top = c_grass top_layer = c_dirt second_layer = c_stone end end if y>=100 then above_top = c_air top = c_snow top_layer = c_snowblock end if y<0 then above_top = c_air end if y<=maxp.y and y>=minp.y then local vi = a:index(x, y, z) if y >= 0 then data[vi] = top else data[vi] = top_layer end end local add_above_top = true for id, tree in ipairs(mg.registered_trees) do if tree.min_humidity <= humidity and humidity <= tree.max_humidity and tree.min_temperature <= temperature and temperature <= tree.max_temperature and tree.min_biome_humidity <= biome_humidity and biome_humidity <= tree.max_biome_humidity and tree.min_biome_temperature <= biome_temperature and biome_temperature <= tree.max_biome_temperature and tree.min_height <= y+1 and y+1 <= tree.max_height and ((not tree.grows_on) or tree.grows_on == top) and pr:next(1, tree.chance) == 1 then if inside_village(x, z, vx, vz, vs, village_noise) and not tree.can_be_in_village then villages_to_grow[#villages_to_grow+1] = {x=x, y=y+1, z=z, id=id} else tree.grow(data, a, x, y+1, z, minp, maxp, pr) end add_above_top = false break end end if add_above_top and y+1<=maxp.y and y+1>=minp.y then local vi = a:index(x, y+1, z) data[vi] = above_top end if y<0 and minp.y<=0 and maxp.y>y then for yy = math.max(y+1, minp.y), math.min(0, maxp.y) do local vi = a:index(x, yy, z) data[vi] = c_water end if maxp.y>=0 then data[a:index(x, 0, z)] = liquid_top end end local tl = math.floor((noise_top_layer[ni]+2.5)*2) if y-tl-1<=maxp.y and y-1>=minp.y then for yy = math.max(y-tl-1, minp.y), math.min(y-1, maxp.y) do local vi = a:index(x, yy, z) data[vi] = top_layer end end local sl = math.floor((noise_second_layer[ni]+5)*3) if y-sl-1<=maxp.y and y-tl-2>=minp.y then for yy = math.max(y-sl-1, minp.y), math.min(y-tl-2, maxp.y) do local vi = a:index(x, yy, z) data[vi] = second_layer end end if y-sl-2>=minp.y then for yy = minp.y, math.min(y-sl-2, maxp.y) do local vi = a:index(x, yy, z) data[vi] = c_stone end end end end local va = VoxelArea:new{MinEdge=minp, MaxEdge=maxp} --[[ local og_start = os.clock() for _, ore_sheet in ipairs(mg.registered_ore_sheets) do local sidelen = maxp.x - minp.x + 1 local np = copytable(ore_sheet.noise_params) np.seed = np.seed + minp.y local pm = minetest.get_perlin_map(np, {x=sidelen, y=sidelen, z=1}) local map = pm:get2dMap_flat({x = minp.x, y = minp.z}) local ni = 0 local trh = ore_sheet.threshhold local wherein = minetest.get_content_id(ore_sheet.wherein) local ore = minetest.get_content_id(ore_sheet.name) local hmin = ore_sheet.height_min local hmax = ore_sheet.height_max local tmin = ore_sheet.tmin local tmax = ore_sheet.tmax for z = minp.z, maxp.z do for x = minp.x, maxp.x do ni = ni+1 local noise = map[ni] if noise > trh then local thickness = pr:next(tmin, tmax) local y0 = math.floor(minp.y + (noise-trh)*4) for y = math.max(y0, hmin), math.min(y0+thickness-1, hmax) do local vi = a:index(x, y, z) if data[vi] == wherein or wherein == c_ignore then data[vi] = ore end end end end end end local og_end = os.clock() --print("Ore gen: " .. tostring(og_end - og_start)) ]] for _, ore in ipairs(mg.registered_ores) do local o_start = os.clock() generate_vein(minetest.get_content_id(ore.name), minetest.get_content_id(ore.wherein), minp, maxp, ore.seeddiff, ore, data, a, va) local o_end = os.clock() --print("Ore "..ore.name.. " gen: "..tostring(o_end-o_start)) end local to_add = generate_village(vx, vz, vs, vh, minp, maxp, data, a, village_noise, villages_to_grow) vm:set_data(data) vm:calc_lighting( {x=minp.x-16, y=minp.y, z=minp.z-16}, {x=maxp.x+16, y=maxp.y, z=maxp.z+16} ) local ul = os.clock() vm:update_liquids() local eul = os.clock() --print("Update liquids: "..tostring(eul-ul)) vm:write_to_map(data) quests.treasure.on_generated(minp,maxp,emin,emax,vm) local meta for _, n in pairs(to_add) do if n.node.name ~= "air" then minetest.set_node(n.pos, n.node) if n.meta ~= nil then meta = minetest.get_meta(n.pos) meta:from_table(n.meta) if n.node.name == "default:chest" or n.node.name == "default:npc_chest" then local inv = meta:get_inventory() local items = inv:get_list("main") for i=1, inv:get_size("main") do inv:set_stack("main", i, ItemStack("")) end local numitems = pr:next(3, 20) for i=1,numitems do local ii = pr:next(1, #items) local prob = items[ii]:get_count() % 2 ^ 8 local stacksz = math.floor(items[ii]:get_count() / 2 ^ 8) if pr:next(0, prob) == 0 and stacksz>0 then stk = ItemStack({name=items[ii]:get_name(), count=pr:next(1, stacksz), wear=items[ii]:get_count(), metadata=items[ii]:get_metadata()}) local ind = pr:next(1, inv:get_size("main")) while not inv:get_stack("main",ind):is_empty() do ind = pr:next(1, inv:get_size("main")) end inv:set_stack("main", ind, stk) end end -- insert some experience into every chest, this gives incentive to explore villages local cexp = math.random(0,25) local expitem = experience.exp_to_items(cexp) for _,e in pairs(expitem) do inv:add_item("main",e) end end end if n.node.name == "mobs:spawner" then meta = minetest.get_meta(n.pos) meta:set_string("entity",n.mob) meta:set_int("active_objects",2) meta:set_int("active_objects_wider",7) meta:set_string("infotext",n.mob) end end end local b_end = os.clock() --print((tostring(b_end - b_start))) end minetest.register_on_generated(function(minp, maxp, seed) local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") mg_generate(minp, maxp, emin, emax, vm) end) function mg_regenerate(pos, name) local minp = {x = 80*math.floor((pos.x+32)/80)-32, y = 80*math.floor((pos.y+32)/80)-32, z = 80*math.floor((pos.z+32)/80)-32} local maxp = {x = minp.x+79, y = minp.y+79, z = minp.z+79} local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(minp, maxp) local data = {} for i = 1, (maxp.x-minp.x+1)*(maxp.y-minp.y+1)*(maxp.z-minp.z+1) do data[i] = c_air end vm:set_data(data) vm:write_to_map() mg_generate(minp, maxp, emin, emax, vm) if name ~= nil then minetest.chat_send_player(name, "Regenerating done, fixing lighting. This may take a while...") end -- Fix lighting local nodes = minetest.find_nodes_in_area(minp, maxp, "air") local nnodes = #nodes local p = math.floor(nnodes/5) local dig_node = minetest.dig_node for _, pos in ipairs(nodes) do dig_node(pos) if _%p == 0 then if name ~= nil then minetest.chat_send_player(name, math.floor(_/nnodes*100).."%") end end end if name ~= nil then minetest.chat_send_player(name, "Done") end end minetest.register_chatcommand("mg_regenerate", { privs = {server = true}, func = function(name, param) local player = minetest.get_player_by_name(name) if player then local pos = player:getpos() mg_regenerate(pos, name) end end, }) mg.registered_ores = {} function mg.register_ore(oredef) if oredef.wherein == nil then oredef.wherein = "ignore" end if DEBUG then oredef.wherein = "ignore" oredef.maxheight = 31000 end mg.registered_ores[#mg.registered_ores+1] = oredef end mg.registered_ore_sheets = {} function mg.register_ore_sheet(oredef) if oredef.wherein == nil then oredef.wherein = "ignore" end if DEBUG then oredef.wherein = "ignore" oredef.height_max = 31000 end mg.registered_ore_sheets[#mg.registered_ore_sheets+1] = oredef end mg.registered_trees = {} function mg.register_tree(treedef) if treedef.min_humidity == nil then treedef.min_humidity = -2 end if treedef.max_humidity == nil then treedef.max_humidity = 2 end if treedef.min_biome_humidity == nil then treedef.min_biome_humidity = -2 end if treedef.max_biome_humidity == nil then treedef.max_biome_humidity = 2 end if treedef.min_temperature == nil then treedef.min_temperature = -2 end if treedef.max_temperature == nil then treedef.max_temperature = 2 end if treedef.min_biome_temperature == nil then treedef.min_biome_temperature = -2 end if treedef.max_biome_temperature == nil then treedef.max_biome_temperature = 2 end mg.registered_trees[#mg.registered_trees+1] = treedef end dofile(minetest.get_modpath(minetest.get_current_modname()).."/oredesc.lua") dofile(minetest.get_modpath(minetest.get_current_modname()).."/trees.lua") if ENABLE_SNOW then dofile(minetest.get_modpath(minetest.get_current_modname()).."/snow.lua") end