diff options
author | kwolekr <kwolekr@minetest.net> | 2014-12-06 04:18:04 -0500 |
---|---|---|
committer | kwolekr <kwolekr@minetest.net> | 2014-12-06 13:53:35 -0500 |
commit | 5062b99cb0d252d9e377ff4560f7ecc9e66fd558 (patch) | |
tree | 3474c0734aac243cabfcf3af763becb4025da35b /src | |
parent | 2b119e1e192ead701e69e261fe94ccb7382dbee7 (diff) | |
download | minetest-5062b99cb0d252d9e377ff4560f7ecc9e66fd558.tar.gz minetest-5062b99cb0d252d9e377ff4560f7ecc9e66fd558.tar.bz2 minetest-5062b99cb0d252d9e377ff4560f7ecc9e66fd558.zip |
Rewrite generate notification mechanism
Add support for notify-on-decoration
Clean up mapgen constructors
Clean up mapgen.cpp code style somewhat
Remove trailing whitespace from some files
Diffstat (limited to 'src')
-rw-r--r-- | src/cavegen.cpp | 106 | ||||
-rw-r--r-- | src/dungeongen.cpp | 27 | ||||
-rw-r--r-- | src/dungeongen.h | 10 | ||||
-rw-r--r-- | src/emerge.cpp | 2 | ||||
-rw-r--r-- | src/emerge.h | 3 | ||||
-rw-r--r-- | src/mapgen.cpp | 127 | ||||
-rw-r--r-- | src/mapgen.h | 40 | ||||
-rw-r--r-- | src/mapgen_singlenode.cpp | 13 | ||||
-rw-r--r-- | src/mapgen_v5.cpp | 56 | ||||
-rw-r--r-- | src/mapgen_v5.h | 9 | ||||
-rw-r--r-- | src/mapgen_v6.cpp | 106 | ||||
-rw-r--r-- | src/mapgen_v6.h | 15 | ||||
-rw-r--r-- | src/mapgen_v7.cpp | 147 | ||||
-rw-r--r-- | src/mapgen_v7.h | 27 | ||||
-rw-r--r-- | src/mg_decoration.cpp | 16 | ||||
-rw-r--r-- | src/mg_decoration.h | 6 | ||||
-rw-r--r-- | src/mg_ore.cpp | 2 | ||||
-rw-r--r-- | src/script/lua_api/l_mapgen.cpp | 38 |
18 files changed, 427 insertions, 323 deletions
diff --git a/src/cavegen.cpp b/src/cavegen.cpp index d93911f27..02eef72d8 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 <v3s16> *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 <v3s16> *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 <v3s16> *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 <v3s16> *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 2027b7f13..2a89c714e 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 <v3s16> *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 4a0bfcefd..ff1d0bc33 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 @@ public: 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 @@ public: 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 6410e56e9..8813a71a9 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 65b1d6594..7de1c8391 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -89,7 +89,8 @@ public: u16 qlimit_diskonly; u16 qlimit_generate; - u32 gennotify; + u32 gen_notify_on; + std::set<u32> gen_notify_on_deco_ids; //// Block emerge queue data structures JMutex queuemutex; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 60fa842a6..44ce0c615 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<v3s16>; +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<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) { +void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) +{ bool isliquid, wasliquid; v3s16 em = vm->m_area.getExtent(); @@ -165,7 +186,8 @@ void Mapgen::updateLiquid(UniqueQueue<v3s16> *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); @@ -289,6 +314,72 @@ void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) { /////////////////////////////////////////////////////////////////////////////// +GenerateNotifier::GenerateNotifier() +{ +} + + +GenerateNotifier::GenerateNotifier(u32 notify_on, + std::set<u32> *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<u32> *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<std::string, std::vector<v3s16> > &event_map, + bool peek_events) +{ + std::list<GenNotifyEvent>::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(); +} + + +/////////////////////////////////////////////////////////////////////////////// + GenElementManager::~GenElementManager() { diff --git a/src/mapgen.h b/src/mapgen.h index cf2120a7a..9cdb157e1 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<u32> *notify_on_deco_ids); + + void setNotifyOn(u32 notify_on); + void setNotifyOnDecoIds(std::set<u32> *notify_on_deco_ids); + + bool addEvent(GenNotifyType type, v3s16 pos, u32 id=0); + void getEvents(std::map<std::string, std::vector<v3s16> > &event_map, + bool peek_events=false); + +private: + u32 m_notify_on; + std::set<u32> *m_notify_on_deco_ids; + std::list<GenNotifyEvent> 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 @@ public: u8 *biomemap; v3s16 csize; - u32 gennotify; - std::vector<v3s16> *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 9f2e6c122..8558b3b14 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 3867827cc..95cfeeef5 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 84e63672b..22a836d64 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 @@ public: int ystride; int zstride; - u32 flags; u32 spflags; u32 blockseed; @@ -62,7 +61,7 @@ public: 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 @@ public: 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 de0c81688..f1ba2a486 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 eecfb1fe6..e6d2cdc54 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 @@ public: EmergeManager *emerge; int ystride; - u32 flags; u32 spflags; u32 blockseed; @@ -111,7 +110,7 @@ public: MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge); ~MapgenV6(); - + void makeChunk(BlockMakeData *data); int getGroundLevelAtPoint(v2s16 p); @@ -124,7 +123,7 @@ public: 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 @@ public: 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 bad01bc2a..82bc4aae8 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 bc497309b..1af88ddf5 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 @@ public: int ystride; int zstride; - u32 flags; u32 spflags; u32 blockseed; @@ -65,9 +64,9 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 3604b06c0..a8fd9eaad 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 d5c9f0165..c698710b5 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -77,7 +77,7 @@ public: 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 @@ public: ~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 @@ public: ~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 edbb224c1..80e86130a 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 bb76bb450..a8f55cd25 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<std::string, std::vector<v3s16> >event_map; + std::map<std::string, std::vector<v3s16> >::iterator it; - std::vector<v3s16> *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); |