Skip to content

Commit

Permalink
Port on_generated callback to mapgen env
Browse files Browse the repository at this point in the history
  • Loading branch information
sfan5 committed Mar 24, 2024
1 parent fcf2dd0 commit 67926f2
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 116 deletions.
2 changes: 1 addition & 1 deletion mods/default/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1651,5 +1651,5 @@ local modpath = minetest.get_modpath(minetest.get_current_modname())
dofile(modpath .. "/alias.lua")
dofile(modpath .. "/furnace.lua")
dofile(modpath .. "/sao.lua")
dofile(modpath .. "/mapgen.lua")
dofile(modpath .. "/mapgen_setup.lua")
dofile(modpath .. "/abm.lua")
133 changes: 18 additions & 115 deletions mods/default/mapgen.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
-- https://github.com/minetest/minetest/blob/stable-0.3/src/mapgen.cpp#L1667

--
-- General
-- Setup
--

if table.indexof({"v6", "singlenode"}, minetest.get_mapgen_setting("mg_name")) == -1 then
error("Minetest Classic only works with the v6 map generator")
local MAPGEN_ENV = minetest.save_gen_notify ~= nil

if not minetest.global_exists("default") then
assert(MAPGEN_ENV)
default = {}
end

assert(minetest.MAP_BLOCKSIZE == 16) -- calculations would need to be redone
Expand All @@ -30,99 +33,13 @@ local temple_workaround_needed = true

do
local spflags = minetest.get_mapgen_setting("mgv6_spflags")
spflags = string.split(spflags, ",", false)
for i, v in ipairs(spflags) do
-- force snow biomes off
if v:find("snowbiomes") then
spflags[i] = "nosnowbiomes"
end
-- disable temples too, if the engine supports it (5.9.0)
if v:find("temples") then
spflags[i] = "notemples"
temple_workaround_needed = false
end
if spflags:find("temples") then
temple_workaround_needed = false
end
spflags = table.concat(spflags, ",")
minetest.set_mapgen_setting("mgv6_spflags", spflags, true)
end

for k, v in pairs({
mapgen_stone = "default:stone",
mapgen_water_source = "default:water_source",
mapgen_lava_source = "default:lava_source",
mapgen_cobble = "default:cobble",
mapgen_dirt = "default:dirt",
mapgen_dirt_with_grass = "default:dirt_with_grass",
mapgen_sand = "default:sand",
mapgen_tree = "default:tree",
mapgen_leaves = "default:leaves",
mapgen_apple = "default:apple",
mapgen_jungletree = "default:jungletree",
mapgen_jungleleaves = "default:jungleleaves",
mapgen_junglegrass = "default:junglegrass",
mapgen_cobble = "default:cobble",
mapgen_mossycobble = "default:mossycobble",
}) do
minetest.register_alias(k, v)
end

minetest.log("info", "Desert temple workaround enabled: " .. dump(temple_workaround_needed))

--
-- Decorations
--

local np_tree_amount = {
-- transformed from '0.04 * (x+0.39) / (1+0.39)'
offset = 0.01122,
scale = 0.02877,
spread = vector.new(125, 125, 125),
seed = 2,
octaves = 4,
persistence = 0.66,
lacunarity = 2,
-- Limitation: Can't model that jungles are supposed to have 5x as many trees
-- (combination with another noise in original code)
}

minetest.register_decoration({
deco_type = "simple",
place_on = {"default:dirt"},

-- Papyrus is part of the tree placing code in 0.3, which tries to place
-- a certain random amount of trees in a mapblock. This maps to the current
-- deco mechanism very well.
sidelen = 16,
noise_params = np_tree_amount,

y_min = water_level - 1,
y_max = water_level - 1,

decoration = "default:papyrus",
height = 2,
height_max = 3,

-- need this to replace water
flags = "force_placement",
})

minetest.register_decoration({
deco_type = "simple",
place_on = {"default:sand"},

-- same as above
sidelen = 16,
noise_params = np_tree_amount,

y_min = water_level + 1,
y_max = 4,

decoration = "default:cactus",
height = 3,
})

-- TODO junglegrass can sit on top of cacti, consider emulating that

--
-- Custom stuff
--
Expand Down Expand Up @@ -203,6 +120,7 @@ local function fix_temple(self, cpos, wetness)
end

-- (debug)
minetest.log("info", "Fixing desert temple at " .. minetest.pos_to_string(cpos))
--[[self.data[self.va:indexp(cpos)] = minetest.get_content_id("default:torch")
for i, off in ipairs(d) do
local tmp = vector.add(cpos, vector.multiply(FIVE_DIRS[i], off))
Expand Down Expand Up @@ -244,6 +162,8 @@ local function make_nc(self, ncrandom, minp, maxp)
local p = vector.offset(minp, ncrandom:next(0, ex.x-1),
ncrandom:next(0, ex.y-1), ncrandom:next(0, ex.z-1))

minetest.log("info", "Placing nyancat at " .. minetest.pos_to_string(p))

-- this sets param2 without needing to retrieve the entire buffer
self.vm:set_node_at(p, { name = "air", param2 = facedir_i })
self.data[self.va:indexp(p)] = c_nc
Expand All @@ -259,7 +179,7 @@ local cached_buf2 = {}
local cached_buf3 = {}
local cached_buf4 = {}

default.on_generated = function(minp, maxp, blockseed)
default.on_generated = function(vmanip, minp, maxp, blockseed)
if minp.y >= 100 then
-- high in the air there's nothing, skip
return
Expand All @@ -269,14 +189,13 @@ default.on_generated = function(minp, maxp, blockseed)
rand = PseudoRandom(blockseed),

--va = <VoxelArea>,
--vm = <VoxelManip>,
vm = vmanip,
data = cached_buf1,

c_stone = minetest.get_content_id("default:stone")
}
do
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
self.vm = vm
local emin, emax = self.vm:get_emerged_area()
self.va = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
self.vm:get_data(self.data)
end
Expand Down Expand Up @@ -427,27 +346,11 @@ default.on_generated = function(minp, maxp, blockseed)
end

self.vm:set_data(self.data)
self.vm:write_to_map()
if not MAPGEN_ENV then
self.vm:write_to_map()
end
end

-- It's possible someone would want ores to be generated in
-- a singlenode map, but the chance is very slim. So leave it alone.
if minetest.get_mapgen_setting("mg_name") ~= "singlenode" then
if MAPGEN_ENV then
minetest.register_on_generated(default.on_generated)
minetest.set_gen_notify({temple = true})
end

-- for mapgen debugging
if false then
minetest.override_item("default:stone", { drawtype = "airlike" })
local hl = {"coalstone", "ironstone", "mese", "clay", "gravel", "nyancat", "nyancat_rainbow"}
for _, s in ipairs(hl) do
minetest.override_item("default:" .. s, {
paramtype = "light",
light_source = 8,
})
end
minetest.register_on_newplayer(function(player)
player:get_inventory():add_item("main", "default:pick_mese")
end)
end
144 changes: 144 additions & 0 deletions mods/default/mapgen_setup.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
-- Original references:
-- https://github.com/minetest/minetest/blob/stable-0.3/src/mapgen.cpp#L1667

--
-- General
--

if table.indexof({"v6", "singlenode"}, minetest.get_mapgen_setting("mg_name")) == -1 then
error("Minetest Classic only works with the v6 map generator")
end

local water_level = tonumber(minetest.get_mapgen_setting("water_level"))

do
local spflags = minetest.get_mapgen_setting("mgv6_spflags")
spflags = string.split(spflags, ",", false)
for i, v in ipairs(spflags) do
-- force snow biomes off
if v:find("snowbiomes") then
spflags[i] = "nosnowbiomes"
end
-- disable temples too, if the engine supports it (5.9.0)
if v:find("temples") then
spflags[i] = "notemples"
end
end
spflags = table.concat(spflags, ",")
minetest.set_mapgen_setting("mgv6_spflags", spflags, true)
end

for k, v in pairs({
mapgen_stone = "default:stone",
mapgen_water_source = "default:water_source",
mapgen_lava_source = "default:lava_source",
mapgen_cobble = "default:cobble",
mapgen_dirt = "default:dirt",
mapgen_dirt_with_grass = "default:dirt_with_grass",
mapgen_sand = "default:sand",
mapgen_tree = "default:tree",
mapgen_leaves = "default:leaves",
mapgen_apple = "default:apple",
mapgen_jungletree = "default:jungletree",
mapgen_jungleleaves = "default:jungleleaves",
mapgen_junglegrass = "default:junglegrass",
mapgen_cobble = "default:cobble",
mapgen_mossycobble = "default:mossycobble",
}) do
minetest.register_alias(k, v)
end

--
-- Decorations
--

local np_tree_amount = {
-- transformed from '0.04 * (x+0.39) / (1+0.39)'
offset = 0.01122,
scale = 0.02877,
spread = vector.new(125, 125, 125),
seed = 2,
octaves = 4,
persistence = 0.66,
lacunarity = 2,
-- Limitation: Can't model that jungles are supposed to have 5x as many trees
-- (combination with another noise in original code)
}

minetest.register_decoration({
deco_type = "simple",
place_on = {"default:dirt"},

-- Papyrus is part of the tree placing code in 0.3, which tries to place
-- a certain random amount of trees in a mapblock. This maps to the current
-- deco mechanism very well.
sidelen = 16,
noise_params = np_tree_amount,

y_min = water_level - 1,
y_max = water_level - 1,

decoration = "default:papyrus",
height = 2,
height_max = 3,

-- need this to replace water
flags = "force_placement",
})

minetest.register_decoration({
deco_type = "simple",
place_on = {"default:sand"},

-- same as above
sidelen = 16,
noise_params = np_tree_amount,

y_min = water_level + 1,
y_max = 4,

decoration = "default:cactus",
height = 3,
})

-- TODO junglegrass can sit on top of cacti, consider emulating that

--
-- on_generated
--

-- It's possible someone would want ores to be generated in
-- a singlenode map, but the chance is very slim. So leave it alone.
if minetest.get_mapgen_setting("mg_name") ~= "singlenode" then

minetest.set_gen_notify({temple = true})

local script = minetest.get_modpath(minetest.get_current_modname()) .. "/mapgen.lua"

-- Mapgen Lua environment (5.9.0)
if minetest.register_mapgen_script then
minetest.log("info", "Using threaded mapgen")
minetest.register_mapgen_script(script)
else
dofile(script)
minetest.register_on_generated(function(minp, maxp, blockseed)
local vm = minetest.get_mapgen_object("voxelmanip")
default.on_generated(vm, minp, maxp, blockseed)
end)
end
end

-- for mapgen debugging
if false then
minetest.override_item("default:stone", { drawtype = "airlike" })
local hl = {"coalstone", "ironstone", "mese", "clay", "gravel", "nyancat", "nyancat_rainbow"}
for _, s in ipairs(hl) do
minetest.override_item("default:" .. s, {
paramtype = "light",
light_source = 8,
})
end
minetest.register_on_newplayer(function(player)
player:get_inventory():add_item("main", "default:pick_mese")
end)
end

0 comments on commit 67926f2

Please sign in to comment.