From e92238edc831a34081790e71249f1459e997974c Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Tue, 1 Feb 2011 16:17:55 +0200 Subject: [PATCH] This map generator is starting to look pretty good now... also, disabled loading player position from disk because map is regenerated always. --- src/environment.cpp | 3 +- src/main.cpp | 16 +- src/map.cpp | 734 +++++++++++++++++++------------------------- src/map.h | 51 ++- src/mapblock.cpp | 3 + src/mapchunk.h | 27 +- src/mapnode.cpp | 3 + src/player.cpp | 4 + src/player.h | 1 + src/server.cpp | 32 +- src/utility.h | 5 +- 11 files changed, 437 insertions(+), 442 deletions(-) diff --git a/src/environment.cpp b/src/environment.cpp index d4d189ac..dc44b3a3 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -112,7 +112,8 @@ void Environment::step(float dtime) { // Apply gravity to local player v3f speed = player->getSpeed(); - speed.Y -= 9.81 * BS * dtime_part * 2; + if(player->swimming_up == false) + speed.Y -= 9.81 * BS * dtime_part * 2; /* Apply water resistance diff --git a/src/main.cpp b/src/main.cpp index 87deefee..176cde63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -333,6 +333,19 @@ Doing now: * Make the generator to run in background and not blocking block placement and transfer * Fix the strange mineral occurences +* When the map is generated and a place is found for the player, the + first chunk is actually still volatile and will have stuff still + changed after spawning, which creates a lot of glitches. + - This is partly fixed by now allowing only 2-sector deeep + modification of volatile chunks. But it should still be fixed? + - How about checking that the neighbors are fully generated too and + generate them when the middle piece is needed + - This is very slow + - How about just enabling changed_blocks properly + - This is probably a good idea + - The server has to make sure the spawn point is not at the + changing borders of a chunk +* Add some kind of erosion and other stuff that now is possible ====================================================================== @@ -2690,8 +2703,7 @@ int main(int argc, char *argv[]) } // We want a slight delay to very little // time consuming nodes - //float mindelay = 0.15; - float mindelay = 0.20; + float mindelay = 0.15; if(nodig_delay_counter < mindelay) { nodig_delay_counter = mindelay; diff --git a/src/map.cpp b/src/map.cpp index 63fccc43..88448276 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1735,8 +1735,8 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): //m_chunksize = 64; //m_chunksize = 16; - //m_chunksize = 8; - m_chunksize = 4; + m_chunksize = 8; + //m_chunksize = 4; //m_chunksize = 2; /* @@ -1749,8 +1749,8 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): 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"); + //PointAttributeList *list_plants_amount = m_padb.getList("plants_amount"); + //PointAttributeList *list_caves_amount = m_padb.getList("caves_amount"); #if 0 /* @@ -2026,119 +2026,6 @@ ServerMap::~ServerMap() } } -#if 0 -MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos) -{ - // Return if chunk already exists - MapChunk *chunk = getChunk(chunkpos); - if(chunk) - return chunk; - - /* - Add all sectors - */ - - dstream<<"generateChunkRaw(): " - <<"("< changed_blocks; - core::map lighting_invalidated_blocks; - - u32 generated_block_count = 0; - - for(s16 y=0; ygetBlockNoCreateNoEx(y2)) - continue; - - generateBlock(p, NULL, sector, changed_blocks, - lighting_invalidated_blocks); - - generated_block_count++; - } - } - } - - dstream<<"generateChunkRaw generated "< lighting_modified_blocks; - updateLighting(lighting_invalidated_blocks, lighting_modified_blocks); - }*/ - - // Add chunk meta information - chunk = new MapChunk(); - m_chunks.insert(chunkpos, chunk); - return chunk; -} - -MapChunk* ServerMap::generateChunk(v2s16 chunkpos) -{ - /* - Generate chunk and neighbors - */ - for(s16 x=-1; x<=1; x++) - for(s16 y=-1; y<=1; y++) - { - generateChunkRaw(chunkpos + v2s16(x,y)); - } - - /* - Get chunk - */ - MapChunk *chunk = getChunk(chunkpos); - assert(chunk); - // Set non-volatile - chunk->setIsVolatile(false); - // Return it - return chunk; -} -#endif - -MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos) -{ - dstream<<"WARNING: No-op "<<__FUNCTION_NAME<<" called"< &changed_blocks) { - TimeTaker timer("generateChunk()"); + /* + Don't generate if already fully generated + */ + { + MapChunk *chunk = getChunk(chunkpos); + if(chunk != NULL && chunk->getGenLevel() == GENERATED_FULLY) + { + dstream<<"generateChunkRaw(): Chunk " + <<"("<setLightingExpired(false); /* - TODO: Do this better. Block gets sunlight if this is true. This should be set to true when the top side of a block is completely exposed to the sky. + + Actually this doesn't matter now because the + initial lighting is done here. */ block->setIsUnderground(y != y_blocks_max); } @@ -2314,15 +2236,19 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) ManualMapVoxelManipulator vmanip(this); // Add the area we just generated { - TimeTaker timer("generateChunk() initialEmerge"); + TimeTaker timer("generateChunkRaw() initialEmerge"); vmanip.initialEmerge(bigarea_blocks_min, bigarea_blocks_max); } - TimeTaker timer_generate("generateChunk() generate"); + TimeTaker timer_generate("generateChunkRaw() generate"); /* Generate general ground level to full area */ + + { + // 22ms @cs=8 + //TimeTaker timer1("ground level"); for(s16 x=0; x stone_surface_max_y) + stone_surface_max_y = y; + count++; if(count >= ob_size.Y) break; @@ -2468,12 +2412,29 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) } } + }//timer1 + { + // 24ms @cs=8 + //TimeTaker timer1("dungeons"); + /* Make dungeons */ - for(u32 jj=0; jj<2; jj++) + u32 dungeons_count = relative_volume/200000; + for(u32 jj=0; jj WATER_LEVEL) - continue; + /* + If ground level is over water level, skip. + NOTE: This leaves caves near water without water, + which looks especially crappy when the nearby water + won't start flowing either for some reason + */ + /*if(surface_y > WATER_LEVEL) + continue;*/ /* Add water on ground @@ -2861,24 +2871,44 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) s16 y_start = WATER_LEVEL; u8 light = LIGHT_MAX; u32 i = vmanip.m_area.index(v3s16(p2d.X, y_start, p2d.Y)); + MapNode *n = &vmanip.m_data[i]; + /* + Add first one to transforming liquid queue + */ + if(n->d == CONTENT_WATER || n->d == CONTENT_WATERSOURCE) + { + v3s16 p = v3s16(p2d.X, y_start, p2d.Y); + m_transforming_liquid.push_back(p); + } for(s16 y=y_start; y>=y_nodes_min; y--) { - MapNode *n = &vmanip.m_data[i]; + n = &vmanip.m_data[i]; - // Fill gaps inside water, too + // Stop when there is no water and no air if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != CONTENT_WATER) + { + /* + Add bottom one to transforming liquid queue + */ + vmanip.m_area.add_y(em, i, 1); + n = &vmanip.m_data[i]; + if(n->d == CONTENT_WATER || n->d == CONTENT_WATERSOURCE) + { + v3s16 p = v3s16(p2d.X, y, p2d.Y); + m_transforming_liquid.push_back(p); + } + break; + } n->d = CONTENT_WATERSOURCE; n->setLight(LIGHTBANK_DAY, light); - /* - Add to transforming liquid queue (in case it'd - start flowing) - */ + /*// Add to transforming liquid queue (in case it'd + // start flowing) v3s16 p = v3s16(p2d.X, y, p2d.Y); - m_transforming_liquid.push_back(p); + m_transforming_liquid.push_back(p);*/ // Next one vmanip.m_area.add_y(em, i, -1); @@ -2889,11 +2919,16 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) } + }//timer1 + { + // 1ms @cs=8 + //TimeTaker timer1("plant trees"); + /* Plant some trees */ { - u32 tree_max = 100; + u32 tree_max = relative_area / 100; u32 count = myrand_range(0, tree_max); for(u32 i=0; id = CONTENT_GRASS; } + }//timer1 + /* Handle lighting */ core::map light_sources; + { + // 750ms @cs=8, can't optimize more + //TimeTaker timer1("initial lighting"); + /*for(s16 x=0; x=y_nodes_min; y--) { @@ -2994,11 +3047,42 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) if(light > 0) light--; } + + // This doesn't take much time + if(add_to_sources == false) + { + /* + Check sides. If side is not air or water, start + adding to light_sources. + */ + v3s16 dirs4[4] = { + v3s16(0,0,1), // back + v3s16(1,0,0), // right + v3s16(0,0,-1), // front + v3s16(-1,0,0), // left + }; + for(u32 di=0; di<4; di++) + { + v3s16 dirp = dirs4[di]; + u32 i2 = i; + vmanip.m_area.add_p(em, i2, dirp); + MapNode *n2 = &vmanip.m_data[i2]; + if( + n2->d != CONTENT_AIR + && n2->d != CONTENT_WATERSOURCE + && n2->d != CONTENT_WATER + ){ + add_to_sources = true; + break; + } + } + } n->setLight(LIGHTBANK_DAY, light); n->setLight(LIGHTBANK_NIGHT, 0); - if(light != 0) + // This doesn't take much time + if(light != 0 && add_to_sources) { // Insert light source light_sources.insert(v3s16(p2d.X, y, p2d.Y), true); @@ -3010,9 +3094,11 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) } } + }//timer1 + // Spread light around { - TimeTaker timer("generateChunk() spreadLight"); + TimeTaker timer("generateChunkRaw() spreadLight"); vmanip.spreadLight(LIGHTBANK_DAY, light_sources); } @@ -3025,16 +3111,16 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) /* Blit generated stuff to map */ - core::map modified_blocks; { - TimeTaker timer("generateChunk() blitBackAll"); - vmanip.blitBackAll(&modified_blocks); + // 70ms @cs=8 + //TimeTaker timer("generateChunkRaw() blitBackAll"); + vmanip.blitBackAll(&changed_blocks); } /* Update day/night difference cache of the MapBlocks */ { - for(core::map::Iterator i = modified_blocks.getIterator(); + for(core::map::Iterator i = changed_blocks.getIterator(); i.atEnd() == false; i++) { MapBlock *block = i.getNode()->getValue(); @@ -3044,7 +3130,7 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) /* - Create chunks and set them volatile + Create chunk metadata */ for(s16 x=-1; x<=1; x++) @@ -3052,13 +3138,15 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) { v2s16 chunkpos0 = chunkpos + v2s16(x,y); // Add chunk meta information - MapChunk *chunk = getChunk(chunkpos); + MapChunk *chunk = getChunk(chunkpos0); if(chunk == NULL) { chunk = new MapChunk(); m_chunks.insert(chunkpos0, chunk); } - chunk->setIsVolatile(true); + //chunk->setIsVolatile(true); + if(chunk->getGenLevel() > GENERATED_PARTLY) + chunk->setGenLevel(GENERATED_PARTLY); } /* @@ -3067,243 +3155,37 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos) MapChunk *chunk = getChunk(chunkpos); assert(chunk); // Set non-volatile - chunk->setIsVolatile(false); + //chunk->setIsVolatile(false); + chunk->setGenLevel(GENERATED_FULLY); // Return it return chunk; } -#if 0 -ServerMapSector * ServerMap::generateSector(v2s16 p2d) +MapChunk* ServerMap::generateChunk(v2s16 chunkpos1, + core::map &changed_blocks) { - DSTACK("%s: p2d=(%d,%d)", - __FUNCTION_NAME, - p2d.X, p2d.Y); - - // Check that it doesn't exist already - ServerMapSector *sector = (ServerMapSector*)getSectorNoGenerateNoEx(p2d); - if(sector != NULL) - return sector; - - /* - If there is no master heightmap, throw. - */ - if(m_heightmap == NULL) - { - throw InvalidPositionException("generateSector(): no heightmap"); - } - - /* - Do not generate over-limit - */ - if(p2d.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE - || p2d.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE - || p2d.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE - || p2d.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE) - throw InvalidPositionException("generateSector(): pos. over limit"); - - /* - Generate sector and heightmaps - */ - - // Number of heightmaps in sector in each direction - u16 hm_split = SECTOR_HEIGHTMAP_SPLIT; - - // Heightmap side width - s16 hm_d = MAP_BLOCKSIZE / hm_split; - - sector = new ServerMapSector(this, p2d, hm_split); - - // Sector position on map in nodes - v2s16 nodepos2d = p2d * MAP_BLOCKSIZE; - - /*dstream<<"Generating sector ("<getGroundHeight(mhm_p+v2s16(0,0)*hm_split), - m_heightmap->getGroundHeight(mhm_p+v2s16(1,0)*hm_split), - m_heightmap->getGroundHeight(mhm_p+v2s16(1,1)*hm_split), - m_heightmap->getGroundHeight(mhm_p+v2s16(0,1)*hm_split), - }; - - float avgheight = (corners[0]+corners[1]+corners[2]+corners[3])/4.0; - float avgslope = 0.0; - avgslope += fabs(avgheight - corners[0]); - avgslope += fabs(avgheight - corners[1]); - avgslope += fabs(avgheight - corners[2]); - avgslope += fabs(avgheight - corners[3]); - avgslope /= 4.0; - avgslope /= MAP_BLOCKSIZE; - //dstream<<"avgslope="<getSlope(p2d+v2s16(0,0)); - pitness += -a.X; - pitness += -a.Y; - a = m_heightmap->getSlope(p2d+v2s16(0,1)); - pitness += -a.X; - pitness += a.Y; - a = m_heightmap->getSlope(p2d+v2s16(1,1)); - pitness += a.X; - pitness += a.Y; - a = m_heightmap->getSlope(p2d+v2s16(1,0)); - pitness += a.X; - pitness += -a.Y; - pitness /= 4.0; - pitness /= MAP_BLOCKSIZE; - //dstream<<"pitness="<getNearAttr(nodepos2d).getFloat();*/ - local_plants_amount = - palist->getInterpolatedFloat(nodepos2d); - } -#endif - - /* - Generate sector heightmap - */ - - // Loop through sub-heightmaps - for(s16 y=0; ygetGroundHeight(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=("<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(); + v2s16 chunkpos0 = chunkpos1 + v2s16(x,y); + MapChunk *chunk = getChunk(chunkpos0); + // Skip if already generated + if(chunk != NULL && chunk->getGenLevel() == GENERATED_FULLY) + continue; + generateChunkRaw(chunkpos0, changed_blocks); } - - /* - Generate objects - */ - core::map *objects = new core::map; - sector->setObjects(objects); + assert(chunkNonVolatile(chunkpos1)); - 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 t = avgslope; - float a = area/16 * m_params.plants_amount * local_plants_amount; - u32 tree_max; - //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; igetGroundHeight(v2s16(x,z))+1; - if(y < WATER_LEVEL) - continue; - objects->insert(v3s16(x, y, z), - 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; - 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) - bush_max = a; - u32 count = (myrand()%(bush_max+1)); - for(u32 i=0; igetGroundHeight(v2s16(x,z))+1; - if(y < WATER_LEVEL) - continue; - objects->insert(v3s16(x, y, z), - SECTOR_OBJECT_BUSH_1); - } - } - /* - Add ravine (randomly) - */ - if(m_params.ravines_amount > 0.001) - { - if(myrand()%(s32)(200.0 / m_params.ravines_amount) == 0) - { - s16 s = 6; - 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; - objects->insert(v3s16(x, y, z), - SECTOR_OBJECT_RAVINE); - } - } - - /* - Insert to container - */ - m_sectors.insert(p2d, sector); - - return sector; + MapChunk *chunk = getChunk(chunkpos1); + return chunk; } -#endif ServerMapSector * ServerMap::createSector(v2s16 p2d) { @@ -3418,7 +3300,8 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d) return sector; } -MapSector * ServerMap::emergeSector(v2s16 p2d) +MapSector * ServerMap::emergeSector(v2s16 p2d, + core::map &changed_blocks) { DSTACK("%s: p2d=(%d,%d)", __FUNCTION_NAME, @@ -3428,18 +3311,19 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) Check chunk status */ v2s16 chunkpos = sector_to_chunk(p2d); - bool chunk_exists = false; + /*bool chunk_nonvolatile = false; MapChunk *chunk = getChunk(chunkpos); if(chunk && chunk->getIsVolatile() == false) - chunk_exists = true; + chunk_nonvolatile = true;*/ + bool chunk_nonvolatile = chunkNonVolatile(chunkpos); /* If chunk is not fully generated, generate chunk */ - if(chunk_exists == false) + if(chunk_nonvolatile == false) { // Generate chunk and neighbors - generateChunk(chunkpos); + generateChunk(chunkpos, changed_blocks); } /* @@ -3474,6 +3358,10 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) //return generateSector(); } +/* + NOTE: This is not used for main map generation, only for blocks + that are very high or low +*/ MapBlock * ServerMap::generateBlock( v3s16 p, MapBlock *original_dummy, @@ -4418,14 +4306,9 @@ MapBlock * ServerMap::emergeBlock( */ ServerMapSector *sector; try{ - sector = (ServerMapSector*)emergeSector(p2d); + sector = (ServerMapSector*)emergeSector(p2d, changed_blocks); assert(sector->getId() == MAPSECTOR_SERVER); } - /*catch(InvalidPositionException &e) - { - dstream<<"emergeBlock: emergeSector() failed"<= 1) + { + dstream<<"initialEmerge: area: "; + block_area_nodes.print(dstream); + dstream<<" ("< &changed_blocks){ return NULL; } // Returns InvalidPositionException if not found MapBlock * getBlockNoCreate(v3s16 p); @@ -364,22 +366,42 @@ public: return n->getValue(); } + /* + True if the chunk and its neighbors are fully generated. + It means the chunk will not be touched in the future by the + generator. If false, generateChunk will make it true. + */ + bool chunkNonVolatile(v2s16 chunkpos) + { + /*for(s16 x=-1; x<=1; x++) + for(s16 y=-1; y<=1; y++)*/ + s16 x=0; + s16 y=0; + { + v2s16 chunkpos0 = chunkpos + v2s16(x,y); + MapChunk *chunk = getChunk(chunkpos); + if(chunk == NULL) + return false; + if(chunk->getGenLevel() != GENERATED_FULLY) + return false; + } + return true; + } + /* Generate a chunk. All chunks touching this one can be altered also. - - Doesn't update lighting. */ - MapChunk* generateChunkRaw(v2s16 chunkpos); + MapChunk* generateChunkRaw(v2s16 chunkpos, + core::map &changed_blocks); /* Generate a chunk and its neighbors so that it won't be touched anymore. - - Doesn't update lighting. */ - MapChunk* generateChunk(v2s16 chunkpos); + MapChunk* generateChunk(v2s16 chunkpos, + core::map &changed_blocks); /* Generate a sector. @@ -402,7 +424,14 @@ public: - Check disk (loads blocks also) - Generate chunk */ - MapSector * emergeSector(v2s16 p); + MapSector * emergeSector(v2s16 p, + core::map &changed_blocks); + + MapSector * emergeSector(v2s16 p) + { + core::map changed_blocks; + return emergeSector(p, changed_blocks); + } MapBlock * generateBlock( v3s16 p, @@ -418,7 +447,11 @@ public: - Create blank */ MapBlock * createBlock(v3s16 p); - + + /* + only_from_disk, changed_blocks and lighting_invalidated_blocks + are not properly used by the new map generator. + */ MapBlock * emergeBlock( v3s16 p, bool only_from_disk, diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 3e20cb4c..b388a82c 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -700,6 +700,9 @@ void MapBlock::updateMesh(u32 daynight_ratio) const u16 indices[] = {0,1,2,2,3,0}; video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec); + if(texture == NULL) + continue; + material.setTexture(0, texture); if(f.tile.alpha != 255) material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; diff --git a/src/mapchunk.h b/src/mapchunk.h index 284eebe6..1f89b38a 100644 --- a/src/mapchunk.h +++ b/src/mapchunk.h @@ -22,14 +22,21 @@ with this program; if not, write to the Free Software Foundation, Inc., /* MapChunk contains map-generation-time metadata for an area of - some MapSectors. (something like 64x64) + some MapSectors. (something like 16x16) */ +enum{ + GENERATED_FULLY = 0, + GENERATED_PARTLY = 10, + GENERATED_NOT = 20 +}; + class MapChunk { public: MapChunk(): - m_is_volatile(true) + //m_is_volatile(true) + m_generation_level(GENERATED_NOT) { } @@ -40,11 +47,21 @@ public: It is set to false when all the 8 neighboring chunks have been generated. */ - bool getIsVolatile(){ return m_is_volatile; } - void setIsVolatile(bool is){ m_is_volatile = is; } + /*bool getIsVolatile(){ return m_is_volatile; } + void setIsVolatile(bool is){ m_is_volatile = is; }*/ + + /* + Generation level. Possible values: + GENERATED_FULLY = 0 = fully generated + GENERATED_PARTLY = partly generated + GENERATED_NOT = not generated + */ + u16 getGenLevel(){ return m_generation_level; } + void setGenLevel(u16 lev){ m_generation_level = lev; } private: - bool m_is_volatile; + //bool m_is_volatile; + u16 m_generation_level; }; #endif diff --git a/src/mapnode.cpp b/src/mapnode.cpp index b2d579d5..f5ca0ca9 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -82,6 +82,9 @@ void init_mapnode(IIrrlichtWrapper *irrlicht) i = CONTENT_TREE; f = &g_content_features[i]; f->setAllTextures(irrlicht->getTextureId("tree.png")); + f->setTexture(0, irrlicht->getTextureId("tree_top.png")); + f->setTexture(1, irrlicht->getTextureId("tree_top.png")); + f->setInventoryTexture(irrlicht->getTextureId("tree_top.png")); f->param_type = CPT_MINERAL; f->is_ground_content = true; diff --git a/src/player.cpp b/src/player.cpp index b260e505..1a553157 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -428,6 +428,9 @@ void LocalPlayer::move(f32 dtime, Map &map) void LocalPlayer::applyControl(float dtime) { + // Clear stuff + swimming_up = false; + // Random constants #define WALK_ACCELERATION (4.0 * BS) #define WALKSPEED_MAX (4.0 * BS) @@ -510,6 +513,7 @@ void LocalPlayer::applyControl(float dtime) v3f speed = getSpeed(); speed.Y = 2.0*BS; setSpeed(speed); + swimming_up = true; } } diff --git a/src/player.h b/src/player.h index 5ab027e0..30df1db8 100644 --- a/src/player.h +++ b/src/player.h @@ -115,6 +115,7 @@ public: bool touching_ground; bool in_water; + bool swimming_up; Inventory inventory; diff --git a/src/server.cpp b/src/server.cpp index 28faaf44..fea4ce73 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -515,9 +515,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, generate = false; } +#if 0 /* If block is far away, don't generate it unless it is near ground level + + NOTE: We can't know the ground level this way with the + new generator. */ if(d > 4) { @@ -543,6 +547,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, generate = false; } } +#endif /* Don't draw if not in sight @@ -610,11 +615,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, v2s16 p2d(p.X, p.Z); ServerMap *map = (ServerMap*)(&server->m_env.getMap()); v2s16 chunkpos = map->sector_to_chunk(p2d); - MapChunk *chunk = map->getChunk(chunkpos); + if(map->chunkNonVolatile(chunkpos) == false) + block_is_invalid = true; + /*MapChunk *chunk = map->getChunk(chunkpos); if(chunk == NULL) block_is_invalid = true; else if(chunk->getIsVolatile() == true) - block_is_invalid = true; + block_is_invalid = true;*/ } /* @@ -3175,6 +3182,16 @@ Player *Server::emergePlayer(const char *name, const char *password, { setCreativeInventory(player); } + + /* + With new map generator the map is regenerated anyway, + so start at somewhere where you probably don't get underground + */ + player->setPosition(intToFloat(v3s16( + 0, + 50, + 0 + ))); return player; } @@ -3206,9 +3223,17 @@ Player *Server::emergePlayer(const char *name, const char *password, dstream<<"Server: Finding spawn place for player \"" <getName()<<"\""<setPosition(intToFloat(v3s16( + 0, + 50, + 0 + ))); +#endif +#if 0 +#if 0 // Try to find a good place a few times for(s32 i=0; i<500; i++) { @@ -3271,6 +3296,7 @@ Player *Server::emergePlayer(const char *name, const char *password, groundheight + 15, nodepos.Y ))); +#endif /* Add player to environment diff --git a/src/utility.h b/src/utility.h index 8839887f..cc69099b 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1474,8 +1474,11 @@ void mysrand(unsigned seed); inline int myrand_range(int min, int max) { - if(min >= max) + if(min > max) + { + assert(0); return max; + } return (myrand()%(max-min+1))+min; } -- 2.30.2