summaryrefslogtreecommitdiff
path: root/src/map.cpp
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2010-11-29 10:52:07 +0200
committerPerttu Ahola <celeron55@gmail.com>2010-11-29 10:52:07 +0200
commitc707e00195f1035ae535f3fc8697af42e73190c0 (patch)
tree0e3c2553bb4726821e49dad599f64ecb5b3cec96 /src/map.cpp
parente8fd5eb8eebbf12b0561d385ef8bc245d87e9ea6 (diff)
downloadminetest-c707e00195f1035ae535f3fc8697af42e73190c0.tar.gz
minetest-c707e00195f1035ae535f3fc8697af42e73190c0.tar.bz2
minetest-c707e00195f1035ae535f3fc8697af42e73190c0.zip
sitä sun tätä tekeillä, toimii kivasti
Diffstat (limited to 'src/map.cpp')
-rw-r--r--src/map.cpp419
1 files changed, 312 insertions, 107 deletions
diff --git a/src/map.cpp b/src/map.cpp
index 35bf8bb40..33f40f064 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -9,6 +9,7 @@
#include "client.h"
#include "filesys.h"
#include "utility.h"
+#include "voxel.h"
#ifdef _WIN32
#include <windows.h>
@@ -18,6 +19,47 @@
#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;
+}
+
+/*
+ Map
+*/
+
Map::Map(std::ostream &dout):
m_dout(dout),
m_camera_position(0,0,0),
@@ -158,33 +200,11 @@ bool Map::isNodeUnderground(v3s16 p)
}
}
-#ifdef LKJnb
-//TODO: Remove: Not used.
-/*
- Goes recursively through the neighbours of the node.
-
- Alters only transparent nodes.
-
- If the lighting of the neighbour is lower than the lighting of
- the node was (before changing it to 0 at the step before), the
- lighting of the neighbour is set to 0 and then the same stuff
- repeats for the neighbour.
-
- Some things are made strangely to make it as fast as possible.
-
- Usage: (for clearing all possible spreaded light of a lamp)
- NOTE: This is outdated
- core::list<v3s16> light_sources;
- core::map<v3s16, MapBlock*> modified_blocks;
- u8 oldlight = node_at_pos.light;
- node_at_pos.setLight(0);
- unLightNeighbors(pos, oldlight, light_sources, modified_blocks);
-*/
-void Map::unLightNeighbors(v3s16 pos, u8 oldlight,
- core::map<v3s16, bool> & light_sources,
- core::map<v3s16, MapBlock*> & modified_blocks)
+#if 0
+void Map::interpolate(v3s16 block,
+ core::map<v3s16, MapBlock*> & modified_blocks)
{
- v3s16 dirs[6] = {
+ const v3s16 dirs[6] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
v3s16(1,0,0), // right
@@ -192,7 +212,16 @@ void Map::unLightNeighbors(v3s16 pos, u8 oldlight,
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
*/
@@ -201,23 +230,22 @@ void Map::unLightNeighbors(v3s16 pos, u8 oldlight,
// Cache this a bit, too
bool block_checked_in_modified = false;
- // Loop through 6 neighbors
- for(u16 i=0; i<6; i++){
- // Get the position of the neighbor node
- v3s16 n2pos = pos + dirs[i];
+ 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);
- // Get the block where the node is located
- v3s16 blockpos = getNodeBlockPos(n2pos);
-
// Only fetch a new block if the block position has changed
try{
- if(block == NULL || blockpos != blockpos_last)
- {
+ if(block == NULL || blockpos != blockpos_last){
block = getBlockNoCreate(blockpos);
blockpos_last = blockpos;
-
+
block_checked_in_modified = false;
- //blockchangecount++;
+ blockchangecount++;
}
}
catch(InvalidPositionException &e)
@@ -227,33 +255,75 @@ void Map::unLightNeighbors(v3s16 pos, u8 oldlight,
if(block->isDummy())
continue;
-
+
// Calculate relative position in block
- v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE;
+ v3s16 relpos = pos - blockpos_last * MAP_BLOCKSIZE;
+
// Get node straight from the block
- MapNode n2 = block->getNode(relpos);
-
- /*
- If the neighbor is dimmer than what was specified
- as oldlight (the light of the previous node)
- */
- if(n2.getLight() < oldlight)
- {
- /*
- And the neighbor is transparent and it has some light
- */
- if(n2.light_propagates() && n2.getLight() != 0)
+ 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;
/*
- Set light to 0 and recurse.
+ If the neighbor is brighter than the current node,
+ add to list (it will light up this node on its turn)
*/
- u8 current_light = n2.getLight();
- n2.setLight(0);
- block->setNode(relpos, n2);
- unLightNeighbors(n2pos, current_light,
- light_sources, modified_blocks);
-
- if(block_checked_in_modified == false)
+ 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)
@@ -263,12 +333,20 @@ void Map::unLightNeighbors(v3s16 pos, u8 oldlight,
block_checked_in_modified = true;
}
}
- }
- else{
- //light_sources.push_back(n2pos);
- light_sources.insert(n2pos, 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
@@ -1090,6 +1168,13 @@ void Map::timerUpdate(float dtime)
void Map::deleteSectors(core::list<v2s16> &list, bool only_blocks)
{
+ /*
+ Wait for caches to be removed before continuing.
+
+ This disables the existence of caches while locked
+ */
+ SharedPtr<JMutexAutoLock> cachelock(m_blockcachelock.waitCaches());
+
core::list<v2s16>::Iterator j;
for(j=list.begin(); j!=list.end(); j++)
{
@@ -1215,13 +1300,13 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
// Create master heightmap
ValueGenerator *maxgen =
- ValueGenerator::deSerialize(hmp.height_randmax);
+ ValueGenerator::deSerialize(hmp.randmax);
ValueGenerator *factorgen =
- ValueGenerator::deSerialize(hmp.height_randfactor);
+ ValueGenerator::deSerialize(hmp.randfactor);
ValueGenerator *basegen =
- ValueGenerator::deSerialize(hmp.height_base);
+ ValueGenerator::deSerialize(hmp.base);
m_heightmap = new UnlimitedHeightmap
- (hmp.heightmap_blocksize, maxgen, factorgen, basegen);
+ (hmp.blocksize, maxgen, factorgen, basegen);
// Set map parameters
m_params = mp;
@@ -1409,6 +1494,9 @@ MapSector * ServerMap::emergeSector(v2s16 p2d)
SECTOR_OBJECT_TREE_1);
}
}
+ /*
+ Plant some bushes if sector is pit-like
+ */
{
// Pitness usually goes at around -0.5...0.5
u32 bush_max = 0;
@@ -1429,6 +1517,22 @@ MapSector * ServerMap::emergeSector(v2s16 p2d)
SECTOR_OBJECT_BUSH_1);
}
}
+ /*
+ Add ravine (randomly)
+ */
+ {
+ if(rand()%10 == 0)
+ {
+ s16 s = 6;
+ s16 x = rand()%(MAP_BLOCKSIZE-s*2-1)+s;
+ s16 z = rand()%(MAP_BLOCKSIZE-s*2-1)+s;
+ /*s16 x = 8;
+ s16 z = 8;*/
+ s16 y = sector->getGroundHeight(v2s16(x,z))+1;
+ objects->insert(v3s16(x, y, z),
+ SECTOR_OBJECT_RAVINE);
+ }
+ }
/*
Insert to container
@@ -1533,9 +1637,16 @@ MapBlock * ServerMap::emergeBlock(
}
// Randomize a bit. This makes dungeons.
- bool low_block_is_empty = false;
+ /*bool low_block_is_empty = false;
if(rand() % 4 == 0)
- low_block_is_empty = true;
+ low_block_is_empty = true;*/
+
+ s32 ued = 4;
+ bool underground_emptiness[ued*ued*ued];
+ for(s32 i=0; i<ued*ued*ued; i++)
+ {
+ underground_emptiness[i] = ((rand() % 4) == 0);
+ }
// This is the basic material of what the visible flat ground
// will consist of
@@ -1551,9 +1662,7 @@ MapBlock * ServerMap::emergeBlock(
{
//dstream<<"emergeBlock: x0="<<x0<<", z0="<<z0<<std::endl;
float surface_y_f = sector->getGroundHeight(v2s16(x0,z0));
-
assert(surface_y_f > GROUNDHEIGHT_VALID_MINVALUE);
-
s16 surface_y = surface_y_f;
//avg_ground_y += surface_y;
if(surface_y < lowest_ground_y)
@@ -1574,13 +1683,14 @@ MapBlock * ServerMap::emergeBlock(
else
surface_depth = (1.-(slope-min_slope)/max_slope) * min_slope_depth;
- for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++){
+ for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
+ {
s16 real_y = block_y * MAP_BLOCKSIZE + y0;
MapNode n;
/*
Calculate lighting
- FIXME: If there are some man-made structures above the
+ NOTE: If there are some man-made structures above the
newly created block, they won't be taken into account.
*/
if(real_y > surface_y)
@@ -1589,12 +1699,17 @@ MapBlock * ServerMap::emergeBlock(
Calculate material
*/
// If node is very low
- if(real_y <= surface_y - 10){
+ if(real_y <= surface_y - 7){
// Create dungeons
- if(low_block_is_empty){
+ if(underground_emptiness[
+ ued*ued*(z0*ued/MAP_BLOCKSIZE)
+ +ued*(y0*ued/MAP_BLOCKSIZE)
+ +(x0*ued/MAP_BLOCKSIZE)])
+ {
n.d = MATERIAL_AIR;
}
- else{
+ else
+ {
n.d = MATERIAL_STONE;
}
}
@@ -1603,7 +1718,14 @@ MapBlock * ServerMap::emergeBlock(
n.d = MATERIAL_STONE;
// If node is at or under heightmap y
else if(real_y <= surface_y)
- n.d = material;
+ {
+ // If under water level, it's mud
+ if(real_y < WATER_LEVEL)
+ n.d = MATERIAL_MUD;
+ // Else it's the main material
+ else
+ n.d = material;
+ }
// If node is over heightmap y
else{
// If under water level, it's water
@@ -1629,10 +1751,20 @@ MapBlock * ServerMap::emergeBlock(
block->setIsUnderground(is_underground);
/*
+ Force lighting update if underground.
+ This is needed because of ravines.
+ */
+
+ if(is_underground)
+ {
+ lighting_invalidated_blocks[block->getPos()] = block;
+ }
+
+ /*
Add some minerals
*/
- if(is_underground && low_block_is_empty == false)
+ if(is_underground)
{
s16 underground_level = lowest_ground_y/MAP_BLOCKSIZE - block_y;
for(s16 i=0; i<underground_level*3; i++)
@@ -1640,9 +1772,6 @@ MapBlock * ServerMap::emergeBlock(
if(rand()%2 == 0)
{
v3s16 cp(
- /*(rand()%(MAP_BLOCKSIZE-4))+2,
- (rand()%(MAP_BLOCKSIZE-4))+2,
- (rand()%(MAP_BLOCKSIZE-4))+2*/
(rand()%(MAP_BLOCKSIZE-2))+1,
(rand()%(MAP_BLOCKSIZE-2))+1,
(rand()%(MAP_BLOCKSIZE-2))+1
@@ -1656,6 +1785,9 @@ MapBlock * ServerMap::emergeBlock(
for(u16 i=0; i<26; i++)
{
+ if(!is_ground_material(block->getNode(cp+g_26dirs[i]).d))
+ continue;
+
if(rand()%8 == 0)
block->setNode(cp+g_26dirs[i], n);
}
@@ -1666,7 +1798,7 @@ MapBlock * ServerMap::emergeBlock(
/*
Create a few rats in empty blocks underground
*/
- if(is_underground && low_block_is_empty == true)
+ /*if(is_underground && low_block_is_empty == true)
{
//for(u16 i=0; i<2; i++)
{
@@ -1674,42 +1806,54 @@ MapBlock * ServerMap::emergeBlock(
RatObject *obj = new RatObject(NULL, -1, intToFloat(pos));
block->addObject(obj);
}
- }
+ }*/
/*
- TODO: REMOVE
- DEBUG
- Add some objects to the block for testing.
+ Add block to sector.
*/
- /*if(p == v3s16(0,0,0))
- {
- //TestObject *obj = new TestObject(NULL, -1, v3f(BS*8,BS*8,BS*8));
- Test2Object *obj = new Test2Object(NULL, -1, v3f(BS*8,BS*15,BS*8));
- block->addObject(obj);
- }*/
+ sector->insertBlock(block);
/*
+ Do some interpolation for dungeons
+ */
+
+#if 0
{
- v3s16 pos(8, 11, 8);
- SignObject *obj = new SignObject(NULL, -1, intToFloat(pos));
- obj->setText("Moicka");
- obj->setYaw(45);
- block->addObject(obj);
- }
+ 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++)
{
- v3s16 pos(8, 11, 8);
- RatObject *obj = new RatObject(NULL, -1, intToFloat(pos));
- block->addObject(obj);
+ MapBlock *block = i.getNode()->getValue();
+
+ changed_blocks.insert(block->getPos(), block);
+ //lighting_invalidated_blocks.insert(block->getPos(), block);
}
- */
+
+ }
+#endif
/*
- Add block to sector.
+ Sector object stuff
*/
- sector->insertBlock(block);
-
- // An y-wise container if changed blocks
+
+ // An y-wise container of changed blocks
core::map<s16, MapBlock*> changed_blocks_sector;
/*
@@ -1722,6 +1866,7 @@ MapBlock * ServerMap::emergeBlock(
i.atEnd() == false; i++)
{
v3s16 p = i.getNode()->getKey();
+ v2s16 p2d(p.X,p.Z);
u8 d = i.getNode()->getValue();
//v3s16 p = p_sector - v3s16(0, block_y*MAP_BLOCKSIZE, 0);
@@ -1795,6 +1940,66 @@ MapBlock * ServerMap::emergeBlock(
objects_to_remove.push_back(p);
}
}
+ else if(d == SECTOR_OBJECT_RAVINE)
+ {
+ s16 maxdepth = -20;
+ v3s16 p_min = p + v3s16(-6,maxdepth,-6);
+ v3s16 p_max = p + v3s16(6,6,6);
+ if(sector->isValidArea(p_min, p_max,
+ &changed_blocks_sector))
+ {
+ MapNode n;
+ n.d = MATERIAL_STONE;
+ MapNode n2;
+ n2.d = MATERIAL_AIR;
+ s16 depth = maxdepth + (rand()%10);
+ s16 z = 0;
+ s16 minz = -6 - (-2);
+ s16 maxz = 6 -1;
+ for(s16 x=-6; x<=6; x++)
+ {
+ z += -1 + (rand()%3);
+ if(z < minz)
+ z = minz;
+ if(z > maxz)
+ z = maxz;
+ for(s16 y=depth+(rand()%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_material(sector->getNode(p2).d))
+ sector->setNode(p2, n);
+ }
+ {
+ v3s16 p2 = p + v3s16(x,y,z-1);
+ if(is_ground_material(sector->getNode(p2).d))
+ sector->setNode(p2, n2);
+ }
+ {
+ v3s16 p2 = p + v3s16(x,y,z+0);
+ if(is_ground_material(sector->getNode(p2).d))
+ sector->setNode(p2, n2);
+ }
+ {
+ v3s16 p2 = p + v3s16(x,y,z+1);
+ if(is_ground_material(sector->getNode(p2).d))
+ sector->setNode(p2, n);
+ }
+
+ //if(sector->getNode(p+v3s16(x,y,z+1)).solidness()==2)
+ //if(p.Y+y <= sector->getGroundHeight(p2d+v2s16(x,z-2))+0.5)
+ }
+ }
+
+ objects_to_remove.push_back(p);
+
+ // Lighting has to be recalculated for this one.
+ sector->getBlocksInArea(p_min, p_max,
+ lighting_invalidated_blocks);
+ }
+ }
else
{
dstream<<"ServerMap::emergeBlock(): "
@@ -1807,7 +2012,7 @@ MapBlock * ServerMap::emergeBlock(
{
dstream<<"WARNING: "<<__FUNCTION_NAME
<<": while inserting object "<<(int)d
- <<" to ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
+ <<" to ("<<p.X<<","<<p.Y<<","<<p.Z<<"):"
<<" InvalidPositionException.what()="
<<e.what()<<std::endl;
// This is not too fatal and seems to happen sometimes.