Skip to content

Commit 0bbbc6e

Browse files
committedJan 7, 2016
Liquids: Flow into and destroy 'floodable' nodes
Add new node property 'floodable', default false Define "air" as floodable = true in C++ and lua
1 parent bd40ee2 commit 0bbbc6e

File tree

7 files changed

+49
-32
lines changed

7 files changed

+49
-32
lines changed
 

Diff for: ‎builtin/game/item.lua

+1
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ core.nodedef_default = {
574574
diggable = true,
575575
climbable = false,
576576
buildable_to = false,
577+
floodable = false,
577578
liquidtype = "none",
578579
liquid_alternative_flowing = "",
579580
liquid_alternative_source = "",

Diff for: ‎builtin/game/register.lua

+1
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ core.register_node(":air", {
289289
pointable = false,
290290
diggable = false,
291291
buildable_to = true,
292+
floodable = true,
292293
air_equivalent = true,
293294
drop = "",
294295
groups = {not_in_creative_inventory=1},

Diff for: ‎doc/lua_api.txt

+1
Original file line numberDiff line numberDiff line change
@@ -3396,6 +3396,7 @@ Definition tables
33963396
diggable = true, -- If false, can never be dug
33973397
climbable = false, -- If true, can be climbed on (ladder)
33983398
buildable_to = false, -- If true, placed nodes can replace this node
3399+
floodable = false, -- If true, liquids flow into and replace this node
33993400
liquidtype = "none", -- "none"/"source"/"flowing"
34003401
liquid_alternative_flowing = "", -- Flowing version of source liquid
34013402
liquid_alternative_source = "", -- Source version of flowing liquid

Diff for: ‎src/map.cpp

+38-32
Original file line numberDiff line numberDiff line change
@@ -1654,10 +1654,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
16541654
loop_max *= m_transforming_liquid_loop_count_multiplier;
16551655
#endif
16561656

1657-
while(m_transforming_liquid.size() != 0)
1657+
while (m_transforming_liquid.size() != 0)
16581658
{
16591659
// This should be done here so that it is done when continue is used
1660-
if(loopcount >= initial_size || loopcount >= loop_max)
1660+
if (loopcount >= initial_size || loopcount >= loop_max)
16611661
break;
16621662
loopcount++;
16631663

@@ -1674,21 +1674,24 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
16741674
*/
16751675
s8 liquid_level = -1;
16761676
content_t liquid_kind = CONTENT_IGNORE;
1677-
LiquidType liquid_type = nodemgr->get(n0).liquid_type;
1677+
content_t floodable_node = CONTENT_AIR;
1678+
ContentFeatures cf = nodemgr->get(n0);
1679+
LiquidType liquid_type = cf.liquid_type;
16781680
switch (liquid_type) {
16791681
case LIQUID_SOURCE:
16801682
liquid_level = LIQUID_LEVEL_SOURCE;
1681-
liquid_kind = nodemgr->getId(nodemgr->get(n0).liquid_alternative_flowing);
1683+
liquid_kind = nodemgr->getId(cf.liquid_alternative_flowing);
16821684
break;
16831685
case LIQUID_FLOWING:
16841686
liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
16851687
liquid_kind = n0.getContent();
16861688
break;
16871689
case LIQUID_NONE:
1688-
// if this is an air node, it *could* be transformed into a liquid. otherwise,
1689-
// continue with the next node.
1690-
if (n0.getContent() != CONTENT_AIR)
1690+
// if this node is 'floodable', it *could* be transformed
1691+
// into a liquid, otherwise, continue with the next node.
1692+
if (!cf.floodable)
16911693
continue;
1694+
floodable_node = n0.getContent();
16921695
liquid_kind = CONTENT_AIR;
16931696
break;
16941697
}
@@ -1718,9 +1721,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
17181721
}
17191722
v3s16 npos = p0 + dirs[i];
17201723
NodeNeighbor nb(getNodeNoEx(npos), nt, npos);
1724+
ContentFeatures cfnb = nodemgr->get(nb.n);
17211725
switch (nodemgr->get(nb.n.getContent()).liquid_type) {
17221726
case LIQUID_NONE:
1723-
if (nb.n.getContent() == CONTENT_AIR) {
1727+
if (cfnb.floodable) {
17241728
airs[num_airs++] = nb;
17251729
// if the current node is a water source the neighbor
17261730
// should be enqueded for transformation regardless of whether the
@@ -1738,8 +1742,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
17381742
case LIQUID_SOURCE:
17391743
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
17401744
if (liquid_kind == CONTENT_AIR)
1741-
liquid_kind = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing);
1742-
if (nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing) != liquid_kind) {
1745+
liquid_kind = nodemgr->getId(cfnb.liquid_alternative_flowing);
1746+
if (nodemgr->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
17431747
neutrals[num_neutrals++] = nb;
17441748
} else {
17451749
// Do not count bottom source, it will screw things up
@@ -1750,8 +1754,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
17501754
case LIQUID_FLOWING:
17511755
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
17521756
if (liquid_kind == CONTENT_AIR)
1753-
liquid_kind = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing);
1754-
if (nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing) != liquid_kind) {
1757+
liquid_kind = nodemgr->getId(cfnb.liquid_alternative_flowing);
1758+
if (nodemgr->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
17551759
neutrals[num_neutrals++] = nb;
17561760
} else {
17571761
flows[num_flows++] = nb;
@@ -1770,8 +1774,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
17701774
s8 max_node_level = -1;
17711775

17721776
u8 range = nodemgr->get(liquid_kind).liquid_range;
1773-
if (range > LIQUID_LEVEL_MAX+1)
1774-
range = LIQUID_LEVEL_MAX+1;
1777+
if (range > LIQUID_LEVEL_MAX + 1)
1778+
range = LIQUID_LEVEL_MAX + 1;
17751779

17761780
if ((num_sources >= 2 && nodemgr->get(liquid_kind).liquid_renewable) || liquid_type == LIQUID_SOURCE) {
17771781
// liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
@@ -1780,10 +1784,11 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
17801784
new_node_content = nodemgr->getId(nodemgr->get(liquid_kind).liquid_alternative_source);
17811785
} else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) {
17821786
// liquid_kind is set properly, see above
1783-
new_node_content = liquid_kind;
17841787
max_node_level = new_node_level = LIQUID_LEVEL_MAX;
1785-
if (new_node_level < (LIQUID_LEVEL_MAX+1-range))
1786-
new_node_content = CONTENT_AIR;
1788+
if (new_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
1789+
new_node_content = liquid_kind;
1790+
else
1791+
new_node_content = floodable_node;
17871792
} else {
17881793
// no surrounding sources, so get the maximum level that can flow into this node
17891794
for (u16 i = 0; i < num_flows; i++) {
@@ -1794,16 +1799,16 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
17941799
max_node_level = LIQUID_LEVEL_MAX;
17951800
if (nb_liquid_level + WATER_DROP_BOOST < LIQUID_LEVEL_MAX)
17961801
max_node_level = nb_liquid_level + WATER_DROP_BOOST;
1797-
} else if (nb_liquid_level > max_node_level)
1802+
} else if (nb_liquid_level > max_node_level) {
17981803
max_node_level = nb_liquid_level;
1804+
}
17991805
break;
18001806
case NEIGHBOR_LOWER:
18011807
break;
18021808
case NEIGHBOR_SAME_LEVEL:
18031809
if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
1804-
nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level) {
1810+
nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level)
18051811
max_node_level = nb_liquid_level - 1;
1806-
}
18071812
break;
18081813
}
18091814
}
@@ -1821,23 +1826,25 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
18211826
new_node_level = liquid_level + 1;
18221827
if (new_node_level != max_node_level)
18231828
must_reflow.push_back(p0);
1824-
} else
1829+
} else {
18251830
new_node_level = max_node_level;
1831+
}
18261832

1827-
if (max_node_level >= (LIQUID_LEVEL_MAX+1-range))
1833+
if (max_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
18281834
new_node_content = liquid_kind;
18291835
else
1830-
new_node_content = CONTENT_AIR;
1836+
new_node_content = floodable_node;
18311837

18321838
}
18331839

18341840
/*
18351841
check if anything has changed. if not, just continue with the next node.
18361842
*/
1837-
if (new_node_content == n0.getContent() && (nodemgr->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
1838-
((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
1839-
((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
1840-
== flowing_down)))
1843+
if (new_node_content == n0.getContent() &&
1844+
(nodemgr->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
1845+
((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
1846+
((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
1847+
== flowing_down)))
18411848
continue;
18421849

18431850

@@ -1857,11 +1864,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
18571864

18581865
// Find out whether there is a suspect for this action
18591866
std::string suspect;
1860-
if(m_gamedef->rollback()) {
1867+
if (m_gamedef->rollback())
18611868
suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
1862-
}
18631869

1864-
if(m_gamedef->rollback() && !suspect.empty()){
1870+
if (m_gamedef->rollback() && !suspect.empty()) {
18651871
// Blame suspect
18661872
RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
18671873
// Get old node for rollback
@@ -1880,10 +1886,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
18801886

18811887
v3s16 blockpos = getNodeBlockPos(p0);
18821888
MapBlock *block = getBlockNoCreateNoEx(blockpos);
1883-
if(block != NULL) {
1889+
if (block != NULL) {
18841890
modified_blocks[blockpos] = block;
18851891
// If new or old node emits light, MapBlock requires lighting update
1886-
if(nodemgr->get(n0).light_source != 0 ||
1892+
if (nodemgr->get(n0).light_source != 0 ||
18871893
nodemgr->get(n00).light_source != 0)
18881894
lighting_modified_blocks[block->getPos()] = block;
18891895
}

Diff for: ‎src/nodedef.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ void ContentFeatures::reset()
233233
diggable = true;
234234
climbable = false;
235235
buildable_to = false;
236+
floodable = false;
236237
rightclickable = true;
237238
leveled = 0;
238239
liquid_type = LIQUID_NONE;
@@ -318,6 +319,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
318319
// the protocol version
319320
os<<serializeString(mesh);
320321
collision_box.serialize(os, protocol_version);
322+
writeU8(os, floodable);
321323
}
322324

323325
void ContentFeatures::deSerialize(std::istream &is)
@@ -388,6 +390,7 @@ void ContentFeatures::deSerialize(std::istream &is)
388390
// otherwise changes the protocol version
389391
mesh = deSerializeString(is);
390392
collision_box.deSerialize(is);
393+
floodable = readU8(is);
391394
}catch(SerializationError &e) {};
392395
}
393396

@@ -520,6 +523,7 @@ void CNodeDefManager::clear()
520523
f.pointable = false;
521524
f.diggable = false;
522525
f.buildable_to = true;
526+
f.floodable = true;
523527
f.is_ground_content = true;
524528
// Insert directly into containers
525529
content_t c = CONTENT_AIR;

Diff for: ‎src/nodedef.h

+2
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ struct ContentFeatures
229229
bool climbable;
230230
// Player can build on these
231231
bool buildable_to;
232+
// Liquids flow into and replace node
233+
bool floodable;
232234
// Player cannot build to these (placement prediction disabled)
233235
bool rightclickable;
234236
// Flowing liquid or snow, value = default level

Diff for: ‎src/script/common/c_content.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,8 @@ ContentFeatures read_content_features(lua_State *L, int index)
481481
getboolfield(L, index, "climbable", f.climbable);
482482
// Player can build on these
483483
getboolfield(L, index, "buildable_to", f.buildable_to);
484+
// Liquids flow into and replace node
485+
getboolfield(L, index, "floodable", f.floodable);
484486
// Whether the node is non-liquid, source liquid or flowing liquid
485487
f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
486488
ScriptApiNode::es_LiquidType, LIQUID_NONE);

0 commit comments

Comments
 (0)
Please sign in to comment.