diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6c33d92d4677..df4b59a054a1 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1533,10 +1533,11 @@ 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) +minetest.set_gen_notify(flags, {deco_ids}) ^ 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 +^ flags is a flag field with the available flags: +^ dungeon, temple, cave_begin, cave_end, large_cave_begin, large_cave_end, decoration +^ The second parameter is a list of IDS of decorations which notification is requested for minetest.get_mapgen_object(objectname) ^ Return requested mapgen object if available (see Mapgen objects) minetest.set_mapgen_params(MapgenParams) @@ -2220,7 +2221,9 @@ current mapgen. 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 +Possible fields of the table returned are: + dungeon, temple, cave_begin, cave_end, large_cave_begin, large_cave_end, decoration +Decorations have a key in the format of "decoration#id", where id is the numeric unique decoration ID. Registered entities -------------------- diff --git a/src/cavegen.cpp b/src/cavegen.cpp index d93911f277bd..02eef72d8f44 100644 --- a/src/cavegen.cpp +++ b/src/cavegen.cpp @@ -45,7 +45,7 @@ CaveV6::CaveV6(MapgenV6 *mg, PseudoRandom *ps, PseudoRandom *ps2, bool is_large_ max_tunnel_diameter = ps->range(2, 6); dswitchint = ps->range(1, 14); flooded = true; - + if (large_cave) { part_max_length_rs = ps->range(2,4); tunnel_routepoints = ps->range(5, ps->range(15,30)); @@ -55,7 +55,7 @@ CaveV6::CaveV6(MapgenV6 *mg, PseudoRandom *ps, PseudoRandom *ps2, bool is_large_ part_max_length_rs = ps->range(2,9); tunnel_routepoints = ps->range(10, ps->range(15,30)); } - + large_cave_is_flat = (ps->range(0,1) == 0); } @@ -109,21 +109,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)); - } + // Add generation notify begin event + v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); + GenNotifyType notifytype = large_cave ? + GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN; + mg->gennotify.addEvent(notifytype, abs_pos); // 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)); - } + // Add generation notify end event + abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); + notifytype = large_cave ? + GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN; + mg->gennotify.addEvent(notifytype, abs_pos); } @@ -179,31 +179,31 @@ void CaveV6::makeTunnel(bool dirswitch) { rp.X = 0; else if (rp.X >= ar.X) rp.X = ar.X - 1; - + if (rp.Y < route_y_min) rp.Y = route_y_min; else if (rp.Y >= route_y_max) rp.Y = route_y_max - 1; - + if (rp.Z < 0) rp.Z = 0; else if (rp.Z >= ar.Z) rp.Z = ar.Z - 1; - + vec = rp - orp; float veclen = vec.getLength(); // As odd as it sounds, veclen is *exactly* 0.0 sometimes, causing a FPE if (veclen < 0.05) veclen = 1.0; - + // Every second section is rough bool randomize_xz = (ps2->range(1, 2) == 1); // Carve routes for (float f = 0; f < 1.0; f += 1.0 / veclen) carveRoute(vec, f, randomize_xz); - + orp = rp; } @@ -212,10 +212,10 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) { MapNode airnode(CONTENT_AIR); MapNode waternode(c_water_source); MapNode lavanode(c_lava_source); - + v3s16 startp(orp.X, orp.Y, orp.Z); startp += of; - + v3f fp = orp + vec * f; fp.X += 0.1 * ps->range(-10, 10); fp.Z += 0.1 * ps->range(-10, 10); @@ -227,13 +227,13 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) { d0 += ps->range(-1, 1); d1 += ps->range(-1, 1); } - + for (s16 z0 = d0; z0 <= d1; z0++) { s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1); for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { s16 maxabsxz = MYMAX(abs(x0), abs(z0)); s16 si2 = rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); - for (s16 y0 = -si2; y0 <= si2; y0++) { + for (s16 y0 = -si2; y0 <= si2; y0++) { if (large_cave_is_flat) { // Make large caves not so tall if (rs > 7 && abs(y0) >= rs / 3) @@ -293,7 +293,7 @@ CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) { dswitchint = ps->range(1, 14); flooded = ps->range(1, 2) == 2; - + if (large_cave) { part_max_length_rs = ps->range(2, 4); tunnel_routepoints = ps->range(5, ps->range(15, 30)); @@ -305,7 +305,7 @@ CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) { min_tunnel_diameter = 2; max_tunnel_diameter = ps->range(2, 6); } - + large_cave_is_flat = (ps->range(0, 1) == 0); } @@ -358,21 +358,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)); - } + // Add generation notify begin event + v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); + GenNotifyType notifytype = large_cave ? + GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN; + mg->gennotify.addEvent(notifytype, abs_pos); // 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)); - } + // Add generation notify end event + abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); + notifytype = large_cave ? + GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; + mg->gennotify.addEvent(notifytype, abs_pos); } @@ -428,7 +428,7 @@ void CaveV7::makeTunnel(bool dirswitch) { v3s16 orpi(orp.X, orp.Y, orp.Z); v3s16 veci(vec.X, vec.Y, vec.Z); v3s16 p; - + p = orpi + veci + of + rs / 2; if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { @@ -439,7 +439,7 @@ void CaveV7::makeTunnel(bool dirswitch) { } else if (p.Y > water_level) { return; // If it's not in our heightmap, use a simple heuristic } - + p = orpi + of + rs / 2; if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { @@ -447,7 +447,7 @@ void CaveV7::makeTunnel(bool dirswitch) { s16 h = mg->ridge_heightmap[index]; if (h < p.Y) return; - } else if (p.Y > water_level) { + } else if (p.Y > water_level) { return; } } @@ -459,23 +459,23 @@ void CaveV7::makeTunnel(bool dirswitch) { rp.X = 0; else if (rp.X >= ar.X) rp.X = ar.X - 1; - + if (rp.Y < route_y_min) rp.Y = route_y_min; else if (rp.Y >= route_y_max) rp.Y = route_y_max - 1; - + if (rp.Z < 0) rp.Z = 0; else if (rp.Z >= ar.Z) rp.Z = ar.Z - 1; - + vec = rp - orp; float veclen = vec.getLength(); if (veclen < 0.05) veclen = 1.0; - + // Every second section is rough bool randomize_xz = (ps->range(1, 2) == 1); @@ -487,7 +487,7 @@ void CaveV7::makeTunnel(bool dirswitch) { // Carve routes for (float f = 0; f < 1.0; f += 1.0 / veclen) carveRoute(vec, f, randomize_xz, is_ravine); - + orp = rp; } @@ -496,14 +496,14 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { MapNode airnode(CONTENT_AIR); MapNode waternode(c_water_source); MapNode lavanode(c_lava_source); - + v3s16 startp(orp.X, orp.Y, orp.Z); startp += of; - + float nval = NoisePerlin3D(np_caveliquids, startp.X, startp.Y, startp.Z, mg->seed); MapNode liquidnode = nval < 0.40 ? lavanode : waternode; - + v3f fp = orp + vec * f; fp.X += 0.1 * ps->range(-10, 10); fp.Z += 0.1 * ps->range(-10, 10); @@ -515,23 +515,23 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { d0 += ps->range(-1, 1); d1 += ps->range(-1, 1); } - + bool flat_cave_floor = !large_cave && ps->range(0, 2) == 2; bool should_make_cave_hole = ps->range(1, 10) == 1; - + for (s16 z0 = d0; z0 <= d1; z0++) { s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1); for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { s16 maxabsxz = MYMAX(abs(x0), abs(z0)); - + s16 si2 = is_ravine ? MYMIN(ps->range(25, 26), ar.Y) : rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); - + for (s16 y0 = -si2; y0 <= si2; y0++) { // Make better floors in small caves if(flat_cave_floor && y0 <= -rs/2 && rs<=7) continue; - + if (large_cave_is_flat) { // Make large caves not so tall if (rs > 7 && abs(y0) >= rs / 3) @@ -540,7 +540,7 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0); p += of; - + if (!is_ravine && mg->heightmap && should_make_cave_hole && p.X <= node_max.X && p.Z <= node_max.Z) { int maplen = node_max.X - node_min.X + 1; @@ -553,13 +553,13 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { continue; u32 i = vm->m_area.index(p); - + // Don't replace air, water, lava, or ice content_t c = vm->m_data[i].getContent(); if (!ndef->get(c).is_ground_content || c == CONTENT_AIR || c == c_water_source || c == c_lava_source || c == c_ice) continue; - + if (large_cave) { int full_ymin = node_min.Y - MAP_BLOCKSIZE; int full_ymax = node_max.Y + MAP_BLOCKSIZE; @@ -573,7 +573,7 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { } else { if (c == CONTENT_IGNORE) continue; - + vm->m_data[i] = airnode; vm->m_flags[i] |= VMANIP_FLAG_CAVE; } diff --git a/src/dungeongen.cpp b/src/dungeongen.cpp index 2027b7f1381c..2a89c714e379 100644 --- a/src/dungeongen.cpp +++ b/src/dungeongen.cpp @@ -46,7 +46,7 @@ DungeonGen::DungeonGen(Mapgen *mapgen, DungeonParams *dparams) { #ifdef DGEN_USE_TORCHES c_torch = ndef->getId("default:torch"); #endif - + if (dparams) { memcpy(&dp, dparams, sizeof(dp)); } else { @@ -95,7 +95,7 @@ void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) { } } } - + // Add it makeDungeon(v3s16(1,1,1) * MAP_BLOCKSIZE); @@ -115,7 +115,7 @@ void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) { } } } - + //printf("== gen dungeons: %dms\n", t.stop()); } @@ -144,7 +144,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding) 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)); - + /* Check that we're not putting the room to an unknown place, otherwise it might end up floating in the air @@ -181,10 +181,7 @@ 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); - } + mg->gennotify.addEvent(dp.notifytype, room_center); #ifdef DGEN_USE_TORCHES // Place torch at room center (for testing) @@ -212,7 +209,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding) // Create walker and find a place for a door v3s16 doorplace; v3s16 doordir; - + m_pos = walker_start_place; if (!findPlaceForDoor(doorplace, doordir)) return; @@ -253,7 +250,7 @@ void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace) { MapNode n_cobble(dp.c_cobble); MapNode n_air(CONTENT_AIR); - + // Make +-X walls for (s16 z = 0; z < roomsize.Z; z++) for (s16 y = 0; y < roomsize.Y; y++) @@ -393,10 +390,10 @@ void DungeonGen::makeCorridor(v3s16 doorplace, u32 partlength = random.range(1, 13); u32 partcount = 0; s16 make_stairs = 0; - + if (random.next() % 2 == 0 && partlength >= 3) make_stairs = random.next() % 2 ? 1 : -1; - + for (u32 i = 0; i < length; i++) { v3s16 p = p0 + dir; if (partcount != 0) @@ -409,7 +406,7 @@ void DungeonGen::makeCorridor(v3s16 doorplace, VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(dp.c_cobble), 0); makeHole(p); makeHole(p - dir); - + // TODO: fix stairs code so it works 100% (quite difficult) // exclude stairs from the bottom step @@ -419,11 +416,11 @@ void DungeonGen::makeCorridor(v3s16 doorplace, ((make_stairs == -1) && i != length - 1))) { // rotate face 180 deg if making stairs backwards int facedir = dir_to_facedir(dir * make_stairs); - + 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 = 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); diff --git a/src/dungeongen.h b/src/dungeongen.h index 4a0bfcefd85c..ff1d0bc33eb7 100644 --- a/src/dungeongen.h +++ b/src/dungeongen.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "voxel.h" #include "noise.h" +#include "mapgen.h" #define VMANIP_FLAG_DUNGEON_INSIDE VOXELFLAG_CHECKED1 #define VMANIP_FLAG_DUNGEON_PRESERVE VOXELFLAG_CHECKED2 @@ -30,7 +31,6 @@ 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,7 +44,7 @@ struct DungeonParams { content_t c_moss; content_t c_stair; - int notifytype; + GenNotifyType notifytype; bool diagonal_dirs; float mossratio; v3s16 holesize; @@ -65,14 +65,14 @@ class DungeonGen { content_t c_torch; DungeonParams dp; - + //RoomWalker v3s16 m_pos; v3s16 m_dir; 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); void makeCorridor(v3s16 doorplace, v3s16 doordir, @@ -84,7 +84,7 @@ class DungeonGen { bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir); bool findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace, v3s16 &result_doordir, v3s16 &result_roomplace); - + void randomizeDir() { m_dir = rand_ortho_dir(random, dp.diagonal_dirs); diff --git a/src/emerge.cpp b/src/emerge.cpp index 6410e56e955a..8813a71a96dc 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -94,7 +94,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef) { this->oremgr = new OreManager(gamedef); this->decomgr = new DecorationManager(gamedef); this->schemmgr = new SchematicManager(gamedef); - this->gennotify = 0; + this->gen_notify_on = 0; // Note that accesses to this variable are not synchronized. // This is because the *only* thread ever starting or stopping diff --git a/src/emerge.h b/src/emerge.h index 65b1d6594ebe..7de1c8391d9c 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -89,7 +89,8 @@ class EmergeManager { u16 qlimit_diskonly; u16 qlimit_generate; - u32 gennotify; + u32 gen_notify_on; + std::set gen_notify_on_deco_ids; //// Block emerge queue data structures JMutex queuemutex; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 60fa842a6635..44ce0c6151fc 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include "content_sao.h" #include "nodedef.h" +#include "emerge.h" #include "content_mapnode.h" // For content_mapnode_get_new_name #include "voxelalgorithms.h" #include "profiler.h" @@ -55,36 +56,53 @@ FlagDesc flagdesc_gennotify[] = { {"cave_end", 1 << GENNOTIFY_CAVE_END}, {"large_cave_begin", 1 << GENNOTIFY_LARGECAVE_BEGIN}, {"large_cave_end", 1 << GENNOTIFY_LARGECAVE_END}, + {"decoration", 1 << GENNOTIFY_DECORATION}, {NULL, 0} }; /////////////////////////////////////////////////////////////////////////////// +Mapgen::Mapgen() +{ + generating = false; + id = -1; + seed = 0; + water_level = 0; + flags = 0; -Mapgen::Mapgen() { - seed = 0; - water_level = 0; - generating = false; - id = -1; vm = NULL; ndef = NULL; heightmap = NULL; biomemap = NULL; +} + - for (unsigned int i = 0; i != NUM_GEN_NOTIFY; i++) - gen_notifications[i] = new std::vector; +Mapgen::Mapgen(int mapgenid, MapgenParams *params, EmergeManager *emerge) : + gennotify(emerge->gen_notify_on, &emerge->gen_notify_on_deco_ids) +{ + generating = false; + id = mapgenid; + seed = (int)params->seed; + water_level = params->water_level; + flags = params->flags; + csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE); + + vm = NULL; + ndef = NULL; + heightmap = NULL; + biomemap = NULL; } -Mapgen::~Mapgen() { - for (unsigned int i = 0; i != NUM_GEN_NOTIFY; i++) - delete gen_notifications[i]; +Mapgen::~Mapgen() +{ } // Returns Y one under area minimum if not found -s16 Mapgen::findGroundLevelFull(v2s16 p2d) { +s16 Mapgen::findGroundLevelFull(v2s16 p2d) +{ v3s16 em = vm->m_area.getExtent(); s16 y_nodes_max = vm->m_area.MaxEdge.Y; s16 y_nodes_min = vm->m_area.MinEdge.Y; @@ -102,7 +120,8 @@ s16 Mapgen::findGroundLevelFull(v2s16 p2d) { } -s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) { +s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) +{ v3s16 em = vm->m_area.getExtent(); u32 i = vm->m_area.index(p2d.X, ymax, p2d.Y); s16 y; @@ -118,7 +137,8 @@ s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) { } -void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) { +void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) +{ if (!heightmap) return; @@ -141,7 +161,8 @@ void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) { } -void Mapgen::updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nmax) { +void Mapgen::updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nmax) +{ bool isliquid, wasliquid; v3s16 em = vm->m_area.getExtent(); @@ -165,7 +186,8 @@ void Mapgen::updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nm } -void Mapgen::setLighting(v3s16 nmin, v3s16 nmax, u8 light) { +void Mapgen::setLighting(v3s16 nmin, v3s16 nmax, u8 light) +{ ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); VoxelArea a(nmin, nmax); @@ -179,7 +201,8 @@ void Mapgen::setLighting(v3s16 nmin, v3s16 nmax, u8 light) { } -void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) { +void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) +{ if (light <= 1 || !a.contains(p)) return; @@ -202,7 +225,8 @@ void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) { } -void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) { +void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) +{ VoxelArea a(nmin, nmax); bool block_is_underground = (water_level >= nmax.Y); @@ -264,7 +288,8 @@ void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) { } -void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) { +void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) +{ enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT}; VoxelArea a(nmin, nmax); bool block_is_underground = (water_level > nmax.Y); @@ -287,6 +312,72 @@ void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) { } +/////////////////////////////////////////////////////////////////////////////// + +GenerateNotifier::GenerateNotifier() +{ +} + + +GenerateNotifier::GenerateNotifier(u32 notify_on, + std::set *notify_on_deco_ids) +{ + m_notify_on = notify_on; + m_notify_on_deco_ids = notify_on_deco_ids; +} + + +void GenerateNotifier::setNotifyOn(u32 notify_on) +{ + m_notify_on = notify_on; +} + + +void GenerateNotifier::setNotifyOnDecoIds(std::set *notify_on_deco_ids) +{ + m_notify_on_deco_ids = notify_on_deco_ids; +} + + +bool GenerateNotifier::addEvent(GenNotifyType type, v3s16 pos, u32 id) +{ + if (!(m_notify_on & (1 << type))) + return false; + + if (type == GENNOTIFY_DECORATION && + m_notify_on_deco_ids->find(id) == m_notify_on_deco_ids->end()) + return false; + + GenNotifyEvent gne; + gne.type = type; + gne.pos = pos; + gne.id = id; + m_notify_events.push_back(gne); + + return true; +} + + +void GenerateNotifier::getEvents( + std::map > &event_map, + bool peek_events) +{ + std::list::iterator it; + + for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) { + GenNotifyEvent &gn = *it; + std::string name = (gn.type == GENNOTIFY_DECORATION) ? + "decoration#"+ itos(gn.id) : + flagdesc_gennotify[gn.type].name; + + event_map[name].push_back(gn.pos); + } + + if (!peek_events) + m_notify_events.clear(); +} + + /////////////////////////////////////////////////////////////////////////////// diff --git a/src/mapgen.h b/src/mapgen.h index cf2120a7a284..9cdb157e1118 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -34,8 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_FLAT 0x08 #define MG_LIGHT 0x10 -#define NUM_GEN_NOTIFY 6 - class Settings; class ManualMapVoxelManipulator; class INodeDefManager; @@ -61,13 +59,39 @@ enum MapgenObject { MGOBJ_GENNOTIFY }; -enum GenNotify { +enum GenNotifyType { GENNOTIFY_DUNGEON, GENNOTIFY_TEMPLE, GENNOTIFY_CAVE_BEGIN, GENNOTIFY_CAVE_END, GENNOTIFY_LARGECAVE_BEGIN, - GENNOTIFY_LARGECAVE_END + GENNOTIFY_LARGECAVE_END, + GENNOTIFY_DECORATION, + NUM_GENNOTIFY_TYPES +}; + +struct GenNotifyEvent { + GenNotifyType type; + v3s16 pos; + u32 id; +}; + +class GenerateNotifier { +public: + GenerateNotifier(); + GenerateNotifier(u32 notify_on, std::set *notify_on_deco_ids); + + void setNotifyOn(u32 notify_on); + void setNotifyOnDecoIds(std::set *notify_on_deco_ids); + + bool addEvent(GenNotifyType type, v3s16 pos, u32 id=0); + void getEvents(std::map > &event_map, + bool peek_events=false); + +private: + u32 m_notify_on; + std::set *m_notify_on_deco_ids; + std::list m_notify_events; }; struct MapgenSpecificParams { @@ -85,7 +109,8 @@ struct MapgenParams { MapgenSpecificParams *sparams; - MapgenParams() { + MapgenParams() + { mg_name = DEFAULT_MAPGEN; seed = 0; water_level = 1; @@ -99,6 +124,7 @@ class Mapgen { public: int seed; int water_level; + u32 flags; bool generating; int id; ManualMapVoxelManipulator *vm; @@ -108,10 +134,10 @@ class Mapgen { u8 *biomemap; v3s16 csize; - u32 gennotify; - std::vector *gen_notifications[NUM_GEN_NOTIFY]; + GenerateNotifier gennotify; Mapgen(); + Mapgen(int mapgenid, MapgenParams *params, EmergeManager *emerge); virtual ~Mapgen(); s16 findGroundLevelFull(v2s16 p2d); diff --git a/src/mapgen_singlenode.cpp b/src/mapgen_singlenode.cpp index 9f2e6c122df9..8558b3b1427e 100644 --- a/src/mapgen_singlenode.cpp +++ b/src/mapgen_singlenode.cpp @@ -39,7 +39,8 @@ void MapgenSinglenodeParams::writeParams(Settings *settings) { /////////////////////////////////////////////////////////////////////////////// MapgenSinglenode::MapgenSinglenode(int mapgenid, - MapgenParams *params, EmergeManager *emerge) + MapgenParams *params, EmergeManager *emerge) + : Mapgen(mapgenid, params, emerge) { flags = params->flags; @@ -67,18 +68,18 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data) { data->blockpos_requested.Z <= data->blockpos_max.Z); this->generating = true; - this->vm = data->vmanip; + this->vm = data->vmanip; this->ndef = data->nodedef; - + v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; // Area of central chunk v3s16 node_min = blockpos_min*MAP_BLOCKSIZE; v3s16 node_max = (blockpos_max+v3s16(1,1,1))*MAP_BLOCKSIZE-v3s16(1,1,1); - + MapNode n_node(c_node); - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 y = node_min.Y; y <= node_max.Y; y++) { u32 i = vm->m_area.index(node_min.X, y, z); @@ -96,7 +97,7 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data) { if (flags & MG_LIGHT) calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); - + this->generating = false; } diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp index 3867827cc96c..95cfeeef5afc 100644 --- a/src/mapgen_v5.cpp +++ b/src/mapgen_v5.cpp @@ -47,19 +47,12 @@ FlagDesc flagdesc_mapgen_v5[] = { }; -MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_) { - this->generating = false; - this->id = mapgenid; +MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_) + : Mapgen(mapgenid, params, emerge) +{ this->emerge = emerge_; this->bmgr = emerge->biomemgr; - this->seed = (int)params->seed; - this->water_level = params->water_level; - this->flags = params->flags; - this->gennotify = emerge->gennotify; - - this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; - // amount of elements to skip for the next index // for noise/height/biome maps (not vmanip) this->ystride = csize.X; @@ -69,8 +62,7 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_) { this->heightmap = new s16[csize.X * csize.Z]; MapgenV5Params *sp = (MapgenV5Params *)params->sparams; - - this->spflags = sp->spflags; + this->spflags = sp->spflags; // Terrain noise noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z); @@ -129,7 +121,7 @@ MapgenV5::~MapgenV5() { delete noise_heat; delete noise_humidity; - + delete[] heightmap; delete[] biomemap; } @@ -234,12 +226,12 @@ void MapgenV5::makeChunk(BlockMakeData *data) { assert(data->blockpos_requested.X <= data->blockpos_max.X && data->blockpos_requested.Y <= data->blockpos_max.Y && data->blockpos_requested.Z <= data->blockpos_max.Z); - + generating = true; - vm = data->vmanip; + vm = data->vmanip; ndef = data->nodedef; //TimeTaker t("makeChunk"); - + v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; node_min = blockpos_min * MAP_BLOCKSIZE; @@ -249,7 +241,7 @@ void MapgenV5::makeChunk(BlockMakeData *data) { // Create a block-specific seed blockseed = emerge->getBlockSeed(full_node_min); //////use getBlockSeed2()! - + // Make some noise calculateNoise(); @@ -265,7 +257,7 @@ void MapgenV5::makeChunk(BlockMakeData *data) { // Calculate biomes bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); - + // Actually place the biome-specific nodes generateBiomes(); @@ -288,12 +280,12 @@ void MapgenV5::makeChunk(BlockMakeData *data) { // Add top and bottom side of water to transforming_liquid queue updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); - + // Calculate lighting if (flags & MG_LIGHT) calcLighting(node_min - v3s16(0, 1, 0) - v3s16(1, 0, 1) * MAP_BLOCKSIZE, node_max + v3s16(0, 1, 0) + v3s16(1, 0, 1) * MAP_BLOCKSIZE); - + this->generating = false; } @@ -303,7 +295,7 @@ void MapgenV5::calculateNoise() { int x = node_min.X; int y = node_min.Y - 1; int z = node_min.Z; - + noise_filler_depth->perlinMap2D(x, z); noise_factor->perlinMap2D(x, z); noise_height->perlinMap2D(x, z); @@ -426,20 +418,20 @@ void MapgenV5::generateBiomes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = (Biome *)bmgr->get(biomemap[index]); s16 dfiller = biome->depth_filler + noise_filler_depth->result[index]; s16 y0_top = biome->depth_top; s16 y0_filler = biome->depth_top + dfiller; - + s16 nplaced = 0; - u32 i = vm->m_area.index(x, node_max.Y, z); + u32 i = vm->m_area.index(x, node_max.Y, z); content_t c_above = vm->m_data[i + em.X].getContent(); bool have_air = c_above == CONTENT_AIR; - + for (s16 y = node_max.Y; y >= node_min.Y; y--) { content_t c = vm->m_data[i].getContent(); bool is_replaceable_content = @@ -448,7 +440,7 @@ void MapgenV5::generateBiomes() { if (is_replaceable_content && have_air) { content_t c_below = vm->m_data[i - em.X].getContent(); - + if (c_below != CONTENT_AIR) { if (nplaced < y0_top) { if(y < water_level) @@ -484,7 +476,7 @@ void MapgenV5::generateBiomes() { have_air = true; nplaced = 0; } - + vm->m_area.add_y(em, i, -1); } } @@ -493,14 +485,14 @@ void MapgenV5::generateBiomes() { void MapgenV5::dustTopNodes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + if (water_level > node_max.Y) return; for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = (Biome *)bmgr->get(biomemap[index]); - + if (biome->c_dust == CONTENT_IGNORE) continue; @@ -512,18 +504,18 @@ void MapgenV5::dustTopNodes() { vm->m_area.add_y(em, vi, -1); } - + content_t c = vm->m_data[vi].getContent(); if (c == biome->c_water && biome->c_dust_water != CONTENT_IGNORE) { if (y < node_min.Y - 1) continue; - + vm->m_data[vi] = MapNode(biome->c_dust_water); } else if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) { if (y == node_max.Y + 1) continue; - + vm->m_area.add_y(em, vi, 1); vm->m_data[vi] = MapNode(biome->c_dust); } diff --git a/src/mapgen_v5.h b/src/mapgen_v5.h index 84e63672b9be..22a836d64afe 100644 --- a/src/mapgen_v5.h +++ b/src/mapgen_v5.h @@ -41,7 +41,7 @@ struct MapgenV5Params : public MapgenSpecificParams { MapgenV5Params(); ~MapgenV5Params() {} - + void readParams(Settings *settings); void writeParams(Settings *settings); }; @@ -54,7 +54,6 @@ class MapgenV5 : public Mapgen { int ystride; int zstride; - u32 flags; u32 spflags; u32 blockseed; @@ -62,7 +61,7 @@ class MapgenV5 : public Mapgen { v3s16 node_max; v3s16 full_node_min; v3s16 full_node_max; - + Noise *noise_filler_depth; Noise *noise_factor; Noise *noise_height; @@ -92,7 +91,7 @@ class MapgenV5 : public Mapgen { MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_); ~MapgenV5(); - + virtual void makeChunk(BlockMakeData *data); int getGroundLevelAtPoint(v2s16 p); void calculateNoise(); @@ -107,7 +106,7 @@ struct MapgenFactoryV5 : public MapgenFactory { Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) { return new MapgenV5(mgid, params, emerge); }; - + MapgenSpecificParams *createMapgenParams() { return new MapgenV5Params(); }; diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index de0c8168821f..f1ba2a486205 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -49,21 +49,13 @@ FlagDesc flagdesc_mapgen_v6[] = { /////////////////////////////////////////////////////////////////////////////// -MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) { - this->generating = false; - this->id = mapgenid; - this->emerge = emerge; - - this->seed = (int)params->seed; - this->water_level = params->water_level; - this->flags = params->flags; - this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; - this->gennotify = emerge->gennotify; - +MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) + : Mapgen(mapgenid, params, emerge) +{ + this->emerge = emerge; this->ystride = csize.X; //////fix this - - MapgenV6Params *sp = (MapgenV6Params *)params->sparams; + MapgenV6Params *sp = (MapgenV6Params *)params->sparams; this->spflags = sp->spflags; this->freq_desert = sp->freq_desert; this->freq_beach = sp->freq_beach; @@ -224,7 +216,7 @@ bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos) //////////////////////// Base terrain height functions float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher, - float steepness, float height_select) { + float steepness, float height_select) { float base = 1 + terrain_base; float higher = 1 + terrain_higher; @@ -245,7 +237,7 @@ float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher, float a_off = -0.20; // Offset to more low float a = 0.5 + b * (a_off + height_select); a = rangelim(a, 0.0, 1.0); // Limit - + return base * (1.0 - a) + higher * a; } @@ -253,7 +245,7 @@ float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher, float MapgenV6::baseTerrainLevelFromNoise(v2s16 p) { if (flags & MG_FLAT) return water_level; - + float terrain_base = NoisePerlin2DPosOffset(noise_terrain_base->np, p.X, 0.5, p.Y, 0.5, seed); float terrain_higher = NoisePerlin2DPosOffset(noise_terrain_higher->np, @@ -277,12 +269,12 @@ float MapgenV6::baseTerrainLevelFromMap(v2s16 p) { float MapgenV6::baseTerrainLevelFromMap(int index) { if (flags & MG_FLAT) return water_level; - + float terrain_base = noise_terrain_base->result[index]; float terrain_higher = noise_terrain_higher->result[index]; float steepness = noise_steepness->result[index]; float height_select = noise_height_select->result[index]; - + return baseTerrainLevel(terrain_base, terrain_higher, steepness, height_select); } @@ -340,7 +332,7 @@ float MapgenV6::getTreeAmount(v2s16 p) /*double noise = noise2d_perlin( 0.5+(float)p.X/125, 0.5+(float)p.Y/125, seed+2, 4, 0.66);*/ - + float noise = NoisePerlin2D(np_trees, p.X, p.Y, seed); float zeroval = -0.39; if (noise < zeroval) @@ -355,9 +347,9 @@ bool MapgenV6::getHaveAppleTree(v2s16 p) /*is_apple_tree = noise2d_perlin( 0.5+(float)p.X/100, 0.5+(float)p.Z/100, data->seed+342902, 3, 0.45) > 0.2;*/ - + float noise = NoisePerlin2D(np_apple_trees, p.X, p.Y, seed); - + return noise > 0.2; } @@ -366,11 +358,11 @@ float MapgenV6::getMudAmount(int index) { if (flags & MG_FLAT) return AVERAGE_MUD_AMOUNT; - + /*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin( 0.5+(float)p.X/200, 0.5+(float)p.Y/200, seed+91013, 3, 0.55));*/ - + return noise_mud->result[index]; } @@ -381,7 +373,7 @@ bool MapgenV6::getHaveBeach(int index) /*double sandnoise = noise2d_perlin( 0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250, seed+59420, 3, 0.50);*/ - + float sandnoise = noise_beach->result[index]; return (sandnoise > freq_beach); } @@ -393,16 +385,16 @@ BiomeV6Type MapgenV6::getBiome(int index, v2s16 p) /*double d = noise2d_perlin( 0.6+(float)p2d.X/250, 0.2+(float)p2d.Y/250, seed+9130, 3, 0.50);*/ - + float d = noise_biome->result[index]; if (d > freq_desert) return BT_DESERT; - + if ((spflags & MGV6_BIOMEBLEND) && (d > freq_desert - 0.10) && ((noise2d(p.X, p.Y, seed) + 1.0) > (freq_desert - d) * 20.0)) return BT_DESERT; - + return BT_NORMAL; } @@ -425,11 +417,11 @@ void MapgenV6::makeChunk(BlockMakeData *data) { assert(data->blockpos_requested.X <= data->blockpos_max.X && data->blockpos_requested.Y <= data->blockpos_max.Y && data->blockpos_requested.Z <= data->blockpos_max.Z); - + this->generating = true; - this->vm = data->vmanip; + this->vm = data->vmanip; this->ndef = data->nodedef; - + // Hack: use minimum block coords for old code that assumes a single block v3s16 blockpos = data->blockpos_requested; v3s16 blockpos_min = data->blockpos_min; @@ -491,7 +483,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) { flowMud(mudflow_minpos, mudflow_maxpos); } - + // Add dungeons if (flags & MG_DUNGEONS) { DungeonParams dp; @@ -525,7 +517,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) { DungeonGen dgen(this, &dp); dgen.generate(blockseed, full_node_min, full_node_max); } - + // Add top and bottom side of water to transforming_liquid queue updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); @@ -535,7 +527,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) { // Generate some trees, and add grass, if a jungle if (flags & MG_TREES) placeTreesAndJungleGrass(); - + // Generate the registered decorations emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); @@ -546,7 +538,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) { if (flags & MG_LIGHT) calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); - + this->generating = false; } @@ -598,25 +590,25 @@ int MapgenV6::generateGround() { MapNode n_stone(c_stone), n_desert_stone(c_desert_stone); int stone_surface_max_y = -MAP_GENERATION_LIMIT; u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { // Surface height s16 surface_y = (s16)baseTerrainLevelFromMap(index); - + // Log it if (surface_y > stone_surface_max_y) stone_surface_max_y = surface_y; BiomeV6Type bt = getBiome(index, v2s16(x, z)); - + // Fill ground with stone v3s16 em = vm->m_area.getExtent(); u32 i = vm->m_area.index(x, node_min.Y, z); for (s16 y = node_min.Y; y <= node_max.Y; y++) { if (vm->m_data[i].getContent() == CONTENT_IGNORE) { if (y <= surface_y) { - vm->m_data[i] = (y > water_level && bt == BT_DESERT) ? + vm->m_data[i] = (y > water_level && bt == BT_DESERT) ? n_desert_stone : n_stone; } else if (y <= water_level) { vm->m_data[i] = n_water_source; @@ -627,7 +619,7 @@ int MapgenV6::generateGround() { vm->m_area.add_y(em, i, 1); } } - + return stone_surface_max_y; } @@ -647,11 +639,11 @@ void MapgenV6::addMud() { // Find ground level s16 surface_y = find_stone_level(v2s16(x, z)); /////////////////optimize this! - + // Handle area not found if (surface_y == vm->m_area.MinEdge.Y - 1) continue; - + BiomeV6Type bt = getBiome(index, v2s16(x, z)); addnode = (bt == BT_DESERT) ? n_desert_sand : n_dirt; @@ -830,7 +822,7 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) { void MapgenV6::addDirtGravelBlobs() { if (getBiome(v2s16(node_min.X, node_min.Z)) != BT_NORMAL) return; - + PseudoRandom pr(blockseed + 983); for (int i = 0; i < volume_nodes/10/10/10; i++) { bool only_fill_cave = (myrand_range(0,1) != 0); @@ -844,7 +836,7 @@ void MapgenV6::addDirtGravelBlobs() { pr.range(node_min.Y, node_max.Y) - size.Y / 2, pr.range(node_min.Z, node_max.Z) - size.Z / 2 ); - + MapNode n1((p0.Y > -32 && !pr.range(0, 1)) ? c_dirt : c_gravel); for (int z1 = 0; z1 < size.Z; z1++) for (int y1 = 0; y1 < size.Y; y1++) @@ -869,7 +861,7 @@ void MapgenV6::placeTreesAndJungleGrass() { //TimeTaker t("placeTrees"); if (node_max.Y < water_level) return; - + PseudoRandom grassrandom(blockseed + 53); content_t c_junglegrass = ndef->getId("mapgen_junglegrass"); // if we don't have junglegrass, don't place cignore... that's bad @@ -877,12 +869,12 @@ void MapgenV6::placeTreesAndJungleGrass() { c_junglegrass = CONTENT_AIR; MapNode n_junglegrass(c_junglegrass); v3s16 em = vm->m_area.getExtent(); - + // Divide area into parts s16 div = 8; s16 sidelen = central_area_size.X / div; double area = sidelen * sidelen; - + // N.B. We must add jungle grass first, since tree leaves will // obstruct the ground, giving us a false ground level for (s16 z0 = 0; z0 < div; z0++) @@ -902,10 +894,10 @@ void MapgenV6::placeTreesAndJungleGrass() { node_min.X + sidelen + sidelen * x0 - 1, node_min.Z + sidelen + sidelen * z0 - 1 ); - + // Amount of trees, jungle area u32 tree_count = area * getTreeAmount(p2d_center); - + float humidity; bool is_jungle = false; if (spflags & MGV6_JUNGLES) { @@ -917,16 +909,16 @@ void MapgenV6::placeTreesAndJungleGrass() { } // Add jungle grass - if (is_jungle) { + if (is_jungle) { u32 grass_count = 5 * humidity * tree_count; for (u32 i = 0; i < grass_count; i++) { s16 x = grassrandom.range(p2d_min.X, p2d_max.X); s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y); - + s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////optimize this! if (y < water_level || y < node_min.Y || y > node_max.Y) continue; - + u32 vi = vm->m_area.index(x, y, z); // place on dirt_with_grass, since we know it is exposed to sunlight if (vm->m_data[vi].getContent() == c_dirt_with_grass) { @@ -935,7 +927,7 @@ void MapgenV6::placeTreesAndJungleGrass() { } } } - + // Put trees in random places on part of division for (u32 i = 0; i < tree_count; i++) { s16 x = myrand_range(p2d_min.X, p2d_max.X); @@ -945,7 +937,7 @@ void MapgenV6::placeTreesAndJungleGrass() { // Don't make a tree so high that it doesn't fit if(y < water_level || y > node_max.Y - 6) continue; - + v3s16 p(x,y,z); // Trees grow only on mud and grass { @@ -956,7 +948,7 @@ void MapgenV6::placeTreesAndJungleGrass() { continue; } p.Y++; - + // Make a tree if (is_jungle) { treegen::make_jungletree(*vm, p, ndef, myrand()); @@ -1009,15 +1001,15 @@ void MapgenV6::generateCaves(int max_stone_y) { u32 bruises_count = 1; PseudoRandom ps(blockseed + 21343); PseudoRandom ps2(blockseed + 1032); - + if (ps.range(1, 6) == 1) bruises_count = ps.range(0, ps.range(0, 2)); - + if (getBiome(v2s16(node_min.X, node_min.Z)) == BT_DESERT) { caves_count /= 3; bruises_count /= 3; } - + for (u32 i = 0; i < caves_count + bruises_count; i++) { bool large_cave = (i >= caves_count); CaveV6 cave(this, &ps, &ps2, large_cave); diff --git a/src/mapgen_v6.h b/src/mapgen_v6.h index eecfb1fe6d91..e6d2cdc544bf 100644 --- a/src/mapgen_v6.h +++ b/src/mapgen_v6.h @@ -55,10 +55,10 @@ struct MapgenV6Params : public MapgenSpecificParams { NoiseParams np_humidity; NoiseParams np_trees; NoiseParams np_apple_trees; - + MapgenV6Params(); ~MapgenV6Params() {} - + void readParams(Settings *settings); void writeParams(Settings *settings); }; @@ -68,7 +68,6 @@ class MapgenV6 : public Mapgen { EmergeManager *emerge; int ystride; - u32 flags; u32 spflags; u32 blockseed; @@ -111,7 +110,7 @@ class MapgenV6 : public Mapgen { MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge); ~MapgenV6(); - + void makeChunk(BlockMakeData *data); int getGroundLevelAtPoint(v2s16 p); @@ -124,7 +123,7 @@ class MapgenV6 : public Mapgen { s16 find_stone_level(v2s16 p2d); bool block_is_underground(u64 seed, v3s16 blockpos); s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision); - + float getHumidity(v2s16 p); float getTreeAmount(v2s16 p); bool getHaveAppleTree(v2s16 p); @@ -134,9 +133,9 @@ class MapgenV6 : public Mapgen { bool getHaveBeach(int index); BiomeV6Type getBiome(v2s16 p); BiomeV6Type getBiome(int index, v2s16 p); - + u32 get_blockseed(u64 seed, v3s16 p); - + virtual void calculateNoise(); int generateGround(); void addMud(); @@ -152,7 +151,7 @@ struct MapgenFactoryV6 : public MapgenFactory { Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) { return new MapgenV6(mgid, params, emerge); }; - + MapgenSpecificParams *createMapgenParams() { return new MapgenV6Params(); }; diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index bad01bc2a649..82bc4aae825c 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -49,19 +49,12 @@ FlagDesc flagdesc_mapgen_v7[] = { /////////////////////////////////////////////////////////////////////////////// -MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) { - this->generating = false; - this->id = mapgenid; +MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) + : Mapgen(mapgenid, params, emerge) +{ this->emerge = emerge; this->bmgr = emerge->biomemgr; - this->seed = (int)params->seed; - this->water_level = params->water_level; - this->flags = params->flags; - this->gennotify = emerge->gennotify; - - this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; - //// amount of elements to skip for the next index //// for noise/height/biome maps (not vmanip) this->ystride = csize.X; @@ -119,7 +112,7 @@ MapgenV7::~MapgenV7() { delete noise_heat; delete noise_humidity; - + delete[] ridge_heightmap; delete[] heightmap; delete[] biomemap; @@ -177,7 +170,7 @@ void MapgenV7Params::writeParams(Settings *settings) { int MapgenV7::getGroundLevelAtPoint(v2s16 p) { // Base terrain calculation s16 y = baseTerrainLevelAtPoint(p.X, p.Y); - + // Ridge/river terrain calculation float width = 0.3; float uwatern = NoisePerlin2DNoTxfm(noise_ridge_uwater->np, p.X, p.Y, seed) * 2; @@ -185,14 +178,14 @@ int MapgenV7::getGroundLevelAtPoint(v2s16 p) { // if inside a river, simply guess if (uwatern >= -width && uwatern <= width) return water_level - 10; - + // Mountain terrain calculation int iters = 128; // don't even bother iterating more than 128 times.. while (iters--) { //current point would have been air if (!getMountainTerrainAtPoint(p.X, y, p.Y)) return y; - + y++; } @@ -209,12 +202,12 @@ void MapgenV7::makeChunk(BlockMakeData *data) { assert(data->blockpos_requested.X <= data->blockpos_max.X && data->blockpos_requested.Y <= data->blockpos_max.Y && data->blockpos_requested.Z <= data->blockpos_max.Z); - + this->generating = true; - this->vm = data->vmanip; + this->vm = data->vmanip; this->ndef = data->nodedef; //TimeTaker t("makeChunk"); - + v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; node_min = blockpos_min * MAP_BLOCKSIZE; @@ -223,19 +216,19 @@ void MapgenV7::makeChunk(BlockMakeData *data) { full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); blockseed = emerge->getBlockSeed(full_node_min); //////use getBlockSeed2()! - + // Make some noise calculateNoise(); - + // Generate base terrain, mountains, and ridges with initial heightmaps s16 stone_surface_max_y = generateTerrain(); - + updateHeightmap(node_min, node_max); - + // Calculate biomes bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); - + // Actually place the biome-specific nodes and what not generateBiomes(); @@ -255,17 +248,17 @@ void MapgenV7::makeChunk(BlockMakeData *data) { // Sprinkle some dust on top after everything else was generated dustTopNodes(); - + //printf("makeChunk: %dms\n", t.stop()); - + updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); - + if (flags & MG_LIGHT) calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); - + this->generating = false; } @@ -275,24 +268,24 @@ void MapgenV7::calculateNoise() { int x = node_min.X; int y = node_min.Y; int z = node_min.Z; - + noise_height_select->perlinMap2D(x, z); noise_height_select->transformNoiseMap(); - + noise_terrain_persist->perlinMap2D(x, z); noise_terrain_persist->transformNoiseMap(); float *persistmap = noise_terrain_persist->result; for (int i = 0; i != csize.X * csize.Z; i++) persistmap[i] = rangelim(persistmap[i], 0.4, 0.9); - + noise_terrain_base->perlinMap2DModulated(x, z, persistmap); noise_terrain_base->transformNoiseMap(); - + noise_terrain_alt->perlinMap2DModulated(x, z, persistmap); noise_terrain_alt->transformNoiseMap(); - + noise_filler_depth->perlinMap2D(x, z); - + if (spflags & MGV7_MOUNTAINS) { noise_mountain->perlinMap3D(x, y, z); noise_mount_height->perlinMap2D(x, z); @@ -303,10 +296,10 @@ void MapgenV7::calculateNoise() { noise_ridge->perlinMap3D(x, y, z); noise_ridge_uwater->perlinMap2D(x, z); } - + noise_heat->perlinMap2D(x, z); noise_humidity->perlinMap2D(x, z); - + //printf("calculateNoise: %dus\n", t.stop()); } @@ -315,7 +308,7 @@ Biome *MapgenV7::getBiomeAtPoint(v3s16 p) { float heat = NoisePerlin2D(bmgr->np_heat, p.X, p.Z, seed); float humidity = NoisePerlin2D(bmgr->np_humidity, p.X, p.Z, seed); s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Z); - + return bmgr->getBiome(heat, humidity, groundlevel); } @@ -323,7 +316,7 @@ Biome *MapgenV7::getBiomeAtPoint(v3s16 p) { float MapgenV7::baseTerrainLevelAtPoint(int x, int z) { float hselect = NoisePerlin2D(noise_height_select->np, x, z, seed); hselect = rangelim(hselect, 0.0, 1.0); - + float persist = NoisePerlin2D(noise_terrain_persist->np, x, z, seed); persist = rangelim(persist, 0.4, 0.9); @@ -335,7 +328,7 @@ float MapgenV7::baseTerrainLevelAtPoint(int x, int z) { if (height_alt > height_base) return height_alt; - + return (height_base * hselect) + (height_alt * (1.0 - hselect)); } @@ -344,7 +337,7 @@ float MapgenV7::baseTerrainLevelFromMap(int index) { float hselect = rangelim(noise_height_select->result[index], 0.0, 1.0); float height_base = noise_terrain_base->result[index]; float height_alt = noise_terrain_alt->result[index]; - + if (height_alt > height_base) return height_alt; @@ -373,7 +366,7 @@ void MapgenV7::carveRivers() { MapNode n_air(CONTENT_AIR), n_water_source(c_water_source); MapNode n_stone(c_stone); u32 index = 0; - + int river_depth = 4; for (s16 z = node_min.Z; z <= node_max.Z; z++) @@ -385,16 +378,16 @@ void MapgenV7::carveRivers() { float height = terrain_river * (1 - abs(terrain_mod)) * noise_terrain_river->np->scale; height = log(height * height); //log(h^3) is pretty interesting for terrain - + s16 y = heightmap[index]; if (height < 1.0 && y > river_depth && y - river_depth >= node_min.Y && y <= node_max.Y) { - + for (s16 ry = y; ry != y - river_depth; ry--) { u32 vi = vm->m_area.index(x, ry, z); vm->m_data[vi] = n_air; } - + u32 vi = vm->m_area.index(x, y - river_depth, z); vm->m_data[vi] = n_water_source; } @@ -411,7 +404,7 @@ int MapgenV7::generateTerrain() { if (spflags & MGV7_RIDGES) generateRidgeTerrain(); - + return ymax; } @@ -420,23 +413,23 @@ int MapgenV7::generateBaseTerrain() { MapNode n_air(CONTENT_AIR); MapNode n_stone(c_stone); MapNode n_water(c_water_source); - + int stone_surface_max_y = -MAP_GENERATION_LIMIT; v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { float surface_height = baseTerrainLevelFromMap(index); s16 surface_y = (s16)surface_height; - - heightmap[index] = surface_y; + + heightmap[index] = surface_y; ridge_heightmap[index] = surface_y; - + if (surface_y > stone_surface_max_y) stone_surface_max_y = surface_y; - u32 i = vm->m_area.index(x, node_min.Y, z); + u32 i = vm->m_area.index(x, node_min.Y, z); for (s16 y = node_min.Y; y <= node_max.Y; y++) { if (vm->m_data[i].getContent() == CONTENT_IGNORE) { if (y <= surface_y) @@ -449,7 +442,7 @@ int MapgenV7::generateBaseTerrain() { vm->m_area.add_y(em, i, 1); } } - + return stone_surface_max_y; } @@ -457,10 +450,10 @@ int MapgenV7::generateBaseTerrain() { void MapgenV7::generateMountainTerrain() { if (node_max.Y <= water_level) return; - + MapNode n_stone(c_stone); u32 j = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 y = node_min.Y; y <= node_max.Y; y++) { u32 vi = vm->m_area.index(node_min.X, y, z); @@ -469,7 +462,7 @@ void MapgenV7::generateMountainTerrain() { if (getMountainTerrainFromMap(j, index, y)) vm->m_data[vi] = n_stone; - + vi++; j++; } @@ -481,36 +474,36 @@ void MapgenV7::generateRidgeTerrain() { MapNode n_water(c_water_source); MapNode n_air(CONTENT_AIR); u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 y = node_min.Y; y <= node_max.Y; y++) { u32 vi = vm->m_area.index(node_min.X, y, z); for (s16 x = node_min.X; x <= node_max.X; x++, index++, vi++) { int j = (z - node_min.Z) * csize.X + (x - node_min.X); - + if (heightmap[j] < water_level - 4) continue; - + float widthn = (noise_terrain_persist->result[j] - 0.6) / 0.1; //widthn = rangelim(widthn, -0.05, 0.5); - + float width = 0.3; // TODO: figure out acceptable perlin noise values float uwatern = noise_ridge_uwater->result[j] * 2; if (uwatern < -width || uwatern > width) continue; - + float height_mod = (float)(y + 17) / 2.5; float width_mod = (width - fabs(uwatern)); float nridge = noise_ridge->result[index] * (float)y / 7.0; if (y < water_level) nridge = -fabs(nridge) * 3.0 * widthn * 0.3; - + if (nridge + width_mod * height_mod < 0.6) continue; - + if (y < ridge_heightmap[j]) - ridge_heightmap[j] = y - 1; + ridge_heightmap[j] = y - 1; vm->m_data[vi] = (y > water_level) ? n_air : n_water; } @@ -528,7 +521,7 @@ void MapgenV7::generateBiomes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = (Biome *)bmgr->get(biomemap[index]); @@ -537,14 +530,14 @@ void MapgenV7::generateBiomes() { s16 y0_filler = biome->depth_top + dfiller; s16 nplaced = 0; - u32 i = vm->m_area.index(x, node_max.Y, z); + u32 i = vm->m_area.index(x, node_max.Y, z); content_t c_above = vm->m_data[i + em.X].getContent(); bool have_air = c_above == CONTENT_AIR; - + for (s16 y = node_max.Y; y >= node_min.Y; y--) { content_t c = vm->m_data[i].getContent(); - + // It could be the case that the elevation is equal to the chunk // boundary, but the chunk above has not been generated yet if (y == node_max.Y && c_above == CONTENT_IGNORE && @@ -554,10 +547,10 @@ void MapgenV7::generateBiomes() { (x - node_min.X); have_air = !getMountainTerrainFromMap(j, index, y); } - + if (c == c_stone && have_air) { content_t c_below = vm->m_data[i - em.X].getContent(); - + if (c_below != CONTENT_AIR) { if (nplaced < y0_top) { if(y < water_level) @@ -593,7 +586,7 @@ void MapgenV7::generateBiomes() { have_air = true; nplaced = 0; } - + vm->m_area.add_y(em, i, -1); } } @@ -603,14 +596,14 @@ void MapgenV7::generateBiomes() { void MapgenV7::dustTopNodes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; - + if (water_level > node_max.Y) return; for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = (Biome *)bmgr->get(biomemap[index]); - + if (biome->c_dust == CONTENT_IGNORE) continue; @@ -622,17 +615,17 @@ void MapgenV7::dustTopNodes() { vm->m_area.add_y(em, vi, -1); } - + content_t c = vm->m_data[vi].getContent(); if (c == biome->c_water && biome->c_dust_water != CONTENT_IGNORE) { if (y < node_min.Y) continue; - + vm->m_data[vi] = MapNode(biome->c_dust_water); } else if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE) { if (y == node_max.Y) continue; - + vm->m_area.add_y(em, vi, 1); vm->m_data[vi] = MapNode(biome->c_dust); } @@ -649,10 +642,10 @@ void MapgenV7::addTopNodes() { for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = bmgr->biomes[biomemap[index]]; - + //////////////////// First, add top nodes below the ridge s16 y = ridge_heightmap[index]; - + // This cutoff is good enough, but not perfect. // It will cut off potentially placed top nodes at chunk boundaries if (y < node_min.Y) @@ -664,7 +657,7 @@ void MapgenV7::addTopNodes() { if (ndef->get(c).walkable) continue; } - + // N.B. It is necessary to search downward since ridge_heightmap[i] // might not be the actual height, just the lowest part in the chunk // where a ridge had been carved @@ -692,7 +685,7 @@ void MapgenV7::addTopNodes() { vm->m_data[i] = MapNode(c_dirt_with_grass); } } - + //////////////////// Now, add top nodes on top of the ridge y = heightmap[index]; if (y > node_max.Y) { diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index bc497309bfa0..1af88ddf5b0a 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -42,10 +42,10 @@ struct MapgenV7Params : public MapgenSpecificParams { NoiseParams np_ridge_uwater; NoiseParams np_mountain; NoiseParams np_ridge; - + MapgenV7Params(); ~MapgenV7Params() {} - + void readParams(Settings *settings); void writeParams(Settings *settings); }; @@ -57,7 +57,6 @@ class MapgenV7 : public Mapgen { int ystride; int zstride; - u32 flags; u32 spflags; u32 blockseed; @@ -65,9 +64,9 @@ class MapgenV7 : public Mapgen { v3s16 node_max; v3s16 full_node_min; v3s16 full_node_max; - + s16 *ridge_heightmap; - + Noise *noise_terrain_base; Noise *noise_terrain_alt; Noise *noise_terrain_persist; @@ -77,10 +76,10 @@ class MapgenV7 : public Mapgen { Noise *noise_ridge_uwater; Noise *noise_mountain; Noise *noise_ridge; - + Noise *noise_heat; Noise *noise_humidity; - + content_t c_stone; content_t c_dirt; content_t c_dirt_with_grass; @@ -95,7 +94,7 @@ class MapgenV7 : public Mapgen { MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge); ~MapgenV7(); - + virtual void makeChunk(BlockMakeData *data); int getGroundLevelAtPoint(v2s16 p); Biome *getBiomeAtPoint(v3s16 p); @@ -104,19 +103,19 @@ class MapgenV7 : public Mapgen { float baseTerrainLevelFromMap(int index); bool getMountainTerrainAtPoint(int x, int y, int z); bool getMountainTerrainFromMap(int idx_xyz, int idx_xz, int y); - + void calculateNoise(); - + virtual int generateTerrain(); int generateBaseTerrain(); void generateMountainTerrain(); void generateRidgeTerrain(); - + void generateBiomes(); void dustTopNodes(); - + //void addTopNodes(); - + void generateCaves(int max_stone_y); }; @@ -124,7 +123,7 @@ struct MapgenFactoryV7 : public MapgenFactory { Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) { return new MapgenV7(mgid, params, emerge); }; - + MapgenSpecificParams *createMapgenParams() { return new MapgenV7Params(); }; diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index 3604b06c0cec..a8fd9eaadf0b 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -144,7 +144,9 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) } } - generate(mg, &ps, max_y, v3s16(x, y, z)); + v3s16 pos(x, y, z); + if (generate(mg, &ps, max_y, pos)) + mg->gennotify.addEvent(GENNOTIFY_DECORATION, pos, id); } } @@ -254,12 +256,12 @@ bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p) } -void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) +size_t DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) { ManualMapVoxelManipulator *vm = mg->vm; if (!canPlaceDecoration(vm, p)) - return; + return 0; content_t c_place = c_decos[pr->range(0, c_decos.size() - 1)]; @@ -279,6 +281,8 @@ void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) vm->m_data[vi] = MapNode(c_place); } + + return 1; } @@ -291,7 +295,7 @@ int DecoSimple::getHeight() /////////////////////////////////////////////////////////////////////////////// -void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) +size_t DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) { ManualMapVoxelManipulator *vm = mg->vm; @@ -305,12 +309,14 @@ void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) u32 vi = vm->m_area.index(p); content_t c = vm->m_data[vi].getContent(); if (!CONTAINS(c_place_on, c)) - return; + return 0; Rotation rot = (rotation == ROTATE_RAND) ? (Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation; schematic->blitToVManip(p, vm, rot, false, mg->ndef); + + return 1; } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index d5c9f0165611..c698710b5343 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -77,7 +77,7 @@ class Decoration : public GenElement { size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); - virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) = 0; + virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) = 0; virtual int getHeight() = 0; }; @@ -92,7 +92,7 @@ class DecoSimple : public Decoration { ~DecoSimple() {} bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p); - virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p); + virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p); virtual int getHeight(); }; @@ -105,7 +105,7 @@ class DecoSchematic : public Decoration { ~DecoSchematic() {} - void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p); + virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p); virtual int getHeight(); }; diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index edbb224c1470..80e86130a1fa 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -95,7 +95,7 @@ size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) nmax.Y = ymax; generate(mg->vm, mg->seed, blockseed, nmin, nmax); - return 0; + return 1; } diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index bb76bb450b8e..a8f55cd25365 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -194,23 +194,21 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L) 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::map >event_map; + std::map >::iterator it; - std::vector *posvec = mg->gen_notifications[i]; - if (!posvec) - return 0; + mg->gennotify.getEvents(event_map); + lua_newtable(L); + for (it = event_map.begin(); it != event_map.end(); ++it) { lua_newtable(L); - for (unsigned int j = 0; j != posvec->size(); j++) { - push_v3s16(L, (*posvec)[j]); + + for (size_t j = 0; j != it->second.size(); j++) { + push_v3s16(L, it->second[j]); lua_rawseti(L, -2, j + 1); } - lua_setfield(L, -2, flagdesc_gennotify[i].name); - posvec->clear(); + lua_setfield(L, -2, it->first.c_str()); } return 1; @@ -291,14 +289,24 @@ int ModApiMapgen::l_set_noiseparam_defaults(lua_State *L) return 0; } -// set_gen_notify(string) +// set_gen_notify(flags, {deco_id_table}) int ModApiMapgen::l_set_gen_notify(lua_State *L) { u32 flags = 0, flagmask = 0; + EmergeManager *emerge = getServer(L)->getEmergeManager(); if (read_flags(L, 1, flagdesc_gennotify, &flags, &flagmask)) { - EmergeManager *emerge = getServer(L)->getEmergeManager(); - emerge->gennotify = flags; + emerge->gen_notify_on &= ~flagmask; + emerge->gen_notify_on |= flags; + } + + if (lua_istable(L, 2)) { + lua_pushnil(L); + while (lua_next(L, 2)) { + if (lua_isnumber(L, -1)) + emerge->gen_notify_on_deco_ids.insert(lua_tonumber(L, -1)); + lua_pop(L, 1); + } } return 0; @@ -372,7 +380,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L) << decotype << " not implemented"; return 0; } - + deco->name = getstringfield_default(L, index, "name", ""); deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02); deco->sidelen = getintfield_default(L, index, "sidelen", 8);