mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2025-01-10 10:37:29 +01:00
prioritize map decorations to make the generations more deterministic
This commit is contained in:
parent
6f76697a24
commit
39eee60031
File diff suppressed because it is too large
Load Diff
@ -141,3 +141,58 @@ function mcl_mapgen_core.unregister_generator(id)
|
|||||||
if rec.needs_param2 then param2 = param2 - 1 end
|
if rec.needs_param2 then param2 = param2 - 1 end
|
||||||
--if rec.needs_level0 then level0 = level0 - 1 end
|
--if rec.needs_level0 then level0 = level0 - 1 end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Try to make decorations more deterministic in order, by sorting by rank and name
|
||||||
|
-- At least for low-rank this should make map seeds more comparable, but
|
||||||
|
-- adding for example a new structure can still change everything that comes
|
||||||
|
-- later, because currently decoration blockseeds are incremented sequentially
|
||||||
|
-- c.f., https://github.com/minetest/minetest/issues/14919
|
||||||
|
local pending_decorations = {}
|
||||||
|
|
||||||
|
function mcl_mapgen_core.register_decoration(def, callback)
|
||||||
|
if pending_decorations == nil then
|
||||||
|
-- Please do not register decorations in minetest.register_on_mods_loaded.
|
||||||
|
-- This should usually not happen, but modders may misuse this.
|
||||||
|
-- Nothing really bad should happen though, but the rank is ignored.
|
||||||
|
minetest.log("warning", "Decoration registered after mapgen: "..tostring(def.name))
|
||||||
|
minetest.register_decoration(def)
|
||||||
|
if callback then callback() end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
def = table.copy(def) -- defensive deep copy, needed for water lily
|
||||||
|
def.callback = callback
|
||||||
|
pending_decorations[#pending_decorations+1] = def
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sort_decorations()
|
||||||
|
local keys, map = {}, {}
|
||||||
|
for i, def in pairs(pending_decorations) do
|
||||||
|
-- Name, or fallback names, for better ordering:
|
||||||
|
local name = def.name or def.decoration
|
||||||
|
if not name and type(def.schematic) == "string" then -- filename based
|
||||||
|
local sc = string.split(def.schematic:gsub(".mts",""), "/")
|
||||||
|
name = sc[#sc]
|
||||||
|
end
|
||||||
|
if not name and type(def.schematic) == "table" and def.schematic.data then
|
||||||
|
name = "" -- "serialize" the schematic
|
||||||
|
for _, v in ipairs(def.schematic.data) do
|
||||||
|
if v.name then name = name .. v.name .. ":" end
|
||||||
|
end
|
||||||
|
if name == "" then name = nil end
|
||||||
|
end
|
||||||
|
-- sorting key is: rank, then insertion sequence, then name
|
||||||
|
local key = string.format("%05d:%04d:%s", def.rank or 1000, i, name or "deco")
|
||||||
|
keys[#keys+1] = key
|
||||||
|
map[key] = def
|
||||||
|
end
|
||||||
|
table.sort(keys)
|
||||||
|
for _, key in ipairs(keys) do
|
||||||
|
-- minetest.log("action", "Deco: "..key) -- dump the resulting order
|
||||||
|
minetest.register_decoration(map[key])
|
||||||
|
if map[key].callback then map[key].callback() end
|
||||||
|
end
|
||||||
|
pending_decorations = nil -- as we will not run again
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_mods_loaded(sort_decorations)
|
||||||
|
@ -45,6 +45,7 @@ local function register_mgv6_decorations()
|
|||||||
|
|
||||||
-- Doubletall grass
|
-- Doubletall grass
|
||||||
minetest.register_decoration({
|
minetest.register_decoration({
|
||||||
|
rank = 1500,
|
||||||
deco_type = "schematic",
|
deco_type = "schematic",
|
||||||
schematic = {
|
schematic = {
|
||||||
size = { x=1, y=3, z=1 },
|
size = { x=1, y=3, z=1 },
|
||||||
@ -81,6 +82,7 @@ local function register_mgv6_decorations()
|
|||||||
},
|
},
|
||||||
-- v6 hack: This makes sure large ferns only appear in jungles
|
-- v6 hack: This makes sure large ferns only appear in jungles
|
||||||
spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
|
spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
|
||||||
|
rank = 1510, -- larger than fern
|
||||||
num_spawn_by = 1,
|
num_spawn_by = 1,
|
||||||
place_on = {"group:grass_block_no_snow"},
|
place_on = {"group:grass_block_no_snow"},
|
||||||
|
|
||||||
@ -192,6 +194,7 @@ local function register_mgv6_decorations()
|
|||||||
},
|
},
|
||||||
-- Small trick to make sure melon spawn in jungles
|
-- Small trick to make sure melon spawn in jungles
|
||||||
spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
|
spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
|
||||||
|
rank = 1510, -- larger than fern
|
||||||
num_spawn_by = 1,
|
num_spawn_by = 1,
|
||||||
y_min = 1,
|
y_min = 1,
|
||||||
y_max = 40,
|
y_max = 40,
|
||||||
@ -214,6 +217,7 @@ local function register_mgv6_decorations()
|
|||||||
y_min = 1,
|
y_min = 1,
|
||||||
y_max = mcl_vars.overworld_max,
|
y_max = mcl_vars.overworld_max,
|
||||||
decoration = "mcl_flowers:tallgrass",
|
decoration = "mcl_flowers:tallgrass",
|
||||||
|
rank = 1500,
|
||||||
})
|
})
|
||||||
minetest.register_decoration({
|
minetest.register_decoration({
|
||||||
deco_type = "simple",
|
deco_type = "simple",
|
||||||
@ -230,6 +234,7 @@ local function register_mgv6_decorations()
|
|||||||
y_min = 1,
|
y_min = 1,
|
||||||
y_max = mcl_vars.overworld_max,
|
y_max = mcl_vars.overworld_max,
|
||||||
decoration = "mcl_flowers:tallgrass",
|
decoration = "mcl_flowers:tallgrass",
|
||||||
|
rank = 1500,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Seagrass and kelp
|
-- Seagrass and kelp
|
||||||
@ -256,6 +261,7 @@ local function register_mgv6_decorations()
|
|||||||
y_min = mcl_vars.overworld_min,
|
y_min = mcl_vars.overworld_min,
|
||||||
y_max = 0,
|
y_max = 0,
|
||||||
decoration = "mcl_ocean:seagrass_"..mat,
|
decoration = "mcl_ocean:seagrass_"..mat,
|
||||||
|
rank = 1500,
|
||||||
})
|
})
|
||||||
minetest.register_decoration({
|
minetest.register_decoration({
|
||||||
deco_type = "simple",
|
deco_type = "simple",
|
||||||
@ -276,6 +282,7 @@ local function register_mgv6_decorations()
|
|||||||
y_min = mcl_vars.overworld_min,
|
y_min = mcl_vars.overworld_min,
|
||||||
y_max = -5,
|
y_max = -5,
|
||||||
decoration = "mcl_ocean:seagrass_"..mat,
|
decoration = "mcl_ocean:seagrass_"..mat,
|
||||||
|
rank = 1500,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_decoration({
|
minetest.register_decoration({
|
||||||
@ -356,6 +363,7 @@ local function register_mgv6_decorations()
|
|||||||
y_min = 1,
|
y_min = 1,
|
||||||
y_max = mcl_vars.overworld_max,
|
y_max = mcl_vars.overworld_max,
|
||||||
decoration = "mcl_flowers:tallgrass",
|
decoration = "mcl_flowers:tallgrass",
|
||||||
|
rank = 1500,
|
||||||
})
|
})
|
||||||
|
|
||||||
local mushrooms = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown"}
|
local mushrooms = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown"}
|
||||||
|
@ -22,6 +22,7 @@ If nospawn is truthy the structure will not be placed by mapgen and the decorati
|
|||||||
-- called before placement. denies placement when returning falsy.
|
-- called before placement. denies placement when returning falsy.
|
||||||
after_place = function(pos,def,pr)
|
after_place = function(pos,def,pr)
|
||||||
-- executed after successful placement
|
-- executed after successful placement
|
||||||
|
rank = int, -- decorations are generated by increasing rank. Default for structures is 100, terrain features 900
|
||||||
sidelen = int, --length of one side of the structure. used for foundations.
|
sidelen = int, --length of one side of the structure. used for foundations.
|
||||||
solid_ground = bool, -- structure requires solid ground
|
solid_ground = bool, -- structure requires solid ground
|
||||||
make_foundation = bool, -- a foundation is automatically built for the structure. needs the sidelen param
|
make_foundation = bool, -- a foundation is automatically built for the structure. needs the sidelen param
|
||||||
|
@ -326,15 +326,15 @@ function mcl_structures.place_structure(pos, def, pr, blockseed, rot)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local EMPTY_SCHEMATIC = { size = {x = 0, y = 0, z = 0}, data = { } }
|
local EMPTY_SCHEMATIC = { size = {x = 0, y = 0, z = 0}, data = { } }
|
||||||
|
|
||||||
function mcl_structures.register_structure(name,def,nospawn) --nospawn means it will not be placed by mapgen decoration mechanism
|
function mcl_structures.register_structure(name,def,nospawn) --nospawn means it will not be placed by mapgen decoration mechanism
|
||||||
if mcl_structures.is_disabled(name) then return end
|
if mcl_structures.is_disabled(name) then return end
|
||||||
local flags = def.flags or "place_center_x, place_center_z, force_placement"
|
local flags = def.flags or "place_center_x, place_center_z, force_placement"
|
||||||
def.name = name
|
def.name = name
|
||||||
if not nospawn and def.place_on then
|
if not nospawn and def.place_on then
|
||||||
minetest.register_on_mods_loaded(function() --make sure all previous decorations and biomes have been registered
|
minetest.register_on_mods_loaded(function() --make sure all previous decorations and biomes have been registered
|
||||||
def.deco = minetest.register_decoration({
|
mcl_mapgen_core.register_decoration({
|
||||||
name = "mcl_structures:deco_"..name,
|
name = "mcl_structures:"..name,
|
||||||
|
rank = def.rank or (def.terrain_feature and 900) or 100, -- run before regular decorations
|
||||||
deco_type = "schematic",
|
deco_type = "schematic",
|
||||||
schematic = EMPTY_SCHEMATIC,
|
schematic = EMPTY_SCHEMATIC,
|
||||||
place_on = def.place_on,
|
place_on = def.place_on,
|
||||||
@ -347,10 +347,13 @@ function mcl_structures.register_structure(name,def,nospawn) --nospawn means it
|
|||||||
biomes = def.biomes,
|
biomes = def.biomes,
|
||||||
y_max = def.y_max,
|
y_max = def.y_max,
|
||||||
y_min = def.y_min
|
y_min = def.y_min
|
||||||
})
|
},
|
||||||
def.deco_id = minetest.get_decoration_id("mcl_structures:deco_"..name)
|
function()
|
||||||
minetest.set_gen_notify({decoration=true}, { def.deco_id })
|
def.deco_id = minetest.get_decoration_id("mcl_structures:"..name)
|
||||||
--catching of gennotify happens in mcl_mapgen_core
|
minetest.set_gen_notify({decoration=true}, { def.deco_id })
|
||||||
|
--catching of gennotify happens in mcl_mapgen_core
|
||||||
|
end
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
mcl_structures.registered_structures[name] = def
|
mcl_structures.registered_structures[name] = def
|
||||||
|
@ -134,6 +134,7 @@ local function get_fallen_tree_schematic(pos,pr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
mcl_structures.register_structure("fallen_tree",{
|
mcl_structures.register_structure("fallen_tree",{
|
||||||
|
rank = 1100, -- after regular trees
|
||||||
place_on = {"group:grass_block"},
|
place_on = {"group:grass_block"},
|
||||||
terrain_feature = true,
|
terrain_feature = true,
|
||||||
noise_params = {
|
noise_params = {
|
||||||
@ -151,12 +152,9 @@ mcl_structures.register_structure("fallen_tree",{
|
|||||||
y_min = minetest.get_mapgen_setting("water_level"),
|
y_min = minetest.get_mapgen_setting("water_level"),
|
||||||
on_place = function(pos,def,pr)
|
on_place = function(pos,def,pr)
|
||||||
local air_p1 = vector.offset(pos,-def.sidelen/2,1,-def.sidelen/2)
|
local air_p1 = vector.offset(pos,-def.sidelen/2,1,-def.sidelen/2)
|
||||||
local air_p2 = vector.offset(pos,def.sidelen/2,1,def.sidelen/2)
|
local air_p2 = vector.offset(air_p1,def.sidelen-1,0,def.sidelen-1)
|
||||||
local air = minetest.find_nodes_in_area(air_p1,air_p2,{"air"})
|
local air = minetest.find_nodes_in_area(air_p1,air_p2,{"air"})
|
||||||
if #air < ( def.sidelen * def.sidelen ) / 2 then
|
return #air >= (def.sidelen * def.sidelen) / 2
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end,
|
end,
|
||||||
place_func = function(pos,def,pr)
|
place_func = function(pos,def,pr)
|
||||||
local schem=get_fallen_tree_schematic(pos,pr)
|
local schem=get_fallen_tree_schematic(pos,pr)
|
||||||
|
Loading…
Reference in New Issue
Block a user