Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
I
illuna-minetest
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Illuna-Minetest
illuna-minetest
Commits
976ec31c
Commit
976ec31c
authored
13 years ago
by
Perttu Ahola
Browse files
Options
Downloads
Patches
Plain Diff
switched to old transformLiquids, new one is not ready
parent
98be7787
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/map.cpp
+216
-207
216 additions, 207 deletions
src/map.cpp
with
216 additions
and
207 deletions
src/map.cpp
+
216
−
207
View file @
976ec31c
...
...
@@ -1540,17 +1540,6 @@ void Map::PrintInfo(std::ostream &out)
#define WATER_DROP_BOOST 4
enum
NeighborType
{
NEIGHBOR_UPPER
,
NEIGHBOR_SAME_LEVEL
,
NEIGHBOR_LOWER
};
struct
NodeNeighbor
{
MapNode
n
;
NeighborType
t
;
v3s16
p
;
};
void
Map
::
transformLiquids
(
core
::
map
<
v3s16
,
MapBlock
*>
&
modified_blocks
)
{
DSTACK
(
__FUNCTION_NAME
);
...
...
@@ -1570,220 +1559,240 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
v3s16
p0
=
m_transforming_liquid
.
pop_front
();
MapNode
n0
=
getNodeNoEx
(
p0
);
/*
Collect information about current node
*/
s8
liquid_level
=
-
1
;
u8
liquid_kind
=
CONTENT_IGNORE
;
LiquidType
liquid_type
=
content_features
(
n0
.
d
).
liquid_type
;
switch
(
liquid_type
)
{
case
LIQUID_SOURCE
:
liquid_level
=
8
;
liquid_kind
=
content_features
(
n0
.
d
).
liquid_alternative_flowing
;
break
;
case
LIQUID_FLOWING
:
liquid_level
=
(
n0
.
param2
&
LIQUID_LEVEL_MASK
);
liquid_kind
=
n0
.
d
;
break
;
case
LIQUID_NONE
:
// if this is an air node, it *could* be transformed into a liquid. otherwise,
// continue with the next node.
if
(
n0
.
d
!=
CONTENT_AIR
)
continue
;
liquid_kind
=
CONTENT_AIR
;
break
;
}
// Don't deal with non-liquids
if
(
content_liquid
(
n0
.
d
)
==
false
)
continue
;
bool
is_source
=
!
content_flowing_liquid
(
n0
.
d
);
u8
liquid_level
=
8
;
if
(
is_source
==
false
)
liquid_level
=
n0
.
param2
&
0x0f
;
// Turn possible source into non-source
u8
nonsource_c
=
make_liquid_flowing
(
n0
.
d
);
/*
Collect information about the environment
*/
v3s16
dirs
[
6
]
=
{
v3s16
(
0
,
1
,
0
),
// top
v3s16
(
0
,
-
1
,
0
),
// bottom
v3s16
(
1
,
0
,
0
),
// right
v3s16
(
-
1
,
0
,
0
),
// left
v3s16
(
0
,
0
,
1
),
// back
v3s16
(
0
,
0
,
-
1
),
// front
};
NodeNeighbor
sources
[
6
];
// surrounding sources
int
num_sources
=
0
;
NodeNeighbor
flows
[
6
];
// surrounding flowing liquid nodes
int
num_flows
=
0
;
NodeNeighbor
airs
[
6
];
// surrounding air
int
num_airs
=
0
;
NodeNeighbor
neutrals
[
6
];
// nodes that are solid or another kind of liquid
int
num_neutrals
=
0
;
bool
flowing_down
=
false
;
for
(
u16
i
=
0
;
i
<
6
;
i
++
)
{
NeighborType
nt
=
NEIGHBOR_SAME_LEVEL
;
switch
(
i
)
{
case
0
:
nt
=
NEIGHBOR_UPPER
;
break
;
case
1
:
nt
=
NEIGHBOR_LOWER
;
break
;
}
v3s16
npos
=
p0
+
dirs
[
i
];
NodeNeighbor
nb
=
{
getNodeNoEx
(
npos
),
nt
,
npos
};
switch
(
content_features
(
nb
.
n
.
d
).
liquid_type
)
{
case
LIQUID_NONE
:
if
(
nb
.
n
.
d
==
CONTENT_AIR
)
{
airs
[
num_airs
++
]
=
nb
;
// if the current node happens to be a flowing node, it will start to flow down here.
if
(
nb
.
t
==
NEIGHBOR_LOWER
)
flowing_down
=
true
;
}
else
{
neutrals
[
num_neutrals
++
]
=
nb
;
If not source, check that some node flows into this one
and what is the level of liquid in this one
*/
if
(
is_source
==
false
)
{
s8
new_liquid_level_max
=
-
1
;
v3s16
dirs_from
[
5
]
=
{
v3s16
(
0
,
1
,
0
),
// top
v3s16
(
0
,
0
,
1
),
// back
v3s16
(
1
,
0
,
0
),
// right
v3s16
(
0
,
0
,
-
1
),
// front
v3s16
(
-
1
,
0
,
0
),
// left
};
for
(
u16
i
=
0
;
i
<
5
;
i
++
)
{
bool
from_top
=
(
i
==
0
);
v3s16
p2
=
p0
+
dirs_from
[
i
];
MapNode
n2
=
getNodeNoEx
(
p2
);
if
(
content_liquid
(
n2
.
d
))
{
u8
n2_nonsource_c
=
make_liquid_flowing
(
n2
.
d
);
// Check that the liquids are the same type
if
(
n2_nonsource_c
!=
nonsource_c
)
{
dstream
<<
"WARNING: Not handling: different liquids"
" collide"
<<
std
::
endl
;
continue
;
}
break
;
case
LIQUID_SOURCE
:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if
(
liquid_kind
==
CONTENT_AIR
)
liquid_kind
=
content_features
(
nb
.
n
.
d
).
liquid_alternative_flowing
;
if
(
content_features
(
nb
.
n
.
d
).
liquid_alternative_flowing
!=
liquid_kind
)
{
neutrals
[
num_neutrals
++
]
=
nb
;
}
else
{
sources
[
num_sources
++
]
=
nb
;
bool
n2_is_source
=
!
content_flowing_liquid
(
n2
.
d
);
s8
n2_liquid_level
=
8
;
if
(
n2_is_source
==
false
)
n2_liquid_level
=
n2
.
param2
&
0x07
;
s8
new_liquid_level
=
-
1
;
if
(
from_top
)
{
//new_liquid_level = 7;
if
(
n2_liquid_level
>=
7
-
WATER_DROP_BOOST
)
new_liquid_level
=
7
;
else
new_liquid_level
=
n2_liquid_level
+
WATER_DROP_BOOST
;
}
break
;
case
LIQUID_FLOWING
:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if
(
liquid_kind
==
CONTENT_AIR
)
liquid_kind
=
content_features
(
nb
.
n
.
d
).
liquid_alternative_flowing
;
if
(
content_features
(
nb
.
n
.
d
).
liquid_alternative_flowing
!=
liquid_kind
)
{
neutrals
[
num_neutrals
++
]
=
nb
;
}
else
{
flows
[
num_flows
++
]
=
nb
;
if
(
nb
.
t
==
NEIGHBOR_LOWER
)
flowing_down
=
true
;
else
if
(
n2_liquid_level
>
0
)
{
new_liquid_level
=
n2_liquid_level
-
1
;
}
break
;
}
}
/*
decide on the type (and possibly level) of the current node
*/
u8
new_node_content
;
s8
new_node_level
=
-
1
;
if
(
num_sources
>=
2
||
liquid_type
==
LIQUID_SOURCE
)
{
// liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
// or the flowing alternative of the first of the surrounding sources (if it's air), so
// it's perfectly safe to use liquid_kind here to determine the new node content.
new_node_content
=
content_features
(
liquid_kind
).
liquid_alternative_source
;
}
else
if
(
num_sources
==
1
&&
sources
[
0
].
t
!=
NEIGHBOR_LOWER
)
{
// liquid_kind is set properly, see above
new_node_content
=
liquid_kind
;
new_node_level
=
7
;
}
else
{
// no surrounding sources, so get the maximum level that can flow into this node
for
(
u16
i
=
0
;
i
<
num_flows
;
i
++
)
{
u8
nb_liquid_level
=
(
flows
[
i
].
n
.
param2
&
LIQUID_LEVEL_MASK
);
switch
(
flows
[
i
].
t
)
{
case
NEIGHBOR_UPPER
:
if
(
nb_liquid_level
+
WATER_DROP_BOOST
>
new_node_level
)
{
new_node_level
=
7
;
if
(
nb_liquid_level
+
WATER_DROP_BOOST
<
7
)
new_node_level
=
nb_liquid_level
+
WATER_DROP_BOOST
;
}
break
;
case
NEIGHBOR_LOWER
:
break
;
case
NEIGHBOR_SAME_LEVEL
:
if
((
flows
[
i
].
n
.
param2
&
LIQUID_FLOW_DOWN_MASK
)
!=
LIQUID_FLOW_DOWN_MASK
&&
nb_liquid_level
>
0
&&
nb_liquid_level
-
1
>
new_node_level
)
{
new_node_level
=
nb_liquid_level
-
1
;
}
break
;
if
(
new_liquid_level
>
new_liquid_level_max
)
new_liquid_level_max
=
new_liquid_level
;
}
}
// don't flow as far in open terrain - if there isn't at least one adjacent solid block,
// substract another unit from the resulting water level.
if
(
!
flowing_down
&&
new_node_level
>=
1
)
{
bool
at_wall
=
false
;
for
(
u16
i
=
0
;
i
<
num_neutrals
;
i
++
)
{
if
(
neutrals
[
i
].
t
==
NEIGHBOR_SAME_LEVEL
)
{
at_wall
=
true
;
break
;
}
//for
/*
If liquid level should be something else, update it and
add all the neighboring water nodes to the transform queue.
*/
if
(
new_liquid_level_max
!=
liquid_level
)
{
if
(
new_liquid_level_max
==
-
1
)
{
// Remove water alltoghether
n0
.
d
=
CONTENT_AIR
;
n0
.
param2
=
0
;
setNode
(
p0
,
n0
);
}
else
{
n0
.
param2
=
new_liquid_level_max
;
setNode
(
p0
,
n0
);
}
// Block has been modified
{
v3s16
blockpos
=
getNodeBlockPos
(
p0
);
MapBlock
*
block
=
getBlockNoCreateNoEx
(
blockpos
);
if
(
block
!=
NULL
)
modified_blocks
.
insert
(
blockpos
,
block
);
}
/*
Add neighboring non-source liquid nodes to transform queue.
*/
v3s16
dirs
[
6
]
=
{
v3s16
(
0
,
0
,
1
),
// back
v3s16
(
0
,
1
,
0
),
// top
v3s16
(
1
,
0
,
0
),
// right
v3s16
(
0
,
0
,
-
1
),
// front
v3s16
(
0
,
-
1
,
0
),
// bottom
v3s16
(
-
1
,
0
,
0
),
// left
};
for
(
u16
i
=
0
;
i
<
6
;
i
++
)
{
v3s16
p2
=
p0
+
dirs
[
i
];
MapNode
n2
=
getNodeNoEx
(
p2
);
if
(
content_flowing_liquid
(
n2
.
d
))
{
m_transforming_liquid
.
push_back
(
p2
);
}
}
if
(
!
at_wall
)
new_node_level
-=
1
;
}
if
(
new_node_level
>=
0
)
new_node_content
=
liquid_kind
;
else
new_node_content
=
CONTENT_AIR
;
}
/*
check if anything has changed. if not, just continue with the next node.
*/
if
(
new_node_content
==
n0
.
d
&&
(
content_features
(
n0
.
d
).
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
)))
// Get a new one from queue if the node has turned into non-water
if
(
content_liquid
(
n0
.
d
)
==
false
)
continue
;
/*
update the current node
*/
bool
flow_down_enabled
=
(
flowing_down
&&
((
n0
.
param2
&
LIQUID_FLOW_DOWN_MASK
)
!=
LIQUID_FLOW_DOWN_MASK
));
n0
.
d
=
new_node_content
;
if
(
content_features
(
n0
.
d
).
liquid_type
==
LIQUID_FLOWING
)
{
// set level to last 3 bits, flowing down bit to 4th bit
n0
.
param2
=
(
flowing_down
?
LIQUID_FLOW_DOWN_MASK
:
0x00
)
|
(
new_node_level
&
LIQUID_LEVEL_MASK
);
}
else
{
n0
.
param2
=
0
;
}
setNode
(
p0
,
n0
);
v3s16
blockpos
=
getNodeBlockPos
(
p0
);
MapBlock
*
block
=
getBlockNoCreateNoEx
(
blockpos
);
if
(
block
!=
NULL
)
modified_blocks
.
insert
(
blockpos
,
block
);
/*
enqueue neighbors for update if neccessary
*/
switch
(
content_features
(
n0
.
d
).
liquid_type
)
{
case
LIQUID_SOURCE
:
// make sure source flows into all neighboring nodes
for
(
u16
i
=
0
;
i
<
num_flows
;
i
++
)
if
(
flows
[
i
].
t
!=
NEIGHBOR_UPPER
)
m_transforming_liquid
.
push_back
(
flows
[
i
].
p
);
for
(
u16
i
=
0
;
i
<
num_airs
;
i
++
)
if
(
airs
[
i
].
t
!=
NEIGHBOR_UPPER
)
m_transforming_liquid
.
push_back
(
airs
[
i
].
p
);
break
;
case
LIQUID_NONE
:
// this flow has turned to air; neighboring flows might need to do the same
for
(
u16
i
=
0
;
i
<
num_flows
;
i
++
)
m_transforming_liquid
.
push_back
(
flows
[
i
].
p
);
break
;
case
LIQUID_FLOWING
:
for
(
u16
i
=
0
;
i
<
num_flows
;
i
++
)
{
u8
flow_level
=
(
flows
[
i
].
n
.
param2
&
LIQUID_LEVEL_MASK
);
// liquid_level is still the ORIGINAL level of this node.
if
(
flows
[
i
].
t
!=
NEIGHBOR_UPPER
&&
((
flow_level
<
liquid_level
||
flow_level
<
new_node_level
)
||
flow_down_enabled
))
m_transforming_liquid
.
push_back
(
flows
[
i
].
p
);
Flow water from this node
*/
v3s16
dirs_to
[
5
]
=
{
v3s16
(
0
,
-
1
,
0
),
// bottom
v3s16
(
0
,
0
,
1
),
// back
v3s16
(
1
,
0
,
0
),
// right
v3s16
(
0
,
0
,
-
1
),
// front
v3s16
(
-
1
,
0
,
0
),
// left
};
for
(
u16
i
=
0
;
i
<
5
;
i
++
)
{
bool
to_bottom
=
(
i
==
0
);
// If liquid is at lowest possible height, it's not going
// anywhere except down
if
(
liquid_level
==
0
&&
to_bottom
==
false
)
continue
;
u8
liquid_next_level
=
0
;
// If going to bottom
if
(
to_bottom
)
{
//liquid_next_level = 7;
if
(
liquid_level
>=
7
-
WATER_DROP_BOOST
)
liquid_next_level
=
7
;
else
liquid_next_level
=
liquid_level
+
WATER_DROP_BOOST
;
}
else
liquid_next_level
=
liquid_level
-
1
;
bool
n2_changed
=
false
;
bool
flowed
=
false
;
v3s16
p2
=
p0
+
dirs_to
[
i
];
MapNode
n2
=
getNodeNoEx
(
p2
);
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
if
(
content_liquid
(
n2
.
d
))
{
u8
n2_nonsource_c
=
make_liquid_flowing
(
n2
.
d
);
// Check that the liquids are the same type
if
(
n2_nonsource_c
!=
nonsource_c
)
{
dstream
<<
"WARNING: Not handling: different liquids"
" collide"
<<
std
::
endl
;
continue
;
}
bool
n2_is_source
=
!
content_flowing_liquid
(
n2
.
d
);
u8
n2_liquid_level
=
8
;
if
(
n2_is_source
==
false
)
n2_liquid_level
=
n2
.
param2
&
0x07
;
if
(
to_bottom
)
{
flowed
=
true
;
}
for
(
u16
i
=
0
;
i
<
num_airs
;
i
++
)
{
if
(
airs
[
i
].
t
!=
NEIGHBOR_UPPER
&&
(
airs
[
i
].
t
==
NEIGHBOR_LOWER
||
new_node_level
>
0
))
m_transforming_liquid
.
push_back
(
airs
[
i
].
p
);
if
(
n2_is_source
)
{
// Just flow into the source, nothing changes.
// n2_changed is not set because destination didn't change
flowed
=
true
;
}
else
{
if
(
liquid_next_level
>
liquid_level
)
{
n2
.
param2
=
liquid_next_level
;
setNode
(
p2
,
n2
);
n2_changed
=
true
;
flowed
=
true
;
}
}
}
else
if
(
n2
.
d
==
CONTENT_AIR
)
{
n2
.
d
=
nonsource_c
;
n2
.
param2
=
liquid_next_level
;
setNode
(
p2
,
n2
);
n2_changed
=
true
;
flowed
=
true
;
}
//dstream<<"[2] n2.param="<<(int)n2.param<<std::endl;
if
(
n2_changed
)
{
m_transforming_liquid
.
push_back
(
p2
);
v3s16
blockpos
=
getNodeBlockPos
(
p2
);
MapBlock
*
block
=
getBlockNoCreateNoEx
(
blockpos
);
if
(
block
!=
NULL
)
modified_blocks
.
insert
(
blockpos
,
block
);
}
// If n2_changed to bottom, don't flow anywhere else
if
(
to_bottom
&&
flowed
&&
!
is_source
)
break
;
}
loopcount
++
;
//if(loopcount >= 100000)
if
(
loopcount
>=
initial_size
*
1
0
)
{
if
(
loopcount
>=
initial_size
*
1
)
break
;
}
}
//dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment