From a26c92d7dda327f2b1483fe7250cb27580a0a039 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 24 Dec 2010 17:08:50 +0200 Subject: disconnect method to connection to be used instead of just timing out --- src/server.cpp | 413 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 310 insertions(+), 103 deletions(-) (limited to 'src/server.cpp') diff --git a/src/server.cpp b/src/server.cpp index 35f1f8a27..c0af61b98 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -849,40 +849,6 @@ void RemoteClient::SetBlocksNotSent(core::map &blocks) } } -/*void RemoteClient::BlockEmerged() -{ - SharedPtr lock(m_num_blocks_in_emerge_queue.getLock()); - assert(m_num_blocks_in_emerge_queue.m_value > 0); - m_num_blocks_in_emerge_queue.m_value--; -}*/ - -/*void RemoteClient::RunSendingTimeouts(float dtime, float timeout) -{ - JMutexAutoLock sendinglock(m_blocks_sending_mutex); - - core::list remove_queue; - for(core::map::Iterator - i = m_blocks_sending.getIterator(); - i.atEnd()==false; i++) - { - v3s16 p = i.getNode()->getKey(); - float t = i.getNode()->getValue(); - t += dtime; - i.getNode()->setValue(t); - - if(t > timeout) - { - remove_queue.push_back(p); - } - } - for(core::list::Iterator - i = remove_queue.begin(); - i != remove_queue.end(); i++) - { - m_blocks_sending.remove(*i); - } -}*/ - /* PlayerInfo */ @@ -931,7 +897,8 @@ Server::Server( m_emergethread(this), m_time_of_day(8000), m_time_counter(0), - m_time_of_day_send_timer(0) + m_time_of_day_send_timer(0), + m_uptime(0) { m_flowwater_timer = 0.0; m_print_info_timer = 0.0; @@ -1026,10 +993,20 @@ void Server::AsyncRunStep() if(dtime < 0.001) return; + //dstream<<"Server steps "<::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + // Get client and check that it is valid + RemoteClient *client = i.getNode()->getValue(); + assert(client->peer_id == i.getNode()->getKey()); + if(client->serialization_version == SER_FMT_VER_INVALID) + continue; + // Get name of player + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(client->peer_id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + // Add name to information string + os<id); - JMutexAutoLock(client->m_dig_mutex); - client->m_dig_tool_item = 0; - client->m_dig_position = p_under; - float dig_time = 0.5; - if(content == CONTENT_STONE) - { - dig_time = 1.5; - } - else if(content == CONTENT_TORCH) - { - dig_time = 0.0; - } - client->m_dig_time_remaining = dig_time; - - // Reset build time counter - getClient(peer->id)->m_time_from_building.set(0.0); -#endif } // action == 0 /* @@ -2240,7 +2212,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) InventoryList *clist = player->inventory.getList("craft"); if(clist) { - clist->decrementMaterials(ma->count); + u16 count = ma->count; + if(count == 0) + count = 1; + clist->decrementMaterials(count); } // Do action // Feed action to player inventory @@ -2424,8 +2399,15 @@ void Server::peerAdded(con::Peer *peer) dout_server<<"Server::peerAdded(): peer->id=" <id<id; + c.timeout = false; + m_peer_change_queue.push_back(c); + +#if 0 + // NOTE: Connection is already locked when this is called. + // NOTE: Environment is already locked when this is called. // Error check core::map::Node *n; @@ -2440,9 +2422,6 @@ void Server::peerAdded(con::Peer *peer) // Create player { - // Already locked when called - //JMutexAutoLock envlock(m_env_mutex); - Player *player = m_env.getPlayer(peer->id); // The player shouldn't already exist @@ -2491,8 +2470,8 @@ void Server::peerAdded(con::Peer *peer) // Give a good pick { InventoryItem *item = new ToolItem("STPick", 32000); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } // Give all materials assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); @@ -2508,8 +2487,8 @@ void Server::peerAdded(con::Peer *peer) // Sign { InventoryItem *item = new MapBlockObjectItem("Sign Example text"); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } /*// Rat { @@ -2520,15 +2499,20 @@ void Server::peerAdded(con::Peer *peer) } else { + { + InventoryItem *item = new CraftItem("Stick", 4); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } { InventoryItem *item = new ToolItem("WPick", 32000); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } { InventoryItem *item = new ToolItem("STPick", 32000); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } /*// Give some lights { @@ -2551,6 +2535,7 @@ void Server::peerAdded(con::Peer *peer) }*/ } } +#endif } void Server::deletingPeer(con::Peer *peer, bool timeout) @@ -2559,8 +2544,18 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) dout_server<<"Server::deletingPeer(): peer->id=" <id<<", timeout="<id; + c.timeout = timeout; + m_peer_change_queue.push_back(c); + +#if 0 + // NOTE: Connection is already locked when this is called. + + // NOTE: Environment is already locked when this is called. + // NOTE: Locking environment cannot be moved here because connection + // is already locked and env has to be locked before // Error check core::map::Node *n; @@ -2568,10 +2563,22 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) // The client should exist assert(n != NULL); + // Send information about leaving in chat + { + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(peer->id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + + std::wstring message; + message += L"*** "; + message += name; + message += L" left game"; + BroadcastChatMessage(message); + } + // Delete player { - // Already locked when called - //JMutexAutoLock envlock(m_env_mutex); m_env.removePlayer(peer->id); } @@ -2581,6 +2588,7 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) // Send player info to all clients SendPlayerInfos(); +#endif } void Server::SendObjectData(float dtime) @@ -2848,6 +2856,205 @@ void Server::UpdateBlockWaterPressure(MapBlock *block, v.blitBack(modified_blocks); } + +void Server::handlePeerChange(PeerChange &c) +{ + JMutexAutoLock envlock(m_env_mutex); + JMutexAutoLock conlock(m_con_mutex); + if(c.type == PEER_ADDED) + { + /* + Add + */ + + // Error check + core::map::Node *n; + n = m_clients.find(c.peer_id); + // The client shouldn't already exist + assert(n == NULL); + + // Create client + RemoteClient *client = new RemoteClient(); + client->peer_id = c.peer_id; + m_clients.insert(client->peer_id, client); + + // Create player + { + Player *player = m_env.getPlayer(c.peer_id); + + // The player shouldn't already exist + assert(player == NULL); + + player = new ServerRemotePlayer(); + player->peer_id = c.peer_id; + + /* + Set player position + */ + + // We're going to throw the player to this position + //v2s16 nodepos(29990,29990); + //v2s16 nodepos(9990,9990); + v2s16 nodepos(0,0); + v2s16 sectorpos = getNodeSectorPos(nodepos); + // Get zero sector (it could have been unloaded to disk) + m_env.getMap().emergeSector(sectorpos); + // Get ground height at origin + f32 groundheight = m_env.getMap().getGroundHeight(nodepos, true); + // The sector should have been generated -> groundheight exists + assert(groundheight > GROUNDHEIGHT_VALID_MINVALUE); + // Don't go underwater + if(groundheight < WATER_LEVEL) + groundheight = WATER_LEVEL; + + player->setPosition(intToFloat(v3s16( + nodepos.X, + groundheight + 1, + nodepos.Y + ))); + + /* + Add player to environment + */ + + m_env.addPlayer(player); + + /* + Add stuff to inventory + */ + + if(g_settings.getBool("creative_mode")) + { + // Give a good pick + { + InventoryItem *item = new ToolItem("STPick", 32000); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + // Give all materials + assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); + for(u16 i=0; iinventory.addItem("main", item); + } + // Sign + { + InventoryItem *item = new MapBlockObjectItem("Sign Example text"); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + /*// Rat + { + InventoryItem *item = new MapBlockObjectItem("Rat"); + bool r = player->inventory.addItem("main", item); + assert(r == true); + }*/ + } + else + { + { + InventoryItem *item = new CraftItem("Stick", 4); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("WPick", 32000); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("STPick", 32000); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + /*// Give some lights + { + InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999); + bool r = player->inventory.addItem("main", item); + assert(r == true); + } + // and some signs + for(u16 i=0; i<4; i++) + { + InventoryItem *item = new MapBlockObjectItem("Sign Example text"); + bool r = player->inventory.addItem("main", item); + assert(r == true); + }*/ + /*// Give some other stuff + { + InventoryItem *item = new MaterialItem(CONTENT_TREE, 999); + bool r = player->inventory.addItem("main", item); + assert(r == true); + }*/ + } + } + + } // PEER_ADDED + else if(c.type == PEER_REMOVED) + { + /* + Delete + */ + + // Error check + core::map::Node *n; + n = m_clients.find(c.peer_id); + // The client should exist + assert(n != NULL); + + // Collect information about leaving in chat + std::wstring message; + { + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(c.peer_id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + + message += L"*** "; + message += name; + message += L" left game"; + } + + // Delete player + { + m_env.removePlayer(c.peer_id); + } + + // Delete client + delete m_clients[c.peer_id]; + m_clients.remove(c.peer_id); + + // Send player info to all remaining clients + SendPlayerInfos(); + + // Send leave chat message to all remaining clients + BroadcastChatMessage(message); + + } // PEER_REMOVED + else + { + assert(0); + } +} + +void Server::handlePeerChanges() +{ + while(m_peer_change_queue.size() > 0) + { + PeerChange c = m_peer_change_queue.pop_front(); + + dout_server<<"Server: Handling peer change: " + <<"id="<