forked from mtcontrib/biome_lib
		
	Use engine decorations when possible
This commit is contained in:
		
							
								
								
									
										65
									
								
								API.txt
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								API.txt
									
									
									
									
									
								
							@@ -332,7 +332,6 @@ will be called in the form:
 | 
			
		||||
 | 
			
		||||
	somefunction(pos)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
biome_lib.update_plant(options)
 | 
			
		||||
 | 
			
		||||
@@ -496,7 +495,6 @@ Perlin noise used.
 | 
			
		||||
The first one is for a "fertile ground" layer, which I tend to refer to as the
 | 
			
		||||
generic "stuff can potentially grow here" layer.  Its values are hard-coded:
 | 
			
		||||
 | 
			
		||||
	biome_lib.plantlife_seed_diff = 329
 | 
			
		||||
	perlin_octaves = 3
 | 
			
		||||
	perlin_persistence = 0.6
 | 
			
		||||
	perlin_scale = 100
 | 
			
		||||
@@ -593,3 +591,66 @@ See settingtypes.txt for a list.  Any item listed there can be changed either
 | 
			
		||||
by adding it to your minetest.conf, or by using the "all settings" menu in
 | 
			
		||||
Minetest, whatever's appropriate for your particular setup.
 | 
			
		||||
 | 
			
		||||
==================
 | 
			
		||||
Engine Decorations
 | 
			
		||||
==================
 | 
			
		||||
 | 
			
		||||
If a call to biome_lib.register_on_generate() contains items and biome
 | 
			
		||||
definition settings that are suitable, biome_lib will pass that call on to the
 | 
			
		||||
engine instead, to use its built-in decorations feature, since it'll be much
 | 
			
		||||
faster than Lua.
 | 
			
		||||
 | 
			
		||||
For this to work, first the item to be added must either be a node, or a
 | 
			
		||||
table with a list of nodes that biome_lib would normally pick from randomly.
 | 
			
		||||
That is to say, you cannot specify an L-tree or a function here, as the engine
 | 
			
		||||
does not support that sort of thing (biome_lib will just switch to its normal
 | 
			
		||||
handling if you do).
 | 
			
		||||
 | 
			
		||||
Second, these biome definition items must not be present:
 | 
			
		||||
 | 
			
		||||
* below_nodes
 | 
			
		||||
* avoid_nodes
 | 
			
		||||
* avoid_radius
 | 
			
		||||
* neighbors
 | 
			
		||||
* ncount
 | 
			
		||||
* depth
 | 
			
		||||
* near_nodes_size
 | 
			
		||||
* near_nodes_vertical
 | 
			
		||||
* temp_min
 | 
			
		||||
* temp_max
 | 
			
		||||
* verticals_list
 | 
			
		||||
* delete_above
 | 
			
		||||
* delete_above_surround
 | 
			
		||||
 | 
			
		||||
The plantlife_limit definition item is ignored when checking if a particular
 | 
			
		||||
call can be routed to the engine.
 | 
			
		||||
 | 
			
		||||
The call given to the engine will use the remaining biome definition items in
 | 
			
		||||
the following manner:
 | 
			
		||||
 | 
			
		||||
deco_type =		"simple",
 | 
			
		||||
flags =			"all_floors"
 | 
			
		||||
decoration =	node or table with node list
 | 
			
		||||
place_on =		surface
 | 
			
		||||
y_min =			min_elevation
 | 
			
		||||
y_max =			max_elevation
 | 
			
		||||
spawn_by =		near_nodes
 | 
			
		||||
num_spawn_by = 	near_nodes_count
 | 
			
		||||
param2 = 		\_ set to the range specified by the biome definition's
 | 
			
		||||
param2_max = 	/  random_facedir table, if present, otherwise omitted
 | 
			
		||||
noise_params = {
 | 
			
		||||
	octaves = biome_lib.fertile_perlin_octaves,
 | 
			
		||||
	persist = biome_lib.fertile_perlin_persistence * (250/biome_lib.fertile_perlin_scale),
 | 
			
		||||
	scale = ((100-biome.rarity)/100) * (math.min(biome.max_count, 6400)/6400),
 | 
			
		||||
	seed = biome.seed_diff,
 | 
			
		||||
	offset = 0,
 | 
			
		||||
	spread = {x = 100, y = 100, z = 100},
 | 
			
		||||
	lacunarity = 2,
 | 
			
		||||
	flags = "absvalue"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
If the biome definition's check_air setting is false, "force_placement" is
 | 
			
		||||
added to the decoration's flags setting.
 | 
			
		||||
 | 
			
		||||
If the biome def's spawn_replace_node is set to true, the decoration's
 | 
			
		||||
place_offset_y is set to -1 (otherwise it is omitted).
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										164
									
								
								api.lua
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								api.lua
									
									
									
									
									
								
							@@ -8,9 +8,11 @@ biome_lib.actionslist_no_aircheck = {}
 | 
			
		||||
biome_lib.surfaceslist_aircheck = {}
 | 
			
		||||
biome_lib.surfaceslist_no_aircheck = {}
 | 
			
		||||
 | 
			
		||||
local perlin_octaves = 3
 | 
			
		||||
local perlin_persistence = 0.6
 | 
			
		||||
local perlin_scale = 100
 | 
			
		||||
biome_lib.registered_decorations = {}
 | 
			
		||||
 | 
			
		||||
biome_lib.fertile_perlin_octaves = 3
 | 
			
		||||
biome_lib.fertile_perlin_persistence = 0.6
 | 
			
		||||
biome_lib.fertile_perlin_scale = 100
 | 
			
		||||
 | 
			
		||||
local temperature_seeddiff = 112
 | 
			
		||||
local temperature_octaves = 3
 | 
			
		||||
@@ -39,7 +41,6 @@ biome_lib.mapgen_elevation_limit = { ["min"] = -16, ["max"] = 48 }
 | 
			
		||||
 | 
			
		||||
biome_lib.perlin_temperature = PerlinNoise(temperature_seeddiff, temperature_octaves, temperature_persistence, temperature_scale)
 | 
			
		||||
biome_lib.perlin_humidity = PerlinNoise(humidity_seeddiff, humidity_octaves, humidity_persistence, humidity_scale)
 | 
			
		||||
biome_lib.plantlife_seed_diff = 329 -- needs to be global so other mods can see it
 | 
			
		||||
 | 
			
		||||
-- Local functions
 | 
			
		||||
 | 
			
		||||
@@ -80,6 +81,7 @@ function biome_lib.is_node_loaded(node_pos)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function biome_lib.set_defaults(biome)
 | 
			
		||||
 | 
			
		||||
	biome.seed_diff = biome.seed_diff or 0
 | 
			
		||||
	biome.min_elevation = biome.min_elevation or biome_lib.mapgen_elevation_limit.min
 | 
			
		||||
	biome.max_elevation = biome.max_elevation or biome_lib.mapgen_elevation_limit.max
 | 
			
		||||
@@ -105,6 +107,7 @@ function biome_lib.set_defaults(biome)
 | 
			
		||||
	biome.light_max = biome.light_max or 15
 | 
			
		||||
	biome.depth_max = biome.depth_max or 1
 | 
			
		||||
	biome.facedir = biome.facedir or 0
 | 
			
		||||
	return biome
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function search_table(t, s)
 | 
			
		||||
@@ -137,7 +140,14 @@ function biome_lib.register_on_generate(biomedef, nodes_or_function_or_model)
 | 
			
		||||
	biome_lib.mapgen_elevation_limit.min = math.min(biomedef.min_elevation or 0, biome_lib.mapgen_elevation_limit.min)
 | 
			
		||||
	biome_lib.mapgen_elevation_limit.max = math.max(biomedef.max_elevation or 0, biome_lib.mapgen_elevation_limit.max)
 | 
			
		||||
 | 
			
		||||
	if biomedef.check_air == false then 
 | 
			
		||||
	local decor_def = biome_lib.can_use_decorations(biomedef, nodes_or_function_or_model)
 | 
			
		||||
 | 
			
		||||
	if decor_def then
 | 
			
		||||
		biome_lib.dbg("Using engine decorations instead of biome_lib functions for node(s): "..dump(nodes_or_function_or_model), 3)
 | 
			
		||||
		biome_lib.registered_decorations[#biome_lib.registered_decorations + 1] = nodes_or_function_or_model
 | 
			
		||||
		minetest.register_decoration(decor_def)
 | 
			
		||||
		return
 | 
			
		||||
	elseif biomedef.check_air == false then 
 | 
			
		||||
		biome_lib.dbg("Register no-air-check mapgen hook: "..dump(nodes_or_function_or_model), 3)
 | 
			
		||||
		biome_lib.actionslist_no_aircheck[#biome_lib.actionslist_no_aircheck + 1] = { biomedef, nodes_or_function_or_model }
 | 
			
		||||
		local s = biomedef.surface
 | 
			
		||||
@@ -269,15 +279,15 @@ local function populate_single_surface(biome, pos, perlin_fertile_area, checkair
 | 
			
		||||
	return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function biome_lib.populate_surfaces(biome, nodes_or_function_or_model, snodes, checkair)
 | 
			
		||||
function biome_lib.populate_surfaces(b, nodes_or_function_or_model, snodes, checkair)
 | 
			
		||||
	local items_added = 0
 | 
			
		||||
 | 
			
		||||
	biome_lib.set_defaults(biome)
 | 
			
		||||
	local biome = biome_lib.set_defaults(b)
 | 
			
		||||
 | 
			
		||||
	-- filter stage 1 - find nodes from the supplied surfaces that are within the current biome.
 | 
			
		||||
 | 
			
		||||
	local in_biome_nodes = {}
 | 
			
		||||
	local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
	local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
 | 
			
		||||
 | 
			
		||||
	for i = 1, #snodes do
 | 
			
		||||
		local pos = vector.new(snodes[i])
 | 
			
		||||
@@ -490,112 +500,31 @@ function biome_lib.generate_block(shutting_down)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- "Play" them back, populating them with new stuff in the process
 | 
			
		||||
 | 
			
		||||
minetest.register_globalstep(function(dtime)
 | 
			
		||||
	if not biome_lib.block_log[1] then return end -- the block log is empty
 | 
			
		||||
 | 
			
		||||
	if math.random(100) > biome_lib.queue_ratio then return end
 | 
			
		||||
	for s = 1, biome_lib.entries_per_step do
 | 
			
		||||
		biome_lib.generate_block()
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- Periodically wake-up the queue to give old blocks a chance to time-out
 | 
			
		||||
-- if the player isn't currently exploring (i.e. they're just playing in one area)
 | 
			
		||||
 | 
			
		||||
function biome_lib.wake_up_queue()
 | 
			
		||||
	if #biome_lib.block_recheck_list > 1
 | 
			
		||||
	  and #biome_lib.block_log == 0 then
 | 
			
		||||
		biome_lib.block_log[#biome_lib.block_log + 1] =
 | 
			
		||||
			table.copy(biome_lib.block_recheck_list[#biome_lib.block_recheck_list])
 | 
			
		||||
		biome_lib.block_recheck_list[#biome_lib.block_recheck_list] = nil
 | 
			
		||||
		biome_lib.run_block_recheck_list = true
 | 
			
		||||
		biome_lib.dbg("Woke-up the map queue to give old blocks a chance to time-out.", 3)
 | 
			
		||||
	end
 | 
			
		||||
	minetest.after(biome_lib.block_queue_wakeup_time, biome_lib.wake_up_queue)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
biome_lib.wake_up_queue()
 | 
			
		||||
 | 
			
		||||
-- Play out the entire log all at once on shutdown
 | 
			
		||||
-- to prevent unpopulated map areas
 | 
			
		||||
 | 
			
		||||
local function format_time(t)
 | 
			
		||||
	if t > 59999999 then
 | 
			
		||||
		return os.date("!%M minutes and %S seconds", math.ceil(t/1000000))
 | 
			
		||||
	else
 | 
			
		||||
		return os.date("!%S seconds", math.ceil(t/1000000))
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function biome_lib.check_remaining_time()
 | 
			
		||||
	if minetest.get_us_time() > (biome_lib.shutdown_last_timestamp + 10000000) then -- report progress every 10s
 | 
			
		||||
		biome_lib.shutdown_last_timestamp = minetest.get_us_time()
 | 
			
		||||
 | 
			
		||||
		local entries_remaining = #biome_lib.block_log + #biome_lib.block_recheck_list
 | 
			
		||||
 | 
			
		||||
		local total_purged = biome_lib.starting_count - entries_remaining
 | 
			
		||||
		local elapsed_time = biome_lib.shutdown_last_timestamp - biome_lib.shutdown_start_time
 | 
			
		||||
		biome_lib.dbg(string.format("%i entries, approximately %s remaining.",
 | 
			
		||||
			entries_remaining, format_time(elapsed_time/total_purged * entries_remaining)))
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_shutdown(function()
 | 
			
		||||
	biome_lib.shutdown_start_time = minetest.get_us_time()
 | 
			
		||||
	biome_lib.shutdown_last_timestamp = minetest.get_us_time()+1
 | 
			
		||||
 | 
			
		||||
	biome_lib.starting_count = #biome_lib.block_log + #biome_lib.block_recheck_list
 | 
			
		||||
 | 
			
		||||
	if biome_lib.starting_count == 0 then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	biome_lib.dbg("Stand by, purging the mapblock log "..
 | 
			
		||||
		"(there are "..biome_lib.starting_count.." entries) ...", 0)
 | 
			
		||||
 | 
			
		||||
	while #biome_lib.block_log > 0 do
 | 
			
		||||
		biome_lib.generate_block(true)
 | 
			
		||||
		biome_lib.check_remaining_time()
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if #biome_lib.block_recheck_list > 0 then
 | 
			
		||||
		biome_lib.block_log = table.copy(biome_lib.block_recheck_list)
 | 
			
		||||
		biome_lib.block_recheck_list = {}
 | 
			
		||||
		while #biome_lib.block_log > 0 do
 | 
			
		||||
			biome_lib.generate_block(true)
 | 
			
		||||
			biome_lib.check_remaining_time()
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	biome_lib.dbg("Log purge completed after "..
 | 
			
		||||
		format_time(minetest.get_us_time() - biome_lib.shutdown_start_time)..".", 0)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- The spawning ABM
 | 
			
		||||
 | 
			
		||||
function biome_lib.register_active_spawner(sd,sp,sr,sc,ss,sa)
 | 
			
		||||
 | 
			
		||||
	local biome = {}
 | 
			
		||||
	local b = {}
 | 
			
		||||
 | 
			
		||||
	if type(sd) ~= "table" then
 | 
			
		||||
		biome.spawn_delay = sd	-- old api expects ABM interval param here.
 | 
			
		||||
		biome.spawn_plants = {sp}
 | 
			
		||||
		biome.avoid_radius = sr
 | 
			
		||||
		biome.spawn_chance = sc
 | 
			
		||||
		biome.spawn_surfaces = {ss}
 | 
			
		||||
		biome.avoid_nodes = sa
 | 
			
		||||
		b.spawn_delay = sd	-- old api expects ABM interval param here.
 | 
			
		||||
		b.spawn_plants = {sp}
 | 
			
		||||
		b.avoid_radius = sr
 | 
			
		||||
		b.spawn_chance = sc
 | 
			
		||||
		b.spawn_surfaces = {ss}
 | 
			
		||||
		b.avoid_nodes = sa
 | 
			
		||||
	else
 | 
			
		||||
		biome = sd
 | 
			
		||||
		b = sd
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if biome.spawn_delay*biome_lib.time_scale >= 1 then
 | 
			
		||||
		biome.interval = biome.spawn_delay*biome_lib.time_scale
 | 
			
		||||
	if b.spawn_delay*biome_lib.time_scale >= 1 then
 | 
			
		||||
		b.interval = b.spawn_delay*biome_lib.time_scale
 | 
			
		||||
	else
 | 
			
		||||
		biome.interval = 1
 | 
			
		||||
		b.interval = 1
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	biome_lib.set_defaults(biome)
 | 
			
		||||
	local biome = biome_lib.set_defaults(b)
 | 
			
		||||
 | 
			
		||||
	biome.spawn_plants_count = #(biome.spawn_plants)
 | 
			
		||||
 | 
			
		||||
	local n
 | 
			
		||||
@@ -615,7 +544,7 @@ function biome_lib.register_active_spawner(sd,sp,sr,sc,ss,sa)
 | 
			
		||||
		action = function(pos, node, active_object_count, active_object_count_wider)
 | 
			
		||||
			local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }	
 | 
			
		||||
			local n_top = minetest.get_node(p_top)
 | 
			
		||||
			local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
			local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
 | 
			
		||||
 | 
			
		||||
			local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area)
 | 
			
		||||
 | 
			
		||||
@@ -725,12 +654,12 @@ function biome_lib.replace_plant(pos, replacement, grow_function, walldir, seedd
 | 
			
		||||
		biome_lib.grow_ltree(pos, grow_function)
 | 
			
		||||
		return
 | 
			
		||||
	elseif growtype == "function" then
 | 
			
		||||
		local perlin_fertile_area = minetest.get_perlin(seeddiff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
		local perlin_fertile_area = minetest.get_perlin(seeddiff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
 | 
			
		||||
		local fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area)
 | 
			
		||||
		grow_function(pos, fertility, temperature, walldir)
 | 
			
		||||
		return
 | 
			
		||||
	elseif growtype == "string" then
 | 
			
		||||
		local perlin_fertile_area = minetest.get_perlin(seeddiff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
		local perlin_fertile_area = minetest.get_perlin(seeddiff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
 | 
			
		||||
		local fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area)
 | 
			
		||||
		assert(loadstring(grow_function.."(...)"))(pos, fertility, temperature, walldir)
 | 
			
		||||
		return
 | 
			
		||||
@@ -758,28 +687,3 @@ function biome_lib.get_nodedef_field(nodename, fieldname)
 | 
			
		||||
	end
 | 
			
		||||
	return minetest.registered_nodes[nodename][fieldname]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if biome_lib.debug_log_level >= 3 then
 | 
			
		||||
	biome_lib.last_count = 0
 | 
			
		||||
 | 
			
		||||
	function biome_lib.show_pending_block_count()
 | 
			
		||||
		if biome_lib.last_count ~= #biome_lib.block_log then
 | 
			
		||||
			biome_lib.dbg(string.format("Pending block counts - ready to process: %-8icurrently deferred: %i",
 | 
			
		||||
				#biome_lib.block_log, #biome_lib.block_recheck_list), 3)
 | 
			
		||||
			biome_lib.last_count = #biome_lib.block_log
 | 
			
		||||
			biome_lib.queue_idle_flag = false
 | 
			
		||||
		elseif not biome_lib.queue_idle_flag then
 | 
			
		||||
			if #biome_lib.block_recheck_list > 0 then
 | 
			
		||||
				biome_lib.dbg("Mapblock queue only contains blocks that can't yet be processed.",  3)
 | 
			
		||||
				biome_lib.dbg("Idling the queue until new blocks arrive or the next wake-up call occurs.",  3)
 | 
			
		||||
			else
 | 
			
		||||
				biome_lib.dbg("Mapblock queue has run dry.",  3)
 | 
			
		||||
				biome_lib.dbg("Idling the queue until new blocks arrive.",  3)
 | 
			
		||||
			end
 | 
			
		||||
			biome_lib.queue_idle_flag = true
 | 
			
		||||
		end
 | 
			
		||||
		minetest.after(1, biome_lib.show_pending_block_count)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	biome_lib.show_pending_block_count()
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										140
									
								
								block_queue_checks.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								block_queue_checks.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
-- Iterate through the mapblock log,
 | 
			
		||||
-- populating blocks with new stuff in the process.
 | 
			
		||||
 | 
			
		||||
minetest.register_globalstep(function(dtime)
 | 
			
		||||
	if not biome_lib.block_log[1] then return end -- the block log is empty
 | 
			
		||||
 | 
			
		||||
	if math.random(100) > biome_lib.queue_ratio then return end
 | 
			
		||||
	for s = 1, biome_lib.entries_per_step do
 | 
			
		||||
		biome_lib.generate_block()
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- Periodically wake-up the queue to give old blocks a chance to time-out
 | 
			
		||||
-- if the player isn't currently exploring (i.e. they're just playing in one area)
 | 
			
		||||
 | 
			
		||||
function biome_lib.wake_up_queue()
 | 
			
		||||
	if #biome_lib.block_recheck_list > 1
 | 
			
		||||
	  and #biome_lib.block_log == 0 then
 | 
			
		||||
		biome_lib.block_log[#biome_lib.block_log + 1] =
 | 
			
		||||
			table.copy(biome_lib.block_recheck_list[#biome_lib.block_recheck_list])
 | 
			
		||||
		biome_lib.block_recheck_list[#biome_lib.block_recheck_list] = nil
 | 
			
		||||
		biome_lib.run_block_recheck_list = true
 | 
			
		||||
		biome_lib.dbg("Woke-up the map queue to give old blocks a chance to time-out.", 3)
 | 
			
		||||
	end
 | 
			
		||||
	minetest.after(biome_lib.block_queue_wakeup_time, biome_lib.wake_up_queue)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
biome_lib.wake_up_queue()
 | 
			
		||||
 | 
			
		||||
-- Play out the entire log all at once on shutdown
 | 
			
		||||
-- to prevent unpopulated map areas
 | 
			
		||||
 | 
			
		||||
local function format_time(t)
 | 
			
		||||
	if t > 59999999 then
 | 
			
		||||
		return os.date("!%M minutes and %S seconds", math.ceil(t/1000000))
 | 
			
		||||
	else
 | 
			
		||||
		return os.date("!%S seconds", math.ceil(t/1000000))
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function biome_lib.check_remaining_time()
 | 
			
		||||
	if minetest.get_us_time() > (biome_lib.shutdown_last_timestamp + 10000000) then -- report progress every 10s
 | 
			
		||||
		biome_lib.shutdown_last_timestamp = minetest.get_us_time()
 | 
			
		||||
 | 
			
		||||
		local entries_remaining = #biome_lib.block_log + #biome_lib.block_recheck_list
 | 
			
		||||
 | 
			
		||||
		local total_purged = biome_lib.starting_count - entries_remaining
 | 
			
		||||
		local elapsed_time = biome_lib.shutdown_last_timestamp - biome_lib.shutdown_start_time
 | 
			
		||||
		biome_lib.dbg(string.format("%i entries, approximately %s remaining.",
 | 
			
		||||
			entries_remaining, format_time(elapsed_time/total_purged * entries_remaining)))
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--Purge the block log at shutdown
 | 
			
		||||
 | 
			
		||||
minetest.register_on_shutdown(function()
 | 
			
		||||
 | 
			
		||||
	biome_lib.shutdown_start_time = minetest.get_us_time()
 | 
			
		||||
	biome_lib.shutdown_last_timestamp = minetest.get_us_time()+1
 | 
			
		||||
 | 
			
		||||
	biome_lib.starting_count = #biome_lib.block_log + #biome_lib.block_recheck_list
 | 
			
		||||
 | 
			
		||||
	if biome_lib.starting_count == 0 then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	biome_lib.dbg("Stand by, purging the mapblock log "..
 | 
			
		||||
		"(there are "..biome_lib.starting_count.." entries) ...", 0)
 | 
			
		||||
 | 
			
		||||
	while #biome_lib.block_log > 0 do
 | 
			
		||||
		biome_lib.generate_block(true)
 | 
			
		||||
		biome_lib.check_remaining_time()
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if #biome_lib.block_recheck_list > 0 then
 | 
			
		||||
		biome_lib.block_log = table.copy(biome_lib.block_recheck_list)
 | 
			
		||||
		biome_lib.block_recheck_list = {}
 | 
			
		||||
		while #biome_lib.block_log > 0 do
 | 
			
		||||
			biome_lib.generate_block(true)
 | 
			
		||||
			biome_lib.check_remaining_time()
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	biome_lib.dbg("Log purge completed after "..
 | 
			
		||||
		format_time(minetest.get_us_time() - biome_lib.shutdown_start_time)..".", 0)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- "Record" the map chunks being generated by the core mapgen,
 | 
			
		||||
-- split into individual mapblocks to reduce lag
 | 
			
		||||
 | 
			
		||||
minetest.register_on_generated(function(minp, maxp, blockseed)
 | 
			
		||||
	local timestamp = minetest.get_us_time()
 | 
			
		||||
	for y = 0, 4 do
 | 
			
		||||
		local miny = minp.y + y*16
 | 
			
		||||
 | 
			
		||||
		if miny >= biome_lib.mapgen_elevation_limit.min
 | 
			
		||||
		  and (miny + 15) <= biome_lib.mapgen_elevation_limit.max then
 | 
			
		||||
 | 
			
		||||
			for x = 0, 4 do
 | 
			
		||||
				local minx = minp.x + x*16
 | 
			
		||||
 | 
			
		||||
				for z = 0, 4 do
 | 
			
		||||
					local minz = minp.z + z*16
 | 
			
		||||
 | 
			
		||||
					local bmin = {x=minx, y=miny, z=minz}
 | 
			
		||||
					local bmax = {x=minx + 15, y=miny + 15, z=minz + 15}
 | 
			
		||||
					biome_lib.block_log[#biome_lib.block_log + 1] = { bmin, bmax, true, timestamp }
 | 
			
		||||
					biome_lib.block_log[#biome_lib.block_log + 1] = { bmin, bmax, false, timestamp }
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			biome_lib.dbg("Did not enqueue mapblocks at elevation "..miny.."m, they're out of range of any generate_plant() calls.", 4)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	biome_lib.run_block_recheck_list = true
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
if biome_lib.debug_log_level >= 3 then
 | 
			
		||||
	biome_lib.last_count = 0
 | 
			
		||||
 | 
			
		||||
	function biome_lib.show_pending_block_count()
 | 
			
		||||
		if biome_lib.last_count ~= #biome_lib.block_log then
 | 
			
		||||
			biome_lib.dbg(string.format("Pending block counts - ready to process: %-8icurrently deferred: %i",
 | 
			
		||||
				#biome_lib.block_log, #biome_lib.block_recheck_list), 3)
 | 
			
		||||
			biome_lib.last_count = #biome_lib.block_log
 | 
			
		||||
			biome_lib.queue_idle_flag = false
 | 
			
		||||
		elseif not biome_lib.queue_idle_flag then
 | 
			
		||||
			if #biome_lib.block_recheck_list > 0 then
 | 
			
		||||
				biome_lib.dbg("Mapblock queue only contains blocks that can't yet be processed.",  3)
 | 
			
		||||
				biome_lib.dbg("Idling the queue until new blocks arrive or the next wake-up call occurs.",  3)
 | 
			
		||||
			else
 | 
			
		||||
				biome_lib.dbg("Mapblock queue has run dry.",  3)
 | 
			
		||||
				biome_lib.dbg("Idling the queue until new blocks arrive.",  3)
 | 
			
		||||
			end
 | 
			
		||||
			biome_lib.queue_idle_flag = true
 | 
			
		||||
		end
 | 
			
		||||
		minetest.after(1, biome_lib.show_pending_block_count)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	biome_lib.show_pending_block_count()
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										64
									
								
								compat.lua
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								compat.lua
									
									
									
									
									
								
							@@ -49,3 +49,67 @@ function biome_lib:grow_tree(p, n)
 | 
			
		||||
	biome_lib.dbg("Item: "..dump(n), 2)
 | 
			
		||||
	biome_lib.grow_ltree(p, n)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function biome_lib.can_use_decorations(b, nodes_or_function_or_treedef)
 | 
			
		||||
	if not b or not nodes_or_function_or_treedef
 | 
			
		||||
	  or b.below_nodes
 | 
			
		||||
	  or b.avoid_nodes
 | 
			
		||||
	  or b.avoid_radius
 | 
			
		||||
	  or b.neighbors
 | 
			
		||||
	  or b.ncount
 | 
			
		||||
	  or b.depth
 | 
			
		||||
	  or b.near_nodes_size
 | 
			
		||||
	  or b.near_nodes_vertical
 | 
			
		||||
	  or b.temp_min
 | 
			
		||||
	  or b.temp_max
 | 
			
		||||
	  or b.verticals_list
 | 
			
		||||
	  or b.delete_above
 | 
			
		||||
	  or b.delete_above_surround
 | 
			
		||||
	  or ( type(nodes_or_function_or_treedef) == "string" and not minetest.registered_nodes[nodes_or_function_or_treedef] )
 | 
			
		||||
	  or ( type(nodes_or_function_or_treedef) == "table" and nodes_or_function_or_treedef.axiom )
 | 
			
		||||
	  or type(nodes_or_function_or_treedef) == "function"
 | 
			
		||||
		then return false
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local biome = biome_lib.set_defaults(b)
 | 
			
		||||
 | 
			
		||||
	local decor_def = {
 | 
			
		||||
		["deco_type"] = "simple",
 | 
			
		||||
		["flags"] = "all_floors",
 | 
			
		||||
		["decoration"] = nodes_or_function_or_treedef,
 | 
			
		||||
		["place_on"] = biome.surface,
 | 
			
		||||
		["y_min"] = biome.min_elevation,
 | 
			
		||||
		["y_max"] = biome.max_elevation,
 | 
			
		||||
		["spawn_by"] = biome.near_nodes,
 | 
			
		||||
		["num_spawn_by"] = biome.near_nodes and biome.near_nodes_count, 
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	local r = (100-biome.rarity)/100
 | 
			
		||||
	local mc = math.min(biome.max_count, 6400)/6400
 | 
			
		||||
 | 
			
		||||
	decor_def.noise_params = {
 | 
			
		||||
		octaves = biome_lib.fertile_perlin_octaves,
 | 
			
		||||
		persist = biome_lib.fertile_perlin_persistence * (100/biome_lib.fertile_perlin_scale),
 | 
			
		||||
		scale = math.min(r, mc),
 | 
			
		||||
		seed = biome.seed_diff,
 | 
			
		||||
		offset = 0,
 | 
			
		||||
		spread = {x = 100, y = 100, z = 100},
 | 
			
		||||
		lacunarity = 2,
 | 
			
		||||
		flags = "absvalue"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if not b.check_air then
 | 
			
		||||
		decor_def.flags = decor_def.flags..",force_placement"
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if b.spawn_replace_node then
 | 
			
		||||
		decor_def.place_offset_y = -1
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if b.random_facedir then
 | 
			
		||||
		decor_def.param2 =     math.min(b.random_facedir[1], b.random_facedir[2])
 | 
			
		||||
		decor_def.param2_max = math.max(b.random_facedir[1], b.random_facedir[2])
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return decor_def
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								init.lua
									
									
									
									
									
								
							@@ -77,13 +77,25 @@ dofile(biome_lib.modpath .. "/search_functions.lua")
 | 
			
		||||
dofile(biome_lib.modpath .. "/growth.lua")
 | 
			
		||||
dofile(biome_lib.modpath .. "/compat.lua")
 | 
			
		||||
 | 
			
		||||
-- and report the final registration results:
 | 
			
		||||
minetest.after(0.01, function()
 | 
			
		||||
	-- report the final registration results and enable the active block queue stuff
 | 
			
		||||
 | 
			
		||||
minetest.after(0, function()
 | 
			
		||||
	biome_lib.dbg("Registered a total of "..(#biome_lib.surfaceslist_aircheck)+(#biome_lib.surfaceslist_no_aircheck).." surface types to be evaluated, spread", 0)
 | 
			
		||||
	biome_lib.dbg("across "..#biome_lib.actionslist_aircheck.." actions with air-checking and "..#biome_lib.actionslist_no_aircheck.." actions without.", 0)
 | 
			
		||||
	biome_lib.dbg("within an elevation range of "..biome_lib.mapgen_elevation_limit.min.." and "..biome_lib.mapgen_elevation_limit.max.." meters.", 0)
 | 
			
		||||
	local n = #biome_lib.actionslist_aircheck + #biome_lib.actionslist_no_aircheck
 | 
			
		||||
 | 
			
		||||
	biome_lib.dbg("All mapgen registrations completed.", 0)
 | 
			
		||||
 | 
			
		||||
	if n > 0 then
 | 
			
		||||
		biome_lib.dbg("Total items/actions to handle manually: "..n.." ("..#biome_lib.actionslist_no_aircheck.." without air checks)", 0)
 | 
			
		||||
		biome_lib.dbg("Total surface types to handle manually: "..#biome_lib.surfaceslist_aircheck + #biome_lib.surfaceslist_no_aircheck, 0)
 | 
			
		||||
	else
 | 
			
		||||
		biome_lib.dbg("There are no \"handle manually\" items/actions registered,", 0)
 | 
			
		||||
		biome_lib.dbg("so the mapblock queue will not be not used this session.", 0)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	biome_lib.dbg("Items sent to the engine's decorations handler: "..#biome_lib.registered_decorations, 0)
 | 
			
		||||
	biome_lib.dbg("Elevation range: "..biome_lib.mapgen_elevation_limit.min.." to "..string.format("%+d", biome_lib.mapgen_elevation_limit.max).." meters.", 0)
 | 
			
		||||
 | 
			
		||||
	if n > 0 then
 | 
			
		||||
		dofile(biome_lib.modpath .. "/block_queue_checks.lua")
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
biome_lib.dbg("[Biome Lib] Loaded", 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -51,33 +51,3 @@ function biome_lib.find_open_side(pos)
 | 
			
		||||
	end
 | 
			
		||||
	return nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- "Record" the map chunks being generated by the core mapgen,
 | 
			
		||||
-- split into individual mapblocks to reduce lag
 | 
			
		||||
 | 
			
		||||
minetest.register_on_generated(function(minp, maxp, blockseed)
 | 
			
		||||
	local timestamp = minetest.get_us_time()
 | 
			
		||||
	for y = 0, 4 do
 | 
			
		||||
		local miny = minp.y + y*16
 | 
			
		||||
 | 
			
		||||
		if miny >= biome_lib.mapgen_elevation_limit.min
 | 
			
		||||
		  and (miny + 15) <= biome_lib.mapgen_elevation_limit.max then
 | 
			
		||||
 | 
			
		||||
			for x = 0, 4 do
 | 
			
		||||
				local minx = minp.x + x*16
 | 
			
		||||
 | 
			
		||||
				for z = 0, 4 do
 | 
			
		||||
					local minz = minp.z + z*16
 | 
			
		||||
 | 
			
		||||
					local bmin = {x=minx, y=miny, z=minz}
 | 
			
		||||
					local bmax = {x=minx + 15, y=miny + 15, z=minz + 15}
 | 
			
		||||
					biome_lib.block_log[#biome_lib.block_log + 1] = { bmin, bmax, true, timestamp }
 | 
			
		||||
					biome_lib.block_log[#biome_lib.block_log + 1] = { bmin, bmax, false, timestamp }
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			biome_lib.dbg("Did not enqueue mapblocks at elevation "..miny.."m, they're out of range of any generate_plant() calls.", 4)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	biome_lib.run_block_recheck_list = true
 | 
			
		||||
end)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user