Add map feature generation notify Lua API

master
kwolekr 2013-12-14 01:52:06 -05:00
parent 83853ccd41
commit c3708b456e
12 changed files with 252 additions and 151 deletions

View File

@ -1289,6 +1289,10 @@ minetest.get_perlin(seeddiff, octaves, persistence, scale)
^ Return world-specific perlin noise (int(worldseed)+seeddiff)
minetest.get_voxel_manip()
^ Return voxel manipulator object
minetest.set_gen_notify(flags)
^ Set the types of on-generate notifications that should be collected
^ flags is a comma-delimited combination of:
^ dungeon, temple, cave_begin, cave_end, large_cave_begin, large_cave_end
minetest.get_mapgen_object(objectname)
^ Return requested mapgen object if available (see Mapgen objects)
minetest.set_mapgen_params(MapgenParams)
@ -1894,6 +1898,12 @@ the current mapgen.
Returns an array containing the humidity values of nodes in the most recently generated chunk by the
current mapgen.
- gennotify
Returns a table mapping requested generation notification types to arrays of positions at which the
corresponding generated structures are located at within the current chunk. To set the capture of positions
of interest to be recorded on generate, use minetest.set_gen_notify().
Possible fields of the table returned are: dungeon, temple, cave_begin, cave_end, large_cave_begin, large_cave_end
Registered entities
--------------------
- Functions receive a "luaentity" as self:

View File

@ -110,9 +110,21 @@ void CaveV6::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
(float)(ps->next() % ar.Z) + 0.5
);
int notifytype = large_cave ? GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN;
if (mg->gennotify & (1 << notifytype)) {
std::vector <v3s16> *nvec = mg->gen_notifications[notifytype];
nvec->push_back(v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z));
}
// Generate some tunnel starting from orp
for (u16 j = 0; j < tunnel_routepoints; j++)
makeTunnel(j % dswitchint == 0);
notifytype = large_cave ? GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END;
if (mg->gennotify & (1 << notifytype)) {
std::vector <v3s16> *nvec = mg->gen_notifications[notifytype];
nvec->push_back(v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z));
}
}
@ -347,9 +359,21 @@ void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
(float)(ps->next() % ar.Z) + 0.5
);
int notifytype = large_cave ? GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN;
if (mg->gennotify & (1 << notifytype)) {
std::vector <v3s16> *nvec = mg->gen_notifications[notifytype];
nvec->push_back(v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z));
}
// Generate some tunnel starting from orp
for (u16 j = 0; j < tunnel_routepoints; j++)
makeTunnel(j % dswitchint == 0);
notifytype = large_cave ? GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END;
if (mg->gennotify & (1 << notifytype)) {
std::vector <v3s16> *nvec = mg->gen_notifications[notifytype];
nvec->push_back(v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z));
}
}

View File

@ -42,11 +42,9 @@ NoiseParams nparams_dungeon_density =
///////////////////////////////////////////////////////////////////////////////
DungeonGen::DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel,
DungeonParams *dparams) {
this->ndef = ndef;
this->mapseed = seed;
this->water_level = waterlevel;
DungeonGen::DungeonGen(Mapgen *mapgen, DungeonParams *dparams) {
this->mg = mapgen;
this->vm = mapgen->vm;
#ifdef DGEN_USE_TORCHES
c_torch = ndef->getId("default:torch");
@ -55,15 +53,16 @@ DungeonGen::DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel,
if (dparams) {
memcpy(&dp, dparams, sizeof(dp));
} else {
dp.c_water = ndef->getId("mapgen_water_source");
dp.c_cobble = ndef->getId("mapgen_cobble");
dp.c_moss = ndef->getId("mapgen_mossycobble");
dp.c_stair = ndef->getId("mapgen_stair_cobble");
dp.c_water = mg->ndef->getId("mapgen_water_source");
dp.c_cobble = mg->ndef->getId("mapgen_cobble");
dp.c_moss = mg->ndef->getId("mapgen_mossycobble");
dp.c_stair = mg->ndef->getId("mapgen_stair_cobble");
dp.diagonal_dirs = false;
dp.mossratio = 3.0;
dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0,0,0);
dp.mossratio = 3.0;
dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0,0,0);
dp.notifytype = GENNOTIFY_DUNGEON;
dp.np_rarity = nparams_dungeon_rarity;
dp.np_wetness = nparams_dungeon_wetness;
@ -72,31 +71,29 @@ DungeonGen::DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel,
}
void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
v3s16 nmin, v3s16 nmax) {
void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) {
//TimeTaker t("gen dungeons");
int approx_groundlevel = 10 + water_level;
int approx_groundlevel = 10 + mg->water_level;
if ((nmin.Y + nmax.Y) / 2 >= approx_groundlevel ||
NoisePerlin3D(&dp.np_rarity, nmin.X, nmin.Y, nmin.Z, mapseed) < 0.2)
NoisePerlin3D(&dp.np_rarity, nmin.X, nmin.Y, nmin.Z, mg->seed) < 0.2)
return;
this->vmanip = vm;
this->blockseed = bseed;
random.seed(bseed + 2);
// Dungeon generator doesn't modify places which have this set
vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
// Set all air and water to be untouchable to make dungeons open
// to caves and open air
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
u32 i = vmanip->m_area.index(nmin.X, y, z);
u32 i = vm->m_area.index(nmin.X, y, z);
for (s16 x = nmin.X; x <= nmax.X; x++) {
content_t c = vmanip->m_data[i].getContent();
content_t c = vm->m_data[i].getContent();
if (c == CONTENT_AIR || c == dp.c_water)
vmanip->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
i++;
}
}
@ -109,13 +106,13 @@ void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
if (dp.mossratio != 0.0) {
for (s16 z = nmin.Z; z <= nmax.Z; z++)
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
u32 i = vmanip->m_area.index(nmin.X, y, z);
u32 i = vm->m_area.index(nmin.X, y, z);
for (s16 x = nmin.X; x <= nmax.X; x++) {
if (vmanip->m_data[i].getContent() == dp.c_cobble) {
float wetness = NoisePerlin3D(&dp.np_wetness, x, y, z, mapseed);
if (vm->m_data[i].getContent() == dp.c_cobble) {
float wetness = NoisePerlin3D(&dp.np_wetness, x, y, z, mg->seed);
float density = NoisePerlin3D(&dp.np_density, x, y, z, blockseed);
if (density < wetness / dp.mossratio)
vmanip->m_data[i].setContent(dp.c_moss);
vm->m_data[i].setContent(dp.c_moss);
}
i++;
}
@ -128,7 +125,7 @@ void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
void DungeonGen::makeDungeon(v3s16 start_padding)
{
v3s16 areasize = vmanip->m_area.getExtent();
v3s16 areasize = vm->m_area.getExtent();
v3s16 roomsize;
v3s16 roomplace;
@ -136,7 +133,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
Find place for first room
*/
bool fits = false;
for (u32 i = 0; i < 100; i++)
for (u32 i = 0; i < 100 && !fits; i++)
{
bool is_large_room = ((random.next() & 3) == 1);
roomsize = is_large_room ?
@ -146,7 +143,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
// start_padding is used to disallow starting the generation of
// a dungeon in a neighboring generation chunk
roomplace = vmanip->m_area.MinEdge + start_padding + v3s16(
roomplace = vm->m_area.MinEdge + start_padding + v3s16(
random.range(0,areasize.X-roomsize.X-1-start_padding.X),
random.range(0,areasize.Y-roomsize.Y-1-start_padding.Y),
random.range(0,areasize.Z-roomsize.Z-1-start_padding.Z));
@ -161,20 +158,13 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
for (s16 x = 1; x < roomsize.X - 1; x++)
{
v3s16 p = roomplace + v3s16(x, y, z);
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_INSIDE)
{
fits = false;
break;
}
if (vmanip->m_data[vi].getContent() == CONTENT_IGNORE)
{
u32 vi = vm->m_area.index(p);
if ((vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_INSIDE) ||
vm->m_data[vi].getContent() == CONTENT_IGNORE) {
fits = false;
break;
}
}
if (fits)
break;
}
// No place found
if (fits == false)
@ -194,10 +184,14 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
makeRoom(roomsize, roomplace);
v3s16 room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2);
if (mg->gennotify & (1 << dp.notifytype)) {
std::vector <v3s16> *nvec = mg->gen_notifications[dp.notifytype];
nvec->push_back(room_center);
}
#ifdef DGEN_USE_TORCHES
// Place torch at room center (for testing)
vmanip->m_data[vmanip->m_area.index(room_center)] = MapNode(c_torch);
vm->m_data[vm->m_area.index(room_center)] = MapNode(c_torch);
#endif
// Quit if last room
@ -210,12 +204,9 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
v3s16 walker_start_place;
if(start_in_last_room)
{
if (start_in_last_room) {
walker_start_place = last_room_center;
}
else
{
} else {
walker_start_place = room_center;
// Store center of current room as the last one
last_room_center = room_center;
@ -226,8 +217,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
v3s16 doordir;
m_pos = walker_start_place;
bool r = findPlaceForDoor(doorplace, doordir);
if (r == false)
if (!findPlaceForDoor(doorplace, doordir))
return;
if (random.range(0,1) == 0)
@ -248,8 +238,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
m_pos = corridor_end;
m_dir = corridor_end_dir;
r = findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace);
if (r == false)
if (!findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace))
return;
if (random.range(0,1) == 0)
@ -274,21 +263,21 @@ void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
{
{
v3s16 p = roomplace + v3s16(0, y, z);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
u32 vi = vm->m_area.index(p);
if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue;
vmanip->m_data[vi] = n_cobble;
vm->m_data[vi] = n_cobble;
}
{
v3s16 p = roomplace + v3s16(roomsize.X - 1, y, z);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
u32 vi = vm->m_area.index(p);
if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue;
vmanip->m_data[vi] = n_cobble;
vm->m_data[vi] = n_cobble;
}
}
@ -298,21 +287,21 @@ void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
{
{
v3s16 p = roomplace + v3s16(x, y, 0);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
u32 vi = vm->m_area.index(p);
if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue;
vmanip->m_data[vi] = n_cobble;
vm->m_data[vi] = n_cobble;
}
{
v3s16 p = roomplace + v3s16(x, y, roomsize.Z - 1);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
u32 vi = vm->m_area.index(p);
if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue;
vmanip->m_data[vi] = n_cobble;
vm->m_data[vi] = n_cobble;
}
}
@ -322,21 +311,21 @@ void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
{
{
v3s16 p = roomplace + v3s16(x, 0, z);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
u32 vi = vm->m_area.index(p);
if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue;
vmanip->m_data[vi] = n_cobble;
vm->m_data[vi] = n_cobble;
}
{
v3s16 p = roomplace + v3s16(x,roomsize. Y - 1, z);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
u32 vi = vm->m_area.index(p);
if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue;
vmanip->m_data[vi] = n_cobble;
vm->m_data[vi] = n_cobble;
}
}
@ -346,11 +335,11 @@ void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
for (s16 x = 1; x < roomsize.X - 1; x++)
{
v3s16 p = roomplace + v3s16(x, y, z);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
vmanip->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE;
vmanip->m_data[vi] = n_air;
u32 vi = vm->m_area.index(p);
vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE;
vm->m_data[vi] = n_air;
}
}
@ -363,13 +352,13 @@ void DungeonGen::makeFill(v3s16 place, v3s16 size,
for (s16 x = 0; x < size.X; x++)
{
v3s16 p = place + v3s16(x, y, z);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
continue;
u32 vi = vmanip->m_area.index(p);
if (vmanip->m_flags[vi] & avoid_flags)
u32 vi = vm->m_area.index(p);
if (vm->m_flags[vi] & avoid_flags)
continue;
vmanip->m_flags[vi] |= or_flags;
vmanip->m_data[vi] = n;
vm->m_flags[vi] |= or_flags;
vm->m_data[vi] = n;
}
}
@ -387,7 +376,7 @@ void DungeonGen::makeDoor(v3s16 doorplace, v3s16 doordir)
#ifdef DGEN_USE_TORCHES
// Place torch (for testing)
vmanip->m_data[vmanip->m_area.index(doorplace)] = MapNode(c_torch);
vm->m_data[vm->m_area.index(doorplace)] = MapNode(c_torch);
#endif
}
@ -416,8 +405,8 @@ void DungeonGen::makeCorridor(v3s16 doorplace,
if (partcount != 0)
p.Y += make_stairs;
if (vmanip->m_area.contains(p) == true &&
vmanip->m_area.contains(p + v3s16(0, 1, 0)) == true) {
if (vm->m_area.contains(p) == true &&
vm->m_area.contains(p + v3s16(0, 1, 0)) == true) {
if (make_stairs) {
makeFill(p + v3s16(-1, -1, -1), dp.holesize + v3s16(2, 3, 2),
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(dp.c_cobble), 0);
@ -434,13 +423,13 @@ void DungeonGen::makeCorridor(v3s16 doorplace,
// rotate face 180 deg if making stairs backwards
int facedir = dir_to_facedir(dir * make_stairs);
u32 vi = vmanip->m_area.index(p.X - dir.X, p.Y - 1, p.Z - dir.Z);
if (vmanip->m_data[vi].getContent() == dp.c_cobble)
vmanip->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
u32 vi = vm->m_area.index(p.X - dir.X, p.Y - 1, p.Z - dir.Z);
if (vm->m_data[vi].getContent() == dp.c_cobble)
vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
vi = vmanip->m_area.index(p.X, p.Y, p.Z);
if (vmanip->m_data[vi].getContent() == dp.c_cobble)
vmanip->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
vi = vm->m_area.index(p.X, p.Y, p.Z);
if (vm->m_data[vi].getContent() == dp.c_cobble)
vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
}
} else {
makeFill(p + v3s16(-1, -1, -1), dp.holesize + v3s16(2, 2, 2),
@ -482,15 +471,15 @@ bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
{
v3s16 p = m_pos + m_dir;
v3s16 p1 = p + v3s16(0, 1, 0);
if (vmanip->m_area.contains(p) == false
|| vmanip->m_area.contains(p1) == false
if (vm->m_area.contains(p) == false
|| vm->m_area.contains(p1) == false
|| i % 4 == 0)
{
randomizeDir();
continue;
}
if (vmanip->getNodeNoExNoEmerge(p).getContent() == dp.c_cobble
&& vmanip->getNodeNoExNoEmerge(p1).getContent() == dp.c_cobble)
if (vm->getNodeNoExNoEmerge(p).getContent() == dp.c_cobble
&& vm->getNodeNoExNoEmerge(p1).getContent() == dp.c_cobble)
{
// Found wall, this is a good place!
result_place = p;
@ -503,18 +492,18 @@ bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
Determine where to move next
*/
// Jump one up if the actual space is there
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == dp.c_cobble
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent() == CONTENT_AIR)
if (vm->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == dp.c_cobble
&& vm->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR
&& vm->getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent() == CONTENT_AIR)
p += v3s16(0,1,0);
// Jump one down if the actual space is there
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == dp.c_cobble
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_AIR
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent() == CONTENT_AIR)
if (vm->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == dp.c_cobble
&& vm->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_AIR
&& vm->getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent() == CONTENT_AIR)
p += v3s16(0,-1,0);
// Check if walking is now possible
if (vmanip->getNodeNoExNoEmerge(p).getContent() != CONTENT_AIR
|| vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() != CONTENT_AIR)
if (vm->getNodeNoExNoEmerge(p).getContent() != CONTENT_AIR
|| vm->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() != CONTENT_AIR)
{
// Cannot continue walking here
randomizeDir();
@ -571,12 +560,12 @@ bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
for (s16 x = 1; x < roomsize.X - 1; x++)
{
v3s16 p = roomplace + v3s16(x, y, z);
if (vmanip->m_area.contains(p) == false)
if (vm->m_area.contains(p) == false)
{
fits = false;
break;
}
if (vmanip->m_flags[vmanip->m_area.index(p)]
if (vm->m_flags[vm->m_area.index(p)]
& VMANIP_FLAG_DUNGEON_INSIDE)
{
fits = false;

View File

@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class ManualMapVoxelManipulator;
class INodeDefManager;
class Mapgen;
v3s16 rand_ortho_dir(PseudoRandom &random, bool diagonal_dirs);
v3s16 turn_xz(v3s16 olddir, int t);
@ -44,6 +44,7 @@ struct DungeonParams {
content_t c_moss;
content_t c_stair;
int notifytype;
bool diagonal_dirs;
float mossratio;
v3s16 holesize;
@ -56,13 +57,11 @@ struct DungeonParams {
class DungeonGen {
public:
ManualMapVoxelManipulator *vm;
Mapgen *mg;
u32 blockseed;
u64 mapseed;
ManualMapVoxelManipulator *vmanip;
INodeDefManager *ndef;
PseudoRandom random;
v3s16 csize;
s16 water_level;
content_t c_torch;
DungeonParams dp;
@ -71,9 +70,8 @@ public:
v3s16 m_pos;
v3s16 m_dir;
DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel, DungeonParams *dparams);
void generate(ManualMapVoxelManipulator *vm, u32 bseed,
v3s16 full_node_min, v3s16 full_node_max);
DungeonGen(Mapgen *mg, DungeonParams *dparams);
void generate(u32 bseed, v3s16 full_node_min, v3s16 full_node_max);
void makeDungeon(v3s16 start_padding);
void makeRoom(v3s16 roomsize, v3s16 roomplace);

View File

@ -105,8 +105,9 @@ EmergeManager::EmergeManager(IGameDef *gamedef) {
this->luaoverride_params_modified = 0;
this->luaoverride_flagmask = 0;
mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
this->gennotify = 0;
mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
int nthreads;
if (g_settings->get("num_emerge_threads").empty()) {

View File

@ -94,6 +94,8 @@ public:
u16 qlimit_diskonly;
u16 qlimit_generate;
u32 gennotify;
MapgenParams *luaoverride_params;
u32 luaoverride_params_modified;
u32 luaoverride_flagmask;

View File

@ -64,6 +64,16 @@ FlagDesc flagdesc_deco_schematic[] = {
{NULL, 0}
};
FlagDesc flagdesc_gennotify[] = {
{"dungeon", 1 << GENNOTIFY_DUNGEON},
{"temple", 1 << GENNOTIFY_TEMPLE},
{"cave_begin", 1 << GENNOTIFY_CAVE_BEGIN},
{"cave_end", 1 << GENNOTIFY_CAVE_END},
{"large_cave_begin", 1 << GENNOTIFY_LARGECAVE_BEGIN},
{"large_cave_end", 1 << GENNOTIFY_LARGECAVE_END},
{NULL, 0}
};
///////////////////////////////////////////////////////////////////////////////
@ -896,6 +906,15 @@ Mapgen::Mapgen() {
ndef = NULL;
heightmap = NULL;
biomemap = NULL;
for (unsigned int i = 0; i != NUM_GEN_NOTIFY; i++)
gen_notifications[i] = new std::vector<v3s16>;
}
Mapgen::~Mapgen() {
for (unsigned int i = 0; i != NUM_GEN_NOTIFY; i++)
delete gen_notifications[i];
}

View File

@ -53,9 +53,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define DECO_PLACE_CENTER_Y 2
#define DECO_PLACE_CENTER_Z 4
#define ORE_RANGE_ACTUAL 1
#define ORE_RANGE_MIRROR 2
#define NUM_GEN_NOTIFY 6
extern FlagDesc flagdesc_mapgen[];
extern FlagDesc flagdesc_ore[];
extern FlagDesc flagdesc_deco_schematic[];
extern FlagDesc flagdesc_gennotify[];
class BiomeDefManager;
class Biome;
@ -67,6 +74,32 @@ struct BlockMakeData;
class VoxelArea;
class Map;
enum MapgenObject {
MGOBJ_VMANIP,
MGOBJ_HEIGHTMAP,
MGOBJ_BIOMEMAP,
MGOBJ_HEATMAP,
MGOBJ_HUMIDMAP,
MGOBJ_GENNOTIFY
};
enum GenNotify {
GENNOTIFY_DUNGEON,
GENNOTIFY_TEMPLE,
GENNOTIFY_CAVE_BEGIN,
GENNOTIFY_CAVE_END,
GENNOTIFY_LARGECAVE_BEGIN,
GENNOTIFY_LARGECAVE_END
};
enum OreType {
ORE_SCATTER,
ORE_SHEET,
ORE_CLAYLIKE
};
struct MapgenParams {
std::string mg_name;
int chunksize;
@ -100,8 +133,11 @@ public:
u8 *biomemap;
v3s16 csize;
u32 gennotify;
std::vector<v3s16> *gen_notifications[NUM_GEN_NOTIFY];
Mapgen();
virtual ~Mapgen() {}
virtual ~Mapgen();
s16 findGroundLevelFull(v2s16 p2d);
s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax);
@ -123,23 +159,6 @@ struct MapgenFactory {
virtual ~MapgenFactory() {}
};
enum MapgenObject {
MGOBJ_VMANIP,
MGOBJ_HEIGHTMAP,
MGOBJ_BIOMEMAP,
MGOBJ_HEATMAP,
MGOBJ_HUMIDMAP
};
enum OreType {
ORE_SCATTER,
ORE_SHEET,
ORE_CLAYLIKE
};
#define ORE_RANGE_ACTUAL 1
#define ORE_RANGE_MIRROR 2
class Ore {
public:
std::string ore_name;

View File

@ -74,6 +74,7 @@ MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge)
this->water_level = params->water_level;
this->flags = params->flags;
this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
this->gennotify = emerge->gennotify;
this->freq_desert = params->freq_desert;
this->freq_beach = params->freq_beach;
@ -456,22 +457,24 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
dp.c_stair = c_stair_cobble;
dp.diagonal_dirs = false;
dp.mossratio = 3.0;
dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0, 0, 0);
dp.mossratio = 3.0;
dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0, 0, 0);
dp.notifytype = GENNOTIFY_DUNGEON;
} else {
dp.c_cobble = c_sandbrick;
dp.c_moss = c_sandbrick; // should make this 'cracked sandstone' later
dp.c_stair = c_stair_sandstone;
dp.diagonal_dirs = true;
dp.mossratio = 0.0;
dp.holesize = v3s16(2, 3, 2);
dp.roomsize = v3s16(2, 5, 2);
dp.mossratio = 0.0;
dp.holesize = v3s16(2, 3, 2);
dp.roomsize = v3s16(2, 5, 2);
dp.notifytype = GENNOTIFY_TEMPLE;
}
DungeonGen dgen(ndef, data->seed, water_level, &dp);
dgen.generate(vm, blockseed, full_node_min, full_node_max);
DungeonGen dgen(this, &dp);
dgen.generate(blockseed, full_node_min, full_node_max);
}
// Add top and bottom side of water to transforming_liquid queue

View File

@ -73,6 +73,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge)
this->seed = (int)params->seed;
this->water_level = params->water_level;
this->flags = params->flags | MGV7_MOUNTAINS | MGV7_RIDGES;
this->gennotify = emerge->gennotify;
this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
@ -207,8 +208,8 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
generateCaves(stone_surface_max_y);
if (flags & MG_DUNGEONS) {
DungeonGen dgen(ndef, data->seed, water_level, NULL);
dgen.generate(vm, blockseed, full_node_min, full_node_max);
DungeonGen dgen(this, NULL);
dgen.generate(blockseed, full_node_min, full_node_max);
}
for (size_t i = 0; i != emerge->decorations.size(); i++) {

View File

@ -54,6 +54,7 @@ struct EnumString ModApiMapgen::es_MapgenObject[] =
{MGOBJ_BIOMEMAP, "biomemap"},
{MGOBJ_HEATMAP, "heatmap"},
{MGOBJ_HUMIDMAP, "humiditymap"},
{MGOBJ_GENNOTIFY, "gennotify"},
{0, NULL},
};
@ -95,8 +96,6 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
size_t maplen = mg->csize.X * mg->csize.Z;
int nargs = 1;
switch (mgobj) {
case MGOBJ_VMANIP: {
ManualMapVoxelManipulator *vm = mg->vm;
@ -113,9 +112,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
// emerged max pos
push_v3s16(L, vm->m_area.MaxEdge);
nargs = 3;
break; }
return 3; }
case MGOBJ_HEIGHTMAP: {
if (!mg->heightmap)
return 0;
@ -125,7 +122,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
lua_pushinteger(L, mg->heightmap[i]);
lua_rawseti(L, -2, i + 1);
}
break; }
return 1; }
case MGOBJ_BIOMEMAP: {
if (!mg->biomemap)
return 0;
@ -135,7 +133,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
lua_pushinteger(L, mg->biomemap[i]);
lua_rawseti(L, -2, i + 1);
}
break; }
return 1; }
case MGOBJ_HEATMAP: { // Mapgen V7 specific objects
case MGOBJ_HUMIDMAP:
if (strcmp(emerge->params->mg_name.c_str(), "v7"))
@ -153,10 +152,32 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
lua_pushnumber(L, arr[i]);
lua_rawseti(L, -2, i + 1);
}
break; }
return 1; }
case MGOBJ_GENNOTIFY: {
lua_newtable(L);
for (int i = 0; flagdesc_gennotify[i].name; i++) {
if (!(emerge->gennotify & flagdesc_gennotify[i].flag))
continue;
std::vector<v3s16> *posvec = mg->gen_notifications[i];
if (!posvec)
return 0;
lua_newtable(L);
for (unsigned int j = 0; j != posvec->size(); j++) {
push_v3s16(L, (*posvec)[j]);
lua_rawseti(L, -2, j + 1);
}
lua_setfield(L, -2, flagdesc_gennotify[i].name);
posvec->clear();
}
return 1; }
}
return nargs;
return 0;
}
// minetest.set_mapgen_params(params)
@ -214,6 +235,16 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L)
return 0;
}
// set_gen_notify(string)
int ModApiMapgen::l_set_gen_notify(lua_State *L)
{
if (lua_isstring(L, 1)) {
EmergeManager *emerge = getServer(L)->getEmergeManager();
emerge->gennotify = readFlagString(lua_tostring(L, 1), flagdesc_gennotify);
}
return 0;
}
// register_biome({lots of stuff})
int ModApiMapgen::l_register_biome(lua_State *L)
{
@ -581,6 +612,7 @@ void ModApiMapgen::Initialize(lua_State *L, int top)
API_FCT(get_mapgen_object);
API_FCT(set_mapgen_params);
API_FCT(set_gen_notify);
API_FCT(register_biome);
API_FCT(register_decoration);

View File

@ -32,6 +32,9 @@ private:
// set mapgen parameters
static int l_set_mapgen_params(lua_State *L);
// set_gen_notify(flagstring)
static int l_set_gen_notify(lua_State *L);
// register_biome({lots of stuff})
static int l_register_biome(lua_State *L);