Run mapgen in MT mapgen environment (MT 5.9.0)

This commit is contained in:
Wuzzy 2024-09-12 23:03:51 +02:00
parent 2ebb0399fb
commit 3a7ef97c3a
6 changed files with 138 additions and 58 deletions

View File

@ -25,10 +25,6 @@ lzr_globals.MENU_SHIP_EDITOR_OFFSET = vector.new(13, 10, 31)
lzr_globals.MENU_SHIP_SPEAKER_OFFSET = vector.new(6, 9, 25) lzr_globals.MENU_SHIP_SPEAKER_OFFSET = vector.new(6, 9, 25)
lzr_globals.MENU_SHIP_TELEVISION_OFFSET = vector.new(5, 9, 25) lzr_globals.MENU_SHIP_TELEVISION_OFFSET = vector.new(5, 9, 25)
lzr_globals.MENU_PLAYER_SPAWN_POS = vector.add(lzr_globals.MENU_SHIP_POS, lzr_globals.MENU_SHIP_PLAYER_SPAWN_OFFSET) lzr_globals.MENU_PLAYER_SPAWN_POS = vector.add(lzr_globals.MENU_SHIP_POS, lzr_globals.MENU_SHIP_PLAYER_SPAWN_OFFSET)
lzr_globals.WATER_LEVEL = 1
lzr_globals.SEABED_LEVEL = -1000
lzr_globals.SEASTONE_LEVEL = -1002
lzr_globals.DEEP_OCEAN_Z = -20000
lzr_globals.GRAVITY = tonumber(minetest.settings:get("movement_gravity")) or 9.81 lzr_globals.GRAVITY = tonumber(minetest.settings:get("movement_gravity")) or 9.81
lzr_globals.LASER_GLOW = 3 lzr_globals.LASER_GLOW = 3
lzr_globals.LASER_ALPHA = 0x8E lzr_globals.LASER_ALPHA = 0x8E
@ -38,6 +34,10 @@ lzr_globals.PARROT_SPAWN_OFFSET = vector.new(0, 0.01, 0)
lzr_globals.MAX_RECEIVER_RECALLS = 5 lzr_globals.MAX_RECEIVER_RECALLS = 5
-- WARNING: This value is duplicated in lzr_mapgen.
-- Only change this value when also changing lzr_mapgen!
lzr_globals.DEEP_OCEAN_Z = -20000
-- Maximum number of nodes the player can see. We do this because -- Maximum number of nodes the player can see. We do this because
-- the map is segmented in multiple zones (e.g. islands, deep ocean) -- the map is segmented in multiple zones (e.g. islands, deep ocean)
-- with visible seams. By making sure the player is always far enough -- with visible seams. By making sure the player is always far enough

View File

@ -370,7 +370,7 @@ function lzr_levels.reset_area(clear, start_pos, size, start_pos_protected, size
aprot_min, aprot_max) aprot_min, aprot_max)
else else
lzr_mapgen.generate_piece(start_pos, vector.add(start_pos, size), lzr_mapgen.generate_piece(start_pos, vector.add(start_pos, size),
false, aprot_min, aprot_max) nil, aprot_min, aprot_max)
end end
-- Also clear objects -- Also clear objects

View File

@ -20,6 +20,11 @@ lzr_mapgen.get_backdrop_description = function(id)
return backdrop_descriptions[id] return backdrop_descriptions[id]
end end
dofile(minetest.get_modpath("lzr_mapgen").."/settings.lua")
dofile(minetest.get_modpath("lzr_mapgen").."/aliases.lua") dofile(minetest.get_modpath("lzr_mapgen").."/aliases.lua")
dofile(minetest.get_modpath("lzr_mapgen").."/islands.lua") dofile(minetest.get_modpath("lzr_mapgen").."/decorations.lua")
dofile(minetest.get_modpath("lzr_mapgen").."/islands_decorations.lua")
-- The mapgen script will both run in the global environment
-- and the mapgen environment. See mapgen.lua to learn why.
dofile(minetest.get_modpath("lzr_mapgen").."/mapgen.lua")
minetest.register_mapgen_script(minetest.get_modpath("lzr_mapgen").."/mapgen.lua")

View File

@ -1,3 +1,68 @@
-- The main mapgen code.
--[[ THIS FILE WILL BE RUN TWICE!
1) In the global Minetest environment,
2) In the heavily-restricted threaded mapgen environment
This means this file is very restricted and only has
access to functions that are available in both the
global and the mapgen environment. Refer to Minetest's
Lua API documentation for details.
In the global environment, this file runs to expose the
function lzr_mapgen.generate_piece, but it does not call
minetest.register_on_generated.
In the mapgen environment, it uses
minetest.register_on_generated, but it does not modify
the global environment.
The reason this file is called twice is to avoid code
duplication.
]]
-- This variable will be true when we're in the mapgen
-- environment. The mapgen environment does not have
-- access to global variables, so if lzr_mapgen does
-- not exist, we can decude we must be the mapgen
-- environment.
local IS_IN_MAPGEN_ENVIRONMENT = not minetest.global_exists("lzr_mapgen")
--[[ MAPGEN OVERVIEW:
The mapgen has two main zones:
Deep Ocean: The Deep Ocean is a very simple zone and very fast
to generate, it's just a flat layer of water with a flat seabed
way below the surface. Perfect to spawn the ship in.
Islands: Islands is a beautiful zone using 2D Perlin
noise, featuring tropical islands, palms, plants, hills, and
a hilly ocean floor. It is derived from the [islands] mod
by TheTermos, released under the MIT License in 2019.
Both zones are separated on the Z axis by DEEP_OCEAN_Z.
There is a hard ugly seam between both zones, so it is
important the game action happens far away from this
seam.
]]
-- Some basic values for mapgen coordinates
-- Water will be at this Y level, all the way down to SEABED_LEVEL+1
local WATER_LEVEL = 1
-- The seabed will be at this Y level, all the way down to SEASTONE_LEVEL+1 (deep ocean only)
local SEABED_LEVEL = -1000
-- The seastone will be at and below this Y level, all the way down to the bottom of the world (deep ocean only)
local SEASTONE_LEVEL = -1002
-- The deep ocean will begin when the Z coordinate is this value or lower.
-- WARNING: This value is duplicated in lzr_globals.
-- When you change it, you MUST also change it in lzr_globals!
local DEEP_OCEAN_Z = -20000
local floor = math.floor local floor = math.floor
local ceil = math.ceil local ceil = math.ceil
local min = math.min local min = math.min
@ -94,22 +159,6 @@ local base_heightmap = {}
local result_heightmap = {} local result_heightmap = {}
-- Set singlenode mapgen (air nodes only).
-- Disable the engine lighting calculation since that will be done for a
-- mapchunk of air nodes and will be incorrect after we place nodes.
minetest.set_mapgen_setting('mg_name', 'singlenode', true)
minetest.set_mapgen_setting('flags', 'nolight', true)
minetest.set_mapgen_setting('seed', '5436146057422610855', true)
minetest.set_mapgen_setting("mg_biome_np_heat",
"90,0,(1000,1000,1000),5349,3,0.5,2",
true)
minetest.set_mapgen_setting("mg_biome_np_humidity",
"54,10,(1000,1000,1000),5349,3,0.5,2",
true)
-- Get the content IDs for the nodes used. -- Get the content IDs for the nodes used.
local c_stone = minetest.get_content_id("lzr_core:stone") local c_stone = minetest.get_content_id("lzr_core:stone")
@ -147,29 +196,33 @@ local function get_terrain_height(theight,hheight,cheight)
return theight return theight
end end
lzr_mapgen.generate_piece = function(minp, maxp, is_on_generated, prot_min, prot_max) -- Generate a piece of the map and set nodes in the specified area.
-- * minp: Minimum position of the area
-- * maxp: Maximum position of the area
-- * vm: VoxelManip object (only required when calling this function in the mapgen environment. Set to nil otherwise)
-- * prot_min: Minimum position of protected area. The protected area will NOT be overwritten by this function
-- * prot_min: Maximum position of protected area
local generate_piece = function(minp, maxp, vm, prot_min, prot_max)
local sidelen_x = maxp.x - minp.x + 1 local sidelen_x = maxp.x - minp.x + 1
local sidelen_z = maxp.z - minp.z + 1 local sidelen_z = maxp.z - minp.z + 1
local permapdims3d = {x = sidelen_x, y = sidelen_z} local permapdims3d = {x = sidelen_x, y = sidelen_z}
local clear = is_on_generated ~= true local clear = IS_IN_MAPGEN_ENVIRONMENT ~= true
-- voxelmanip stuff -- voxelmanip stuff
local vm, emin, emax if not vm then
if is_on_generated then
vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
else
vm = minetest.get_voxel_manip(minp, maxp) vm = minetest.get_voxel_manip(minp, maxp)
emin, emax = vm:get_emerged_area()
end end
local emin, emax = vm:get_emerged_area()
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax} local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
vm:get_data(data) vm:get_data(data)
-- If we are fully outside the islands area, -- If we are fully outside the islands area,
-- we can switch to the ultra-fast deep ocean -- we can switch to the ultra-fast deep ocean
-- algorithm. -- algorithm.
local generate_islands = maxp.z > lzr_globals.DEEP_OCEAN_Z local generate_islands = maxp.z > DEEP_OCEAN_Z
local isln_terrain = nil local isln_terrain = nil
local isln_var = nil local isln_var = nil
local isln_hills = nil local isln_hills = nil
@ -238,12 +291,12 @@ lzr_mapgen.generate_piece = function(minp, maxp, is_on_generated, prot_min, prot
if not prot_min or not vector.in_area(mpos, prot_min, prot_max) then if not prot_min or not vector.in_area(mpos, prot_min, prot_max) then
local vi = area:index(x, y, z) local vi = area:index(x, y, z)
-- Deep ocean -- Deep ocean
if z <= lzr_globals.DEEP_OCEAN_Z then if z <= DEEP_OCEAN_Z then
if y <= lzr_globals.SEASTONE_LEVEL then if y <= SEASTONE_LEVEL then
data[vi] = c_stone data[vi] = c_stone
elseif y <= lzr_globals.SEABED_LEVEL then elseif y <= SEABED_LEVEL then
data[vi] = c_seabed data[vi] = c_seabed
elseif y <= lzr_globals.WATER_LEVEL then elseif y <= WATER_LEVEL then
data[vi] = c_water data[vi] = c_water
elseif clear then elseif clear then
data[vi] = minetest.CONTENT_AIR data[vi] = minetest.CONTENT_AIR
@ -271,37 +324,36 @@ lzr_mapgen.generate_piece = function(minp, maxp, is_on_generated, prot_min, prot
end end
vm:set_data(data) vm:set_data(data)
if generate_islands then if generate_islands then
minetest.generate_decorations(vm) minetest.generate_decorations(vm)
minetest.generate_ores(vm) minetest.generate_ores(vm)
if is_on_generated then if IS_IN_MAPGEN_ENVIRONMENT then
vm:calc_lighting() vm:calc_lighting()
end
vm:write_to_map(true)
minetest.after(0,function()
minetest.fix_light(minp, maxp)
end)
else else
vm:write_to_map(true) vm:write_to_map(true)
end end
elseif not IS_IN_MAPGEN_ENVIRONMENT then
vm:write_to_map(true)
end
end end
-- On generated function. if IS_IN_MAPGEN_ENVIRONMENT then
minetest.log("action", "[lzr_mapgen] mapgen script successfully run in mapgen environment")
-- On generated function for the mapgen environment
-- 'minp' and 'maxp' are the minimum and maximum positions of the mapchunk that minetest.register_on_generated(function(vmanip, minp, maxp)
-- define the 3D volume.
minetest.register_on_generated(function(minp, maxp, seed)
-- Start time of mapchunk generation. -- Start time of mapchunk generation.
local t0 = os.clock() local t0 = os.clock()
lzr_mapgen.generate_piece(minp, maxp, true) generate_piece(minp, maxp, vmanip)
-- Print generation time of this mapchunk. -- Print generation time of this mapchunk.
local chugent = ceil((os.clock() - t0) * 1000) local chugent = ceil((os.clock() - t0) * 1000)
minetest.log("action", "[lzr_mapgen] Mapchunk generation time for piece at " .. minetest.pos_to_string(minp)..": " .. chugent .. " ms") minetest.log("action", "[lzr_mapgen] Mapchunk generation time for piece at " .. minetest.pos_to_string(minp)..": " .. chugent .. " ms")
end) end)
else
minetest.log("action", "[lzr_mapgen] mapgen script successfully run in global environment")
-- Expose generate_piece to the global environment when this file does not
-- run as mapgen thrad
lzr_mapgen.generate_piece = generate_piece
end

View File

@ -0,0 +1,23 @@
-- Mapgen settings
-- Set singlenode mapgen
minetest.set_mapgen_setting('mg_name', 'singlenode', true)
-- Disable the engine lighting calculation since that will be done for a
-- mapchunk of air nodes and will be incorrect after we place nodes.
minetest.set_mapgen_setting('flags', 'nolight', true)
-- Set a fixed seed so the islands backdrop used by levels
-- will stay consistent for all players
minetest.set_mapgen_setting('seed', '5436146057422610855', true)
minetest.set_mapgen_setting("mg_biome_np_heat",
"90,0,(1000,1000,1000),5349,3,0.5,2",
true)
minetest.set_mapgen_setting("mg_biome_np_humidity",
"54,10,(1000,1000,1000),5349,3,0.5,2",
true)