559 lines
22 KiB
Lua
559 lines
22 KiB
Lua
-- Mapgen Valleys 2.3c
|
|
print("*** using 2.3c")
|
|
|
|
|
|
-- Read the noise parameters from the actual mapgen.
|
|
local function getCppSettingNoise(name, default)
|
|
local noise
|
|
local n = minetest.setting_get(name)
|
|
|
|
if n then
|
|
local parse = {spread = {}}
|
|
local n1, n2, n3, n4, n5, n6, n7, n8, n9
|
|
|
|
n1, n2, n3, n4, n5, n6, n7, n8, n9 = string.match(n, '([%d%.%-]+), ([%d%.%-]+), %(([%d%.%-]+), ([%d%.%-]+), ([%d%.%-]+)%), ([%d%.%-]+), ([%d%.%-]+), ([%d%.%-]+), ([%d%.%-]+)')
|
|
if n9 then
|
|
noise = {offset = tonumber(n1), scale = tonumber(n2), seed = tonumber(n6), spread = {x = tonumber(n3), y = tonumber(n4), z = tonumber(n5)}, octaves = tonumber(n7), persist = tonumber(n8), lacunarity = tonumber(n9)}
|
|
end
|
|
end
|
|
|
|
-- Use the default otherwise.
|
|
if not noise then
|
|
noise = default
|
|
end
|
|
|
|
return noise
|
|
end
|
|
|
|
|
|
-- Define perlin noises used in this mapgen by default
|
|
vmg.noises = {}
|
|
|
|
-- Noise 2 : Valleys (River where around zero) 2D
|
|
vmg.noises[2] = getCppSettingNoise('mg_valleys_np_rivers', {offset = 0, scale = 1, seed = -6050, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.6, lacunarity = 2})
|
|
|
|
-- Noise 13 : Clayey dirt noise 2D
|
|
vmg.noises[13] = {offset = 0, scale = 1, seed = 2835, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4}
|
|
|
|
-- Noise 14 : Silty dirt noise 2D
|
|
vmg.noises[14] = {offset = 0, scale = 1, seed = 6674, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4}
|
|
|
|
-- Noise 15 : Sandy dirt noise 2D
|
|
vmg.noises[15] = {offset = 0, scale = 1, seed = 6940, spread = {x = 256, y = 256, z = 256}, octaves = 5, persist = 0.5, lacunarity = 4}
|
|
|
|
-- Noise 16 : Beaches 2D
|
|
vmg.noises[16] = {offset = 2, scale = 8, seed = 2349, spread = {x = 256, y = 256, z = 256}, octaves = 3, persist = 0.5, lacunarity = 2}
|
|
|
|
-- Noise 21 : Water plants 2D
|
|
vmg.noises[21] = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = 33, octaves = 3, persist = 0.7, lacunarity = 2.0}
|
|
|
|
-- function to get noisemaps
|
|
function vmg.noisemap(i, minp, chulens)
|
|
local obj = minetest.get_perlin_map(vmg.noises[i], chulens)
|
|
if minp.z then
|
|
return obj:get3dMap_flat(minp)
|
|
else
|
|
return obj:get2dMap_flat(minp)
|
|
end
|
|
end
|
|
|
|
-- If the noises are already defined in settings, use it instead of the noise parameters above.
|
|
for i, n in ipairs(vmg.noises) do
|
|
vmg.noises[i] = vmg.define("noise_" .. i, n)
|
|
end
|
|
|
|
-- List of functions to run at the end of the mapgen procedure, used especially by jungle tree roots
|
|
vmg.after_mapgen = {}
|
|
|
|
function vmg.register_after_mapgen(f, ...)
|
|
table.insert(vmg.after_mapgen, {f = f, ...})
|
|
end
|
|
|
|
function vmg.execute_after_mapgen()
|
|
for i, params in ipairs(vmg.after_mapgen) do
|
|
params.f(unpack(params))
|
|
end
|
|
vmg.after_mapgen = {}
|
|
end
|
|
|
|
local function getCppSettingNumeric(name, default)
|
|
local setting = minetest.setting_get(name)
|
|
|
|
if setting and tonumber(setting) then
|
|
setting = tonumber(setting)
|
|
else
|
|
setting = default
|
|
end
|
|
|
|
return setting
|
|
end
|
|
|
|
-- Mapgen time stats
|
|
local mapgen_times = {
|
|
preparation = {},
|
|
noises = {},
|
|
collecting = {},
|
|
writing = {},
|
|
total = {},
|
|
}
|
|
|
|
-- Define parameters
|
|
local river_size = vmg.define("river_size", 5) / 100
|
|
local do_cave_stuff = vmg.define("cave_stuff", false)
|
|
local dry_dirt_threshold = vmg.define("dry_dirt_threshold", 0.6)
|
|
|
|
local clay_threshold = vmg.define("clay_threshold", 1)
|
|
local silt_threshold = vmg.define("silt_threshold", 1)
|
|
local sand_threshold = vmg.define("sand_threshold", 0.75)
|
|
local dirt_threshold = vmg.define("dirt_threshold", 0.5)
|
|
local average_snow_level = vmg.define("average_snow_level", 100)
|
|
local altitude_chill = getCppSettingNumeric('mg_valleys_altitude_chill', 90)
|
|
local heat_multiplier = tonumber(getCppSettingNoise('mg_biome_np_heat', {offset=50}).offset) / 25
|
|
local snow_threshold = heat_multiplier * 0.5 ^ (average_snow_level / altitude_chill)
|
|
local water_level = getCppSettingNumeric('water_level', 1)
|
|
|
|
-- This table holds the content IDs. They aren't available until
|
|
-- the actual mapgen loop is run, but they can stay local to the
|
|
-- file rather than having to load them for every map chunk.
|
|
--
|
|
local node = {}
|
|
|
|
local soil_translate = {}
|
|
|
|
-- Register ores
|
|
-- We need more types of stone than just gray. Fortunately, there are
|
|
-- two available already. Sandstone forms in layers. Desert stone...
|
|
-- doesn't exist, but let's assume it's another sedementary rock
|
|
-- and place it similarly.
|
|
if vmg.define("stone_ores", true) then
|
|
minetest.register_ore({ore_type="sheet", ore="default:sandstone", wherein="default:stone", clust_num_ores=250, clust_scarcity=60, clust_size=10, y_min=-1000, y_max=31000, noise_threshhold=0.1, noise_params={offset=0, scale=1, spread={x=256, y=256, z=256}, seed=4130293965, octaves=5, persist=0.60}, random_factor=1.0})
|
|
minetest.register_ore({ore_type="sheet", ore="default:desert_stone", wherein="default:stone", clust_num_ores=250, clust_scarcity=60, clust_size=10, y_min=-1000, y_max=31000, noise_threshhold=0.1, noise_params={offset=0, scale=1, spread={x=256, y=256, z=256}, seed=163281090, octaves=5, persist=0.60}, random_factor=1.0})
|
|
end
|
|
|
|
|
|
---- Create a table of biome ids, so I can use the biomemap.
|
|
--if not vmg.biome_ids then
|
|
-- vmg.biome_ids = {}
|
|
-- for name, desc in pairs(minetest.registered_biomes) do
|
|
-- local i = minetest.get_biome_id(desc.name)
|
|
-- vmg.biome_ids[i] = desc.name
|
|
-- end
|
|
--end
|
|
|
|
|
|
local data = {}
|
|
|
|
|
|
-- THE MAPGEN FUNCTION
|
|
function vmg.generate(minp, maxp, seed)
|
|
if vmg.registered_on_first_mapgen then -- Run callbacks
|
|
for _, f in ipairs(vmg.registered_on_first_mapgen) do
|
|
f()
|
|
end
|
|
vmg.registered_on_first_mapgen = nil
|
|
vmg.register_on_first_mapgen = nil
|
|
end
|
|
|
|
-- minp and maxp strings, used by logs
|
|
local minps, maxps = minetest.pos_to_string(minp), minetest.pos_to_string(maxp)
|
|
if vmg.loglevel >= 2 then
|
|
print("[Valleys Mapgen] Preparing to generate map from " .. minps .. " to " .. maxps .. " ...")
|
|
elseif vmg.loglevel == 1 then
|
|
--print("[Valleys Mapgen] Generating map from " .. minps .. " to " .. maxps .. " ...")
|
|
end
|
|
-- start the timer
|
|
local t0 = os.clock()
|
|
|
|
-- Define content IDs
|
|
-- A content ID is a number that represents a node in the core of Minetest.
|
|
-- Every nodename has its ID.
|
|
-- The VoxelManipulator uses content IDs instead of nodenames.
|
|
|
|
if not node["stone"] then
|
|
node["stone"] = minetest.get_content_id("default:stone")
|
|
node["sandstone"] = minetest.get_content_id("default:sandstone")
|
|
node["desertstone"] = minetest.get_content_id("default:desert_stone")
|
|
node["dirt"] = minetest.get_content_id("default:dirt")
|
|
node["lawn"] = minetest.get_content_id("default:dirt_with_grass")
|
|
node["dry"] = minetest.get_content_id("default:dirt_with_dry_grass")
|
|
node["snow"] = minetest.get_content_id("default:dirt_with_snow")
|
|
node["dirt_clay"] = minetest.get_content_id("valleys_mapgen:dirt_clayey")
|
|
node["lawn_clay"] = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_grass")
|
|
node["dry_clay"] = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_dry_grass")
|
|
node["snow_clay"] = minetest.get_content_id("valleys_mapgen:dirt_clayey_with_snow")
|
|
node["dirt_silt"] = minetest.get_content_id("valleys_mapgen:dirt_silty")
|
|
node["lawn_silt"] = minetest.get_content_id("valleys_mapgen:dirt_silty_with_grass")
|
|
node["dry_silt"] = minetest.get_content_id("valleys_mapgen:dirt_silty_with_dry_grass")
|
|
node["snow_silt"] = minetest.get_content_id("valleys_mapgen:dirt_silty_with_snow")
|
|
node["dirt_sand"] = minetest.get_content_id("valleys_mapgen:dirt_sandy")
|
|
node["lawn_sand"] = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_grass")
|
|
node["dry_sand"] = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_dry_grass")
|
|
node["snow_sand"] = minetest.get_content_id("valleys_mapgen:dirt_sandy_with_snow")
|
|
node["desert_sand"] = minetest.get_content_id("default:desert_sand")
|
|
node["sand"] = minetest.get_content_id("default:sand")
|
|
node["gravel"] = minetest.get_content_id("default:gravel")
|
|
node["silt"] = minetest.get_content_id("valleys_mapgen:silt")
|
|
node["clay"] = minetest.get_content_id("valleys_mapgen:red_clay")
|
|
node["water"] = minetest.get_content_id("default:water_source")
|
|
node["riverwater"] = minetest.get_content_id("default:river_water_source")
|
|
node["lava"] = minetest.get_content_id("default:lava_source")
|
|
node["snow_layer"] = minetest.get_content_id("default:snow")
|
|
node["glowing_fungal_stone"] = minetest.get_content_id("valleys_mapgen:glowing_fungal_stone")
|
|
node["stalactite"] = minetest.get_content_id("valleys_mapgen:stalactite")
|
|
node["stalagmite"] = minetest.get_content_id("valleys_mapgen:stalagmite")
|
|
|
|
-- Mushrooms
|
|
node["huge_mushroom_cap"] = minetest.get_content_id("valleys_mapgen:huge_mushroom_cap")
|
|
node["giant_mushroom_cap"] = minetest.get_content_id("valleys_mapgen:giant_mushroom_cap")
|
|
node["giant_mushroom_stem"] = minetest.get_content_id("valleys_mapgen:giant_mushroom_stem")
|
|
node["mushroom_fertile_red"] = minetest.get_content_id("flowers:mushroom_fertile_red")
|
|
node["mushroom_fertile_brown"] = minetest.get_content_id("flowers:mushroom_fertile_brown")
|
|
|
|
-- Air and Ignore
|
|
node["air"] = minetest.get_content_id("air")
|
|
node["ignore"] = minetest.get_content_id("ignore")
|
|
|
|
-- This saves assigning a lot of variables during every loop,
|
|
-- most of which won't be used.
|
|
soil_translate["clay_over"] = { dirt = node["clay"], lawn = node["clay"], dry = node["clay"], snow = node["clay"], }
|
|
soil_translate["clay_under"] = { dirt = node["dirt_clay"], lawn = node["lawn_clay"], dry = node["dry_clay"], snow = node["snow_clay"], }
|
|
soil_translate["silt_over"] = { dirt = node["silt"], lawn = node["silt"], dry = node["silt"], snow = node["silt"], }
|
|
soil_translate["silt_under"] = { dirt = node["dirt_silt"], lawn = node["lawn_silt"], dry = node["dry_silt"], snow = node["snow_silt"], }
|
|
soil_translate["sand"] = { dirt = node["dirt_sand"], lawn = node["lawn_sand"], dry = node["dry_sand"], snow = node["snow_sand"], }
|
|
soil_translate["dirt"] = { dirt = node["dirt"], lawn = node["lawn"], dry = node["dry"], snow = node["snow"], }
|
|
end
|
|
|
|
-- The VoxelManipulator, a complicated but speedy method to set many nodes at the same time
|
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
|
vm:get_data(data) -- data is the original array of content IDs (solely or mostly air)
|
|
-- Be careful: emin ≠ minp and emax ≠ maxp !
|
|
-- The data array is not limited by minp and maxp. It exceeds it by 16 nodes in the 6 directions.
|
|
-- The real limits of data array are emin and emax.
|
|
-- The VoxelArea is used to convert a position into an index for the array.
|
|
local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local ystride = a.ystride -- Tip : the ystride of a VoxelArea is the number to add to the array index to get the index of the position above. It's faster because it avoids to completely recalculate the index.
|
|
|
|
local chulens = vector.add(vector.subtract(maxp, minp), 1) -- Size of the generated area, used by noisemaps
|
|
local chulens_sup = {x = chulens.x, y = chulens.y + 6, z = chulens.z} -- for the noise #6 that needs extra values
|
|
local minp2d = pos2d(minp)
|
|
|
|
-- The biomemap is a table of biome index numbers for each horizontal
|
|
-- location. It's created in the mapgen, and is right most of the time.
|
|
-- It's off in about 1% of cases, for various reasons.
|
|
-- Bear in mind that biomes can change from one voxel to the next.
|
|
--local biomemap = minetest.get_mapgen_object("biomemap")
|
|
local heightmap = minetest.get_mapgen_object("heightmap")
|
|
local heatmap = minetest.get_mapgen_object("heatmap")
|
|
local humiditymap = minetest.get_mapgen_object("humiditymap")
|
|
|
|
-- Mapgen preparation is now finished. Check the timer to know the elapsed time.
|
|
local t1 = os.clock()
|
|
if vmg.loglevel >= 2 then
|
|
print("[Valleys Mapgen] Mapgen preparation finished in " .. displaytime(t1-t0))
|
|
print("[Valleys Mapgen] Calculating noises ...")
|
|
end
|
|
|
|
-- Calculate the noise values
|
|
local n2 = vmg.noisemap(2, minp2d, chulens)
|
|
local n13 = vmg.noisemap(13, minp2d, chulens)
|
|
local n14 = vmg.noisemap(14, minp2d, chulens)
|
|
local n15 = vmg.noisemap(15, minp2d, chulens)
|
|
local n16 = vmg.noisemap(16, minp2d, chulens)
|
|
local n21 = vmg.noisemap(21, minp2d, chulens)
|
|
|
|
-- After noise calculation, check the timer
|
|
local t2 = os.clock()
|
|
if vmg.loglevel >= 2 then
|
|
print("[Valleys Mapgen] Noises calculation finished in " .. displaytime(t2-t1))
|
|
print("[Valleys Mapgen] Collecting data ...")
|
|
end
|
|
|
|
-- THE CORE OF THE MOD: THE MAPGEN ALGORITHM ITSELF
|
|
|
|
-- indexes for noise arrays
|
|
local i2d = 1 -- index for 2D noises
|
|
local i3d_sup = 1 -- index for noise #6 which has a special size
|
|
local i3d = 1 -- index for 3D noises
|
|
|
|
-- Calculate increments
|
|
local i2d_incrZ = chulens.z
|
|
local i2d_decrX = chulens.x * chulens.z - 1
|
|
local i3d_incrY = chulens.y
|
|
local i3d_sup_incrZ = 6 * chulens.y
|
|
local i3d_decrX = chulens.x * chulens.y * chulens.z - 1
|
|
local i3d_sup_decrX = chulens.x * (chulens.y + 6) * chulens.z - 1
|
|
|
|
for x = minp.x, maxp.x do -- for each YZ plane
|
|
for z = minp.z, maxp.z do -- for each vertical line in this plane
|
|
local air_count = 0
|
|
local v2, v13, v14, v15, v16 = n2[i2d], n13[i2d], n14[i2d], n15[i2d], n16[i2d] -- take the noise values for 2D noises
|
|
|
|
-- Choose biome, by default normal dirt
|
|
local soil = "dirt"
|
|
local max = math.max(v13, v14, v15) -- the biome is the maximal of these 3 values.
|
|
if max > dirt_threshold then -- if one of these values is bigger than dirt_threshold, make clayey, silty or sandy dirt, depending on the case. If none of clay, silt or sand is predominant, make normal dirt.
|
|
if v13 == max then
|
|
if v13 > clay_threshold then
|
|
soil = "clay_over"
|
|
else
|
|
soil = "clay_under"
|
|
end
|
|
elseif v14 == max then
|
|
if v14 > silt_threshold then
|
|
soil = "silt_over"
|
|
else
|
|
soil = "silt_under"
|
|
end
|
|
else
|
|
soil = "sand"
|
|
end
|
|
end
|
|
|
|
for y = maxp.y, minp.y, -1 do -- for each node in vertical line
|
|
local ivm = a:index(x, y, z) -- index of the data array, matching the position {x, y, z}
|
|
local ground = math.max(heightmap[i2d], 0) - 5
|
|
|
|
if data[ivm] == node["snow_layer"] then
|
|
data[ivm] = node["air"]
|
|
end
|
|
|
|
-- Replace dirt and sand nodes appropriately.
|
|
if data[ivm] == node["dirt"] or data[ivm] == node["dry"] or data[ivm] == node["lawn"] or data[ivm] == node["snow"] or data[ivm] == node["sand"] then
|
|
|
|
-- a top node
|
|
if y >= ground and data[ivm + ystride] == node["air"] then
|
|
-- Humidity and temperature are simplified from the original,
|
|
-- and derived from the actual mapgen.
|
|
local humidity = 2 ^ (v13 - v15 + (humiditymap[i2d] / 25) - 2)
|
|
local temperature = (heatmap[i2d] - 32) / 60 + 1
|
|
|
|
-- Add sea humidity (the mapgen doesn't)
|
|
--if humidity < 1.8 and y < 5 then
|
|
-- humidity = humidity * (1 + (5 - y) * 10)
|
|
--end
|
|
|
|
-- Replace the nodes.
|
|
if data[ivm] == node["dirt"] then
|
|
data[ivm] = soil_translate[soil].dirt
|
|
else
|
|
if temperature < snow_threshold then
|
|
data[ivm] = soil_translate[soil].snow
|
|
data[ivm + ystride] = node["snow_layer"]
|
|
elseif humidity < dry_dirt_threshold then
|
|
data[ivm] = soil_translate[soil].dry
|
|
else
|
|
data[ivm] = soil_translate[soil].lawn
|
|
end
|
|
end
|
|
|
|
v2 = math.abs(v2) - river_size -- v2 represents the distance from the river, in arbitrary units.
|
|
|
|
-- Most of the terrain noises are unavailable.
|
|
local conditions = { -- pack it in a table, for plants API
|
|
v1 = 0,
|
|
v2 = v2,
|
|
v3 = 0,
|
|
v4 = 0,
|
|
v5 = 0,
|
|
v6 = 0,
|
|
v7 = 0,
|
|
v8 = 0,
|
|
v9 = 0,
|
|
v10 = 0,
|
|
v11 = 0,
|
|
v12 = 0,
|
|
v13 = v13,
|
|
v14 = v14,
|
|
v15 = v15,
|
|
v16 = v16,
|
|
v17 = 0,
|
|
v18 = 0,
|
|
v19 = 0,
|
|
v20 = 0,
|
|
shade = 0,
|
|
temp = temperature,
|
|
humidity = humidity,
|
|
sea_water = 0,
|
|
river_water = 0,
|
|
water = 0,
|
|
thickness = 0 }
|
|
|
|
--for y1 = 1, math.min(10, maxp.y - y) do
|
|
-- if data[ivm + 1 + y1 * ystride] ~= node["air"] then
|
|
-- conditions.shade = y1
|
|
-- break
|
|
-- end
|
|
--end
|
|
vmg.choose_generate_plant(conditions, {x=x,y=y+1,z=z}, data, a, ivm + ystride)
|
|
else
|
|
if data[ivm] == node["dirt"] or data[ivm] == node["sand"] then
|
|
data[ivm] = soil_translate[soil].dirt
|
|
end
|
|
end
|
|
end
|
|
|
|
-- cave ceilings
|
|
if do_cave_stuff and y < maxp.y and data[ivm] == node["air"] and data[ivm + ystride] == node["stone"] then
|
|
local sr = math.random(20)
|
|
if sr == 1 then
|
|
data[ivm + ystride] = node["glowing_fungal_stone"]
|
|
elseif sr < 5 then
|
|
data[ivm] = node["stalactite"]
|
|
end
|
|
end
|
|
|
|
-- cave floors
|
|
if do_cave_stuff and y > minp.y and y < ground and data[ivm] == node["air"] then
|
|
air_count = air_count + 1
|
|
if data[ivm - ystride] == node["stone"] then
|
|
local sr = math.random(100)
|
|
if sr < 21 then
|
|
data[ivm] = node["stalagmite"]
|
|
elseif sr < 24 then
|
|
data[ivm] = node["mushroom_fertile_red"]
|
|
data[ivm - ystride] = node["dirt"]
|
|
elseif sr < 27 then
|
|
data[ivm] = node["mushroom_fertile_brown"]
|
|
data[ivm - ystride] = node["dirt"]
|
|
elseif air_count > 1 and sr < 29 then
|
|
data[ivm + ystride] = node["huge_mushroom_cap"]
|
|
data[ivm] = node["giant_mushroom_stem"]
|
|
data[ivm - ystride] = node["dirt"]
|
|
elseif air_count > 2 and sr < 30 then
|
|
data[ivm + 2 * ystride] = node["giant_mushroom_cap"]
|
|
data[ivm + ystride] = node["giant_mushroom_stem"]
|
|
data[ivm] = node["giant_mushroom_stem"]
|
|
data[ivm - ystride] = node["dirt"]
|
|
elseif sr < 34 then
|
|
data[ivm - ystride] = node["dirt"]
|
|
end
|
|
end
|
|
end
|
|
|
|
-- if y > minp.y and data[ivm] == node["air"] and data[ivm - ystride] == node["river_water_source"] then
|
|
-- local biome = vmg.biome_ids[biomemap[i2d]]
|
|
-- -- I haven't figured out what the decoration manager is
|
|
-- -- doing with the noise functions, but this works ok.
|
|
-- if table.contains(water_lily_biomes, biome) and n21[i2d] > 0.5 and math.random(5) == 1 then
|
|
-- data[ivm] = node["waterlily"]
|
|
-- end
|
|
-- end
|
|
|
|
if data[ivm] ~= node["air"] then
|
|
air_count = 0
|
|
end
|
|
|
|
i3d = i3d - i3d_incrY -- decrement i3d by one line
|
|
i3d_sup = i3d_sup + i3d_incrY -- idem
|
|
end
|
|
i2d = i2d + i2d_incrZ -- increment i2d by one Z
|
|
-- useless to increment i3d, because increment would be 0 !
|
|
i3d_sup = i3d_sup + i3d_sup_incrZ -- for i3d_sup, just avoid the 6 supplemental lines
|
|
end
|
|
i2d = i2d - i2d_decrX -- decrement the Z line previously incremented and increment by one X (1)
|
|
i3d = i3d - i3d_decrX -- decrement the YZ plane previously incremented and increment by one X (1)
|
|
i3d_sup = i3d_sup - i3d_sup_decrX -- idem, including the supplemental lines
|
|
end
|
|
vmg.execute_after_mapgen() -- needed for jungletree roots
|
|
|
|
-- After data collecting, check timer
|
|
local t3 = os.clock()
|
|
if vmg.loglevel >= 2 then
|
|
print("[Valleys Mapgen] Data collecting finished in " .. displaytime(t3-t2))
|
|
print("[Valleys Mapgen] Writing data ...")
|
|
end
|
|
|
|
-- execute voxelmanip boring stuff to write to the map...
|
|
vm:set_data(data)
|
|
vm:calc_lighting()
|
|
vm:write_to_map()
|
|
|
|
local t4 = os.clock()
|
|
if vmg.loglevel >= 2 then
|
|
print("[Valleys Mapgen] Data writing finished in " .. displaytime(t4-t3))
|
|
end
|
|
if vmg.loglevel >= 1 then
|
|
--print("[Valleys Mapgen] Mapgen finished in " .. displaytime(t4-t0))
|
|
end
|
|
|
|
table.insert(mapgen_times.preparation, t1 - t0)
|
|
table.insert(mapgen_times.noises, t2 - t1)
|
|
table.insert(mapgen_times.collecting, t3 - t2)
|
|
table.insert(mapgen_times.writing, t4 - t3)
|
|
table.insert(mapgen_times.total, t4 - t0)
|
|
end
|
|
|
|
-- Display mapgen stats on shutdown
|
|
local function stats(t)
|
|
local n = #t
|
|
|
|
local sum = 0
|
|
local sum_sq = 0
|
|
for _, k in ipairs(t) do
|
|
sum = sum + k
|
|
sum_sq = sum_sq + k^2
|
|
end
|
|
local average = sum / n
|
|
local variance = sum_sq / n - average^2
|
|
local standard_dev = math.sqrt(variance)
|
|
|
|
return average, standard_dev
|
|
end
|
|
|
|
minetest.register_on_shutdown(function()
|
|
if #mapgen_times.total == 0 then
|
|
return
|
|
end
|
|
|
|
if vmg.loglevel >= 1 then
|
|
local average, standard_dev
|
|
print("[Valleys Mapgen] Mapgen statistics:")
|
|
|
|
if vmg.loglevel >= 2 then
|
|
average, standard_dev = stats(mapgen_times.preparation)
|
|
print("[Valleys Mapgen] Mapgen preparation step:")
|
|
print(" average " .. displaytime(average))
|
|
print(" standard deviation " .. displaytime(standard_dev))
|
|
|
|
average, standard_dev = stats(mapgen_times.noises)
|
|
print("[Valleys Mapgen] Noises calculation step:")
|
|
print(" average " .. displaytime(average))
|
|
print(" standard deviation " .. displaytime(standard_dev))
|
|
|
|
average, standard_dev = stats(mapgen_times.collecting)
|
|
print("[Valleys Mapgen] Data collecting step:")
|
|
print(" average " .. displaytime(average))
|
|
print(" standard deviation " .. displaytime(standard_dev))
|
|
|
|
average, standard_dev = stats(mapgen_times.writing)
|
|
print("[Valleys Mapgen] Data writing step:")
|
|
print(" average " .. displaytime(average))
|
|
print(" standard deviation " .. displaytime(standard_dev))
|
|
end
|
|
average, standard_dev = stats(mapgen_times.total)
|
|
print("[Valleys Mapgen] TOTAL:")
|
|
print(" average " .. displaytime(average))
|
|
print(" standard deviation " .. displaytime(standard_dev))
|
|
end
|
|
end)
|
|
|
|
-- Trees are registered in a separate file
|
|
dofile(vmg.path .. "/trees.lua")
|
|
dofile(vmg.path .. "/plants_api.lua")
|
|
dofile(vmg.path .. "/plants.lua")
|
|
|
|
function vmg.get_noise(pos, i)
|
|
local n = vmg.noises[i]
|
|
local noise = minetest.get_perlin(n)
|
|
if not pos.z then -- 2D noise
|
|
return noise:get2d(pos)
|
|
else -- 3D noise
|
|
return noise:get3d(pos)
|
|
end
|
|
end
|
|
|
|
local function round(n)
|
|
return math.floor(n + 0.5)
|
|
end
|
|
|