]> git.lizzy.rs Git - minetest.git/blobdiff - src/server.cpp
added dedicated server build without irrlicht
[minetest.git] / src / server.cpp
index 487ce2a98656ab518737bbdf22ecc2a0c72266eb..a2dfc8269790cbbd8b43aba9114453a73a2bd937 100644 (file)
@@ -285,6 +285,12 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 {
        DSTACK(__FUNCTION_NAME);
        
+       // Increment timers
+       {
+               JMutexAutoLock lock(m_blocks_sent_mutex);
+               m_nearest_unsent_reset_timer += dtime;
+       }
+
        // Won't send anything if already sending
        {
                JMutexAutoLock lock(m_blocks_sending_mutex);
@@ -320,12 +326,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                        m_last_center = center;
                }
 
-               static float reset_counter = 0;
-               reset_counter += dtime;
-               if(reset_counter > 5.0)
+               /*dstream<<"m_nearest_unsent_reset_timer="
+                               <<m_nearest_unsent_reset_timer<<std::endl;*/
+               if(m_nearest_unsent_reset_timer > 5.0)
                {
-                       reset_counter = 0;
+                       m_nearest_unsent_reset_timer = 0;
                        m_nearest_unsent_d = 0;
+                       //dstream<<"Resetting m_nearest_unsent_d"<<std::endl;
                }
 
                last_nearest_unsent_d = m_nearest_unsent_d;
@@ -353,6 +360,21 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
                }
        }
+       
+       u32 num_blocks_selected;
+       {
+               JMutexAutoLock lock(m_blocks_sending_mutex);
+               num_blocks_selected = m_blocks_sending.size();
+       }
+       
+       /*
+               next time d will be continued from the d from which the nearest
+               unsent block was found this time.
+
+               This is because not necessarily any of the blocks found this
+               time are actually sent.
+       */
+       s32 new_nearest_unsent_d = -1;
 
        // Serialization version used
        //u8 ser_version = serialization_version;
@@ -380,12 +402,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                        if(m_nearest_unsent_d != last_nearest_unsent_d)
                        {
                                d = m_nearest_unsent_d;
+                               last_nearest_unsent_d = m_nearest_unsent_d;
                        }
-                       else
-                       {
-                               m_nearest_unsent_d = d;
-                       }
-                       last_nearest_unsent_d = m_nearest_unsent_d;
                }
 
                /*
@@ -421,13 +439,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                JMutexAutoLock lock(m_blocks_sending_mutex);
                                
                                // Limit is dynamically lowered when building
-                               if(m_blocks_sending.size()
+                               if(num_blocks_selected
                                                >= maximum_simultaneous_block_sends_now)
                                {
                                        /*dstream<<"Not sending more blocks. Queue full. "
                                                        <<m_blocks_sending.size()
                                                        <<std::endl;*/
-                                       return;
+                                       goto queue_full;
                                }
 
                                if(m_blocks_sending.find(p) != NULL)
@@ -460,7 +478,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                if(m_blocks_sent.find(p) != NULL)
                                        continue;
                        }
-                                       
+
                        /*
                                Check if map has this block
                        */
@@ -498,6 +516,15 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                continue;
                        }
 
+                       /*
+                               Record the lowest d from which a a block has been
+                               found being not sent and possibly to exist
+                       */
+                       if(new_nearest_unsent_d == -1 || d < new_nearest_unsent_d)
+                       {
+                               new_nearest_unsent_d = d;
+                       }
+                                       
                        /*
                                Add inexistent block to emerge queue.
                        */
@@ -531,10 +558,17 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                        PrioritySortedBlockTransfer q((float)d, p, peer_id);
 
                        dest.push_back(q);
+
+                       num_blocks_selected += 1;
                }
        }
+queue_full:
 
-       // Don't add anything here. The loop breaks by returning.
+       if(new_nearest_unsent_d != -1)
+       {
+               JMutexAutoLock lock(m_blocks_sent_mutex);
+               m_nearest_unsent_d = new_nearest_unsent_d;
+       }
 }
 
 void RemoteClient::SendObjectData(
@@ -894,6 +928,12 @@ Server::Server(
        m_thread(this),
        m_emergethread(this)
 {
+       m_flowwater_timer = 0.0;
+       m_print_info_timer = 0.0;
+       m_objectdata_timer = 0.0;
+       m_emergethread_trigger_timer = 0.0;
+       m_savemap_timer = 0.0;
+       
        m_env_mutex.Init();
        m_con_mutex.Init();
        m_step_dtime_mutex.Init();
@@ -983,7 +1023,7 @@ void Server::AsyncRunStep()
        
        {
                JMutexAutoLock lock1(m_step_dtime_mutex);
-               m_step_dtime = 0.0;
+               m_step_dtime -= dtime;
        }
 
        //dstream<<"Server steps "<<dtime<<std::endl;
@@ -1018,7 +1058,7 @@ void Server::AsyncRunStep()
                else
                        interval = 0.25;
 
-               static float counter = 0.0;
+               float &counter = m_flowwater_timer;
                counter += dtime;
                if(counter >= 0.25 && m_flow_active_nodes.size() > 0)
                {
@@ -1082,7 +1122,7 @@ void Server::AsyncRunStep()
        
        // Periodically print some info
        {
-               static float counter = 0.0;
+               float &counter = m_print_info_timer;
                counter += dtime;
                if(counter >= 30.0)
                {
@@ -1101,26 +1141,114 @@ 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::GetNextBlocks for example.
-       /*{
-               // Clients are behind connection lock
-               JMutexAutoLock lock(m_con_mutex);
+       /*
+               Update digging
+
+               NOTE: Some of this could be moved to RemoteClient
+       */
+
+       {
+               JMutexAutoLock envlock(m_env_mutex);
+               JMutexAutoLock conlock(m_con_mutex);
 
                for(core::map<u16, RemoteClient*>::Iterator
                        i = m_clients.getIterator();
                        i.atEnd() == false; i++)
                {
                        RemoteClient *client = i.getNode()->getValue();
-                       //con::Peer *peer = m_con.GetPeer(client->peer_id);
-                       //client->RunSendingTimeouts(dtime, peer->resend_timeout);
+                       Player *player = m_env.getPlayer(client->peer_id);
+
+                       JMutexAutoLock digmutex(client->m_dig_mutex);
+
+                       if(client->m_dig_tool_item == -1)
+                               continue;
+
+                       client->m_dig_time_remaining -= dtime;
+
+                       if(client->m_dig_time_remaining > 0)
+                               continue;
+
+                       v3s16 p_under = client->m_dig_position;
+                       
+                       // Mandatory parameter; actually used for nothing
+                       core::map<v3s16, MapBlock*> modified_blocks;
+
+                       u8 material;
+
+                       try
+                       {
+                               // Get material at position
+                               material = m_env.getMap().getNode(p_under).d;
+                               // If it's not diggable, do nothing
+                               if(content_diggable(material) == false)
+                               {
+                                       derr_server<<"Server: Not finishing digging: Node not diggable"
+                                                       <<std::endl;
+                                       client->m_dig_tool_item = -1;
+                                       break;
+                               }
+                       }
+                       catch(InvalidPositionException &e)
+                       {
+                               derr_server<<"Server: Not finishing digging: Node not found"
+                                               <<std::endl;
+                               client->m_dig_tool_item = -1;
+                               break;
+                       }
+                       
+                       // Create packet
+                       u32 replysize = 8;
+                       SharedBuffer<u8> reply(replysize);
+                       writeU16(&reply[0], TOCLIENT_REMOVENODE);
+                       writeS16(&reply[2], p_under.X);
+                       writeS16(&reply[4], p_under.Y);
+                       writeS16(&reply[6], p_under.Z);
+                       // Send as reliable
+                       m_con.SendToAll(0, reply, true);
+                       
+                       if(g_settings.getBool("creative_mode") == false)
+                       {
+                               // Add to inventory and send inventory
+                               InventoryItem *item = new MaterialItem(material, 1);
+                               player->inventory.addItem(item);
+                               SendInventory(player->peer_id);
+                       }
+
+                       /*
+                               Remove the node
+                               (this takes some time so it is done after the quick stuff)
+                       */
+                       m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks);
+                       
+                       /*
+                               Update water
+                       */
+                       
+                       // Update water pressure around modification
+                       // This also adds it to m_flow_active_nodes if appropriate
+
+                       MapVoxelManipulator v(&m_env.getMap());
+                       v.m_disable_water_climb =
+                                       g_settings.getBool("disable_water_climb");
+                       
+                       VoxelArea area(p_under-v3s16(1,1,1), p_under+v3s16(1,1,1));
+
+                       try
+                       {
+                               v.updateAreaWaterPressure(area, m_flow_active_nodes);
+                       }
+                       catch(ProcessingLimitException &e)
+                       {
+                               dstream<<"Processing limit reached (1)"<<std::endl;
+                       }
+                       
+                       v.blitBack(modified_blocks);
                }
-       }*/
+       }
 
        // Send object positions
        {
-               static float counter = 0.0;
+               float &counter = m_objectdata_timer;
                counter += dtime;
                if(counter >= g_settings.getFloat("objectdata_interval"))
                {
@@ -1135,7 +1263,7 @@ void Server::AsyncRunStep()
        // Trigger emergethread (it gets somehow gets to a
        // non-triggered but bysy state sometimes)
        {
-               static float counter = 0.0;
+               float &counter = m_emergethread_trigger_timer;
                counter += dtime;
                if(counter >= 2.0)
                {
@@ -1147,7 +1275,7 @@ void Server::AsyncRunStep()
 
        // Save map
        {
-               static float counter = 0.0;
+               float &counter = m_savemap_timer;
                counter += dtime;
                if(counter >= SERVER_MAP_SAVE_INTERVAL)
                {
@@ -1466,19 +1594,23 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        block->removeObject(id);
                }
        }
-       else if(command == TOSERVER_CLICK_GROUND)
+       else if(command == TOSERVER_GROUND_ACTION)
        {
                if(datasize < 17)
                        return;
                /*
                        length: 17
                        [0] u16 command
-                       [2] u8 button (0=left, 1=right)
+                       [2] u8 action
                        [3] v3s16 nodepos_undersurface
                        [9] v3s16 nodepos_abovesurface
                        [15] u16 item
+                       actions:
+                       0: start digging
+                       1: place block
+                       2: stop digging (all parameters ignored)
                */
-               u8 button = readU8(&data[2]);
+               u8 action = readU8(&data[2]);
                v3s16 p_under;
                p_under.X = readS16(&data[3]);
                p_under.Y = readS16(&data[5]);
@@ -1492,91 +1624,67 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                //TODO: Check that target is reasonably close
                
                /*
-                       Left button digs ground
+                       0: start digging
                */
-               if(button == 0)
+               if(action == 0)
                {
 
-                       core::map<v3s16, MapBlock*> modified_blocks;
-
-                       u8 material;
+                       u8 content;
 
                        try
                        {
-                               // Get material at position
-                               material = m_env.getMap().getNode(p_under).d;
+                               // Get content at position
+                               content = m_env.getMap().getNode(p_under).d;
                                // If it's not diggable, do nothing
-                               if(content_diggable(material) == false)
+                               if(content_diggable(content) == false)
                                {
                                        return;
                                }
                        }
                        catch(InvalidPositionException &e)
                        {
-                               derr_server<<"Server: Ignoring REMOVENODE: Node not found"
+                               derr_server<<"Server: Not starting digging: Node not found"
                                                <<std::endl;
                                return;
                        }
                        
-                       // Reset build time counter
-                       getClient(peer->id)->m_time_from_building.set(0.0);
-                       
-                       // Create packet
-                       u32 replysize = 8;
-                       SharedBuffer<u8> reply(replysize);
-                       writeU16(&reply[0], TOCLIENT_REMOVENODE);
-                       writeS16(&reply[2], p_under.X);
-                       writeS16(&reply[4], p_under.Y);
-                       writeS16(&reply[6], p_under.Z);
-                       // Send as reliable
-                       m_con.SendToAll(0, reply, true);
-                       
-                       if(g_settings.getBool("creative_mode") == false)
-                       {
-                               // Add to inventory and send inventory
-                               InventoryItem *item = new MaterialItem(material, 1);
-                               player->inventory.addItem(item);
-                               SendInventory(player->peer_id);
-                       }
-
                        /*
-                               Remove the node
-                               (this takes some time so it is done after the quick stuff)
+                               Set stuff in RemoteClient
                        */
-                       m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks);
-                       
-                       /*
-                               Update water
-                       */
-                       
-                       // Update water pressure around modification
-                       // This also adds it to m_flow_active_nodes if appropriate
-
-                       MapVoxelManipulator v(&m_env.getMap());
-                       v.m_disable_water_climb =
-                                       g_settings.getBool("disable_water_climb");
-                       
-                       VoxelArea area(p_under-v3s16(1,1,1), p_under+v3s16(1,1,1));
-
-                       try
+                       RemoteClient *client = getClient(peer->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)
                        {
-                               v.updateAreaWaterPressure(area, m_flow_active_nodes);
+                               dig_time = 1.5;
                        }
-                       catch(ProcessingLimitException &e)
+                       else if(content == CONTENT_TORCH)
                        {
-                               dstream<<"Processing limit reached (1)"<<std::endl;
+                               dig_time = 0.0;
                        }
+                       client->m_dig_time_remaining = dig_time;
                        
-                       v.blitBack(modified_blocks);
+                       // Reset build time counter
+                       getClient(peer->id)->m_time_from_building.set(0.0);
                        
-                       // Add the node to m_flow_active_nodes.
-                       //m_flow_active_nodes[p_under] = 1;
+               } // action == 0
+
+               /*
+                       2: stop digging
+               */
+               else if(action == 2)
+               {
+                       RemoteClient *client = getClient(peer->id);
+                       JMutexAutoLock digmutex(client->m_dig_mutex);
+                       client->m_dig_tool_item = -1;
+               }
 
-               } // button == 0
                /*
-                       Right button places blocks and stuff
+                       1: place block
                */
-               else if(button == 1)
+               else if(action == 1)
                {
 
                        // Get item
@@ -1772,16 +1880,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                }
                        }
 
-               } // button == 1
+               } // action == 1
                /*
-                       Catch invalid buttons
+                       Catch invalid actions
                */
                else
                {
-                       derr_server<<"WARNING: Server: Invalid button "
-                                       <<button<<std::endl;
+                       derr_server<<"WARNING: Server: Invalid action "
+                                       <<action<<std::endl;
                }
        }
+#if 0
        else if(command == TOSERVER_RELEASE)
        {
                if(datasize < 3)
@@ -1791,8 +1900,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        [0] u16 command
                        [2] u8 button
                */
-               //TODO
+               dstream<<"TOSERVER_RELEASE ignored"<<std::endl;
        }
+#endif
        else if(command == TOSERVER_SIGNTEXT)
        {
                /*
@@ -1972,27 +2082,32 @@ void Server::peerAdded(con::Peer *peer)
                // The player shouldn't already exist
                assert(player == NULL);
 
-               player = new RemotePlayer();
+               player = new ServerRemotePlayer();
                player->peer_id = 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(v2s16(0,0));
+               m_env.getMap().emergeSector(sectorpos);
                // Get ground height at origin
-               f32 groundheight = m_env.getMap().getGroundHeight(v2s16(0,0), true);
-               // The zero sector should have been generated
+               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(
-                               0,
+                               nodepos.X,
                                groundheight + 1,
-                               0
+                               nodepos.Y
                )));
 
                /*