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.
This commit is contained in:
paramat 2017-09-06 22:20:09 +01:00 committed by paramat
parent 557bbc6704
commit 51002b1629
4 changed files with 27 additions and 83 deletions

@ -4743,6 +4743,13 @@ The Biome API is still in an experimental phase and subject to change.
-- ^ Flags for schematic decorations. See 'Schematic attributes'. -- ^ Flags for schematic decorations. See 'Schematic attributes'.
rotation = "90" -- rotate schematic 90 degrees on placement rotation = "90" -- rotate schematic 90 degrees on placement
-- ^ Rotation can be "0", "90", "180", "270", or "random". -- ^ 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`) ### Chat command definition (`register_chatcommand`)

@ -67,6 +67,7 @@ size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed,
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void Decoration::resolveNodeNames() void Decoration::resolveNodeNames()
{ {
getIdsFromNrBacklog(&c_place_on); 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) if (y < y_min_disp || y > y_max_disp || y < nmin.Y || y > nmax.Y)
continue; continue;
if (y + getHeight() > mg->vm->m_area.MaxEdge.Y) { if (y + getHeight() > mg->vm->m_area.MaxEdge.Y)
continue; 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()) { if (mg->biomemap && !biomes.empty()) {
std::unordered_set<u8>::const_iterator iter = std::unordered_set<u8>::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<CutoffData> 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<CutoffData>::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<CutoffData>::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) size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
{ {
// Schematic could have been unloaded but not the decoration // 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) if (flags & DECO_PLACE_CENTER_X)
p.X -= (schematic->size.X - 1) / 2; 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) if (flags & DECO_PLACE_CENTER_Z)
p.Z -= (schematic->size.Z - 1) / 2; 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 rot = (rotation == ROTATE_RAND) ?
(Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation; (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() int DecoSchematic::getHeight()
{ {
// Account for a schematic being sunk into the ground by flag. // Account for a schematic being sunk into the ground by flag.
// When placed normally account for how a schematic is placed // When placed normally account for how a schematic is by default placed
// sunk 1 node into the ground. // sunk 1 node into the ground or is vertically shifted by 'y_offset'.
return (flags & DECO_PLACE_CENTER_Y) ? 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;
} }

@ -46,21 +46,6 @@ enum DecorationType {
extern FlagDesc flagdesc_deco[]; 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 { class Decoration : public ObjDef, public NodeResolver {
public: public:
Decoration() = default; Decoration() = default;
@ -71,7 +56,6 @@ public:
bool canPlaceDecoration(MMVManip *vm, v3s16 p); bool canPlaceDecoration(MMVManip *vm, v3s16 p);
size_t placeDeco(Mapgen *mg, u32 blockseed, size_t placeDeco(Mapgen *mg, u32 blockseed,
v3s16 nmin, v3s16 nmax, s16 deco_zero_level); 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 size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p) = 0;
virtual int getHeight() = 0; virtual int getHeight() = 0;
@ -90,6 +74,7 @@ public:
std::unordered_set<u8> biomes; std::unordered_set<u8> biomes;
}; };
class DecoSimple : public Decoration { class DecoSimple : public Decoration {
public: public:
virtual void resolveNodeNames(); virtual void resolveNodeNames();
@ -102,6 +87,7 @@ public:
u8 deco_param2; u8 deco_param2;
}; };
class DecoSchematic : public Decoration { class DecoSchematic : public Decoration {
public: public:
DecoSchematic() = default; DecoSchematic() = default;
@ -110,6 +96,7 @@ public:
virtual int getHeight(); virtual int getHeight();
Rotation rotation; Rotation rotation;
s16 place_offset_y = 0;
Schematic *schematic = nullptr; Schematic *schematic = nullptr;
}; };
@ -121,6 +108,7 @@ public:
}; };
*/ */
class DecorationManager : public ObjDefManager { class DecorationManager : public ObjDefManager {
public: public:
DecorationManager(IGameDef *gamedef); DecorationManager(IGameDef *gamedef);

@ -1018,6 +1018,8 @@ bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic
deco->rotation = (Rotation)getenumfield(L, index, "rotation", deco->rotation = (Rotation)getenumfield(L, index, "rotation",
ModApiMapgen::es_Rotation, ROTATE_0); ModApiMapgen::es_Rotation, ROTATE_0);
deco->place_offset_y = getintfield_default(L, index, "place_offset_y", 0);
StringMap replace_names; StringMap replace_names;
lua_getfield(L, index, "replacements"); lua_getfield(L, index, "replacements");
if (lua_istable(L, -1)) if (lua_istable(L, -1))