In lua_api.txt, make clear that 'place on' and 'spawn by' can be lists.
{
deco_type = "simple", -- See "Decoration types"
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,
-- ^ 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.
-- ^ Minimum and maximum `y` positions these decorations can be generated at.
-- ^ This parameter refers to the `y` position of the decoration base, so
-- 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 for all decoration types.
-- ^ "liquid_surface": Instead of placement on the highest solid surface
height_max = 0,
-- ^ Number of nodes the decoration can be at maximum.
-- ^ 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 = "foobar.mts",
#include "util/numeric.h"
FlagDesc flagdesc_deco[] = {
- {"place_center_x", DECO_PLACE_CENTER_X},
- {"place_center_y", DECO_PLACE_CENTER_Y},
- {"place_center_z", DECO_PLACE_CENTER_Z},
+ {"place_center_x", DECO_PLACE_CENTER_X},
+ {"place_center_y", DECO_PLACE_CENTER_Y},
+ {"place_center_z", DECO_PLACE_CENTER_Z},
{"force_placement", DECO_FORCE_PLACEMENT},
- {"liquid_surface", DECO_LIQUID_SURFACE},
- {NULL, 0}
+ {"liquid_surface", DECO_LIQUID_SURFACE},
+ {NULL, 0}
};
void Decoration::resolveNodeNames()
{
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;
}
{
Decoration::resolveNodeNames();
getIdsFromNrBacklog(&c_decos);
- getIdsFromNrBacklog(&c_spawnby);
}
-bool DecoSimple::canPlaceDecoration(MMVManip *vm, 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 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;
-}
-
+ return 0;
-size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
-{
if (!canPlaceDecoration(vm, p))
return 0;
if (schematic == NULL)
return 0;
- u32 vi = vm->m_area.index(p);
- content_t c = vm->m_data[vi].getContent();
- if (!CONTAINS(c_place_on, c))
+ if (!canPlaceDecoration(vm, p))
return 0;
if (flags & DECO_PLACE_CENTER_X)
virtual void resolveNodeNames();
+ bool canPlaceDecoration(MMVManip *vm, v3s16 p);
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
//size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
s16 y_max;
float fill_ratio;
NoiseParams np;
+ std::vector<content_t> c_spawnby;
+ s16 nspawnby;
UNORDERED_SET<u8> biomes;
//std::list<CutoffData> cutoffs;
class DecoSimple : public Decoration {
public:
+ virtual void resolveNodeNames();
virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p);
- bool canPlaceDecoration(MMVManip *vm, v3s16 p);
virtual int getHeight();
- virtual void resolveNodeNames();
-
std::vector<content_t> c_decos;
- std::vector<content_t> c_spawnby;
s16 deco_height;
s16 deco_height_max;
- s16 nspawnby;
};
class DecoSchematic : public Decoration {
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
deco->y_min = getintfield_default(L, index, "y_min", -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);
if (deco->sidelen <= 0) {
errorstream << "register_decoration: sidelen must be "
errorstream << "register_decoration: couldn't get all biomes " << std::endl;
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
bool success = false;
switch (decotype) {
bool read_deco_simple(lua_State *L, DecoSimple *deco)
{
- size_t nnames;
int index = 1;
deco->deco_height = getintfield_default(L, index, "height", 1);
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) {
errorstream << "register_decoration: simple decoration height"
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);
if (nnames == 0) {
errorstream << "register_decoration: no decoration nodes "
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;
}