From: Perttu Ahola Date: Sat, 2 Apr 2011 17:55:22 +0000 (+0300) Subject: Mapgen is better now. Not a lot, but a bit! X-Git-Url: http://81.2.79.47:8989/gitweb/?a=commitdiff_plain;h=bc66bb2d409f13554bdcec7386766af82a343cad;p=zefram%2Fminetest%2Fminetest_engine.git Mapgen is better now. Not a lot, but a bit! --- diff --git a/data/water.png b/data/water.png index 20f74edf..9657dbed 100644 Binary files a/data/water.png and b/data/water.png differ diff --git a/src/main.cpp b/src/main.cpp index ec406086..fb1b2d8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -194,7 +194,7 @@ TODO: Copy the text of the last picked sign to inventory in creative TODO: Check what goes wrong with caching map to disk (Kray) - Nothing? -FIXME: Server went into some infinite PeerNotFoundException loop +FIXME: Server sometimes goes into some infinite PeerNotFoundException loop * Fix the problem with the server constantly saving one or a few blocks? List the first saved block, maybe it explains. @@ -259,7 +259,7 @@ FEATURE: Erosion simulation at map generation time - Simulate rock falling from cliffs when water has removed enough solid rock from the bottom -Mapgen v2: +Mapgen v2 (not doing): * only_from_disk might not work anymore - check and fix it. * Make the generator to run in background and not blocking block placement and transfer @@ -280,7 +280,7 @@ Mapgen v4 (not doing): * Make chunks to be tiled vertically too * MAKE IT FASTER -Mapgen v3: +Mapgen v3 (not doing): * Generate trees better - Add a "trees_added" flag to sector, or something * How 'bout making turbulence controlled so that for a given 2d position @@ -292,7 +292,7 @@ Mapgen v3: Mapgen v4: * This will be the final way. -* Generate blocks in the same way as chunks, by copying a voxelmanipulator +* Generate blocks in the same way as chunks, by copying a VoxelManipulator from the map that is one block larger in all directions. Misc. stuff: diff --git a/src/map.cpp b/src/map.cpp index aabe8406..651bece4 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1710,13 +1710,6 @@ ServerMap::ServerMap(std::string savedir): Map(dout_server), m_seed(0) { - - //m_chunksize = 64; - //m_chunksize = 16; // Too slow - //m_chunksize = 8; // Takes a few seconds - m_chunksize = 4; // Too small? - //m_chunksize = 2; - // TODO: Save to and load from a file m_seed = (((u64)(myrand()%0xffff)<<0) + ((u64)(myrand()%0xffff)<<16) @@ -1751,12 +1744,9 @@ ServerMap::ServerMap(std::string savedir): } else { - // Load map metadata (seed, chunksize) + // Load map metadata (seed) loadMapMeta(); - // Load chunk metadata - loadChunkMeta(); - /*// Load sector (0,0) and throw and exception on fail if(loadSectorFull(v2s16(0,0)) == false) throw LoadError("Failed to load sector (0,0)");*/ @@ -1819,16 +1809,6 @@ ServerMap::~ServerMap() dstream<::Iterator i = m_chunks.getIterator(); - for(; i.atEnd() == false; i++) - { - MapChunk *chunk = i.getNode()->getValue(); - delete chunk; - } } /* @@ -1883,6 +1863,7 @@ void make_tree(VoxelManipulator &vmanip, v3s16 p0) { MapNode treenode(CONTENT_TREE); MapNode leavesnode(CONTENT_LEAVES); + leavesnode.setLight(LIGHTBANK_DAY, LIGHT_MAX-1); vmanip.emerge(VoxelArea(p0-v3s16(2,0,2),p0+v3s16(2,7+2,2))); @@ -1962,18 +1943,18 @@ double tree_amount_2d(u64 seed, v2s16 p) double noise = noise2d_perlin( 0.5+(float)p.X/250, 0.5+(float)p.Y/250, seed+2, 5, 0.7); - double zeroval = -0.4; + double zeroval = -0.5; if(noise < zeroval) return 0; else - return 0.025 * (noise-zeroval) / (1.0-zeroval); + return 0.03 * (noise-zeroval) / (1.0-zeroval); } #define AVERAGE_MUD_AMOUNT 4.0 double get_mud_amount(u64 seed, v2f p) { - return ((float)AVERAGE_MUD_AMOUNT + 3.0 * noise2d_perlin( + return ((float)AVERAGE_MUD_AMOUNT + 2.5 * noise2d_perlin( 0.5+p.X/200, 0.5+p.Y/200, seed+1, 5, 0.65)); } @@ -2121,8 +2102,8 @@ double base_rock_level_2d(u64 seed, v2f p) { // Mountains double m4 = 1.0 - 3.0 * noise2d_perlin_abs( - 0.324+(float)p.X/2000., 0.423+(float)p.Y/2000., - (seed>>32)+65012102, 9, 0.57); + 0.324+(float)p.X/1000., 0.423+(float)p.Y/1000., + (seed>>32)+65012102, 8, 0.57); m4 *= 120; if(m4 > h) h = m4; @@ -2365,7 +2346,7 @@ bool is_carved(u64 seed, v3f p) #endif double f = 10.0; - double y_div = 1.5; + double y_div = 1.0; double v4 = contour(f*noise3d_perlin( 0.5+p.X/200, @@ -4082,6 +4063,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, } #endif +#if 0 MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, core::map &changed_blocks, bool force) @@ -4813,6 +4795,7 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos1, MapChunk *chunk = getChunk(chunkpos1); return chunk; } +#endif ServerMapSector * ServerMap::createSector(v2s16 p2d) { @@ -4873,7 +4856,8 @@ MapSector * ServerMap::emergeSector(v2s16 p2d, DSTACK("%s: p2d=(%d,%d)", __FUNCTION_NAME, p2d.X, p2d.Y); - + +#if 0 /* Check chunk status */ @@ -4892,7 +4876,8 @@ MapSector * ServerMap::emergeSector(v2s16 p2d, // Generate chunk and neighbors generateChunk(chunkpos, changed_blocks); } - +#endif + /* Return sector if it exists now */ @@ -4923,7 +4908,7 @@ MapSector * ServerMap::emergeSector(v2s16 p2d, < &changed_blocks, - core::map &lighting_invalidated_blocks -) + bool force) { - DSTACK("%s: p=(%d,%d,%d)", - __FUNCTION_NAME, - p.X, p.Y, p.Z); - - /*dstream<<"generateBlock(): " - <<"("<isFullyGenerated()) + { + dstream<<"generateBlockRaw(): Block " + <<"("<createBlankBlockNoInsert(block_y); - } - else - { - // Remove the block so that nobody can get a half-generated one. - sector->removeBlock(block); - // Allocate the block to contain the generated data - block->unDummify(); - } + s16 y_blocks_min = blockpos0.Y-1; + s16 y_blocks_max = blockpos0.Y+1; + s16 y_nodes_min = y_blocks_min * MAP_BLOCKSIZE; + s16 y_nodes_max = y_blocks_max * MAP_BLOCKSIZE + MAP_BLOCKSIZE - 1; + v2s16 sectorpos_bigbase = sectorpos0 - v2s16(1,1); + s16 sectorpos_bigbase_size = 3; + v2s16 sectorpos_base = sectorpos0; + s16 sectorpos_base_size = 1; + s16 max_spread_amount = MAP_BLOCKSIZE; + s16 lighting_min_d = 0-max_spread_amount; + s16 lighting_max_d = sectorpos_base_size*MAP_BLOCKSIZE+max_spread_amount-1; - u8 water_material = CONTENT_WATERSOURCE; + /* + Create the whole area of this and the neighboring blocks + */ - s32 lowest_ground_y = 32767; - s32 highest_ground_y = -32768; + core::list blocks_created; - enum{ - BT_GROUND, - BT_SURFACE, - BT_SKY - } block_type = BT_SURFACE; + { + //TimeTaker timer("generateBlockRaw() create area"); + + for(s16 x=-1; x<=1; x++) + for(s16 z=-1; z<=1; z++) + { + v2s16 sectorpos = sectorpos0 + v2s16(x,z); + ServerMapSector *sector = createSector(sectorpos); + assert(sector); - {// ground_timer (0ms or ~100ms) - TimeTaker ground_timer("Ground generation"); + for(s16 y=blockpos0.Y-1; y<=blockpos0.Y+1; y++) + { + v3s16 blockpos(sectorpos.X, y, sectorpos.Y); + + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block && block->isDummy() == false) + continue; + + block = createBlock(blockpos); + block->setFullyGenerated(false); + + blocks_created.push_back(blockpos); + + // Lighting won't be calculated + block->setLightingExpired(true); + // Lighting will be calculated + //block->setLightingExpired(false); + + /* + 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. + This doesn't matter if the initial lighting is done + here. + */ + //block->setIsUnderground(y != y_blocks_max); + block->setIsUnderground(false); + } + } + } + /* - Approximate whether this block is a surface block, an air - block or a ground block. + Now we have a big empty area of (16x16x16)x27. - This shall never mark a surface block as non-surface. + Make a ManualMapVoxelManipulator that contains the whole area. */ + ManualMapVoxelManipulator vmanip(this); + // Add the area we just generated + { + //TimeTaker timer("generateBlockRaw() initialEmerge"); + vmanip.initialEmerge(blockpos0-v3s16(1,1,1), blockpos0+v3s16(1,1,1)); + } + + // Clear all flags + vmanip.clearFlag(0xff); + + // Block type of blockpos0 + BlockType center_block_type = BT_SURFACE; + + /* + Generate general ground level to newly created blocks. + Only stone is used and it is converted to other stuff later on. + */ + { + // 22ms @cs=8 + //dstream<<"Generating base ground..."<::Iterator i = blocks_created.begin(); + i != blocks_created.end(); i++) { + v3s16 blockpos = *i; + v2s16 sectorpos(blockpos.X, blockpos.Z); + /* - Estimate surface at different positions of the block, to - try to accomodate the effect of turbulence. + Approximate whether this block is a surface block, an air + block or a ground block. + + This shall never mark a surface block as non-surface. */ - v3f checklist[] = { - v3f(0,0,0), - v3f(0,1,0), - v3f(0,1,1), - v3f(0,0,1), - v3f(1,0,0), - v3f(1,1,0), - v3f(1,1,1), - v3f(1,0,1), - v3f(0.5,0.5,0.5), - }; - v3f p_nodes_f = intToFloat(p_nodes, 1); - float surface_y_max = -1000000; - float surface_y_min = 1000000; - for(u32 i=0; i surface_y_max) - surface_y_max = surface_y_f; - if(surface_y_f < surface_y_min) - surface_y_min = surface_y_f; - } + if(surface_y_f > surface_y_max) + surface_y_max = surface_y_f; + if(surface_y_f < surface_y_min) + surface_y_min = surface_y_f; + } - float block_low_y_f = p_nodes_f.Y; - float block_high_y_f = p_nodes_f.Y + MAP_BLOCKSIZE; + float block_low_y_f = p_nodes_f.Y; + float block_high_y_f = p_nodes_f.Y + MAP_BLOCKSIZE; - /*dstream<<"surface_y_max="<= surface_y_max + d_up - && block_low_y_f > WATER_LEVEL + d_up) - { - //dstream<<"BT_SKY"<= surface_y_max + d_up + && block_low_y_f > WATER_LEVEL + d_up) + { + //dstream<<"BT_SKY"<setIsUnderground(true); } - } - - if(block_type == BT_SURFACE || block_type == BT_GROUND) - { + /* - Generate ground precisely + If the block has ground, generate ground precisely. */ - for(s16 z0=0; z0=y_nodes_min; y--) + { + MapNode *n = &vmanip.m_data[i]; + if(light_propagates_content(n->d) == false) + { + light = 0; + } + else if(light != LIGHT_SUN + || sunlight_propagates_content(n->d) == false) + { + if(light > 0) + light--; + } + + n->setLight(LIGHTBANK_DAY, light); + n->setLight(LIGHTBANK_NIGHT, 0); + + if(light != 0) + { + // Insert light source + light_sources.insert(v3s16(p2d.X, y, p2d.Y), true); + } + + // Increment index by y + vmanip.m_area.add_y(em, i, -1); + } + } + } + + /* + This has to be 1 smaller than the actual area, because + neighboring nodes are checked. + */ + for(s16 x=lighting_min_d+1; + x<=lighting_max_d-1; + x++) + for(s16 z=lighting_min_d+1; + z<=lighting_max_d-1; + z++) + { + // Node position in 2d + v2s16 p2d = sectorpos_base*MAP_BLOCKSIZE + v2s16(x,z); + + /* + Apply initial sunlight + */ + { + u8 light = LIGHT_SUN; + bool add_to_sources = false; + v3s16 em = vmanip.m_area.getExtent(); + s16 y_start = y_nodes_max; + u32 i = vmanip.m_area.index(v3s16(p2d.X, y_start, p2d.Y)); + for(s16 y=y_start; y>=y_nodes_min; y--) + { + MapNode *n = &vmanip.m_data[i]; + + if(light_propagates_content(n->d) == false) + { + light = 0; + } + else if(light != LIGHT_SUN + || sunlight_propagates_content(n->d) == false) + { + 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); + + // 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); + } + + // Increment index by y + vmanip.m_area.add_y(em, i, -1); + } + } + } + + }//timer1 + + // Spread light around + { + TimeTaker timer("generateBlockRaw() spreadLight"); + vmanip.spreadLight(LIGHTBANK_DAY, light_sources); + } +#endif + + /* + Blit generated stuff to map + */ + { + vmanip.blitBackAll(&changed_blocks); + } + +#if 0 + /* + Update day/night difference cache of the MapBlocks + */ + { + for(core::map::Iterator i = changed_blocks.getIterator(); + i.atEnd() == false; i++) + { + MapBlock *block = i.getNode()->getValue(); + block->updateDayNightDiff(); + } + } +#endif + + /*for(core::map::Iterator + i = changed_blocks*/ + + // Done! + MapBlock *block = getBlockNoCreate(blockpos0); + block->setFullyGenerated(true); + + /* + TODO: Calculate lighting with the VoxelManipulator, not this way + */ + // emergeBlock reads this + block->setLightingExpired(true); + // Also set the above one, trees often will be there + { + MapBlock *block = getBlockNoCreate(blockpos0+v3s16(0,1,0)); + if(block) + block->setLightingExpired(true); + } + + return block; +} + + +/*MapBlock* ServerMap::generateBlock(v3s16 blockpos1, + core::map &changed_blocks)*/ +MapBlock * ServerMap::generateBlock( + v3s16 blockpos1, + MapBlock *original_dummy, + ServerMapSector *sector, + core::map &changed_blocks, + core::map &lighting_invalidated_blocks +) +{ + dstream<<"generateBlock(): Generating block " + <<"("<isFullyGenerated()) + continue; + generateBlockRaw(blockpos0, changed_blocks); + } + + assert(blockNonVolatile(blockpos1)); + + MapBlock *block = getBlockNoCreate(blockpos1); + + return block; +} + +#if 0 +/* + NOTE: This is not used for main map generation, only for blocks + that are very high or low. + NOTE: Now it is used mainly. Might change in the future. +*/ +MapBlock * ServerMap::generateBlock( + v3s16 p, + MapBlock *original_dummy, + ServerMapSector *sector, + core::map &changed_blocks, + core::map &lighting_invalidated_blocks +) +{ + DSTACK("%s: p=(%d,%d,%d)", + __FUNCTION_NAME, + p.X, p.Y, p.Z); + + /*dstream<<"generateBlock(): " + <<"("<createBlankBlockNoInsert(block_y); + } + else + { + // Remove the block so that nobody can get a half-generated one. + sector->removeBlock(block); + // Allocate the block to contain the generated data + block->unDummify(); + } + + u8 water_material = CONTENT_WATERSOURCE; + + s32 lowest_ground_y = 32767; + s32 highest_ground_y = -32768; + + enum{ + BT_GROUND, + BT_SURFACE, + BT_SKY + } block_type = BT_SURFACE; + + {// ground_timer (0ms or ~100ms) + TimeTaker ground_timer("Ground generation"); + + /* + Approximate whether this block is a surface block, an air + block or a ground block. + + This shall never mark a surface block as non-surface. + */ + + { + /* + Estimate surface at different positions of the block, to + try to accomodate the effect of turbulence. + */ + v3f checklist[] = { + v3f(0,0,0), + v3f(0,1,0), + v3f(0,1,1), + v3f(0,0,1), + v3f(1,0,0), + v3f(1,1,0), + v3f(1,1,1), + v3f(1,0,1), + v3f(0.5,0.5,0.5), + }; + v3f p_nodes_f = intToFloat(p_nodes, 1); + float surface_y_max = -1000000; + float surface_y_min = 1000000; + for(u32 i=0; i surface_y_max) + surface_y_max = surface_y_f; + if(surface_y_f < surface_y_min) + surface_y_min = surface_y_f; + } + + float block_low_y_f = p_nodes_f.Y; + float block_high_y_f = p_nodes_f.Y + MAP_BLOCKSIZE; + + /*dstream<<"surface_y_max="<= surface_y_max + d_up + && block_low_y_f > WATER_LEVEL + d_up) + { + //dstream<<"BT_SKY"<insertBlock(block); + if(block == NULL) + { + // Create dummy block + block = new MapBlock(this, p, true); + + // Add block to sector + sector->insertBlock(block); + } + // Done. + return block; } - // Done. - return block; } //dstream<<"Not found on disk, generating."< list = fs::GetDirListing(m_savedir+"/sectors/"); @@ -6363,7 +7307,8 @@ void ServerMap::saveMapMeta() DSTACK(__FUNCTION_NAME); dstream<<"INFO: ServerMap::saveMapMeta(): " - <<"seed="<::Node *n; - n = m_chunks.find(chunkpos); - if(n == NULL) - return NULL; - 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. + True if the block and its neighbors are fully generated. + It means the block will not be touched in the future by the + generator. If false, generateBlock will make it true. */ - bool chunkNonVolatile(v2s16 chunkpos) + bool blockNonVolatile(v3s16 blockpos) { - /*for(s16 x=-1; x<=1; x++) - for(s16 y=-1; y<=1; y++)*/ - s16 x=0; - s16 y=0; + for(s16 x=-1; x<=1; x++) + for(s16 y=-1; y<=1; y++) + for(s16 z=-1; z<=1; z++) { - v2s16 chunkpos0 = chunkpos + v2s16(x,y); - MapChunk *chunk = getChunk(chunkpos); - if(chunk == NULL) + v3s16 blockpos0 = blockpos + v3s16(x,y,z); + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block == NULL) return false; - if(chunk->getGenLevel() != GENERATED_FULLY) + if(block->isFullyGenerated() == false) return false; } return true; } - /* - Generate a chunk. - - All chunks touching this one can be altered also. - */ - MapChunk* generateChunkRaw(v2s16 chunkpos, - core::map &changed_blocks, - bool force=false); - - /* - Generate a chunk and its neighbors so that it won't be touched - anymore. - */ - MapChunk* generateChunk(v2s16 chunkpos, - core::map &changed_blocks); - /* Generate a sector. - - This is mainly called by generateChunkRaw. */ //ServerMapSector * generateSector(v2s16 p); @@ -437,6 +384,27 @@ public: return emergeSector(p, changed_blocks); } + /*MapBlock * generateBlock( + v3s16 p, + MapBlock *original_dummy, + ServerMapSector *sector, + core::map &changed_blocks, + core::map &lighting_invalidated_blocks + );*/ + + /* + Generate a block. + + All blocks touching this one can be altered also. + */ + MapBlock* generateBlockRaw(v3s16 blockpos, + core::map &changed_blocks, + bool force=false); + + /* + Generate a block and its neighbors so that it won't be touched + anymore. + */ MapBlock * generateBlock( v3s16 p, MapBlock *original_dummy, @@ -444,6 +412,8 @@ public: core::map &changed_blocks, core::map &lighting_invalidated_blocks ); + /*MapBlock* generateBlock(v3s16 blockpos, + core::map &changed_blocks);*/ /* Get a block from somewhere. @@ -516,9 +486,6 @@ public: void saveMapMeta(); void loadMapMeta(); - void saveChunkMeta(); - void loadChunkMeta(); - // The sector mutex should be locked when calling most of these // This only saves sector-specific data such as the heightmap @@ -551,11 +518,6 @@ private: std::string m_savedir; bool m_map_saving_enabled; - - // Chunk size in MapSectors - s16 m_chunksize; - // Chunks - core::map m_chunks; }; /* diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 9594b296..94c6ad90 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -36,6 +36,7 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy): is_underground(false), m_lighting_expired(true), m_day_night_differs(false), + m_not_fully_generated(false), m_objects(this) { data = NULL; @@ -1762,6 +1763,8 @@ void MapBlock::serialize(std::ostream &os, u8 version) flags |= 0x02; if(m_lighting_expired) flags |= 0x04; + if(m_not_fully_generated) + flags |= 0x08; os.write((char*)&flags, 1); u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; @@ -1884,6 +1887,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version) is_underground = (flags & 0x01) ? true : false; m_day_night_differs = (flags & 0x02) ? true : false; m_lighting_expired = (flags & 0x04) ? true : false; + m_not_fully_generated = (flags & 0x08) ? true : false; // Uncompress data std::ostringstream os(std::ios_base::binary); diff --git a/src/mapblock.h b/src/mapblock.h index 02c07289..97129bd3 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -244,6 +244,17 @@ public: return m_lighting_expired; } + bool isFullyGenerated() + { + return !m_not_fully_generated; + } + + void setFullyGenerated(bool b) + { + setChangedFlag(); + m_not_fully_generated = !b; + } + bool isValid() { if(m_lighting_expired) @@ -655,12 +666,28 @@ private: // Whether day and night lighting differs bool m_day_night_differs; + /* + Whether everything that is mainly located on this block has + been added to the world. + + While this is false, a block can still be changed a bit when + stuff is added to the neighboring blocks that extends to this + one. + + When this is false on every one of a 3x3x3 chunk of blocks, the + central one will not be changed by the map generator in the + future. + + TODO: Save in file + */ + bool m_not_fully_generated; + MapBlockObjectList m_objects; // Object spawning stuff float m_spawn_timer; -#ifndef SERVER +#ifndef SERVER // Only on client /* Set to true if the mesh has been ordered to be updated sometime in the background. diff --git a/src/mapchunk.h b/src/mapchunk.h deleted file mode 100644 index 1819fa13..00000000 --- a/src/mapchunk.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef MAPCHUNK_HEADER -#define MAPCHUNK_HEADER - -/* - MapChunk contains map-generation-time metadata for an area of - some MapSectors. (something like 16x16) -*/ - -// These should fit in 8 bits, as they are saved as such. -enum{ - GENERATED_FULLY = 0, - GENERATED_PARTLY = 10, - GENERATED_NOT = 20 -}; - -class MapChunk -{ -public: - MapChunk(): - m_generation_level(GENERATED_NOT) - { - } - - /* - 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; } - - void serialize(std::ostream &os, u8 version) - { - os.write((char*)&m_generation_level, 1); - } - void deSerialize(std::istream &is, u8 version) - { - is.read((char*)&m_generation_level, 1); - } - -private: - u8 m_generation_level; -}; - -#endif - diff --git a/src/materials.cpp b/src/materials.cpp index f56b024b..0558a5e3 100644 --- a/src/materials.cpp +++ b/src/materials.cpp @@ -13,9 +13,9 @@ void setStoneLikeDiggingProperties(u8 material, float toughness) DiggingProperties(true, 15.0*toughness, 0)); g_material_properties[material].setDiggingProperties("WPick", - DiggingProperties(true, 1.5*toughness, 65535./30.*toughness)); + DiggingProperties(true, 1.3*toughness, 65535./30.*toughness)); g_material_properties[material].setDiggingProperties("STPick", - DiggingProperties(true, 0.7*toughness, 65535./100.*toughness)); + DiggingProperties(true, 0.65*toughness, 65535./100.*toughness)); /*g_material_properties[material].setDiggingProperties("MesePick", DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/ diff --git a/src/server.cpp b/src/server.cpp index 61f35417..abdbd975 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -544,11 +544,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, block_is_invalid = true; } - v2s16 p2d(p.X, p.Z); - ServerMap *map = (ServerMap*)(&server->m_env.getMap()); - v2s16 chunkpos = map->sector_to_chunk(p2d); - if(map->chunkNonVolatile(chunkpos) == false) + if(block->isFullyGenerated() == false) + { block_is_invalid = true; + } } /* @@ -3420,16 +3419,6 @@ Player *Server::emergePlayer(const char *name, const char *password, nodepos = v2s16(-range + (myrand()%(range*2)), -range + (myrand()%(range*2))); v2s16 sectorpos = getNodeSectorPos(nodepos); - /* - Ignore position if it is near a chunk edge. - Otherwise it would cause excessive loading time at - initial generation - */ - { - if(m_env.getServerMap().sector_to_chunk(sectorpos+v2s16(1,1)) - != m_env.getServerMap().sector_to_chunk(sectorpos+v2s16(-1,-1))) - continue; - } // Get sector (NOTE: Don't get because it's slow) //m_env.getMap().emergeSector(sectorpos); // Get ground height at point (fallbacks to heightmap function)