From 51002b1629c69adb0053bc36d3667d2b790e5c21 Mon Sep 17 00:00:00 2001 From: paramat Date: Wed, 6 Sep 2017 22:20:09 +0100 Subject: [PATCH] Schematic decorations: Add 'place_offset_y' placement parameter For precise control of schematic vertical position relative to the 'place_on' node. Avoids workarounds that add empty nodes to a schematic and therefore reduce performance. Also remove long-unused decoration cutoff code. --- doc/lua_api.txt | 7 +++ src/mg_decoration.cpp | 81 ++++++--------------------------- src/mg_decoration.h | 20 ++------ src/script/lua_api/l_mapgen.cpp | 2 + 4 files changed, 27 insertions(+), 83 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ec5a8ff3..ef62f135 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4743,6 +4743,13 @@ The Biome API is still in an experimental phase and subject to change. -- ^ Flags for schematic decorations. See 'Schematic attributes'. rotation = "90" -- rotate schematic 90 degrees on placement -- ^ Rotation can be "0", "90", "180", "270", or "random". + place_offset_y = 0, + -- ^ Y offset of the schematic base node layer relative to the 'place_on' + -- ^ node. + -- ^ Can be positive or negative. Default is 0. + -- ^ If the flag 'place_center_y' is set this parameter is ignored. + -- ^ If absent or 0 the schematic base node layer will be placed level + -- ^ with the 'place_on' node. } ### Chat command definition (`register_chatcommand`) diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index db640626..1872e32e 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -67,6 +67,7 @@ size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed, /////////////////////////////////////////////////////////////////////////////// + void Decoration::resolveNodeNames() { getIdsFromNrBacklog(&c_place_on); @@ -192,15 +193,8 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, if (y < y_min_disp || y > y_max_disp || y < nmin.Y || y > nmax.Y) continue; - if (y + getHeight() > mg->vm->m_area.MaxEdge.Y) { + if (y + getHeight() > mg->vm->m_area.MaxEdge.Y) continue; -#if 0 - printf("Decoration at (%d %d %d) cut off\n", x, y, z); - //add to queue - MutexAutoLock cutofflock(cutoff_mutex); - cutoffs.push_back(CutoffData(x, y, z, height)); -#endif - } if (mg->biomemap && !biomes.empty()) { std::unordered_set::const_iterator iter = @@ -219,60 +213,6 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, } -#if 0 -void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) -{ - PcgRandom pr(blockseed + 53); - std::vector handled_cutoffs; - - // Copy over the cutoffs we're interested in so we don't needlessly hold a lock - { - MutexAutoLock cutofflock(cutoff_mutex); - for (std::list::iterator i = cutoffs.begin(); - i != cutoffs.end(); ++i) { - CutoffData cutoff = *i; - v3s16 p = cutoff.p; - s16 height = cutoff.height; - if (p.X < nmin.X || p.X > nmax.X || - p.Z < nmin.Z || p.Z > nmax.Z) - continue; - if (p.Y + height < nmin.Y || p.Y > nmax.Y) - continue; - - handled_cutoffs.push_back(cutoff); - } - } - - // Generate the cutoffs - for (size_t i = 0; i != handled_cutoffs.size(); i++) { - v3s16 p = handled_cutoffs[i].p; - s16 height = handled_cutoffs[i].height; - - if (p.Y + height > nmax.Y) { - //printf("Decoration at (%d %d %d) cut off again!\n", p.X, p.Y, p.Z); - cuttoffs.push_back(v3s16(p.X, p.Y, p.Z)); - } - - generate(mg, &pr, nmax.Y, nmin.Y - p.Y, v3s16(p.X, nmin.Y, p.Z)); - } - - // Remove cutoffs that were handled from the cutoff list - { - MutexAutoLock cutofflock(cutoff_mutex); - for (std::list::iterator i = cutoffs.begin(); - i != cutoffs.end(); ++i) { - - for (size_t j = 0; j != handled_cutoffs.size(); j++) { - CutoffData coff = *i; - if (coff.p == handled_cutoffs[j].p) - i = cutoffs.erase(i); - } - } - } -} -#endif - - /////////////////////////////////////////////////////////////////////////////// @@ -324,6 +264,7 @@ int DecoSimple::getHeight() /////////////////////////////////////////////////////////////////////////////// + size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p) { // Schematic could have been unloaded but not the decoration @@ -336,11 +277,17 @@ size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p) if (flags & DECO_PLACE_CENTER_X) p.X -= (schematic->size.X - 1) / 2; - if (flags & DECO_PLACE_CENTER_Y) - p.Y -= (schematic->size.Y - 1) / 2; if (flags & DECO_PLACE_CENTER_Z) p.Z -= (schematic->size.Z - 1) / 2; + if (flags & DECO_PLACE_CENTER_Y) + p.Y -= (schematic->size.Y - 1) / 2; + else + p.Y += place_offset_y; + // Check shifted schematic base is in voxelmanip + if (p.Y < vm->m_area.MinEdge.Y) + return 0; + Rotation rot = (rotation == ROTATE_RAND) ? (Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation; @@ -355,8 +302,8 @@ size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p) int DecoSchematic::getHeight() { // Account for a schematic being sunk into the ground by flag. - // When placed normally account for how a schematic is placed - // sunk 1 node into the ground. + // When placed normally account for how a schematic is by default placed + // sunk 1 node into the ground or is vertically shifted by 'y_offset'. return (flags & DECO_PLACE_CENTER_Y) ? - (schematic->size.Y - 1) / 2 : schematic->size.Y - 1; + (schematic->size.Y - 1) / 2 : schematic->size.Y - 1 + place_offset_y; } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index fd6e89e7..01e063ca 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -46,21 +46,6 @@ enum DecorationType { extern FlagDesc flagdesc_deco[]; -#if 0 -struct CutoffData { - VoxelArea a; - Decoration *deco; - //v3s16 p; - //v3s16 size; - //s16 height; - - CutoffData(s16 x, s16 y, s16 z, s16 h) { - p = v3s16(x, y, z); - height = h; - } -}; -#endif - class Decoration : public ObjDef, public NodeResolver { public: Decoration() = default; @@ -71,7 +56,6 @@ public: bool canPlaceDecoration(MMVManip *vm, v3s16 p); size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax, s16 deco_zero_level); - //size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p) = 0; virtual int getHeight() = 0; @@ -90,6 +74,7 @@ public: std::unordered_set biomes; }; + class DecoSimple : public Decoration { public: virtual void resolveNodeNames(); @@ -102,6 +87,7 @@ public: u8 deco_param2; }; + class DecoSchematic : public Decoration { public: DecoSchematic() = default; @@ -110,6 +96,7 @@ public: virtual int getHeight(); Rotation rotation; + s16 place_offset_y = 0; Schematic *schematic = nullptr; }; @@ -121,6 +108,7 @@ public: }; */ + class DecorationManager : public ObjDefManager { public: DecorationManager(IGameDef *gamedef); diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index c2b25622..7757ea80 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -1018,6 +1018,8 @@ bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic deco->rotation = (Rotation)getenumfield(L, index, "rotation", ModApiMapgen::es_Rotation, ROTATE_0); + deco->place_offset_y = getintfield_default(L, index, "place_offset_y", 0); + StringMap replace_names; lua_getfield(L, index, "replacements"); if (lua_istable(L, -1))