mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
new adjustable finite liquid
This commit is contained in:
parent
9bd76f2972
commit
b90e431fc7
@ -27,7 +27,7 @@ minetest.register_alias("mapgen_mese", "default:mese")
|
|||||||
-- Ore generation
|
-- Ore generation
|
||||||
--
|
--
|
||||||
|
|
||||||
local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume, ore_per_chunk, height_min, height_max)
|
local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume, ore_per_chunk, height_min, height_max, param2)
|
||||||
if maxp.y < height_min or minp.y > height_max then
|
if maxp.y < height_min or minp.y > height_max then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -57,7 +57,7 @@ local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume,
|
|||||||
local z2 = z0+z1
|
local z2 = z0+z1
|
||||||
local p2 = {x=x2, y=y2, z=z2}
|
local p2 = {x=x2, y=y2, z=z2}
|
||||||
if minetest.env:get_node(p2).name == wherein then
|
if minetest.env:get_node(p2).name == wherein then
|
||||||
minetest.env:set_node(p2, {name=name})
|
minetest.env:set_node(p2, {name=name, param2=param2})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -110,5 +110,11 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if minetest.setting_get("liquid_finite") then
|
||||||
|
generate_ore("default:water_source", "default:stone", minp, maxp, seed+42, 1/24/24/24, 4, -100, -10, 128)
|
||||||
|
generate_ore("default:water_source", "default:stone", minp, maxp, seed+42, 1/28/28/28, 3, -10000, -101, 128)
|
||||||
|
generate_ore("default:lava_source", "default:stone", minp, maxp, seed+43, 1/38/38/38, 2, -500, -100, 128)
|
||||||
|
generate_ore("default:lava_source", "default:stone", minp, maxp, seed+43, 1/30/30/30, 4, -31000, -501, 128)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -90,6 +90,14 @@
|
|||||||
#enable_fog = true
|
#enable_fog = true
|
||||||
# Enable a bit lower water surface; disable for speed (not quite optimized)
|
# Enable a bit lower water surface; disable for speed (not quite optimized)
|
||||||
#new_style_water = false
|
#new_style_water = false
|
||||||
|
# Constant volume liquids
|
||||||
|
#liquid_finite = false
|
||||||
|
# Update liquids every .. recommend for finite: 0.2
|
||||||
|
#liquid_update = 1.0
|
||||||
|
# When finite liquid: relax flowing blocks to source if level near max and N nearby source blocks, more realistic, but not true constant. values: 0,1,2,3,4 : 0 - disable, 1 - most aggresive
|
||||||
|
#liquid_relax = 1
|
||||||
|
# optimization: faster cave flood (and not true constant)
|
||||||
|
#liquid_fast_flood = 1
|
||||||
# Enable nice leaves; disable for speed
|
# Enable nice leaves; disable for speed
|
||||||
#new_style_leaves = true
|
#new_style_leaves = true
|
||||||
# Enable smooth lighting with simple ambient occlusion;
|
# Enable smooth lighting with simple ambient occlusion;
|
||||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "mapblock.h" // For getNodeBlockPos
|
#include "mapblock.h" // For getNodeBlockPos
|
||||||
#include "treegen.h" // For treegen::make_tree
|
#include "treegen.h" // For treegen::make_tree
|
||||||
|
#include "main.h" // for g_settings
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
@ -146,11 +147,42 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LiquidFlowABM : public ActiveBlockModifier
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::set<std::string> contents;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr)
|
||||||
|
{
|
||||||
|
std::set<content_t> liquids;
|
||||||
|
nodemgr->getIds("group:liquid", liquids);
|
||||||
|
for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
|
||||||
|
contents.insert(nodemgr->get(*k).liquid_alternative_flowing);
|
||||||
|
|
||||||
|
}
|
||||||
|
virtual std::set<std::string> getTriggerContents()
|
||||||
|
{
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
virtual float getTriggerInterval()
|
||||||
|
{ return 10.0; }
|
||||||
|
virtual u32 getTriggerChance()
|
||||||
|
{ return 10; }
|
||||||
|
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
|
||||||
|
{
|
||||||
|
ServerMap *map = &env->getServerMap();
|
||||||
|
if (map->transforming_liquid_size() < 500)
|
||||||
|
map->transforming_liquid_add(p);
|
||||||
|
//if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
|
void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
|
||||||
{
|
{
|
||||||
env->addActiveBlockModifier(new GrowGrassABM());
|
env->addActiveBlockModifier(new GrowGrassABM());
|
||||||
env->addActiveBlockModifier(new RemoveGrassABM());
|
env->addActiveBlockModifier(new RemoveGrassABM());
|
||||||
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
|
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
|
||||||
|
if (g_settings->getBool("liquid_finite"))
|
||||||
|
env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
level = (-0.5+node_liquid_level) * BS;
|
level = (-0.5+node_liquid_level) * BS;
|
||||||
else if(n2.getContent() == c_flowing)
|
else if(n2.getContent() == c_flowing)
|
||||||
level = (-0.5 + ((float)(n2.param2&LIQUID_LEVEL_MASK)
|
level = (-0.5 + ((float)(n2.param2&LIQUID_LEVEL_MASK)
|
||||||
+ 0.5) / 8.0 * node_liquid_level) * BS;
|
+ 0.5) / (float)LIQUID_LEVEL_SOURCE * node_liquid_level) * BS;
|
||||||
|
|
||||||
// Check node above neighbor.
|
// Check node above neighbor.
|
||||||
// NOTE: This doesn't get executed if neighbor
|
// NOTE: This doesn't get executed if neighbor
|
||||||
@ -324,7 +324,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(air_count >= 2)
|
if(air_count >= 2)
|
||||||
cornerlevel = -0.5*BS;
|
cornerlevel = -0.5*BS+0.1;
|
||||||
else if(valid_count > 0)
|
else if(valid_count > 0)
|
||||||
cornerlevel /= valid_count;
|
cornerlevel /= valid_count;
|
||||||
corner_levels[i] = cornerlevel;
|
corner_levels[i] = cornerlevel;
|
||||||
|
@ -201,6 +201,11 @@ void set_default_settings(Settings *settings)
|
|||||||
//mapgen related things
|
//mapgen related things
|
||||||
settings->setDefault("mg_name", "v6");
|
settings->setDefault("mg_name", "v6");
|
||||||
settings->setDefault("water_level", "1");
|
settings->setDefault("water_level", "1");
|
||||||
|
settings->setDefault("liquid_finite", "false");
|
||||||
|
settings->setDefault("liquid_update", "1.0");
|
||||||
|
settings->setDefault("liquid_relax", "1");
|
||||||
|
settings->setDefault("liquid_fast_flood", "1");
|
||||||
|
|
||||||
settings->setDefault("chunksize", "5");
|
settings->setDefault("chunksize", "5");
|
||||||
settings->setDefault("mg_flags", "trees, caves, v6_biome_blend");
|
settings->setDefault("mg_flags", "trees, caves, v6_biome_blend");
|
||||||
settings->setDefault("mgv6_freq_desert", "0.45");
|
settings->setDefault("mgv6_freq_desert", "0.45");
|
||||||
|
312
src/map.cpp
312
src/map.cpp
@ -1613,10 +1613,322 @@ struct NodeNeighbor {
|
|||||||
MapNode n;
|
MapNode n;
|
||||||
NeighborType t;
|
NeighborType t;
|
||||||
v3s16 p;
|
v3s16 p;
|
||||||
|
bool l; //can liquid
|
||||||
|
bool i; //infinity
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Map::transforming_liquid_add(v3s16 p) {
|
||||||
|
m_transforming_liquid.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Map::transforming_liquid_size() {
|
||||||
|
return m_transforming_liquid.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const v3s16 g_7dirs[7] =
|
||||||
|
{
|
||||||
|
// +right, +top, +back
|
||||||
|
v3s16( 0,-1, 0), // bottom
|
||||||
|
v3s16( 0, 0, 0), // self
|
||||||
|
v3s16( 0, 0, 1), // back
|
||||||
|
v3s16( 0, 0,-1), // front
|
||||||
|
v3s16( 1, 0, 0), // right
|
||||||
|
v3s16(-1, 0, 0), // left
|
||||||
|
v3s16( 0, 1, 0) // top
|
||||||
|
};
|
||||||
|
|
||||||
|
#define D_BOTTOM 0
|
||||||
|
#define D_TOP 6
|
||||||
|
#define D_SELF 1
|
||||||
|
|
||||||
|
void Map::transformLiquidsFinite(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||||
|
{
|
||||||
|
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||||
|
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
//TimeTaker timer("transformLiquids()");
|
||||||
|
|
||||||
|
u32 loopcount = 0;
|
||||||
|
u32 initial_size = m_transforming_liquid.size();
|
||||||
|
|
||||||
|
u8 relax = g_settings->getS16("liquid_relax");
|
||||||
|
bool fast_flood = g_settings->getS16("liquid_fast_flood");
|
||||||
|
int water_level = g_settings->getS16("water_level");
|
||||||
|
|
||||||
|
/*if(initial_size != 0)
|
||||||
|
infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
|
||||||
|
|
||||||
|
// list of nodes that due to viscosity have not reached their max level height
|
||||||
|
UniqueQueue<v3s16> must_reflow, must_reflow_second;
|
||||||
|
|
||||||
|
// List of MapBlocks that will require a lighting update (due to lava)
|
||||||
|
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
||||||
|
|
||||||
|
while(m_transforming_liquid.size() > 0)
|
||||||
|
{
|
||||||
|
// This should be done here so that it is done when continue is used
|
||||||
|
if(loopcount >= initial_size || loopcount >= 1000)
|
||||||
|
break;
|
||||||
|
loopcount++;
|
||||||
|
/*
|
||||||
|
Get a queued transforming liquid node
|
||||||
|
*/
|
||||||
|
v3s16 p0 = m_transforming_liquid.pop_front();
|
||||||
|
u16 total_level = 0;
|
||||||
|
NodeNeighbor neighbors[7]; // surrounding flowing liquid nodes
|
||||||
|
s8 liquid_levels[7] = {-1, -1, -1, -1, -1, -1, -1}; // current level of every block
|
||||||
|
s8 liquid_levels_want[7] = {-1, -1, -1, -1, -1, -1, -1}; // target levels
|
||||||
|
s8 can_liquid_same_level = 0;
|
||||||
|
content_t liquid_kind = CONTENT_IGNORE;
|
||||||
|
content_t liquid_kind_flowing = CONTENT_IGNORE;
|
||||||
|
/*
|
||||||
|
Collect information about the environment
|
||||||
|
*/
|
||||||
|
const v3s16 *dirs = g_7dirs;
|
||||||
|
for (u16 i = 0; i < 7; i++) {
|
||||||
|
NeighborType nt = NEIGHBOR_SAME_LEVEL;
|
||||||
|
switch (i) {
|
||||||
|
case D_TOP:
|
||||||
|
nt = NEIGHBOR_UPPER;
|
||||||
|
break;
|
||||||
|
case D_BOTTOM:
|
||||||
|
nt = NEIGHBOR_LOWER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v3s16 npos = p0 + dirs[i];
|
||||||
|
|
||||||
|
neighbors[i].n = getNodeNoEx(npos);
|
||||||
|
neighbors[i].t = nt;
|
||||||
|
neighbors[i].p = npos;
|
||||||
|
neighbors[i].l = 0;
|
||||||
|
neighbors[i].i = 0;
|
||||||
|
NodeNeighbor & nb = neighbors[i];
|
||||||
|
|
||||||
|
switch (nodemgr->get(nb.n.getContent()).liquid_type) {
|
||||||
|
case LIQUID_NONE:
|
||||||
|
if (nb.n.getContent() == CONTENT_AIR) {
|
||||||
|
liquid_levels[i] = 0;
|
||||||
|
nb.l = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LIQUID_SOURCE:
|
||||||
|
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
|
||||||
|
if (liquid_kind_flowing == CONTENT_IGNORE)
|
||||||
|
liquid_kind_flowing = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing);
|
||||||
|
if (liquid_kind == CONTENT_IGNORE)
|
||||||
|
liquid_kind = nb.n.getContent();
|
||||||
|
if (nb.n.getContent() == liquid_kind) {
|
||||||
|
liquid_levels[i] = LIQUID_LEVEL_SOURCE;
|
||||||
|
nb.l = 1;
|
||||||
|
nb.i = (nb.n.param2 & LIQUID_INFINITY_MASK);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LIQUID_FLOWING:
|
||||||
|
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
|
||||||
|
if (liquid_kind_flowing == CONTENT_IGNORE)
|
||||||
|
liquid_kind_flowing = nb.n.getContent();
|
||||||
|
if (liquid_kind == CONTENT_IGNORE)
|
||||||
|
liquid_kind = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_source);
|
||||||
|
if (nb.n.getContent() == liquid_kind_flowing) {
|
||||||
|
liquid_levels[i] = (nb.n.param2 & LIQUID_LEVEL_MASK);
|
||||||
|
nb.l = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nb.l && nb.t == NEIGHBOR_SAME_LEVEL) ++can_liquid_same_level;
|
||||||
|
if (liquid_levels[i] > 0) total_level += liquid_levels[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
infostream << "get node i=" <<(int)i<<" " << PP(npos) << " c="<<nb.n.getContent() <<" p0="<< (int)nb.n.param0 <<" p1="<< (int)nb.n.param1 <<" p2="<< (int)nb.n.param2 << " lt="<<nodemgr->get(nb.n.getContent()).liquid_type
|
||||||
|
//<< " lk=" << liquid_kind << " lkf=" << liquid_kind_flowing
|
||||||
|
<< " l="<< nb.l << " inf="<< nb.i << " nlevel=" << (int)liquid_levels[i] << " tlevel=" << (int)total_level << " cansame="<<(int)can_liquid_same_level<<std::endl;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (liquid_kind == CONTENT_IGNORE || !neighbors[D_SELF].l || total_level <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// fill bottom block
|
||||||
|
if (neighbors[D_BOTTOM].l) {
|
||||||
|
liquid_levels_want[D_BOTTOM] = total_level > LIQUID_LEVEL_SOURCE ? LIQUID_LEVEL_SOURCE : total_level;
|
||||||
|
total_level -= liquid_levels_want[D_BOTTOM];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relax && p0.Y <= water_level && liquid_levels[D_TOP] == 0 && total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level - can_liquid_same_level + 2 && can_liquid_same_level >= relax + 1) { //relax up
|
||||||
|
total_level = LIQUID_LEVEL_SOURCE * can_liquid_same_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate self level 5 blocks
|
||||||
|
u8 want_level =
|
||||||
|
total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level
|
||||||
|
? LIQUID_LEVEL_SOURCE
|
||||||
|
: total_level / can_liquid_same_level;
|
||||||
|
total_level -= want_level * can_liquid_same_level;
|
||||||
|
|
||||||
|
if (relax && p0.Y > water_level && liquid_levels[D_TOP] == 0 && liquid_levels[D_BOTTOM] == LIQUID_LEVEL_SOURCE && want_level == 0 && total_level <= can_liquid_same_level - 2 && can_liquid_same_level >= relax + 1) { //relax down
|
||||||
|
total_level = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u16 ii = D_SELF; ii < D_TOP; ++ii) { // fill only same level
|
||||||
|
if (!neighbors[ii].l)
|
||||||
|
continue;
|
||||||
|
liquid_levels_want[ii] = want_level;
|
||||||
|
if (liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE && total_level > 0
|
||||||
|
&& liquid_levels[ii] > liquid_levels_want[ii]
|
||||||
|
) {
|
||||||
|
++liquid_levels_want[ii];
|
||||||
|
--total_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u16 ii = 0; ii < 7; ++ii) {
|
||||||
|
if (total_level < 1) break;
|
||||||
|
if (liquid_levels_want[ii] >= 0 && liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE) {
|
||||||
|
++liquid_levels_want[ii];
|
||||||
|
--total_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill top block if can
|
||||||
|
if (neighbors[D_TOP].l) {
|
||||||
|
liquid_levels_want[D_TOP] = total_level > LIQUID_LEVEL_SOURCE ? LIQUID_LEVEL_SOURCE : total_level ;
|
||||||
|
total_level -= liquid_levels_want[D_TOP];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u16 ii = 0; ii < 7; ii++) // infinity and cave flood optimization
|
||||||
|
if (liquid_levels_want[ii] >= 0 &&
|
||||||
|
(neighbors[ii].i ||
|
||||||
|
(fast_flood && p0.Y < water_level &&
|
||||||
|
(initial_size >= 1000
|
||||||
|
&& ii != D_TOP
|
||||||
|
&& want_level >= LIQUID_LEVEL_SOURCE/4
|
||||||
|
&& can_liquid_same_level >= 5
|
||||||
|
&& liquid_levels[D_TOP] >= LIQUID_LEVEL_SOURCE))))
|
||||||
|
liquid_levels_want[ii] = LIQUID_LEVEL_SOURCE;
|
||||||
|
|
||||||
|
//if (total_level > 0 /*|| flowed != volume*/) infostream <<" AFTER level=" << (int)total_level /*<< " flowed="<<flowed<< " volume=" <<volume*/<< " wantsame="<<(int)want_level<< " top="<< (int)liquid_levels_want[D_TOP]<< " topwas="<< (int)liquid_levels[D_TOP]<< " bot="<< (int)liquid_levels_want[D_BOTTOM]<<std::endl;
|
||||||
|
|
||||||
|
u8 changed = 0;
|
||||||
|
for (u16 i = 0; i < 7; i++) {
|
||||||
|
if (liquid_levels_want[i] < 0 || !neighbors[i].l)
|
||||||
|
continue;
|
||||||
|
MapNode & n0 = neighbors[i].n;
|
||||||
|
p0 = neighbors[i].p;
|
||||||
|
/*
|
||||||
|
decide on the type (and possibly level) of the current node
|
||||||
|
*/
|
||||||
|
content_t new_node_content;
|
||||||
|
s8 new_node_level = -1;
|
||||||
|
u8 viscosity = nodemgr->get(liquid_kind).liquid_viscosity;
|
||||||
|
if (viscosity > 1 && liquid_levels_want[i] != liquid_levels[i]) {
|
||||||
|
// amount to gain, limited by viscosity
|
||||||
|
// must be at least 1 in absolute value
|
||||||
|
s8 level_inc = liquid_levels_want[i] - liquid_levels[i];
|
||||||
|
if (level_inc < -viscosity || level_inc > viscosity)
|
||||||
|
new_node_level = liquid_levels[i] + level_inc/viscosity;
|
||||||
|
else if (level_inc < 0)
|
||||||
|
new_node_level = liquid_levels[i] - 1;
|
||||||
|
else if (level_inc > 0)
|
||||||
|
new_node_level = liquid_levels[i] + 1;
|
||||||
|
} else
|
||||||
|
new_node_level = liquid_levels_want[i];
|
||||||
|
if (new_node_level >= LIQUID_LEVEL_SOURCE)
|
||||||
|
new_node_content = liquid_kind;
|
||||||
|
else if (new_node_level > 0)
|
||||||
|
new_node_content = liquid_kind_flowing;
|
||||||
|
else
|
||||||
|
new_node_content = CONTENT_AIR;
|
||||||
|
|
||||||
|
// last level must flow down on stairs
|
||||||
|
if (liquid_levels_want[i] != liquid_levels[i] && liquid_levels[D_TOP] <= 0 && !neighbors[D_BOTTOM].l && new_node_level >= 1 && new_node_level <= 2) //maybe == 1 //
|
||||||
|
for (u16 ii = D_SELF + 1; ii < D_TOP; ++ii) { // only same level
|
||||||
|
if (!neighbors[ii].l)
|
||||||
|
continue;
|
||||||
|
must_reflow_second.push_back(p0 + dirs[ii]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
check if anything has changed. if not, just continue with the next node.
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
new_node_content == n0.getContent()
|
||||||
|
&& (nodemgr->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
|
||||||
|
((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level
|
||||||
|
// &&((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)== flowing_down
|
||||||
|
))
|
||||||
|
&&
|
||||||
|
(nodemgr->get(n0.getContent()).liquid_type != LIQUID_SOURCE ||
|
||||||
|
(((n0.param2 & LIQUID_INFINITY_MASK) == LIQUID_INFINITY_MASK) == neighbors[i].i
|
||||||
|
))
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++changed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
update the current node
|
||||||
|
*/
|
||||||
|
if (nodemgr->get(new_node_content).liquid_type == LIQUID_FLOWING) {
|
||||||
|
// set level to last 3 bits, flowing down bit to 4th bit
|
||||||
|
n0.param2 = (new_node_level & LIQUID_LEVEL_MASK);
|
||||||
|
} else if (nodemgr->get(new_node_content).liquid_type == LIQUID_SOURCE) {
|
||||||
|
//n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
|
||||||
|
n0.param2 = (neighbors[i].i ? LIQUID_INFINITY_MASK : 0x00);
|
||||||
|
}
|
||||||
|
//infostream << "set node i=" <<(int)i<<" "<< PP(p0)<< " nc="<<new_node_content<< " p2="<<(int)n0.param2<< " nl="<<(int)new_node_level<<std::endl;
|
||||||
|
n0.setContent(new_node_content);
|
||||||
|
// Find out whether there is a suspect for this action
|
||||||
|
std::string suspect;
|
||||||
|
if(m_gamedef->rollback()){
|
||||||
|
suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!suspect.empty()){
|
||||||
|
// Blame suspect
|
||||||
|
RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
|
||||||
|
// Get old node for rollback
|
||||||
|
RollbackNode rollback_oldnode(this, p0, m_gamedef);
|
||||||
|
// Set node
|
||||||
|
setNode(p0, n0);
|
||||||
|
// Report
|
||||||
|
RollbackNode rollback_newnode(this, p0, m_gamedef);
|
||||||
|
RollbackAction action;
|
||||||
|
action.setSetNode(p0, rollback_oldnode, rollback_newnode);
|
||||||
|
m_gamedef->rollback()->reportAction(action);
|
||||||
|
} else {
|
||||||
|
// Set node
|
||||||
|
setNode(p0, n0);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p0);
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||||
|
if(block != NULL) {
|
||||||
|
modified_blocks.insert(blockpos, block);
|
||||||
|
// If node emits light, MapBlock requires lighting update
|
||||||
|
if(nodemgr->get(n0).light_source != 0)
|
||||||
|
lighting_modified_blocks[block->getPos()] = block;
|
||||||
|
}
|
||||||
|
must_reflow.push_back(neighbors[i].p);
|
||||||
|
}
|
||||||
|
/* //for better relax
|
||||||
|
if (changed) for (u16 ii = D_SELF + 1; ii < D_TOP; ++ii) { // only same level
|
||||||
|
if (!neighbors[ii].l) continue;
|
||||||
|
must_reflow.push_back(p0 + dirs[ii]);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
//if (loopcount) infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<" reflow="<<must_reflow.size()<<" queue="<< m_transforming_liquid.size()<<std::endl;
|
||||||
|
while (must_reflow.size() > 0)
|
||||||
|
m_transforming_liquid.push_back(must_reflow.pop_front());
|
||||||
|
while (must_reflow_second.size() > 0)
|
||||||
|
m_transforming_liquid.push_back(must_reflow_second.pop_front());
|
||||||
|
updateLighting(lighting_modified_blocks, modified_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (g_settings->getBool("liquid_finite")) return Map::transformLiquidsFinite(modified_blocks);
|
||||||
|
|
||||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||||
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -300,6 +300,7 @@ public:
|
|||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||||
|
void transformLiquidsFinite(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Node metadata
|
Node metadata
|
||||||
@ -328,6 +329,9 @@ public:
|
|||||||
Variables
|
Variables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void transforming_liquid_add(v3s16 p);
|
||||||
|
s32 transforming_liquid_size();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::ostream &m_dout; // A bit deprecated, could be removed
|
std::ostream &m_dout; // A bit deprecated, could be removed
|
||||||
|
@ -67,10 +67,15 @@ enum LightBank
|
|||||||
#define LIQUID_LEVEL_MASK 0x07
|
#define LIQUID_LEVEL_MASK 0x07
|
||||||
#define LIQUID_FLOW_DOWN_MASK 0x08
|
#define LIQUID_FLOW_DOWN_MASK 0x08
|
||||||
|
|
||||||
|
//#define LIQUID_LEVEL_MASK 0x3f // better finite water
|
||||||
|
//#define LIQUID_FLOW_DOWN_MASK 0x40 // not used when finite water
|
||||||
|
|
||||||
/* maximum amount of liquid in a block */
|
/* maximum amount of liquid in a block */
|
||||||
#define LIQUID_LEVEL_MAX LIQUID_LEVEL_MASK
|
#define LIQUID_LEVEL_MAX LIQUID_LEVEL_MASK
|
||||||
#define LIQUID_LEVEL_SOURCE (LIQUID_LEVEL_MAX+1)
|
#define LIQUID_LEVEL_SOURCE (LIQUID_LEVEL_MAX+1)
|
||||||
|
|
||||||
|
#define LIQUID_INFINITY_MASK 0x80 //0b10000000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is the stuff what the whole world consists of.
|
This is the stuff what the whole world consists of.
|
||||||
*/
|
*/
|
||||||
|
@ -961,6 +961,7 @@ Server::Server(
|
|||||||
m_ignore_map_edit_events_peer_id(0)
|
m_ignore_map_edit_events_peer_id(0)
|
||||||
{
|
{
|
||||||
m_liquid_transform_timer = 0.0;
|
m_liquid_transform_timer = 0.0;
|
||||||
|
m_liquid_transform_every = 1.0;
|
||||||
m_print_info_timer = 0.0;
|
m_print_info_timer = 0.0;
|
||||||
m_masterserver_timer = 0.0;
|
m_masterserver_timer = 0.0;
|
||||||
m_objectdata_timer = 0.0;
|
m_objectdata_timer = 0.0;
|
||||||
@ -1136,6 +1137,8 @@ Server::Server(
|
|||||||
Add some test ActiveBlockModifiers to environment
|
Add some test ActiveBlockModifiers to environment
|
||||||
*/
|
*/
|
||||||
add_legacy_abms(m_env, m_nodedef);
|
add_legacy_abms(m_env, m_nodedef);
|
||||||
|
|
||||||
|
m_liquid_transform_every = g_settings->getFloat("liquid_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
@ -1452,9 +1455,9 @@ void Server::AsyncRunStep()
|
|||||||
|
|
||||||
/* Transform liquids */
|
/* Transform liquids */
|
||||||
m_liquid_transform_timer += dtime;
|
m_liquid_transform_timer += dtime;
|
||||||
if(m_liquid_transform_timer >= 1.00)
|
if(m_liquid_transform_timer >= m_liquid_transform_every)
|
||||||
{
|
{
|
||||||
m_liquid_transform_timer -= 1.00;
|
m_liquid_transform_timer -= m_liquid_transform_every;
|
||||||
|
|
||||||
JMutexAutoLock lock(m_env_mutex);
|
JMutexAutoLock lock(m_env_mutex);
|
||||||
|
|
||||||
|
@ -719,6 +719,7 @@ private:
|
|||||||
|
|
||||||
// Some timers
|
// Some timers
|
||||||
float m_liquid_transform_timer;
|
float m_liquid_transform_timer;
|
||||||
|
float m_liquid_transform_every;
|
||||||
float m_print_info_timer;
|
float m_print_info_timer;
|
||||||
float m_masterserver_timer;
|
float m_masterserver_timer;
|
||||||
float m_objectdata_timer;
|
float m_objectdata_timer;
|
||||||
|
Loading…
Reference in New Issue
Block a user