From 24c4b7c68d283a4d1de72a3eb68f1268f1fe34e3 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 27 Nov 2010 17:18:34 +0200 Subject: Working version before block send priorization update --- src/client.cpp | 31 ++++++++++-- src/client.h | 2 + src/clientserver.h | 42 ++++++++-------- src/constants.h | 23 ++++----- src/debug.h | 57 +++++++++++++++++++++- src/main.cpp | 112 ++++++++++++++++++++++++------------------ src/main.h | 5 -- src/map.cpp | 20 +++++--- src/map.h | 23 +++++++-- src/mapblock.h | 5 ++ src/mapblockobject.h | 6 +++ src/server.cpp | 135 +++++++++++++++++++++++++-------------------------- src/server.h | 43 +++++++++++++++- src/utility.h | 10 ++++ 14 files changed, 335 insertions(+), 179 deletions(-) (limited to 'src') diff --git a/src/client.cpp b/src/client.cpp index ee3269974..a4f0ffb07 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -14,10 +14,6 @@ #define sleep_ms(x) usleep(x*1000) #endif -/* - FIXME: This thread can access the environment at any time -*/ - void * ClientUpdateThread::Thread() { ThreadStarted(); @@ -144,6 +140,22 @@ void Client::step(float dtime) m_con.RunTimeouts(dtime); } + /* + Packet counter + */ + { + static float counter = -0.001; + counter -= dtime; + if(counter <= 0.0) + { + counter = 10.0; + + dout_client<<"Client packetcounter:"< 0) { - dstream<getKey() + <<" count "<getValue() + < m_packets; +}; + + +#endif // DEBUG_HEADER + diff --git a/src/main.cpp b/src/main.cpp index 971e0eac3..258119c4a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,24 @@ /* -(c) 2010 Perttu Ahola +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. +*/ -Minetest +/* +=============================== NOTES ============================== NOTE: VBO cannot be turned on for fast-changing stuff because there is an apparanet memory leak in irrlicht when using it @@ -137,43 +154,39 @@ TODO: Make fetching sector's blocks more efficient when rendering TODO: Make the video backend selectable -TODO: A timestamp to blocks - -TODO: Client side: - - The server sends all active objects of the active blocks - at constant intervals. They should fit in a few packets. - - The client keeps track of what blocks at the moment are - having active objects in them. - - All blocks going in and out of the active buffer are recorded. - - For outgoing blocks, objects are removed from the blocks - and from the scene - - For incoming blocks, objects are added to the blocks and - to the scene. - -TODO: Server side: +Block object server side: - A "near blocks" buffer, in which some nearby blocks are stored. - For all blocks in the buffer, objects are stepped(). This means they are active. - - All blocks going in and out of the buffer are recorded. - - For outgoing blocks, a timestamp is written. - - For incoming blocks, the time difference is calculated and + - TODO All blocks going in and out of the buffer are recorded. + - TODO For outgoing blocks, a timestamp is written. + - TODO For incoming blocks, the time difference is calculated and objects are stepped according to it. +TODO: A timestamp to blocks TODO: Add config parameters for server's sending and generating distance -TODO: Make amount of trees and other plants configurable - - Save to a metafile - TODO: Copy the text of the last picked sign to inventory in creative mode TODO: Untie client network operations from framerate -TODO: Make a copy of close-range environment on client for showing +SUGG: Make a copy of close-range environment on client for showing on screen, with minimal mutexes to slow the main loop down -TODO: Make a PACKET_COMBINED which contains many subpackets. Utilize +SUGG: Make a PACKET_COMBINED which contains many subpackets. Utilize it by sending more stuff in a single packet. + - Add a packet queue to RemoteClient, from which packets will be + combined with object data packets + - This is not exactly trivial: the object data packets are + sometimes very big by themselves + +SUGG: Split MapBlockObject serialization to to-client and to-disk + - This will allow saving ages of rats on disk but not sending + them to clients + +TODO: Fix the long-lived Server Block Emerge Jam bug + - Is it related to the client deleting blocks? Doing now: ====================================================================== @@ -261,10 +274,6 @@ video::SMaterial g_materials[MATERIALS_COUNT]; // All range-related stuff below is locked behind this JMutex g_range_mutex; -// Blocks are generated in this range from the player -// This is limited vertically to half by Client::fetchBlocks() -s16 g_forcedfetch_range_nodes = FORCEDFETCH_RANGE; - // Blocks are viewed in this range from the player s16 g_viewing_range_nodes = 60; @@ -305,7 +314,10 @@ float g_client_delete_unused_sectors_timeout = 1200; // Server stuff bool g_creative_mode = false; -MapgenParams g_mapgen_params; +HMParams g_hm_params; +MapParams g_map_params; +float g_objectdata_interval = 0.2; +u16 g_active_object_range = 2; /* Random stuff @@ -395,21 +407,11 @@ bool parseConfigObject(std::istream &is) } else if(name == "viewing_range_nodes_max") { - s32 v = atoi(value.c_str()); - if(v < 0) - v = 0; - if(v > 32767) - v = 32767; - g_viewing_range_nodes_max = v; + g_viewing_range_nodes_max = stoi(value, 0, 32767); } else if(name == "viewing_range_nodes_min") { - s32 v = atoi(value.c_str()); - if(v < 0) - v = 0; - if(v > 32767) - v = 32767; - g_viewing_range_nodes_min = v; + g_viewing_range_nodes_min = stoi(value, 0, 32767); } else if(name=="screenW") g_screenW = value; @@ -439,19 +441,29 @@ bool parseConfigObject(std::istream &is) { s32 d = atoi(value.c_str()); if(d > 0 && (d & (d-1)) == 0) - g_mapgen_params.heightmap_blocksize = d; + g_hm_params.heightmap_blocksize = d; else dstream<<"Invalid value in config file: \"" <>g_map_params.plants_amount; + } + else if(name == "objectdata_inverval") + { + std::istringstream vis(value); + vis>>g_objectdata_interval; + } + else if(name == "active_object_range") + g_active_object_range = stoi(value, 0, 65535); else { @@ -1161,7 +1173,9 @@ int main(int argc, char *argv[]) std::cout<<"========================"< server; if(hosting){ - server = new Server("../map", g_creative_mode, g_mapgen_params); + server = new Server("../map", g_creative_mode, g_hm_params, + g_map_params, g_objectdata_interval, + g_active_object_range); server->start(port); } diff --git a/src/main.h b/src/main.h index 3118e5f52..59ef0ff03 100644 --- a/src/main.h +++ b/src/main.h @@ -12,7 +12,6 @@ extern std::string getTimestamp(); #include extern JMutex g_range_mutex; -extern s16 g_forcedfetch_range_nodes; extern s16 g_viewing_range_nodes; //extern s16 g_actual_viewing_range_nodes; extern bool g_viewing_range_all; @@ -42,9 +41,5 @@ extern video::SMaterial g_materials[MATERIALS_COUNT]; extern IrrlichtDevice *g_device; -// Settings -#include "map.h" -extern MapgenParams g_mapgen_params; - #endif diff --git a/src/map.cpp b/src/map.cpp index c69c3f248..35bf8bb40 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1160,7 +1160,7 @@ void Map::PrintInfo(std::ostream &out) ServerMap */ -ServerMap::ServerMap(std::string savedir, MapgenParams params): +ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): Map(dout_server), m_heightmap(NULL) { @@ -1212,15 +1212,19 @@ ServerMap::ServerMap(std::string savedir, MapgenParams params): } dstream< 0.03) tree_max = a / (t/0.03); @@ -1408,7 +1412,7 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) { // Pitness usually goes at around -0.5...0.5 u32 bush_max = 0; - u32 a = MAP_BLOCKSIZE * 3; + u32 a = MAP_BLOCKSIZE * 3.0 * m_params.plants_amount; if(pitness > 0) bush_max = (pitness*a*4); if(bush_max > a) diff --git a/src/map.h b/src/map.h index ca3b0086b..482ab2ac7 100644 --- a/src/map.h +++ b/src/map.h @@ -242,21 +242,32 @@ public: virtual void PrintInfo(std::ostream &out); }; -struct MapgenParams +// Master heightmap parameters +struct HMParams { - MapgenParams() + HMParams() { heightmap_blocksize = 64; height_randmax = "constant 70.0"; height_randfactor = "constant 0.6"; height_base = "linear 0 80 0"; - plants_amount = "1.0"; } s16 heightmap_blocksize; std::string height_randmax; std::string height_randfactor; std::string height_base; - std::string plants_amount; +}; + +// Map parameters +struct MapParams +{ + MapParams() + { + plants_amount = 1.0; + //max_objects_in_block = 30; + } + float plants_amount; + //u16 max_objects_in_block; }; class ServerMap : public Map @@ -265,7 +276,7 @@ public: /* savedir: directory to which map data should be saved */ - ServerMap(std::string savedir, MapgenParams params); + ServerMap(std::string savedir, HMParams hmp, MapParams mp); ~ServerMap(); s32 mapType() const @@ -346,6 +357,8 @@ public: private: UnlimitedHeightmap *m_heightmap; + MapParams m_params; + std::string m_savedir; bool m_map_saving_enabled; }; diff --git a/src/mapblock.h b/src/mapblock.h index 9fcfa0793..60f78b6ff 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -352,6 +352,11 @@ public: m_objects.getObjects(origin, max_d, dest); } + s32 getObjectCount() + { + return m_objects.getCount(); + } + private: /* diff --git a/src/mapblockobject.h b/src/mapblockobject.h index 1939cc896..15409bbd7 100644 --- a/src/mapblockobject.h +++ b/src/mapblockobject.h @@ -879,6 +879,12 @@ public: // origin is relative to block void getObjects(v3f origin, f32 max_d, core::array &dest); + + // Number of objects + s32 getCount() + { + return m_objects.size(); + } private: JMutex m_mutex; diff --git a/src/server.cpp b/src/server.cpp index a5f55ab5d..8969bdedd 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -284,56 +284,8 @@ void RemoteClient::SendBlocks(Server *server, float dtime) v3s16 center = getNodeBlockPos(center_nodepos); /* - Find out what block the player is going to next and set - center to it. - - Don't react to speeds under the initial value of highest_speed - */ - /*f32 highest_speed = 0.1 * BS; - v3s16 dir(0,0,0); - if(abs(playerspeed.X) > highest_speed) - { - highest_speed = playerspeed.X; - if(playerspeed.X > 0) - dir = v3s16(1,0,0); - else - dir = v3s16(-1,0,0); - } - if(abs(playerspeed.Y) > highest_speed) - { - highest_speed = playerspeed.Y; - if(playerspeed.Y > 0) - dir = v3s16(0,1,0); - else - dir = v3s16(0,-1,0); - } - if(abs(playerspeed.Z) > highest_speed) - { - highest_speed = playerspeed.Z; - if(playerspeed.Z > 0) - dir = v3s16(0,0,1); - else - dir = v3s16(0,0,-1); - } - - center += dir;*/ - - /* - Calculate the starting value of the block finder radius. - - The radius shall be the last used value minus the - maximum moved distance. + Get the starting value of the block finder radius. */ - /*s16 d_start = m_last_block_find_d; - if(max_moved >= d_start) - { - d_start = 0; - } - else - { - d_start -= max_moved; - }*/ - s16 last_nearest_unsent_d; s16 d_start; { @@ -382,10 +334,6 @@ void RemoteClient::SendBlocks(Server *server, float dtime) /* TODO: Get this from somewhere - TODO: Values more than 7 make placing and removing blocks very - sluggish when the map is being generated. This is - because d is looped every time from 0 to d_max if no - blocks are found for sending. */ //s16 d_max = 7; s16 d_max = 8; @@ -659,6 +607,10 @@ void RemoteClient::SendObjectData( in memory): - Set blocks changed - Add blocks to emerge queue if they are not found + + SUGGESTION: These could be ignored from the backside of the player + + TODO: Keep track of total size of packet and stop when it is too big */ Player *player = server->m_env.getPlayer(peer_id); @@ -669,9 +621,14 @@ void RemoteClient::SendObjectData( v3s16 center_nodepos = floatToInt(playerpos); v3s16 center = getNodeBlockPos(center_nodepos); - s16 d_max = ACTIVE_OBJECT_D_BLOCKS; + //s16 d_max = ACTIVE_OBJECT_D_BLOCKS; + s16 d_max = server->m_active_object_range; + + // Number of blocks whose objects were written to bos + u16 blockcount = 0; - core::map blocks; + //core::map blocks; + std::ostringstream bos(std::ios_base::binary); for(s16 d = 0; d <= d_max; d++) { @@ -691,13 +648,18 @@ void RemoteClient::SendObjectData( if(m_blocks_sent.find(p) == NULL) continue; } - + + // Try stepping block and add it to a send queue try { // Get block MapBlock *block = server->m_env.getMap().getBlockNoCreate(p); + // Skip block if there are no objects + if(block->getObjectCount() == 0) + continue; + // Step block if not in stepped_blocks and add to stepped_blocks if(stepped_blocks.find(p) == NULL) { @@ -705,9 +667,28 @@ void RemoteClient::SendObjectData( stepped_blocks.insert(p, true); block->setChangedFlag(); } - - // Add block to queue - blocks.insert(p, block); + + /* + Write objects + */ + + // Write blockpos + writeV3S16(buf, p); + bos.write((char*)buf, 6); + + // Write objects + block->serializeObjects(bos, serialization_version); + + blockcount++; + + /* + Stop collecting objects if data is already too big + */ + // Sum of player and object data sizes + s32 sum = (s32)os.tellp() + 2 + (s32)bos.tellp(); + // break out if data too big + if(sum > MAX_OBJECTDATA_SIZE) + d = d_max+1; } //try catch(InvalidPositionException &e) @@ -729,12 +710,11 @@ void RemoteClient::SendObjectData( } } +#if 0 /* Write objects */ - u16 blockcount = blocks.size(); - // Write block count writeU16(buf, blockcount); os.write((char*)buf, 2); @@ -751,11 +731,21 @@ void RemoteClient::SendObjectData( MapBlock *block = i.getNode()->getValue(); block->serializeObjects(os, serialization_version); } - +#endif + + // Write block count + writeU16(buf, blockcount); + os.write((char*)buf, 2); + + // Write block objects + os< data((u8*)s.c_str(), s.size()); @@ -898,13 +888,18 @@ u32 PIChecksum(core::list &l) Server::Server( std::string mapsavedir, bool creative_mode, - MapgenParams mapgen_params + HMParams hm_params, + MapParams map_params, + float objectdata_interval, + u16 active_object_range ): - m_env(new ServerMap(mapsavedir, mapgen_params), dout_server), + m_env(new ServerMap(mapsavedir, hm_params, map_params), dout_server), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_thread(this), m_emergethread(this), - m_creative_mode(creative_mode) + m_creative_mode(creative_mode), + m_objectdata_interval(objectdata_interval), + m_active_object_range(active_object_range) { m_env_mutex.Init(); m_con_mutex.Init(); @@ -980,6 +975,7 @@ void Server::step(float dtime) void Server::AsyncRunStep() { DSTACK(__FUNCTION_NAME); + float dtime; { JMutexAutoLock lock1(m_step_dtime_mutex); @@ -1033,7 +1029,7 @@ void Server::AsyncRunStep() // Run time- and client- related stuff // NOTE: If you intend to add something here, check that it - // doesn't fit in RemoteClient::SendBlocks for exampel. + // doesn't fit in RemoteClient::SendBlocks for example. /*{ // Clients are behind connection lock JMutexAutoLock lock(m_con_mutex); @@ -1055,8 +1051,7 @@ void Server::AsyncRunStep() { static float counter = 0.0; counter += dtime; - //TODO: Get value from somewhere - if(counter >= 0.1) + if(counter >= m_objectdata_interval) { JMutexAutoLock lock1(m_env_mutex); JMutexAutoLock lock2(m_con_mutex); @@ -1930,12 +1925,12 @@ void Server::peerAdded(con::Peer *peer) bool r = player->inventory.addItem(item); assert(r == true); } - // Rat + /*// Rat { InventoryItem *item = new MapBlockObjectItem("Rat"); bool r = player->inventory.addItem(item); assert(r == true); - } + }*/ } else { diff --git a/src/server.h b/src/server.h index 5c856333a..c178480d5 100644 --- a/src/server.h +++ b/src/server.h @@ -201,6 +201,28 @@ struct PlayerInfo u32 PIChecksum(core::list &l); +/* + Used for queueing and sorting block transfers in containers + + Lower priority number means higher priority. +*/ +struct PrioritySortedBlockTransfer +{ + PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_dest_peer) + { + priority = a_priority; + pos = a_pos; + dest_peer = a_dest_peer; + } + bool operator < (PrioritySortedBlockTransfer &other) + { + return priority < other.priority; + } + float priority; + v3s16 pos; + u16 a_dest_peer; +}; + class RemoteClient { public: @@ -252,6 +274,8 @@ public: void BlockEmerged(); // Increments timeouts and removes timed-out blocks from list + // NOTE: This doesn't fix the server-not-sending-block bug + // because it is related to emerging, not sending. //void RunSendingTimeouts(float dtime, float timeout); void PrintInfo(std::ostream &o) @@ -310,6 +334,15 @@ private: JMutex m_blocks_sending_mutex; }; +/*struct ServerSettings +{ + ServerSettings() + { + creative_mode = false; + } + bool creative_mode; +};*/ + class Server : public con::PeerHandler { public: @@ -319,7 +352,10 @@ public: Server( std::string mapsavedir, bool creative_mode, - MapgenParams mapgen_params + HMParams hm_params, + MapParams map_params, + float objectdata_inverval, + u16 active_object_range ); ~Server(); void start(unsigned short port); @@ -377,8 +413,11 @@ private: EmergeThread m_emergethread; BlockEmergeQueue m_emerge_queue; - + + // Settings bool m_creative_mode; + float m_objectdata_interval; + u16 m_active_object_range; friend class EmergeThread; friend class RemoteClient; diff --git a/src/utility.h b/src/utility.h index 4178e9d95..e6a09547b 100644 --- a/src/utility.h +++ b/src/utility.h @@ -603,5 +603,15 @@ inline bool is_yes(std::string s) return false; } +inline s32 stoi(std::string s, s32 min, s32 max) +{ + s32 i = atoi(s.c_str()); + if(i < min) + i = min; + if(i > max) + i = max; + return i; +} + #endif -- cgit v1.2.3