m_camera_position(0,0,0),
m_camera_direction(0,0,1),
m_sector_cache(NULL),
- m_hwrapper(this),
- drawoffset(0,0,0)
+ m_hwrapper(this)
{
m_sector_mutex.Init();
m_camera_mutex.Init();
MapBlock *block = i.getNode()->getValue();
block->updateDayNightDiff();
}
+
+ /*
+ Add neighboring liquid nodes and the node itself if it is
+ liquid (=water node was added) to transform queue.
+ */
+ v3s16 dirs[7] = {
+ v3s16(0,0,0), // self
+ 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++)
+ {
+ try
+ {
+
+ v3s16 p2 = p + dirs[i];
+
+ MapNode n2 = getNode(p2);
+ if(content_liquid(n2.d))
+ {
+ m_transforming_liquid.push_back(p2);
+ }
+
+ }catch(InvalidPositionException &e)
+ {
+ }
+ }
}
/*
MapBlock *block = i.getNode()->getValue();
block->updateDayNightDiff();
}
+
+ /*
+ Add neighboring 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++)
+ {
+ try
+ {
+
+ v3s16 p2 = p + dirs[i];
+
+ MapNode n2 = getNode(p2);
+ if(content_liquid(n2.d))
+ {
+ m_transforming_liquid.push_back(p2);
+ }
+
+ }catch(InvalidPositionException &e)
+ {
+ }
+ }
}
#ifndef SERVER
This disables the existence of caches while locked
*/
- SharedPtr<JMutexAutoLock> cachelock(m_blockcachelock.waitCaches());
+ //SharedPtr<JMutexAutoLock> cachelock(m_blockcachelock.waitCaches());
core::list<v2s16>::Iterator j;
for(j=list.begin(); j!=list.end(); j++)
out<<"Map: ";
}
+#define WATER_DROP_BOOST 4
+
+void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
+{
+ DSTACK(__FUNCTION_NAME);
+ //TimeTaker timer("transformLiquids()");
+
+ u32 loopcount = 0;
+ u32 initial_size = m_transforming_liquid.size();
+ while(m_transforming_liquid.size() != 0)
+ {
+ v3s16 p0 = m_transforming_liquid.pop_front();
+
+ MapNode n0 = getNode(p0);
+
+ // 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);
+
+ /*
+ 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++)
+ {
+ try
+ {
+
+ bool from_top = (i==0);
+
+ v3s16 p2 = p0 + dirs_from[i];
+ MapNode n2 = getNode(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;
+ }
+ 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;
+ }
+ else if(n2_liquid_level > 0)
+ {
+ new_liquid_level = n2_liquid_level - 1;
+ }
+
+ if(new_liquid_level > new_liquid_level_max)
+ new_liquid_level_max = new_liquid_level;
+ }
+
+ }catch(InvalidPositionException &e)
+ {
+ }
+ } //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++)
+ {
+ try
+ {
+
+ v3s16 p2 = p0 + dirs[i];
+
+ MapNode n2 = getNode(p2);
+ if(content_flowing_liquid(n2.d))
+ {
+ m_transforming_liquid.push_back(p2);
+ }
+
+ }catch(InvalidPositionException &e)
+ {
+ }
+ }
+ }
+ }
+
+ // Get a new one from queue if the node has turned into non-water
+ if(content_liquid(n0.d) == false)
+ continue;
+
+ /*
+ 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++)
+ {
+ try
+ {
+
+ 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 = getNode(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;
+ }
+ 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;
+ }
+
+ 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;
+ }
+
+ 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)
+ break;
+
+ }catch(InvalidPositionException &e)
+ {
+ }
+ }
+
+ loopcount++;
+ //if(loopcount >= 100000)
+ if(loopcount >= initial_size * 1)
+ break;
+ }
+ //dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
+}
+
/*
ServerMap
*/
Map(dout_server),
m_heightmap(NULL)
{
+ /*
+ Experimental and debug stuff
+ */
+
+ {
+ dstream<<"Generating map point attribute lists"<<std::endl;
+
+ PointAttributeList *list_baseheight = m_padb.getList("hm_baseheight");
+ PointAttributeList *list_randmax = m_padb.getList("hm_randmax");
+ PointAttributeList *list_randfactor = m_padb.getList("hm_randfactor");
+ PointAttributeList *list_plants_amount = m_padb.getList("plants_amount");
+ PointAttributeList *list_caves_amount = m_padb.getList("caves_amount");
+
+ /*
+ NOTE: BEWARE: Too big amount of these will make map generation
+ slow. Especially those that are read by every block emerge.
+
+ Fetch times:
+ 1000 points: 2-3ms
+ 5000 points: 15ms
+ 15000 points: 40ms
+ */
+
+ for(u32 i=0; i<5000; i++)
+ {
+ /*u32 lim = MAP_GENERATION_LIMIT;
+ if(i < 400)
+ lim = 2000;*/
+
+ u32 lim = 1000 + MAP_GENERATION_LIMIT * i / 5000;
+
+ v3s16 p(
+ -lim + myrand()%(lim*2),
+ 0,
+ -lim + myrand()%(lim*2)
+ );
+ /*float plants_amount = (float)(myrand()%1050) / 1000.0;
+ plants_amount = pow(plants_amount, 5);
+ list_plants_amount->addPoint(p, Attribute(plants_amount));*/
+
+ float plants_amount = 0;
+ if(myrand()%5 == 0)
+ {
+ plants_amount = 1.5;
+ }
+ else if(myrand()%4 == 0)
+ {
+ plants_amount = 0.5;
+ }
+ else if(myrand()%2 == 0)
+ {
+ plants_amount = 0.03;
+ }
+ else
+ {
+ plants_amount = 0.0;
+ }
+
+
+ list_plants_amount->addPoint(p, Attribute(plants_amount));
+ }
+
+ for(u32 i=0; i<1000; i++)
+ {
+ /*u32 lim = MAP_GENERATION_LIMIT;
+ if(i < 400)
+ lim = 2000;*/
+
+ u32 lim = 500 + MAP_GENERATION_LIMIT * i / 1000;
+
+ v3s16 p(
+ -lim + myrand()%(lim*2),
+ 0,
+ -lim + myrand()%(lim*2)
+ );
+
+ float caves_amount = 0;
+ if(myrand()%5 == 0)
+ {
+ caves_amount = 1.0;
+ }
+ else if(myrand()%3 == 0)
+ {
+ caves_amount = 0.3;
+ }
+ else
+ {
+ caves_amount = 0.05;
+ }
+
+ list_caves_amount->addPoint(p, Attribute(caves_amount));
+ }
+
+ for(u32 i=0; i<5000; i++)
+ {
+ /*u32 lim = MAP_GENERATION_LIMIT;
+ if(i < 400)
+ lim = 2000;*/
+
+ u32 lim = 1000 + MAP_GENERATION_LIMIT * i / 5000;
+
+ v3s16 p(
+ -lim + (myrand()%(lim*2)),
+ 0,
+ -lim + (myrand()%(lim*2))
+ );
+
+ /*s32 bh_i = (myrand()%200) - 50;
+ float baseheight = (float)bh_i;
+
+ float m = 100.;
+ float e = 3.;
+ float randmax = (float)(myrand()%(int)(10.*pow(m, 1./e)))/10.;
+ randmax = pow(randmax, e);
+
+ //float randmax = (float)(myrand()%60);
+ float randfactor = (float)(myrand()%450) / 1000.0 + 0.4;*/
+
+ float baseheight = 0;
+ float randmax = 0;
+ float randfactor = 0;
+
+ if(myrand()%4 == 0)
+ {
+ baseheight = 100;
+ randmax = 50;
+ randfactor = 0.63;
+ }
+ else if(myrand()%6 == 0)
+ {
+ baseheight = 200;
+ randmax = 100;
+ randfactor = 0.66;
+ }
+ else if(myrand()%4 == 0)
+ {
+ baseheight = -3;
+ randmax = 30;
+ randfactor = 0.7;
+ }
+ else if(myrand()%3 == 0)
+ {
+ baseheight = 0;
+ randmax = 30;
+ randfactor = 0.63;
+ }
+ else
+ {
+ baseheight = -3;
+ randmax = 20;
+ randfactor = 0.5;
+ }
+
+ list_baseheight->addPoint(p, Attribute(baseheight));
+ list_randmax->addPoint(p, Attribute(randmax));
+ list_randfactor->addPoint(p, Attribute(randfactor));
+ }
+
+ /*list_baseheight->addPoint(v3s16(0,0,0), Attribute(5));
+ list_randmax->addPoint(v3s16(0,0,0), Attribute(20));
+ list_randfactor->addPoint(v3s16(0,0,0), Attribute(0.6));*/
+
+ // Easy spawn point
+ /*list_baseheight->addPoint(v3s16(0,0,0), Attribute(0));
+ list_randmax->addPoint(v3s16(0,0,0), Attribute(10));
+ list_randfactor->addPoint(v3s16(0,0,0), Attribute(0.65));*/
+ }
+
+ /*
+ Try to load map; if not found, create a new one.
+ */
+
m_savedir = savedir;
m_map_saving_enabled = false;
dstream<<DTIME<<"Initializing new map."<<std::endl;
// Create master heightmap
- ValueGenerator *maxgen =
+ /*ValueGenerator *maxgen =
ValueGenerator::deSerialize(hmp.randmax);
ValueGenerator *factorgen =
ValueGenerator::deSerialize(hmp.randfactor);
ValueGenerator *basegen =
ValueGenerator::deSerialize(hmp.base);
m_heightmap = new UnlimitedHeightmap
- (hmp.blocksize, maxgen, factorgen, basegen);
+ (hmp.blocksize, maxgen, factorgen, basegen, &m_padb);*/
+
+ /*m_heightmap = new UnlimitedHeightmap
+ (hmp.blocksize, &m_padb);*/
+
+ m_heightmap = new UnlimitedHeightmap
+ (32, &m_padb);
// Set map parameters
m_params = mp;
s16 hm_d = MAP_BLOCKSIZE / hm_split;
ServerMapSector *sector = new ServerMapSector(this, p2d, hm_split);
+
+ // Sector position on map in nodes
+ v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
/*dstream<<"Generating sector ("<<p2d.X<<","<<p2d.Y<<")"
" heightmaps and objects"<<std::endl;*/
- // Loop through sub-heightmaps
- for(s16 y=0; y<hm_split; y++)
- for(s16 x=0; x<hm_split; x++)
- {
- v2s16 p_in_sector = v2s16(x,y);
- v2s16 mhm_p = p2d * hm_split + p_in_sector;
- f32 corners[4] = {
- m_heightmap->getGroundHeight(mhm_p+v2s16(0,0)),
- m_heightmap->getGroundHeight(mhm_p+v2s16(1,0)),
- m_heightmap->getGroundHeight(mhm_p+v2s16(1,1)),
- m_heightmap->getGroundHeight(mhm_p+v2s16(0,1)),
- };
-
- /*dstream<<"p_in_sector=("<<p_in_sector.X<<","<<p_in_sector.Y<<")"
- <<" mhm_p=("<<mhm_p.X<<","<<mhm_p.Y<<")"
- <<std::endl;*/
-
- FixedHeightmap *hm = new FixedHeightmap(&m_hwrapper,
- mhm_p, hm_d);
- sector->setHeightmap(p_in_sector, hm);
-
- //TODO: Make these values configurable
-
- //hm->generateContinued(0.0, 0.0, corners);
- hm->generateContinued(0.25, 0.2, corners);
- //hm->generateContinued(0.5, 0.2, corners);
- //hm->generateContinued(1.0, 0.2, corners);
- //hm->generateContinued(2.0, 0.2, corners);
-
- //hm->print();
-
- }
-
/*
- Generate objects
+ Calculate some information about local properties
*/
- core::map<v3s16, u8> *objects = new core::map<v3s16, u8>;
- sector->setObjects(objects);
-
v2s16 mhm_p = p2d * hm_split;
f32 corners[4] = {
m_heightmap->getGroundHeight(mhm_p+v2s16(0,0)*hm_split),
pitness /= 4.0;
pitness /= MAP_BLOCKSIZE;
//dstream<<"pitness="<<pitness<<std::endl;
+
+ /*
+ Get local attributes
+ */
+ float local_plants_amount = 0.0;
+ {
+ //dstream<<"emergeSector(): Reading point attribute lists"<<std::endl;
+ //TimeTaker attrtimer("emergeSector() attribute fetch");
+
+ // Get plant amount from attributes
+ PointAttributeList *palist = m_padb.getList("plants_amount");
+ assert(palist);
+ /*local_plants_amount =
+ palist->getNearAttr(nodepos2d).getFloat();*/
+ local_plants_amount =
+ palist->getInterpolatedFloat(nodepos2d);
+ }
+
+ /*
+ Generate sector heightmap
+ */
+
+ // Loop through sub-heightmaps
+ for(s16 y=0; y<hm_split; y++)
+ for(s16 x=0; x<hm_split; x++)
+ {
+ v2s16 p_in_sector = v2s16(x,y);
+ v2s16 mhm_p = p2d * hm_split + p_in_sector;
+ f32 corners[4] = {
+ m_heightmap->getGroundHeight(mhm_p+v2s16(0,0)),
+ m_heightmap->getGroundHeight(mhm_p+v2s16(1,0)),
+ m_heightmap->getGroundHeight(mhm_p+v2s16(1,1)),
+ m_heightmap->getGroundHeight(mhm_p+v2s16(0,1)),
+ };
+
+ /*dstream<<"p_in_sector=("<<p_in_sector.X<<","<<p_in_sector.Y<<")"
+ <<" mhm_p=("<<mhm_p.X<<","<<mhm_p.Y<<")"
+ <<std::endl;*/
+
+ FixedHeightmap *hm = new FixedHeightmap(&m_hwrapper,
+ mhm_p, hm_d);
+ sector->setHeightmap(p_in_sector, hm);
+
+ //TODO: Make these values configurable
+ //hm->generateContinued(0.0, 0.0, corners);
+ //hm->generateContinued(0.25, 0.2, corners);
+ //hm->generateContinued(0.5, 0.2, corners);
+ //hm->generateContinued(1.0, 0.2, corners);
+ //hm->generateContinued(2.0, 0.2, corners);
+ //hm->generateContinued(2.0 * avgslope, 0.5, corners);
+ hm->generateContinued(avgslope * MAP_BLOCKSIZE/8, 0.5, corners);
+
+ //hm->print();
+ }
+
+ /*
+ Generate objects
+ */
+
+ core::map<v3s16, u8> *objects = new core::map<v3s16, u8>;
+ sector->setObjects(objects);
+
+ float area = MAP_BLOCKSIZE * MAP_BLOCKSIZE;
+
/*
Plant some trees if there is not much slope
*/
{
// Avgslope is the derivative of a hill
- float t = avgslope * avgslope;
- float a = MAP_BLOCKSIZE * m_params.plants_amount;
+ //float t = avgslope * avgslope;
+ float t = avgslope;
+ float a = area/16 * m_params.plants_amount * local_plants_amount;
u32 tree_max;
- if(t > 0.03)
- tree_max = a / (t/0.03);
+ //float something = 0.17*0.17;
+ float something = 0.3;
+ if(t > something)
+ tree_max = a / (t/something);
else
tree_max = a;
+
u32 count = (myrand()%(tree_max+1));
//u32 count = tree_max;
for(u32 i=0; i<count; i++)
{
// Pitness usually goes at around -0.5...0.5
u32 bush_max = 0;
- u32 a = MAP_BLOCKSIZE * 3.0 * m_params.plants_amount;
+ u32 a = area/16 * 3.0 * m_params.plants_amount * local_plants_amount;
if(pitness > 0)
bush_max = (pitness*a*4);
if(bush_max > a)
/*
Add ravine (randomly)
*/
- if(m_params.ravines_amount != 0)
+ if(m_params.ravines_amount > 0.001)
{
- if(myrand()%(s32)(20.0 / m_params.ravines_amount) == 0)
+ if(myrand()%(s32)(200.0 / m_params.ravines_amount) == 0)
{
s16 s = 6;
s16 x = myrand()%(MAP_BLOCKSIZE-s*2-1)+s;
block->unDummify();
}
- u8 water_material = CONTENT_WATER;
+ /*u8 water_material = CONTENT_WATER;
if(g_settings.getBool("endless_water"))
- water_material = CONTENT_OCEAN;
+ water_material = CONTENT_WATERSOURCE;*/
+ u8 water_material = CONTENT_WATERSOURCE;
s32 lowest_ground_y = 32767;
s32 highest_ground_y = -32768;
n.d = water_material;
n.setLight(LIGHTBANK_DAY,
diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
+ /*
+ Add to transforming liquid queue (in case it'd
+ start flowing)
+ */
+ v3s16 real_pos = v3s16(x0,y0,z0) + p*MAP_BLOCKSIZE;
+ m_transforming_liquid.push_back(real_pos);
}
// else air
else
bool some_part_underground = block_y * MAP_BLOCKSIZE <= highest_ground_y;
+ bool mostly_underwater_surface = false;
+ if(highest_ground_y < WATER_LEVEL
+ && some_part_underground && !completely_underground)
+ mostly_underwater_surface = true;
+
+ /*
+ Get local attributes
+ */
+
+ //dstream<<"emergeBlock(): Getting local attributes"<<std::endl;
+
+ float caves_amount = 0;
+
+ {
+ /*
+ NOTE: BEWARE: Too big amount of attribute points slows verything
+ down by a lot.
+ 1 interpolation from 5000 points takes 2-3ms.
+ */
+ //TimeTaker timer("emergeBlock() local attribute retrieval");
+ v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
+ PointAttributeList *list_caves_amount = m_padb.getList("caves_amount");
+ caves_amount = list_caves_amount->getInterpolatedFloat(nodepos2d);
+ }
+
+ //dstream<<"emergeBlock(): Done"<<std::endl;
+
/*
Generate dungeons
*/
}
// Fill table
+#if 1
{
/*
Initialize orp and ors. Try to find if some neighboring
}
catch(InvalidPositionException &e){}
+ // Check y-
+ try
+ {
+ s16 y = -1;
+ for(s16 x=0; x<ued; x++)
+ for(s16 z=0; z<ued; z++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ if(getNode(ap).d == CONTENT_AIR)
+ {
+ orp = v3f(x+1,0,z+1);
+ found_existing = true;
+ goto continue_generating;
+ }
+ }
+ }
+ catch(InvalidPositionException &e){}
+
+ // Check y+
+ try
+ {
+ s16 y = ued;
+ for(s16 x=0; x<ued; x++)
+ for(s16 z=0; z<ued; z++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ if(getNode(ap).d == CONTENT_AIR)
+ {
+ orp = v3f(x+1,ued-1,z+1);
+ found_existing = true;
+ goto continue_generating;
+ }
+ }
+ }
+ catch(InvalidPositionException &e){}
+
continue_generating:
/*
- Don't always generate dungeon
+ Choose whether to actually generate dungeon
*/
bool do_generate_dungeons = true;
+ // Don't generate if no part is underground
if(!some_part_underground)
+ {
+ do_generate_dungeons = false;
+ }
+ // Don't generate if mostly underwater surface
+ else if(mostly_underwater_surface)
+ {
do_generate_dungeons = false;
+ }
+ // Partly underground = cave
else if(!completely_underground)
- do_generate_dungeons = rand() % 5;
- else if(found_existing)
- do_generate_dungeons = true;
+ {
+ do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100));
+ }
+ // Found existing dungeon underground
+ else if(found_existing && completely_underground)
+ {
+ do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100));
+ }
+ // Underground and no dungeons found
else
- do_generate_dungeons = rand() % 2;
+ {
+ do_generate_dungeons = (rand() % 300 <= (s32)(caves_amount*100));
+ }
if(do_generate_dungeons)
{
}
}
}
+#endif
// Set to true if has caves.
// Set when some non-air is changed to air when making caves.
- bool has_caves = false;
+ bool has_dungeons = false;
/*
Apply temporary cave data to block
if(is_ground_content(n.d))
{
// Has now caves
- has_caves = true;
+ has_dungeons = true;
// Set air to node
n.d = CONTENT_AIR;
}
Force lighting update if some part of block is partly
underground and has caves.
*/
- /*if(some_part_underground && !completely_underground && has_caves)
+ /*if(some_part_underground && !completely_underground && has_dungeons)
{
//dstream<<"Half-ground caves"<<std::endl;
lighting_invalidated_blocks[block->getPos()] = block;
/*
Add meseblocks
*/
- for(s16 i=0; i< underground_level/4 + 1; i++)
+ for(s16 i=0; i<underground_level/4 + 1; i++)
{
- if(myrand()%10 == 0)
+ if(myrand()%50 == 0)
{
v3s16 cp(
(myrand()%(MAP_BLOCKSIZE-2))+1,
core::map<v3s16, bool> light_sources;
bool black_air_left = false;
bool bottom_invalid =
- block->propagateSunlight(light_sources, true, &black_air_left);
+ block->propagateSunlight(light_sources, true,
+ &black_air_left, true);
// If sunlight didn't reach everywhere and part of block is
// above ground, lighting has to be properly updated
{
lighting_invalidated_blocks[block->getPos()] = block;
}
+
+ if(bottom_invalid)
+ {
+ lighting_invalidated_blocks[block->getPos()] = block;
+ }
}
/*
changed_blocks.insert(block->getPos(), block);
}
+ /*
+ Debug information
+ */
+ if(0)
+ {
+ dstream
+ <<"lighting_invalidated_blocks.size()"
+ <<", has_dungeons"
+ <<", completely_ug"
+ <<", some_part_ug"
+ <<" "<<lighting_invalidated_blocks.size()
+ <<", "<<has_dungeons
+ <<", "<<completely_underground
+ <<", "<<some_part_underground
+ <<std::endl;
+ }
+
+ /*
+ Debug mode operation
+ */
+ bool haxmode = g_settings.getBool("haxmode");
+ if(haxmode)
+ {
+ // Don't calculate lighting at all
+ //lighting_invalidated_blocks.clear();
+ }
+
return block;
}
if(m_heightmap != NULL)
delete m_heightmap;
- m_heightmap = UnlimitedHeightmap::deSerialize(is);
+ m_heightmap = UnlimitedHeightmap::deSerialize(is, &m_padb);
}
void ServerMap::saveSectorMeta(ServerMapSector *sector)
if not seen on display
*/
+ float range = 100000 * BS;
+ if(m_control.range_all == false)
+ range = m_control.wanted_range * BS;
+
+ if(isBlockInSight(block->getPos(), camera_position,
+ camera_direction, range) == false)
+ {
+ continue;
+ }
+
+#if 0
v3s16 blockpos_nodes = block->getPosRelative();
// Block center position
{
// If block is far away, don't draw it
if(d > m_control.wanted_range * BS)
- // This is nicer when fog is used
- //if((dforward+d)/2 > m_control.wanted_range * BS)
continue;
}
if(cosangle < cos(FOV_ANGLE/2. * 4./3.))
continue;
}
+#endif
+
+ v3s16 blockpos_nodes = block->getPosRelative();
+
+ // Block center position
+ v3f blockpos(
+ ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
+ ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS,
+ ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS
+ );
+
+ // Block position relative to camera
+ v3f blockpos_relative = blockpos - camera_position;
+
+ // Total distance
+ f32 d = blockpos_relative.getLength();
+#if 1
/*
- Draw the faces of the block
+ Update expired mesh
*/
-#if 1
+
bool mesh_expired = false;
{
continue;
}*/
#endif
+ /*
+ Draw the faces of the block
+ */
{
JMutexAutoLock lock(block->mesh_mutex);
<<", rendered "<<vertex_count<<" vertices."<<std::endl;*/
}
-v3s16 ClientMap::setTempMod(v3s16 p, NodeMod mod)
+v3s16 ClientMap::setTempMod(v3s16 p, NodeMod mod, bool *changed)
{
/*
Add it to all blocks touching it
continue;
// Relative position of requested node
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
- blockref->setTempMod(relpos, mod);
+ if(blockref->setTempMod(relpos, mod))
+ {
+ if(changed != NULL)
+ *changed = true;
+ }
}
return getNodeBlockPos(p);
}
-v3s16 ClientMap::clearTempMod(v3s16 p)
+v3s16 ClientMap::clearTempMod(v3s16 p, bool *changed)
{
v3s16 dirs[7] = {
v3s16(0,0,0), // this
continue;
// Relative position of requested node
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
- blockref->clearTempMod(relpos);
+ if(blockref->clearTempMod(relpos))
+ {
+ if(changed != NULL)
+ *changed = true;
+ }
}
return getNodeBlockPos(p);
}