Compare commits

...

28 Commits

Author SHA1 Message Date
kay27 5dfc0ac9b5 Merge remote-tracking branch 'origin/master' into mapgen 2021-07-22 03:23:26 +04:00
kay27 b70859e185 Merge origin/master into mapgen 2021-07-17 21:45:48 +04:00
kay27 279b1b09cd [mapgen] Add `mcl_mapgen.priorities` table 2021-05-08 02:51:17 +04:00
kay27 3bd1a6f89e [mapgen] [mcl_ocean_monument] Fix a typo in water_flowing node name 2021-05-06 02:58:49 +04:00
kay27 e529c4839a Merge remote-tracking branch 'origin/master' into mapgen 2021-05-06 02:42:56 +04:00
kay27 ce6f5b0ee1 [mapgen] [mcl_ocean_monument] Generate prismarine legs up to the bottom 2021-05-06 02:42:45 +04:00
NO11 135c8ece41 Remove some helper recipes, because the ocean monument generates now 2021-05-05 21:42:11 +00:00
kay27 2272753652 [mapgen] [mcl_ocean_monument] Reorder check loops to make it work faster, add random rotation 2021-05-06 00:41:20 +04:00
kay27 2fda0f2644 [mapgen] Add true builder name of Ocean Monument into mod.conf 2021-05-05 14:22:50 +00:00
kay27 9e3c2fe21e [mapgen] [mcl_ocean_monument] Support ice 2021-05-04 03:27:35 +04:00
kay27 66d1172852 [mapgen] Add ocean monument 2021-05-03 05:24:53 +04:00
kay27 8a53d24fa7 Merge remote-tracking branch 'origin/master' into mapgen 2021-05-02 23:18:18 +04:00
kay27 16700632af [mapgen] [debug] Add blockseed calculation functions 2021-05-02 23:18:03 +04:00
kay27 238eb6cb68 [mapgen] Comment complex part of the code 2021-05-02 13:29:29 +04:00
kay27 fd56bb746c [mapgen] Spawn strongholds without emerge areas 2021-05-02 04:25:23 +04:00
kay27 f4a28cfab0 [mapgen] GETTING RID OF EMERGE AREAS! Currently for dungeons and villages, and it works 2021-05-02 03:56:55 +04:00
kay27 f38c8daab7 [mapgen] Add safe chunk calculation 2021-05-02 02:26:41 +04:00
kay27 b12367b500 merge 2021-05-02 00:29:39 +04:00
kay27 d60e0d75b4 Merge remote-tracking branch 'origin/master' into mapgen 2021-04-29 00:54:08 +04:00
kay27 3c5bf8c9b2 [mapgen] Use more readable constants, increase max_block_generate_distance 2021-04-29 00:53:48 +04:00
kay27 c23bb1d59d [mapgen] rebalance mapgen/init core code 2021-04-28 03:03:47 +04:00
kay27 29727136ac [mapgen] redesign the code 2021-04-27 01:30:07 +04:00
kay27 3f20d8c1f0 [mapgen] ... and make it unrunnable back 2021-04-26 20:37:13 +04:00
kay27 269e560db1 [mapgen] Fix old-style API calls, make the code runnable 2021-04-26 20:14:36 +04:00
kay27 3732097ed6 Merge remote-tracking branch 'origin/master' into mapgen 2021-04-26 19:58:11 +04:00
kay27 942d70ee62 [mapgen] temporarily delay chorus nodes grow 2021-04-26 04:09:14 +04:00
kay27 abc3a1f139 [mapgen] To be continued... (this version won't run) 2021-04-26 03:35:54 +04:00
kay27 49ac211f87 [mapgen] Add undebugged `CORE/mcl_mapgen` mod for further integration 2021-04-25 23:31:52 +04:00
30 changed files with 959 additions and 749 deletions

View File

@ -27,6 +27,8 @@ movement_gravity = 10.4
# Mapgen stuff
max_block_generate_distance = 13
# altitude_chill and altitude_dry doesn't go well together with MCL2 biomes
# which already include "snowed" variants as you go higher.
# humid_rivers would cause the MushroomIsland biome to appear frequently around rivers.

View File

@ -24,153 +24,6 @@ mcl_vars.inventory_header = ""
-- Tool wield size
mcl_vars.tool_wield_scale = { x = 1.8, y = 1.8, z = 1 }
-- Mapgen variables
local mg_name = minetest.get_mapgen_setting("mg_name")
local minecraft_height_limit = 256
local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true"
local singlenode = mg_name == "singlenode"
-- Calculate mapgen_edge_min/mapgen_edge_max
mcl_vars.chunksize = math.max(1, tonumber(minetest.get_mapgen_setting("chunksize")) or 5)
mcl_vars.MAP_BLOCKSIZE = math.max(1, minetest.MAP_BLOCKSIZE or 16)
mcl_vars.mapgen_limit = math.max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000)
mcl_vars.MAX_MAP_GENERATION_LIMIT = math.max(1, minetest.MAX_MAP_GENERATION_LIMIT or 31000)
local central_chunk_offset = -math.floor(mcl_vars.chunksize / 2)
mcl_vars.central_chunk_offset_in_nodes = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
mcl_vars.chunk_size_in_nodes = mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE
local central_chunk_min_pos = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
local central_chunk_max_pos = central_chunk_min_pos + mcl_vars.chunk_size_in_nodes - 1
local ccfmin = central_chunk_min_pos - mcl_vars.MAP_BLOCKSIZE -- Fullminp/fullmaxp of central chunk, in nodes
local ccfmax = central_chunk_max_pos + mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_b = math.floor(math.min(mcl_vars.mapgen_limit, mcl_vars.MAX_MAP_GENERATION_LIMIT) / mcl_vars.MAP_BLOCKSIZE)
local mapgen_limit_min = -mapgen_limit_b * mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_vars.MAP_BLOCKSIZE - 1
local numcmin = math.max(math.floor((ccfmin - mapgen_limit_min) / mcl_vars.chunk_size_in_nodes), 0) -- Number of complete chunks from central chunk
local numcmax = math.max(math.floor((mapgen_limit_max - ccfmax) / mcl_vars.chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits.
mcl_vars.mapgen_edge_min = central_chunk_min_pos - numcmin * mcl_vars.chunk_size_in_nodes
mcl_vars.mapgen_edge_max = central_chunk_max_pos + numcmax * mcl_vars.chunk_size_in_nodes
local function coordinate_to_block(x)
return math.floor(x / mcl_vars.MAP_BLOCKSIZE)
end
local function coordinate_to_chunk(x)
return math.floor((coordinate_to_block(x) - central_chunk_offset) / mcl_vars.chunksize)
end
function mcl_vars.pos_to_block(pos)
return {
x = coordinate_to_block(pos.x),
y = coordinate_to_block(pos.y),
z = coordinate_to_block(pos.z)
}
end
function mcl_vars.pos_to_chunk(pos)
return {
x = coordinate_to_chunk(pos.x),
y = coordinate_to_chunk(pos.y),
z = coordinate_to_chunk(pos.z)
}
end
local k_positive = math.ceil(mcl_vars.MAX_MAP_GENERATION_LIMIT / mcl_vars.chunk_size_in_nodes)
local k_positive_z = k_positive * 2
local k_positive_y = k_positive_z * k_positive_z
function mcl_vars.get_chunk_number(pos) -- unsigned int
local c = mcl_vars.pos_to_chunk(pos)
return
(c.y + k_positive) * k_positive_y +
(c.z + k_positive) * k_positive_z +
c.x + k_positive
end
if not superflat and not singlenode then
-- Normal mode
--[[ Realm stacking (h is for height)
- Overworld (h>=256)
- Void (h>=1000)
- Realm Barrier (h=11), to allow escaping the End
- End (h>=256)
- Void (h>=1000)
- Nether (h=128)
- Void (h>=1000)
]]
-- Overworld
mcl_vars.mg_overworld_min = -62
mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit
mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min
mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min + 4
mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min + 10
mcl_vars.mg_lava = true
mcl_vars.mg_bedrock_is_rough = true
elseif singlenode then
mcl_vars.mg_overworld_min = -66
mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit
mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min
mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min
mcl_vars.mg_lava = false
mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min
mcl_vars.mg_bedrock_is_rough = false
else
-- Classic superflat
local ground = minetest.get_mapgen_setting("mgflat_ground_level")
ground = tonumber(ground)
if not ground then
ground = 8
end
mcl_vars.mg_overworld_min = ground - 3
mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit
mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min
mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min
mcl_vars.mg_lava = false
mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min
mcl_vars.mg_bedrock_is_rough = false
end
mcl_vars.mg_overworld_max = mcl_vars.mapgen_edge_max
-- The Nether (around Y = -29000)
mcl_vars.mg_nether_min = -29067 -- Carefully chosen to be at a mapchunk border
mcl_vars.mg_nether_max = mcl_vars.mg_nether_min + 128
mcl_vars.mg_bedrock_nether_bottom_min = mcl_vars.mg_nether_min
mcl_vars.mg_bedrock_nether_top_max = mcl_vars.mg_nether_max
if not superflat then
mcl_vars.mg_bedrock_nether_bottom_max = mcl_vars.mg_bedrock_nether_bottom_min + 4
mcl_vars.mg_bedrock_nether_top_min = mcl_vars.mg_bedrock_nether_top_max - 4
mcl_vars.mg_lava_nether_max = mcl_vars.mg_nether_min + 31
else
-- Thin bedrock in classic superflat mapgen
mcl_vars.mg_bedrock_nether_bottom_max = mcl_vars.mg_bedrock_nether_bottom_min
mcl_vars.mg_bedrock_nether_top_min = mcl_vars.mg_bedrock_nether_top_max
mcl_vars.mg_lava_nether_max = mcl_vars.mg_nether_min + 2
end
if mg_name == "flat" then
if superflat then
mcl_vars.mg_flat_nether_floor = mcl_vars.mg_bedrock_nether_bottom_max + 4
mcl_vars.mg_flat_nether_ceiling = mcl_vars.mg_bedrock_nether_bottom_max + 52
else
mcl_vars.mg_flat_nether_floor = mcl_vars.mg_lava_nether_max + 4
mcl_vars.mg_flat_nether_ceiling = mcl_vars.mg_lava_nether_max + 52
end
end
-- The End (surface at ca. Y = -27000)
mcl_vars.mg_end_min = -27073 -- Carefully chosen to be at a mapchunk border
mcl_vars.mg_end_max_official = mcl_vars.mg_end_min + minecraft_height_limit
mcl_vars.mg_end_max = mcl_vars.mg_overworld_min - 2000
mcl_vars.mg_end_platform_pos = { x = 100, y = mcl_vars.mg_end_min + 74, z = 0 }
-- Realm barrier used to safely separate the End from the void below the Overworld
mcl_vars.mg_realm_barrier_overworld_end_max = mcl_vars.mg_end_max
mcl_vars.mg_realm_barrier_overworld_end_min = mcl_vars.mg_end_max - 11
-- Use MineClone 2-style dungeons
mcl_vars.mg_dungeons = true
-- Set default stack sizes
minetest.nodedef_default.stack_max = 64
minetest.craftitemdef_default.stack_max = 64
@ -178,86 +31,3 @@ minetest.craftitemdef_default.stack_max = 64
-- Set random seed for all other mods (Remember to make sure no other mod calls this function)
math.randomseed(os.time())
local chunks = {} -- intervals of chunks generated
function mcl_vars.add_chunk(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
local prev
for i, d in pairs(chunks) do
if n <= d[2] then -- we've found it
if (n == d[2]) or (n >= d[1]) then return end -- already here
if n == d[1]-1 then -- right before:
if prev and (prev[2] == n-1) then
prev[2] = d[2]
table.remove(chunks, i)
return
end
d[1] = n
return
end
if prev and (prev[2] == n-1) then --join to previous
prev[2] = n
return
end
table.insert(chunks, i, {n, n}) -- insert new interval before i
return
end
prev = d
end
chunks[#chunks+1] = {n, n}
end
function mcl_vars.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
for i, d in pairs(chunks) do
if n <= d[2] then
return (n >= d[1])
end
end
return false
end
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does.
-- p: Position, if it's wrong, {name="error"} node will return.
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
--
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
function mcl_vars.get_node(p, force, us_timeout)
-- check initial circumstances
if not p or not p.x or not p.y or not p.z then return {name="error"} end
-- try common way
local node = minetest.get_node(p)
if node.name ~= "ignore" then
return node
end
-- copy table to get sure it won't changed by other threads
local pos = {x=p.x,y=p.y,z=p.z}
-- try LVM
minetest.get_voxel_manip():read_from_map(pos, pos)
node = minetest.get_node(pos)
if node.name ~= "ignore" or not force then
return node
end
-- all ways failed - need to emerge (or forceload if generated)
local us_timeout = us_timeout or 244
if mcl_vars.is_generated(pos) then
minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!")
minetest.forceload_block(pos)
else
minetest.emerge_area(pos, pos)
end
local t = minetest.get_us_time()
node = minetest.get_node(pos)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
node = minetest.get_node(pos)
end
return node
-- it still can return "ignore", LOL, even if force = true, but only after time out
end

View File

@ -0,0 +1,74 @@
# mcl_mapgen
============
Helps to avoid problems caused by 'chunk-in-shell' feature of mapgen.cpp.
It also queues your generators to run them in proper order:
## mcl_mapgen.register_chunk_generator(chunk_callback_function, priority)
=========================================================================
Registers callback function to be called when current chunk generation is finished.
`callback_function`: chunk callback function definition:
`function(minp, maxp, seed)`:
`minp` & `maxp`: minimum and maximum chunk position;
`seed`: seed of this mapchunk;
`priority` (optional): order number - the less, the earlier,
e.g. `mcl_mapgen.priorities.BUILDINGS` or `mcl_mapgen.priorities.LARGE_BUILDINGS`
## mcl_mapgen.register_block_generator(callback_function, priority)
===================================================================
Registers callback function to be called when block (usually 16x16x16 nodes) generation is finished.
`callback_function`: block callback function definition, see below;
`priority` (optional): order number - the less, the earlier,
e.g. `mcl_mapgen.priorities.BUILDINGS` or `mcl_mapgen.priorities.LARGE_BUILDINGS`
## mcl_mapgen.register_block_generator_lvm(callback_function, priority)
=======================================================================
Registers callback function to be called when block (usually 16x16x16 nodes) generation is finished.
`vm_context` passes into callback function and should be returned back.
`callback_function`: block callback LVM function definition, see below;
`priority` (optional): order number - the less, the earlier,
e.g. `mcl_mapgen.priorities.BUILDINGS` or `mcl_mapgen.priorities.LARGE_BUILDINGS`
## mcl_mapgen.register_chunk_generator_lvm(callback_function, priority)
=======================================================================
UNSAFE! See https://git.minetest.land/MineClone2/MineClone2/issues/1395
Registers callback function to be called when current chunk generation is finished.
IT IS UNSAFE! GROUND CONTENT YOU PLACE (INCLUDING WATER AND AIR) CAN BE OVERWRITTEN BY cavegen.
ALL OTHER API FUNCTIONS ARE SAFE! USE THEM PLEASE! BUT WE NEED THIS FUNCTION STILL SOMETIMES,
WHEN WE NEED TO ACCESS MAPGEN OBJECTS like `heightmap`, `biomemap`, ETC.
`callback_function`: chunk callback LVM function definition, see below;
`function(vm_context)`:
Function MUST RETURN `vm_context` back anyway! It will passed into next callback function from the queue.
`vm_context`: a table which already contains some LVM data if the fields, and some of them can be added right in callback function:
`vm`: curent voxel manipulator object itself;
`blockseed`: seed of this mapchunk;
`minp` & `maxp`: minimum and maximum chunk position;
`emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT;
`area`: voxel area, can be helpful to access data;
`data`: LVM buffer data array, data loads into it before the callbacks;
`write`: set it to true in yout callback functionm, if you changed `data` and want to write it;
`data2`: LVM buffer data array of `param2`, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourfels:
`vm_context.data2 = vm_context.data2 or vm_context.vm.get_param2_data(vm_context.lvm_param2_buffer)`
`write_param2`: set it to true in yout callback functionm, if you used `data2` and want to write it;
`lvm_param2_buffer`: static `param2` buffer pointer, used to load `data2` array;
`shadow`: set it to false to disable shadow propagation;
`heightmap`: mapgen object contanting y coordinates of ground level,
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourfels:
`vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')`
`biomemap`: mapgen object contanting biome IDs of nodes,
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourfels:
`vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')`
`heatmap`: mapgen object contanting temperature values of nodes,
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourfels:
`vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')`
`humiditymap`: mapgen object contanting humidity values of nodes,
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourfels:
`vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')`
`gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation,
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourfels:
`vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')`
`priority` (optional): order number - the less, the earlier,
e.g. `mcl_mapgen.priorities.BUILDINGS` or `mcl_mapgen.priorities.LARGE_BUILDINGS`
## mcl_mapgen.get_far_node(pos)
===============================
Returns node if it is generated. Otherwise returns `{name = "ignore"}`.

View File

@ -0,0 +1,413 @@
mcl_mapgen = {}
local priorities = { -- mcl_mapgen.priorities...
DEFAULT = 5000,
CHORUS = 100000,
BUILDINGS = 200000,
VILLAGES = 900000,
DUNGEONS = 950000,
STRONGHOLDS = 999999,
OCEAN_MONUMENT = 1000000,
LARGE_BUILDINGS = 2000000,
}
local math_floor = math.floor
local math_max = math.max
local minetest_get_node = minetest.get_node
local minetest_get_voxel_manip = minetest.get_voxel_manip
local minetest_log = minetest.log
local minetest_pos_to_string = minetest.pos_to_string
-- Calculate mapgen_edge_min/mapgen_edge_max
mcl_mapgen.CS = math_max(1, tonumber(minetest.get_mapgen_setting("chunksize")) or 5)
mcl_mapgen.BS = math_max(1, core.MAP_BLOCKSIZE or 16)
mcl_mapgen.LIMIT = math_max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000)
mcl_mapgen.MAX_LIMIT = math_max(1, core.MAX_MAP_GENERATION_LIMIT or 31000) -- might be set to 31000 or removed, see https://github.com/minetest/minetest/issues/10428
mcl_mapgen.OFFSET = - math_floor(mcl_mapgen.CS / 2)
mcl_mapgen.OFFSET_NODES = mcl_mapgen.OFFSET * mcl_mapgen.BS
mcl_mapgen.CS_NODES = mcl_mapgen.CS * mcl_mapgen.BS
local central_chunk_min_pos = mcl_mapgen.OFFSET * mcl_mapgen.BS
local central_chunk_max_pos = central_chunk_min_pos + mcl_mapgen.CS_NODES - 1
local ccfmin = central_chunk_min_pos - mcl_mapgen.BS -- Fullminp/fullmaxp of central chunk, in nodes
local ccfmax = central_chunk_max_pos + mcl_mapgen.BS
local mapgen_limit_b = math_floor(math.min(mcl_mapgen.LIMIT, mcl_mapgen.MAX_LIMIT) / mcl_mapgen.BS)
local mapgen_limit_min = - mapgen_limit_b * mcl_mapgen.BS
local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_mapgen.BS - 1
local numcmin = math_max(math_floor((ccfmin - mapgen_limit_min) / mcl_mapgen.CS_NODES), 0) -- Number of complete chunks from central chunk
local numcmax = math_max(math_floor((mapgen_limit_max - ccfmax) / mcl_mapgen.CS_NODES), 0) -- fullminp/fullmaxp to effective mapgen limits.
mcl_mapgen.EDGE_MIN = central_chunk_min_pos - numcmin * mcl_mapgen.CS_NODES
mcl_mapgen.EDGE_MAX = central_chunk_max_pos + numcmax * mcl_mapgen.CS_NODES
minetest_log("action", "[mcl_mapgen] World edges are: mcl_mapgen.EDGE_MIN = " .. tostring(mcl_mapgen.EDGE_MIN) .. ", mcl_mapgen.EDGE_MAX = " .. tostring(mcl_mapgen.EDGE_MAX))
------------------------------------------
-- Mapgen variables
local overworld, end_, nether = {}, {}, {}
mcl_mapgen.seed = minetest.get_mapgen_setting("seed")
mcl_mapgen.name = minetest.get_mapgen_setting("mg_name")
mcl_mapgen.v6 = mcl_mapgen.name == "v6"
mcl_mapgen.superflat = mcl_mapgen.name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true"
mcl_mapgen.singlenode = mcl_mapgen.name == "singlenode"
mcl_mapgen.normal = not mcl_mapgen.superflat and not mcl_mapgen.singlenode
local superflat, singlenode, normal = mcl_mapgen.superflat, mcl_mapgen.singlenode, mcl_mapgen.normal
minetest_log("action", "[mcl_mapgen] Mapgen mode: " .. (normal and "normal" or (superflat and "superflat" or "singlenode")))
------------------------------------------
local lvm_block_queue, lvm_chunk_queue, node_block_queue, node_chunk_queue = {}, {}, {}, {} -- Generators' queues
local lvm, block, lvm_block, lvm_chunk, param2, nodes_block, nodes_chunk, safe_functions = 0, 0, 0, 0, 0, 0, 0, 0 -- Requirements: 0 means none; greater than 0 means 'required'
local lvm_buffer, lvm_param2_buffer = {}, {} -- Static buffer pointers
local BS, CS = mcl_mapgen.BS, mcl_mapgen.CS -- Mapblock size (in nodes), Mapchunk size (in blocks)
local LAST_BLOCK, LAST_NODE = CS - 1, BS - 1 -- First mapblock in chunk (node in mapblock) has number 0, last has THIS number. It's for runtime optimization
local offset = mcl_mapgen.OFFSET -- Central mapchunk offset (in blocks)
local CS_NODES = mcl_mapgen.CS_NODES -- 80
local CS_3D = CS * CS * CS
local DEFAULT_PRIORITY = priorities.DEFAULT
function mcl_mapgen.register_chunk_generator(callback_function, priority)
nodes_chunk = nodes_chunk + 1
safe_functions = safe_functions + 1
node_chunk_queue[nodes_chunk] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
table.sort(node_chunk_queue, function(a, b) return (a.i <= b.i) end)
end
function mcl_mapgen.register_chunk_generator_lvm(callback_function, priority)
lvm = lvm + 1
lvm_chunk_queue[lvm_chunk] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
table.sort(lvm_chunk_queue, function(a, b) return (a.i <= b.i) end)
end
function mcl_mapgen.register_block_generator(callback_function, priority)
block = block + 1
nodes_block = nodes_block + 1
safe_functions = safe_functions + 1
node_block_queue[nodes_block] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
table.sort(node_block_queue, function(a, b) return (a.i <= b.i) end)
end
function mcl_mapgen.register_block_generator_lvm(callback_function, priority)
block = block + 1
lvm = lvm + 1
lvm_block = lvm_block + 1
lvm_block_queue[lvm_block] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
table.sort(lvm_block_queue, function(a, b) return (a.i <= b.i) end)
end
function mcl_mapgen.get_block_seed(pos, seed)
local p = pos
local x, y, z = p.x, p.y, p.z
if x<0 then x = 4294967296+x end
if y<0 then y = 4294967296+y end
if z<0 then z = 4294967296+z end
local seed = (seed or mcl_mapgen.seed or 0) % 4294967296
return (seed + (z*38134234)%4294967296 + (y*42123)%4294967296 + (x*23)%4294967296) % 4294967296
end
function mcl_mapgen.get_block_seed_2(pos, seed)
local p = pos
local seed = seed or mcl_mapgen.seed or 0
local x, y, z = p.x, p.y, p.z
if x<0 then x = 4294967296+x end
if y<0 then y = 4294967296+y end
if z<0 then z = 4294967296+z end
local n = ((1619*x)%4294967296 + (31337*y)%4294967296 + (52591*z)%4294967296 + (1013*seed)%4294967296) % 4294967296
-- n = (math_floor(n / 8192) ^ n) % 4294967296
local m = (n*n) % 4294967296
m = (m*60493) % 4294967296
m = (m+19990303) % 4294967296
return (n * m + 1376312589) % 4294967296
end
local storage = minetest.get_mod_storage()
local blocks = minetest.deserialize(storage:get_string("mapgen_blocks") or "return {}") or {}
local chunks = minetest.deserialize(storage:get_string("mapgen_chunks") or "return {}") or {}
minetest.register_on_shutdown(function()
storage:set_string("mapgen_chunks", minetest.serialize(chunks))
storage:set_string("mapgen_blocks", minetest.serialize(blocks))
end)
local vm_context-- here will be many references and flags, like: param2, light_data, heightmap, biomemap, heatmap, humiditymap, gennotify, write_lvm, write_param2, shadow
local data, data2, area
local current_blocks = {}
local current_chunks = {}
minetest.register_on_generated(function(minp, maxp, blockseed)
local minp, maxp, blockseed = minp, maxp, blockseed
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
minetest_log("warning", "[mcl_mapgen] New_chunk=" .. minetest_pos_to_string(minp) .. "..." .. minetest_pos_to_string(maxp) .. ", shell=" .. minetest_pos_to_string(emin) .. "..." .. minetest_pos_to_string(emax) .. ", blockseed=" .. tostring(blockseed) .. ", seed1=" .. mcl_mapgen.get_block_seed(minp) .. ", seed2=" .. mcl_mapgen.get_block_seed_2(minp))
if lvm > 0 then
vm_context = {lvm_param2_buffer = lvm_param2_buffer, vm = vm, emin = emin, emax = emax, minp = minp, maxp = maxp, blockseed = blockseed}
data = vm:get_data(lvm_buffer)
vm_context.data = data
area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
vm_context.area = area
end
if safe_functions > 0 then
local x0, y0, z0 = minp.x, minp.y, minp.z
local bx0, by0, bz0 = math_floor(x0/BS), math_floor(y0/BS), math_floor(z0/BS)
local bx1, by1, bz1 = bx0 + LAST_BLOCK, by0 + LAST_BLOCK, bz0 + LAST_BLOCK -- only for entire chunk check
-- Keep `blockseed` in `chunks[cx][cy][cz].seed` for further safe usage:
local cx0, cy0, cz0 = math_floor((bx0-offset)/CS), math_floor((by0-offset)/CS), math_floor((bz0-offset)/CS)
if not chunks[cx0] then chunks[cx0] = {} end
if not chunks[cx0][cy0] then chunks[cx0][cy0] = {} end
if not chunks[cx0][cy0][cz0] then
chunks[cx0][cy0][cz0] = {seed = blockseed, counter = 0}
else
chunks[cx0][cy0][cz0].seed = blockseed
end
local x1, y1, z1, x2, y2, z2 = emin.x, emin.y, emin.z, emax.x, emax.y, emax.z
local x, y, z = x1, y1, z1 -- iterate 7x7x7 mapchunk, {x,y,z} - first node pos. of mapblock
local bx, by, bz -- block coords (in blocs)
local box, boy, boz -- block offsets in chunks (in blocks)
while x < x2 do
bx = math_floor(x/BS)
local block_pos_offset_removed = bx - offset
local cx = math_floor(block_pos_offset_removed / CS)
box = block_pos_offset_removed % CS
if not blocks[bx] then blocks[bx]={} end
-- We don't know how many calls, including this one, will overwrite this block's content!
-- Start calculating it with `total_mapgen_block_writes_through_x` variable.
-- It can be `8 or less`, if we (speaking of `x` axis) are on chunk edge now,
-- or it can be `4 or less` - if we are in the middle of the chunk by `x` axis:
local total_mapgen_block_writes_through_x = (box > 0 and box < LAST_BLOCK) and 4 or 8
while y < y2 do
by = math_floor(y/BS)
block_pos_offset_removed = by - offset
local cy = math_floor(block_pos_offset_removed / CS)
boy = block_pos_offset_removed % CS
if not blocks[bx][by] then blocks[bx][by]={} end
-- Here we just divide `total_mapgen_block_writes_through_x` by 2,
-- if we are (speaking of `y` axis now) in the middle of the chunk now.
-- Or we don't divide it, if not.
-- So, basing on `total_mapgen_block_writes_through_x`,
--- we calculate `total_mapgen_block_writes_through_y` this way:
local total_mapgen_block_writes_through_y = (boy > 0 and boy < LAST_BLOCK) and math_floor(total_mapgen_block_writes_through_x / 2) or total_mapgen_block_writes_through_x
while z < z2 do
bz = math_floor(z/BS)
block_pos_offset_removed = bz - offset
local cz = math_floor(block_pos_offset_removed / CS)
boz = block_pos_offset_removed % CS
-- Now we do absolutely the same for `z` axis, basing on our previous result
-- from `total_mapgen_block_writes_through_y` variable.
-- And our final result is in `total_mapgen_block_writes`.
-- It can be still 8, derived from `x` calculation, but it can be less!
-- It can be even 1, if we are in safe 3x3x3 area of mapchunk:
local total_mapgen_block_writes = (boz > 0 and boz < LAST_BLOCK) and math_floor(total_mapgen_block_writes_through_y / 2) or total_mapgen_block_writes_through_y
-- Get current number of writes from the table, or just set it to 1, if accessed first time:
local current_mapgen_block_writes = blocks[bx][by][bz] and (blocks[bx][by][bz] + 1) or 1
-- And compare:
if current_mapgen_block_writes == total_mapgen_block_writes then
-- this block shouldn't be overwritten anymore, no need to keep it in memory
blocks[bx][by][bz] = nil
if not chunks[cx] then chunks[cx] = {} end
if not chunks[cx][cy] then chunks[cx][cy] = {} end
if not chunks[cx][cy][cz] then
if not chunks[cx][cy][cz] then chunks[cx][cy][cz] = {counter = 1} end
else
chunks[cx][cy][cz].counter = chunks[cx][cy][cz].counter + 1
if chunks[cx][cy][cz].counter >= CS_3D then
current_chunks[#current_chunks+1] = { x = cx, y = cy, z = cz, s = chunks[cx][cy][cz].seed }
-- this chunk shouldn't be overwritten anymore, no need to keep it in memory
chunks[cx][cy][cz] = nil
if next(chunks[cx][cy]) == nil then chunks[cx][cy] = nil end
if next(chunks[cx]) == nil then chunks[cx] = nil end
end
end
vm_context.seed = blockseed + box * 7 + boy * 243 + boz * 11931
if lvm_block > 0 then
vm_context.minp, vm_content.maxp = {x=x, y=y, z=z}, {x=x+LAST_NODE, y=y+LAST_NODE, z=z+LAST_NODE}
for _, v in pairs(lvm_block_queue) do
vm_context = v.f(vm_context)
end
end
if nodes_block > 0 then
current_blocks[#current_blocks+1] = { minp = {x=x, y=y, z=z}, maxp = {x=pos.x+LAST_NODE, y=pos.y+LAST_NODE, z=pos.z+LAST_NODE}, seed = seed }
end
else
blocks[bx][by][bz] = current_mapgen_block_writes
end
z = z + BS
end
if next(blocks[bx][by]) == nil then blocks[bx][by] = nil end
z = z1
y = y + BS
end
if next(blocks[bx]) == nil then blocks[bx] = nil end
y = y1
x = x + BS
end
end
if lvm > 0 then
for _, v in pairs(lvm_chunk_queue) do
vm_context = v.f(vm_context)
end
if vm_context.write then
vm:set_data(data)
end
if vm_context.write_param2 then
vm:set_param2_data(data2)
end
vm:calc_lighting(minp, maxp, vm_context.shadow or true) -- TODO: check boundaries
vm:write_to_map()
vm:update_liquids()
end
for i, b in pairs(current_chunks) do
local cx, cy, cz, seed = b.x, b.y, b.z, b.s
local bx, by, bz = cx * CS + offset, cy * CS + offset, cz * CS + offset
local x, y, z = bx * BS, by * BS, bz * BS
local minp = {x = x, y = y, z = z}
local maxp = {x = x + CS_NODES - 1, y = y + CS_NODES - 1, z = z + CS_NODES - 1}
for _, v in pairs(node_chunk_queue) do
v.f(minp, maxp, seed)
end
current_chunks[i] = nil
end
for i, b in pairs(current_blocks) do
for _, v in pairs(node_block_queue) do
v.f(b.minp, b.maxp, b.seed)
end
current_blocks[i] = nil
end
end)
minetest.register_on_generated = mcl_mapgen.register_chunk_generator
function mcl_mapgen.get_far_node(p)
local p = p
local node = minetest_get_node(p)
if node.name ~= "ignore" then return node end
minetest_get_voxel_manip():read_from_map(p, p)
return minetest_get_node(p)
end
local function coordinate_to_block(x)
return math_floor(x / BS)
end
local function coordinate_to_chunk(x)
return math_floor((coordinate_to_block(x) - offset) / CS)
end
function mcl_mapgen.pos_to_block(pos)
return {
x = coordinate_to_block(pos.x),
y = coordinate_to_block(pos.y),
z = coordinate_to_block(pos.z)
}
end
function mcl_mapgen.pos_to_chunk(pos)
return {
x = coordinate_to_chunk(pos.x),
y = coordinate_to_chunk(pos.y),
z = coordinate_to_chunk(pos.z)
}
end
local k_positive = math.ceil(mcl_mapgen.MAX_LIMIT / mcl_mapgen.CS_NODES)
local k_positive_z = k_positive * 2
local k_positive_y = k_positive_z * k_positive_z
function mcl_mapgen.get_chunk_number(pos) -- unsigned int
local c = mcl_mapgen.pos_to_chunk(pos)
return
(c.y + k_positive) * k_positive_y +
(c.z + k_positive) * k_positive_z +
c.x + k_positive
end
mcl_mapgen.minecraft_height_limit = 256
mcl_mapgen.bedrock_is_rough = normal
--[[ Realm stacking (h is for height)
- Overworld (h>=256)
- Void (h>=1000)
- Realm Barrier (h=11), to allow escaping the End
- End (h>=256)
- Void (h>=1000)
- Nether (h=128)
- Void (h>=1000)
]]
-- Overworld
overworld.min = -62
if superflat then
mcl_mapgen.ground = tonumber(minetest.get_mapgen_setting("mgflat_ground_level")) or 8
overworld.min = ground - 3
end
-- if singlenode then mcl_mapgen.overworld.min = -66 end -- DONT KNOW WHY
overworld.max = mcl_mapgen.EDGE_MAX
overworld.bedrock_min = overworld.min
overworld.bedrock_max = overworld.bedrock_min + (mcl_mapgen.bedrock_is_rough and 4 or 0)
mcl_mapgen.lava = normal
overworld.lava_max = overworld.min + (normal and 10 or 0)
-- The Nether (around Y = -29000)
nether.min = -29067 -- Carefully chosen to be at a mapchunk border
nether.max = nether.min + 128
nether.bedrock_bottom_min = nether.min
nether.bedrock_top_max = nether.max
if not superflat then
nether.bedrock_bottom_max = nether.bedrock_bottom_min + 4
nether.bedrock_top_min = nether.bedrock_top_max - 4
nether.lava_max = nether.min + 31
else
-- Thin bedrock in classic superflat mapgen
nether.bedrock_bottom_max = nether.bedrock_bottom_min
nether.bedrock_top_min = nether.bedrock_top_max
nether.lava_max = nether.min + 2
end
if mcl_mapgen.name == "flat" then
if superflat then
nether.flat_nether_floor = nether.bedrock_bottom_max + 4
nether.flat_nether_ceiling = nether.bedrock_bottom_max + 52
else
nether.flat_nether_floor = nether.lava_max + 4
nether.flat_nether_ceiling = nether.lava_max + 52
end
end
-- The End (surface at ca. Y = -27000)
end_.min = -27073 -- Carefully chosen to be at a mapchunk border
end_.max = overworld.min - 2000
end_.platform_pos = { x = 100, y = end_.min + 74, z = 0 }
-- Realm barrier used to safely separate the End from the void below the Overworld
mcl_mapgen.realm_barrier_overworld_end_max = end_.max
mcl_mapgen.realm_barrier_overworld_end_min = end_.max - 11
-- Use MineClone 2-style dungeons for normal mapgen
mcl_mapgen.dungeons = normal
mcl_mapgen.overworld = overworld
mcl_mapgen.end_ = end_
mcl_mapgen.nether = nether
mcl_mapgen.priorities = priorities

View File

@ -0,0 +1,4 @@
name = mcl_mapgen
author = kay27
description = MineClone 2 MapGen Basic Stuff
depends = mcl_init

View File

@ -5,25 +5,25 @@ local get_connected_players = minetest.get_connected_players
-- For a given position, returns a 2-tuple:
-- 1st return value: true if pos is in void
-- 2nd return value: true if it is in the deadly part of the void
local min1, min2, min3 = mcl_mapgen.overworld.min, mcl_mapgen.end_.min, mcl_mapgen.nether.min
local max1, max2, max3 = mcl_mapgen.overworld.max, mcl_mapgen.end_.max, mcl_mapgen.nether.max+128
function mcl_worlds.is_in_void(pos)
local void =
not ((pos.y < mcl_vars.mg_overworld_max and pos.y > mcl_vars.mg_overworld_min) or
(pos.y < mcl_vars.mg_nether_max+128 and pos.y > mcl_vars.mg_nether_min) or
(pos.y < mcl_vars.mg_end_max and pos.y > mcl_vars.mg_end_min))
local y = pos.y
local void = not ((y < max1 and y > min1) or (y < max2 and y > min2) or (y < max3 and y > min3))
local void_deadly = false
local deadly_tolerance = 64 -- the player must be this many nodes “deep” into the void to be damaged
if void then
-- Overworld → Void → End → Void → Nether → Void
if pos.y < mcl_vars.mg_overworld_min and pos.y > mcl_vars.mg_end_max then
void_deadly = pos.y < mcl_vars.mg_overworld_min - deadly_tolerance
elseif pos.y < mcl_vars.mg_end_min and pos.y > mcl_vars.mg_nether_max+128 then
if y < min1 and y > max2 then
void_deadly = y < min1 - deadly_tolerance
elseif y < min2 and y > max3 then
-- The void between End and Nether. Like usual, but here, the void
-- *above* the Nether also has a small tolerance area, so player
-- can fly above the Nether without getting hurt instantly.
void_deadly = (pos.y < mcl_vars.mg_end_min - deadly_tolerance) and (pos.y > mcl_vars.mg_nether_max+128 + deadly_tolerance)
elseif pos.y < mcl_vars.mg_nether_min then
void_deadly = pos.y < mcl_vars.mg_nether_min - deadly_tolerance
void_deadly = (y < min2 - deadly_tolerance) and (y > max3 + deadly_tolerance)
elseif y < min3 then
void_deadly = y < min3 - deadly_tolerance
end
end
return void, void_deadly
@ -35,15 +35,15 @@ end
-- If the Y coordinate is not located in any dimension, it will return:
-- nil, "void"
function mcl_worlds.y_to_layer(y)
if y >= mcl_vars.mg_overworld_min then
return y - mcl_vars.mg_overworld_min, "overworld"
elseif y >= mcl_vars.mg_nether_min and y <= mcl_vars.mg_nether_max+128 then
return y - mcl_vars.mg_nether_min, "nether"
elseif y >= mcl_vars.mg_end_min and y <= mcl_vars.mg_end_max then
return y - mcl_vars.mg_end_min, "end"
else
return nil, "void"
end
if y >= min1 then
return y - min1, "overworld"
elseif y >= min3 and y <= max3 then
return y - min3, "nether"
elseif y >= min2 and y <= max2 then
return y - min2, "end"
else
return nil, "void"
end
end
local y_to_layer = mcl_worlds.y_to_layer
@ -61,38 +61,38 @@ local pos_to_dimension = mcl_worlds.pos_to_dimension
-- MineClone 2.
-- mc_dimension is one of "overworld", "nether", "end" (default: "overworld").
function mcl_worlds.layer_to_y(layer, mc_dimension)
if mc_dimension == "overworld" or mc_dimension == nil then
return layer + mcl_vars.mg_overworld_min
elseif mc_dimension == "nether" then
return layer + mcl_vars.mg_nether_min
elseif mc_dimension == "end" then
return layer + mcl_vars.mg_end_min
end
if mc_dimension == "overworld" or mc_dimension == nil then
return layer + min1
elseif mc_dimension == "nether" then
return layer + min3
elseif mc_dimension == "end" then
return layer + min2
end
end
-- Takes a position and returns true if this position can have weather
function mcl_worlds.has_weather(pos)
-- Weather in the Overworld and the high part of the void below
return pos.y <= mcl_vars.mg_overworld_max and pos.y >= mcl_vars.mg_overworld_min - 64
-- Weather in the Overworld and the high part of the void below
return pos.y <= max1 and pos.y >= min1 - 64
end
-- Takes a position and returns true if this position can have Nether dust
function mcl_worlds.has_dust(pos)
-- Weather in the Overworld and the high part of the void below
return pos.y <= mcl_vars.mg_nether_max + 138 and pos.y >= mcl_vars.mg_nether_min - 10
-- Weather in the Overworld and the high part of the void below
return pos.y <= max3 + 138 and pos.y >= min3 - 10
end
-- Takes a position (pos) and returns true if compasses are working here
function mcl_worlds.compass_works(pos)
-- It doesn't work in Nether and the End, but it works in the Overworld and in the high part of the void below
local _, dim = mcl_worlds.y_to_layer(pos.y)
if dim == "nether" or dim == "end" then
return false
elseif dim == "void" then
return pos.y <= mcl_vars.mg_overworld_max and pos.y >= mcl_vars.mg_overworld_min - 64
else
return true
end
-- It doesn't work in Nether and the End, but it works in the Overworld and in the high part of the void below
local _, dim = mcl_worlds.y_to_layer(pos.y)
if dim == "nether" or dim == "end" then
return false
elseif dim == "void" then
return pos.y <= max1 and pos.y >= min1 - 64
else
return true
end
end
-- Takes a position (pos) and returns true if clocks are working here
@ -152,4 +152,3 @@ minetest.register_globalstep(function(dtime)
dimtimer = 0
end
end)

View File

@ -1,5 +1,4 @@
name = mcl_worlds
author = Wuzzy
description = Utility functions for worlds and the “dimensions”.
depends = mcl_init
depends = mcl_mapgen

View File

@ -1,5 +1,5 @@
name = mcl_mobs
author = PilzAdam
description = Adds a mob API for mods to add animals or monsters, etc.
depends = mcl_particles
depends = mcl_mapgen, mcl_particles
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience

View File

@ -233,15 +233,15 @@ mobs_mc.override.spawn_height = {
water = tonumber(minetest.settings:get("water_level")) or 0, -- Water level in the Overworld
-- Overworld boundaries (inclusive)
overworld_min = mcl_vars.mg_overworld_min,
overworld_max = mcl_vars.mg_overworld_max,
overworld_min = mcl_mapgen.overworld.min,
overworld_max = mcl_mapgen.overworld.max,
-- Nether boundaries (inclusive)
nether_min = mcl_vars.mg_nether_min,
nether_max = mcl_vars.mg_nether_max,
nether_min = mcl_mapgen.nether.min,
nether_max = mcl_mapgen.nether.max,
-- End boundaries (inclusive)
end_min = mcl_vars.mg_end_min,
end_max = mcl_vars.mg_end_max,
end_min = mcl_mapgen.end_.min,
end_max = mcl_mapgen.end_.max,
}

View File

@ -1,4 +1,4 @@
name = mcl_portals
description = Adds buildable portals to the Nether and End dimensions.
depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn
depends = mcl_mapgen, mcl_nether, mcl_end, mcl_particles, mcl_spawn
optional_depends = awards, doc

View File

@ -4,12 +4,6 @@ local table = table
local vector = vector
local math = math
-- Parameters
--local SPAWN_MIN = mcl_vars.mg_end_min+70
--local SPAWN_MAX = mcl_vars.mg_end_min+98
--local mg_name = minetest.get_mapgen_setting("mg_name")
local function destroy_portal(pos)
local neighbors = {
{ x=1, y=0, z=0 },
@ -182,7 +176,7 @@ function mcl_portals.end_teleport(obj, pos)
-- Teleport to the End at a fixed position and generate a
-- 5×5 obsidian platform below.
local platform_pos = mcl_vars.mg_end_platform_pos
local platform_pos = mcl_mapgen.end_.platform_pos
-- force emerge of target1 area
minetest.get_voxel_manip():read_from_map(platform_pos, platform_pos)
if not minetest.get_node_or_nil(platform_pos) then

View File

@ -19,7 +19,7 @@ local W_MIN, W_MAX = 4, 23
local H_MIN, H_MAX = 5, 23
local N_MIN, N_MAX = 6, (W_MAX-2) * (H_MAX-2)
local TRAVEL_X, TRAVEL_Y, TRAVEL_Z = 8, 1, 8
local LIM_MIN, LIM_MAX = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max
local LIM_MIN, LIM_MAX = mcl_mapgen.EDGE_MIN, mcl_mapgen.EDGE_MAX
local PLAYER_COOLOFF, MOB_COOLOFF = 3, 14 -- for this many seconds they won't teleported again
local TOUCH_CHATTER_TIME = 1 -- prevent multiple teleportation attempts caused by multiple portal touches, for this number of seconds
local CHATTER_US = TOUCH_CHATTER_TIME * 1000000
@ -27,8 +27,8 @@ local DELAY = 3 -- seconds before teleporting in Nether portal in Survival mo
local DISTANCE_MAX = 128
local PORTAL = "mcl_portals:portal"
local OBSIDIAN = "mcl_core:obsidian"
local O_Y_MIN, O_Y_MAX = max(mcl_vars.mg_overworld_min, -31), min(mcl_vars.mg_overworld_max, 2048)
local N_Y_MIN, N_Y_MAX = mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_top_min - H_MIN
local O_Y_MIN, O_Y_MAX = max(mcl_mapgen.overworld.min, -31), min(mcl_mapgen.overworld.max, 2048)
local N_Y_MIN, N_Y_MAX = mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_top_min - H_MIN
-- Alpha and particles
local node_particles_allowed = minetest.settings:get("mcl_node_particles") or "none"
@ -66,7 +66,7 @@ minetest.register_on_shutdown(function()
storage:set_string("nether_exits_keys", minetest.serialize(keys))
end)
local get_node = mcl_vars.get_node
local get_node = mcl_mapgen.get_far_node
local set_node = minetest.set_node
local registered_nodes = minetest.registered_nodes
local is_protected = minetest.is_protected
@ -426,7 +426,7 @@ local function create_portal_2(pos1, name, obj)
end
local exit = build_nether_portal(pos1, W_MIN-2, H_MIN-2, orientation, name)
finalize_teleport(obj, exit)
local cn = mcl_vars.get_chunk_number(pos1)
local cn = mcl_mapgen.get_chunk_number(pos1)
chunks[cn] = nil
if queue[cn] then
for next_obj, _ in pairs(queue[cn]) do
@ -440,9 +440,9 @@ end
local function get_lava_level(pos, pos1, pos2)
if pos.y > -1000 then
return max(min(mcl_vars.mg_lava_overworld_max, pos2.y-1), pos1.y+1)
return max(min(mcl_mapgen.overworld.lava_max, pos2.y-1), pos1.y+1)
end
return max(min(mcl_vars.mg_lava_nether_max, pos2.y-1), pos1.y+1)
return max(min(mcl_mapgen.nether.lava_max, pos2.y-1), pos1.y+1)
end
local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
@ -521,7 +521,7 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
end
local function create_portal(pos, limit1, limit2, name, obj)
local cn = mcl_vars.get_chunk_number(pos)
local cn = mcl_mapgen.get_chunk_number(pos)
if chunks[cn] then
local q = queue[cn] or {}
q[obj] = true
@ -534,8 +534,8 @@ local function create_portal(pos, limit1, limit2, name, obj)
-- so we'll emerge single chunk only: 5x5x5 blocks, 80x80x80 nodes maximum
-- and maybe one more chunk from below if (SCAN_2_MAP_CHUNKS = true)
local pos1 = add(mul(mcl_vars.pos_to_chunk(pos), mcl_vars.chunk_size_in_nodes), mcl_vars.central_chunk_offset_in_nodes)
local pos2 = add(pos1, mcl_vars.chunk_size_in_nodes - 1)
local pos1 = add(mul(mcl_mapgen.pos_to_chunk(pos), mcl_mapgen.CS_NODES), mcl_mapgen.OFFSET_NODES)
local pos2 = add(pos1, mcl_mapgen.CS_NODES - 1)
if not SCAN_2_MAP_CHUNKS then
if limit1 and limit1.x and limit1.y and limit1.z then
@ -549,8 +549,8 @@ local function create_portal(pos, limit1, limit2, name, obj)
end
-- Basically the copy of code above, with minor additions to continue the search in single additional chunk below:
local next_chunk_1 = {x = pos1.x, y = pos1.y - mcl_vars.chunk_size_in_nodes, z = pos1.z}
local next_chunk_2 = add(next_chunk_1, mcl_vars.chunk_size_in_nodes - 1)
local next_chunk_1 = {x = pos1.x, y = pos1.y - mcl_mapgen.CS_NODES, z = pos1.z}
local next_chunk_2 = add(next_chunk_1, mcl_mapgen.CS_NODES - 1)
local next_pos = {x = pos.x, y=max(next_chunk_2.y, limit1.y), z = pos.z}
if limit1 and limit1.x and limit1.y and limit1.z then
pos1 = {x = max(min(limit1.x, pos.x), pos1.x), y = max(min(limit1.y, pos.y), pos1.y), z = max(min(limit1.z, pos.z), pos1.z)}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
name = mcl_biomes
author = maikerumine
description = Adds the various biomes and biome-related things for non-v6 map generators.
depends = mcl_init, mcl_mapgen_core, mcl_core, mcl_worlds, mcl_farming, mcl_flowers, mcl_end, mcl_ocean
depends = mcl_mapgen, mcl_mapgen_core, mcl_core, mcl_worlds, mcl_farming, mcl_flowers, mcl_end, mcl_ocean

View File

@ -2,10 +2,8 @@
mcl_dungeons = {}
local mg_name = minetest.get_mapgen_setting("mg_name")
-- Are dungeons disabled?
if mcl_vars.mg_dungeons == false or mg_name == "singlenode" then
if mcl_mapgen.dungeons == false or mcl_mapgen.singlenode == true then
return
end
@ -16,7 +14,6 @@ local swap_node = minetest.swap_node
local set_node = minetest.set_node
local dir_to_facedir = minetest.dir_to_facedir
local get_meta = minetest.get_meta
local emerge_area = minetest.emerge_area
--vector
local vector_add = vector.add
@ -32,15 +29,15 @@ local math_max = math.max
local math_ceil = math.ceil
--custom mcl_vars
local get_node = mcl_vars.get_node
local get_node = mcl_mapgen.get_far_node
local min_y = math_max(mcl_vars.mg_overworld_min, mcl_vars.mg_bedrock_overworld_max) + 1
local max_y = mcl_vars.mg_overworld_max - 1
local min_y = math_max(mcl_mapgen.overworld.min, mcl_mapgen.overworld.bedrock_max) + 1
local max_y = mcl_mapgen.overworld.max - 1
-- Calculate the number of dungeon spawn attempts
-- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks).
-- Minetest chunks don't have this size, so scale the number accordingly.
local attempts = math_ceil(((mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE) ^ 3) / 8192) -- 63 = 80*80*80/8192
local attempts = math_ceil((mcl_mapgen.CS_NODES ^ 3) / 8192) -- 63 = 80*80*80/8192
local dungeonsizes = {
{ x=5, y=4, z=5},
@ -63,12 +60,14 @@ local surround_vectors = {
{ x=0, y=0, z=1 },
}
local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
if calls_remaining >= 1 then return end
--local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- if calls_remaining >= 1 then return end
-- local p1, _, dim, pr = param.p1, param.p2, param.dim, param.pr
-- local check = not (param.dontcheck or false)
local function spawn_dungeon(p1, p2, dim, pr, dontcheck)
local p1, _, dim, pr = param.p1, param.p2, param.dim, param.pr
local x, y, z = p1.x, p1.y, p1.z
local check = not (param.dontcheck or false)
local check = not (dontcheck or false)
-- Check floor and ceiling: Must be *completely* solid
local y_floor = y
@ -358,7 +357,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
}
-- Bonus loot for v6 mapgen: Otherwise unobtainable saplings.
if mg_name == "v6" then
if mcl_mapgen.v6 then
table_insert(loottable, {
stacks_min = 1,
stacks_max = 3,
@ -403,8 +402,7 @@ local function dungeons_nodes(minp, maxp, blockseed)
local z = pr:next(minp.z, maxp.z-dim.z-1)
local p1 = {x=x,y=y,z=z}
local p2 = {x = x+dim.x+1, y = y+dim.y+1, z = z+dim.z+1}
minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr})
spawn_dungeon(p1, p2, dim, pr)
end
end
@ -412,8 +410,7 @@ function mcl_dungeons.spawn_dungeon(p1, _, pr)
if not p1 or not pr or not p1.x or not p1.y or not p1.z then return end
local dim = dungeonsizes[pr:next(1, #dungeonsizes)]
local p2 = {x = p1.x+dim.x+1, y = p1.y+dim.y+1, z = p1.z+dim.z+1}
minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr, dontcheck=true})
spawn_dungeon(p1, p2, dim, pr, true)
end
mcl_mapgen_core.register_generator("dungeons", nil, dungeons_nodes, 999999)
mcl_mapgen.register_chunk_generator(dungeons_nodes, mcl_mapgen.priorities.DUNGEONS)

View File

@ -1,4 +1,4 @@
name = mcl_dungeons
author = Wuzzy
description = Generates random dungeons in the world
depends = mcl_init, mcl_core, mcl_chests, mcl_mobs, mcl_mobspawners, mcl_mapgen_core, mobs_mc
depends = mcl_mapgen, mcl_core, mcl_chests, mcl_mobs, mcl_mobspawners, mcl_mapgen_core, mobs_mc

View File

@ -1,8 +1,4 @@
mcl_mapgen_core = {}
local registered_generators = {}
local lvm, nodes, param2 = 0, 0, 0
local lvm_buffer = {}
--
-- Aliases for map generator outputs
@ -101,8 +97,8 @@ for s=1, #specialstones do
clust_scarcity = 15*15*15,
clust_num_ores = 33,
clust_size = 5,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_vars.mg_overworld_max,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_mapgen.overworld.max,
noise_params = {
offset = 0,
scale = 1,
@ -121,8 +117,8 @@ for s=1, #specialstones do
clust_scarcity = 10*10*10,
clust_num_ores = 58,
clust_size = 7,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_vars.mg_overworld_max,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_mapgen.overworld.max,
noise_params = {
offset = 0,
scale = 1,
@ -146,8 +142,8 @@ minetest.register_ore({
clust_scarcity = 15*15*15,
clust_num_ores = 33,
clust_size = 4,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_vars.mg_overworld_max,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_mapgen.overworld.max,
noise_params = {
offset = 0,
scale = 1,
@ -168,7 +164,7 @@ minetest.register_ore({
clust_scarcity = 14*14*14,
clust_num_ores = 33,
clust_size = 5,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(111),
noise_params = {
offset = 0,
@ -195,7 +191,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 525*3,
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(50),
})
minetest.register_ore({
@ -205,7 +201,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 510*3,
clust_num_ores = 8,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(50),
})
minetest.register_ore({
@ -215,7 +211,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 500*3,
clust_num_ores = 12,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(50),
})
@ -293,7 +289,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 830,
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(39),
})
minetest.register_ore({
@ -319,7 +315,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 4775,
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(30),
})
minetest.register_ore({
@ -329,7 +325,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 6560,
clust_num_ores = 7,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(30),
})
@ -357,7 +353,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 10000,
clust_num_ores = 4,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(12),
})
minetest.register_ore({
@ -367,7 +363,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 5000,
clust_num_ores = 2,
clust_size = 2,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(12),
})
minetest.register_ore({
@ -377,7 +373,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 10000,
clust_num_ores = 8,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(12),
})
@ -415,7 +411,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 500,
clust_num_ores = 4,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(13),
})
minetest.register_ore({
@ -425,7 +421,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 800,
clust_num_ores = 7,
clust_size = 4,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(13),
})
@ -466,7 +462,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
clust_scarcity = 14340,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_vars.mg_overworld_min,
y_min = mcl_mapgen.overworld.min,
y_max = mcl_worlds.layer_to_y(29),
})
-- Rare spawn
@ -682,7 +678,7 @@ local function register_mgv6_decorations()
persist = 0.6
},
y_min = 4,
y_max = mcl_vars.mg_overworld_max,
y_max = mcl_mapgen.overworld.max,
decoration = "mcl_core:cactus",
height = 1,
height_max = 3,
@ -702,7 +698,7 @@ local function register_mgv6_decorations()
persist = 0.7
},
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
y_max = mcl_mapgen.overworld.max,
decoration = "mcl_core:reeds",
height = 1,
height_max = 3,
@ -732,7 +728,7 @@ local function register_mgv6_decorations()
persist = 0.0,
},
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
y_max = mcl_mapgen.overworld.max,
})
-- Large ferns
@ -761,7 +757,7 @@ local function register_mgv6_decorations()
persist = 0.66,
},
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
y_max = mcl_mapgen.overworld.max,
})
-- Large flowers
@ -1010,7 +1006,7 @@ local function register_mgv6_decorations()
persist = 0.666
},
flags = "force_placement",
y_min = mcl_vars.mg_lava_overworld_max + 5,
y_min = mcl_mapgen.overworld.lava_max + 5,
y_max = -20,
})
@ -1042,7 +1038,7 @@ local function register_mgv6_decorations()
persist = 0.6
},
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
y_max = mcl_mapgen.overworld.max,
decoration = mushrooms[m],
spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree", },
num_spawn_by = 1,
@ -1063,7 +1059,7 @@ local function register_mgv6_decorations()
persist = 0.6
},
y_min = 4,
y_max = mcl_vars.mg_overworld_max,
y_max = mcl_mapgen.overworld.max,
decoration = "mcl_core:deadbush",
})
@ -1072,7 +1068,7 @@ local function register_mgv6_decorations()
offset = 0
end
if y_max == nil then
y_max = mcl_vars.mg_overworld_max
y_max = mcl_mapgen.overworld.max
end
minetest.register_decoration({
deco_type = "simple",
@ -1115,7 +1111,7 @@ local function register_mgv6_decorations()
sidelen = 16,
fill_ratio = 11.0, -- complete coverage
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
y_max = mcl_mapgen.overworld.max,
decoration = "mcl_core:snow",
})
@ -1194,11 +1190,14 @@ local perlin_structures
local perlin_vines, perlin_vines_fine, perlin_vines_upwards, perlin_vines_length, perlin_vines_density
local perlin_clay
local function generate_clay(minp, maxp, blockseed, voxelmanip_data, voxelmanip_area, lvm_used)
-- Generate Clay
mcl_mapgen.register_chunk_generator_lvm(function(c)
local minp, maxp, blockseed, voxelmanip_data, voxelmanip_area, lvm_used = c.minp, c.maxp, c.blockseed, c.data, c.area, c.write or false
-- TODO: Make clay generation reproducible for same seed.
if maxp.y < -5 or minp.y > 0 then
return lvm_used
return c
end
minetest.log("warning", "CLAY!")
local pr = PseudoRandom(blockseed)
@ -1244,8 +1243,9 @@ local function generate_clay(minp, maxp, blockseed, voxelmanip_data, voxelmanip_
end
end
end
return lvm_used
end
c.write = lvm_used
return c
end)
local function generate_end_exit_portal(pos)
local obj = minetest.add_entity(vector.add(pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon")
@ -1724,7 +1724,7 @@ local function generate_underground_mushrooms(minp, maxp, seed)
local pr_shroom = PseudoRandom(seed-24359)
-- Generate rare underground mushrooms
-- TODO: Make them appear in groups, use Perlin noise
local min, max = mcl_vars.mg_lava_overworld_max + 4, 0
local min, max = mcl_mapgen.overworld.lava_max + 4, 0
if minp.y > max or maxp.y < min then
return
end
@ -1757,7 +1757,7 @@ end
local function generate_nether_decorations(minp, maxp, seed)
local pr_nether = PseudoRandom(seed+667)
if minp.y > mcl_vars.mg_nether_max or maxp.y < mcl_vars.mg_nether_min then
if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then
return
end
@ -1819,92 +1819,6 @@ local function generate_nether_decorations(minp, maxp, seed)
end
minetest.register_on_generated(function(minp, maxp, blockseed)
minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp))
local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z}
if lvm > 0 then
local lvm_used, shadow = false, false
local lb2 = {} -- param2
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z}
local data2
local data = vm:get_data(lvm_buffer)
if param2 > 0 then
data2 = vm:get_param2_data(lb2)
end
local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
for _, rec in pairs(registered_generators) do
if rec.vf then
local lvm_used0, shadow0 = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed)
if lvm_used0 then
lvm_used = true
end
if shadow0 then
shadow = true
end
end
end
if lvm_used then
-- Write stuff
vm:set_data(data)
if param2 > 0 then
vm:set_param2_data(data2)
end
vm:calc_lighting(p1, p2, shadow)
vm:write_to_map()
vm:update_liquids()
end
end
if nodes > 0 then
for _, rec in pairs(registered_generators) do
if rec.nf then
rec.nf(p1, p2, blockseed)
end
end
end
mcl_vars.add_chunk(minp)
end)
function minetest.register_on_generated(node_function)
mcl_mapgen_core.register_generator("mod_"..tostring(#registered_generators+1), nil, node_function)
end
function mcl_mapgen_core.register_generator(id, lvm_function, node_function, priority, needs_param2)
if not id then return end
local priority = priority or 5000
if lvm_function then lvm = lvm + 1 end
if lvm_function then nodes = nodes + 1 end
if needs_param2 then param2 = param2 + 1 end
local new_record = {
i = priority,
vf = lvm_function,
nf = node_function,
needs_param2 = needs_param2,
}
registered_generators[id] = new_record
table.sort(registered_generators, function(a, b)
return (a.i < b.i) or ((a.i == b.i) and a.vf and (b.vf == nil))
end)
end
function mcl_mapgen_core.unregister_generator(id)
if not registered_generators[id] then return end
local rec = registered_generators[id]
registered_generators[id] = nil
if rec.vf then lvm = lvm - 1 end
if rec.nf then nodes = nodes - 1 end
if rec.needs_param2 then param2 = param2 - 1 end
--if rec.needs_level0 then level0 = level0 - 1 end
end
-- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc.
-- Also perform some basic node replacements.
@ -1981,29 +1895,32 @@ local function set_layers(data, area, content_id, check, min, max, minp, maxp, l
end
-- Below the bedrock, generate air/void
local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
local biomemap --ymin, ymax
local function basic(c)
local vm, data, emin, emax, area, minp, maxp, blockseed = c.vm, c.data, c.emin, c.emax, c.area, c.minp, c.maxp, c.blockseed
c.data2 = c.data2 or vm:get_data_param2(lvm_buffer_param2)
local data2 = c.data2
local lvm_used = false
local pr = PseudoRandom(blockseed)
-- The Void below the Nether:
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mapgen_edge_min , mcl_vars.mg_nether_min -1, minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min -1, minp, maxp, lvm_used, pr)
-- [[ THE NETHER: mcl_vars.mg_nether_min mcl_vars.mg_nether_max ]]
-- [[ THE NETHER: mcl_mapgen.nether.min mcl_mapgen.nether.max ]]
-- The Air on the Nether roof, https://git.minetest.land/MineClone2/MineClone2/issues/1186
lvm_used = set_layers(data, area, c_air , nil, mcl_vars.mg_nether_max +1, mcl_vars.mg_nether_max + 128 , minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_air , nil, mcl_mapgen.nether.max +1, mcl_mapgen.nether.max + 128 , minp, maxp, lvm_used, pr)
-- The Void above the Nether below the End:
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_nether_max + 128 +1, mcl_vars.mg_end_min -1, minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.nether.max + 128 +1, mcl_mapgen.end_.min -1, minp, maxp, lvm_used, pr)
-- [[ THE END: mcl_vars.mg_end_min mcl_vars.mg_end_max ]]
-- [[ THE END: mcl_mapgen.end_.min mcl_mapgen.end_.max ]]
-- The Void above the End below the Realm barrier:
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_end_max +1, mcl_vars.mg_realm_barrier_overworld_end_min-1, minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.end_.max +1, mcl_vars.mg_realm_barrier_overworld_end_min-1, minp, maxp, lvm_used, pr)
-- Realm barrier between the Overworld void and the End
lvm_used = set_layers(data, area, c_realm_barrier, nil, mcl_vars.mg_realm_barrier_overworld_end_min , mcl_vars.mg_realm_barrier_overworld_end_max , minp, maxp, lvm_used, pr)
-- The Void above Realm barrier below the Overworld:
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_realm_barrier_overworld_end_max+1, mcl_vars.mg_overworld_min -1, minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_realm_barrier_overworld_end_max+1, mcl_mapgen.overworld.min -1, minp, maxp, lvm_used, pr)
if mg_name ~= "singlenode" then
@ -2019,14 +1936,15 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- Big lava seas by replacing air below a certain height
if mcl_vars.mg_lava then
lvm_used = set_layers(data, area, c_lava, c_air, mcl_vars.mg_overworld_min, mcl_vars.mg_lava_overworld_max, minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_nether_lava, c_air, mcl_vars.mg_nether_min, mcl_vars.mg_lava_nether_max, minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_lava, c_air, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, minp, maxp, lvm_used, pr)
lvm_used = set_layers(data, area, c_nether_lava, c_air, mcl_mapgen.nether.min, mcl_vars.mg_lava_nether_max, minp, maxp, lvm_used, pr)
end
-- Clay, vines, cocoas
lvm_used = generate_clay(minp, maxp, blockseed, data, area, lvm_used)
biomemap = minetest.get_mapgen_object("biomemap")
c.biomemap = c.biomemap or minetest.get_mapgen_object("biomemap")
lvm_used = generate_tree_decorations(minp, maxp, blockseed, data, data2, area, biomemap, lvm_used, pr)
----- Interactive block fixing section -----
@ -2035,7 +1953,7 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- Snow and sand fixes. This code implements snow consistency
-- and fixes floating sand and cut plants.
-- A snowy grass block must be below a top snow or snow block at all times.
if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
if minp.y <= mcl_mapgen.overworld.max and maxp.y >= mcl_mapgen.overworld.min then
-- v6 mapgen:
if mg_name == "v6" then
@ -2101,7 +2019,7 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- Nether block fixes:
-- * Replace water with Nether lava.
-- * Replace stone, sand dirt in v6 so the Nether works in v6.
elseif emin.y <= mcl_vars.mg_nether_max and emax.y >= mcl_vars.mg_nether_min then
elseif emin.y <= mcl_mapgen.nether.max and emax.y >= mcl_mapgen.nether.min then
if mg_name == "v6" then
local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
for n=1, #nodes do
@ -2128,7 +2046,7 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- * Replace water with end stone or air (depending on height).
-- * Remove stone, sand, dirt in v6 so our End map generator works in v6.
-- * Generate spawn platform (End portal destination)
elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then
elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then
local nodes
if mg_name == "v6" then
nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
@ -2170,11 +2088,11 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- Final hackery: Set sun light level in the End.
-- -26912 is at a mapchunk border.
local shadow = true
if minp.y >= -26912 and maxp.y <= mcl_vars.mg_end_max then
if minp.y >= -26912 and maxp.y <= mcl_mapgen.end_.max then
vm:set_lighting({day=15, night=15})
lvm_used = true
end
if minp.y >= mcl_vars.mg_end_min and maxp.y <= -26911 then
if minp.y >= mcl_mapgen.end_.min and maxp.y <= -26911 then
shadow = false
lvm_used = true
end
@ -2189,5 +2107,5 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
return lvm_used, shadow
end
mcl_mapgen_core.register_generator("main", basic, nil, 1, true)
mcl_mapgen.register_chunk_generator_lvm(basic, 1)

View File

@ -1,5 +1,5 @@
name = mcl_mapgen_core
author = Wuzzy
description = The core of the MCL2 mapgen
depends = mcl_init, mcl_core, biomeinfo, mcl_worlds, mcl_cocoas, mcl_sponges, mcl_ocean, mcl_stairs, mcl_monster_eggs, mcl_structures
depends = mcl_mapgen, mcl_core, biomeinfo, mcl_worlds, mcl_cocoas, mcl_sponges, mcl_ocean, mcl_stairs, mcl_monster_eggs, mcl_structures
optional_depends = mclx_core

View File

@ -0,0 +1,97 @@
-- Check it:
-- seed 1, v7 mapgen
-- /teleport 14958,8,11370
local mcl_mapgen_get_far_node = mcl_mapgen.get_far_node
local minetest_log = minetest.log
local minetest_place_schematic = minetest.place_schematic
local minetest_pos_to_string = minetest.pos_to_string
local minetest_swap_node = minetest.swap_node
local path = minetest.get_modpath("mcl_ocean_monument") .. "/schematics/ocean_monument.mts"
local water = "mcl_core:water_source"
local air = "air"
local ice = "mcl_core:ice"
local leg_materials = {
"mcl_ocean:prismarine_brick",
"mcl_ocean:prismarine",
}
local what_we_can_replace_by_legs = {
water,
air,
"mcl_core:water_flowing",
"mcl_core:stone",
}
local leg_search_quick_index = {}
for _, v in pairs(leg_materials) do
leg_search_quick_index[v] = true
end
local leg_replace_quick_index = {}
for _, v in pairs(what_we_can_replace_by_legs) do
leg_replace_quick_index[v] = true
end
local y_wanted = mcl_mapgen.OFFSET_NODES -- supposed to be -32
local y_bottom = mcl_mapgen.overworld.min -- -62
mcl_mapgen.register_chunk_generator(function(minp, maxp, seed)
local minp = minp
local y = minp.y
if y ~= y_wanted then return end
local x, z = minp.x, minp.z
local pr = PseudoRandom(seed)
-- scan the ocean - it should be the ocean:
for i = 1, pr:next(10, 100) do
local pos = {x = pr:next(15, 64) + x, y = pr:next(0, 25) - 25, z = pr:next(15, 64) + z}
local node_name = mcl_mapgen_get_far_node(pos).name
if node_name ~= water then return end
end
-- scan nodes above water level - there should be the air:
for i = 1, pr:next(10, 100) do
local pos = {x = pr:next(0, 79) + x, y = 2, z = pr:next(0,79) + z}
local node_name = mcl_mapgen_get_far_node(pos).name
if node_name ~= air then return end
end
-- scan ocean surface - allow only water and ice:
for i = 1, pr:next(10,100) do
local pos = {x=pr:next(0, 79)+x, y=1, z=pr:next(0,79)+z}
local node_name = mcl_mapgen_get_far_node(pos).name
if node_name ~= water and node_name ~= ice then return end
end
-- random rotation:
local rotation = pr:next(0, 3)
local rotation_str = tostring(rotation * 90)
minetest_place_schematic(minp, path, rotation_str, nil, true)
-- search prismarine legs at base level and continue them up to the bottom:
for x = x, maxp.x do
for z = z, maxp.z do
local pos = {x = x, y = y, z = z}
local node_name = mcl_mapgen_get_far_node(pos).name
if leg_search_quick_index[node_name] then
local node_leg = {name = node_name}
for y = y - 1, y_bottom, -1 do
pos.y = y
local next_name = mcl_mapgen_get_far_node(pos).name
if not leg_replace_quick_index[next_name] then
break
end
minetest_swap_node(pos, node_leg)
end
end
end
end
minetest_log("action", "[mcl_ocean_monument] Placed at " .. minetest_pos_to_string(minp) .. ", " .. rotation_str .. " deg.")
end, mcl_mapgen.priorities.OCEAN_MONUMENT)

View File

@ -0,0 +1,4 @@
name = mcl_ocean_monument
author = TrashPanda
description = Adds Ocean Monument, https://git.minetest.land/MineClone2/MineClone2/issues/958#issuecomment-14102
depends = mcl_mapgen, mcl_structures

View File

@ -18,8 +18,7 @@ local stronghold_rings = {
local strongholds = {}
local strongholds_inited = false
local mg_name = minetest.get_mapgen_setting("mg_name")
local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true"
local superflat = mcl_mapgen.superflat
-- Determine the stronghold positions and store them into the strongholds table.
-- The stronghold positions are based on the world seed.
@ -30,7 +29,7 @@ local function init_strongholds()
return
end
-- Don't generate strongholds in singlenode
if mg_name == "singlenode" then
if mcl_mapgen.singlenode then
strongholds_inited = true
return
end
@ -47,9 +46,9 @@ local function init_strongholds()
local dist = pr:next(ring.min, ring.max)
local y
if superflat then
y = mcl_vars.mg_bedrock_overworld_max + 3
y = mcl_mapgen.overworld.bedrock_max + 3
else
y = pr:next(mcl_vars.mg_bedrock_overworld_max+1, mcl_vars.mg_overworld_min+48)
y = pr:next(mcl_mapgen.overworld.bedrock_max+1, mcl_mapgen.overworld.bedrock_min+48)
end
local pos = { x = math.cos(angle) * dist, y = y, z = math.sin(angle) * dist }
pos = vector.round(pos)
@ -66,8 +65,10 @@ local function init_strongholds()
strongholds_inited = true
end
init_strongholds()
-- Stronghold generation for register_on_generated.
local function generate_strongholds(minp, maxp, blockseed)
mcl_mapgen.register_chunk_generator(function(minp, maxp, blockseed)
local pr = PseudoRandom(blockseed)
for s=1, #strongholds do
if not strongholds[s].generated then
@ -99,8 +100,4 @@ local function generate_strongholds(minp, maxp, blockseed)
end
end
end
end
init_strongholds()
mcl_mapgen_core.register_generator("strongholds", nil, generate_strongholds, 999999)
end, mcl_mapgen.priorities.STRONGHOLDS)

View File

@ -38,7 +38,9 @@ function mcl_structures.place_schematic(pos, schematic, rotation, replacements,
local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1}
minetest.log("verbose", "[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param}
minetest.emerge_area(p1, p2, ecb_place, param)
-- minetest.emerge_area(p1, p2, ecb_place, param)
-- TODO: Make it better
ecb_place(0, 0, 0, param)
end
end
@ -115,14 +117,14 @@ function mcl_structures.generate_igloo(pos, rotation, pr)
if r == 1 then
-- Select basement depth
local dim = mcl_worlds.pos_to_dimension(pos)
--local buffer = pos.y - (mcl_vars.mg_lava_overworld_max + 10)
--local buffer = pos.y - (mcl_mapgen.overworld.lava_max + 10)
local buffer
if dim == "nether" then
buffer = pos.y - (mcl_vars.mg_lava_nether_max + 10)
elseif dim == "end" then
buffer = pos.y - (mcl_vars.mg_end_min + 1)
elseif dim == "overworld" then
buffer = pos.y - (mcl_vars.mg_lava_overworld_max + 10)
buffer = pos.y - (mcl_mapgen.overworld.lava_max + 10)
else
return success
end
@ -284,7 +286,7 @@ local function hut_placement_callback(p1, p2, size, orientation, pr)
if not p1 or not p2 then return end
local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree")
for i = 1, #legs do
while minetest.get_item_group(mcl_vars.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do
while minetest.get_item_group(mcl_mapgen.get_far_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do
legs[i].y = legs[i].y - 1
minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2})
end

View File

@ -88,7 +88,7 @@ function settlements.create_site_plan(maxp, minp, pr)
-- find center_surface of chunk
local center_surface , surface_material = settlements.find_surface(center, true)
local chunks = {}
chunks[mcl_vars.get_chunk_number(center)] = true
chunks[mcl_mapgen.get_chunk_number(center)] = true
-- go build settlement around center
if not center_surface then return false end
@ -124,7 +124,7 @@ function settlements.create_site_plan(maxp, minp, pr)
ptx = settlements.round(ptx, 0)
ptz = settlements.round(ptz, 0)
local pos1 = { x=ptx, y=center_surface.y+50, z=ptz}
local chunk_number = mcl_vars.get_chunk_number(pos1)
local chunk_number = mcl_mapgen.get_chunk_number(pos1)
local pos_surface, surface_material
if chunks[chunk_number] then
pos_surface, surface_material = settlements.find_surface(pos1)

View File

@ -1,6 +1,8 @@
settlements = {}
settlements.modpath = minetest.get_modpath(minetest.get_current_modname())
local minetest_get_spawn_level = minetest.get_spawn_level
dofile(settlements.modpath.."/const.lua")
dofile(settlements.modpath.."/utils.lua")
dofile(settlements.modpath.."/foundation.lua")
@ -53,6 +55,7 @@ end
-- on map generation, try to build a settlement
--
local function build_a_settlement(minp, maxp, blockseed)
minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp) .. ", blockseed = " .. tostring(blockseed))
local pr = PseudoRandom(blockseed)
-- fill settlement_info with buildings and their data
@ -69,29 +72,38 @@ local function build_a_settlement(minp, maxp, blockseed)
settlements.place_schematics(settlement_info, pr)
end
local function ecb_village(blockpos, action, calls_remaining, param)
if calls_remaining >= 1 then return end
local minp, maxp, blockseed = param.minp, param.maxp, param.blockseed
build_a_settlement(minp, maxp, blockseed)
end
-- Disable natural generation in singlenode.
local mg_name = minetest.get_mapgen_setting("mg_name")
if mg_name ~= "singlenode" then
mcl_mapgen_core.register_generator("villages", nil, function(minp, maxp, blockseed)
mcl_mapgen.register_chunk_generator(function(minp, maxp, blockseed)
-- local str1 = (maxp.y >= 0 and blockseed % 77 == 17) and "YES" or "no"
-- minetest.log("action","[mcl_villages] " .. str1 .. ": minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. tostring(blockseed))
-- don't build settlement underground
if maxp.y < 0 then return end
-- randomly try to build settlements
if blockseed % 77 ~= 17 then return end
-- needed for manual and automated settlement building
-- don't build settlements on (too) uneven terrain
--local heightmap = minetest.get_mapgen_object("heightmap")
local height_difference = settlements.evaluate_heightmap()
-- lame and quick replacement of `heightmap` by kay27 - we maybe need to restore `heightmap` analysis if there will be a way for the engine to avoid cavegen conflicts:
--------------------------------------------------------------------------
local height_difference, min, max
local pr1=PseudoRandom(blockseed)
for i=1,pr1:next(5,10) do
local x = pr1:next(0, 40) + minp.x + 19
local z = pr1:next(0, 40) + minp.z + 19
local y = minetest_get_spawn_level(x, z)
if not y then return end
if y < (min or y+1) then min = y end
if y > (max or y-1) then max = y end
end
height_difference = max - min + 1
--------------------------------------------------------------------------
if height_difference > max_height_difference then return end
local param={minp=vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed}
minetest.emerge_area(minp, maxp, ecb_village, param)
end)
build_a_settlement(minp, maxp, blockseed)
end, mcl_mapgen.priorities.VILLAGES)
end
-- manually place villages
if minetest.is_creative_enabled("") then

View File

@ -1,4 +1,4 @@
local get_node = mcl_vars.get_node
local get_node = mcl_mapgen.get_far_node
-------------------------------------------------------------------------------
-- function to copy tables
@ -207,44 +207,6 @@ function shuffle(tbl, pr)
return table
end
-------------------------------------------------------------------------------
-- evaluate heightmap
-------------------------------------------------------------------------------
function settlements.evaluate_heightmap()
local heightmap = minetest.get_mapgen_object("heightmap")
-- max height and min height, initialize with impossible values for easier first time setting
local max_y = -50000
local min_y = 50000
-- only evaluate the center square of heightmap 40 x 40
local square_start = 1621
local square_end = 1661
for j = 1 , 40, 1 do
for i = square_start, square_end, 1 do
-- skip buggy heightmaps, return high value
if heightmap[i] == -31000 or heightmap[i] == 31000 then
return max_height_difference + 1
end
if heightmap[i] < min_y then
min_y = heightmap[i]
end
if heightmap[i] > max_y then
max_y = heightmap[i]
end
end
-- set next line
square_start = square_start + 80
square_end = square_end + 80
end
-- return the difference between highest and lowest pos in chunk
local height_diff = max_y - min_y
-- filter buggy heightmaps
if height_diff <= 1 then
return max_height_difference + 1
end
-- debug info
settlements.debug("heightdiff ".. height_diff)
return height_diff
end
-------------------------------------------------------------------------------
-- Set array to list
-- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list
-------------------------------------------------------------------------------

View File

@ -19,8 +19,7 @@ end
local probability_railcaves_in_mapchunk = P(0.33333)
setting = tonumber(minetest.settings:get("tsm_railcorridors_probability_railcaves_in_mapchunk"))
-- Extra check to prevent mod griefing in singlenode, mcimported worlds.
local mg_name = minetest.get_mapgen_setting("mg_name")
if mg_name == "singlenode" then
if mcl_mapgen.singlenode then
probability_railcaves_in_mapchunk = P(0)
elseif setting then
probability_railcaves_in_mapchunk = P(setting)
@ -96,10 +95,10 @@ end
-- Max. and min. heights between rail corridors are generated
local height_min
if mcl_vars.mg_lava then
height_min = mcl_vars.mg_lava_overworld_max + 2
if mcl_mapgen.lava then
height_min = mcl_mapgen.overworld.lava_max + 2
else
height_min = mcl_vars.mg_bedrock_overworld_max + 2
height_min = mcl_mapgen.overworld.bedrock_max + 2
end
local height_max = mcl_worlds.layer_to_y(60)
@ -1093,7 +1092,7 @@ local function create_corridor_system(main_cave_coords)
end
-- The rail corridor algorithm starts here
mcl_mapgen_core.register_generator("railcorridors", nil, function(minp, maxp, blockseed, _pr)
mcl_mapgen.register_chunk_generator(function(minp, maxp, blockseed, _pr)
-- We re-init the randomizer for every mapchunk as we start generating in the middle of each mapchunk.
-- We can't use the mapgen seed as this would make the algorithm depending on the order the mapchunk generate.
InitRandomizer(blockseed)

View File

@ -8,33 +8,6 @@ minetest.register_craft({
recipe = {"mcl_core:iron_ingot", "mcl_core:stick", "group:wood", "mcl_chests:chest"},
})
minetest.register_craft({
output = "mcl_sponges:sponge",
recipe = {
{ "mcl_farming:hay_block", "mcl_farming:hay_block", "mcl_farming:hay_block" },
{ "mcl_farming:hay_block", "mcl_core:goldblock", "mcl_farming:hay_block" },
{ "mcl_farming:hay_block", "mcl_farming:hay_block", "mcl_farming:hay_block" },
}
})
minetest.register_craft({
output = "mcl_ocean:prismarine_shard",
recipe = {
{ "mcl_core:glass_cyan", },
}
})
minetest.register_craft({
type = "shapeless",
output = "mcl_ocean:prismarine_crystals",
recipe = {
"mcl_ocean:prismarine_shard",
"mcl_ocean:prismarine_shard",
"mcl_ocean:prismarine_shard",
"mcl_core:gold_ingot",
},
})
minetest.register_craft({
output = "mcl_armor:helmet_chain",
recipe = {

View File

@ -81,7 +81,7 @@ local dir_step = storage:get_int("mcl_spawn_dir_step") or 0
local dir_ind = storage:get_int("mcl_spawn_dir_ind") or 1
local emerge_pos1, emerge_pos2
local spawn_limit = mcl_vars.mapgen_edge_max
local spawn_limit = mcl_mapgen.EDGE_MAX
--Functions

View File

@ -1,4 +1,4 @@
name = mcl_spawn
author = Wuzzy
description = Set and get the player's respawn position
depends = mcl_init
depends = mcl_mapgen