Weather: Clean up getHeat/getHumidity somewhat
authorkwolekr <kwolekr@minetest.net>
Tue, 17 Sep 2013 02:52:24 +0000 (22:52 -0400)
committerkwolekr <kwolekr@minetest.net>
Tue, 17 Sep 2013 03:33:53 +0000 (23:33 -0400)
13 files changed:
src/biome.cpp
src/biome.h
src/constants.h
src/content_abm.cpp
src/emerge.cpp
src/environment.cpp
src/environment.h
src/map.cpp
src/map.h
src/mapblock.cpp
src/mapblock.h
src/script/lua_api/l_env.cpp
src/server.h

index e68429effb74c44b506cce86ef9f40785ffd12cc..83d4e7a4c87ac0c41ddc88c52bd2a28aae1d0c71 100644 (file)
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nodedef.h"
 #include "map.h" //for ManualMapVoxelManipulator
 #include "log.h"
+#include "util/numeric.h"
 #include "main.h"
 
 
@@ -203,3 +204,54 @@ u8 BiomeDefManager::getBiomeIdByName(const char *name) {
        
        return 0;
 }
+
+
+///////////////////////////// Weather
+
+
+s16 BiomeDefManager::calcBlockHeat(v3s16 p, u64 seed, float timeofday, float totaltime) {
+       //variant 1: full random
+       //f32 heat = NoisePerlin3D(np_heat, p.X, env->getGameTime()/100, p.Z, seed);
+
+       //variant 2: season change based on default heat map
+       const f32 offset = 20; // = np_heat->offset
+       const f32 scale  = 20; // = np_heat->scale
+       const f32 range  = 20;
+       f32 heat = NoisePerlin2D(np_heat, p.X, p.Z, seed); // 0..50..100
+
+       heat -= np_heat->offset; // -50..0..+50
+
+       // normalizing - todo REMOVE after fixed NoiseParams nparams_biome_def_heat = {50, 50, -> 20, 50,
+       if (np_heat->scale)
+               heat /= np_heat->scale / scale; //  -20..0..+20
+
+       f32 seasonv = totaltime;
+       seasonv /= 86400 * g_settings->getS16("year_days"); // season change speed
+       seasonv += (f32)p.X / 3000; // you can walk to area with other season
+       seasonv = sin(seasonv * M_PI);
+       heat += (range * (heat < 0 ? 2 : 0.5)) * seasonv; // -60..0..30
+
+       heat += offset; // -40..0..50
+       heat += p.Y / -333; // upper=colder, lower=hotter, 3c per 1000
+
+       // daily change, hotter at sun +4, colder at night -4
+       heat += 8 * (sin(cycle_shift(timeofday, -0.25) * M_PI) - 0.5); //-44..20..54
+       
+       return heat;
+}
+
+
+s16 BiomeDefManager::calcBlockHumidity(v3s16 p, u64 seed, float timeofday, float totaltime) {
+
+       f32 humidity = NoisePerlin2D(np_humidity, p.X, p.Z, seed);
+
+       f32 seasonv = totaltime;
+       seasonv /= 86400 * 2; // bad weather change speed (2 days)
+       seasonv += (f32)p.Z / 300;
+       humidity += 30 * sin(seasonv * M_PI);
+
+       humidity += -12 * (sin(cycle_shift(timeofday, -0.1) * M_PI) - 0.5);
+       humidity = rangelim(humidity, 0, 100);
+       
+       return humidity;
+}
index cf3bd1b9f073affebf17ffbd7dd4937a3e7bb7ed..aa83c4e0b25ff9ec22b6ed375d8b8d3bd601d418 100644 (file)
@@ -91,6 +91,9 @@ public:
        void addBiome(Biome *b);
        void resolveNodeNames(INodeDefManager *ndef);
        u8 getBiomeIdByName(const char *name);
+       
+       s16 calcBlockHeat(v3s16 p, u64 seed, float timeofday, float totaltime);
+       s16 calcBlockHumidity(v3s16 p, u64 seed, float timeofday, float totaltime);
 };
 
 #endif
index 8c478ac6a2a1a3fdb7b1963a79da9726f1106d17..17f5d389af5ccd39f5b28419bf5d544c81324a6b 100644 (file)
@@ -89,5 +89,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 // Maximum hit points of a player
 #define PLAYER_MAX_HP 20
 
+/*
+       Environmental condition constants
+*/
+#define HEAT_UNDEFINED     (-0x7fff-1)
+#define HUMIDITY_UNDEFINED (-0x7fff-1)
+
 #endif
 
index 6e2d438fdbc32971fbf3b401d3cc855143b82c69..fa6a128eb68db0eb68203283fede129a79c48871 100644 (file)
@@ -253,7 +253,7 @@ class LiquidFreeze : public ActiveBlockModifier {
                        ServerMap *map = &env->getServerMap();
                        INodeDefManager *ndef = env->getGameDef()->ndef();
 
-                       float heat = map->getHeat(env, p);
+                       float heat = map->updateBlockHeat(env, p);
                        //heater = rare
                        content_t c = map->getNodeNoEx(p - v3s16(0,  -1, 0 )).getContent(); // top
                        //more chance to freeze if air at top
@@ -315,7 +315,7 @@ class LiquidMeltWeather : public ActiveBlockModifier {
                        ServerMap *map = &env->getServerMap();
                        INodeDefManager *ndef = env->getGameDef()->ndef();
 
-                       float heat = map->getHeat(env, p);
+                       float heat = map->updateBlockHeat(env, p);
                        content_t c = map->getNodeNoEx(p - v3s16(0,  -1, 0 )).getContent(); // top
                        if (heat >= 1 && (heat >= 40 || ((myrand_range(heat, 40)) >= (c == CONTENT_AIR ? 10 : 20)))) {
                                n.freezeMelt(ndef);
@@ -378,7 +378,7 @@ void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) {
                env->addActiveBlockModifier(new LiquidDropABM(env, nodedef));
                env->addActiveBlockModifier(new LiquidMeltHot(env, nodedef));
                //env->addActiveBlockModifier(new LiquidMeltAround(env, nodedef));
-               if (g_settings->getBool("weather")) {
+               if (env->m_use_weather) {
                        env->addActiveBlockModifier(new LiquidFreeze(env, nodedef));
                        env->addActiveBlockModifier(new LiquidMeltWeather(env, nodedef));
                }
index a81ff7d929be8416947f983d5ccfb79a3848158d..ed9aa9044505329433aced8d84760dd27de3f6ed 100644 (file)
@@ -512,8 +512,7 @@ void *EmergeThread::Thread() {
                                                ign(&m_server->m_ignore_map_edit_events_area,
                                                VoxelArea(minp, maxp));
                                        {  // takes about 90ms with -O1 on an e3-1230v2
-                                               m_server->getScriptIface()->
-                                                               environment_OnGenerated(
+                                               m_server->getScriptIface()->environment_OnGenerated(
                                                                minp, maxp, emerge->getBlockSeed(minp));
                                        }
 
@@ -535,14 +534,6 @@ void *EmergeThread::Thread() {
                if (block)
                        modified_blocks[p] = block;
 
-               // Update weather data in mapblock
-               for(std::map<v3s16, MapBlock *>::iterator
-                       i = modified_blocks.begin();
-                       i != modified_blocks.end(); ++i) {
-                       map->getHeat(m_server->m_env, MAP_BLOCKSIZE*i->first ,i->second);
-                       map->getHumidity(m_server->m_env, MAP_BLOCKSIZE*i->first, i->second);
-               }
-
                // Set the modified blocks unsent for all the clients
                for (std::map<u16, RemoteClient*>::iterator
                         i = m_server->m_clients.begin();
index 86c98f2c2afdaf70aa66d30e70be017f5ad1ef65..03b436890b333d4c7fe8db968806889264da7ce1 100644 (file)
@@ -322,6 +322,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
        m_recommended_send_interval(0.1),
        m_max_lag_estimate(0.1)
 {
+       m_use_weather = g_settings->getBool("weather");
 }
 
 ServerEnvironment::~ServerEnvironment()
@@ -808,6 +809,16 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
        
        // Activate stored objects
        activateObjects(block, dtime_s);
+       
+       // Calculate weather conditions
+       if (m_use_weather) {
+               m_map->updateBlockHeat(this, block->getPos() *  MAP_BLOCKSIZE, block);
+               m_map->updateBlockHumidity(this, block->getPos() * MAP_BLOCKSIZE, block);
+       } else {
+               block->heat     = HEAT_UNDEFINED;
+               block->humidity = HUMIDITY_UNDEFINED;
+               block->weather_update_time = 0;
+       }
 
        // Run node timers
        std::map<v3s16, NodeTimer> elapsed_timers =
index 597ad5ff0187698bdc6c4338f0e3c7e07cea714f..86654937d0f18aee14402e530906d9385c032d3c 100644 (file)
@@ -300,6 +300,10 @@ public:
 
        void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; }
        float getMaxLagEstimate() { return m_max_lag_estimate; }
+       
+       // is weather active in this environment?
+       bool m_use_weather;
+       
 private:
 
        /*
index a8fbbac2a208c3c0ab92f6278d3816fce234374f..08f255deed3ea81f0e479ac091df7444528c759c 100644 (file)
@@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapgen_v6.h"
 #include "biome.h"
 #include "config.h"
+#include "server.h"
 #include "database.h"
 #include "database-dummy.h"
 #include "database-sqlite3.h"
@@ -2824,6 +2825,38 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
        /*infostream<<"finishBlockMake() done for ("<<blockpos_requested.X
                        <<","<<blockpos_requested.Y<<","
                        <<blockpos_requested.Z<<")"<<std::endl;*/
+                       
+       /*
+               Update weather data in central blocks if needed
+       */
+       ServerEnvironment *senv = &((Server *)m_gamedef)->getEnv();
+       if (senv->m_use_weather) {
+               for(s16 x=blockpos_min.X-extra_borders.X;
+                       x<=blockpos_max.X+extra_borders.X; x++)
+               for(s16 z=blockpos_min.Z-extra_borders.Z;
+                       z<=blockpos_max.Z+extra_borders.Z; z++)
+               for(s16 y=blockpos_min.Y-extra_borders.Y;
+                       y<=blockpos_max.Y+extra_borders.Y; y++)
+               {
+                       v3s16 p(x, y, z);
+                       updateBlockHeat(senv, p * MAP_BLOCKSIZE, NULL);
+                       updateBlockHumidity(senv, p * MAP_BLOCKSIZE, NULL);
+               }
+       } else {
+               for(s16 x=blockpos_min.X-extra_borders.X;
+                       x<=blockpos_max.X+extra_borders.X; x++)
+               for(s16 z=blockpos_min.Z-extra_borders.Z;
+                       z<=blockpos_max.Z+extra_borders.Z; z++)
+               for(s16 y=blockpos_min.Y-extra_borders.Y;
+                       y<=blockpos_max.Y+extra_borders.Y; y++)
+               {
+                       MapBlock *block = getBlockNoCreateNoEx(v3s16(x, y, z));
+                       block->heat     = HEAT_UNDEFINED;
+                       block->humidity = HUMIDITY_UNDEFINED;
+                       block->weather_update_time = 0;
+               }
+       }
+       
 #if 0
        if(enable_mapgen_debug_info)
        {
@@ -3888,74 +3921,41 @@ void ServerMap::PrintInfo(std::ostream &out)
        out<<"ServerMap: ";
 }
 
-s16 ServerMap::getHeat(ServerEnvironment *env, v3s16 p, MapBlock *block)
+s16 ServerMap::updateBlockHeat(ServerEnvironment *env, v3s16 p, MapBlock *block)
 {
-       if(block == NULL)
-               block = getBlockNoCreateNoEx(getNodeBlockPos(p));
-       if(block != NULL) {
-               if (env->getGameTime() - block->heat_time < 10)
+       u32 gametime = env->getGameTime();
+       
+       if (block) {
+               if (gametime - block->weather_update_time < 10)
                        return block->heat;
+       } else {
+               block = getBlockNoCreateNoEx(getNodeBlockPos(p));
        }
 
-       //variant 1: full random
-       //f32 heat = NoisePerlin3D(m_emerge->biomedef->np_heat, p.X, env->getGameTime()/100, p.Z, m_emerge->params->seed);
-
-       //variant 2: season change based on default heat map
-       const f32 offset = 20; // = m_emerge->biomedef->np_heat->offset
-       const f32 scale  = 20; // = m_emerge->biomedef->np_heat->scale
-       const f32 range  = 20;
-       f32 heat = NoisePerlin2D(m_emerge->biomedef->np_heat, p.X, p.Z,
-                                       m_emerge->params->seed); // 0..50..100
-
-       heat -= m_emerge->biomedef->np_heat->offset; // -50..0..+50
+       f32 heat = m_emerge->biomedef->calcBlockHeat(p, m_seed,
+                       env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed());
 
-       // normalizing - todo REMOVE after fixed NoiseParams nparams_biome_def_heat = {50, 50, -> 20, 50,
-       if(m_emerge->biomedef->np_heat->scale)
-               heat /= m_emerge->biomedef->np_heat->scale / scale; //  -20..0..+20
-
-       f32 seasonv = (f32)env->getGameTime() * env->getTimeOfDaySpeed();
-       seasonv /= 86400 * g_settings->getS16("year_days"); // season change speed
-       seasonv += (f32)p.X / 3000; // you can walk to area with other season
-       seasonv = sin(seasonv * M_PI);
-       heat += (range * (heat < 0 ? 2 : 0.5)) * seasonv; // -60..0..30
-
-       heat += offset; // -40..0..50
-       heat += p.Y / -333; // upper=colder, lower=hotter, 3c per 1000
-
-       // daily change, hotter at sun +4, colder at night -4
-       heat += 8 * (sin(cycle_shift(env->getTimeOfDayF(), -0.25) * M_PI) - 0.5); //-44..20..54
-
-       if(block != NULL) {
-               block->heat = heat;
-               block->heat_time = env->getGameTime();
-       }
+       block->heat = heat;
+       block->weather_update_time = gametime;
        return heat;
 }
 
-s16 ServerMap::getHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block)
+s16 ServerMap::updateBlockHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block)
 {
-       if(block == NULL)
-               block = getBlockNoCreateNoEx(getNodeBlockPos(p));
-       if(block != NULL) {
-               if (env->getGameTime() - block->humidity_time < 10)
+       u32 gametime = env->getGameTime();
+       
+       if (block) {
+               if (gametime - block->weather_update_time < 10)
                        return block->humidity;
+       } else {
+               block = getBlockNoCreateNoEx(getNodeBlockPos(p));
        }
 
-       f32 humidity = NoisePerlin2D(m_emerge->biomedef->np_humidity, p.X, p.Z, 
-                                               m_emerge->params->seed);
-
-       f32 seasonv = (f32)env->getGameTime() * env->getTimeOfDaySpeed();
-       seasonv /= 86400 * 2; // bad weather change speed (2 days)
-       seasonv += (f32)p.Z / 300;
-       humidity += 30 * sin(seasonv * M_PI);
-
-       humidity += -12 * ( sin(cycle_shift(env->getTimeOfDayF(), -0.1) * M_PI) - 0.5);
-       humidity = rangelim(humidity, 0, 100);
-
-       if(block != NULL) {
-               block->humidity = humidity;
-               block->humidity_time = env->getGameTime();
-       }
+       f32 humidity = m_emerge->biomedef->calcBlockHumidity(p, m_seed,
+                       env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed());
+                       
+       block->humidity = humidity;
+       block->weather_update_time = gametime;
        return humidity;
 }
 
index 34456d6825dd2116a3f6fb5beeb172a38f7b9fb7..b70b18acc0ff80c9d4b85668705d780d9fe951d3 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -477,8 +477,8 @@ public:
        // Parameters fed to the Mapgen
        MapgenParams *m_mgparams;
 
-       virtual s16 getHeat(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
-       virtual s16 getHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
+       virtual s16 updateBlockHeat(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
+       virtual s16 updateBlockHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
 
 private:
        // Seed used for all kinds of randomness in generation
index b8278b3be740829bdc0e0428ec705f0823f4139b..3fb2ec5eda0bd3bfc8f0141d3f545f752f98cf63 100644 (file)
@@ -44,9 +44,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
                heat(0),
-               heat_time(0),
                humidity(0),
-               humidity_time(0),
+               weather_update_time(0),
                m_parent(parent),
                m_pos(pos),
                m_gamedef(gamedef),
index de49e613055069616b4b5ae2a0f99cc2b5918cf7..e0730ffcf459093a3e4f87aef11dd14e85e15b7a 100644 (file)
@@ -515,9 +515,8 @@ public:
        StaticObjectList m_static_objects;
        
        s16 heat;
-       u32 heat_time;
        s16 humidity;
-       u32 humidity_time;
+       u32 weather_update_time;
 
 private:
        /*
index 8b0d8cd6ec506bfea9e164b9453a4607aa0120be..436eb014d77f44c20c760c44eee0cd41e34165e6 100644 (file)
@@ -764,7 +764,7 @@ int ModApiEnvMod::l_get_heat(lua_State *L)
        GET_ENV_PTR;
 
        v3s16 pos = read_v3s16(L, 1);
-       lua_pushnumber(L, env->getServerMap().getHeat(env, pos));
+       lua_pushnumber(L, env->getServerMap().updateBlockHeat(env, pos));
        return 1;
 }
 
@@ -775,7 +775,7 @@ int ModApiEnvMod::l_get_humidity(lua_State *L)
        GET_ENV_PTR;
 
        v3s16 pos = read_v3s16(L, 1);
-       lua_pushnumber(L, env->getServerMap().getHumidity(env, pos));
+       lua_pushnumber(L, env->getServerMap().updateBlockHumidity(env, pos));
        return 1;
 }
 
index d502d68a0b0fccc77ee45ad0412ed323e10d3047..bc7829f748cafcda5bf29d35b382a4b1a85615c7 100644 (file)
@@ -489,6 +489,7 @@ public:
 
        bool showFormspec(const char *name, const std::string &formspec, const std::string &formname);
        Map & getMap() { return m_env->getMap(); }
+       ServerEnvironment & getEnv() { return *m_env; }
        
        u32 hudAdd(Player *player, HudElement *element);
        bool hudRemove(Player *player, u32 id);