forked from MineClone5/MineClone5
Merge production (v1.2) into master
This commit is contained in:
commit
d007f33e6e
|
@ -1,101 +1,120 @@
|
||||||
# mcl_mapgen
|
# mcl_mapgen
|
||||||
============
|
------------
|
||||||
Helps to avoid problems caused by 'chunk-in-shell' feature of mapgen.cpp.
|
Helps to avoid problems caused by 'chunk-in-shell' feature of mapgen.cpp.
|
||||||
|
|
||||||
It also queues your generators to run them in proper order:
|
It also queues your generators to run them in proper order:
|
||||||
|
|
||||||
### mcl_mapgen.register_on_generated(lvm_callback_function, order_number)
|
### mcl_mapgen.register_on_generated(lvm_callback_function, order_number)
|
||||||
=========================================================================
|
-------------------------------------------------------------------------
|
||||||
Replacement of engine API function `minetest.register_on_generated(function(vm_context))`
|
Replacement of engine API function `minetest.register_on_generated(function(vm_context))`
|
||||||
|
|
||||||
It is still unsafe. Cavegen part can and will overwrite outer 1-block layer of the chunk which is expected to be generated.
|
It is still unsafe. Cavegen part can and will overwrite outer 1-block layer of the chunk which is expected to be generated.
|
||||||
|
|
||||||
Nodes marked as `is_ground_content` could be overwritten. Air and water are usually 'ground content' too.
|
Nodes marked as `is_ground_content` could be overwritten. Air and water are usually 'ground content' too.
|
||||||
For Minetest 5.4 it doesn't recommended to place blocks within lvm callback function.
|
For Minetest 5.4 it doesn't recommended to place blocks within lvm callback function.
|
||||||
|
|
||||||
See https://git.minetest.land/MineClone2/MineClone2/issues/1395
|
See https://git.minetest.land/MineClone2/MineClone2/issues/1395
|
||||||
`lvm_callback_function`: chunk callback LVM function definition:
|
|
||||||
`function(vm_context)`:
|
* `lvm_callback_function`: chunk callback LVM function definition:
|
||||||
`vm_context` will pass into next lvm callback function from the queue!
|
* `function(vm_context)`:
|
||||||
`vm_context`: a table which already contains some LVM data as the fields, and some of them can be added in your lvm callback function:
|
* `vm_context` will pass into next lvm callback function from the queue!
|
||||||
`vm`: curent voxel manipulator object itself;
|
* `vm_context`: a table which already contains some LVM data as the fields, and some of them can be added in your lvm callback function:
|
||||||
`chunkseed`: seed of this mapchunk;
|
* `vm`: curent voxel manipulator object itself;
|
||||||
`minp` & `maxp`: minimum and maximum chunk position;
|
* `chunkseed`: seed of this mapchunk;
|
||||||
`emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT;
|
* `minp` & `maxp`: minimum and maximum chunk position;
|
||||||
`area`: voxel area, can be helpful to access data;
|
* `emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT;
|
||||||
`data`: LVM buffer data array, data loads into it before the callbacks;
|
* `area`: voxel area, can be helpful to access data;
|
||||||
`write`: set it to true in your lvm callback functionm, if you changed `data` and want to write it;
|
* `data`: LVM buffer data array, data loads into it before the callbacks;
|
||||||
`param2_data`: LVM buffer data array of `param2`, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself:
|
* `write`: set it to true in your lvm callback functionm, if you changed `data` and want to write it;
|
||||||
`vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer)`
|
* `param2_data`: LVM buffer data array of `param2`, *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - you load it yourself:
|
||||||
`write_param2`: set it to true in your lvm callback function, if you used `param2_data` and want to write it;
|
* `vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer)`
|
||||||
`light`: LVM buffer data array of light, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself:
|
* `write_param2`: set it to true in your lvm callback function, if you used `param2_data` and want to write it;
|
||||||
`vm_context.light = vm_context.light or vm_context.vm.get_light_data(vm_context.lvm_light_buffer)`
|
* `light`: LVM buffer data array of light, *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - you load it yourself:
|
||||||
`write_light`: set it to true in your lvm callback function, if you used `light` and want to write it;
|
* `vm_context.light = vm_context.light or vm_context.vm.get_light_data(vm_context.lvm_light_buffer)`
|
||||||
`lvm_param2_buffer`: static `param2` buffer pointer, used to load `param2_data` array;
|
* `write_light`: set it to true in your lvm callback function, if you used `light` and want to write it;
|
||||||
`shadow`: set it to false to disable shadow propagation;
|
* `lvm_param2_buffer`: static `param2` buffer pointer, used to load `param2_data` array;
|
||||||
`heightmap`: mapgen object contanting y coordinates of ground level,
|
* `shadow`: set it to false to disable shadow propagation;
|
||||||
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself:
|
* `heightmap`: mapgen object contanting y coordinates of ground level,
|
||||||
`vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')`
|
* *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself:
|
||||||
`biomemap`: mapgen object contanting biome IDs of nodes,
|
* `vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')`
|
||||||
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself:
|
* `biomemap`: mapgen object contanting biome IDs of nodes,
|
||||||
`vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')`
|
* *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself:
|
||||||
`heatmap`: mapgen object contanting temperature values of nodes,
|
* `vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')`
|
||||||
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself:
|
* `heatmap`: mapgen object contanting temperature values of nodes,
|
||||||
`vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')`
|
* *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself:
|
||||||
`humiditymap`: mapgen object contanting humidity values of nodes,
|
* `vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')`
|
||||||
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself:
|
* `humiditymap`: mapgen object contanting humidity values of nodes,
|
||||||
`vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')`
|
* *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself:
|
||||||
`gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation,
|
* `vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')`
|
||||||
!NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself:
|
* `gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation,
|
||||||
`vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')`
|
* *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself:
|
||||||
`order_number` (optional): the less, the earlier,
|
* `vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')`
|
||||||
e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS`
|
* `order_number` (optional): the less, the earlier,
|
||||||
|
* e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS`
|
||||||
|
|
||||||
### mcl_mapgen.register_mapgen_block_lvm(lvm_callback_function, order_number)
|
### mcl_mapgen.register_mapgen_block_lvm(lvm_callback_function, order_number)
|
||||||
=============================================================================
|
-----------------------------------------------------------------------------
|
||||||
Registers lvm callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished.
|
Registers lvm callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished.
|
||||||
|
|
||||||
`vm_context` passes into lvm callback function.
|
`vm_context` passes into lvm callback function.
|
||||||
`lvm_callback_function`: the block callback LVM function definition - same as for chunks - see definition example above;
|
* `lvm_callback_function`: the block callback LVM function definition - same as for chunks - see definition example above;
|
||||||
`order_number` (optional): the less, the earlier,
|
* `order_number` (optional): the less, the earlier,
|
||||||
e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS`
|
* e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS`
|
||||||
|
|
||||||
### mcl_mapgen.register_mapgen_block(node_callback_function, order_number)
|
### mcl_mapgen.register_mapgen_block(node_callback_function, order_number)
|
||||||
==========================================================================
|
--------------------------------------------------------------------------
|
||||||
Registers node_callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished.
|
Registers node_callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished.
|
||||||
`node_callback_function`: node callback function definition:
|
* `node_callback_function`: node callback function definition:
|
||||||
`function(minp, maxp, seed)`:
|
* `function(minp, maxp, seed)`:
|
||||||
`minp` & `maxp`: minimum and maximum block position;
|
* `minp` & `maxp`: minimum and maximum block position;
|
||||||
`seed`: seed of this mapblock;
|
* `seed`: seed of this mapblock;
|
||||||
`order_number` (optional): the less, the earlier,
|
* `order_number` (optional): the less, the earlier,
|
||||||
e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS`
|
* e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS`
|
||||||
|
|
||||||
### mcl_mapgen.register_mapgen(callback_function, order_number)
|
### mcl_mapgen.register_mapgen(callback_function, order_number)
|
||||||
====================================================================
|
---------------------------------------------------------------
|
||||||
Registers callback function to be called when current chunk generation is REALLY 100% finished.
|
Registers callback function to be called when current chunk generation is REALLY 100% finished.
|
||||||
|
|
||||||
For LVM it's the most frustrating function from this mod.
|
For LVM it's the most frustrating function from this mod.
|
||||||
|
|
||||||
It can't provide you access to mapgen objects. They are probably gone long ago.
|
It can't provide you access to mapgen objects. They are probably gone long ago.
|
||||||
|
|
||||||
Don't use it for accessing mapgen objects please.
|
Don't use it for accessing mapgen objects please.
|
||||||
|
|
||||||
To use VM you have to run `vm_context.vm = mcl_mapgen.get_voxel_manip(vm_context.emin, vm_context.emax)`.
|
To use VM you have to run `vm_context.vm = mcl_mapgen.get_voxel_manip(vm_context.emin, vm_context.emax)`.
|
||||||
Set
|
* `callback_function`: callback function definition:
|
||||||
`callback_function`: callback function definition:
|
* `function(minp, maxp, seed, vm_context)`:
|
||||||
`function(minp, maxp, seed, vm_context)`:
|
* `minp` & `maxp`: minimum and maximum block position;
|
||||||
`minp` & `maxp`: minimum and maximum block position;
|
* `seed`: seed of this mapblock;
|
||||||
`seed`: seed of this mapblock;
|
* `vm_context`: a table - see description above.
|
||||||
`vm_context`: a table - see description above.
|
* `order_number` (optional): the less, the earlier.
|
||||||
`order_number` (optional): the less, the earlier.
|
|
||||||
|
|
||||||
### mcl_mapgen.register_mapgen_lvm(lvm_callback_function, order_number)
|
### mcl_mapgen.register_mapgen_lvm(lvm_callback_function, order_number)
|
||||||
=======================================================================
|
-----------------------------------------------------------------------
|
||||||
Registers lvm callback function to be called when current chunk generation is REALLY 100% finished.
|
Registers lvm callback function to be called when current chunk generation is REALLY 100% finished.
|
||||||
|
|
||||||
It's the most frustrating function from this mod. It can't provide you access to mapgen objects. They are probably gone long ago.
|
It's the most frustrating function from this mod. It can't provide you access to mapgen objects. They are probably gone long ago.
|
||||||
|
|
||||||
Don't use it for accessing mapgen objects please.
|
Don't use it for accessing mapgen objects please.
|
||||||
|
|
||||||
`vm_context` passes into lvm callback function.
|
`vm_context` passes into lvm callback function.
|
||||||
`lvm_callback_function`: the block callback LVM function definition - same as above;
|
* `lvm_callback_function`: the block callback LVM function definition - same as above;
|
||||||
`order_number` (optional): the less, the earlier.
|
* `order_number` (optional): the less, the earlier.
|
||||||
|
|
||||||
### mcl_mapgen.get_far_node(pos)
|
### mcl_mapgen.get_far_node(pos)
|
||||||
================================
|
--------------------------------
|
||||||
Returns node if it is generated, otherwise returns `{name = "ignore"}`.
|
Returns node if it is generated, otherwise returns `{name = "ignore"}`.
|
||||||
|
|
||||||
## Constants:
|
### mcl_mapgen.clamp_to_chunk(x, size)
|
||||||
|
--------------------------------------
|
||||||
|
Returns new `x`, slighty tuned to make structure of size `size` be within single chunk side of 80 nodes.
|
||||||
|
|
||||||
* `mcl_mapgen.EDGE_MIN`, `mcl_mapgen.EDGE_MAX` - world edges, min & max.
|
### function mcl_mapgen.get_chunk_beginning(x)
|
||||||
* `mcl_mapgen.seed`, `mcl_mapgen.name` - mapgen seed & name.
|
----------------------------------------------
|
||||||
* `mcl_mapgen.v6`, `mcl_mapgen.superflat`, `mcl_mapgen.singlenode` - is mapgen v6, superflat, singlenode.
|
Returns chunk beginning of `x`. It is the same as `minp.axis` for per-chunk callbacks, but we don't always have `minp`.
|
||||||
* `mcl_mapgen.normal` is mapgen normal (not superflat or singlenode).
|
|
||||||
|
## Constants:
|
||||||
|
* `mcl_mapgen.EDGE_MIN`, `mcl_mapgen.EDGE_MAX` - world edges, min & max.
|
||||||
|
* `mcl_mapgen.seed`, `mcl_mapgen.name` - mapgen seed & name.
|
||||||
|
* `mcl_mapgen.v6`, `mcl_mapgen.superflat`, `mcl_mapgen.singlenode` - is mapgen v6, superflat, singlenode.
|
||||||
|
* `mcl_mapgen.normal` is mapgen normal (not superflat or singlenode).
|
||||||
|
|
|
@ -52,13 +52,14 @@ local seed = minetest.get_mapgen_setting("seed")
|
||||||
mcl_mapgen.seed = seed
|
mcl_mapgen.seed = seed
|
||||||
mcl_mapgen.name = minetest.get_mapgen_setting("mg_name")
|
mcl_mapgen.name = minetest.get_mapgen_setting("mg_name")
|
||||||
mcl_mapgen.v6 = mcl_mapgen.name == "v6"
|
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.flat = mcl_mapgen.name == "flat"
|
||||||
|
mcl_mapgen.superflat = mcl_mapgen.flat and minetest.get_mapgen_setting("mcl_superflat_classic") == "true"
|
||||||
mcl_mapgen.singlenode = mcl_mapgen.name == "singlenode"
|
mcl_mapgen.singlenode = mcl_mapgen.name == "singlenode"
|
||||||
mcl_mapgen.normal = not mcl_mapgen.superflat and not mcl_mapgen.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
|
local flat, superflat, singlenode, normal = mcl_mapgen.flat, 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")))
|
minetest_log("action", "[mcl_mapgen] Mapgen mode: " .. (normal and "normal" or (superflat and "superflat" or (flat and "flat" or "singlenode"))))
|
||||||
----------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Generator queues
|
-- Generator queues
|
||||||
local queue_unsafe_engine = {}
|
local queue_unsafe_engine = {}
|
||||||
|
@ -263,6 +264,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed)
|
||||||
end
|
end
|
||||||
|
|
||||||
if #queue_unsafe_engine > 0 then
|
if #queue_unsafe_engine > 0 then
|
||||||
|
vm_context.minp, vm_context.maxp = minp, maxp
|
||||||
for _, v in pairs(queue_unsafe_engine) do
|
for _, v in pairs(queue_unsafe_engine) do
|
||||||
v.f(vm_context)
|
v.f(vm_context)
|
||||||
end
|
end
|
||||||
|
@ -430,14 +432,12 @@ else
|
||||||
nether.bedrock_top_min = nether.bedrock_top_max
|
nether.bedrock_top_min = nether.bedrock_top_max
|
||||||
nether.lava_max = nether.min + 2
|
nether.lava_max = nether.min + 2
|
||||||
end
|
end
|
||||||
if mcl_mapgen.name == "flat" then
|
if superflat then
|
||||||
if superflat then
|
nether.flat_floor = nether.bedrock_bottom_max + 4
|
||||||
nether.flat_floor = nether.bedrock_bottom_max + 4
|
nether.flat_ceiling = nether.bedrock_bottom_max + 52
|
||||||
nether.flat_ceiling = nether.bedrock_bottom_max + 52
|
elseif flat then
|
||||||
else
|
nether.flat_floor = nether.lava_max + 4
|
||||||
nether.flat_floor = nether.lava_max + 4
|
nether.flat_ceiling = nether.lava_max + 52
|
||||||
nether.flat_ceiling = nether.lava_max + 52
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The End (surface at ca. Y = -27000)
|
-- The End (surface at ca. Y = -27000)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow")
|
||||||
|
local c_top_snow = minetest.get_content_id("mcl_core:snow")
|
||||||
|
local c_snow_block = minetest.get_content_id("mcl_core:snowblock")
|
||||||
|
|
||||||
|
mcl_mapgen.register_on_generated(function(vm_context)
|
||||||
|
local minp, maxp = vm_context.minp, vm_context.maxp
|
||||||
|
local min_y, max_y = minp.y, maxp.y
|
||||||
|
if min_y > mcl_mapgen.overworld.max or max_y < mcl_mapgen.overworld.min then return end
|
||||||
|
|
||||||
|
vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer)
|
||||||
|
vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap")
|
||||||
|
local param2_data = vm_context.param2_data
|
||||||
|
local biomemap = vm_context.biomemap
|
||||||
|
local vm, data, area = vm_context.vm, vm_context.data, vm_context.area
|
||||||
|
|
||||||
|
local min_x, min_z = minp.x, minp.z
|
||||||
|
local chunksize = max_y - min_y + 1
|
||||||
|
|
||||||
|
----- Interactive block fixing section -----
|
||||||
|
----- The section to perform basic block overrides of the core mapgen generated world. -----
|
||||||
|
|
||||||
|
-- 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.
|
||||||
|
|
||||||
|
-- Set param2 (=color) of grass blocks.
|
||||||
|
-- Clear snowy grass blocks without snow above to ensure consistency.
|
||||||
|
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"})
|
||||||
|
|
||||||
|
for n=1, #nodes do
|
||||||
|
local pos = nodes[n]
|
||||||
|
local x, y, z = pos.x, pos.y, pos.z
|
||||||
|
local p_pos = area:index(x, y, z)
|
||||||
|
local p_pos_above = area:index(x, y + 1, z)
|
||||||
|
local biomemap_offset = (z - min_z) * chunksize + x - min_x + 1
|
||||||
|
local biome_id = biomemap[biomemap_offset]
|
||||||
|
local biome_name = minetest.get_biome_name(biome_id)
|
||||||
|
if biome_name then
|
||||||
|
local biome = minetest.registered_biomes[biome_name]
|
||||||
|
if biome and biome._mcl_biome_type then
|
||||||
|
param2_data[p_pos] = biome._mcl_palette_index
|
||||||
|
vm_context.write_param2 = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then
|
||||||
|
data[p_pos] = c_dirt_with_grass
|
||||||
|
vm_context.write = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, 999999999)
|
|
@ -56,19 +56,14 @@ local mg_name = mcl_mapgen.name
|
||||||
local superflat = mcl_mapgen.superflat
|
local superflat = mcl_mapgen.superflat
|
||||||
local v6 = mcl_mapgen.v6
|
local v6 = mcl_mapgen.v6
|
||||||
local singlenode = mcl_mapgen.singlenode
|
local singlenode = mcl_mapgen.singlenode
|
||||||
|
local flat = mcl_mapgen.flat
|
||||||
|
|
||||||
-- Content IDs
|
-- Content IDs
|
||||||
local c_bedrock = minetest.get_content_id("mcl_core:bedrock")
|
local c_bedrock = minetest.get_content_id("mcl_core:bedrock")
|
||||||
local c_obsidian = minetest.get_content_id("mcl_core:obsidian")
|
|
||||||
local c_stone = minetest.get_content_id("mcl_core:stone")
|
|
||||||
local c_dirt = minetest.get_content_id("mcl_core:dirt")
|
local c_dirt = minetest.get_content_id("mcl_core:dirt")
|
||||||
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
|
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
|
||||||
local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow")
|
|
||||||
local c_sand = minetest.get_content_id("mcl_core:sand")
|
|
||||||
--local c_sandstone = minetest.get_content_id("mcl_core:sandstone")
|
|
||||||
local c_void = minetest.get_content_id("mcl_core:void")
|
local c_void = minetest.get_content_id("mcl_core:void")
|
||||||
local c_lava = minetest.get_content_id("mcl_core:lava_source")
|
local c_lava = minetest.get_content_id("mcl_core:lava_source")
|
||||||
local c_water = minetest.get_content_id("mcl_core:water_source")
|
|
||||||
|
|
||||||
local c_nether = nil
|
local c_nether = nil
|
||||||
if minetest.get_modpath("mcl_nether") then
|
if minetest.get_modpath("mcl_nether") then
|
||||||
|
@ -79,12 +74,7 @@ if minetest.get_modpath("mcl_nether") then
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
--local c_end_stone = minetest.get_content_id("mcl_end:end_stone")
|
|
||||||
local c_realm_barrier = minetest.get_content_id("mcl_core:realm_barrier")
|
local c_realm_barrier = minetest.get_content_id("mcl_core:realm_barrier")
|
||||||
local c_top_snow = minetest.get_content_id("mcl_core:snow")
|
|
||||||
local c_snow_block = minetest.get_content_id("mcl_core:snowblock")
|
|
||||||
local c_clay = minetest.get_content_id("mcl_core:clay")
|
|
||||||
--local c_jungletree = minetest.get_content_id("mcl_core:jungletree")
|
|
||||||
local c_air = minetest.CONTENT_AIR
|
local c_air = minetest.CONTENT_AIR
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -1194,100 +1184,6 @@ function mcl_mapgen_core.generate_end_exit_portal(pos)
|
||||||
portal_generated = true
|
portal_generated = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Generate mushrooms in caves manually.
|
|
||||||
-- Minetest's API does not support decorations in caves yet. :-(
|
|
||||||
local function generate_underground_mushrooms(minp, maxp, seed)
|
|
||||||
if not mcl_mushrooms then return end
|
|
||||||
|
|
||||||
local pr_shroom = PseudoRandom(seed-24359)
|
|
||||||
-- Generate rare underground mushrooms
|
|
||||||
-- TODO: Make them appear in groups, use Perlin noise
|
|
||||||
local min, max = mcl_mapgen.overworld.lava_max + 4, 0
|
|
||||||
if minp.y > max or maxp.y < min then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local bpos
|
|
||||||
local stone = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_core:stone", "mcl_core:dirt", "mcl_core:mycelium", "mcl_core:podzol", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:stone_with_iron", "mcl_core:stone_with_gold"})
|
|
||||||
|
|
||||||
for n = 1, #stone do
|
|
||||||
bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z }
|
|
||||||
|
|
||||||
local l = minetest.get_node_light(bpos, 0.5)
|
|
||||||
if bpos.y >= min and bpos.y <= max and l and l <= 12 and pr_shroom:next(1,1000) < 4 then
|
|
||||||
if pr_shroom:next(1,2) == 1 then
|
|
||||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
|
||||||
else
|
|
||||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Generate Nether decorations manually: Eternal fire, mushrooms
|
|
||||||
-- Minetest's API does not support decorations in caves yet. :-(
|
|
||||||
local function generate_nether_decorations(minp, maxp, seed)
|
|
||||||
if c_nether == nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local pr_nether = PseudoRandom(seed+667)
|
|
||||||
|
|
||||||
if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.log("action", "[mcl_mapgen_core] Nether decorations " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp))
|
|
||||||
|
|
||||||
-- TODO: Generate everything based on Perlin noise instead of PseudoRandom
|
|
||||||
|
|
||||||
local bpos
|
|
||||||
local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"})
|
|
||||||
local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"})
|
|
||||||
local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"})
|
|
||||||
|
|
||||||
-- Helper function to spawn “fake” decoration
|
|
||||||
local function special_deco(nodes, spawn_func)
|
|
||||||
for n = 1, #nodes do
|
|
||||||
bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z }
|
|
||||||
|
|
||||||
spawn_func(bpos)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Eternal fire on netherrack
|
|
||||||
special_deco(rack, function(bpos)
|
|
||||||
-- Eternal fire on netherrack
|
|
||||||
if pr_nether:next(1,100) <= 3 then
|
|
||||||
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Eternal fire on magma cubes
|
|
||||||
special_deco(magma, function(bpos)
|
|
||||||
if pr_nether:next(1,150) == 1 then
|
|
||||||
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Mushrooms on netherrack
|
|
||||||
-- Note: Spawned *after* the fire because of light level checks
|
|
||||||
if mcl_mushrooms then
|
|
||||||
special_deco(rack, function(bpos)
|
|
||||||
local l = minetest.get_node_light(bpos, 0.5)
|
|
||||||
if bpos.y > mcl_mapgen.nether.lava_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then
|
|
||||||
-- TODO: Make mushrooms appear in groups, use Perlin noise
|
|
||||||
if pr_nether:next(1,2) == 1 then
|
|
||||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
|
||||||
else
|
|
||||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc.
|
-- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc.
|
||||||
-- Also perform some basic node replacements.
|
-- Also perform some basic node replacements.
|
||||||
|
|
||||||
|
@ -1338,268 +1234,96 @@ end
|
||||||
-- lvm_used: Set to true if any node in this on_generated has been set before.
|
-- lvm_used: Set to true if any node in this on_generated has been set before.
|
||||||
--
|
--
|
||||||
-- returns true if any node was set and lvm_used otherwise
|
-- returns true if any node was set and lvm_used otherwise
|
||||||
local function set_layers(data, area, content_id, check, min, max, minp, maxp, lvm_used, pr)
|
local function set_layers(vm_context, pr, min, max, content_id, check)
|
||||||
|
local minp, maxp, data, area = vm_context.minp, vm_context.maxp, vm_context.data, vm_context.area
|
||||||
if (maxp.y >= min and minp.y <= max) then
|
if (maxp.y >= min and minp.y <= max) then
|
||||||
for y = math.max(min, minp.y), math.min(max, maxp.y) do
|
for y = math.max(min, minp.y), math.min(max, maxp.y) do
|
||||||
for x = minp.x, maxp.x do
|
for x = minp.x, maxp.x do
|
||||||
for z = minp.z, maxp.z do
|
for z = minp.z, maxp.z do
|
||||||
local p_pos = area:index(x, y, z)
|
local p_pos = vm_context.area:index(x, y, z)
|
||||||
if check then
|
if check then
|
||||||
if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then
|
if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then
|
||||||
data[p_pos] = content_id
|
data[p_pos] = content_id
|
||||||
lvm_used = true
|
vm_context.write = true
|
||||||
elseif check == data[p_pos] then
|
elseif check == data[p_pos] then
|
||||||
data[p_pos] = content_id
|
data[p_pos] = content_id
|
||||||
lvm_used = true
|
vm_context.write = true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
data[p_pos] = content_id
|
vm_context.data[p_pos] = content_id
|
||||||
lvm_used = true
|
vm_context.write = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return lvm_used
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Below the bedrock, generate air/void
|
---- Generate layers of air, void, etc
|
||||||
local function basic_safe(vm_context)
|
local air_layers = {
|
||||||
local vm, data, emin, emax, area, minp, maxp, chunkseed, blockseed = vm_context.vm, vm_context.data, vm_context.emin, vm_context.emax, vm_context.area, vm_context.minp, vm_context.maxp, vm_context.chunkseed, vm_context.blockseed
|
{mcl_mapgen.nether.max + 1, mcl_mapgen.nether.max + 128} -- on Nether Roof
|
||||||
|
}
|
||||||
|
if flat then
|
||||||
|
air_layers[#air_layers + 1] = {mcl_mapgen.nether.flat_floor, mcl_mapgen.nether.flat_ceiling} -- Flat Nether
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Realm barrier between the Overworld void and the End
|
||||||
|
local barrier_min = mcl_mapgen.realm_barrier_overworld_end_min
|
||||||
|
local barrier_max = mcl_mapgen.realm_barrier_overworld_end_max
|
||||||
|
|
||||||
|
local void_layers = {
|
||||||
|
{mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min - 1 }, -- below Nether
|
||||||
|
{mcl_mapgen.nether.max + 129, mcl_mapgen.end_.min - 1 }, -- below End (above Nether)
|
||||||
|
{mcl_mapgen.end_.max + 1 , barrier_min - 1 }, -- below Realm Barrier, above End
|
||||||
|
{barrier_max + 1 , mcl_mapgen.overworld.min - 1}, -- below Overworld, above Realm Barrier
|
||||||
|
}
|
||||||
|
|
||||||
|
local bedrock_layers = {}
|
||||||
|
if not singlelayer then
|
||||||
|
bedrock_layers = {
|
||||||
|
{mcl_mapgen.overworld.bedrock_min , mcl_mapgen.overworld.bedrock_max },
|
||||||
|
{mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_bottom_max},
|
||||||
|
{mcl_mapgen.nether.bedrock_top_min , mcl_mapgen.nether.bedrock_top_max },
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
mcl_mapgen.register_mapgen_block_lvm(function(vm_context)
|
||||||
|
local vm, data, area, minp, maxp, chunkseed, blockseed = vm_context.vm, vm_context.data, vm_context.area, vm_context.minp, vm_context.maxp, vm_context.chunkseed, vm_context.blockseed
|
||||||
vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer)
|
vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer)
|
||||||
local param2_data = vm_context.param2_data
|
local param2_data = vm_context.param2_data
|
||||||
|
|
||||||
local lvm_used = false
|
|
||||||
local pr = PseudoRandom(blockseed)
|
local pr = PseudoRandom(blockseed)
|
||||||
|
for _, layer in pairs(void_layers) do
|
||||||
-- The Void below the Nether:
|
set_layers(vm_context, pr, layer[1], layer[2], c_void)
|
||||||
lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min -1, minp, maxp, lvm_used, pr)
|
end
|
||||||
|
for _, layer in pairs(air_layers) do
|
||||||
-- [[ THE NETHER: mcl_mapgen.nether.min mcl_mapgen.nether.max ]]
|
set_layers(vm_context, pr, layer[1], layer[2], c_air)
|
||||||
|
end
|
||||||
-- The Air on the Nether roof, https://git.minetest.land/MineClone2/MineClone2/issues/1186
|
set_layers(vm_context, pr, barrier_min, barrier_max, c_realm_barrier)
|
||||||
lvm_used = set_layers(data, area, c_air , nil, mcl_mapgen.nether.max +1, mcl_mapgen.nether.max + 128 , minp, maxp, lvm_used, pr)
|
for _, layer in pairs(bedrock_layers) do
|
||||||
-- The Void above the Nether below the End:
|
set_layers(vm_context, pr, layer[1], layer[2], c_bedrock, bedrock_check)
|
||||||
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)
|
end
|
||||||
|
|
||||||
-- [[ 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_mapgen.end_.max +1, mcl_mapgen.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_mapgen.realm_barrier_overworld_end_min , mcl_mapgen.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_mapgen.realm_barrier_overworld_end_max+1, mcl_mapgen.overworld.min -1, minp, maxp, lvm_used, pr)
|
|
||||||
|
|
||||||
|
|
||||||
if not singlenode then
|
if not singlenode then
|
||||||
-- Bedrock
|
|
||||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.overworld.bedrock_min, mcl_mapgen.overworld.bedrock_max, minp, maxp, lvm_used, pr)
|
|
||||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_bottom_max, minp, maxp, lvm_used, pr)
|
|
||||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_top_min, mcl_mapgen.nether.bedrock_top_max, minp, maxp, lvm_used, pr)
|
|
||||||
|
|
||||||
-- Flat Nether
|
|
||||||
if mg_name == "flat" then
|
|
||||||
lvm_used = set_layers(data, area, c_air, nil, mcl_mapgen.nether.flat_floor, mcl_mapgen.nether.flat_ceiling, minp, maxp, lvm_used, pr)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Big lava seas by replacing air below a certain height
|
-- Big lava seas by replacing air below a certain height
|
||||||
if mcl_mapgen.lava then
|
if mcl_mapgen.lava then
|
||||||
lvm_used = set_layers(data, area, c_lava, c_air, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, minp, maxp, lvm_used, pr)
|
set_layers(vm_context, pr, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, c_lava, c_air)
|
||||||
if c_nether then
|
if c_nether then
|
||||||
lvm_used = set_layers(data, area, c_nether.lava, c_air, mcl_mapgen.nether.min, mcl_mapgen.nether.lava_max, minp, maxp, lvm_used, pr)
|
set_layers(vm_context, pr, mcl_mapgen.nether.min, mcl_mapgen.nether.lava_max, c_nether.lava, c_air)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap")
|
|
||||||
local biomemap = vm_context.biomemap
|
|
||||||
|
|
||||||
----- Interactive block fixing section -----
|
|
||||||
----- The section to perform basic block overrides of the core mapgen generated world. -----
|
|
||||||
|
|
||||||
-- 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_mapgen.overworld.max and maxp.y >= mcl_mapgen.overworld.min then
|
|
||||||
-- v6 mapgen:
|
|
||||||
if v6 then
|
|
||||||
|
|
||||||
--[[ Remove broken double plants caused by v6 weirdness.
|
|
||||||
v6 might break the bottom part of double plants because of how it works.
|
|
||||||
There are 3 possibilities:
|
|
||||||
1) Jungle: Top part is placed on top of a jungle tree or fern (=v6 jungle grass).
|
|
||||||
This is because the schematic might be placed even if some nodes of it
|
|
||||||
could not be placed because the destination was already occupied.
|
|
||||||
TODO: A better fix for this would be if schematics could abort placement
|
|
||||||
altogether if ANY of their nodes could not be placed.
|
|
||||||
2) Cavegen: Removes the bottom part, the upper part floats
|
|
||||||
3) Mudflow: Same as 2) ]]
|
|
||||||
local plants = minetest.find_nodes_in_area(minp, maxp, "group:double_plant")
|
|
||||||
for n = 1, #plants do
|
|
||||||
local node = vm:get_node_at(plants[n])
|
|
||||||
local is_top = minetest.get_item_group(node.name, "double_plant") == 2
|
|
||||||
if is_top then
|
|
||||||
local p_pos = area:index(plants[n].x, plants[n].y-1, plants[n].z)
|
|
||||||
if p_pos then
|
|
||||||
node = vm:get_node_at({x=plants[n].x, y=plants[n].y-1, z=plants[n].z})
|
|
||||||
local is_bottom = minetest.get_item_group(node.name, "double_plant") == 1
|
|
||||||
if not is_bottom then
|
|
||||||
p_pos = area:index(plants[n].x, plants[n].y, plants[n].z)
|
|
||||||
data[p_pos] = c_air
|
|
||||||
lvm_used = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Non-v6 mapgens:
|
|
||||||
else
|
|
||||||
-- Set param2 (=color) of grass blocks.
|
|
||||||
-- Clear snowy grass blocks without snow above to ensure consistency.
|
|
||||||
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"})
|
|
||||||
|
|
||||||
-- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration:
|
|
||||||
local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}})
|
|
||||||
for n=1, #nodes do
|
|
||||||
local n = nodes[n]
|
|
||||||
local p_pos = area:index(n.x, n.y, n.z)
|
|
||||||
local p_pos_above = area:index(n.x, n.y+1, n.z)
|
|
||||||
--local p_pos_below = area:index(n.x, n.y-1, n.z)
|
|
||||||
local b_pos = aream:index(n.x, 0, n.z)
|
|
||||||
local bn = minetest.get_biome_name(biomemap[b_pos])
|
|
||||||
if bn then
|
|
||||||
local biome = minetest.registered_biomes[bn]
|
|
||||||
if biome and biome._mcl_biome_type then
|
|
||||||
param2_data[p_pos] = biome._mcl_palette_index
|
|
||||||
vm_context.write_param2 = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then
|
|
||||||
data[p_pos] = c_dirt_with_grass
|
|
||||||
lvm_used = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Nether block fixes:
|
|
||||||
-- * Replace water with Nether lava.
|
|
||||||
-- * Replace stone, sand dirt in v6 so the Nether works in v6.
|
|
||||||
elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then
|
|
||||||
-- elseif emin.y <= mcl_mapgen.nether.max and emax.y >= mcl_mapgen.nether.min then
|
|
||||||
if c_nether then
|
|
||||||
if v6 then
|
|
||||||
-- local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
|
|
||||||
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
|
|
||||||
for n=1, #nodes do
|
|
||||||
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
|
|
||||||
if data[p_pos] == c_water then
|
|
||||||
data[p_pos] = c_nether.lava
|
|
||||||
lvm_used = true
|
|
||||||
elseif data[p_pos] == c_stone then
|
|
||||||
data[p_pos] = c_netherrack
|
|
||||||
lvm_used = true
|
|
||||||
elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then
|
|
||||||
data[p_pos] = c_soul_sand
|
|
||||||
lvm_used = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"})
|
|
||||||
local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"})
|
|
||||||
for _, n in pairs(nodes) do
|
|
||||||
data[area:index(n.x, n.y, n.z)] = c_nether.lava
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- End block fixes:
|
|
||||||
-- * 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_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then
|
|
||||||
local nodes
|
|
||||||
if v6 then
|
|
||||||
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
|
|
||||||
-- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
|
|
||||||
else
|
|
||||||
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"})
|
|
||||||
-- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"})
|
|
||||||
end
|
|
||||||
if #nodes > 0 then
|
|
||||||
lvm_used = true
|
|
||||||
for _,n in pairs(nodes) do
|
|
||||||
data[area:index(n.x, n.y, n.z)] = c_air
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Obsidian spawn platform
|
|
||||||
if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and
|
|
||||||
minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and
|
|
||||||
minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.end_.platform_pos.z then
|
|
||||||
|
|
||||||
--local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)}
|
|
||||||
--local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2)}
|
|
||||||
|
|
||||||
for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do
|
|
||||||
for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do
|
|
||||||
for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do
|
|
||||||
local p_pos = area:index(x, y, z)
|
|
||||||
if y == mcl_mapgen.end_.platform_pos.y then
|
|
||||||
data[p_pos] = c_obsidian
|
|
||||||
else
|
|
||||||
data[p_pos] = c_air
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
lvm_used = true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end, 1)
|
||||||
|
|
||||||
if not singlenode then
|
|
||||||
-- Generate special decorations
|
|
||||||
generate_underground_mushrooms(minp, maxp, blockseed)
|
|
||||||
generate_nether_decorations(minp, maxp, blockseed)
|
|
||||||
end
|
|
||||||
|
|
||||||
vm_context.write = vm_context.write or lvm_used
|
|
||||||
end
|
|
||||||
|
|
||||||
mcl_mapgen.register_mapgen_block_lvm(basic_safe, 1)
|
|
||||||
|
|
||||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
dofile(modpath .. "/clay.lua")
|
dofile(modpath .. "/clay.lua")
|
||||||
dofile(modpath .. "/tree_decoration.lua")
|
dofile(modpath .. "/tree_decoration.lua")
|
||||||
dofile(modpath .. "/nether_wart.lua")
|
dofile(modpath .. "/nether_wart.lua")
|
||||||
|
dofile(modpath .. "/light.lua")
|
||||||
-- Nether Roof Light:
|
if v6 then
|
||||||
mcl_mapgen.register_mapgen_block_lvm(function(vm_context)
|
dofile(modpath .. "/v6.lua")
|
||||||
local minp = vm_context.minp
|
elseif not singlenode then
|
||||||
local miny = minp.y
|
dofile(modpath .. "/biomes.lua")
|
||||||
if miny > mcl_mapgen.nether.max+127 then return end
|
end
|
||||||
local maxp = vm_context.maxp
|
if not singlenode and c_nether then
|
||||||
local maxy = maxp.y
|
dofile(modpath .. "/nether.lua")
|
||||||
if maxy <= mcl_mapgen.nether.max then return end
|
end
|
||||||
local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z}
|
|
||||||
local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z}
|
|
||||||
vm_context.vm:set_lighting({day=15, night=15}, p1, p2)
|
|
||||||
vm_context.write = true
|
|
||||||
end, 999999999)
|
|
||||||
|
|
||||||
-- End Light:
|
|
||||||
mcl_mapgen.register_mapgen_block_lvm(function(vm_context)
|
|
||||||
local minp = vm_context.minp
|
|
||||||
local miny = minp.y
|
|
||||||
if miny > mcl_mapgen.end_.max then return end
|
|
||||||
local maxp = vm_context.maxp
|
|
||||||
local maxy = maxp.y
|
|
||||||
if maxy <= mcl_mapgen.end_.min then return end
|
|
||||||
local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.end_.min), z = minp.z}
|
|
||||||
local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.end_.max), z = maxp.z}
|
|
||||||
vm_context.vm:set_lighting({day=15, night=15}, p1, p2)
|
|
||||||
vm_context.write = true
|
|
||||||
end, 9999999999)
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
-- Nether Light:
|
||||||
|
mcl_mapgen.register_mapgen_block_lvm(function(vm_context)
|
||||||
|
local minp = vm_context.minp
|
||||||
|
local miny = minp.y
|
||||||
|
if miny > mcl_mapgen.nether.max then return end
|
||||||
|
local maxp = vm_context.maxp
|
||||||
|
local maxy = maxp.y
|
||||||
|
if maxy < mcl_mapgen.nether.min then return end
|
||||||
|
local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.min), z = minp.z}
|
||||||
|
local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max), z = maxp.z}
|
||||||
|
vm_context.vm:set_lighting({day = 3, night = 4}, p1, p2)
|
||||||
|
vm_context.write = true
|
||||||
|
end, 999999999)
|
||||||
|
|
||||||
|
-- Nether Roof Light:
|
||||||
|
mcl_mapgen.register_mapgen_block_lvm(function(vm_context)
|
||||||
|
local minp = vm_context.minp
|
||||||
|
local miny = minp.y
|
||||||
|
if miny > mcl_mapgen.nether.max+127 then return end
|
||||||
|
local maxp = vm_context.maxp
|
||||||
|
local maxy = maxp.y
|
||||||
|
if maxy <= mcl_mapgen.nether.max then return end
|
||||||
|
local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z}
|
||||||
|
local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z}
|
||||||
|
vm_context.vm:set_lighting({day = 15, night = 15}, p1, p2)
|
||||||
|
vm_context.write = true
|
||||||
|
end, 999999999)
|
||||||
|
|
||||||
|
-- End Light:
|
||||||
|
mcl_mapgen.register_mapgen_block_lvm(function(vm_context)
|
||||||
|
local minp = vm_context.minp
|
||||||
|
local miny = minp.y
|
||||||
|
if miny > mcl_mapgen.end_.max then return end
|
||||||
|
local maxp = vm_context.maxp
|
||||||
|
local maxy = maxp.y
|
||||||
|
if maxy <= mcl_mapgen.end_.min then return end
|
||||||
|
local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.end_.min), z = minp.z}
|
||||||
|
local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.end_.max), z = maxp.z}
|
||||||
|
vm_context.vm:set_lighting({day=15, night=15}, p1, p2)
|
||||||
|
vm_context.write = true
|
||||||
|
end, 9999999999)
|
|
@ -0,0 +1,131 @@
|
||||||
|
local v6 = mcl_mapgen.v6
|
||||||
|
|
||||||
|
local mcl_mushrooms = minetest.get_modpath("mcl_mushrooms")
|
||||||
|
|
||||||
|
local c_water = minetest.get_content_id("mcl_core:water_source")
|
||||||
|
local c_stone = minetest.get_content_id("mcl_core:stone")
|
||||||
|
local c_sand = minetest.get_content_id("mcl_core:sand")
|
||||||
|
|
||||||
|
local c_soul_sand = minetest.get_content_id("mcl_nether:soul_sand")
|
||||||
|
local c_netherrack = minetest.get_content_id("mcl_nether:netherrack")
|
||||||
|
local c_nether_lava = minetest.get_content_id("mcl_nether:nether_lava_source")
|
||||||
|
|
||||||
|
-- Generate mushrooms in caves manually.
|
||||||
|
-- Minetest's API does not support decorations in caves yet. :-(
|
||||||
|
local function generate_underground_mushrooms(minp, maxp, seed)
|
||||||
|
if not mcl_mushrooms then return end
|
||||||
|
|
||||||
|
local pr_shroom = PseudoRandom(seed-24359)
|
||||||
|
-- Generate rare underground mushrooms
|
||||||
|
-- TODO: Make them appear in groups, use Perlin noise
|
||||||
|
local min, max = mcl_mapgen.overworld.lava_max + 4, 0
|
||||||
|
if minp.y > max or maxp.y < min then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local bpos
|
||||||
|
local stone = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_core:stone", "mcl_core:dirt", "mcl_core:mycelium", "mcl_core:podzol", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:stone_with_iron", "mcl_core:stone_with_gold"})
|
||||||
|
|
||||||
|
for n = 1, #stone do
|
||||||
|
bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z }
|
||||||
|
|
||||||
|
local l = minetest.get_node_light(bpos, 0.5)
|
||||||
|
if bpos.y >= min and bpos.y <= max and l and l <= 12 and pr_shroom:next(1,1000) < 4 then
|
||||||
|
if pr_shroom:next(1,2) == 1 then
|
||||||
|
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
||||||
|
else
|
||||||
|
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate Nether decorations manually: Eternal fire, mushrooms
|
||||||
|
-- Minetest's API does not support decorations in caves yet. :-(
|
||||||
|
local function generate_nether_decorations(minp, maxp, seed)
|
||||||
|
local pr_nether = PseudoRandom(seed+667)
|
||||||
|
|
||||||
|
if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.log("action", "[mcl_mapgen_core] Nether decorations " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp))
|
||||||
|
|
||||||
|
-- TODO: Generate everything based on Perlin noise instead of PseudoRandom
|
||||||
|
|
||||||
|
local bpos
|
||||||
|
local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"})
|
||||||
|
local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"})
|
||||||
|
local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"})
|
||||||
|
|
||||||
|
-- Helper function to spawn “fake” decoration
|
||||||
|
local function special_deco(nodes, spawn_func)
|
||||||
|
for n = 1, #nodes do
|
||||||
|
bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z }
|
||||||
|
|
||||||
|
spawn_func(bpos)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Eternal fire on netherrack
|
||||||
|
special_deco(rack, function(bpos)
|
||||||
|
-- Eternal fire on netherrack
|
||||||
|
if pr_nether:next(1,100) <= 3 then
|
||||||
|
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Eternal fire on magma cubes
|
||||||
|
special_deco(magma, function(bpos)
|
||||||
|
if pr_nether:next(1,150) == 1 then
|
||||||
|
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Mushrooms on netherrack
|
||||||
|
-- Note: Spawned *after* the fire because of light level checks
|
||||||
|
if mcl_mushrooms then
|
||||||
|
special_deco(rack, function(bpos)
|
||||||
|
local l = minetest.get_node_light(bpos, 0.5)
|
||||||
|
if bpos.y > mcl_mapgen.nether.lava_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then
|
||||||
|
-- TODO: Make mushrooms appear in groups, use Perlin noise
|
||||||
|
if pr_nether:next(1,2) == 1 then
|
||||||
|
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
||||||
|
else
|
||||||
|
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context)
|
||||||
|
local min_y, max_y = minp.y, maxp.y
|
||||||
|
|
||||||
|
-- Nether block fixes:
|
||||||
|
-- * Replace water with Nether lava.
|
||||||
|
-- * Replace stone, sand dirt in v6 so the Nether works in v6.
|
||||||
|
if min_y > mcl_mapgen.nether.max or max_y < mcl_mapgen.nether.min then return end
|
||||||
|
if v6 then
|
||||||
|
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
|
||||||
|
if #nodes < 1 then return end
|
||||||
|
vm_context.write = true
|
||||||
|
local data = vm_context.data
|
||||||
|
local area = vm_context.area
|
||||||
|
for n = 1, #nodes do
|
||||||
|
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
|
||||||
|
if data[p_pos] == c_water then
|
||||||
|
data[p_pos] = c_nether_lava
|
||||||
|
elseif data[p_pos] == c_stone then
|
||||||
|
data[p_pos] = c_netherrack
|
||||||
|
elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then
|
||||||
|
data[p_pos] = c_soul_sand
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
end
|
||||||
|
|
||||||
|
generate_underground_mushrooms(minp, maxp, seed)
|
||||||
|
generate_nether_decorations(minp, maxp, seed)
|
||||||
|
end, 1)
|
|
@ -0,0 +1,49 @@
|
||||||
|
local c_air = minetest.CONTENT_AIR
|
||||||
|
|
||||||
|
mcl_mapgen.register_on_generated(function(vm_context)
|
||||||
|
local minp, maxp = vm_context.minp, vm_context.maxp
|
||||||
|
|
||||||
|
if minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then
|
||||||
|
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
|
||||||
|
if #nodes > 0 then
|
||||||
|
for _, n in pairs(nodes) do
|
||||||
|
data[area:index(n.x, n.y, n.z)] = c_air
|
||||||
|
end
|
||||||
|
end
|
||||||
|
vm_context.write = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if minp.y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end
|
||||||
|
local vm, data, area = vm_context.vm, vm_context.data, vm_context.area
|
||||||
|
|
||||||
|
--[[ Remove broken double plants caused by v6 weirdness.
|
||||||
|
v6 might break the bottom part of double plants because of how it works.
|
||||||
|
There are 3 possibilities:
|
||||||
|
1) Jungle: Top part is placed on top of a jungle tree or fern (=v6 jungle grass).
|
||||||
|
This is because the schematic might be placed even if some nodes of it
|
||||||
|
could not be placed because the destination was already occupied.
|
||||||
|
TODO: A better fix for this would be if schematics could abort placement
|
||||||
|
altogether if ANY of their nodes could not be placed.
|
||||||
|
2) Cavegen: Removes the bottom part, the upper part floats
|
||||||
|
3) Mudflow: Same as 2) ]]
|
||||||
|
local plants = minetest.find_nodes_in_area(minp, maxp, "group:double_plant")
|
||||||
|
for n = 1, #plants do
|
||||||
|
local node = vm:get_node_at(plants[n])
|
||||||
|
local is_top = minetest.get_item_group(node.name, "double_plant") == 2
|
||||||
|
if is_top then
|
||||||
|
local p_pos = area:index(plants[n].x, plants[n].y-1, plants[n].z)
|
||||||
|
if p_pos then
|
||||||
|
node = vm:get_node_at({x=plants[n].x, y=plants[n].y-1, z=plants[n].z})
|
||||||
|
local is_bottom = minetest.get_item_group(node.name, "double_plant") == 1
|
||||||
|
if not is_bottom then
|
||||||
|
p_pos = area:index(plants[n].x, plants[n].y, plants[n].z)
|
||||||
|
data[p_pos] = c_air
|
||||||
|
vm_context.write = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end, 999999999)
|
Loading…
Reference in New Issue