1
0
mirror of https://github.com/moparisthebest/minetest synced 2024-11-11 11:55:03 -05:00

Add map feature generation notify Lua API

This commit is contained in:
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) ^ Return world-specific perlin noise (int(worldseed)+seeddiff)
minetest.get_voxel_manip() minetest.get_voxel_manip()
^ Return voxel manipulator object ^ 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) minetest.get_mapgen_object(objectname)
^ Return requested mapgen object if available (see Mapgen objects) ^ Return requested mapgen object if available (see Mapgen objects)
minetest.set_mapgen_params(MapgenParams) 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 Returns an array containing the humidity values of nodes in the most recently generated chunk by the
current mapgen. 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 Registered entities
-------------------- --------------------
- Functions receive a "luaentity" as self: - 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 (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 // Generate some tunnel starting from orp
for (u16 j = 0; j < tunnel_routepoints; j++) for (u16 j = 0; j < tunnel_routepoints; j++)
makeTunnel(j % dswitchint == 0); 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 (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 // Generate some tunnel starting from orp
for (u16 j = 0; j < tunnel_routepoints; j++) for (u16 j = 0; j < tunnel_routepoints; j++)
makeTunnel(j % dswitchint == 0); 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, DungeonGen::DungeonGen(Mapgen *mapgen, DungeonParams *dparams) {
DungeonParams *dparams) { this->mg = mapgen;
this->ndef = ndef; this->vm = mapgen->vm;
this->mapseed = seed;
this->water_level = waterlevel;
#ifdef DGEN_USE_TORCHES #ifdef DGEN_USE_TORCHES
c_torch = ndef->getId("default:torch"); c_torch = ndef->getId("default:torch");
@ -55,15 +53,16 @@ DungeonGen::DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel,
if (dparams) { if (dparams) {
memcpy(&dp, dparams, sizeof(dp)); memcpy(&dp, dparams, sizeof(dp));
} else { } else {
dp.c_water = ndef->getId("mapgen_water_source"); dp.c_water = mg->ndef->getId("mapgen_water_source");
dp.c_cobble = ndef->getId("mapgen_cobble"); dp.c_cobble = mg->ndef->getId("mapgen_cobble");
dp.c_moss = ndef->getId("mapgen_mossycobble"); dp.c_moss = mg->ndef->getId("mapgen_mossycobble");
dp.c_stair = ndef->getId("mapgen_stair_cobble"); dp.c_stair = mg->ndef->getId("mapgen_stair_cobble");
dp.diagonal_dirs = false; dp.diagonal_dirs = false;
dp.mossratio = 3.0; dp.mossratio = 3.0;
dp.holesize = v3s16(1, 2, 1); dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0,0,0); dp.roomsize = v3s16(0,0,0);
dp.notifytype = GENNOTIFY_DUNGEON;
dp.np_rarity = nparams_dungeon_rarity; dp.np_rarity = nparams_dungeon_rarity;
dp.np_wetness = nparams_dungeon_wetness; 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, void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) {
v3s16 nmin, v3s16 nmax) {
//TimeTaker t("gen dungeons"); //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 || 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; return;
this->vmanip = vm;
this->blockseed = bseed; this->blockseed = bseed;
random.seed(bseed + 2); random.seed(bseed + 2);
// Dungeon generator doesn't modify places which have this set // 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 // Set all air and water to be untouchable to make dungeons open
// to caves and open air // to caves and open air
for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 z = nmin.Z; z <= nmax.Z; z++) {
for (s16 y = nmin.Y; y <= nmax.Y; y++) { 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++) { 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) 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++; i++;
} }
} }
@ -109,13 +106,13 @@ void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
if (dp.mossratio != 0.0) { if (dp.mossratio != 0.0) {
for (s16 z = nmin.Z; z <= nmax.Z; z++) for (s16 z = nmin.Z; z <= nmax.Z; z++)
for (s16 y = nmin.Y; y <= nmax.Y; y++) { 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++) { for (s16 x = nmin.X; x <= nmax.X; x++) {
if (vmanip->m_data[i].getContent() == dp.c_cobble) { if (vm->m_data[i].getContent() == dp.c_cobble) {
float wetness = NoisePerlin3D(&dp.np_wetness, x, y, z, mapseed); float wetness = NoisePerlin3D(&dp.np_wetness, x, y, z, mg->seed);
float density = NoisePerlin3D(&dp.np_density, x, y, z, blockseed); float density = NoisePerlin3D(&dp.np_density, x, y, z, blockseed);
if (density < wetness / dp.mossratio) if (density < wetness / dp.mossratio)
vmanip->m_data[i].setContent(dp.c_moss); vm->m_data[i].setContent(dp.c_moss);
} }
i++; i++;
} }
@ -128,7 +125,7 @@ void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
void DungeonGen::makeDungeon(v3s16 start_padding) void DungeonGen::makeDungeon(v3s16 start_padding)
{ {
v3s16 areasize = vmanip->m_area.getExtent(); v3s16 areasize = vm->m_area.getExtent();
v3s16 roomsize; v3s16 roomsize;
v3s16 roomplace; v3s16 roomplace;
@ -136,7 +133,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
Find place for first room Find place for first room
*/ */
bool fits = false; 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); bool is_large_room = ((random.next() & 3) == 1);
roomsize = is_large_room ? roomsize = is_large_room ?
@ -146,7 +143,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
// start_padding is used to disallow starting the generation of // start_padding is used to disallow starting the generation of
// a dungeon in a neighboring generation chunk // 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.X-roomsize.X-1-start_padding.X),
random.range(0,areasize.Y-roomsize.Y-1-start_padding.Y), random.range(0,areasize.Y-roomsize.Y-1-start_padding.Y),
random.range(0,areasize.Z-roomsize.Z-1-start_padding.Z)); 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++) for (s16 x = 1; x < roomsize.X - 1; x++)
{ {
v3s16 p = roomplace + v3s16(x, y, z); v3s16 p = roomplace + v3s16(x, y, z);
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_INSIDE) if ((vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_INSIDE) ||
{ vm->m_data[vi].getContent() == CONTENT_IGNORE) {
fits = false;
break;
}
if (vmanip->m_data[vi].getContent() == CONTENT_IGNORE)
{
fits = false; fits = false;
break; break;
} }
} }
if (fits)
break;
} }
// No place found // No place found
if (fits == false) if (fits == false)
@ -194,10 +184,14 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
makeRoom(roomsize, roomplace); makeRoom(roomsize, roomplace);
v3s16 room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2); 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 #ifdef DGEN_USE_TORCHES
// Place torch at room center (for testing) // 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 #endif
// Quit if last room // Quit if last room
@ -210,12 +204,9 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
v3s16 walker_start_place; v3s16 walker_start_place;
if(start_in_last_room) if (start_in_last_room) {
{
walker_start_place = last_room_center; walker_start_place = last_room_center;
} } else {
else
{
walker_start_place = room_center; walker_start_place = room_center;
// Store center of current room as the last one // Store center of current room as the last one
last_room_center = room_center; last_room_center = room_center;
@ -226,8 +217,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
v3s16 doordir; v3s16 doordir;
m_pos = walker_start_place; m_pos = walker_start_place;
bool r = findPlaceForDoor(doorplace, doordir); if (!findPlaceForDoor(doorplace, doordir))
if (r == false)
return; return;
if (random.range(0,1) == 0) if (random.range(0,1) == 0)
@ -248,8 +238,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
m_pos = corridor_end; m_pos = corridor_end;
m_dir = corridor_end_dir; m_dir = corridor_end_dir;
r = findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace); if (!findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace))
if (r == false)
return; return;
if (random.range(0,1) == 0) if (random.range(0,1) == 0)
@ -274,21 +263,21 @@ void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
{ {
{ {
v3s16 p = roomplace + v3s16(0, y, z); v3s16 p = roomplace + v3s16(0, y, z);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue; continue;
vmanip->m_data[vi] = n_cobble; vm->m_data[vi] = n_cobble;
} }
{ {
v3s16 p = roomplace + v3s16(roomsize.X - 1, y, z); v3s16 p = roomplace + v3s16(roomsize.X - 1, y, z);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue; 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); v3s16 p = roomplace + v3s16(x, y, 0);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue; continue;
vmanip->m_data[vi] = n_cobble; vm->m_data[vi] = n_cobble;
} }
{ {
v3s16 p = roomplace + v3s16(x, y, roomsize.Z - 1); v3s16 p = roomplace + v3s16(x, y, roomsize.Z - 1);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue; 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); v3s16 p = roomplace + v3s16(x, 0, z);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue; continue;
vmanip->m_data[vi] = n_cobble; vm->m_data[vi] = n_cobble;
} }
{ {
v3s16 p = roomplace + v3s16(x,roomsize. Y - 1, z); v3s16 p = roomplace + v3s16(x,roomsize. Y - 1, z);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE)
continue; 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++) for (s16 x = 1; x < roomsize.X - 1; x++)
{ {
v3s16 p = roomplace + v3s16(x, y, z); v3s16 p = roomplace + v3s16(x, y, z);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
vmanip->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE; vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE;
vmanip->m_data[vi] = n_air; 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++) for (s16 x = 0; x < size.X; x++)
{ {
v3s16 p = place + v3s16(x, y, z); v3s16 p = place + v3s16(x, y, z);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip->m_area.index(p); u32 vi = vm->m_area.index(p);
if (vmanip->m_flags[vi] & avoid_flags) if (vm->m_flags[vi] & avoid_flags)
continue; continue;
vmanip->m_flags[vi] |= or_flags; vm->m_flags[vi] |= or_flags;
vmanip->m_data[vi] = n; vm->m_data[vi] = n;
} }
} }
@ -387,7 +376,7 @@ void DungeonGen::makeDoor(v3s16 doorplace, v3s16 doordir)
#ifdef DGEN_USE_TORCHES #ifdef DGEN_USE_TORCHES
// Place torch (for testing) // 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 #endif
} }
@ -416,8 +405,8 @@ void DungeonGen::makeCorridor(v3s16 doorplace,
if (partcount != 0) if (partcount != 0)
p.Y += make_stairs; p.Y += make_stairs;
if (vmanip->m_area.contains(p) == true && if (vm->m_area.contains(p) == true &&
vmanip->m_area.contains(p + v3s16(0, 1, 0)) == true) { vm->m_area.contains(p + v3s16(0, 1, 0)) == true) {
if (make_stairs) { if (make_stairs) {
makeFill(p + v3s16(-1, -1, -1), dp.holesize + v3s16(2, 3, 2), makeFill(p + v3s16(-1, -1, -1), dp.holesize + v3s16(2, 3, 2),
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(dp.c_cobble), 0); 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 // rotate face 180 deg if making stairs backwards
int facedir = dir_to_facedir(dir * make_stairs); 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); u32 vi = vm->m_area.index(p.X - dir.X, p.Y - 1, p.Z - dir.Z);
if (vmanip->m_data[vi].getContent() == dp.c_cobble) if (vm->m_data[vi].getContent() == dp.c_cobble)
vmanip->m_data[vi] = MapNode(dp.c_stair, 0, facedir); vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
vi = vmanip->m_area.index(p.X, p.Y, p.Z); vi = vm->m_area.index(p.X, p.Y, p.Z);
if (vmanip->m_data[vi].getContent() == dp.c_cobble) if (vm->m_data[vi].getContent() == dp.c_cobble)
vmanip->m_data[vi] = MapNode(dp.c_stair, 0, facedir); vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
} }
} else { } else {
makeFill(p + v3s16(-1, -1, -1), dp.holesize + v3s16(2, 2, 2), 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 p = m_pos + m_dir;
v3s16 p1 = p + v3s16(0, 1, 0); v3s16 p1 = p + v3s16(0, 1, 0);
if (vmanip->m_area.contains(p) == false if (vm->m_area.contains(p) == false
|| vmanip->m_area.contains(p1) == false || vm->m_area.contains(p1) == false
|| i % 4 == 0) || i % 4 == 0)
{ {
randomizeDir(); randomizeDir();
continue; continue;
} }
if (vmanip->getNodeNoExNoEmerge(p).getContent() == dp.c_cobble if (vm->getNodeNoExNoEmerge(p).getContent() == dp.c_cobble
&& vmanip->getNodeNoExNoEmerge(p1).getContent() == dp.c_cobble) && vm->getNodeNoExNoEmerge(p1).getContent() == dp.c_cobble)
{ {
// Found wall, this is a good place! // Found wall, this is a good place!
result_place = p; result_place = p;
@ -503,18 +492,18 @@ bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
Determine where to move next Determine where to move next
*/ */
// Jump one up if the actual space is there // Jump one up if the actual space is there
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == dp.c_cobble if (vm->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == dp.c_cobble
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR && vm->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent() == CONTENT_AIR) && vm->getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent() == CONTENT_AIR)
p += v3s16(0,1,0); p += v3s16(0,1,0);
// Jump one down if the actual space is there // Jump one down if the actual space is there
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == dp.c_cobble if (vm->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == dp.c_cobble
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_AIR && vm->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_AIR
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent() == CONTENT_AIR) && vm->getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent() == CONTENT_AIR)
p += v3s16(0,-1,0); p += v3s16(0,-1,0);
// Check if walking is now possible // Check if walking is now possible
if (vmanip->getNodeNoExNoEmerge(p).getContent() != CONTENT_AIR if (vm->getNodeNoExNoEmerge(p).getContent() != CONTENT_AIR
|| vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() != CONTENT_AIR) || vm->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() != CONTENT_AIR)
{ {
// Cannot continue walking here // Cannot continue walking here
randomizeDir(); randomizeDir();
@ -571,12 +560,12 @@ bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
for (s16 x = 1; x < roomsize.X - 1; x++) for (s16 x = 1; x < roomsize.X - 1; x++)
{ {
v3s16 p = roomplace + v3s16(x, y, z); v3s16 p = roomplace + v3s16(x, y, z);
if (vmanip->m_area.contains(p) == false) if (vm->m_area.contains(p) == false)
{ {
fits = false; fits = false;
break; break;
} }
if (vmanip->m_flags[vmanip->m_area.index(p)] if (vm->m_flags[vm->m_area.index(p)]
& VMANIP_FLAG_DUNGEON_INSIDE) & VMANIP_FLAG_DUNGEON_INSIDE)
{ {
fits = false; fits = false;

View File

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

View File

@ -105,8 +105,9 @@ EmergeManager::EmergeManager(IGameDef *gamedef) {
this->luaoverride_params_modified = 0; this->luaoverride_params_modified = 0;
this->luaoverride_flagmask = 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; int nthreads;
if (g_settings->get("num_emerge_threads").empty()) { if (g_settings->get("num_emerge_threads").empty()) {

View File

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

View File

@ -64,6 +64,16 @@ FlagDesc flagdesc_deco_schematic[] = {
{NULL, 0} {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; ndef = NULL;
heightmap = NULL; heightmap = NULL;
biomemap = 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_Y 2
#define DECO_PLACE_CENTER_Z 4 #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_mapgen[];
extern FlagDesc flagdesc_ore[]; extern FlagDesc flagdesc_ore[];
extern FlagDesc flagdesc_deco_schematic[]; extern FlagDesc flagdesc_deco_schematic[];
extern FlagDesc flagdesc_gennotify[];
class BiomeDefManager; class BiomeDefManager;
class Biome; class Biome;
@ -67,6 +74,32 @@ struct BlockMakeData;
class VoxelArea; class VoxelArea;
class Map; 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 { struct MapgenParams {
std::string mg_name; std::string mg_name;
int chunksize; int chunksize;
@ -100,8 +133,11 @@ public:
u8 *biomemap; u8 *biomemap;
v3s16 csize; v3s16 csize;
u32 gennotify;
std::vector<v3s16> *gen_notifications[NUM_GEN_NOTIFY];
Mapgen(); Mapgen();
virtual ~Mapgen() {} virtual ~Mapgen();
s16 findGroundLevelFull(v2s16 p2d); s16 findGroundLevelFull(v2s16 p2d);
s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax); s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax);
@ -123,23 +159,6 @@ struct MapgenFactory {
virtual ~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 { class Ore {
public: public:
std::string ore_name; 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->water_level = params->water_level;
this->flags = params->flags; this->flags = params->flags;
this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
this->gennotify = emerge->gennotify;
this->freq_desert = params->freq_desert; this->freq_desert = params->freq_desert;
this->freq_beach = params->freq_beach; this->freq_beach = params->freq_beach;
@ -456,22 +457,24 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
dp.c_stair = c_stair_cobble; dp.c_stair = c_stair_cobble;
dp.diagonal_dirs = false; dp.diagonal_dirs = false;
dp.mossratio = 3.0; dp.mossratio = 3.0;
dp.holesize = v3s16(1, 2, 1); dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0, 0, 0); dp.roomsize = v3s16(0, 0, 0);
dp.notifytype = GENNOTIFY_DUNGEON;
} else { } else {
dp.c_cobble = c_sandbrick; dp.c_cobble = c_sandbrick;
dp.c_moss = c_sandbrick; // should make this 'cracked sandstone' later dp.c_moss = c_sandbrick; // should make this 'cracked sandstone' later
dp.c_stair = c_stair_sandstone; dp.c_stair = c_stair_sandstone;
dp.diagonal_dirs = true; dp.diagonal_dirs = true;
dp.mossratio = 0.0; dp.mossratio = 0.0;
dp.holesize = v3s16(2, 3, 2); dp.holesize = v3s16(2, 3, 2);
dp.roomsize = v3s16(2, 5, 2); dp.roomsize = v3s16(2, 5, 2);
dp.notifytype = GENNOTIFY_TEMPLE;
} }
DungeonGen dgen(ndef, data->seed, water_level, &dp); DungeonGen dgen(this, &dp);
dgen.generate(vm, blockseed, full_node_min, full_node_max); dgen.generate(blockseed, full_node_min, full_node_max);
} }
// Add top and bottom side of water to transforming_liquid queue // 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->seed = (int)params->seed;
this->water_level = params->water_level; this->water_level = params->water_level;
this->flags = params->flags | MGV7_MOUNTAINS | MGV7_RIDGES; this->flags = params->flags | MGV7_MOUNTAINS | MGV7_RIDGES;
this->gennotify = emerge->gennotify;
this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
@ -207,8 +208,8 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
generateCaves(stone_surface_max_y); generateCaves(stone_surface_max_y);
if (flags & MG_DUNGEONS) { if (flags & MG_DUNGEONS) {
DungeonGen dgen(ndef, data->seed, water_level, NULL); DungeonGen dgen(this, NULL);
dgen.generate(vm, blockseed, full_node_min, full_node_max); dgen.generate(blockseed, full_node_min, full_node_max);
} }
for (size_t i = 0; i != emerge->decorations.size(); i++) { 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_BIOMEMAP, "biomemap"},
{MGOBJ_HEATMAP, "heatmap"}, {MGOBJ_HEATMAP, "heatmap"},
{MGOBJ_HUMIDMAP, "humiditymap"}, {MGOBJ_HUMIDMAP, "humiditymap"},
{MGOBJ_GENNOTIFY, "gennotify"},
{0, NULL}, {0, NULL},
}; };
@ -95,8 +96,6 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
size_t maplen = mg->csize.X * mg->csize.Z; size_t maplen = mg->csize.X * mg->csize.Z;
int nargs = 1;
switch (mgobj) { switch (mgobj) {
case MGOBJ_VMANIP: { case MGOBJ_VMANIP: {
ManualMapVoxelManipulator *vm = mg->vm; ManualMapVoxelManipulator *vm = mg->vm;
@ -113,9 +112,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
// emerged max pos // emerged max pos
push_v3s16(L, vm->m_area.MaxEdge); push_v3s16(L, vm->m_area.MaxEdge);
nargs = 3; return 3; }
break; }
case MGOBJ_HEIGHTMAP: { case MGOBJ_HEIGHTMAP: {
if (!mg->heightmap) if (!mg->heightmap)
return 0; return 0;
@ -125,7 +122,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
lua_pushinteger(L, mg->heightmap[i]); lua_pushinteger(L, mg->heightmap[i]);
lua_rawseti(L, -2, i + 1); lua_rawseti(L, -2, i + 1);
} }
break; }
return 1; }
case MGOBJ_BIOMEMAP: { case MGOBJ_BIOMEMAP: {
if (!mg->biomemap) if (!mg->biomemap)
return 0; return 0;
@ -135,7 +133,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
lua_pushinteger(L, mg->biomemap[i]); lua_pushinteger(L, mg->biomemap[i]);
lua_rawseti(L, -2, i + 1); lua_rawseti(L, -2, i + 1);
} }
break; }
return 1; }
case MGOBJ_HEATMAP: { // Mapgen V7 specific objects case MGOBJ_HEATMAP: { // Mapgen V7 specific objects
case MGOBJ_HUMIDMAP: case MGOBJ_HUMIDMAP:
if (strcmp(emerge->params->mg_name.c_str(), "v7")) 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_pushnumber(L, arr[i]);
lua_rawseti(L, -2, i + 1); 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) // minetest.set_mapgen_params(params)
@ -214,6 +235,16 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L)
return 0; 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}) // register_biome({lots of stuff})
int ModApiMapgen::l_register_biome(lua_State *L) 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(get_mapgen_object);
API_FCT(set_mapgen_params); API_FCT(set_mapgen_params);
API_FCT(set_gen_notify);
API_FCT(register_biome); API_FCT(register_biome);
API_FCT(register_decoration); API_FCT(register_decoration);

View File

@ -32,6 +32,9 @@ private:
// set mapgen parameters // set mapgen parameters
static int l_set_mapgen_params(lua_State *L); 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}) // register_biome({lots of stuff})
static int l_register_biome(lua_State *L); static int l_register_biome(lua_State *L);