mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-16 16:11:06 +01:00
cleanups and fixes
This commit is contained in:
parent
27b6963d20
commit
d7ac288ba1
18 changed files with 300 additions and 229 deletions
|
@ -4,7 +4,7 @@ local modpath = minetest.get_modpath(modname)
|
|||
vl_structures.register_structure("fossil",{
|
||||
place_on = {"group:material_stone","group:sand"},
|
||||
flags = "place_center_x, place_center_z",
|
||||
prepare = { },
|
||||
prepare = false,
|
||||
chunk_probability = 15, -- was 25, FIXME: needs rebalancing
|
||||
y_offset = function(pr) return pr:next(-32,-16) end,
|
||||
y_max = 15,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local water_level = minetest.get_mapgen_setting("water_level")
|
||||
|
||||
local cold_oceans = {
|
||||
"RoofedForest_ocean",
|
||||
|
@ -71,14 +72,15 @@ local warm_oceans = {
|
|||
|
||||
local cold = {
|
||||
place_on = {"group:sand","mcl_core:gravel","mcl_core:dirt","mcl_core:clay","group:material_stone"},
|
||||
spawn_by = {"mcl_core:water_source"},
|
||||
spawn_by = {"group:water"},
|
||||
num_spawn_by = 2,
|
||||
flags = "place_center_x, place_center_z, force_placement",
|
||||
y_offset = -1,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = -2,
|
||||
chunk_probability = 10, -- todo: 15?
|
||||
biomes = cold_oceans,
|
||||
chunk_probability = 10,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = water_level - 6,
|
||||
y_offset = -1,
|
||||
flags = "place_center_x, place_center_z, force_placement",
|
||||
prepare = { foundation = -2, clear = false, mode="water" },
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_ocean_ruins_cold_1.mts",
|
||||
modpath.."/schematics/mcl_structures_ocean_ruins_cold_2.mts",
|
||||
|
|
|
@ -82,7 +82,7 @@ vl_structures.register_structure("ocean_temple",{
|
|||
},
|
||||
flags = "force_placement",
|
||||
force_place = true,
|
||||
prepare = { tolerance = -1, clear = false, foundation = false },
|
||||
prepare = { tolerance = 8, clear = false, foundation = 3, mode="water" },
|
||||
biomes = ocean_biomes,
|
||||
y_max = water_level-4,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
|
@ -90,7 +90,7 @@ vl_structures.register_structure("ocean_temple",{
|
|||
modpath .. "/schematics/mcl_structures_ocean_temple.mts",
|
||||
modpath .. "/schematics/mcl_structures_ocean_temple_2.mts",
|
||||
},
|
||||
y_offset = function(pr) return pr:next(-2,0) end,
|
||||
y_offset = -1, --function(pr) return pr:next(-2,-1) end, -- fewer mobs if buried in sand
|
||||
after_place = function(p, _, pr, p1, p2)
|
||||
vl_structures.spawn_mobs("mobs_mc:guardian",spawnon,p1,p2,pr,5,true)
|
||||
vl_structures.spawn_mobs("mobs_mc:guardian_elder",spawnon,p1,p2,pr,1,true)
|
||||
|
|
|
@ -6,7 +6,7 @@ local spawnon = {"mcl_core:stripped_oak","mcl_stairs:slab_birchwood_top"}
|
|||
vl_structures.register_structure("pillager_outpost",{
|
||||
place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass","group:sand"},
|
||||
flags = "place_center_x, place_center_z",
|
||||
prepare = { padding = 3, corners = 4, foundation = -6, clear = true },
|
||||
prepare = { padding = 3, corners = 4, foundation = -8, clear = true },
|
||||
y_offset = 0,
|
||||
chunk_probability = 15,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
|
|
|
@ -2,15 +2,6 @@ local modname = minetest.get_current_modname()
|
|||
local modpath = minetest.get_modpath(modname)
|
||||
local water_level = minetest.get_mapgen_setting("water_level")
|
||||
|
||||
--schematics by chmodsayshello
|
||||
local schems = {
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_normal.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_back_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_front.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_back.mts",
|
||||
}
|
||||
|
||||
local ocean_biomes = {
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
|
@ -74,44 +65,27 @@ local ocean_biomes = {
|
|||
"JungleM_ocean"
|
||||
}
|
||||
|
||||
local beach_biomes = {
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore"
|
||||
}
|
||||
|
||||
-- FIXME: integrate treasure maps from MCLA
|
||||
|
||||
vl_structures.register_structure("shipwreck",{
|
||||
place_on = {"group:sand","mcl_core:gravel"},
|
||||
spawn_by = {"group:water"},
|
||||
num_spawn_by = 4,
|
||||
noise_params = {
|
||||
offset = 0,
|
||||
scale = 0.000022,
|
||||
spread = {x = 250, y = 250, z = 250},
|
||||
seed = 3,
|
||||
octaves = 3,
|
||||
persist = 0.001,
|
||||
flags = "absvalue",
|
||||
},
|
||||
flags = "force_placement",
|
||||
chunk_probability = 10, -- todo: 15?
|
||||
biomes = ocean_biomes,
|
||||
y_max = water_level-4,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
prepare = { tolerance = -1, clear = false, foundation = false },
|
||||
filenames = schems,
|
||||
y_max = water_level-4,
|
||||
y_offset = function(pr) return pr:next(-4,-2) end,
|
||||
flags = "place_center_x, place_center_z, force_placement",
|
||||
prepare = { tolerance = -1, clear = false, foundation = -2, mode = "water" },
|
||||
filenames = {
|
||||
--schematics by chmodsayshello
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_normal.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_back_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_front.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_back.mts",
|
||||
},
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {
|
||||
{
|
||||
|
|
|
@ -251,7 +251,7 @@ function mcl_villages.post_process_village(blockseed)
|
|||
local jobs, beds = {}, {}
|
||||
|
||||
local bell_pos = vector.copy(settlement_info[1].pos)
|
||||
local bell = vector.offset(bell_pos, 0, 1, 0)
|
||||
local bell = vector.offset(bell_pos, 0, 2, 0)
|
||||
local biome_name = minetest.get_biome_name(minetest.get_biome_data(bell_pos).biome)
|
||||
|
||||
-- Spawn Golem
|
||||
|
|
|
@ -1,37 +1,107 @@
|
|||
# vl_structures
|
||||
|
||||
Updated API for structure spawning for VoxeLibre and Mineclonia
|
||||
Updated API for structure spawning.
|
||||
|
||||
## vl_structures.register_structure(name,structure definition,nospawn)
|
||||
If nospawn is truthy the structure will not be placed by mapgen and the decoration parameters can be omitted. This is intended for secondary structures the placement of which gets triggered by the placement of other structures. It can also be used to register testing structures so they can be used with /spawnstruct.
|
||||
This module was developed with VoxeLibre and Mineclonia in mind, but means to be portable or at least easy to adapt to other games.
|
||||
|
||||
### structure definition
|
||||
## structure definition
|
||||
|
||||
Structures in this API are defined using the following table:
|
||||
|
||||
```
|
||||
{
|
||||
fill_ratio = OR noise = {},
|
||||
biomes = {},
|
||||
y_min =,
|
||||
y_max =,
|
||||
place_on = {},
|
||||
spawn_by = {},
|
||||
num_spawn_by =,
|
||||
flags = (default: "place_center_x, place_center_z, force_placement")
|
||||
(same as decoration def)
|
||||
y_offset =, --can be a number or a function returning a number
|
||||
filenames = {} OR place_func = function(pos,def,pr)
|
||||
-- filenames can be a list of any schematics accepted by mcl_structures.place_schematic / minetest.place_schematic
|
||||
on_place = function(pos,def,pr) end,
|
||||
-- called before placement. denies placement when returning falsy.
|
||||
after_place = function(pos,def,pr)
|
||||
-- executed after successful placement
|
||||
prepare = table, -- a foundation is automatically built for the structure
|
||||
loot = ,
|
||||
--a table of loot tables for mcl_loot indexed by node names
|
||||
name =, -- structure identifier for logging
|
||||
priority = 100, -- priority to make placement order more deterministic. Default 100 except for terrain features (900)
|
||||
chunk_probability =, -- ratio that a block is chosen, 10 means 1-in-10 blocks
|
||||
fill_ratio = nil, -- OR number of structure spawn attempts per map chunk, default is 1/(80 x 80) when chunk_probability is set
|
||||
noise = nil, -- OR specify noise parameters, as per minetest.register_decoration
|
||||
y_min =, -- minimum depth
|
||||
y_max =, -- maximum depth
|
||||
biomes = {}, -- biome restriction
|
||||
place_on = {}, -- if nil, the structure will not be automatically spawned
|
||||
spawn_by = {}, -- nodes required nearby, as in minetest.register_decoration
|
||||
num_spawn_by =, -- number of nodes required nearby
|
||||
prepare =, -- configure foundation and clearing, see vl_terraforming -- ignored for place_func
|
||||
flags =, -- minetest.register_decoration placement flags, default: "place_center_x, place_center_z"
|
||||
y_offset =, -- vertical placement offset, can be a number or a function(pr) returning a number
|
||||
filenames = {}, -- table of schematic filenames
|
||||
schematics = {}, -- OR table of preloaded schematics
|
||||
place_func = function(pos,def,pr,blockseed)
|
||||
-- OR a function to place a structure
|
||||
after_place = function(pos,def,pr,pmin,pmax,size,rotation)
|
||||
-- callback executed after successful placement
|
||||
loot =, -- a table of loot tables for mcl_loot indexed by node names -- ignored for place_func, to be removed
|
||||
-- e.g. { ["mcl_chests:chest_small"] = {loot},... }
|
||||
terrain_feature =, -- affects placement priority and disables logging for uninteresting structures
|
||||
daughters =, -- substructures to spawn, unstable API
|
||||
}
|
||||
```
|
||||
|
||||
## vl_structures.register_structure(name,def)
|
||||
|
||||
Register a new structure spawn.
|
||||
|
||||
For extension modules, if you choose a larger (later) placement priority, this
|
||||
should be less likely to change spawning of original structures and keep the
|
||||
resulting maps more consistent across seeds.
|
||||
|
||||
## vl_structures.load_schematic(filename, name)
|
||||
|
||||
Load a schematic from a given file name, the name is used for error logging; otherwise it will be derived from the file name.
|
||||
|
||||
## vl_structures.place_structure(pos, def, pr, blockseed, rot)
|
||||
|
||||
Places structure defined by def at position pos, using the pseudorandom pr.
|
||||
|
||||
blockseed is only used by the place_func call, and unused for many simple structures.
|
||||
|
||||
rot is optional, it will then be chosen randomly.
|
||||
|
||||
This is usually called from the mapgen decoration gennotify mechanism, but can be used for substructure spawns.
|
||||
|
||||
## vl_structures.registered_structures
|
||||
|
||||
Table of the registered structure defintions indexed by name.
|
||||
|
||||
## vl_structures.place_structure(pos, def, pr)
|
||||
Places a structure using the mapgen placement function
|
||||
## vl_structures.place_schematic(pos, yoffset, schematic, rotation, def, pr)
|
||||
|
||||
Spawn a structure as defined by "def" at the given position, yoffset, schematic, and rotation.
|
||||
|
||||
This is primarily meant for substructure placement where size (and hence schematic and offsets) need to be fixed before computing the position.
|
||||
|
||||
## vl_structures.parse_rotation(rotation, pr)
|
||||
|
||||
Parse a rotation value (stirngs "0", "90", "180", "270" or "random"), or choosing a random rotation.
|
||||
|
||||
## vl_structures.size_rotated(size, rotation)
|
||||
|
||||
Return the size after rotation, i.e., if rotation is 90 or 270, the x and z sizes are swapped.
|
||||
|
||||
## vl_structures.top_left_from_flags(pos, size, flags)
|
||||
|
||||
Compute the top left corner from the flags, i.e., parse place_center_x, place_center_z etc.
|
||||
|
||||
## vl_structures.get_extends(pos, size, yoffset, rotation, flags)
|
||||
|
||||
Parse rotation and flags, and return the center, minimum corner, maximum corner, and size.
|
||||
|
||||
## vl_structures.init_node_construct(pos)
|
||||
|
||||
Call on_construct callbacks for the node at the given position.
|
||||
|
||||
## vl_structures.construct_nodes(p1,p2,nodes)
|
||||
|
||||
Find all nodes of the listed types in the area and call their on_construct callbacks.
|
||||
|
||||
## vl_structures.fill_chests(p1,p2,loot,pr)
|
||||
|
||||
Fill all loot containers in the area, requires mcl_loot and likely should be moved to the loot API.
|
||||
|
||||
## vl_structures.spawn_mobs(mob,spawnon,p1,p2,pr,n,water)
|
||||
|
||||
This function spawns the desired mobs in the given area. The function should move to the mobs API.
|
||||
|
||||
## vl_structures.register_structure_spawn(def)
|
||||
|
||||
This function creates a spawn ABM for the desired mobs. The function should move to the mobs API.
|
||||
|
||||
## vl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param)
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
vl_structures.registered_structures = {}
|
||||
|
||||
local structure_boost = tonumber(minetest.settings:get("vl_structures_boost")) or 1
|
||||
local worldseed = minetest.get_mapgen_setting("seed")
|
||||
local RANDOM_SEED_OFFSET = 959 -- random constant that should be unique across each library
|
||||
|
||||
local vector_offset = vector.offset
|
||||
|
||||
-- FIXME: switch to vl_structures_logging?
|
||||
local logging = true or minetest.settings:get_bool("mcl_logging_structures", true)
|
||||
|
||||
-- FIXME: switch to vl_structures_disabled?
|
||||
local disabled_structures = minetest.settings:get("mcl_disabled_structures")
|
||||
local logging = minetest.settings:get_bool("vl_structures_logging", false)
|
||||
local disabled_structures = minetest.settings:get("vl_structures_disabled")
|
||||
disabled_structures = disabled_structures and disabled_structures:split(",") or {}
|
||||
function vl_structures.is_disabled(structname)
|
||||
return table.indexof(disabled_structures,structname) ~= -1
|
||||
end
|
||||
|
||||
local worldseed = minetest.get_mapgen_setting("seed")
|
||||
local RANDOM_SEED_OFFSET = 959 -- random constant that should be unique across each library
|
||||
local vector_offset = vector.offset
|
||||
|
||||
--- Trim a full path name to its last two parts as short name for logging
|
||||
local function basename(filename)
|
||||
local fn = string.split(filename, "/")
|
||||
|
@ -106,25 +102,23 @@ function vl_structures.place_structure(pos, def, pr, blockseed, rot)
|
|||
end
|
||||
local pp = yoffset ~= 0 and vector_offset(pos, 0, yoffset, 0) or pos
|
||||
if def.place_func and def.prepare then
|
||||
minetest.log("warning", "[vl_structures] needed prepare for "..def.name.." placed at "..minetest.pos_to_string(pp).." but do not have size information")
|
||||
minetest.log("warning", "[vl_structures] needed prepare for "..def.name.." placed at "..minetest.pos_to_string(pp).." but do not have size information.")
|
||||
end
|
||||
if def.place_func and def.place_func(pp,def,pr,blockseed) then
|
||||
if not def.after_place or (def.after_place and def.after_place(pos,def,pr,pmin,pmax,size,param.rotation)) then
|
||||
if def.sidelen then
|
||||
local p1, p2 = vector_offset(pos,-def.sidelen,-def.sidelen,-def.sidelen), vector.offset(pos,def.sidelen,def.sidelen,def.sidelen)
|
||||
if def.loot then vl_structures.fill_chests(p1,p2,def.loot,pr) end
|
||||
if def.construct_nodes then vl_structures.construct_nodes(p1,p2,def.construct_nodes) end
|
||||
if def.after_place and not def.after_place(pos,def,pr,pmin,pmax,size,param.rotation) then
|
||||
minetest.log("warning", "[vl_structures] after_place failed for structure "..def.name)
|
||||
return false
|
||||
end
|
||||
if log_enabled then
|
||||
minetest.log("action","[vl_structures] "..def.name.." placed at "..minetest.pos_to_string(pp))
|
||||
end
|
||||
return true
|
||||
else
|
||||
minetest.log("warning","[vl_structures] after_place failed for schematic "..def.name)
|
||||
return false
|
||||
end
|
||||
elseif log_enabled then
|
||||
minetest.log("warning","[vl_structures] place_func failed for schematic "..def.name)
|
||||
if def.place_func then
|
||||
minetest.log("warning","[vl_structures] place_func failed for structure "..def.name)
|
||||
else
|
||||
minetest.log("warning","[vl_structures] do not know how to place structure "..def.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -139,13 +133,13 @@ function vl_structures.register_structure(name,def)
|
|||
def.name = name
|
||||
vl_structures.registered_structures[name] = def
|
||||
if def.prepare and def.prepare.clear == nil and (def.prepare.clear_bottom or def.prepare.clear_top) then def.prepare.clear = true end
|
||||
if not def.noise_params and def.chunk_probability and not def.fill_ratio then
|
||||
if not def.fill_ratio and def.chunk_probability and not def.noise_params then
|
||||
def.fill_ratio = 1.1/80/80 -- 1 per chunk, controlled by chunk probability only
|
||||
end
|
||||
def.flags = def.flags or vl_structures.DEFAULT_FLAGS
|
||||
if def.filenames then
|
||||
for _, filename in ipairs(def.filenames) do
|
||||
if not mcl_util.file_exists(filename) then
|
||||
if mcl_util and not mcl_util.file_exists(filename) then
|
||||
minetest.log("warning","[vl_structures] schematic "..(name or "unknown").." is missing file "..basename(filename))
|
||||
return nil
|
||||
end
|
||||
|
@ -153,21 +147,22 @@ function vl_structures.register_structure(name,def)
|
|||
end
|
||||
if def.place_on then
|
||||
minetest.register_on_mods_loaded(function()
|
||||
def.deco = mcl_mapgen_core.register_decoration({
|
||||
local register_decoration = mcl_mapgen_core.register_decoration or minetest.register_decoration -- optional dependency
|
||||
register_decoration({
|
||||
name = "vl_structures:"..name,
|
||||
priority = def.priority or (def.terrain_feature and 900) or 100, -- run before regular decorations
|
||||
deco_type = "schematic",
|
||||
schematic = EMPTY_SCHEMATIC, -- use gennotify only
|
||||
fill_ratio = def.fill_ratio,
|
||||
noise_params = def.noise_params,
|
||||
y_max = def.y_max,
|
||||
y_min = def.y_min,
|
||||
biomes = def.biomes,
|
||||
place_on = def.place_on,
|
||||
spawn_by = def.spawn_by,
|
||||
num_spawn_by = def.num_spawn_by,
|
||||
sidelen = 80, -- no def.sidelen subdivisions for now, this field was used differently before
|
||||
fill_ratio = def.fill_ratio,
|
||||
noise_params = def.noise_params,
|
||||
flags = def.flags,
|
||||
biomes = def.biomes,
|
||||
y_max = def.y_max,
|
||||
y_min = def.y_min,
|
||||
deco_type = "schematic",
|
||||
schematic = EMPTY_SCHEMATIC, -- use gennotify only
|
||||
gen_callback = function(t,minp,maxp,blockseed)
|
||||
for _, pos in ipairs(t) do
|
||||
local pr = PcgRandom(minetest.hash_node_position(pos) + worldseed + RANDOM_SEED_OFFSET)
|
||||
|
@ -183,6 +178,7 @@ function vl_structures.register_structure(name,def)
|
|||
end
|
||||
|
||||
-- To avoid a cyclic dependency, run this when modules have finished loading
|
||||
-- Maybe we can eventually remove this - the end portal should likely go into the mapgen itself.
|
||||
minetest.register_on_mods_loaded(function()
|
||||
mcl_mapgen_core.register_generator("static structures", nil, function(minp, maxp, blockseed)
|
||||
for _,struct in pairs(vl_structures.registered_structures) do
|
||||
|
@ -200,37 +196,3 @@ mcl_mapgen_core.register_generator("static structures", nil, function(minp, maxp
|
|||
end, 100, true)
|
||||
end)
|
||||
|
||||
local structure_spawns = {}
|
||||
function vl_structures.register_structure_spawn(def)
|
||||
--name,y_min,y_max,spawnon,biomes,chance,interval,limit
|
||||
minetest.register_abm({
|
||||
label = "Spawn "..def.name,
|
||||
nodenames = def.spawnon,
|
||||
min_y = def.y_min or -31000,
|
||||
max_y = def.y_max or 31000,
|
||||
interval = def.interval or 60,
|
||||
chance = def.chance or 5,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local limit = def.limit or 7
|
||||
if active_object_count_wider > limit + mob_cap_animal then return end
|
||||
if active_object_count_wider > mob_cap_player then return end
|
||||
local p = vector_offset(pos, 0, 1, 0)
|
||||
local pname = minetest.get_node(p).name
|
||||
if def.type_of_spawning == "water" then
|
||||
if pname ~= "mcl_core:water_source" and pname ~= "mclx_core:river_water_source" then return end
|
||||
else
|
||||
if pname ~= "air" then return end
|
||||
end
|
||||
if minetest.get_meta(pos):get_string("spawnblock") == "" then return end
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" and def.biomes then
|
||||
if table.indexof(def.biomes, minetest.get_biome_name(minetest.get_biome_data(p).biome)) == -1 then
|
||||
return
|
||||
end
|
||||
end
|
||||
local mobdef = minetest.registered_entities[def.name]
|
||||
if mobdef.can_spawn and not mobdef.can_spawn(p) then return end
|
||||
minetest.add_entity(p, def.name)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
@ -1,22 +1,14 @@
|
|||
local DEFAULT_FLAGS = vl_structures.DEFAULT_FLAGS
|
||||
local DEFAULT_PREPARE = vl_structures.DEFAULT_PREPARE
|
||||
|
||||
local vector_offset = vector.offset
|
||||
local floor = math.floor
|
||||
|
||||
-- FIXME: switch to vl_structures_logging?
|
||||
local logging = true or minetest.settings:get_bool("mcl_logging_structures", true)
|
||||
|
||||
local logging = minetest.settings:get_bool("vl_structures_logging", false)
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
|
||||
-- parse the prepare parameter
|
||||
local function parse_prepare(prepare)
|
||||
if prepare == nil or prepare == true then return DEFAULT_PREPARE end
|
||||
if prepare == nil or prepare == true then return vl_structures.DEFAULT_PREPARE end
|
||||
if prepare == false then return {} end
|
||||
if prepare.foundation == true then
|
||||
prepare = table.copy(prepare)
|
||||
prepare.foundation = DEFAULT_PREPARE.foundation
|
||||
end
|
||||
if prepare.foundation == true then prepare.foundation = vl_structures.DEFAULT_PREPARE.foundation end
|
||||
return prepare
|
||||
end
|
||||
|
||||
|
@ -68,17 +60,17 @@ local function emerge_schematics(blockpos, action, calls_remaining, param)
|
|||
local prepare_start = os.clock()
|
||||
-- Get materials from biome (TODO: make this a function + table?):
|
||||
local b = mg_name ~= "v6" and minetest.registered_biomes[minetest.get_biome_name(minetest.get_biome_data(pos).biome)]
|
||||
local node_top = b and b.node_top and { name = b.node_top } or surface_mat or { name = "mcl_core:dirt_with_grass" }
|
||||
local node_filler = { name = b and b.node_filler or "mcl_core:dirt" }
|
||||
local node_stone = { name = b and b.node_stone or "mcl_core:stone" }
|
||||
local node_dust = b and b.node_dust and { name = b.node_dust } or nil
|
||||
local node_top = b and b.node_top and { name = b.node_top } or surface_mat or vl_structures.DEFAULT_SURFACE
|
||||
local node_filler = b and b.node_filler and { name = b.node_filler } or vl_structures.DEFAULT_FILLER
|
||||
local node_stone = b and b.node_stone and { name = b.node_stone } or vl_structures.DEFAULT_STONE
|
||||
local node_dust = b and b.node_dust and { name = b.node_dust } or vl_structures.DEFAULT_DUST
|
||||
if node_top.name == "mcl_core:dirt_with_grass" and b then node_top.param2 = b._mcl_grass_palette_index end
|
||||
|
||||
-- Step 2a: clear overhead area
|
||||
local corners, padding, depth = prepare.corners or 1, prepare.padding or 1, (type(prepare.foundation) == "number" and prepare.foundation) or -4
|
||||
local corners, padding = prepare.corners or 1, prepare.padding or 1
|
||||
local gp = vector_offset(pmin, -padding, -yoffset, -padding) -- base level
|
||||
if prepare.clear then
|
||||
local yoff, ymax = prepare.clear_bottom or 0, size.y + yoffset + (prepare.clear_top or DEFAULT_PREPARE.clear_top)
|
||||
local yoff, ymax = prepare.clear_bottom or 0, size.y + yoffset + (prepare.clear_top or vl_structures.DEFAULT_PREPARE.clear_top)
|
||||
if prepare.clear_bottom == "top" or prepare.clear_bottom == "above" then yoff = size.y + yoffset end
|
||||
--minetest.log("action", "[vl_structures] clearing air "..minetest.pos_to_string(gp)..": ".. (size.x + padding * 2)..","..ymax..","..(size.z + padding * 2))
|
||||
vl_terraforming.clearance_vm(vm, gp.x, gp.y + yoff, gp.z,
|
||||
|
@ -91,7 +83,7 @@ local function emerge_schematics(blockpos, action, calls_remaining, param)
|
|||
if ddp and ddp.clear then
|
||||
local dsize = vl_structures.size_rotated(ds.size, dr) -- FIXME: rotation of parent
|
||||
local corners, padding, yoffset = ddp.corners or 1, ddp.padding or 1, ddp.yoffset or 0
|
||||
local yoff, ymax = ddp.clear_bottom or 0, dsize.y + yoffset + (ddp.clear_top or DEFAULT_PREPARE.clear_top)
|
||||
local yoff, ymax = ddp.clear_bottom or 0, dsize.y + yoffset + (ddp.clear_top or vl_structures.DEFAULT_PREPARE.clear_top)
|
||||
if ddp.clear_bottom == "top" or ddp.clear_bottom == "above" then yoff = dsize.y + yoffset end
|
||||
local gp = vector_offset(pos, dd.pos.x - floor((dsize.x-1)*0.5) - padding,
|
||||
dd.pos.y,
|
||||
|
@ -110,7 +102,7 @@ local function emerge_schematics(blockpos, action, calls_remaining, param)
|
|||
-- Step 2b: baseplate underneath
|
||||
if prepare.foundation then
|
||||
-- minetest.log("action", "[vl_structures] fill foundation "..minetest.pos_to_string(gp).." with "..tostring(node_top.name).." "..tostring(node_filler.name))
|
||||
local depth = (type(prepare.foundation) == "number" and prepare.foundation) or DEFAULT_PREPARE.foundation
|
||||
local depth = (type(prepare.foundation) == "number" and prepare.foundation) or vl_structures.DEFAULT_PREPARE.foundation
|
||||
vl_terraforming.foundation_vm(vm, gp.x, gp.y - 1, gp.z,
|
||||
size.x + padding * 2, depth, size.z + padding * 2,
|
||||
corners, node_top, node_filler, node_stone, node_dust, pr)
|
||||
|
@ -121,7 +113,7 @@ local function emerge_schematics(blockpos, action, calls_remaining, param)
|
|||
if ddp and ddp.foundation then
|
||||
local dsize = vl_structures.size_rotated(ds.size, dr) -- FIXME: rotation of parent
|
||||
local corners, padding, yoffset = ddp.corners or 1, ddp.padding or 1, ddp.yoffset or 0
|
||||
local depth = (type(ddp.foundation) == "number" and ddp.foundation) or DEFAULT_PREPARE.foundation
|
||||
local depth = (type(ddp.foundation) == "number" and ddp.foundation) or vl_structures.DEFAULT_PREPARE.foundation
|
||||
local gp = vector_offset(pos, dd.pos.x - floor((dsize.x-1)*0.5) - padding,
|
||||
dd.pos.y + (yoffset or 0),
|
||||
dd.pos.z - floor((dsize.z-1)*0.5) - padding)
|
||||
|
@ -158,16 +150,16 @@ vl_structures.place_schematic = function(pos, yoffset, schematic, rotation, def,
|
|||
if schematic and not schematic.size then schematic = vl_structures.load_schematic(schematic) end -- legacy
|
||||
local rotation = vl_structures.parse_rotation(rotation, pr)
|
||||
local prepare = parse_prepare(def.prepare)
|
||||
local ppos, pmin, pmax, size = vl_structures.get_extends(pos, schematic.size, yoffset, rotation, def.flags or DEFAULT_FLAGS)
|
||||
local ppos, pmin, pmax, size = vl_structures.get_extends(pos, schematic.size, yoffset, rotation, def.flags or vl_structures.DEFAULT_FLAGS)
|
||||
-- area to emerge. Add some margin to allow for finding better suitable ground etc.
|
||||
local tolerance = prepare.tolerance or DEFAULT_PREPARE.tolerance -- may be negative to disable foundations
|
||||
local tolerance = prepare.tolerance or vl_structures.DEFAULT_PREPARE.tolerance -- may be negative to disable foundations
|
||||
if type(tolerance) ~= "number" then tolerance = 10 end -- extra height for emerge only, min/max/liquid_surface
|
||||
local emin, emax = vector_offset(pmin, 0, -math.max(tolerance, 0), 0), vector.offset(pmax, 0, math.max(tolerance, 0), 0)
|
||||
-- if we need to generate a foundation, we need to emerge a larger area:
|
||||
if prepare.foundation or prepare.clear then -- these functions need some extra margins. Must match mcl_foundations!
|
||||
if prepare.foundation or prepare.clear then -- these functions need some extra margins. Must match vl_terraforming!
|
||||
local padding = (prepare.padding or 0) + 3
|
||||
local depth = prepare.foundation and ((type(prepare.foundation) == "number" and prepare.foundation or DEFAULT_PREPARE.foundation) - 3) or 0 -- minimum depth
|
||||
local height = prepare.clear and ((prepare.clear_top or DEFAULT_PREPARE.clear_top)*1.5+0.5*(size.y+yoffset)+2) or 0 -- headroom
|
||||
local depth = prepare.foundation and ((type(prepare.foundation) == "number" and prepare.foundation or vl_structures.DEFAULT_PREPARE.foundation) - 3) or 0 -- minimum depth
|
||||
local height = prepare.clear and ((prepare.clear_top or vl_structures.DEFAULT_PREPARE.clear_top)*1.5+0.5*(size.y+yoffset)+2) or 0 -- headroom
|
||||
emin = vector_offset(emin, -padding, depth, -padding)
|
||||
emax = vector_offset(emax, padding, height, padding)
|
||||
end
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
vl_structures = {}
|
||||
|
||||
---- Customization parameters for different games
|
||||
-- see vl_terraforming for documentation
|
||||
vl_structures.DEFAULT_PREPARE = { tolerance = 10, foundation = -3, clear = false, clear_bottom = 0, clear_top = 4, padding = 1, corners = 1 }
|
||||
vl_structures.DEFAULT_FLAGS = "place_center_x,place_center_z"
|
||||
|
||||
-- fallback types
|
||||
vl_structures.DEFAULT_SURFACE = { name = "mcl_core:dirt_with_grass" }
|
||||
vl_structures.DEFAULT_FILLER = { name = "mcl_core:dirt" }
|
||||
vl_structures.DEFAULT_STONE = { name = "mcl_core:stone" }
|
||||
vl_structures.DEFAULT_DUST = nil
|
||||
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
dofile(modpath.."/util.lua")
|
||||
dofile(modpath.."/emerge.lua")
|
||||
dofile(modpath.."/api.lua")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name = vl_structures
|
||||
author = kno10
|
||||
description = Structures API for VoxeLibre and Mineclonia
|
||||
depends = mcl_init, mcl_util, mcl_loot, vl_terraforming
|
||||
description = Structure spawning API for VoxeLibre
|
||||
depends = vl_terraforming
|
||||
optional_depends = mcl_util, mcl_loot
|
||||
|
|
|
@ -1,10 +1,54 @@
|
|||
-- todo: move this mostly to the mcl_mobs module?
|
||||
-- TODO: move this to the mcl_mobs module?
|
||||
local mob_cap_player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75
|
||||
local mob_cap_animal = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10
|
||||
local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false)
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
local vector_offset = vector.offset
|
||||
|
||||
-- check if a node is an air node
|
||||
local function is_air(node)
|
||||
return node == "air"
|
||||
-- todo: or: not walkable and not liquid?
|
||||
end
|
||||
-- check if a node is a water node
|
||||
local function is_water(node)
|
||||
return minetest.get_item_group(node.name, "water") ~= 0
|
||||
-- return node.name == "mcl_core:water_source" or node.name ~= "mclx_core:river_water_source"
|
||||
end
|
||||
|
||||
--- Spawn mobs for a structure
|
||||
-- @param mob string: mob to spawn
|
||||
-- @param spawnon string or table: nodes to spawn on
|
||||
-- @param p1 vector: Lowest coordinates of range
|
||||
-- @param p2 vector: Highest coordinates of range
|
||||
-- @param pr PseudoRandom: random generator
|
||||
-- @param n number: Number of mobs to spawn
|
||||
-- @param water boolean: Spawn water mobs
|
||||
function vl_structures.spawn_mobs(mob,spawnon,p1,p2,pr,n,water)
|
||||
n = n or 1
|
||||
local sp = {}
|
||||
if water then
|
||||
local nn = minetest.find_nodes_in_area(p1,p2,spawnon)
|
||||
for k,v in pairs(nn) do
|
||||
if is_water(minetest.get_node(vector_offset(v,0,1,0))) then
|
||||
table.insert(sp,v)
|
||||
end
|
||||
end
|
||||
else
|
||||
sp = minetest.find_nodes_in_area_under_air(p1,p2,spawnon)
|
||||
end
|
||||
table.shuffle(sp)
|
||||
local count = 0
|
||||
local mob_def = minetest.registered_entities[mob]
|
||||
local enabled = (not peaceful) or (mob_def and mob_spawn_class ~= "hostile")
|
||||
for _, node in pairs(sp) do
|
||||
if enabled and count < n and minetest.add_entity(vector_offset(node, 0, 0.5, 0), mob) then
|
||||
count = count + 1
|
||||
end
|
||||
minetest.get_meta(node):set_string("spawnblock", "yes") -- note: also in peaceful mode!
|
||||
end
|
||||
end
|
||||
|
||||
local structure_spawns = {}
|
||||
--- Structure spawns via ABM
|
||||
-- @param def table: containing
|
||||
|
@ -30,12 +74,8 @@ function vl_structures.register_structure_spawn(def)
|
|||
if active_object_count_wider > limit + mob_cap_animal then return end
|
||||
if active_object_count_wider > mob_cap_player then return end
|
||||
local p = vector_offset(pos, 0, 1, 0)
|
||||
local pname = minetest.get_node(p).name
|
||||
if def.type_of_spawning == "water" then
|
||||
if pname ~= "mcl_core:water_source" and pname ~= "mclx_core:river_water_source" then return end
|
||||
else
|
||||
if pname ~= "air" then return end -- FIXME: allow everything non-walkable, non-water, non-lava?
|
||||
end
|
||||
local pnode = minetest.get_node(p)
|
||||
if not (def.type_of_spawning == "water" and is_water or is_air)(pnode) then return end
|
||||
if minetest.get_meta(pos):get_string("spawnblock") == "" then return end
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" and def.biomes then
|
||||
if table.indexof(def.biomes, minetest.get_biome_name(minetest.get_biome_data(p).biome)) == -1 then
|
||||
|
@ -49,36 +89,3 @@ function vl_structures.register_structure_spawn(def)
|
|||
})
|
||||
end
|
||||
|
||||
--- Spawn mobs for a structure
|
||||
-- @param mob string: mob to spawn
|
||||
-- @param spawnon string or table: nodes to spawn on
|
||||
-- @param p1 vector: Lowest coordinates of range
|
||||
-- @param p2 vector: Highest coordinates of range
|
||||
-- @param pr PseudoRandom: random generator
|
||||
-- @param n number: Number of mobs to spawn
|
||||
-- @param water boolean: Spawn water mobs
|
||||
function vl_structures.spawn_mobs(mob,spawnon,p1,p2,pr,n,water)
|
||||
n = n or 1
|
||||
local sp = {}
|
||||
if water then
|
||||
local nn = minetest.find_nodes_in_area(p1,p2,spawnon)
|
||||
for k,v in pairs(nn) do
|
||||
if minetest.get_item_group(minetest.get_node(vector_offset(v,0,1,0)).name,"water") > 0 then
|
||||
table.insert(sp,v)
|
||||
end
|
||||
end
|
||||
else
|
||||
sp = minetest.find_nodes_in_area_under_air(p1,p2,spawnon)
|
||||
end
|
||||
table.shuffle(sp)
|
||||
local count = 0
|
||||
local mob_def = minetest.registered_entities[mob]
|
||||
local enabled = (not peaceful) or (mob_def and mob_spawn_class ~= "hostile")
|
||||
for _, node in pairs(sp) do
|
||||
if enabled and count < n and minetest.add_entity(vector_offset(node, 0, 0.5, 0), mob) then
|
||||
count = count + 1
|
||||
end
|
||||
minetest.get_meta(node):set_string("spawnblock", "yes") -- note: also in peaceful mode!
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ end
|
|||
-- @param loot table: Loot table
|
||||
-- @param pr PseudoRandom: random generator
|
||||
function vl_structures.fill_chests(p1,p2,loot,pr)
|
||||
if not mcl_loot then return end -- optional dependency
|
||||
for it,lt in pairs(loot) do
|
||||
local nodes = minetest.find_nodes_in_area(p1, p2, it)
|
||||
for _,p in pairs(nodes) do
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# vl_terraforming
|
||||
Terraforming module for VoxeLibre and MineClonia
|
||||
|
||||
Terraforming module built with VoxeLibre and MineClonia in mind, but also useful for other games.
|
||||
|
||||
This module provides the following key functionalities:
|
||||
|
||||
|
@ -8,7 +9,6 @@ This module provides the following key functionalities:
|
|||
- build a baseplate for a building
|
||||
- clear the area above a building
|
||||
|
||||
|
||||
## Rounded corners support
|
||||
|
||||
To get nicer looking baseplates, the code supports rounded corners.
|
||||
|
@ -55,7 +55,7 @@ One of these values may be "extreme", and tolerance specifies the maximum height
|
|||
|
||||
The (rounded) median of these values is used, unless tolerance is set to "min" or "max".
|
||||
|
||||
The "mode" can be set to "solid" (default), "liquid" (liquid surfaces only), "under_air" (both liquid and solid surfaces).
|
||||
The "mode" can be set to "solid" (default), "liquid" (liquid surfaces only), "under_air" (both liquid and solid surfaces), "under_water" (solid below water).
|
||||
|
||||
|
||||
## vl_terraforming.foundation_vm(vm, px, py, pz, sx, sy, sz, corners, surface_mat, platform_mat, stone_mat, dust_mat, pr)
|
||||
|
@ -94,6 +94,6 @@ pr is a PcgRandom random generator
|
|||
|
||||
- [ ] add an API that works on VM buffers
|
||||
- [ ] add an API version working on the non-VM API
|
||||
- [ ] benchmark if VM is actually faster than not using VM (5.9 has some optimizations not in VM)
|
||||
- [ ] benchmark if VM is actually faster than not using VM (5.9 has some optimizations not yet in VM)
|
||||
- [ ] improve tree removal
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ function vl_terraforming.foundation_vm(vm, px, py, pz, sx, sy, sz, corners, surf
|
|||
end
|
||||
-- construct additional baseplate below, also try to make it interesting
|
||||
for yi = py-2,py-20,-1 do
|
||||
local dy2 = max(0,py-2-yi)^2*0.05
|
||||
local dy2 = max(0,py-2-yi)^2*0.10
|
||||
local active = false
|
||||
for xi = px-1,px+sx do
|
||||
local dx22 = max(abs(cx-xi)-1.49,0)^2*wx2
|
||||
|
|
|
@ -154,6 +154,59 @@ function vl_terraforming.find_liquid_surface_vm(vm, pos)
|
|||
end
|
||||
local find_liquid_surface_vm = vl_terraforming.find_liquid_surface_vm
|
||||
|
||||
--- Find under water surface for a given position
|
||||
-- @param vm VoxelManip: buffer
|
||||
-- @param pos vector: Start position
|
||||
-- @return position and material of surface
|
||||
function vl_terraforming.find_under_water_surface_vm(vm, pos)
|
||||
if not pos then return nil, nil end
|
||||
pos = vector_copy(pos)
|
||||
local cur = vm:get_node_at(pos)
|
||||
if cur.name == "ignore" then
|
||||
local e1, e2 = vm:get_emerged_area()
|
||||
minetest.log("warning", "find_under_water_surface with invalid position (outside of emerged area?) at "..minetest.pos_to_string(pos)
|
||||
..": "..tostring(cur and cur.name).." area: "..minetest.pos_to_string(e1).." "..minetest.pos_to_string(e2))
|
||||
return nil
|
||||
end
|
||||
if is_solid_not_tree(cur) then -- find up
|
||||
local prev = cur
|
||||
while true do
|
||||
pos.y = pos.y + 1
|
||||
local cur = vm:get_node_at(pos)
|
||||
if not cur or cur.name == "ignore" then
|
||||
-- minetest.log("action", "No ground, "..tostring(cur and cur.name).." over "..tostring(prev and prev.name).." at "..minetest.pos_to_string(pos))
|
||||
return nil
|
||||
end
|
||||
if is_liquid(cur) then
|
||||
pos.y = pos.y - 1
|
||||
-- minetest.log("action", "Found surface: "..minetest.pos_to_string(pos).." "..tostring(prev and prev.name).." under "..tostring(cur and cur.name))
|
||||
return pos, prev
|
||||
end
|
||||
prev = cur
|
||||
end
|
||||
else -- find down
|
||||
while true do
|
||||
pos.y = pos.y - 1
|
||||
local prev = cur
|
||||
local cur = vm:get_node_at(pos)
|
||||
if not cur or cur.name == "ignore" then
|
||||
-- minetest.log("action", "No ground, "..tostring(cur and cur.name).." below "..tostring(prev and prev.name).." at "..minetest.pos_to_string(pos))
|
||||
return nil
|
||||
end
|
||||
if is_solid_not_tree(cur) then
|
||||
if is_liquid(prev) then
|
||||
-- minetest.log("action", "Found surface: "..minetest.pos_to_string(pos).." "..(cur and cur.name).." over "..(prev and prev.name))
|
||||
return pos, cur
|
||||
else
|
||||
-- minetest.log("action", "No ground, "..tostring(cur and cur.name).." below "..tostring(prev and prev.name).." at "..minetest.pos_to_string(pos))
|
||||
return nil, nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local find_under_water_surface_vm = vl_terraforming.find_under_water_surface_vm
|
||||
|
||||
--- find suitable height for a structure of this size
|
||||
-- @param vm VoxelManip: to read data
|
||||
-- @param cpos vector: center
|
||||
|
@ -164,10 +217,14 @@ local find_liquid_surface_vm = vl_terraforming.find_liquid_surface_vm
|
|||
function vl_terraforming.find_level_vm(vm, cpos, size, tolerance, mode)
|
||||
local find_ground = find_ground_vm
|
||||
if mode == "liquid_surface" or mode == "liquid" then find_ground = find_liquid_surface_vm end
|
||||
if mode == "under_water" or mode == "water" then find_ground = find_under_water_surface_vm end
|
||||
if mode == "under_air" then find_ground = find_under_air_vm end
|
||||
-- begin at center, then top-left and clockwise
|
||||
local pos, surface_material = find_ground(vm, cpos)
|
||||
if not pos then return nil, nil end
|
||||
if not pos then
|
||||
-- minetest.log("action", "[vl_terraforming] no ground at starting position "..minetest.pos_to_string(cpos).." mode "..tostring(mode or "default"))
|
||||
return nil, nil
|
||||
end
|
||||
local ys = { pos.y }
|
||||
pos.y = pos.y + 1 -- position above surface
|
||||
if size.x == 1 and size.z == 1 then return pos end
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
name = vl_terraforming
|
||||
author = kno10
|
||||
description = Terraforming API for VoxeLibre and Mineclonia
|
||||
description = Terraforming API
|
||||
|
|
|
@ -40,7 +40,7 @@ mcl_doTileDrops (Blocks have drops) bool true
|
|||
mcl_explosions_griefing (Explosions destroy blocks) bool true
|
||||
|
||||
# Comma separated list of disabled structure names
|
||||
mcl_disabled_structures (Disabled structures) string
|
||||
vl_structures_disabled (Disabled structures) string
|
||||
|
||||
# Comma separated list of disabled event names
|
||||
mcl_disabled_events (Disabled events) string
|
||||
|
@ -344,7 +344,7 @@ mcl_logging_mobs_spawn (Log Mob Spawning) bool false
|
|||
mcl_logging_mapgen (Chunk generation logging) bool false
|
||||
|
||||
# If enabled generated structures will be logged
|
||||
mcl_logging_structures (Structure generation logging) bool false
|
||||
vl_structures_logging (Structure generation logging) bool false
|
||||
|
||||
#Complete debug logging for mcl_signs events. Use this if you have issues with signs.
|
||||
mcl_logging_mcl_signs (Complete debug logging for mcl_signs) bool false
|
||||
|
|
Loading…
Reference in a new issue