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' })