diff --git a/CHANGELOG.md b/CHANGELOG.md index be3403866..a43fe4d90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ Core: fast reliable network protocol, fast multi-threaded server, utf8 chat, bui Changelog ====== +### 5.7.0.0 (?) + * Tree growth + * Weather tuned + + ### 5.6.1.0 (?) * auth_kv removed, use instead in world.mt: auth_backend = leveldbfm diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 79fda5472..bfb2fbd06 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -312,7 +312,7 @@ local function main_button_handler(tabview, fields, name, tabdata) if gamedata.address and gamedata.port then core.settings:set("address", gamedata.address) core.settings:set("remote_port", gamedata.port) - core.settings:set("remote_proto", gamedata.proto) + core.settings:set("remote_proto", gamedata.proto or "mt") core.start() end return true diff --git a/games/default b/games/default index 8c9754d57..3b92947db 160000 --- a/games/default +++ b/games/default @@ -1 +1 @@ -Subproject commit 8c9754d578c092b2863b917f11aa803ba8fcc680 +Subproject commit 3b92947db70cca3bd707d644482e123efc3f6350 diff --git a/src/content_abm_grow_tree.cpp b/src/content_abm_grow_tree.cpp index b4659e005..46682f60d 100644 --- a/src/content_abm_grow_tree.cpp +++ b/src/content_abm_grow_tree.cpp @@ -27,16 +27,18 @@ along with Freeminer. If not, see . #include "serverenvironment.h" constexpr auto grow_debug = false; +constexpr auto grow_debug_fast_default = 0; //constexpr auto grow_debug_no_die = false; // Trees use param2 for rotation, level1 is free -inline uint8_t get_tree_water_level(const MapNode &n) +inline uint8_t get_tree_water_level(const MapNode &n, bool use_param2) { - return n.getParam1(); + return use_param2 ? n.getParam2() : n.getParam1(); } -inline void set_tree_water_level(MapNode &n, const uint8_t level) + +inline void set_tree_water_level(MapNode &n, const uint8_t level, bool use_param2) { - n.setParam1(level); + use_param2 ? n.setParam2(level) : n.setParam1(level); } // Leaves use param1 for light, level2 is free @@ -78,6 +80,7 @@ constexpr auto D_BOTTOM = 6; struct GrowParams { + int tree_water_param2 = 0; int tree_water_max = 50; // todo: depend on humidity 10-100 int tree_grow_water_min = 20; int tree_grow_heat_min = 7; @@ -85,7 +88,9 @@ struct GrowParams int tree_grow_light_max = 12; // grow more leaves around before grow tree up int tree_get_water_from_humidity = 70; // rain start int tree_get_water_max_from_humidity = 30; // max level to get from air + int tree_grow_bottom = 1; int tree_grow_chance = 10; + int tree_width_to_height = 1; int leaves_water_max = 20; // todo: depend on humidity 2-20 int leaves_grow_light_min = 8; int leaves_grow_water_min_top = 4; @@ -104,8 +109,10 @@ struct GrowParams int leaves_to_fruit_light_min = 10; int leaves_to_fruit_chance = 10; - GrowParams(const ContentFeatures &cf, bool grow_debug_fast = false) + GrowParams(const ContentFeatures &cf, int16_t grow_debug_fast = 0) { + if (cf.groups.contains("tree_water_param2")) + tree_water_param2 = cf.groups.at("tree_water_param2"); if (cf.groups.contains("tree_water_max")) tree_water_max = cf.groups.at("tree_water_max"); if (cf.groups.contains("tree_grow_water_min")) @@ -116,8 +123,12 @@ struct GrowParams tree_grow_heat_max = cf.groups.at("tree_grow_heat_max"); if (cf.groups.contains("tree_grow_light_max")) tree_grow_light_max = cf.groups.at("tree_grow_light_max"); + if (cf.groups.contains("tree_grow_bottom")) + tree_grow_bottom = cf.groups.at("tree_grow_bottom"); if (cf.groups.contains("tree_grow_chance")) - tree_grow_chance = grow_debug_fast ? 0 : cf.groups.at("tree_grow_chance"); + tree_grow_chance = cf.groups.at("tree_grow_chance"); + if (cf.groups.contains("tree_width_to_height")) + tree_width_to_height = cf.groups.at("tree_width_to_height"); if (cf.groups.contains("tree_get_water_from_humidity")) tree_get_water_from_humidity = cf.groups.at("tree_get_water_from_humidity"); if (cf.groups.contains("tree_get_water_max_from_humidity")) @@ -146,7 +157,7 @@ struct GrowParams if (cf.groups.contains("leaves_die_heat_min")) leaves_die_heat_min = cf.groups.at("leaves_die_heat_min"); if (cf.groups.contains("leaves_die_chance")) - leaves_die_chance = grow_debug_fast ? 0 : cf.groups.at("leaves_die_chance"); + leaves_die_chance = cf.groups.at("leaves_die_chance"); if (cf.groups.contains("leaves_die_from_liquid")) leaves_die_from_liquid = cf.groups.at("leaves_die_from_liquid"); if (cf.groups.contains("leaves_to_fruit_water_min")) @@ -157,21 +168,29 @@ struct GrowParams leaves_to_fruit_light_min = cf.groups.at("leaves_to_fruit_light_min"); if (cf.groups.contains("leaves_to_fruit_chance")) leaves_to_fruit_chance = cf.groups.at("leaves_to_fruit_chance"); + + if (grow_debug_fast) { + tree_grow_chance = leaves_die_chance = 0; + } + if (grow_debug_fast > 1) { + tree_grow_heat_min = tree_grow_heat_max = leaves_grow_heat_min = + leaves_grow_heat_max = 0; + } } }; class GrowTree : public ActiveBlockModifier { - std::unordered_map tree_to_leaves, tree_to_fruit; + std::unordered_map tree_to_leaves; //, tree_to_fruit; std::unordered_map type_params; - bool grow_debug_fast = false; + int16_t grow_debug_fast = grow_debug_fast_default; // bool grow_debug = false; public: GrowTree(ServerEnvironment *env, NodeDefManager *ndef) { // g_settings->getBoolNoEx("grow_debug", grow_debug); - g_settings->getBoolNoEx("grow_debug_fast", grow_debug_fast); + g_settings->getS16NoEx("grow_debug_fast", grow_debug_fast); std::vector ids; ndef->getIds("group:grow_tree", ids); @@ -183,10 +202,9 @@ class GrowTree : public ActiveBlockModifier tree_to_leaves[id_tree] = id_leaves; const auto &cf_leaves = ndef->get(id_leaves); - type_params.emplace(id_leaves, GrowParams(cf_leaves)); - if (!cf_leaves.liquid_alternative_source.empty()) - tree_to_fruit[id_tree] = - ndef->getId(cf_leaves.liquid_alternative_source); + type_params.emplace(id_leaves, GrowParams(cf_leaves, grow_debug_fast)); + // if (!cf_leaves.liquid_alternative_source.empty()) + // tree_to_fruit[id_tree] = ndef->getId(cf_leaves.liquid_alternative_source); } } } @@ -220,7 +238,7 @@ class GrowTree : public ActiveBlockModifier int8_t near_soil{0}; int8_t near_liquid{0}; content_t leaves_content{CONTENT_IGNORE}; - content_t fruit_content{CONTENT_IGNORE}; + //content_t fruit_content{CONTENT_IGNORE}; struct Neighbor { @@ -229,7 +247,7 @@ class GrowTree : public ActiveBlockModifier bool is_liquid{false}; bool is_my_leaves{false}; bool is_any_leaves{false}; - bool is_fruit{false}; + //bool is_fruit{false}; bool is_tree{false}; bool is_other_tree{false}; bool is_soil{false}; @@ -259,6 +277,8 @@ class GrowTree : public ActiveBlockModifier } nb.content = nb.node.getContent(); + const auto ¶ms = type_params.at(nbh[D_SELF].content); + nb.cf = (ContentFeatures *)&ndef->get(nb.content); nb.light = getLight(ndef, nb.node); nb.top = i == D_TOP; @@ -275,27 +295,27 @@ class GrowTree : public ActiveBlockModifier leaves_content = tree_to_leaves.contains(nb.content) ? tree_to_leaves.at(nb.content) : CONTENT_IGNORE; - fruit_content = tree_to_fruit.contains(nb.content) - ? tree_to_fruit.at(nb.content) - : CONTENT_IGNORE; + //fruit_content = tree_to_fruit.contains(nb.content) ? tree_to_fruit.at(nb.content) : CONTENT_IGNORE; } //DUMP(is_self, leaves_content); if (!is_self) { - if (!nb.top && !nb.bottom && around_all_is_tree && !nb.is_tree) + if (!nb.top && !nb.bottom && around_all_is_tree && !nb.is_tree) { around_all_is_tree = false; + } nb.is_my_leaves = nb.content == leaves_content; nb.is_any_leaves = nb.is_my_leaves || nb.cf->groups.contains("leaves"); - nb.is_fruit = nb.content == fruit_content; + //nb.is_fruit = nb.content == fruit_content; // DUMP(is_self, nb.is_leaves, "=", nb.content, "==", (int)leaves_content); nb.is_liquid = nb.cf->groups.contains("liquid"); near_liquid += nb.is_liquid; ///has_liquids.emplace_back(nb.pos); - if (nb.top && !nb.is_tree) + if (nb.top && !nb.is_tree) { top_is_not_tree = true; + } nb.is_soil = nb.cf->groups.contains("soil"); near_soil += nb.is_soil; @@ -306,8 +326,9 @@ class GrowTree : public ActiveBlockModifier } nb.water_level = nb.is_my_leaves ? get_leaves_water_level(nb.node) - : nb.is_tree ? get_tree_water_level(nb.node) - : 0; + : nb.is_tree ? get_tree_water_level( + nb.node, params.tree_water_param2) + : 0; nb.facedir = nb.node.getFaceDir(ndef); @@ -342,24 +363,29 @@ class GrowTree : public ActiveBlockModifier const auto save = [&]() { if (self_water_level_orig != self_water_level) { - set_tree_water_level(n, self_water_level); + set_tree_water_level(n, self_water_level, params.tree_water_param2); map->setNode(pos, n); } }; const auto decrease = [&](auto &level, int amount = 1) -> auto { - if (level <= amount) + if (level <= amount) { return false; + } level -= amount; return true; }; if (params.tree_get_water_from_humidity && + self_water_level < params.tree_water_max && self_water_level < params.tree_get_water_max_from_humidity - 1 && near_soil && self_allow_grow_by_rotation && !near_liquid) { float humidity = map->updateBlockHumidity(env, pos); if (humidity >= params.tree_get_water_from_humidity) { if (grow_debug_fast) { - self_water_level = params.tree_get_water_max_from_humidity; + self_water_level = params.tree_get_water_max_from_humidity > + params.tree_water_max + ? params.tree_water_max + : params.tree_get_water_max_from_humidity; } else { // TODO: depend on += ceil( max_from_air * (params.tree_get_water_from_humidity)/(100-humidity)) ++self_water_level; @@ -383,22 +409,23 @@ class GrowTree : public ActiveBlockModifier auto level = nb.node.getLevel(ndef); // TODO: allow get all water if bottom of water != water - if (level <= 1) - return; - //auto amount = grow_debug_fast ? level - 1 : 1; - auto amount = level - 1; - if (self_water_level + amount > params.tree_water_max) - amount = params.tree_water_max - self_water_level; - level -= amount; + if (level > 1) { + //auto amount = grow_debug_fast ? level - 1 : 1; + auto amount = level - 1; + if (self_water_level + amount > params.tree_water_max) { + amount = params.tree_water_max - self_water_level; + } - nb.node.setLevel(ndef, level); + level -= amount; - if (!grow_debug_fast) - map->setNode(nb.pos, nb.node); - self_water_level += amount; - //set_tree_water_level(n, self_water_level); - //map->setNode(p, n); - //if (grow_debug) DUMP("absorbwater", self_water_level, level, amount); + if (!grow_debug_fast) { + nb.node.setLevel(ndef, level); + map->setNode(nb.pos, nb.node); + } + + self_water_level += amount; + + } } // Light recalc sometimes too rare @@ -417,95 +444,122 @@ class GrowTree : public ActiveBlockModifier // DUMP(i, pos.Y, self_water_level, nb.top, nb.water_level, allow_grow_by_light, up_all_leaves, nb.is_my_leaves, nb.is_any_leaves, up_all_leaves, nb.light, params.leaves_die_light_max, nb.allow_grow_by_rotation, nb.is_liquid, nb.cf->name); auto tree_grow = [&]() { - if (content == nb.content) + if (content == nb.content) { return false; + } - if (!((!params.tree_grow_heat_min || heat > params.tree_grow_heat_min) && - (!params.tree_grow_heat_max || - heat < params.tree_grow_heat_max))) + if ((params.tree_grow_heat_min && heat < params.tree_grow_heat_min) || + (params.tree_grow_heat_max && heat > params.tree_grow_heat_max)) { return false; + } - if (self_water_level < params.tree_grow_water_min) + if (self_water_level < params.tree_grow_water_min) { return false; + } - if (!nb.allow_grow_by_rotation) + if (!nb.allow_grow_by_rotation) { return false; + } - if (!(nb.is_any_leaves || nb.is_fruit || nb.cf->buildable_to || - nb.is_liquid || nb.is_soil || nb.cf->groups.contains("sand"))) + if (!(nb.is_any_leaves || nb.cf->buildable_to || nb.is_liquid || + nb.is_soil || nb.cf->groups.contains("sand") || + nb.cf->groups.contains("sapling") || + nb.cf->groups.contains("fruit"))) { + // || nb.is_fruit return false; + } if (nb.top) { - if (nb.content == CONTENT_AIR && - nb.light > params.leaves_grow_light_min) + if (nb.content == CONTENT_AIR && params.leaves_grow_light_min && + nb.light < params.leaves_grow_light_min) { return false; + } //if (nb.is_any_leaves) return false; - if (!(allow_grow_by_light || up_all_leaves)) + if (!(allow_grow_by_light || up_all_leaves)) { return false; + } } // dont grow too deep in liquid if (nb.bottom) { - if (nb.is_liquid && nb.light <= 0) + if (!params.tree_grow_bottom) { + return false; + } + if (nb.is_liquid && nb.light <= 1) { return false; + } - if (near_tree >= 1) + if (near_tree >= 1) { return false; + } } if (!(grow_debug_fast || activate || !myrand_range( - 0, params.tree_grow_chance * (nb.bottom ? 3 : 1)))) + 0, params.tree_grow_chance * (nb.bottom ? 3 : 1)))) { return false; + } - if (!decrease(self_water_level)) + if (!decrease(self_water_level)) { return true; + } //if (grow_debug) DUMP("tr->tr", i, nb.pos.Y, nb.top, nb.bottom, nb.content, content, self_water_level, self_water_level_orig, nb.light); - map->setNode(nb.pos, {content, 1, nbh[D_SELF].node.getParam2()}); + auto node = + nbh[D_SELF].node; //{content, 1, nbh[D_SELF].node.getParam2()}; + set_tree_water_level(node, 1, params.tree_water_param2); + map->setNode(nb.pos, node); + return true; }; - if (tree_grow()) + if (tree_grow()) { break; + } auto water_pump = [&]() { if (!(((!nb.top || nb.is_other_tree) && !nb.bottom && nb.is_tree && !around_all_is_tree) || - nb.is_my_leaves)) + nb.is_my_leaves)) { return false; + } - if (nb.side && nb.is_tree && self_allow_grow_by_rotation) + if (nb.side && nb.is_tree && self_allow_grow_by_rotation) { // DUMP("skip tr side pump", water_level, nb.is_tree, allow_grow_up_by_rotation), return false; + } // DUMP(nb.node, self_water_level, water_level); //??if (is_tree && dir_allow_grow_up_by_rotation && n_water_level >= params.tree_water_max) continue; if (!(!nb.is_my_leaves || (nb.is_my_leaves && (nb.top || !self_allow_grow_by_rotation || - (!nb.top && top_is_not_tree))))) + (!nb.top && top_is_not_tree))))) { return false; + } - auto water_level = nb.content == leaves_content - ? get_leaves_water_level(nb.node) - : get_tree_water_level(nb.node); + auto water_level = + nb.content == leaves_content + ? get_leaves_water_level(nb.node) + : get_tree_water_level(nb.node, params.tree_water_param2); //DUMP(water_level, nb.is_leaves, allow_grow_up_by_rotation, nb.top, top_is_not_tree); if (water_level >= (nb.is_my_leaves ? params.leaves_water_max - : params.tree_water_max)) + : params.tree_water_max)) { return false; + } if (self_water_level <= water_level + (nb.top ? 2 : 1) /* !!! n_water_level > wl_dir + (top ? -1 :bottom ? 1 : 0) */ - ) + ) { return false; + } if (!decrease(self_water_level)) { // if (grow_debug) DUMP("pumpfail", n_water_level, n_water_level_orig, wl_dir, top, bottom, nb.content, c); @@ -514,13 +568,15 @@ class GrowTree : public ActiveBlockModifier //if (grow_debug)DUMP("tr pump", pos.Y, self_water_level,self_water_level_orig, water_level, nb.top,nb.bottom, nb.content, content); ++water_level; nb.is_my_leaves ? set_leaves_water_level(nb.node, water_level) - : set_tree_water_level(nb.node, water_level); + : set_tree_water_level( + nb.node, water_level, params.tree_water_param2); map->setNode(nb.pos, nb.node); return true; }; - if (water_pump()) + if (water_pump()) { break; + } // Dont grow after top //if ((nb.top && nb.is_my_leaves) || nb.content == content) { @@ -530,24 +586,35 @@ class GrowTree : public ActiveBlockModifier //DUMP(allow_grow_leaves, leaves_c, heat , params.leaves_grow_heat_min, params.leaves_grow_heat_max, n_water_level, light_dir); auto leaves_grow = [&]() { - if (!nb.allow_grow_by_rotation) + if (!nb.allow_grow_by_rotation) { + // if (grow_debug) DUMP(nb.allow_grow_by_rotation, nb.top, nb.bottom, (int)nb.facedir); return false; + } if (nbh[D_TOP].content == content) // TODO not top, by grow direction + { return false; - if (leaves_content == CONTENT_IGNORE) + } + if (leaves_content == CONTENT_IGNORE) { return false; - if (!(heat >= params.leaves_grow_heat_min && - heat <= params.leaves_grow_heat_max)) + } + if ((params.leaves_grow_heat_min && heat < params.leaves_grow_heat_min) || + (params.leaves_grow_heat_max && + heat > params.leaves_grow_heat_max)) { return false; + } if (!(self_water_level >= (nb.top ? params.leaves_grow_water_min_top - : params.leaves_grow_water_min_side))) + : params.leaves_grow_water_min_side))) { return false; - if (nb.light < params.leaves_grow_light_min) + } + if (nb.light < params.leaves_grow_light_min) { return false; - if (!nb.cf->buildable_to || nb.is_liquid) + } + if (!nb.cf->buildable_to || nb.is_liquid) { return false; - if (!decrease(self_water_level)) + } + if (!decrease(self_water_level)) { return true; + } //if (grow_debug)DUMP("tr->lv", nb.pos, self_water_level, self_water_level_orig,nb.light_dir); map->setNode(nb.pos, {leaves_content, nb.node.param1, 1}); @@ -555,11 +622,13 @@ class GrowTree : public ActiveBlockModifier if (const auto block = map->getBlock(getNodeBlockPos(nb.pos)); block) { block->setLightingComplete(0); } + return true; }; - if (leaves_grow()) + if (leaves_grow()) { break; + } } // up-down distribute of rest @@ -567,19 +636,20 @@ class GrowTree : public ActiveBlockModifier if (self_allow_grow_by_rotation) { int16_t total_level = self_water_level; int8_t have_liquid = 1; - auto &n_bottom = nbh[D_BOTTOM].node; + //auto &n_bottom = nbh[D_BOTTOM].node; if (nbh[D_BOTTOM].content == content) { total_level += nbh[D_BOTTOM].water_level; ++have_liquid; //if (grow_debug)DUMP("get bot", nbh[D_BOTTOM].water_level, total_level,(int)have_liquid); } - auto &n_top = nbh[D_TOP].node; + //auto &n_top = nbh[D_TOP].node; if (nbh[D_TOP].content == content) { total_level += nbh[D_TOP].water_level; // wl_top; ++have_liquid; //if (grow_debug)DUMP("get top", nbh[D_TOP].water_level, total_level,(int)have_liquid); } + const auto total_level_orig = total_level; /* tot @@ -599,10 +669,14 @@ self = round(avg) top = ceil(avg - 1) */ + const auto float_avg_level = (float)total_level / have_liquid; const auto fill_bottom = [&](bool prefer = false) { - if (nbh[D_BOTTOM].content == content) { - - /* + if (nbh[D_BOTTOM].content != content) + return; + if (total_level <= 1) + return; + //const auto float_avg_level = (float)total_level / have_liquid; + /* const auto float_avg_level = (float)total_level / have_liquid; //if (grow_debug)DUMP(avg_level_for_bottom, (int)have_liquid, total_level); const auto avg_level = prefer ? ceil(float_avg_level + 0.1) @@ -612,25 +686,42 @@ top = ceil(avg - 1) ? avg_level + (avg_level >= (total_level ? 0 : 1)) : params.tree_water_max; */ - const auto float_avg_level = (float)total_level / have_liquid; - const auto avg_level = prefer ? floor(float_avg_level + 1) - : ceil(float_avg_level - 1); - const auto want_level = - std::min(avg_level, params.tree_water_max); - - total_level -= want_level; - --have_liquid; - if (nbh[D_BOTTOM].water_level != want_level) { - //if (grow_debug)DUMP("setbot", bottom_level, total_level,avg_level_for_bottom); - set_tree_water_level(n_bottom, want_level); - map->setNode(nbh[D_BOTTOM].pos, n_bottom); - } + //const auto float_avg_level = (float)total_level / have_liquid; + auto avg_level = + prefer ? floor(float_avg_level + 1) : ceil(float_avg_level - 1); + if (avg_level < 1) + avg_level = 1; + auto want_level = std::min(avg_level, params.tree_water_max); + + // dont grow down + if (want_level > nbh[D_BOTTOM].water_level) { + want_level = nbh[D_BOTTOM].water_level; + } + + total_level -= want_level; + + --have_liquid; + if (have_liquid == 1 && total_level > params.tree_water_max && + want_level < params.tree_water_max) { + --total_level; + ++want_level; + } + + if (nbh[D_BOTTOM].water_level != want_level) { + //if (grow_debug)DUMP("setbot", bottom_level, total_level,avg_level_for_bottom); + set_tree_water_level( + nbh[D_BOTTOM].node, want_level, params.tree_water_param2); + map->setNode(nbh[D_BOTTOM].pos, nbh[D_BOTTOM].node); } }; const auto fill_top = [&](bool prefer = false) { - if (nbh[D_TOP].content == content) { - /* + if (nbh[D_TOP].content != content) + return; + if (total_level <= 1) + return; + //const auto float_avg_level = (float)total_level / have_liquid; + /* const auto float_avg_level = (float)total_level / have_liquid; //const int16_t avg_level_for_top = const auto avg_level = prefer ? ceil(float_avg_level + 0.1) @@ -640,20 +731,26 @@ top = ceil(avg - 1) ? avg_level + (avg_level >= (total_level ? 0 : 1)) : params.tree_water_max; */ - const auto float_avg_level = (float)total_level / have_liquid; - const auto avg_level = prefer ? floor(float_avg_level + 1) - : ceil(float_avg_level - 1); - const auto want_level = - std::min(avg_level, params.tree_water_max); - - total_level -= want_level; - --have_liquid; - if (nbh[D_TOP].water_level != want_level) { + auto avg_level = + prefer ? floor(float_avg_level + 1) : ceil(float_avg_level - 1); + if (avg_level < 1) + avg_level = 1; + auto want_level = std::min(avg_level, params.tree_water_max); + + total_level -= want_level; + --have_liquid; + + if (have_liquid == 1 && total_level > params.tree_water_max && + want_level < params.tree_water_max) { + --total_level; + ++want_level; + } + if (nbh[D_TOP].water_level != want_level) { //if (grow_debug) DUMP("settop", top_level, total_level, avg_level_for_top,around_all_is_tree); - // if (all_is_tree && n_water_level>= params.tree_water_max) DUMP(top_level, total_level, float_avg_level_for_top, avg_level_for_top); - set_tree_water_level(n_top, want_level); - map->setNode(nbh[D_TOP].pos, n_top); - } + // if (all_is_tree && n_water_level>= params.tree_water_max) DUMP(top_level, total_level, float_avg_level_for_top, avg_level_for_top); + set_tree_water_level( + nbh[D_TOP].node, want_level, params.tree_water_param2); + map->setNode(nbh[D_TOP].pos, nbh[D_TOP].node); } }; @@ -673,19 +770,17 @@ S S S S S S S S S SSS SSS SSS SSS SSS */ // Yggdrasil mode - if (near_tree >= 4 + if (near_tree >= 4 && params.tree_width_to_height //&&((nbh[D_BOTTOM].water_level >= params.tree_get_water_from_humidity / 2) || // params.tree_water_max //(nbh[D_SELF].water_level >= params.tree_get_water_from_humidity / 2)) ) { - //DUMP("prefer top", pos.Y, around_all_is_tree, total_level, nbh[D_BOTTOM].water_level, nbh[D_SELF].water_level,nbh[D_TOP].water_level); fill_top(true); fill_bottom(); } else { - //DUMP("prefer bot", pos.Y, around_all_is_tree, total_level); fill_bottom(true); fill_top(); } - // if (grow_debug) DUMP("total res self:", total_level, (int)have_liquid, (int)near_tree, nbh[D_BOTTOM].water_level, nbh[D_SELF].water_level, nbh[D_TOP].water_level); + self_water_level = total_level; } @@ -697,15 +792,17 @@ class GrowLeaves : public ActiveBlockModifier { std::unordered_map leaves_to_fruit; std::unordered_map type_params; - bool grow_debug_fast = false; + int16_t grow_debug_fast = grow_debug_fast_default; static bool can_grow_leaves( GrowParams params, int8_t level, bool is_top, bool is_bottom) { - if (is_top) + if (is_top) { return level >= params.leaves_grow_water_min_top; - if (is_bottom) + } + if (is_bottom) { return level >= params.leaves_grow_water_min_bottom; + } return level >= params.leaves_grow_water_min_side; } @@ -713,15 +810,16 @@ class GrowLeaves : public ActiveBlockModifier GrowLeaves(ServerEnvironment *env, NodeDefManager *ndef) { // g_settings->getBoolNoEx("grow_debug", grow_debug); - g_settings->getBoolNoEx("grow_debug_fast", grow_debug_fast); + g_settings->getS16NoEx("grow_debug_fast", grow_debug_fast); std::vector ids; ndef->getIds("group:grow_leaves", ids); for (const auto &id : ids) { const auto &cf = ndef->get(id); - type_params.emplace(id, GrowParams(cf)); - if (!cf.liquid_alternative_source.empty()) + type_params.emplace(id, GrowParams(cf, grow_debug_fast)); + if (!cf.liquid_alternative_source.empty()) { leaves_to_fruit[id] = ndef->getId(cf.liquid_alternative_source); + } } } virtual const std::vector getTriggerContents() const override @@ -750,7 +848,7 @@ class GrowLeaves : public ActiveBlockModifier content_t c_fruit{}; bool top_is_full_liquid = false; bool have_tree_or_soil = false; - bool have_air = false; + uint8_t have_not_leaves = 0; bool allow_grow_fruit = false; struct Neighbor @@ -783,44 +881,53 @@ class GrowLeaves : public ActiveBlockModifier if (!nb.node) { have_tree_or_soil = true; // dont remove when map busy allow_grow_fruit = false; - have_air = false; + ++have_not_leaves; goto NEXT; } - - nb.light = getLight(ndef, nb.node); - nb.content = nb.node.getContent(); - nb.is_my_leaves = is_self || nb.content == nbh[D_SELF].content; - nb.cf = (ContentFeatures *)&ndef->get(nb.content); - nb.is_tree = nb.cf->groups.contains("tree"); - nb.is_any_leaves = nb.cf->groups.contains("leaves"); - nb.is_liquid = nb.cf->groups.contains("liquid"); - nb.water_level = nb.is_my_leaves ? get_leaves_water_level(nb.node) - : nb.is_tree ? get_tree_water_level(nb.node) - : 0; - top_is_full_liquid = nb.top && nb.is_liquid && - nb.node.getMaxLevel(ndef) == nb.node.getLevel(ndef); - - if (is_self) { - allow_grow_fruit = leaves_to_fruit.contains(nbh[D_SELF].content); - - c_fruit = allow_grow_fruit ? leaves_to_fruit.at(nbh[D_SELF].content) - : CONTENT_IGNORE; - } else { - if ((nb.content == c_fruit) || - (!nb.top && !nb.bottom && !nb.is_any_leaves)) - allow_grow_fruit = false; - - if (nb.is_tree) // no fruit near tree - allow_grow_fruit = false; - - if (!have_tree_or_soil) - have_tree_or_soil = nb.is_tree || nb.is_any_leaves || - nb.cf->groups.contains("soil") || - nb.is_liquid; - if (!have_air) - have_air = nb.content == CONTENT_AIR; + { + nb.light = getLight(ndef, nb.node); + nb.content = nb.node.getContent(); + const auto params = type_params.at(nbh[D_SELF].content); + nb.is_my_leaves = is_self || nb.content == nbh[D_SELF].content; + nb.cf = (ContentFeatures *)&ndef->get(nb.content); + nb.is_tree = nb.cf->groups.contains("tree"); + nb.is_any_leaves = nb.cf->groups.contains("leaves"); + nb.is_liquid = nb.cf->groups.contains("liquid"); + nb.water_level = nb.is_my_leaves ? get_leaves_water_level(nb.node) + : nb.is_tree ? get_tree_water_level(nb.node, + params.tree_water_param2) + : 0; + top_is_full_liquid = + nb.top && nb.is_liquid && + nb.node.getMaxLevel(ndef) == nb.node.getLevel(ndef); + + if (is_self) { + allow_grow_fruit = leaves_to_fruit.contains(nbh[D_SELF].content); + + c_fruit = allow_grow_fruit + ? leaves_to_fruit.at(nbh[D_SELF].content) + : CONTENT_IGNORE; + } else { + if ((nb.content == c_fruit) || + (!nb.top && !nb.bottom && !nb.is_any_leaves)) { + allow_grow_fruit = false; + } + + if (nb.is_tree) // no fruit near tree + { + allow_grow_fruit = false; + } + + if (!have_tree_or_soil) { + have_tree_or_soil = nb.is_tree || nb.is_any_leaves || + nb.cf->groups.contains("soil") || + nb.is_liquid; + } + if (!have_not_leaves && !nb.is_any_leaves) { + ++have_not_leaves; + } + } } - NEXT: ++i; } @@ -842,8 +949,9 @@ class GrowLeaves : public ActiveBlockModifier for (auto &i : grow_order) { auto &nb = nbh[i]; - if (!nb.node) + if (!nb.node) { continue; + } /*todo: shapes: o sphere @@ -860,9 +968,22 @@ class GrowLeaves : public ActiveBlockModifier can_grow_leaves(params, n_water_level, nb.top, nb.bottom) && nb.light >= params.leaves_grow_light_min && nb.cf->buildable_to && !nb.is_liquid) { - //if (grow_debug)DUMP("lv->lv ", p.X, p.Y, p.Z, nb.content, c, l, n_water_level,n_water_level_orig, l, ndef->get(nb.content).name); - map->setNode(nb.pos, {nbh[D_SELF].content, nb.node.getParam1(), 2}); - n_water_level -= 2; + uint8_t water_transfer = 0; + // Leaves grow should cost 2 wates, nobody knows why + if (n_water_level > 1) { + ++water_transfer; + --n_water_level; + } + if (n_water_level > 1) { + ++water_transfer; + --n_water_level; + } + if (water_transfer <= 0) { + break; + } + //if (grow_debug)DUMP("lv->lv ", p.X, p.Y, p.Z, nb.content, c, l, n_water_level,n_water_level_orig, water_transfer, ndef->get(nb.content).name); + map->setNode(nb.pos, + {nbh[D_SELF].content, nb.node.getParam1(), water_transfer}); if (!myrand_range(0, 10)) if (const auto block = map->getBlock(getNodeBlockPos(nb.pos)); @@ -893,12 +1014,14 @@ class GrowLeaves : public ActiveBlockModifier ++i; } - const auto can_decrease = nbh[D_SELF].light < LIGHT_SUN - 1; - if (n_water_level > 1 && can_decrease && + // Slowly evaporate water and kill leaves with water_level==1 + const auto can_decay = !have_not_leaves && nbh[D_SELF].light < LIGHT_SUN - 1; + if (n_water_level > 1 && can_decay && (!myrand_range(0, 10 * (grow_debug_fast ? 1 : 10)))) { float humidity = map->updateBlockHumidity(env, pos); - if (humidity < params.tree_get_water_from_humidity) + if (humidity < params.tree_get_water_from_humidity) { --n_water_level; + } } // DUMP(allow_grow_fruit, n_water_level, leaves_to_fruit_water_min, heat, leaves_to_fruit_heat_min); @@ -908,10 +1031,10 @@ class GrowLeaves : public ActiveBlockModifier (grow_debug_fast || !myrand_range(0, params.leaves_to_fruit_chance))) { map->setNode(pos, {c_fruit}); } else if ( - (n_water_level == 1 && can_decrease && + (n_water_level == 1 && can_decay && (!myrand_range(0, 30 * (grow_debug_fast ? 1 : 10)))) || (n_water_level >= 1 && // dont touch old static trees - have_air && + !have_not_leaves && ((nbh[D_SELF].light < params.leaves_die_light_max && (nbh[D_SELF].light > 0 || activate || !myrand_range(0, params.leaves_die_chance))) || diff --git a/src/mapgen/mapgen_indev.cpp b/src/mapgen/mapgen_indev.cpp index c563673f4..5e857894c 100644 --- a/src/mapgen/mapgen_indev.cpp +++ b/src/mapgen/mapgen_indev.cpp @@ -165,10 +165,10 @@ MapgenIndev::MapgenIndev(MapgenIndevParams *params, EmergeParams *emerge) floatland_ywater = params->floatland_ywater; - noise_layers = new Noise(&sp->np_layers, seed, csize.X, csize.Y + y_offset * 2, csize.Z); + noise_layers = new Noise(&sp->np_layers, seed, csize.X, csize.Y + y_offset * 2 + 2, csize.Z); layers_init(emerge, sp->paramsj); - noise_cave_indev = new Noise(&sp->np_cave_indev, seed, csize.X, csize.Y + y_offset * 2, csize.Z); + noise_cave_indev = new Noise(&sp->np_cave_indev, seed, csize.X, csize.Y + y_offset * 2 + 2, csize.Z); if (spflags & MGV6_FLOATLANDS) { diff --git a/src/mapgen/mapgen_v5.cpp b/src/mapgen/mapgen_v5.cpp index bc266017b..a229c10fe 100644 --- a/src/mapgen/mapgen_v5.cpp +++ b/src/mapgen/mapgen_v5.cpp @@ -78,7 +78,7 @@ MapgenV5::MapgenV5(MapgenV5Params *params, EmergeParams *emerge) noise_float_islands2 = new Noise(¶ms->np_float_islands2, seed, csize.X, csize.Y + y_offset * 2, csize.Z); noise_float_islands3 = new Noise(¶ms->np_float_islands3, seed, csize.X, csize.Z); - noise_layers = new Noise(¶ms->np_layers, seed, csize.X, csize.Y + y_offset * 2, csize.Z); + noise_layers = new Noise(¶ms->np_layers, seed, csize.X, csize.Y + y_offset * 2 + 2, csize.Z); layers_init(emerge, params->paramsj); //noise_cave_indev = new Noise(&sp->np_cave_indev, seed, csize.X, csize.Y + y_offset * 2, csize.Z); diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index 3c690c1e4..3fc3de017 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -131,9 +131,9 @@ MapgenV7::MapgenV7(MapgenV7Params *params, EmergeParams *emerge) //noise_float_islands2 = new Noise(¶ms->np_float_islands2, seed, csize.X, csize.Y + y_offset * 2, csize.Z); //noise_float_islands3 = new Noise(¶ms->np_float_islands3, seed, csize.X, csize.Z); - noise_layers = new Noise(¶ms->np_layers, seed, csize.X, csize.Y + y_offset * 2, csize.Z); + noise_layers = new Noise(¶ms->np_layers, seed, csize.X, csize.Y + y_offset * 2 + 2, csize.Z); layers_init(emerge, params->paramsj); - noise_cave_indev = new Noise(¶ms->np_cave_indev, seed, csize.X, csize.Y + y_offset * 2, csize.Z); + noise_cave_indev = new Noise(¶ms->np_cave_indev, seed, csize.X, csize.Y + y_offset * 2 + 2, csize.Z); //========== diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index d47e289b8..e0a7ea153 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -1703,7 +1703,7 @@ void read_groups(lua_State *L, int index, ItemGroupList &result) std::string name = luaL_checkstring(L, -2); int rating = luaL_checkinteger(L, -1); // zero rating indicates not in the group - if (rating != 0) + //fm: wtf? if (rating != 0) result[name] = rating; // removes value, keeps key for next iteration lua_pop(L, 1); diff --git a/src/server.cpp b/src/server.cpp index ab7deab25..e425fa039 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -264,7 +264,6 @@ Server::Server( CONNECTION_TIMEOUT, m_bind_addr.isIPv6(), this)), - stat(path_world), m_itemdef(createItemDefManager()), m_nodedef(createNodeDefManager()), m_craftdef(createCraftDefManager()), @@ -272,6 +271,7 @@ Server::Server( m_clients(m_con), m_admin_chat(iface), m_on_shutdown_errmsg(on_shutdown_errmsg), + stat(path_world), m_modchannel_mgr(new ModChannelMgr()) { #if ENABLE_THREADS diff --git a/src/voxelalgorithms.cpp b/src/voxelalgorithms.cpp index 2a0f14054..177eb36cd 100644 --- a/src/voxelalgorithms.cpp +++ b/src/voxelalgorithms.cpp @@ -866,23 +866,23 @@ void is_sunlight_above_block(Map *map, mapblock_v3 pos, light[z][x] = above.getLight(LIGHTBANK_DAY, above_f) == LIGHT_SUN; if (!light[z][x]) { - auto p = source_block->getPosRelative(); + v3pos_t p; bool go = false; if (x == 0) { - p += v3pos_t(x - 1, 0, z); + p = v3pos_t(x - 1, 0, z); go = true; } else if (z == 0) { - p += v3pos_t(x, 0, z - 1); + p = v3pos_t(x, 0, z - 1); go = true; } else if (z == MAP_BLOCKSIZE - 1) { - p += v3pos_t(x, 0, z + 1); + p = v3pos_t(x, 0, z + 1); go = true; } else if (x == MAP_BLOCKSIZE - 1) { - p += v3pos_t(x + 1, 0, z); + p = v3pos_t(x + 1, 0, z); go = true; } if (go) { - const auto n = map->getNode(p); + const auto n = map->getNode(p + source_block->getPosRelative()); if (n.getLight(LIGHTBANK_DAY, ndef->getLightingFlags(n)) == LIGHT_SUN) light[z][x] = true; } diff --git a/util/autotest/auto.pl b/util/autotest/auto.pl index 510832e5a..d541c25c4 100755 --- a/util/autotest/auto.pl +++ b/util/autotest/auto.pl @@ -413,7 +413,7 @@ () sy qq{$config->{env} $config->{runner} @_ ./freeminer --run-unittests --logfile $config->{logdir}/autotest.$g->{task_name}.test.log } . options_make([qw(verbose trace)]); }, set_bot => {'----bot' => 1, '----bot_random' => 1}, - run_bot => ['set_bot', 'run_single'], + run_bot => ['set_bot', 'set_client', 'run_single'], run_single_tsan => sub { local $config->{options_display} = 'software' if $config->{tsan_opengl_fix} and !$config->{options_display}; local $config->{cmake_leveldb} //= 0 if $config->{tsan_leveldb_fix}; @@ -488,8 +488,8 @@ () fail => sub { warn 'fail:', join ' ', @_; }, - set_client => [{-no_build_client => 0, -no_build_server => 1,}], - set_server => [{-no_build_client => 1, -no_build_server => 0, -options_add => 'no_exit'}], + set_client => [{'---no_build_client' => 0, '---no_build_server' => 1,}], + set_server => [{'---no_build_client' => 1, '---no_build_server' => 0, -options_add => 'no_exit'}], }; our $tasks = { @@ -693,6 +693,7 @@ () ++$g->{keep_config}; $config->{runner} = $config->{runner} + . ' ASAN_OPTIONS=abort_on_error=1 ' . $config->{gdb} . q{ -ex 'run' -ex 't a a bt' } . ($config->{gdb_stay} ? '' : q{ -ex 'cont' -ex 'quit' })