From c3708b456e90bccf19e7c82c54a93c8cb7c8896c Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sat, 14 Dec 2013 01:52:06 -0500 Subject: [PATCH] Add map feature generation notify Lua API --- doc/lua_api.txt | 10 ++ src/cavegen.cpp | 24 ++++ src/dungeongen.cpp | 199 +++++++++++++++----------------- src/dungeongen.h | 14 +-- src/emerge.cpp | 3 +- src/emerge.h | 2 + src/mapgen.cpp | 19 +++ src/mapgen.h | 55 ++++++--- src/mapgen_v6.cpp | 19 +-- src/mapgen_v7.cpp | 5 +- src/script/lua_api/l_mapgen.cpp | 50 ++++++-- src/script/lua_api/l_mapgen.h | 3 + 12 files changed, 252 insertions(+), 151 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 28d8b9cc8..abfb8f94b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -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: diff --git a/src/cavegen.cpp b/src/cavegen.cpp index f04c02db9..b32e140f8 100644 --- a/src/cavegen.cpp +++ b/src/cavegen.cpp @@ -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 *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 *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 *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 *nvec = mg->gen_notifications[notifytype]; + nvec->push_back(v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z)); + } } diff --git a/src/dungeongen.cpp b/src/dungeongen.cpp index fee6f66c0..ff0a39e9e 100644 --- a/src/dungeongen.cpp +++ b/src/dungeongen.cpp @@ -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 *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; diff --git a/src/dungeongen.h b/src/dungeongen.h index b2b28db3a..4a0bfcefd 100644 --- a/src/dungeongen.h +++ b/src/dungeongen.h @@ -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); diff --git a/src/emerge.cpp b/src/emerge.cpp index 94b6464f6..f096bb874 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -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()) { diff --git a/src/emerge.h b/src/emerge.h index ed982924b..d5bb72f85 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -94,6 +94,8 @@ public: u16 qlimit_diskonly; u16 qlimit_generate; + u32 gennotify; + MapgenParams *luaoverride_params; u32 luaoverride_params_modified; u32 luaoverride_flagmask; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 20fc4459b..3d5c7b3cc 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -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; +} + + +Mapgen::~Mapgen() { + for (unsigned int i = 0; i != NUM_GEN_NOTIFY; i++) + delete gen_notifications[i]; } diff --git a/src/mapgen.h b/src/mapgen.h index 47a7204bc..feec60e19 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -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 *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; diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 11491b6b6..3e152861c 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -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 diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 88da4fcd2..6d5c04900 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -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++) { diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index fe7ac8dd6..5489531b6 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -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 *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); diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index d0da5bb13..43fd6a09f 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -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);