diff options
-rw-r--r-- | src/defaultsettings.cpp | 4 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/map.cpp | 14 | ||||
-rw-r--r-- | src/map.h | 35 | ||||
-rw-r--r-- | src/mapchunk.h | 7 | ||||
-rw-r--r-- | src/server.cpp | 168 | ||||
-rw-r--r-- | src/server.h | 6 |
7 files changed, 175 insertions, 62 deletions
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index fc63856ba..1ba8c1194 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -62,8 +62,8 @@ void set_default_settings() g_settings.setDefault("max_simultaneous_block_sends_per_client", "1"); //g_settings.setDefault("max_simultaneous_block_sends_per_client", "2"); g_settings.setDefault("max_simultaneous_block_sends_server_total", "4"); - g_settings.setDefault("max_block_send_distance", "7"); - g_settings.setDefault("max_block_generate_distance", "7"); + g_settings.setDefault("max_block_send_distance", "8"); + g_settings.setDefault("max_block_generate_distance", "8"); g_settings.setDefault("time_send_interval", "20"); g_settings.setDefault("time_speed", "96"); g_settings.setDefault("server_unload_unused_sectors_timeout", "60"); diff --git a/src/main.cpp b/src/main.cpp index 51a407827..1f178ab6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -219,6 +219,9 @@ SUGG: MovingObject::move and Player::move are basically the same. - NOTE: Player::move is more up-to-date.
- NOTE: There is a simple move implementation now in collision.{h,cpp}
+SUGG: Server-side objects could be moved based on nodes to enable very
+ lightweight operation and simple AI
+
Map:
----
diff --git a/src/map.cpp b/src/map.cpp index 9610b0b53..a5e230419 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1792,7 +1792,8 @@ void Map::nodeMetadataStep(float dtime, ServerMap::ServerMap(std::string savedir): Map(dout_server), - m_seed(0) + m_seed(0), + m_map_metadata_changed(true) { dstream<<__FUNCTION_NAME<<std::endl; @@ -4797,12 +4798,17 @@ void ServerMap::save(bool only_changed) dstream<<DTIME<<"ServerMap: Saving whole map, this can take time." <<std::endl; - saveMapMeta(); + if(only_changed == false || m_map_metadata_changed) + { + saveMapMeta(); + m_map_metadata_changed = false; + } - // Disable saving chunk metadata file if chunks are disabled + // Disable saving chunk metadata if chunks are disabled if(m_chunksize != 0) { - saveChunkMeta(); + if(only_changed == false || anyChunkModified()) + saveChunkMeta(); } u32 sector_meta_count = 0; @@ -401,6 +401,35 @@ public: } return true; } + + /* + Returns true if any chunk is marked as modified + */ + bool anyChunkModified() + { + for(core::map<v2s16, MapChunk*>::Iterator + i = m_chunks.getIterator(); + i.atEnd()==false; i++) + { + v2s16 p = i.getNode()->getKey(); + MapChunk *chunk = i.getNode()->getValue(); + if(chunk->isModified()) + return true; + } + return false; + } + + void setChunksNonModified() + { + for(core::map<v2s16, MapChunk*>::Iterator + i = m_chunks.getIterator(); + i.atEnd()==false; i++) + { + v2s16 p = i.getNode()->getKey(); + MapChunk *chunk = i.getNode()->getValue(); + chunk->setModified(false); + } + } /* Chunks are generated by using these and makeChunk(). @@ -573,6 +602,12 @@ private: s16 m_chunksize; // Chunks core::map<v2s16, MapChunk*> m_chunks; + + /* + Metadata is re-written on disk only if this is true. + This is reset to false when written on disk. + */ + bool m_map_metadata_changed; }; /* diff --git a/src/mapchunk.h b/src/mapchunk.h index 1819fa13e..9860abad0 100644 --- a/src/mapchunk.h +++ b/src/mapchunk.h @@ -36,7 +36,8 @@ class MapChunk { public: MapChunk(): - m_generation_level(GENERATED_NOT) + m_generation_level(GENERATED_NOT), + m_modified(true) { } @@ -58,8 +59,12 @@ public: is.read((char*)&m_generation_level, 1); } + bool isModified(){ return m_modified; } + void setModified(bool modified){ m_modified = modified; } + private: u8 m_generation_level; + bool m_modified; }; #endif diff --git a/src/server.cpp b/src/server.cpp index 9c02389e2..c9c115abb 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -306,8 +306,15 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, { DSTACK(__FUNCTION_NAME); + /*u32 timer_result; + TimeTaker timer("RemoteClient::GetNextBlocks", &timer_result);*/ + // Increment timers m_nearest_unsent_reset_timer += dtime; + m_nothing_to_send_pause_timer -= dtime; + + if(m_nothing_to_send_pause_timer >= 0) + return; // Won't send anything if already sending if(m_blocks_sending.size() >= g_settings.getU16 @@ -338,8 +345,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, /* Get the starting value of the block finder radius. */ - s16 last_nearest_unsent_d; - s16 d_start; if(m_last_center != center) { @@ -356,14 +361,14 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, //dstream<<"Resetting m_nearest_unsent_d"<<std::endl; } - last_nearest_unsent_d = m_nearest_unsent_d; - - d_start = m_nearest_unsent_d; + //s16 last_nearest_unsent_d = m_nearest_unsent_d; + s16 d_start = m_nearest_unsent_d; - u16 maximum_simultaneous_block_sends_setting = g_settings.getU16 + //dstream<<"d_start="<<d_start<<std::endl; + + u16 max_simul_sends_setting = g_settings.getU16 ("max_simultaneous_block_sends_per_client"); - u16 maximum_simultaneous_block_sends = - maximum_simultaneous_block_sends_setting; + u16 max_simul_sends_usually = max_simul_sends_setting; /* Check the time from last addNode/removeNode. @@ -374,10 +379,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, if(m_time_from_building < g_settings.getFloat( "full_block_send_enable_min_time_from_building")) { - maximum_simultaneous_block_sends + max_simul_sends_usually = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS; } + /* + Number of blocks sending + number of blocks selected for sending + */ u32 num_blocks_selected = m_blocks_sending.size(); /* @@ -394,6 +402,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, //dstream<<"Starting from "<<d_start<<std::endl; + bool sending_something = false; + for(s16 d = d_start; d <= d_max; d++) { //dstream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl; @@ -404,11 +414,11 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, update our d to it. Else update m_nearest_unsent_d */ - if(m_nearest_unsent_d != last_nearest_unsent_d) + /*if(m_nearest_unsent_d != last_nearest_unsent_d) { d = m_nearest_unsent_d; last_nearest_unsent_d = m_nearest_unsent_d; - } + }*/ /* Get the border/face dot coordinates of a "d-radiused" @@ -430,25 +440,18 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, Also, don't send blocks that are already flying. */ - u16 maximum_simultaneous_block_sends_now = - maximum_simultaneous_block_sends; + // Start with the usual maximum + u16 max_simul_dynamic = max_simul_sends_usually; + // If block is very close, allow full maximum if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D) - { - maximum_simultaneous_block_sends_now = - maximum_simultaneous_block_sends_setting; - } + max_simul_dynamic = max_simul_sends_setting; - // Limit is dynamically lowered when building - if(num_blocks_selected - >= maximum_simultaneous_block_sends_now) - { - /*dstream<<"Not sending more blocks. Queue full. " - <<m_blocks_sending.size() - <<std::endl;*/ + // Don't select too many blocks for sending + if(num_blocks_selected >= max_simul_dynamic) goto queue_full; - } - + + // Don't send blocks that are currently being transferred if(m_blocks_sending.find(p) != NULL) continue; @@ -476,37 +479,35 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, continue; } -#if 0 +#if 1 /* 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. + near ground level. */ - if(d > 4) + if(d >= 4) { - v2s16 p2d(p.X, p.Z); - MapSector *sector = NULL; - try - { - sector = server->m_env.getMap().getSectorNoGenerate(p2d); - } - catch(InvalidPositionException &e) - { - } - - if(sector != NULL) - { - // Get center ground height in nodes - f32 gh = sector->getGroundHeight( - v2s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2)); - // Block center y in nodes - f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2); - // If differs a lot, don't generate - if(fabs(gh - y) > MAP_BLOCKSIZE*2) - generate = false; - } + #if 1 + // Block center y in nodes + f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2); + // Don't generate if it's very high or very low + if(y < -64 || y > 64) + generate = false; + #endif + #if 0 + v2s16 p2d_nodes_center( + MAP_BLOCKSIZE*p.X, + MAP_BLOCKSIZE*p.Z); + + // Get ground height in nodes + s16 gh = server->m_env.getServerMap().findGroundLevel( + p2d_nodes_center); + + // If differs a lot, don't generate + if(fabs(gh - y) > MAP_BLOCKSIZE*2) + generate = false; + // Actually, don't even send it + //continue; + #endif } #endif @@ -556,6 +557,20 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, v2s16 chunkpos = map->sector_to_chunk(p2d); if(map->chunkNonVolatile(chunkpos) == false) block_is_invalid = true; +#if 1 + /* + If block is not close, don't send it unless it is near + ground level. + + Block is not near ground level if night-time mesh + doesn't differ from day-time mesh. + */ + if(d >= 3) + { + if(block->dayNightDiffed() == false) + continue; + } +#endif } /* @@ -574,7 +589,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, */ if(new_nearest_unsent_d == -1 || d < new_nearest_unsent_d) { - new_nearest_unsent_d = d; + if(generate == true) + new_nearest_unsent_d = d; } /* @@ -612,6 +628,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, dest.push_back(q); num_blocks_selected += 1; + sending_something = true; } } queue_full: @@ -620,6 +637,24 @@ queue_full: { m_nearest_unsent_d = new_nearest_unsent_d; } + + if(sending_something == false) + { + m_nothing_to_send_counter++; + if(m_nothing_to_send_counter >= 3) + { + // Pause time in seconds + m_nothing_to_send_pause_timer = 2.0; + } + } + else + { + m_nothing_to_send_counter = 0; + } + + /*timer_result = timer.stop(true); + if(timer_result != 0) + dstream<<"GetNextBlocks duration: "<<timer_result<<" (!=0)"<<std::endl;*/ } void RemoteClient::SendObjectData( @@ -3402,6 +3437,30 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver) { DSTACK(__FUNCTION_NAME); + + v3s16 p = block->getPos(); + +#if 0 + // Analyze it a bit + bool completely_air = true; + for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++) + for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++) + for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++) + { + if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR) + { + completely_air = false; + x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out + } + } + + // Print result + dstream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "; + if(completely_air) + dstream<<"[completely air] "; + dstream<<std::endl; +#endif + /* Create a packet with the block in the right format */ @@ -3413,7 +3472,6 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver) u32 replysize = 8 + blockdata.getSize(); SharedBuffer<u8> reply(replysize); - v3s16 p = block->getPos(); writeU16(&reply[0], TOCLIENT_BLOCKDATA); writeS16(&reply[2], p.X); writeS16(&reply[4], p.Y); diff --git a/src/server.h b/src/server.h index cba5fc2ce..e9477ba53 100644 --- a/src/server.h +++ b/src/server.h @@ -250,6 +250,8 @@ public: pending_serialization_version = SER_FMT_VER_INVALID; m_nearest_unsent_d = 0; m_nearest_unsent_reset_timer = 0.0; + m_nothing_to_send_counter = 0; + m_nothing_to_send_pause_timer = 0; } ~RemoteClient() { @@ -350,6 +352,10 @@ private: This is resetted by PrintInfo() */ u32 m_excess_gotblocks; + + // CPU usage optimization + u32 m_nothing_to_send_counter; + float m_nothing_to_send_pause_timer; }; class Server : public con::PeerHandler, public MapEventReceiver, |