summaryrefslogtreecommitdiff
path: root/src/map.cpp
diff options
context:
space:
mode:
authorDániel Juhász <juhdanad@gmail.com>2017-01-04 19:18:40 +0100
committerest31 <est31@users.noreply.github.com>2017-01-04 19:18:40 +0100
commit3f8261830e0503cd59d8713d5c9aab12fc1491db (patch)
treeb49d898815a6c2e692cfe2fc0978cfedd49cd34f /src/map.cpp
parent8aadc62856cc3789ed345ddf3870e311af60afe9 (diff)
downloadminetest-3f8261830e0503cd59d8713d5c9aab12fc1491db.tar.gz
minetest-3f8261830e0503cd59d8713d5c9aab12fc1491db.tar.bz2
minetest-3f8261830e0503cd59d8713d5c9aab12fc1491db.zip
Improve getPointedThing() (#4346)
* Improved getPointedThing() The new algorithm checks every node exactly once. Now the point and normal vector of the collision is also returned in the PointedThing (currently they are not used outside of the function). Now the CNodeDefManager keeps the union of all possible nodeboxes, so the raycast won't miss any nodes. Also if there are only small nodeboxes, getPointedThing() is exceptionally fast. Also adds unit test for VoxelLineIterator. * Cleanup, code move This commit moves getPointedThing() and Client::getSelectedActiveObject() to ClientEnvironment. The map nodes now can decide which neighbors they are connecting to (MapNode::getNeighbors()).
Diffstat (limited to 'src/map.cpp')
-rw-r--r--src/map.cpp91
1 files changed, 40 insertions, 51 deletions
diff --git a/src/map.cpp b/src/map.cpp
index c3b62ded0..53657ce6b 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -66,6 +66,7 @@ Map::Map(std::ostream &dout, IGameDef *gamedef):
m_dout(dout),
m_gamedef(gamedef),
m_sector_cache(NULL),
+ m_nodedef(gamedef->ndef()),
m_transforming_liquid_loop_count_multiplier(1.0f),
m_unprocessed_count(0),
m_inc_trending_up_start_time(0),
@@ -227,7 +228,7 @@ void Map::setNode(v3s16 p, MapNode & n)
bool temp_bool;
errorstream<<"Map::setNode(): Not allowing to place CONTENT_IGNORE"
<<" while trying to replace \""
- <<m_gamedef->ndef()->get(block->getNodeNoCheck(relpos, &temp_bool)).name
+ <<m_nodedef->get(block->getNodeNoCheck(relpos, &temp_bool)).name
<<"\" at "<<PP(p)<<" (block "<<PP(blockpos)<<")"<<std::endl;
debug_stacks_print_to(infostream);
return;
@@ -257,8 +258,6 @@ void Map::unspreadLight(enum LightBank bank,
std::set<v3s16> & light_sources,
std::map<v3s16, MapBlock*> & modified_blocks)
{
- INodeDefManager *nodemgr = m_gamedef->ndef();
-
v3s16 dirs[6] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
@@ -353,20 +352,20 @@ void Map::unspreadLight(enum LightBank bank,
If the neighbor is dimmer than what was specified
as oldlight (the light of the previous node)
*/
- if(n2.getLight(bank, nodemgr) < oldlight)
+ if(n2.getLight(bank, m_nodedef) < oldlight)
{
/*
And the neighbor is transparent and it has some light
*/
- if(nodemgr->get(n2).light_propagates
- && n2.getLight(bank, nodemgr) != 0)
+ if(m_nodedef->get(n2).light_propagates
+ && n2.getLight(bank, m_nodedef) != 0)
{
/*
Set light to 0 and add to queue
*/
- u8 current_light = n2.getLight(bank, nodemgr);
- n2.setLight(bank, 0, nodemgr);
+ u8 current_light = n2.getLight(bank, m_nodedef);
+ n2.setLight(bank, 0, m_nodedef);
block->setNode(relpos, n2);
unlighted_nodes[n2pos] = current_light;
@@ -421,8 +420,6 @@ void Map::spreadLight(enum LightBank bank,
std::set<v3s16> & from_nodes,
std::map<v3s16, MapBlock*> & modified_blocks)
{
- INodeDefManager *nodemgr = m_gamedef->ndef();
-
const v3s16 dirs[6] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
@@ -476,7 +473,7 @@ void Map::spreadLight(enum LightBank bank,
bool is_valid_position;
MapNode n = block->getNode(relpos, &is_valid_position);
- u8 oldlight = is_valid_position ? n.getLight(bank, nodemgr) : 0;
+ u8 oldlight = is_valid_position ? n.getLight(bank, m_nodedef) : 0;
u8 newlight = diminish_light(oldlight);
// Loop through 6 neighbors
@@ -512,7 +509,7 @@ void Map::spreadLight(enum LightBank bank,
If the neighbor is brighter than the current node,
add to list (it will light up this node on its turn)
*/
- if(n2.getLight(bank, nodemgr) > undiminish_light(oldlight))
+ if(n2.getLight(bank, m_nodedef) > undiminish_light(oldlight))
{
lighted_nodes.insert(n2pos);
changed = true;
@@ -521,11 +518,11 @@ void Map::spreadLight(enum LightBank bank,
If the neighbor is dimmer than how much light this node
would spread on it, add to list
*/
- if(n2.getLight(bank, nodemgr) < newlight)
+ if(n2.getLight(bank, m_nodedef) < newlight)
{
- if(nodemgr->get(n2).light_propagates)
+ if(m_nodedef->get(n2).light_propagates)
{
- n2.setLight(bank, newlight, nodemgr);
+ n2.setLight(bank, newlight, m_nodedef);
block->setNode(relpos, n2);
lighted_nodes.insert(n2pos);
changed = true;
@@ -558,8 +555,6 @@ void Map::updateLighting(enum LightBank bank,
std::map<v3s16, MapBlock*> & a_blocks,
std::map<v3s16, MapBlock*> & modified_blocks)
{
- INodeDefManager *nodemgr = m_gamedef->ndef();
-
/*m_dout<<"Map::updateLighting(): "
<<a_blocks.size()<<" blocks."<<std::endl;*/
@@ -614,12 +609,12 @@ void Map::updateLighting(enum LightBank bank,
<<std::endl;
continue;
}
- u8 oldlight = n.getLight(bank, nodemgr);
- n.setLight(bank, 0, nodemgr);
+ u8 oldlight = n.getLight(bank, m_nodedef);
+ n.setLight(bank, 0, m_nodedef);
block->setNode(p, n);
// If node sources light, add to list
- u8 source = nodemgr->get(n).light_source;
+ u8 source = m_nodedef->get(n).light_source;
if(source != 0)
light_sources.insert(p + posnodes);
@@ -810,8 +805,6 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
std::map<v3s16, MapBlock*> &modified_blocks,
bool remove_metadata)
{
- INodeDefManager *ndef = m_gamedef->ndef();
-
// Collect old node for rollback
RollbackNode rollback_oldnode(this, p, m_gamedef);
@@ -825,14 +818,14 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
// Set the node on the map
// Ignore light (because calling voxalgo::update_lighting_nodes)
- n.setLight(LIGHTBANK_DAY, 0, ndef);
- n.setLight(LIGHTBANK_NIGHT, 0, ndef);
+ n.setLight(LIGHTBANK_DAY, 0, m_nodedef);
+ n.setLight(LIGHTBANK_NIGHT, 0, m_nodedef);
setNode(p, n);
// Update lighting
std::vector<std::pair<v3s16, MapNode> > oldnodes;
oldnodes.push_back(std::pair<v3s16, MapNode>(p, oldnode));
- voxalgo::update_lighting_nodes(this, ndef, oldnodes, modified_blocks);
+ voxalgo::update_lighting_nodes(this, m_nodedef, oldnodes, modified_blocks);
for(std::map<v3s16, MapBlock*>::iterator
i = modified_blocks.begin();
@@ -869,11 +862,10 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
bool is_valid_position;
MapNode n2 = getNodeNoEx(p2, &is_valid_position);
- if(is_valid_position
- && (ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR))
- {
+ if(is_valid_position &&
+ (m_nodedef->get(n2).isLiquid() ||
+ n2.getContent() == CONTENT_AIR))
m_transforming_liquid.push_back(p2);
- }
}
}
@@ -1213,9 +1205,6 @@ s32 Map::transforming_liquid_size() {
void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
{
-
- INodeDefManager *nodemgr = m_gamedef->ndef();
-
DSTACK(FUNCTION_NAME);
//TimeTaker timer("transformLiquids()");
@@ -1275,12 +1264,12 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
// The node which will be placed there if liquid
// can't flow into this node.
content_t floodable_node = CONTENT_AIR;
- const ContentFeatures &cf = nodemgr->get(n0);
+ const ContentFeatures &cf = m_nodedef->get(n0);
LiquidType liquid_type = cf.liquid_type;
switch (liquid_type) {
case LIQUID_SOURCE:
liquid_level = LIQUID_LEVEL_SOURCE;
- liquid_kind = nodemgr->getId(cf.liquid_alternative_flowing);
+ liquid_kind = m_nodedef->getId(cf.liquid_alternative_flowing);
break;
case LIQUID_FLOWING:
liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
@@ -1322,8 +1311,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
}
v3s16 npos = p0 + dirs[i];
NodeNeighbor nb(getNodeNoEx(npos), nt, npos);
- const ContentFeatures &cfnb = nodemgr->get(nb.n);
- switch (nodemgr->get(nb.n.getContent()).liquid_type) {
+ const ContentFeatures &cfnb = m_nodedef->get(nb.n);
+ switch (m_nodedef->get(nb.n.getContent()).liquid_type) {
case LIQUID_NONE:
if (cfnb.floodable) {
airs[num_airs++] = nb;
@@ -1351,8 +1340,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
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 = nodemgr->getId(cfnb.liquid_alternative_flowing);
- if (nodemgr->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
+ liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing);
+ if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
neutrals[num_neutrals++] = nb;
} else {
// Do not count bottom source, it will screw things up
@@ -1363,8 +1352,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
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 = nodemgr->getId(cfnb.liquid_alternative_flowing);
- if (nodemgr->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
+ liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing);
+ if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
neutrals[num_neutrals++] = nb;
} else {
flows[num_flows++] = nb;
@@ -1382,15 +1371,15 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
s8 new_node_level = -1;
s8 max_node_level = -1;
- u8 range = nodemgr->get(liquid_kind).liquid_range;
+ u8 range = m_nodedef->get(liquid_kind).liquid_range;
if (range > LIQUID_LEVEL_MAX + 1)
range = LIQUID_LEVEL_MAX + 1;
- if ((num_sources >= 2 && nodemgr->get(liquid_kind).liquid_renewable) || liquid_type == LIQUID_SOURCE) {
+ if ((num_sources >= 2 && m_nodedef->get(liquid_kind).liquid_renewable) || 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 = nodemgr->getId(nodemgr->get(liquid_kind).liquid_alternative_source);
+ new_node_content = m_nodedef->getId(m_nodedef->get(liquid_kind).liquid_alternative_source);
} else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) {
// liquid_kind is set properly, see above
max_node_level = new_node_level = LIQUID_LEVEL_MAX;
@@ -1427,7 +1416,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
}
}
- u8 viscosity = nodemgr->get(liquid_kind).liquid_viscosity;
+ u8 viscosity = m_nodedef->get(liquid_kind).liquid_viscosity;
if (viscosity > 1 && max_node_level != liquid_level) {
// amount to gain, limited by viscosity
// must be at least 1 in absolute value
@@ -1455,7 +1444,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
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 ||
+ (m_nodedef->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)))
@@ -1467,7 +1456,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
*/
MapNode n00 = n0;
//bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
- if (nodemgr->get(new_node_content).liquid_type == LIQUID_FLOWING) {
+ if (m_nodedef->get(new_node_content).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 {
@@ -1477,8 +1466,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
n0.setContent(new_node_content);
// Ignore light (because calling voxalgo::update_lighting_nodes)
- n0.setLight(LIGHTBANK_DAY, 0, nodemgr);
- n0.setLight(LIGHTBANK_NIGHT, 0, nodemgr);
+ n0.setLight(LIGHTBANK_DAY, 0, m_nodedef);
+ n0.setLight(LIGHTBANK_NIGHT, 0, m_nodedef);
// Find out whether there is a suspect for this action
std::string suspect;
@@ -1512,7 +1501,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
/*
enqueue neighbors for update if neccessary
*/
- switch (nodemgr->get(n0.getContent()).liquid_type) {
+ switch (m_nodedef->get(n0.getContent()).liquid_type) {
case LIQUID_SOURCE:
case LIQUID_FLOWING:
// make sure source flows into all neighboring nodes
@@ -1535,7 +1524,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
for (std::deque<v3s16>::iterator iter = must_reflow.begin(); iter != must_reflow.end(); ++iter)
m_transforming_liquid.push_back(*iter);
- voxalgo::update_lighting_nodes(this, nodemgr, changed_nodes, modified_blocks);
+ voxalgo::update_lighting_nodes(this, m_nodedef, changed_nodes, modified_blocks);
/* ----------------------------------------------------------------------
@@ -1900,7 +1889,7 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
data->blockpos_min = bpmin;
data->blockpos_max = bpmax;
data->blockpos_requested = blockpos;
- data->nodedef = m_gamedef->ndef();
+ data->nodedef = m_nodedef;
/*
Create the whole area of this and the neighboring blocks