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_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.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.LASER_GLOW = 3
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
-- 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
-- the map is segmented in multiple zones (e.g. islands, deep ocean)
-- 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)
else
lzr_mapgen.generate_piece(start_pos, vector.add(start_pos, size),
false, aprot_min, aprot_max)
nil, aprot_min, aprot_max)
end
-- Also clear objects

View File

@ -20,6 +20,11 @@ lzr_mapgen.get_backdrop_description = function(id)
return backdrop_descriptions[id]
end
dofile(minetest.get_modpath("lzr_mapgen").."/settings.lua")
dofile(minetest.get_modpath("lzr_mapgen").."/aliases.lua")
dofile(minetest.get_modpath("lzr_mapgen").."/islands.lua")
dofile(minetest.get_modpath("lzr_mapgen").."/islands_decorations.lua")
dofile(minetest.get_modpath("lzr_mapgen").."/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 ceil = math.ceil
local min = math.min
@ -94,22 +159,6 @@ local base_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.
local c_stone = minetest.get_content_id("lzr_core:stone")
@ -147,29 +196,33 @@ local function get_terrain_height(theight,hheight,cheight)
return theight
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_z = maxp.z - minp.z + 1
local permapdims3d = {x = sidelen_x, y = sidelen_z}
local clear = is_on_generated ~= true
local clear = IS_IN_MAPGEN_ENVIRONMENT ~= true
-- voxelmanip stuff
local vm, emin, emax
if is_on_generated then
vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
else
if not vm then
vm = minetest.get_voxel_manip(minp, maxp)
emin, emax = vm:get_emerged_area()
end
local emin, emax = vm:get_emerged_area()
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
vm:get_data(data)
-- If we are fully outside the islands area,
-- we can switch to the ultra-fast deep ocean
-- 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_var = 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
local vi = area:index(x, y, z)
-- Deep ocean
if z <= lzr_globals.DEEP_OCEAN_Z then
if y <= lzr_globals.SEASTONE_LEVEL then
if z <= DEEP_OCEAN_Z then
if y <= SEASTONE_LEVEL then
data[vi] = c_stone
elseif y <= lzr_globals.SEABED_LEVEL then
elseif y <= SEABED_LEVEL then
data[vi] = c_seabed
elseif y <= lzr_globals.WATER_LEVEL then
elseif y <= WATER_LEVEL then
data[vi] = c_water
elseif clear then
data[vi] = minetest.CONTENT_AIR
@ -271,37 +324,36 @@ lzr_mapgen.generate_piece = function(minp, maxp, is_on_generated, prot_min, prot
end
vm:set_data(data)
if generate_islands then
minetest.generate_decorations(vm)
minetest.generate_ores(vm)
if is_on_generated then
if IS_IN_MAPGEN_ENVIRONMENT then
vm:calc_lighting()
end
vm:write_to_map(true)
minetest.after(0,function()
minetest.fix_light(minp, maxp)
end)
else
vm:write_to_map(true)
end
elseif not IS_IN_MAPGEN_ENVIRONMENT then
vm:write_to_map(true)
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
-- define the 3D volume.
minetest.register_on_generated(function(minp, maxp, seed)
minetest.register_on_generated(function(vmanip, minp, maxp)
-- Start time of mapchunk generation.
local t0 = os.clock()
lzr_mapgen.generate_piece(minp, maxp, true)
generate_piece(minp, maxp, vmanip)
-- Print generation time of this mapchunk.
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")
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)