35 changes: 17 additions & 18 deletions src/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ struct ActiveABM
{
ActiveBlockModifier *abm;
int chance;
int neighbors_range;
std::set<content_t> required_neighbors;
};

Expand Down Expand Up @@ -672,6 +673,7 @@ class ABMHandler
chance = 1;
ActiveABM aabm;
aabm.abm = abm;
aabm.neighbors_range = abm->getNeighborsRange();
aabm.chance = chance / intervals;
if(aabm.chance == 0)
aabm.chance = 1;
Expand Down Expand Up @@ -712,6 +714,8 @@ class ABMHandler
if(m_aabms.empty())
return;

ScopeProfiler sp(g_profiler, "ABM apply", SPT_ADD);

ServerMap *map = &m_env->getServerMap();

v3s16 p0;
Expand All @@ -735,12 +739,14 @@ class ABMHandler
continue;

// Check neighbors
MapNode neighbor;
if(!i->required_neighbors.empty())
{
v3s16 p1;
for(p1.X = p.X-1; p1.X <= p.X+1; p1.X++)
for(p1.Y = p.Y-1; p1.Y <= p.Y+1; p1.Y++)
for(p1.Z = p.Z-1; p1.Z <= p.Z+1; p1.Z++)
int neighbors_range = i->neighbors_range;
for(p1.X = p.X - neighbors_range; p1.X <= p.X + neighbors_range; ++p1.X)
for(p1.Y = p.Y - neighbors_range; p1.Y <= p.Y + neighbors_range; ++p1.Y)
for(p1.Z = p.Z - neighbors_range; p1.Z <= p.Z + neighbors_range; ++p1.Z)
{
if(p1 == p)
continue;
Expand All @@ -749,6 +755,7 @@ class ABMHandler
std::set<content_t>::const_iterator k;
k = i->required_neighbors.find(c);
if(k != i->required_neighbors.end()){
neighbor = n;
goto neighbor_found;
}
}
Expand All @@ -761,29 +768,28 @@ class ABMHandler
u32 active_object_count = block->m_static_objects.m_active.size();
// Find out how many objects this and all the neighbors contain
u32 active_object_count_wider = 0;
u32 wider_unknown_count = 0;
//u32 wider_unknown_count = 0;
for(s16 x=-1; x<=1; x++)
for(s16 y=-1; y<=1; y++)
for(s16 z=-1; z<=1; z++)
{
MapBlock *block2 = map->getBlockNoCreateNoEx(
block->getPos() + v3s16(x,y,z));
if(block2==NULL){
wider_unknown_count = 0;
//wider_unknown_count = 0;
continue;
}
active_object_count_wider +=
block2->m_static_objects.m_active.size()
+ block2->m_static_objects.m_stored.size();
}
// Extrapolate
u32 wider_known_count = 3*3*3 - wider_unknown_count;
active_object_count_wider += wider_unknown_count * active_object_count_wider / wider_known_count;
//u32 wider_known_count = 3*3*3; // - wider_unknown_count;
//active_object_count_wider += wider_unknown_count * active_object_count_wider / wider_known_count;

// Call all the trigger variations
i->abm->trigger(m_env, p, n);
// Call trigger
i->abm->trigger(m_env, p, n,
active_object_count, active_object_count_wider);
active_object_count, active_object_count_wider, neighbor);
}
}
}
Expand Down Expand Up @@ -811,14 +817,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
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;
}
m_map->updateBlockHeat(this, block->getPos() * MAP_BLOCKSIZE, block);

// Run node timers
std::map<v3s16, NodeTimer> elapsed_timers =
Expand Down
8 changes: 6 additions & 2 deletions src/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,18 @@ class ActiveBlockModifier
// Empty = do not check neighbors
virtual std::set<std::string> getRequiredNeighbors()
{ return std::set<std::string>(); }
// Maximum range to neighbors
virtual u32 getNeighborsRange()
{ return 1; };
// Trigger interval in seconds
virtual float getTriggerInterval() = 0;
// Random chance of (1 / return value), 0 is disallowed
virtual u32 getTriggerChance() = 0;
// This is called usually at interval for 1/chance of the nodes
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){};
//virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){};
//virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, MapNode neighbor){};
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
u32 active_object_count, u32 active_object_count_wider){};
u32 active_object_count, u32 active_object_count_wider, MapNode neighbor){};
};

struct ABMWithState
Expand Down
6 changes: 3 additions & 3 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2864,7 +2864,7 @@ void the_game(
else {
fog_range = draw_control.wanted_range*BS + 0.0*MAP_BLOCKSIZE*BS;
if(use_weather)
fog_range *= (1.5 - 1.4*(float)client.getEnv().getClientMap().getHumidity(pos_i)/100);
fog_range *= (1.5 - 1.4*(float)client.getEnv().getClientMap().getHumidity(pos_i, 1)/100);
fog_range = MYMIN(fog_range, (draw_control.farthest_drawn+20)*BS);
fog_range *= 0.9;
}
Expand Down Expand Up @@ -3011,8 +3011,8 @@ void the_game(
<<", "<<(player_position.Y/BS)
<<", "<<(player_position.Z/BS)
<<") (yaw="<<(wrapDegrees_0_360(camera_yaw))
<<") (t="<<client.getEnv().getClientMap().getHeat(pos_i)
<<"C, h="<<client.getEnv().getClientMap().getHumidity(pos_i)
<<") (t="<<client.getEnv().getClientMap().getHeat(pos_i, 1)
<<"C, h="<<client.getEnv().getClientMap().getHumidity(pos_i, 1)
<<"%) (seed = "<<((unsigned long long)client.getMapSeed())
<<")";
guitext2->setText(narrow_to_wide(os.str()).c_str());
Expand Down
76 changes: 33 additions & 43 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2385,21 +2385,21 @@ void Map::removeNodeTimer(v3s16 p)
block->m_node_timers.remove(p_rel);
}

s16 Map::getHeat(v3s16 p)
s16 Map::getHeat(v3s16 p, bool no_random)
{
MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p));
if(block != NULL) {
return block->heat;
return block->heat + (no_random ? 0 : myrand_range(0, 1));
}
//errorstream << "No heat for " << p.X<<"," << p.Z << std::endl;
return 0;
}

s16 Map::getHumidity(v3s16 p)
s16 Map::getHumidity(v3s16 p, bool no_random)
{
MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p));
if(block != NULL) {
return block->humidity;
return block->humidity + (no_random ? 0 : myrand_range(0, 1));
}
//errorstream << "No humidity for " << p.X<<"," << p.Z << std::endl;
return 0;
Expand Down Expand Up @@ -2828,39 +2828,17 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
<<","<<blockpos_requested.Y<<","
<<blockpos_requested.Z<<")"<<std::endl;*/

#if 0
/*
Update weather data in blocks
*/
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);
MapBlock *block = getBlockNoCreateNoEx(p);
block->weather_update_time = 0;
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;
}
}

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++)
updateBlockHeat(senv, v3s16(x, y, z) * MAP_BLOCKSIZE, NULL);
#endif

#if 0
if(enable_mapgen_debug_info)
{
Expand Down Expand Up @@ -3930,41 +3908,53 @@ s16 ServerMap::updateBlockHeat(ServerEnvironment *env, v3s16 p, MapBlock *block)
u32 gametime = env->getGameTime();

if (block) {
if (gametime - block->weather_update_time < 10)
return block->heat;
if (gametime < block->weather_update_time)
return block->heat + myrand_range(0, 1);
} else {
block = getBlockNoCreateNoEx(getNodeBlockPos(p));
}

f32 heat = m_emerge->biomedef->calcBlockHeat(p, m_seed,
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed());
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed(), env->m_use_weather);
f32 humidity = m_emerge->biomedef->calcBlockHumidity(p, m_seed,
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed(), env->m_use_weather);

if(block) {
block->heat = heat;
block->weather_update_time = gametime;
block->humidity = humidity;
if (env->m_use_weather)
block->weather_update_time = gametime + 10;
else
block->weather_update_time = -1; //never update
}
return heat;
return heat + myrand_range(0, 1);
}

s16 ServerMap::updateBlockHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block)
{
u32 gametime = env->getGameTime();

if (block) {
if (gametime - block->weather_update_time < 10)
return block->humidity;
if (gametime < block->weather_update_time)
return block->humidity + myrand_range(0, 1);
} else {
block = getBlockNoCreateNoEx(getNodeBlockPos(p));
}

f32 heat = m_emerge->biomedef->calcBlockHeat(p, m_seed,
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed(), env->m_use_weather);
f32 humidity = m_emerge->biomedef->calcBlockHumidity(p, m_seed,
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed());
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed(), env->m_use_weather);

if(block) {
block->heat = heat;
block->humidity = humidity;
block->weather_update_time = gametime;
if (env->m_use_weather)
block->weather_update_time = gametime + 10;
else
block->weather_update_time = -1; //never update
}
return humidity;
return humidity + myrand_range(0, 1);
}

/*
Expand Down
4 changes: 2 additions & 2 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,8 @@ class Map /*: public NodeContainer*/
void transforming_liquid_add(v3s16 p);
s32 transforming_liquid_size();

virtual s16 getHeat(v3s16 p);
virtual s16 getHumidity(v3s16 p);
virtual s16 getHeat(v3s16 p, bool no_random = 0);
virtual s16 getHumidity(v3s16 p, bool no_random = 0);

protected:
friend class LuaVoxelManip;
Expand Down
5 changes: 4 additions & 1 deletion src/mapnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,12 @@ u8 MapNode::addLevel(INodeDefManager *nodemgr, s8 add)
}

void MapNode::freezeMelt(INodeDefManager *ndef) {
content_t to = ndef->getId(ndef->get(*this).freezemelt);
if (to == CONTENT_IGNORE)
return;
u8 level_was_max = this->getMaxLevel(ndef);
u8 level_was = this->getLevel(ndef);
this->setContent(ndef->getId(ndef->get(*this).freezemelt));
this->setContent(to);
u8 level_now_max = this->getMaxLevel(ndef);
if (level_was_max && level_was_max != level_now_max) {
u8 want = (float)level_now_max / level_was_max * level_was;
Expand Down
5 changes: 4 additions & 1 deletion src/script/cpp_api/s_env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,11 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
int trigger_chance = 50;
getintfield(L, current_abm, "chance", trigger_chance);

int neighbors_range = 1;
getintfield(L, current_abm, "neighbors_range", neighbors_range);

LuaABM *abm = new LuaABM(L, id, trigger_contents,
required_neighbors, trigger_interval, trigger_chance);
required_neighbors, neighbors_range, trigger_interval, trigger_chance);

env->addActiveBlockModifier(abm);

Expand Down
5 changes: 3 additions & 2 deletions src/script/lua_api/l_env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,


void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
u32 active_object_count, u32 active_object_count_wider)
u32 active_object_count, u32 active_object_count_wider, MapNode neighbor)
{
GameScripting *scriptIface = env->getScriptIface();
scriptIface->realityCheck();
Expand Down Expand Up @@ -73,7 +73,8 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
pushnode(L, n, env->getGameDef()->ndef());
lua_pushnumber(L, active_object_count);
lua_pushnumber(L, active_object_count_wider);
if(lua_pcall(L, 4, 0, 0))
pushnode(L, neighbor, env->getGameDef()->ndef());
if(lua_pcall(L, 5, 0, 0))
script_error(L, "error: %s", lua_tostring(L, -1));
}

Expand Down
9 changes: 8 additions & 1 deletion src/script/lua_api/l_env.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,19 @@ class LuaABM : public ActiveBlockModifier

std::set<std::string> m_trigger_contents;
std::set<std::string> m_required_neighbors;
u32 m_neighbors_range;
float m_trigger_interval;
u32 m_trigger_chance;
public:
LuaABM(lua_State *L, int id,
const std::set<std::string> &trigger_contents,
const std::set<std::string> &required_neighbors,
int neighbors_range,
float trigger_interval, u32 trigger_chance):
m_id(id),
m_trigger_contents(trigger_contents),
m_required_neighbors(required_neighbors),
m_neighbors_range(neighbors_range),
m_trigger_interval(trigger_interval),
m_trigger_chance(trigger_chance)
{
Expand All @@ -180,6 +183,10 @@ class LuaABM : public ActiveBlockModifier
{
return m_required_neighbors;
}
virtual u32 getNeighborsRange()
{
return m_neighbors_range;
}
virtual float getTriggerInterval()
{
return m_trigger_interval;
Expand All @@ -189,7 +196,7 @@ class LuaABM : public ActiveBlockModifier
return m_trigger_chance;
}
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
u32 active_object_count, u32 active_object_count_wider);
u32 active_object_count, u32 active_object_count_wider, MapNode neighbor);
};

#endif /* L_ENV_H_ */