*/
#include "map.h"
-//#include "player.h"
#include "main.h"
#include "jmutexautolock.h"
#include "client.h"
#include "filesys.h"
#include "utility.h"
#include "voxel.h"
-
-#ifdef _WIN32
- #include <windows.h>
- #define sleep_ms(x) Sleep(x)
-#else
- #include <unistd.h>
- #define sleep_ms(x) usleep(x*1000)
-#endif
-
-MapBlockPointerCache::MapBlockPointerCache(Map *map)
-{
- m_map = map;
- m_map->m_blockcachelock.cacheCreated();
-
- m_from_cache_count = 0;
- m_from_map_count = 0;
-}
-
-MapBlockPointerCache::~MapBlockPointerCache()
-{
- m_map->m_blockcachelock.cacheRemoved();
-
- /*dstream<<"MapBlockPointerCache:"
- <<" from_cache_count="<<m_from_cache_count
- <<" from_map_count="<<m_from_map_count
- <<std::endl;*/
-}
-
-MapBlock * MapBlockPointerCache::getBlockNoCreate(v3s16 p)
-{
- core::map<v3s16, MapBlock*>::Node *n = NULL;
- n = m_blocks.find(p);
- if(n != NULL)
- {
- m_from_cache_count++;
- return n->getValue();
- }
-
- m_from_map_count++;
-
- // Throws InvalidPositionException if not found
- MapBlock *b = m_map->getBlockNoCreate(p);
- m_blocks[p] = b;
- return b;
-}
+#include "porting.h"
/*
Map
}
}
-/*bool Map::sectorExists(v2s16 p)
-{
- JMutexAutoLock lock(m_sector_mutex);
- core::map<v2s16, MapSector*>::Node *n = m_sectors.find(p);
- return (n != NULL);
-}*/
-
MapSector * Map::getSectorNoGenerate(v2s16 p)
{
JMutexAutoLock lock(m_sector_mutex);
return block;
}
-/*MapBlock * Map::getBlock(v3s16 p3d, bool generate)
+MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d)
{
- dstream<<"Map::getBlock() with generate=true called"
- <<std::endl;
- v2s16 p2d(p3d.X, p3d.Z);
- //MapSector * sector = getSector(p2d, generate);
- MapSector * sector = getSectorNoGenerate(p2d);
-
- if(sector == NULL)
- throw InvalidPositionException();
-
- return sector->getBlockNoCreate(p3d.Y);
-}*/
+ try
+ {
+ v2s16 p2d(p3d.X, p3d.Z);
+ MapSector * sector = getSectorNoGenerate(p2d);
+ MapBlock *block = sector->getBlockNoCreate(p3d.Y);
+ return block;
+ }
+ catch(InvalidPositionException &e)
+ {
+ return NULL;
+ }
+}
f32 Map::getGroundHeight(v2s16 p, bool generate)
{
}
}
-#if 0
-void Map::interpolate(v3s16 block,
- core::map<v3s16, MapBlock*> & modified_blocks)
-{
- const 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
- };
-
- if(from_nodes.size() == 0)
- return;
-
- u32 blockchangecount = 0;
-
- core::map<v3s16, bool> lighted_nodes;
- core::map<v3s16, bool>::Iterator j;
- j = from_nodes.getIterator();
-
- /*
- Initialize block cache
- */
- v3s16 blockpos_last;
- MapBlock *block = NULL;
- // Cache this a bit, too
- bool block_checked_in_modified = false;
-
- for(; j.atEnd() == false; j++)
- //for(; j != from_nodes.end(); j++)
- {
- v3s16 pos = j.getNode()->getKey();
- //v3s16 pos = *j;
- //dstream<<"pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl;
- v3s16 blockpos = getNodeBlockPos(pos);
-
- // Only fetch a new block if the block position has changed
- try{
- if(block == NULL || blockpos != blockpos_last){
- block = getBlockNoCreate(blockpos);
- blockpos_last = blockpos;
-
- block_checked_in_modified = false;
- blockchangecount++;
- }
- }
- catch(InvalidPositionException &e)
- {
- continue;
- }
-
- if(block->isDummy())
- continue;
-
- // Calculate relative position in block
- v3s16 relpos = pos - blockpos_last * MAP_BLOCKSIZE;
-
- // Get node straight from the block
- MapNode n = block->getNode(relpos);
-
- u8 oldlight = n.getLight();
- u8 newlight = diminish_light(oldlight);
-
- // Loop through 6 neighbors
- for(u16 i=0; i<6; i++){
- // Get the position of the neighbor node
- v3s16 n2pos = pos + dirs[i];
-
- // Get the block where the node is located
- v3s16 blockpos = getNodeBlockPos(n2pos);
-
- try
- {
- // Only fetch a new block if the block position has changed
- try{
- if(block == NULL || blockpos != blockpos_last){
- block = getBlockNoCreate(blockpos);
- blockpos_last = blockpos;
-
- block_checked_in_modified = false;
- blockchangecount++;
- }
- }
- catch(InvalidPositionException &e)
- {
- continue;
- }
-
- // Calculate relative position in block
- v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE;
- // Get node straight from the block
- MapNode n2 = block->getNode(relpos);
-
- bool changed = false;
- /*
- If the neighbor is brighter than the current node,
- add to list (it will light up this node on its turn)
- */
- if(n2.getLight() > undiminish_light(oldlight))
- {
- lighted_nodes.insert(n2pos, true);
- //lighted_nodes.push_back(n2pos);
- changed = true;
- }
- /*
- If the neighbor is dimmer than how much light this node
- would spread on it, add to list
- */
- if(n2.getLight() < newlight)
- {
- if(n2.light_propagates())
- {
- n2.setLight(newlight);
- block->setNode(relpos, n2);
- lighted_nodes.insert(n2pos, true);
- //lighted_nodes.push_back(n2pos);
- changed = true;
- }
- }
-
- // Add to modified_blocks
- if(changed == true && block_checked_in_modified == false)
- {
- // If the block is not found in modified_blocks, add.
- if(modified_blocks.find(blockpos) == NULL)
- {
- modified_blocks.insert(blockpos, block);
- }
- block_checked_in_modified = true;
- }
- }
- catch(InvalidPositionException &e)
- {
- continue;
- }
- }
- }
-
- /*dstream<<"spreadLight(): Changed block "
- <<blockchangecount<<" times"
- <<" for "<<from_nodes.size()<<" nodes"
- <<std::endl;*/
-
- if(lighted_nodes.size() > 0)
- spreadLight(lighted_nodes, modified_blocks);
-}
-#endif
-
/*
Goes recursively through the neighbours of the node.
values of from_nodes are lighting values.
*/
-void Map::unspreadLight(core::map<v3s16, u8> & from_nodes,
+void Map::unspreadLight(enum LightBank bank,
+ core::map<v3s16, u8> & from_nodes,
core::map<v3s16, bool> & light_sources,
core::map<v3s16, MapBlock*> & modified_blocks)
{
If the neighbor is dimmer than what was specified
as oldlight (the light of the previous node)
*/
- if(n2.getLight() < oldlight)
+ if(n2.getLight(bank) < oldlight)
{
/*
And the neighbor is transparent and it has some light
*/
- if(n2.light_propagates() && n2.getLight() != 0)
+ if(n2.light_propagates() && n2.getLight(bank) != 0)
{
/*
Set light to 0 and add to queue
*/
- u8 current_light = n2.getLight();
- n2.setLight(0);
+ u8 current_light = n2.getLight(bank);
+ n2.setLight(bank, 0);
block->setNode(relpos, n2);
unlighted_nodes.insert(n2pos, current_light);
<<std::endl;*/
if(unlighted_nodes.size() > 0)
- unspreadLight(unlighted_nodes, light_sources, modified_blocks);
+ unspreadLight(bank, unlighted_nodes, light_sources, modified_blocks);
}
/*
A single-node wrapper of the above
*/
-void Map::unLightNeighbors(v3s16 pos, u8 lightwas,
+void Map::unLightNeighbors(enum LightBank bank,
+ v3s16 pos, u8 lightwas,
core::map<v3s16, bool> & light_sources,
core::map<v3s16, MapBlock*> & modified_blocks)
{
core::map<v3s16, u8> from_nodes;
from_nodes.insert(pos, lightwas);
- unspreadLight(from_nodes, light_sources, modified_blocks);
+ unspreadLight(bank, from_nodes, light_sources, modified_blocks);
}
/*
Lights neighbors of from_nodes, collects all them and then
goes on recursively.
*/
-void Map::spreadLight(core::map<v3s16, bool> & from_nodes,
+void Map::spreadLight(enum LightBank bank,
+ core::map<v3s16, bool> & from_nodes,
core::map<v3s16, MapBlock*> & modified_blocks)
{
const v3s16 dirs[6] = {
// Get node straight from the block
MapNode n = block->getNode(relpos);
- u8 oldlight = n.getLight();
+ u8 oldlight = n.getLight(bank);
u8 newlight = diminish_light(oldlight);
// Loop through 6 neighbors
If the neighbor is brighter than the current node,
add to list (it will light up this node on its turn)
*/
- if(n2.getLight() > undiminish_light(oldlight))
+ if(n2.getLight(bank) > undiminish_light(oldlight))
{
lighted_nodes.insert(n2pos, true);
//lighted_nodes.push_back(n2pos);
If the neighbor is dimmer than how much light this node
would spread on it, add to list
*/
- if(n2.getLight() < newlight)
+ if(n2.getLight(bank) < newlight)
{
if(n2.light_propagates())
{
- n2.setLight(newlight);
+ n2.setLight(bank, newlight);
block->setNode(relpos, n2);
lighted_nodes.insert(n2pos, true);
//lighted_nodes.push_back(n2pos);
<<std::endl;*/
if(lighted_nodes.size() > 0)
- spreadLight(lighted_nodes, modified_blocks);
+ spreadLight(bank, lighted_nodes, modified_blocks);
}
/*
A single-node source variation of the above.
*/
-void Map::lightNeighbors(v3s16 pos,
+void Map::lightNeighbors(enum LightBank bank,
+ v3s16 pos,
core::map<v3s16, MapBlock*> & modified_blocks)
{
core::map<v3s16, bool> from_nodes;
from_nodes.insert(pos, true);
- spreadLight(from_nodes, modified_blocks);
+ spreadLight(bank, from_nodes, modified_blocks);
}
-v3s16 Map::getBrightestNeighbour(v3s16 p)
+v3s16 Map::getBrightestNeighbour(enum LightBank bank, v3s16 p)
{
v3s16 dirs[6] = {
v3s16(0,0,1), // back
{
continue;
}
- if(n2.getLight() > brightest_light || found_something == false){
- brightest_light = n2.getLight();
+ if(n2.getLight(bank) > brightest_light || found_something == false){
+ brightest_light = n2.getLight(bank);
brightest_pos = n2pos;
found_something = true;
}
if(n.sunlight_propagates())
{
- n.setLight(LIGHT_SUN);
+ n.setLight(LIGHTBANK_DAY, LIGHT_SUN);
block->setNode(relpos, n);
modified_blocks.insert(blockpos, block);
return y + 1;
}
-void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
+void Map::updateLighting(enum LightBank bank,
+ core::map<v3s16, MapBlock*> & a_blocks,
core::map<v3s16, MapBlock*> & modified_blocks)
{
/*m_dout<<DTIME<<"Map::updateLighting(): "
bool debug=false;
u32 count_was = modified_blocks.size();
- /*core::list<MapBlock *>::Iterator i = a_blocks.begin();
- for(; i != a_blocks.end(); i++)
- {
- MapBlock *block = *i;*/
-
core::map<v3s16, bool> light_sources;
core::map<v3s16, u8> unlight_from;
try{
v3s16 p(x,y,z);
MapNode n = block->getNode(v3s16(x,y,z));
- u8 oldlight = n.getLight();
- n.setLight(0);
+ u8 oldlight = n.getLight(bank);
+ n.setLight(bank, 0);
block->setNode(v3s16(x,y,z), n);
// Collect borders for unlighting
}
}
- bool bottom_valid = block->propagateSunlight(light_sources);
+ if(bank == LIGHTBANK_DAY)
+ {
+ bool bottom_valid = block->propagateSunlight(light_sources);
- // If bottom is valid, we're done.
- if(bottom_valid)
+ // If bottom is valid, we're done.
+ if(bottom_valid)
+ break;
+ }
+ else if(bank == LIGHTBANK_NIGHT)
+ {
break;
+ }
+ else
+ {
+ assert(0);
+ }
/*dstream<<"Bottom for sunlight-propagated block ("
<<pos.X<<","<<pos.Y<<","<<pos.Z<<") not valid"
}
{
- //TimeTaker timer("unspreadLight", g_device);
- unspreadLight(unlight_from, light_sources, modified_blocks);
+ //TimeTaker timer("unspreadLight");
+ unspreadLight(bank, unlight_from, light_sources, modified_blocks);
}
if(debug)
// Yes, add it to light_sources... somehow.
// It has to be added at somewhere above, in the loop.
// TODO
- // NOTE: This actually works quite fine without it
+ // NOTE: This actually works fine without doing so
// - Find out why it works
{
- //TimeTaker timer("spreadLight", g_device);
- spreadLight(light_sources, modified_blocks);
+ //TimeTaker timer("spreadLight");
+ spreadLight(bank, light_sources, modified_blocks);
}
if(debug)
//m_dout<<"Done ("<<getTimestamp()<<")"<<std::endl;
}
+void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
+ core::map<v3s16, MapBlock*> & modified_blocks)
+{
+ updateLighting(LIGHTBANK_DAY, a_blocks, modified_blocks);
+ updateLighting(LIGHTBANK_NIGHT, a_blocks, modified_blocks);
+
+ /*
+ Update information about whether day and night light differ
+ */
+ for(core::map<v3s16, MapBlock*>::Iterator
+ i = modified_blocks.getIterator();
+ i.atEnd() == false; i++)
+ {
+ MapBlock *block = i.getNode()->getValue();
+ block->updateDayNightDiff();
+ }
+}
+
/*
This is called after changing a node from transparent to opaque.
The lighting value of the node should be left as-is after changing
m_dout<<DTIME<<"Map::nodeAddedUpdate(): p=("
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
- u8 lightwas = getNode(p).getLight();
-
- //core::list<v3s16> light_sources;
- core::map<v3s16, bool> light_sources;
- //MapNode n = getNode(p);
-
/*
From this node to nodes underneath:
If lighting is sunlight (1.0), unlight neighbours and
Else discontinue.
*/
- bool node_under_sunlight = true;
-
v3s16 toppos = p + v3s16(0,1,0);
+ v3s16 bottompos = p + v3s16(0,-1,0);
+
+ bool node_under_sunlight = true;
+ core::map<v3s16, bool> light_sources;
/*
If there is a node at top and it doesn't have sunlight,
try{
MapNode topnode = getNode(toppos);
- if(topnode.getLight() != LIGHT_SUN)
+ if(topnode.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
node_under_sunlight = false;
}
catch(InvalidPositionException &e)
{
}
-
- // Add the block of the added node to modified_blocks
- v3s16 blockpos = getNodeBlockPos(p);
- MapBlock * block = getBlockNoCreate(blockpos);
- assert(block != NULL);
- modified_blocks.insert(blockpos, block);
- if(isValidPosition(p) == false)
- throw;
+ if(n.d != CONTENT_TORCH)
+ {
+ /*
+ If there is grass below, change it to mud
+ */
+ try{
+ MapNode bottomnode = getNode(bottompos);
+
+ if(bottomnode.d == CONTENT_GRASS
+ || bottomnode.d == CONTENT_GRASS_FOOTSTEPS)
+ {
+ bottomnode.d = CONTENT_MUD;
+ setNode(bottompos, bottomnode);
+ }
+ }
+ catch(InvalidPositionException &e)
+ {
+ }
+ }
+
+ enum LightBank banks[] =
+ {
+ LIGHTBANK_DAY,
+ LIGHTBANK_NIGHT
+ };
+ for(s32 i=0; i<2; i++)
+ {
+ enum LightBank bank = banks[i];
+
+ u8 lightwas = getNode(p).getLight(bank);
+
+ // Add the block of the added node to modified_blocks
+ v3s16 blockpos = getNodeBlockPos(p);
+ MapBlock * block = getBlockNoCreate(blockpos);
+ assert(block != NULL);
+ modified_blocks.insert(blockpos, block);
- // Unlight neighbours of node.
- // This means setting light of all consequent dimmer nodes
- // to 0.
- // This also collects the nodes at the border which will spread
- // light again into this.
- unLightNeighbors(p, lightwas, light_sources, modified_blocks);
-
- n.setLight(0);
+ if(isValidPosition(p) == false)
+ throw;
+
+ // Unlight neighbours of node.
+ // This means setting light of all consequent dimmer nodes
+ // to 0.
+ // This also collects the nodes at the border which will spread
+ // light again into this.
+ unLightNeighbors(bank, p, lightwas, light_sources, modified_blocks);
+
+ n.setLight(bank, 0);
+ }
+
setNode(p, n);
/*
If node is under sunlight, take all sunlighted nodes under
it and clear light from them and from where the light has
been spread.
+ TODO: This could be optimized by mass-unlighting instead
+ of looping
*/
if(node_under_sunlight)
{
break;
}
- if(n2.getLight() == LIGHT_SUN)
+ if(n2.getLight(LIGHTBANK_DAY) == LIGHT_SUN)
{
//m_dout<<DTIME<<"doing"<<std::endl;
- unLightNeighbors(n2pos, n2.getLight(), light_sources, modified_blocks);
- n2.setLight(0);
+ unLightNeighbors(LIGHTBANK_DAY,
+ n2pos, n2.getLight(LIGHTBANK_DAY),
+ light_sources, modified_blocks);
+ n2.setLight(LIGHTBANK_DAY, 0);
setNode(n2pos, n2);
}
else
}
}
+ for(s32 i=0; i<2; i++)
+ {
+ enum LightBank bank = banks[i];
+
+ /*
+ Spread light from all nodes that might be capable of doing so
+ TODO: Convert to spreadLight
+ */
+ spreadLight(bank, light_sources, modified_blocks);
+ }
+
/*
- Spread light from all nodes that might be capable of doing so
- TODO: Convert to spreadLight
+ Update information about whether day and night light differ
*/
- spreadLight(light_sources, modified_blocks);
+ for(core::map<v3s16, MapBlock*>::Iterator
+ i = modified_blocks.getIterator();
+ i.atEnd() == false; i++)
+ {
+ MapBlock *block = i.getNode()->getValue();
+ block->updateDayNightDiff();
+ }
}
/*
// Node will be replaced with this
u8 replace_material = CONTENT_AIR;
- // NOTE: Water is now managed elsewhere
-#if 0
- {
- /*
- Find out with what material the node will be replaced.
- It will be replaced with the mostly seen buildable_to.
- */
-
- 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
- };
-
- core::map<u8, u16> neighbor_rankings;
-
- for(u32 i=0; i<sizeof(dirs)/sizeof(dirs[0]); i++)
- {
- try{
- MapNode n2 = getNode(p + dirs[i]);
-
- if(material_buildable_to(n2.d))
- {
- if(neighbor_rankings.find(n2.d) == NULL)
- neighbor_rankings[n2.d] = 1;
- else
- neighbor_rankings[n2.d]
- = neighbor_rankings[n2.d] + 1;
- }
- }
- catch(InvalidPositionException &e)
- {
- }
- }
-
- u16 highest_ranking = 0;
-
- for(core::map<u8, u16>::Iterator
- i = neighbor_rankings.getIterator();
- i.atEnd() == false; i++)
- {
- u8 m = i.getNode()->getKey();
- u8 c = i.getNode()->getValue();
- if(
- c > highest_ranking ||
- // Prefer something else than air
- (c >= highest_ranking && m != CONTENT_AIR)
-
- )
- {
- replace_material = m;
- highest_ranking = c;
- }
- }
- }
-
-#endif
-
/*
If there is a node at top and it doesn't have sunlight,
there will be no sunlight going down.
try{
MapNode topnode = getNode(toppos);
- if(topnode.getLight() != LIGHT_SUN)
+ if(topnode.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
node_under_sunlight = false;
}
catch(InvalidPositionException &e)
{
}
- /*
- Unlight neighbors (in case the node is a light source)
- */
- //core::list<v3s16> light_sources;
core::map<v3s16, bool> light_sources;
- unLightNeighbors(p, getNode(p).getLight(),
- light_sources, modified_blocks);
+
+ enum LightBank banks[] =
+ {
+ LIGHTBANK_DAY,
+ LIGHTBANK_NIGHT
+ };
+ for(s32 i=0; i<2; i++)
+ {
+ enum LightBank bank = banks[i];
+
+ /*
+ Unlight neighbors (in case the node is a light source)
+ */
+ unLightNeighbors(bank, p,
+ getNode(p).getLight(bank),
+ light_sources, modified_blocks);
+ }
/*
- Remove the node
+ Remove the node.
+ This also clears the lighting.
*/
+
MapNode n;
n.d = replace_material;
- n.setLight(0);
setNode(p, n);
- /*
- Recalculate lighting
- */
- spreadLight(light_sources, modified_blocks);
+ for(s32 i=0; i<2; i++)
+ {
+ enum LightBank bank = banks[i];
+
+ /*
+ Recalculate lighting
+ */
+ spreadLight(bank, light_sources, modified_blocks);
+ }
// Add the block of the removed node to modified_blocks
v3s16 blockpos = getNodeBlockPos(p);
/*m_dout<<DTIME<<"lighting neighbors of node ("
<<p2.X<<","<<p2.Y<<","<<p2.Z<<")"
<<std::endl;*/
- lightNeighbors(p2, modified_blocks);
+ lightNeighbors(LIGHTBANK_DAY, p2, modified_blocks);
+ }
+ }
+ else
+ {
+ // Set the lighting of this node to 0
+ // TODO: Is this needed? Lighting is cleared up there already.
+ try{
+ MapNode n = getNode(p);
+ n.setLight(LIGHTBANK_DAY, 0);
+ setNode(p, n);
+ }
+ catch(InvalidPositionException &e)
+ {
+ throw;
+ }
+ }
+
+ for(s32 i=0; i<2; i++)
+ {
+ enum LightBank bank = banks[i];
+
+ // Get the brightest neighbour node and propagate light from it
+ v3s16 n2p = getBrightestNeighbour(bank, p);
+ try{
+ MapNode n2 = getNode(n2p);
+ lightNeighbors(bank, n2p, modified_blocks);
+ }
+ catch(InvalidPositionException &e)
+ {
}
}
- else
- {
- // Set the lighting of this node to 0
- try{
- MapNode n = getNode(p);
- n.setLight(0);
- setNode(p, n);
- }
- catch(InvalidPositionException &e)
- {
- throw;
- }
+
+ /*
+ Update information about whether day and night light differ
+ */
+ for(core::map<v3s16, MapBlock*>::Iterator
+ i = modified_blocks.getIterator();
+ i.atEnd() == false; i++)
+ {
+ MapBlock *block = i.getNode()->getValue();
+ block->updateDayNightDiff();
+ }
+}
+
+#ifndef SERVER
+void Map::expireMeshes(bool only_daynight_diffed)
+{
+ TimeTaker timer("expireMeshes()");
+
+ core::map<v2s16, MapSector*>::Iterator si;
+ si = m_sectors.getIterator();
+ for(; si.atEnd() == false; si++)
+ {
+ MapSector *sector = si.getNode()->getValue();
+
+ core::list< MapBlock * > sectorblocks;
+ sector->getBlocks(sectorblocks);
+
+ core::list< MapBlock * >::Iterator i;
+ for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
+ {
+ MapBlock *block = *i;
+
+ if(only_daynight_diffed && dayNightDiffed(block->getPos()) == false)
+ {
+ continue;
+ }
+
+ {
+ JMutexAutoLock lock(block->mesh_mutex);
+ if(block->mesh != NULL)
+ {
+ /*block->mesh->drop();
+ block->mesh = NULL;*/
+ block->setMeshExpired(true);
+ }
+ }
+ }
+ }
+}
+
+void Map::updateMeshes(v3s16 blockpos, u32 daynight_ratio)
+{
+ assert(mapType() == MAPTYPE_CLIENT);
+
+ try{
+ v3s16 p = blockpos + v3s16(0,0,0);
+ MapBlock *b = getBlockNoCreate(p);
+ b->updateMesh(daynight_ratio);
+ }
+ catch(InvalidPositionException &e){}
+ // Leading edge
+ try{
+ v3s16 p = blockpos + v3s16(-1,0,0);
+ MapBlock *b = getBlockNoCreate(p);
+ b->updateMesh(daynight_ratio);
+ }
+ catch(InvalidPositionException &e){}
+ try{
+ v3s16 p = blockpos + v3s16(0,-1,0);
+ MapBlock *b = getBlockNoCreate(p);
+ b->updateMesh(daynight_ratio);
+ }
+ catch(InvalidPositionException &e){}
+ try{
+ v3s16 p = blockpos + v3s16(0,0,-1);
+ MapBlock *b = getBlockNoCreate(p);
+ b->updateMesh(daynight_ratio);
}
-
- // Get the brightest neighbour node and propagate light from it
- v3s16 n2p = getBrightestNeighbour(p);
+ catch(InvalidPositionException &e){}
+ /*// Trailing edge
try{
- MapNode n2 = getNode(n2p);
- lightNeighbors(n2p, modified_blocks);
+ v3s16 p = blockpos + v3s16(1,0,0);
+ MapBlock *b = getBlockNoCreate(p);
+ b->updateMesh(daynight_ratio);
}
- catch(InvalidPositionException &e)
- {
+ catch(InvalidPositionException &e){}
+ try{
+ v3s16 p = blockpos + v3s16(0,1,0);
+ MapBlock *b = getBlockNoCreate(p);
+ b->updateMesh(daynight_ratio);
+ }
+ catch(InvalidPositionException &e){}
+ try{
+ v3s16 p = blockpos + v3s16(0,0,1);
+ MapBlock *b = getBlockNoCreate(p);
+ b->updateMesh(daynight_ratio);
}
+ catch(InvalidPositionException &e){}*/
}
-void Map::updateMeshes(v3s16 blockpos)
-{
- assert(mapType() == MAPTYPE_CLIENT);
+#endif
+bool Map::dayNightDiffed(v3s16 blockpos)
+{
try{
v3s16 p = blockpos + v3s16(0,0,0);
MapBlock *b = getBlockNoCreate(p);
- b->updateMesh();
+ if(b->dayNightDiffed())
+ return true;
}
catch(InvalidPositionException &e){}
+ // Leading edges
try{
v3s16 p = blockpos + v3s16(-1,0,0);
MapBlock *b = getBlockNoCreate(p);
- b->updateMesh();
+ if(b->dayNightDiffed())
+ return true;
}
catch(InvalidPositionException &e){}
try{
v3s16 p = blockpos + v3s16(0,-1,0);
MapBlock *b = getBlockNoCreate(p);
- b->updateMesh();
+ if(b->dayNightDiffed())
+ return true;
}
catch(InvalidPositionException &e){}
try{
v3s16 p = blockpos + v3s16(0,0,-1);
MapBlock *b = getBlockNoCreate(p);
- b->updateMesh();
+ if(b->dayNightDiffed())
+ return true;
+ }
+ catch(InvalidPositionException &e){}
+ // Trailing edges
+ try{
+ v3s16 p = blockpos + v3s16(1,0,0);
+ MapBlock *b = getBlockNoCreate(p);
+ if(b->dayNightDiffed())
+ return true;
+ }
+ catch(InvalidPositionException &e){}
+ try{
+ v3s16 p = blockpos + v3s16(0,1,0);
+ MapBlock *b = getBlockNoCreate(p);
+ if(b->dayNightDiffed())
+ return true;
+ }
+ catch(InvalidPositionException &e){}
+ try{
+ v3s16 p = blockpos + v3s16(0,0,1);
+ MapBlock *b = getBlockNoCreate(p);
+ if(b->dayNightDiffed())
+ return true;
}
catch(InvalidPositionException &e){}
+
+ return false;
}
/*
tree_max = a / (t/0.03);
else
tree_max = a;
- u32 count = (rand()%(tree_max+1));
+ u32 count = (myrand()%(tree_max+1));
//u32 count = tree_max;
for(u32 i=0; i<count; i++)
{
- s16 x = (rand()%(MAP_BLOCKSIZE-2))+1;
- s16 z = (rand()%(MAP_BLOCKSIZE-2))+1;
+ s16 x = (myrand()%(MAP_BLOCKSIZE-2))+1;
+ s16 z = (myrand()%(MAP_BLOCKSIZE-2))+1;
s16 y = sector->getGroundHeight(v2s16(x,z))+1;
if(y < WATER_LEVEL)
continue;
bush_max = (pitness*a*4);
if(bush_max > a)
bush_max = a;
- u32 count = (rand()%(bush_max+1));
+ u32 count = (myrand()%(bush_max+1));
for(u32 i=0; i<count; i++)
{
- s16 x = rand()%(MAP_BLOCKSIZE-0)+0;
- s16 z = rand()%(MAP_BLOCKSIZE-0)+0;
+ s16 x = myrand()%(MAP_BLOCKSIZE-0)+0;
+ s16 z = myrand()%(MAP_BLOCKSIZE-0)+0;
s16 y = sector->getGroundHeight(v2s16(x,z))+1;
if(y < WATER_LEVEL)
continue;
*/
if(m_params.ravines_amount != 0)
{
- if(rand()%(s32)(20.0 / m_params.ravines_amount) == 0)
+ if(myrand()%(s32)(20.0 / m_params.ravines_amount) == 0)
{
s16 s = 6;
- s16 x = rand()%(MAP_BLOCKSIZE-s*2-1)+s;
- s16 z = rand()%(MAP_BLOCKSIZE-s*2-1)+s;
+ s16 x = myrand()%(MAP_BLOCKSIZE-s*2-1)+s;
+ s16 z = myrand()%(MAP_BLOCKSIZE-s*2-1)+s;
/*s16 x = 8;
s16 z = 8;*/
s16 y = sector->getGroundHeight(v2s16(x,z))+1;
}
//dstream<<"Not found on disk, generating."<<std::endl;
+ //TimeTaker("emergeBlock()", g_irrlicht);
/*
Do not generate over-limit
// Allocate the block to be a proper one.
block->unDummify();
}
-
- // Randomize a bit. This makes dungeons.
- /*bool low_block_is_empty = false;
- if(rand() % 4 == 0)
- low_block_is_empty = true;*/
- const s32 ued = 4;
- //const s32 ued = 8;
- bool underground_emptiness[ued*ued*ued];
+#if 0
+ /*
+ Initialize dungeon making by creating a random table
+ */
+ const s32 ued_max = 5;
+ const s32 ued_min = 3;
+ bool underground_emptiness[ued_max*ued_max*ued_max];
+ s32 ued = (myrand()%(ued_max-ued_min+1))+1;
+ //s32 ued = ued_max;
for(s32 i=0; i<ued*ued*ued; i++)
{
- underground_emptiness[i] = ((rand() % 5) == 0);
+ underground_emptiness[i] = ((myrand() % 5) == 0);
}
-#if 0
/*
This is a messy hack to sort the emptiness a bit
*/
+ // Iterator through a few times
for(s32 j=0; j<2; j++)
for(s32 y0=0; y0<ued; y0++)
for(s32 z0=0; z0<ued; z0++)
/*v3s16(0,1,0), // top
v3s16(0,-1,0), // bottom*/
};
+
for(s32 i=0; i<4; i++)
{
v3s16 p1 = p0 + dirs[i];
}
}
#endif
+
+ /*
+ Create dungeon making table
+ */
+ const s32 ued = MAP_BLOCKSIZE;
+ bool underground_emptiness[ued*ued*ued];
+ for(s32 i=0; i<ued*ued*ued; i++)
+ {
+ underground_emptiness[i] = 0;
+ }
+ // Generate dungeons
+ {
+ /*
+ Initialize orp and ors. Try to find if some neighboring
+ MapBlock has a tunnel ended in its side
+ */
+
+ v3f orp(
+ (float)(myrand()%ued)+0.5,
+ (float)(myrand()%ued)+0.5,
+ (float)(myrand()%ued)+0.5
+ );
+
+ // Check z-
+ try
+ {
+ s16 z = -1;
+ for(s16 y=0; y<ued; y++)
+ for(s16 x=0; x<ued; x++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ if(getNode(ap).d == CONTENT_AIR)
+ {
+ orp = v3f(x+1,y+1,0);
+ goto continue_generating;
+ }
+ }
+ }
+ catch(InvalidPositionException &e){}
+
+ // Check z+
+ try
+ {
+ s16 z = ued;
+ for(s16 y=0; y<ued; y++)
+ for(s16 x=0; x<ued; x++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ if(getNode(ap).d == CONTENT_AIR)
+ {
+ orp = v3f(x+1,y+1,ued-1);
+ goto continue_generating;
+ }
+ }
+ }
+ catch(InvalidPositionException &e){}
+
+ // Check x-
+ try
+ {
+ s16 x = -1;
+ for(s16 y=0; y<ued; y++)
+ for(s16 z=0; z<ued; z++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ if(getNode(ap).d == CONTENT_AIR)
+ {
+ orp = v3f(0,y+1,z+1);
+ goto continue_generating;
+ }
+ }
+ }
+ catch(InvalidPositionException &e){}
+
+ // Check x+
+ try
+ {
+ s16 x = ued;
+ for(s16 y=0; y<ued; y++)
+ for(s16 z=0; z<ued; z++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ if(getNode(ap).d == CONTENT_AIR)
+ {
+ orp = v3f(ued-1,y+1,z+1);
+ goto continue_generating;
+ }
+ }
+ }
+ catch(InvalidPositionException &e){}
+
+continue_generating:
+
+ /*
+ Generate some tunnel starting from orp and ors
+ */
+ for(u16 i=0; i<3; i++)
+ {
+ v3f rp(
+ (float)(myrand()%ued)+0.5,
+ (float)(myrand()%ued)+0.5,
+ (float)(myrand()%ued)+0.5
+ );
+ s16 min_d = 0;
+ s16 max_d = 4;
+ s16 rs = (myrand()%(max_d-min_d+1))+min_d;
+
+ v3f vec = rp - orp;
+
+ for(float f=0; f<1.0; f+=0.04)
+ {
+ v3f fp = orp + vec * f;
+ v3s16 cp(fp.X, fp.Y, fp.Z);
+ s16 d0 = -rs/2;
+ s16 d1 = d0 + rs - 1;
+ for(s16 z0=d0; z0<=d1; z0++)
+ {
+ s16 si = rs - abs(z0);
+ for(s16 x0=-si; x0<=si-1; x0++)
+ {
+ s16 si2 = rs - abs(x0);
+ for(s16 y0=-si2+1; y0<=si2-1; y0++)
+ {
+ s16 z = cp.Z + z0;
+ s16 y = cp.Y + y0;
+ s16 x = cp.X + x0;
+ v3s16 p(x,y,z);
+ if(isInArea(p, ued) == false)
+ continue;
+ underground_emptiness[ued*ued*z + ued*y + x] = 1;
+ }
+ }
+ }
+ }
+
+ orp = rp;
+ }
+ }
// This is the basic material of what the visible flat ground
// will consist of
newly created block, they won't be taken into account.
*/
if(real_y > surface_y)
- n.setLight(LIGHT_SUN);
+ n.setLight(LIGHTBANK_DAY, LIGHT_SUN);
/*
Calculate material
*/
- // If node is very low
- /*if(real_y <= surface_y - 7)
- {
- // Create dungeons
- if(underground_emptiness[
- ued*ued*(z0*ued/MAP_BLOCKSIZE)
- +ued*(y0*ued/MAP_BLOCKSIZE)
- +(x0*ued/MAP_BLOCKSIZE)])
- {
- n.d = CONTENT_AIR;
- }
- else
- {
- n.d = CONTENT_STONE;
- }
- }
- // If node is under surface level
- else if(real_y <= surface_y - surface_depth)
- n.d = CONTENT_STONE;
- */
if(real_y <= surface_y - surface_depth)
{
// Create dungeons
if(real_y < WATER_LEVEL)
{
n.d = water_material;
- n.setLight(diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
+ n.setLight(LIGHTBANK_DAY,
+ diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
}
// else air
else
Add some minerals
*/
- //if(is_underground)
if(some_part_underground)
{
s16 underground_level = (lowest_ground_y/MAP_BLOCKSIZE - block_y)+1;
- for(s16 i=0; i<underground_level*3; i++)
+
+ /*
+ Add meseblocks
+ */
+ for(s16 i=0; i<underground_level*1; i++)
{
- if(rand()%2 == 0)
+ if(myrand()%2 == 0)
{
v3s16 cp(
- (rand()%(MAP_BLOCKSIZE-2))+1,
- (rand()%(MAP_BLOCKSIZE-2))+1,
- (rand()%(MAP_BLOCKSIZE-2))+1
+ (myrand()%(MAP_BLOCKSIZE-2))+1,
+ (myrand()%(MAP_BLOCKSIZE-2))+1,
+ (myrand()%(MAP_BLOCKSIZE-2))+1
);
MapNode n;
//if(is_ground_content(block->getNode(cp).d))
if(block->getNode(cp).d == CONTENT_STONE)
- if(rand()%8 == 0)
+ if(myrand()%8 == 0)
+ block->setNode(cp, n);
+
+ for(u16 i=0; i<26; i++)
+ {
+ //if(is_ground_content(block->getNode(cp+g_26dirs[i]).d))
+ if(block->getNode(cp+g_26dirs[i]).d == CONTENT_STONE)
+ if(myrand()%8 == 0)
+ block->setNode(cp+g_26dirs[i], n);
+ }
+ }
+ }
+
+ /*
+ Add coal
+ */
+ u16 coal_amount = 30.0 * g_settings.getFloat("coal_amount");
+ u16 coal_rareness = 60 / coal_amount;
+ if(coal_rareness == 0)
+ coal_rareness = 1;
+ if(myrand()%coal_rareness == 0)
+ {
+ u16 a = myrand() % 16;
+ u16 amount = coal_amount * a*a*a / 1000;
+ for(s16 i=0; i<amount; i++)
+ {
+ v3s16 cp(
+ (myrand()%(MAP_BLOCKSIZE-2))+1,
+ (myrand()%(MAP_BLOCKSIZE-2))+1,
+ (myrand()%(MAP_BLOCKSIZE-2))+1
+ );
+
+ MapNode n;
+ n.d = CONTENT_COALSTONE;
+
+ //dstream<<"Adding coalstone"<<std::endl;
+
+ //if(is_ground_content(block->getNode(cp).d))
+ if(block->getNode(cp).d == CONTENT_STONE)
+ if(myrand()%8 == 0)
block->setNode(cp, n);
for(u16 i=0; i<26; i++)
{
//if(is_ground_content(block->getNode(cp+g_26dirs[i]).d))
if(block->getNode(cp+g_26dirs[i]).d == CONTENT_STONE)
- if(rand()%8 == 0)
+ if(myrand()%8 == 0)
block->setNode(cp+g_26dirs[i], n);
}
}
//for(u16 i=0; i<2; i++)
{
v3s16 cp(
- (rand()%(MAP_BLOCKSIZE-2))+1,
- (rand()%(MAP_BLOCKSIZE-2))+1,
- (rand()%(MAP_BLOCKSIZE-2))+1
+ (myrand()%(MAP_BLOCKSIZE-2))+1,
+ (myrand()%(MAP_BLOCKSIZE-2))+1,
+ (myrand()%(MAP_BLOCKSIZE-2))+1
);
// Check that the place is empty
*/
sector->insertBlock(block);
- /*
- Do some interpolation for dungeons
- */
-
-#if 0
- {
- TimeTaker timer("interpolation", g_device);
-
- MapVoxelManipulator vmanip(this);
-
- v3s16 relpos = block->getPosRelative();
-
- vmanip.interpolate(VoxelArea(relpos-v3s16(1,1,1),
- relpos+v3s16(1,1,1)*(MAP_BLOCKSIZE+1)));
- /*vmanip.interpolate(VoxelArea(relpos,
- relpos+v3s16(1,1,1)*(MAP_BLOCKSIZE-1)));*/
-
- core::map<v3s16, MapBlock*> modified_blocks;
- vmanip.blitBack(modified_blocks);
- dstream<<"blitBack modified "<<modified_blocks.size()
- <<" blocks"<<std::endl;
-
- // Add modified blocks to changed_blocks and lighting_invalidated_blocks
- for(core::map<v3s16, MapBlock*>::Iterator
- i = modified_blocks.getIterator();
- i.atEnd() == false; i++)
- {
- MapBlock *block = i.getNode()->getValue();
-
- changed_blocks.insert(block->getPos(), block);
- //lighting_invalidated_blocks.insert(block->getPos(), block);
- }
-
- }
-#endif
-
/*
Sector object stuff
*/
n.d = CONTENT_STONE;
MapNode n2;
n2.d = CONTENT_AIR;
- s16 depth = maxdepth + (rand()%10);
+ s16 depth = maxdepth + (myrand()%10);
s16 z = 0;
s16 minz = -6 - (-2);
s16 maxz = 6 -1;
for(s16 x=-6; x<=6; x++)
{
- z += -1 + (rand()%3);
+ z += -1 + (myrand()%3);
if(z < minz)
z = minz;
if(z > maxz)
z = maxz;
- for(s16 y=depth+(rand()%2); y<=6; y++)
+ for(s16 y=depth+(myrand()%2); y<=6; y++)
{
/*std::cout<<"("<<p2.X<<","<<p2.Y<<","<<p2.Z<<")"
<<std::endl;*/
{
v3s16 p2 = p + v3s16(x,y,z-2);
- if(is_ground_content(sector->getNode(p2).d))
+ if(is_ground_content(sector->getNode(p2).d)
+ && !is_mineral(sector->getNode(p2).d))
sector->setNode(p2, n);
}
{
v3s16 p2 = p + v3s16(x,y,z-1);
- if(is_ground_content(sector->getNode(p2).d))
+ if(is_ground_content(sector->getNode(p2).d)
+ && !is_mineral(sector->getNode(p2).d))
sector->setNode(p2, n2);
}
{
v3s16 p2 = p + v3s16(x,y,z+0);
- if(is_ground_content(sector->getNode(p2).d))
+ if(is_ground_content(sector->getNode(p2).d)
+ && !is_mineral(sector->getNode(p2).d))
sector->setNode(p2, n2);
}
{
v3s16 p2 = p + v3s16(x,y,z+1);
- if(is_ground_content(sector->getNode(p2).d))
+ if(is_ground_content(sector->getNode(p2).d)
+ && !is_mineral(sector->getNode(p2).d))
sector->setNode(p2, n);
}
}//sectorlock
- u32 deleted_count = 0;
- deleted_count = deleteUnusedSectors
- (SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT);
-
/*
Only print if something happened or saved whole map
*/
if(only_changed == false || sector_meta_count != 0
- || block_count != 0 || deleted_count != 0)
+ || block_count != 0)
{
dstream<<DTIME<<"ServerMap: Written: "
<<sector_meta_count<<" sector metadata files, "
- <<block_count<<" block files, "
- <<deleted_count<<" sectors unloaded from memory."
+ <<block_count<<" block files"
<<std::endl;
}
}
*/
if(version >= 9)
{
- block->updateObjects(is, version, NULL);
+ block->updateObjects(is, version, NULL, 0);
}
if(created_new)
out<<"ServerMap: ";
}
+#ifndef SERVER
+
/*
ClientMap
*/
ClientMap::ClientMap(
Client *client,
+ MapDrawControl &control,
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id
Map(dout_client),
scene::ISceneNode(parent, mgr, id),
m_client(client),
- mesh(NULL)
+ mesh(NULL),
+ m_control(control)
{
+ mesh_mutex.Init();
+
/*m_box = core::aabbox3d<f32>(0,0,0,
map->getW()*BS, map->getH()*BS, map->getD()*BS);*/
/*m_box = core::aabbox3d<f32>(0,0,0,
map->getSizeNodes().Z * BS);*/
m_box = core::aabbox3d<f32>(-BS*1000000,-BS*1000000,-BS*1000000,
BS*1000000,BS*1000000,BS*1000000);
-
- mesh_mutex.Init();
+
+ //setPosition(v3f(BS,BS,BS));
}
ClientMap::~ClientMap()
*/
int time1 = time(0);
- /*
- Collect all blocks that are in the view range
-
- Should not optimize more here as we want to auto-update
- all changed nodes in viewing range at the next step.
- */
-
- s16 viewing_range_nodes;
- bool viewing_range_all;
- {
- JMutexAutoLock lock(g_range_mutex);
- viewing_range_nodes = g_viewing_range_nodes;
- viewing_range_all = g_viewing_range_all;
- }
+ u32 daynight_ratio = m_client->getDayNightRatio();
m_camera_mutex.Lock();
v3f camera_position = m_camera_position;
camera_position.Y / BS,
camera_position.Z / BS);
- v3s16 box_nodes_d = viewing_range_nodes * v3s16(1,1,1);
+ v3s16 box_nodes_d = m_control.wanted_range * v3s16(1,1,1);
v3s16 p_nodes_min = cam_pos_nodes - box_nodes_d;
v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d;
u32 vertex_count = 0;
- core::map<v2s16, MapSector*>::Iterator si;
+ // For limiting number of mesh updates per frame
+ u32 mesh_update_count = 0;
+
+ u32 blocks_would_have_drawn = 0;
+ u32 blocks_drawn = 0;
//NOTE: The sectors map should be locked but we're not doing it
// because it'd cause too much delays
+ int timecheck_counter = 0;
+ core::map<v2s16, MapSector*>::Iterator si;
si = m_sectors.getIterator();
for(; si.atEnd() == false; si++)
{
{
- static int timecheck_counter = 0;
timecheck_counter++;
if(timecheck_counter > 50)
{
MapSector *sector = si.getNode()->getValue();
v2s16 sp = sector->getPos();
- if(viewing_range_all == false)
+ if(m_control.range_all == false)
{
if(sp.X < p_blocks_min.X
|| sp.X > p_blocks_max.X
// Total distance
f32 d = blockpos_relative.getLength();
- if(viewing_range_all == false)
+ if(m_control.range_all == false)
{
// If block is far away, don't draw it
- if(d > viewing_range_nodes * BS)
+ if(d > m_control.wanted_range * BS)
// This is nicer when fog is used
- //if((dforward+d)/2 > viewing_range_nodes * BS)
+ //if((dforward+d)/2 > m_control.wanted_range * BS)
continue;
}
/*
Draw the faces of the block
*/
+#if 1
+ bool mesh_expired = false;
+
+ {
+ JMutexAutoLock lock(block->mesh_mutex);
+
+ mesh_expired = block->getMeshExpired();
+
+ // Mesh has not been expired and there is no mesh:
+ // block has no content
+ if(block->mesh == NULL && mesh_expired == false)
+ continue;
+ }
+
+ f32 faraway = BS*50;
+ //f32 faraway = m_control.wanted_range * BS;
+
+ /*
+ This has to be done with the mesh_mutex unlocked
+ */
+ if(mesh_expired && mesh_update_count < 6
+ && (d < faraway || mesh_update_count < 3))
+ //if(mesh_expired && mesh_update_count < 4)
+ {
+ mesh_update_count++;
+
+ // Mesh has been expired: generate new mesh
+ //block->updateMeshes(daynight_i);
+ block->updateMesh(daynight_ratio);
+
+ mesh_expired = false;
+ }
+ /*
+ Don't draw an expired mesh that is far away
+ */
+ /*if(mesh_expired && d >= faraway)
+ //if(mesh_expired)
+ {
+ // Instead, delete it
+ JMutexAutoLock lock(block->mesh_mutex);
+ if(block->mesh)
+ {
+ block->mesh->drop();
+ block->mesh = NULL;
+ }
+ // And continue to next block
+ continue;
+ }*/
+#endif
{
JMutexAutoLock lock(block->mesh_mutex);
- // Cancel if block has no mesh
- if(block->mesh == NULL)
+ scene::SMesh *mesh = block->mesh;
+
+ if(mesh == NULL)
+ continue;
+
+ blocks_would_have_drawn++;
+ if(blocks_drawn >= m_control.wanted_max_blocks
+ && m_control.range_all == false
+ && d > m_control.wanted_min_range * BS)
continue;
+ blocks_drawn++;
- u32 c = block->mesh->getMeshBufferCount();
+ u32 c = mesh->getMeshBufferCount();
for(u32 i=0; i<c; i++)
{
- scene::IMeshBuffer *buf = block->mesh->getMeshBuffer(i);
+ scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
const video::SMaterial& material = buf->getMaterial();
video::IMaterialRenderer* rnd =
driver->getMaterialRenderer(material.MaterialType);
}
} // foreach sectorblocks
}
+
+ m_control.blocks_drawn = blocks_drawn;
+ m_control.blocks_would_have_drawn = blocks_would_have_drawn;
/*dstream<<"renderMap(): is_transparent_pass="<<is_transparent_pass
<<", rendered "<<vertex_count<<" vertices."<<std::endl;*/
}
-void ClientMap::updateMesh()
+v3s16 ClientMap::setTempMod(v3s16 p, NodeMod mod)
+{
+ /*
+ Add it to all blocks touching it
+ */
+ v3s16 dirs[7] = {
+ v3s16(0,0,0), // this
+ 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<7; i++)
+ {
+ v3s16 p2 = p + dirs[i];
+ // Block position of neighbor (or requested) node
+ v3s16 blockpos = getNodeBlockPos(p2);
+ MapBlock * blockref = getBlockNoCreateNoEx(blockpos);
+ if(blockref == NULL)
+ continue;
+ // Relative position of requested node
+ v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
+ blockref->setTempMod(relpos, mod);
+ }
+ return getNodeBlockPos(p);
+}
+v3s16 ClientMap::clearTempMod(v3s16 p)
{
- //TODO: Remove this
+ v3s16 dirs[7] = {
+ v3s16(0,0,0), // this
+ 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<7; i++)
+ {
+ v3s16 p2 = p + dirs[i];
+ // Block position of neighbor (or requested) node
+ v3s16 blockpos = getNodeBlockPos(p2);
+ MapBlock * blockref = getBlockNoCreateNoEx(blockpos);
+ if(blockref == NULL)
+ continue;
+ // Relative position of requested node
+ v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
+ blockref->clearTempMod(relpos);
+ }
+ return getNodeBlockPos(p);
}
void ClientMap::PrintInfo(std::ostream &out)
out<<"ClientMap: ";
}
+#endif // !SERVER
/*
MapVoxelManipulator
#if 1
void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
{
- TimeTaker timer1("emerge", g_device, &emerge_time);
+ TimeTaker timer1("emerge", &emerge_time);
// Units of these are MapBlocks
v3s16 p_min = getNodeBlockPos(a.MinEdge);
bool block_data_inexistent = false;
try
{
- TimeTaker timer1("emerge load", g_device, &emerge_load_time);
+ TimeTaker timer1("emerge load", &emerge_load_time);
/*dstream<<"Loading block (caller_id="<<caller_id<<")"
<<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
#if 0
void MapVoxelManipulator::emerge(VoxelArea a)
{
- TimeTaker timer1("emerge", g_device, &emerge_time);
+ TimeTaker timer1("emerge", &emerge_time);
v3s16 size = a.getExtent();
continue;
try
{
- TimeTaker timer1("emerge load", g_device, &emerge_load_time);
+ TimeTaker timer1("emerge load", &emerge_load_time);
MapNode n = m_map->getNode(a.MinEdge + p);
m_data[i] = n;
m_flags[i] = 0;
if(m_area.getExtent() == v3s16(0,0,0))
return;
- //TimeTaker timer1("blitBack", g_device);
+ //TimeTaker timer1("blitBack");
/*
Initialize block cache