mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Decorations: Generalise 'spawn by' to be used by all decoration types
In lua_api.txt, make clear that 'place on' and 'spawn by' can be lists.
This commit is contained in:
parent
b77cee146b
commit
b88595050f
@ -3909,7 +3909,7 @@ The Biome API is still in an experimental phase and subject to change.
|
|||||||
{
|
{
|
||||||
deco_type = "simple", -- See "Decoration types"
|
deco_type = "simple", -- See "Decoration types"
|
||||||
place_on = "default:dirt_with_grass",
|
place_on = "default:dirt_with_grass",
|
||||||
-- ^ Node that decoration can be placed on
|
-- ^ Node (or list of nodes) that the decoration can be placed on
|
||||||
sidelen = 8,
|
sidelen = 8,
|
||||||
-- ^ Size of divisions made in the chunk being generated.
|
-- ^ Size of divisions made in the chunk being generated.
|
||||||
-- ^ If the chunk size is not evenly divisible by sidelen, sidelen is made equal to the chunk size.
|
-- ^ If the chunk size is not evenly divisible by sidelen, sidelen is made equal to the chunk size.
|
||||||
@ -3928,6 +3928,13 @@ The Biome API is still in an experimental phase and subject to change.
|
|||||||
-- ^ Minimum and maximum `y` positions these decorations can be generated at.
|
-- ^ Minimum and maximum `y` positions these decorations can be generated at.
|
||||||
-- ^ This parameter refers to the `y` position of the decoration base, so
|
-- ^ This parameter refers to the `y` position of the decoration base, so
|
||||||
-- the actual maximum height would be `height_max + size.Y`.
|
-- the actual maximum height would be `height_max + size.Y`.
|
||||||
|
spawn_by = "default:water",
|
||||||
|
-- ^ Node (or list of nodes) that the decoration only spawns next to.
|
||||||
|
-- ^ Checks two horizontal planes of neighbouring nodes (including diagonal neighbours),
|
||||||
|
-- ^ one plane at Y = surface and one plane at Y = surface = + 1.
|
||||||
|
num_spawn_by = 1,
|
||||||
|
-- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
|
||||||
|
-- ^ If absent or -1, decorations occur next to any nodes.
|
||||||
flags = "liquid_surface, force_placement",
|
flags = "liquid_surface, force_placement",
|
||||||
-- ^ Flags for all decoration types.
|
-- ^ Flags for all decoration types.
|
||||||
-- ^ "liquid_surface": Instead of placement on the highest solid surface
|
-- ^ "liquid_surface": Instead of placement on the highest solid surface
|
||||||
@ -3945,13 +3952,6 @@ The Biome API is still in an experimental phase and subject to change.
|
|||||||
height_max = 0,
|
height_max = 0,
|
||||||
-- ^ Number of nodes the decoration can be at maximum.
|
-- ^ Number of nodes the decoration can be at maximum.
|
||||||
-- ^ If absent, the parameter 'height' is used as a constant.
|
-- ^ If absent, the parameter 'height' is used as a constant.
|
||||||
spawn_by = "default:water",
|
|
||||||
-- ^ Node that the decoration only spawns next to.
|
|
||||||
-- ^ The neighbours checked are the 8 nodes horizontally surrounding the lowest node of the
|
|
||||||
-- ^ decoration, and the 8 nodes horizontally surrounding the ground node below the decoration.
|
|
||||||
num_spawn_by = 1,
|
|
||||||
-- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
|
|
||||||
-- ^ If absent or -1, decorations occur next to any nodes.
|
|
||||||
|
|
||||||
----- Schematic-type parameters
|
----- Schematic-type parameters
|
||||||
schematic = "foobar.mts",
|
schematic = "foobar.mts",
|
||||||
|
@ -82,6 +82,56 @@ Decoration::~Decoration()
|
|||||||
void Decoration::resolveNodeNames()
|
void Decoration::resolveNodeNames()
|
||||||
{
|
{
|
||||||
getIdsFromNrBacklog(&c_place_on);
|
getIdsFromNrBacklog(&c_place_on);
|
||||||
|
getIdsFromNrBacklog(&c_spawnby);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p)
|
||||||
|
{
|
||||||
|
// Check if the decoration can be placed on this node
|
||||||
|
u32 vi = vm->m_area.index(p);
|
||||||
|
if (!CONTAINS(c_place_on, vm->m_data[vi].getContent()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't continue if there are no spawnby constraints
|
||||||
|
if (nspawnby == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int nneighs = 0;
|
||||||
|
static const v3s16 dirs[16] = {
|
||||||
|
v3s16( 0, 0, 1),
|
||||||
|
v3s16( 0, 0, -1),
|
||||||
|
v3s16( 1, 0, 0),
|
||||||
|
v3s16(-1, 0, 0),
|
||||||
|
v3s16( 1, 0, 1),
|
||||||
|
v3s16(-1, 0, 1),
|
||||||
|
v3s16(-1, 0, -1),
|
||||||
|
v3s16( 1, 0, -1),
|
||||||
|
|
||||||
|
v3s16( 0, 1, 1),
|
||||||
|
v3s16( 0, 1, -1),
|
||||||
|
v3s16( 1, 1, 0),
|
||||||
|
v3s16(-1, 1, 0),
|
||||||
|
v3s16( 1, 1, 1),
|
||||||
|
v3s16(-1, 1, 1),
|
||||||
|
v3s16(-1, 1, -1),
|
||||||
|
v3s16( 1, 1, -1)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check these 16 neighbouring nodes for enough spawnby nodes
|
||||||
|
for (size_t i = 0; i != ARRLEN(dirs); i++) {
|
||||||
|
u32 index = vm->m_area.index(p + dirs[i]);
|
||||||
|
if (!vm->m_area.contains(index))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (CONTAINS(c_spawnby, vm->m_data[index].getContent()))
|
||||||
|
nneighs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nneighs < nspawnby)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -236,66 +286,15 @@ void DecoSimple::resolveNodeNames()
|
|||||||
{
|
{
|
||||||
Decoration::resolveNodeNames();
|
Decoration::resolveNodeNames();
|
||||||
getIdsFromNrBacklog(&c_decos);
|
getIdsFromNrBacklog(&c_decos);
|
||||||
getIdsFromNrBacklog(&c_spawnby);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool DecoSimple::canPlaceDecoration(MMVManip *vm, v3s16 p)
|
|
||||||
{
|
|
||||||
// Don't bother if there aren't any decorations to place
|
|
||||||
if (c_decos.size() == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
u32 vi = vm->m_area.index(p);
|
|
||||||
|
|
||||||
// Check if the decoration can be placed on this node
|
|
||||||
if (!CONTAINS(c_place_on, vm->m_data[vi].getContent()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Don't continue if there are no spawnby constraints
|
|
||||||
if (nspawnby == -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
int nneighs = 0;
|
|
||||||
v3s16 dirs[16] = {
|
|
||||||
v3s16( 0, 0, 1),
|
|
||||||
v3s16( 0, 0, -1),
|
|
||||||
v3s16( 1, 0, 0),
|
|
||||||
v3s16(-1, 0, 0),
|
|
||||||
v3s16( 1, 0, 1),
|
|
||||||
v3s16(-1, 0, 1),
|
|
||||||
v3s16(-1, 0, -1),
|
|
||||||
v3s16( 1, 0, -1),
|
|
||||||
|
|
||||||
v3s16( 0, 1, 1),
|
|
||||||
v3s16( 0, 1, -1),
|
|
||||||
v3s16( 1, 1, 0),
|
|
||||||
v3s16(-1, 1, 0),
|
|
||||||
v3s16( 1, 1, 1),
|
|
||||||
v3s16(-1, 1, 1),
|
|
||||||
v3s16(-1, 1, -1),
|
|
||||||
v3s16( 1, 1, -1)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check a Moore neighborhood if there are enough spawnby nodes
|
|
||||||
for (size_t i = 0; i != ARRLEN(dirs); i++) {
|
|
||||||
u32 index = vm->m_area.index(p + dirs[i]);
|
|
||||||
if (!vm->m_area.contains(index))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (CONTAINS(c_spawnby, vm->m_data[index].getContent()))
|
|
||||||
nneighs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nneighs < nspawnby)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
|
size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
|
||||||
{
|
{
|
||||||
|
// Don't bother if there aren't any decorations to place
|
||||||
|
if (c_decos.size() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!canPlaceDecoration(vm, p))
|
if (!canPlaceDecoration(vm, p))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -345,9 +344,7 @@ size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
|
|||||||
if (schematic == NULL)
|
if (schematic == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 vi = vm->m_area.index(p);
|
if (!canPlaceDecoration(vm, p))
|
||||||
content_t c = vm->m_data[vi].getContent();
|
|
||||||
if (!CONTAINS(c_place_on, c))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (flags & DECO_PLACE_CENTER_X)
|
if (flags & DECO_PLACE_CENTER_X)
|
||||||
|
@ -68,6 +68,7 @@ public:
|
|||||||
|
|
||||||
virtual void resolveNodeNames();
|
virtual void resolveNodeNames();
|
||||||
|
|
||||||
|
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
|
||||||
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||||
//size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
//size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||||
|
|
||||||
@ -82,6 +83,8 @@ public:
|
|||||||
s16 y_max;
|
s16 y_max;
|
||||||
float fill_ratio;
|
float fill_ratio;
|
||||||
NoiseParams np;
|
NoiseParams np;
|
||||||
|
std::vector<content_t> c_spawnby;
|
||||||
|
s16 nspawnby;
|
||||||
|
|
||||||
UNORDERED_SET<u8> biomes;
|
UNORDERED_SET<u8> biomes;
|
||||||
//std::list<CutoffData> cutoffs;
|
//std::list<CutoffData> cutoffs;
|
||||||
@ -90,17 +93,13 @@ public:
|
|||||||
|
|
||||||
class DecoSimple : public Decoration {
|
class DecoSimple : public Decoration {
|
||||||
public:
|
public:
|
||||||
|
virtual void resolveNodeNames();
|
||||||
virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p);
|
virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p);
|
||||||
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
|
|
||||||
virtual int getHeight();
|
virtual int getHeight();
|
||||||
|
|
||||||
virtual void resolveNodeNames();
|
|
||||||
|
|
||||||
std::vector<content_t> c_decos;
|
std::vector<content_t> c_decos;
|
||||||
std::vector<content_t> c_spawnby;
|
|
||||||
s16 deco_height;
|
s16 deco_height;
|
||||||
s16 deco_height_max;
|
s16 deco_height_max;
|
||||||
s16 nspawnby;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DecoSchematic : public Decoration {
|
class DecoSchematic : public Decoration {
|
||||||
|
@ -902,6 +902,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
||||||
deco->y_min = getintfield_default(L, index, "y_min", -31000);
|
deco->y_min = getintfield_default(L, index, "y_min", -31000);
|
||||||
deco->y_max = getintfield_default(L, index, "y_max", 31000);
|
deco->y_max = getintfield_default(L, index, "y_max", 31000);
|
||||||
|
deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
|
||||||
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
||||||
if (deco->sidelen <= 0) {
|
if (deco->sidelen <= 0) {
|
||||||
errorstream << "register_decoration: sidelen must be "
|
errorstream << "register_decoration: sidelen must be "
|
||||||
@ -929,6 +930,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
errorstream << "register_decoration: couldn't get all biomes " << std::endl;
|
errorstream << "register_decoration: couldn't get all biomes " << std::endl;
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
//// Get node name(s) to 'spawn by'
|
||||||
|
size_t nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
|
||||||
|
deco->m_nnlistsizes.push_back(nnames);
|
||||||
|
if (nnames == 0 && deco->nspawnby != -1) {
|
||||||
|
errorstream << "register_decoration: no spawn_by nodes defined,"
|
||||||
|
" but num_spawn_by specified" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//// Handle decoration type-specific parameters
|
//// Handle decoration type-specific parameters
|
||||||
bool success = false;
|
bool success = false;
|
||||||
switch (decotype) {
|
switch (decotype) {
|
||||||
@ -962,12 +971,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
|
|
||||||
bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
||||||
{
|
{
|
||||||
size_t nnames;
|
|
||||||
int index = 1;
|
int index = 1;
|
||||||
|
|
||||||
deco->deco_height = getintfield_default(L, index, "height", 1);
|
deco->deco_height = getintfield_default(L, index, "height", 1);
|
||||||
deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
|
deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
|
||||||
deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
|
|
||||||
|
|
||||||
if (deco->deco_height <= 0) {
|
if (deco->deco_height <= 0) {
|
||||||
errorstream << "register_decoration: simple decoration height"
|
errorstream << "register_decoration: simple decoration height"
|
||||||
@ -975,7 +982,7 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
|
size_t nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
|
||||||
deco->m_nnlistsizes.push_back(nnames);
|
deco->m_nnlistsizes.push_back(nnames);
|
||||||
if (nnames == 0) {
|
if (nnames == 0) {
|
||||||
errorstream << "register_decoration: no decoration nodes "
|
errorstream << "register_decoration: no decoration nodes "
|
||||||
@ -983,14 +990,6 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
|
|
||||||
deco->m_nnlistsizes.push_back(nnames);
|
|
||||||
if (nnames == 0 && deco->nspawnby != -1) {
|
|
||||||
errorstream << "register_decoration: no spawn_by nodes defined,"
|
|
||||||
" but num_spawn_by specified" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user