#include "nodedef.h"
#include "map.h" //for ManualMapVoxelManipulator
#include "log.h"
+#include "util/numeric.h"
#include "main.h"
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;
+}
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
// 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
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
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);
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));
}
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));
}
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();
m_recommended_send_interval(0.1),
m_max_lag_estimate(0.1)
{
+ m_use_weather = g_settings->getBool("weather");
}
ServerEnvironment::~ServerEnvironment()
// 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 =
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:
/*
#include "mapgen_v6.h"
#include "biome.h"
#include "config.h"
+#include "server.h"
#include "database.h"
#include "database-dummy.h"
#include "database-sqlite3.h"
/*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)
{
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;
}
// 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
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),
StaticObjectList m_static_objects;
s16 heat;
- u32 heat_time;
s16 humidity;
- u32 humidity_time;
+ u32 weather_update_time;
private:
/*
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;
}
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;
}
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);