diff --git a/src/map.cpp b/src/map.cpp index f4d9871af..10a0c3543 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -533,6 +533,8 @@ void ServerMap::transformLiquids(std::map &modified_blocks, std::vector > changed_nodes; + std::vector check_for_falling; + u32 liquid_loop_max = g_settings->getS32("liquid_loop_max"); u32 loop_max = liquid_loop_max; @@ -595,6 +597,7 @@ void ServerMap::transformLiquids(std::map &modified_blocks, int num_neutrals = 0; bool flowing_down = false; bool ignored_sources = false; + bool floating_node_above = false; for (u16 i = 0; i < 6; i++) { NeighborType nt = NEIGHBOR_SAME_LEVEL; switch (i) { @@ -610,7 +613,9 @@ void ServerMap::transformLiquids(std::map &modified_blocks, v3s16 npos = p0 + liquid_6dirs[i]; NodeNeighbor nb(getNode(npos), nt, npos); const ContentFeatures &cfnb = m_nodedef->get(nb.n); - switch (m_nodedef->get(nb.n.getContent()).liquid_type) { + if (nt == NEIGHBOR_UPPER && cfnb.floats) + floating_node_above = true; + switch (cfnb.liquid_type) { case LIQUID_NONE: if (cfnb.floodable) { airs[num_airs++] = nb; @@ -752,6 +757,11 @@ void ServerMap::transformLiquids(std::map &modified_blocks, == flowing_down))) continue; + /* + check if there is a floating node above that needs to be updated. + */ + if (floating_node_above && new_node_content == CONTENT_AIR) + check_for_falling.push_back(p0); /* update the current node @@ -836,6 +846,11 @@ void ServerMap::transformLiquids(std::map &modified_blocks, m_transforming_liquid.push_back(iter); voxalgo::update_lighting_nodes(this, changed_nodes, modified_blocks); + + for (const v3s16 &p : check_for_falling) { + env->getScriptIface()->check_for_falling(p); + } + env->getScriptIface()->on_liquid_transformed(changed_nodes); /* ---------------------------------------------------------------------- diff --git a/src/nodedef.cpp b/src/nodedef.cpp index e5f056807..607107264 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -1393,6 +1393,7 @@ content_t NodeDefManager::set(const std::string &name, const ContentFeatures &de eraseIdFromGroups(id); m_content_features[id] = def; + m_content_features[id].floats = itemgroup_get(def.groups, "float") != 0; m_content_lighting_flag_cache[id] = def.getLightingFlags(); verbosestream << "NodeDefManager: registering content id \"" << id << "\": name=\"" << def.name << "\""<= m_content_features.size()) m_content_features.resize((u32)(i) + 1); m_content_features[i] = f; + m_content_features[i].floats = itemgroup_get(f.groups, "float") != 0; m_content_lighting_flag_cache[i] = f.getLightingFlags(); addNameIdMapping(i, f.name); TRACESTREAM(<< "NodeDef: deserialized " << f.name << std::endl); diff --git a/src/nodedef.h b/src/nodedef.h index 044fdd8b2..acc711611 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -322,6 +322,9 @@ struct ContentFeatures bool has_on_destruct; bool has_after_destruct; + // "float" group + bool floats; + /* Actual data */ diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp index 55c0a84f5..e49113405 100644 --- a/src/script/cpp_api/s_env.cpp +++ b/src/script/cpp_api/s_env.cpp @@ -257,6 +257,18 @@ void ScriptApiEnv::on_emerge_area_completion( } } +void ScriptApiEnv::check_for_falling(v3s16 p) +{ + SCRIPTAPI_PRECHECKHEADER + + int error_handler = PUSH_ERROR_HANDLER(L); + lua_getglobal(L, "core"); + lua_getfield(L, -1, "check_for_falling"); + luaL_checktype(L, -1, LUA_TFUNCTION); + push_v3s16(L, p); + PCALL_RES(lua_pcall(L, 1, 0, error_handler)); +} + void ScriptApiEnv::on_liquid_transformed( const std::vector> &list) { diff --git a/src/script/cpp_api/s_env.h b/src/script/cpp_api/s_env.h index 090858f17..9a50a01cc 100644 --- a/src/script/cpp_api/s_env.h +++ b/src/script/cpp_api/s_env.h @@ -43,6 +43,8 @@ public: void on_emerge_area_completion(v3s16 blockpos, int action, ScriptCallbackState *state); + void check_for_falling(v3s16 p); + // Called after liquid transform changes void on_liquid_transformed(const std::vector> &list);