X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmap.cpp;h=d644215be78911de0d56af9825eb684e98d94d3d;hb=7df125c249dc9b99b66f047a395106c2038eb00e;hp=159682696b0b1a792b88c489f53d16460771afcf;hpb=741776313a0be27de722bc9894a9cc987db433b0;p=dragonfireclient.git diff --git a/src/map.cpp b/src/map.cpp index 159682696..d644215be 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -34,30 +34,16 @@ with this program; if not, write to the Free Software Foundation, Inc., Map::Map(std::ostream &dout): m_dout(dout), - m_camera_position(0,0,0), - m_camera_direction(0,0,1), m_sector_cache(NULL) { m_sector_mutex.Init(); - m_camera_mutex.Init(); assert(m_sector_mutex.IsInitialized()); - assert(m_camera_mutex.IsInitialized()); - - // Get this so that the player can stay on it at first - //getSector(v2s16(0,0)); } Map::~Map() { /* - Stop updater thread - */ - /*updater.setRun(false); - while(updater.IsRunning()) - sleep_s(1);*/ - - /* - Free all MapSectors. + Free all MapSectors */ core::map::Iterator i = m_sectors.getIterator(); for(; i.atEnd() == false; i++) @@ -67,6 +53,29 @@ Map::~Map() } } +void Map::addEventReceiver(MapEventReceiver *event_receiver) +{ + m_event_receivers.insert(event_receiver, false); +} + +void Map::removeEventReceiver(MapEventReceiver *event_receiver) +{ + if(m_event_receivers.find(event_receiver) == NULL) + return; + m_event_receivers.remove(event_receiver); +} + +void Map::dispatchEvent(MapEditEvent *event) +{ + for(core::map::Iterator + i = m_event_receivers.getIterator(); + i.atEnd()==false; i++) + { + MapEventReceiver* event_receiver = i.getNode()->getKey(); + event_receiver->onMapEditEvent(event); + } +} + MapSector * Map::getSectorNoGenerateNoExNoLock(v2s16 p) { if(m_sector_cache != NULL && p == m_sector_cache_p){ @@ -145,34 +154,6 @@ MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d) return block; }*/ -f32 Map::getGroundHeight(v2s16 p, bool generate) -{ - try{ - v2s16 sectorpos = getNodeSectorPos(p); - MapSector * sref = getSectorNoGenerate(sectorpos); - v2s16 relpos = p - sectorpos * MAP_BLOCKSIZE; - f32 y = sref->getGroundHeight(relpos); - return y; - } - catch(InvalidPositionException &e) - { - return GROUNDHEIGHT_NOTFOUND_SETVALUE; - } -} - -void Map::setGroundHeight(v2s16 p, f32 y, bool generate) -{ - /*m_dout<mutex.Lock(); - sref->setGroundHeight(relpos, y); - //sref->mutex.Unlock(); -} - bool Map::isNodeUnderground(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); @@ -866,7 +847,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, /*PrintInfo(m_dout); m_dout<clone(); + setNodeMetadata(p, meta); + } /* - If node is under sunlight, take all sunlighted nodes under - it and clear light from them and from where the light has - been spread. + If node is under sunlight and doesn't let sunlight through, + 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) + if(node_under_sunlight && !content_features(n.d).sunlight_propagates) { s16 y = p.Y - 1; for(;; y--){ @@ -1001,7 +1001,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, break; } } - + for(s32 i=0; i<2; i++) { enum LightBank bank = banks[i]; @@ -1104,6 +1104,12 @@ void Map::removeNodeAndUpdate(v3s16 p, light_sources, modified_blocks); } + /* + Remove node metadata + */ + + removeNodeMetadata(p); + /* Remove the node. This also clears the lighting. @@ -1161,7 +1167,7 @@ void Map::removeNodeAndUpdate(v3s16 p, } catch(InvalidPositionException &e) { - throw; + assert(0); } } @@ -1221,94 +1227,62 @@ void Map::removeNodeAndUpdate(v3s16 p, } } -#ifndef SERVER -void Map::expireMeshes(bool only_daynight_diffed) +bool Map::addNodeWithEvent(v3s16 p, MapNode n) { - TimeTaker timer("expireMeshes()"); + MapEditEvent event; + event.type = MEET_ADDNODE; + event.p = p; + event.n = n; - core::map::Iterator si; - si = m_sectors.getIterator(); - for(; si.atEnd() == false; si++) - { - MapSector *sector = si.getNode()->getValue(); + bool succeeded = true; + try{ + core::map modified_blocks; + addNodeAndUpdate(p, n, modified_blocks); - core::list< MapBlock * > sectorblocks; - sector->getBlocks(sectorblocks); - - core::list< MapBlock * >::Iterator i; - for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++) + // Copy modified_blocks to event + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd()==false; 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); - } - } + event.modified_blocks.insert(i.getNode()->getKey(), false); } } + catch(InvalidPositionException &e){ + succeeded = false; + } + + dispatchEvent(&event); + + return succeeded; } -void Map::updateMeshes(v3s16 blockpos, u32 daynight_ratio) +bool Map::removeNodeWithEvent(v3s16 p) { - assert(mapType() == MAPTYPE_CLIENT); + MapEditEvent event; + event.type = MEET_REMOVENODE; + event.p = p; + bool succeeded = true; 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); - } - catch(InvalidPositionException &e){} - /*// Trailing 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); + core::map modified_blocks; + removeNodeAndUpdate(p, modified_blocks); + + // Copy modified_blocks to event + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd()==false; i++) + { + event.modified_blocks.insert(i.getNode()->getKey(), false); + } } - catch(InvalidPositionException &e){} - try{ - v3s16 p = blockpos + v3s16(0,0,1); - MapBlock *b = getBlockNoCreate(p); - b->updateMesh(daynight_ratio); + catch(InvalidPositionException &e){ + succeeded = false; } - catch(InvalidPositionException &e){}*/ -} -#endif + dispatchEvent(&event); + + return succeeded; +} bool Map::dayNightDiffed(v3s16 blockpos) { @@ -1739,6 +1713,49 @@ void Map::transformLiquids(core::map & modified_blocks) //dstream<<"Map::transformLiquids(): loopcount="<m_node_metadata.get(p_rel); + return meta; +} + +void Map::setNodeMetadata(v3s16 p, NodeMetadata *meta) +{ + v3s16 blockpos = getNodeBlockPos(p); + v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE; + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block == NULL) + { + dstream<<"WARNING: Map::setNodeMetadata(): Block not found" + <m_node_metadata.set(p_rel, meta); +} + +void Map::removeNodeMetadata(v3s16 p) +{ + v3s16 blockpos = getNodeBlockPos(p); + v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE; + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block == NULL) + { + dstream<<"WARNING: Map::removeNodeMetadata(): Block not found" + <m_node_metadata.remove(p_rel); +} + /* ServerMap */ @@ -3179,6 +3196,9 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, // Don't make a tree under water level if(y < WATER_LEVEL) continue; + // Don't make a tree so high that it doesn't fit + if(y > y_nodes_max - 6) + continue; v3s16 p(x,y,z); /* Trees grow only on mud and grass @@ -4371,7 +4391,7 @@ MapBlock * ServerMap::generateBlock( //if(!is_ground_content(block->getNode(cp).d)) if(1) { - RatObject *obj = new RatObject(NULL, -1, intToFloat(cp)); + RatObject *obj = new RatObject(NULL, -1, intToFloat(cp, BS)); block->addObject(obj); } } @@ -4624,6 +4644,42 @@ MapBlock * ServerMap::emergeBlock( return block; } +s16 ServerMap::findGroundLevel(v2s16 p2d) +{ + /* + Uh, just do something random... + */ + // Find existing map from top to down + s16 max=63; + s16 min=-64; + v3s16 p(p2d.X, max, p2d.Y); + for(; p.Y>min; p.Y--) + { + MapNode n = getNodeNoEx(p); + if(n.d != CONTENT_IGNORE) + break; + } + if(p.Y == min) + goto plan_b; + // If this node is not air, go to plan b + if(getNodeNoEx(p).d != CONTENT_AIR) + goto plan_b; + // Search existing walkable and return it + for(; p.Y>min; p.Y--) + { + MapNode n = getNodeNoEx(p); + if(content_walkable(n.d) && n.d != CONTENT_IGNORE) + return p.Y; + } + // Move to plan b +plan_b: + /* + Plan B: Get from map generator perlin noise function + */ + double level = base_rock_level_2d(m_seed, p2d); + return (s16)level; +} + void ServerMap::createDir(std::string path) { if(fs::CreateDir(path) == false) @@ -5211,28 +5267,6 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto } } -// Gets from master heightmap -void ServerMap::getSectorCorners(v2s16 p2d, s16 *corners) -{ - dstream<<"DEPRECATED: "<<__FUNCTION_NAME<getGroundHeight - ((p2d+v2s16(0,0))*SECTOR_HEIGHTMAP_SPLIT); - corners[1] = m_heightmap->getGroundHeight - ((p2d+v2s16(1,0))*SECTOR_HEIGHTMAP_SPLIT); - corners[2] = m_heightmap->getGroundHeight - ((p2d+v2s16(1,1))*SECTOR_HEIGHTMAP_SPLIT); - corners[3] = m_heightmap->getGroundHeight - ((p2d+v2s16(0,1))*SECTOR_HEIGHTMAP_SPLIT);*/ -} - void ServerMap::PrintInfo(std::ostream &out) { out<<"ServerMap: "; @@ -5254,20 +5288,15 @@ ClientMap::ClientMap( Map(dout_client), scene::ISceneNode(parent, mgr, id), m_client(client), - m_control(control) + m_control(control), + m_camera_position(0,0,0), + m_camera_direction(0,0,1) { - //mesh_mutex.Init(); - - /*m_box = core::aabbox3d(0,0,0, - map->getW()*BS, map->getH()*BS, map->getD()*BS);*/ - /*m_box = core::aabbox3d(0,0,0, - map->getSizeNodes().X * BS, - map->getSizeNodes().Y * BS, - map->getSizeNodes().Z * BS);*/ + m_camera_mutex.Init(); + assert(m_camera_mutex.IsInitialized()); + m_box = core::aabbox3d(-BS*1000000,-BS*1000000,-BS*1000000, BS*1000000,BS*1000000,BS*1000000); - - //setPosition(v3f(BS,BS,BS)); } ClientMap::~ClientMap() @@ -5355,7 +5384,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) */ int time1 = time(0); - u32 daynight_ratio = m_client->getDayNightRatio(); + //u32 daynight_ratio = m_client->getDayNightRatio(); m_camera_mutex.Lock(); v3f camera_position = m_camera_position; @@ -5458,7 +5487,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) continue; } - // This is ugly + // This is ugly (spherical distance limit?) /*if(m_control.range_all == false && d - 0.5*BS*MAP_BLOCKSIZE > range) continue;*/ @@ -5466,6 +5495,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) #if 1 /* Update expired mesh (used for day/night change) + + It doesn't work exactly like it should now with the + tasked mesh update but whatever. */ bool mesh_expired = false; @@ -5502,28 +5534,12 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) mesh_update_count++; // Mesh has been expired: generate new mesh - //block->updateMeshes(daynight_i); - block->updateMesh(daynight_ratio); + //block->updateMesh(daynight_ratio); + m_client->addUpdateMeshTask(block->getPos()); 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 /* Draw the faces of the block @@ -5667,6 +5683,114 @@ bool ClientMap::clearTempMod(v3s16 p, return changed; } +void ClientMap::expireMeshes(bool only_daynight_diffed) +{ + TimeTaker timer("expireMeshes()"); + + core::map::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 ClientMap::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); + //b->setMeshExpired(true); + } + catch(InvalidPositionException &e){} + // Leading edge + try{ + v3s16 p = blockpos + v3s16(-1,0,0); + MapBlock *b = getBlockNoCreate(p); + b->updateMesh(daynight_ratio); + //b->setMeshExpired(true); + } + catch(InvalidPositionException &e){} + try{ + v3s16 p = blockpos + v3s16(0,-1,0); + MapBlock *b = getBlockNoCreate(p); + b->updateMesh(daynight_ratio); + //b->setMeshExpired(true); + } + catch(InvalidPositionException &e){} + try{ + v3s16 p = blockpos + v3s16(0,0,-1); + MapBlock *b = getBlockNoCreate(p); + b->updateMesh(daynight_ratio); + //b->setMeshExpired(true); + } + catch(InvalidPositionException &e){} +} + +#if 0 +/* + Update mesh of block in which the node is, and if the node is at the + leading edge, update the appropriate leading blocks too. +*/ +void ClientMap::updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio) +{ + v3s16 dirs[4] = { + v3s16(0,0,0), + v3s16(-1,0,0), + v3s16(0,-1,0), + v3s16(0,0,-1), + }; + v3s16 blockposes[4]; + for(u32 i=0; i<4; i++) + { + v3s16 np = nodepos + dirs[i]; + blockposes[i] = getNodeBlockPos(np); + // Don't update mesh of block if it has been done already + bool already_updated = false; + for(u32 j=0; jupdateMesh(daynight_ratio); + } +} +#endif + void ClientMap::PrintInfo(std::ostream &out) { out<<"ClientMap: ";