diff options
Diffstat (limited to 'src/mapgen.cpp')
-rw-r--r-- | src/mapgen.cpp | 132 |
1 files changed, 84 insertions, 48 deletions
diff --git a/src/mapgen.cpp b/src/mapgen.cpp index f8e9477c5..b3c9380a0 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_sao.h" #include "nodedef.h" #include "emerge.h" -#include "content_mapnode.h" // For content_mapnode_get_new_name #include "voxelalgorithms.h" #include "porting.h" #include "profiler.h" @@ -42,11 +41,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" FlagDesc flagdesc_mapgen[] = { - {"trees", MG_TREES}, - {"caves", MG_CAVES}, - {"dungeons", MG_DUNGEONS}, - {"flat", MG_FLAT}, - {"light", MG_LIGHT}, + {"trees", MG_TREES}, + {"caves", MG_CAVES}, + {"dungeons", MG_DUNGEONS}, + {"flat", MG_FLAT}, + {"light", MG_LIGHT}, + {"decorations", MG_DECORATIONS}, {NULL, 0} }; @@ -62,8 +62,9 @@ FlagDesc flagdesc_gennotify[] = { }; -/////////////////////////////////////////////////////////////////////////////// - +//// +//// Mapgen +//// Mapgen::Mapgen() { @@ -161,6 +162,26 @@ s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) } +// Returns -MAX_MAP_GENERATION_LIMIT if not found or if ground is found first +s16 Mapgen::findLiquidSurface(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; + + for (y = ymax; y >= ymin; y--) { + MapNode &n = vm->m_data[i]; + if (ndef->get(n).walkable) + return -MAX_MAP_GENERATION_LIMIT; + else if (ndef->get(n).isLiquid()) + break; + + vm->m_area.add_y(em, i, -1); + } + return (y >= ymin) ? y : -MAX_MAP_GENERATION_LIMIT; +} + + void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) { if (!heightmap) @@ -225,14 +246,31 @@ void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) return; u32 vi = vm->m_area.index(p); - MapNode &nn = vm->m_data[vi]; - - light--; - // should probably compare masked, but doesn't seem to make a difference - if (light <= nn.param1 || !ndef->get(nn).light_propagates) + MapNode &n = vm->m_data[vi]; + + // Decay light in each of the banks separately + u8 light_day = light & 0x0F; + if (light_day > 0) + light_day -= 0x01; + + u8 light_night = light & 0xF0; + if (light_night > 0) + light_night -= 0x10; + + // Bail out only if we have no more light from either bank to propogate, or + // we hit a solid block that light cannot pass through. + if ((light_day <= (n.param1 & 0x0F) && + light_night <= (n.param1 & 0xF0)) || + !ndef->get(n).light_propagates) return; - nn.param1 = light; + // Since this recursive function only terminates when there is no light from + // either bank left, we need to take the max of both banks into account for + // the case where spreading has stopped for one light bank but not the other. + light = MYMAX(light_day, n.param1 & 0x0F) | + MYMAX(light_night, n.param1 & 0xF0); + + n.param1 = light; lightSpread(a, p + v3s16(0, 0, 1), light); lightSpread(a, p + v3s16(0, 1, 0), light); @@ -243,43 +281,29 @@ void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) } -void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax) +void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax, + bool propagate_shadow) { ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); //TimeTaker t("updateLighting"); - propagateSunlight(nmin, nmax); + propagateSunlight(nmin, nmax, propagate_shadow); spreadLight(full_nmin, full_nmax); //printf("updateLighting: %dms\n", t.stop()); } - -void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) -{ - ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); - //TimeTaker t("updateLighting"); - - propagateSunlight( - nmin - v3s16(1, 1, 1) * MAP_BLOCKSIZE, - nmax + v3s16(1, 0, 1) * MAP_BLOCKSIZE); - - spreadLight( - nmin - v3s16(1, 1, 1) * MAP_BLOCKSIZE, - nmax + v3s16(1, 1, 1) * MAP_BLOCKSIZE); - - //printf("updateLighting: %dms\n", t.stop()); -} - - -void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax) +void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow) { //TimeTaker t("propagateSunlight"); VoxelArea a(nmin, nmax); bool block_is_underground = (water_level >= nmax.Y); v3s16 em = vm->m_area.getExtent(); + // NOTE: Direct access to the low 4 bits of param1 is okay here because, + // by definition, sunlight will never be in the night lightbank. + for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++) { // see if we can get a light value from the overtop @@ -287,7 +311,8 @@ void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax) if (vm->m_data[i].getContent() == CONTENT_IGNORE) { if (block_is_underground) continue; - } else if ((vm->m_data[i].param1 & 0x0F) != LIGHT_SUN) { + } else if ((vm->m_data[i].param1 & 0x0F) != LIGHT_SUN && + propagate_shadow) { continue; } vm->m_area.add_y(em, i, -1); @@ -305,7 +330,6 @@ void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax) } - void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax) { //TimeTaker t("spreadLight"); @@ -316,15 +340,21 @@ void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax) u32 i = vm->m_area.index(a.MinEdge.X, y, z); for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++) { MapNode &n = vm->m_data[i]; - if (n.getContent() == CONTENT_IGNORE || - !ndef->get(n).light_propagates) + if (n.getContent() == CONTENT_IGNORE) continue; - u8 light_produced = ndef->get(n).light_source & 0x0F; + const ContentFeatures &cf = ndef->get(n); + if (!cf.light_propagates) + continue; + + // TODO(hmmmmm): Abstract away direct param1 accesses with a + // wrapper, but something lighter than MapNode::get/setLight + + u8 light_produced = cf.light_source; if (light_produced) - n.param1 = light_produced; + n.param1 = light_produced | (light_produced << 4); - u8 light = n.param1 & 0x0F; + u8 light = n.param1; if (light) { lightSpread(a, v3s16(x, y, z + 1), light); lightSpread(a, v3s16(x, y + 1, z ), light); @@ -341,8 +371,9 @@ void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax) } - -/////////////////////////////////////////////////////////////////////////////// +//// +//// GenerateNotifier +//// GenerateNotifier::GenerateNotifier() { @@ -408,7 +439,10 @@ void GenerateNotifier::getEvents( m_notify_events.clear(); } -/////////////////////////////////////////////////////////////////////////////// + +//// +//// MapgenParams +//// void MapgenParams::load(const Settings &settings) { @@ -430,9 +464,11 @@ void MapgenParams::load(const Settings &settings) settings.getNoiseParams("mg_biome_np_humidity_blend", np_biome_humidity_blend); delete sparams; - sparams = EmergeManager::createMapgenParams(mg_name); - if (sparams) + MapgenFactory *mgfactory = EmergeManager::getMapgenFactory(mg_name); + if (mgfactory) { + sparams = mgfactory->createMapgenParams(); sparams->readParams(&settings); + } } @@ -442,7 +478,7 @@ void MapgenParams::save(Settings &settings) const settings.setU64("seed", seed); settings.setS16("water_level", water_level); settings.setS16("chunksize", chunksize); - settings.setFlagStr("mg_flags", flags, flagdesc_mapgen, (u32)-1); + settings.setFlagStr("mg_flags", flags, flagdesc_mapgen, U32_MAX); settings.setNoiseParams("mg_biome_np_heat", np_biome_heat); settings.setNoiseParams("mg_biome_np_heat_blend", np_biome_heat_blend); settings.setNoiseParams("mg_biome_np_humidity", np_biome_humidity); |