]> git.lizzy.rs Git - minetest.git/blobdiff - src/server.cpp
Initial directory structure rework
[minetest.git] / src / server.cpp
index a0c8a00928011740af8f9e862f7c03b6d3556871..69f655e6acd7b244a2bc4a7cdd62dca0f8d96281 100644 (file)
@@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "main.h"
 #include "constants.h"
 #include "voxel.h"
-#include "materials.h"
 #include "config.h"
 #include "servercommand.h"
 #include "filesys.h"
@@ -48,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mods.h"
 #include "sha1.h"
 #include "base64.h"
+#include "tool.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -843,13 +843,17 @@ u32 PIChecksum(core::list<PlayerInfo> &l)
 */
 
 Server::Server(
-               std::string mapsavedir,
-               std::string configpath
+               std::string path_world,
+               std::string path_config,
+               std::string gamename
        ):
+       m_gamename(gamename),
+       m_path_world(path_world),
+       m_path_config(path_config),
        m_env(NULL),
        m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
-       m_authmanager(mapsavedir+DIR_DELIM+"auth.txt"),
-       m_banmanager(mapsavedir+DIR_DELIM+"ipban.txt"),
+       m_authmanager(path_world+DIR_DELIM+"auth.txt"),
+       m_banmanager(path_world+DIR_DELIM+"ipban.txt"),
        m_lua(NULL),
        m_itemdef(createItemDefManager()),
        m_nodedef(createNodeDefManager()),
@@ -859,12 +863,15 @@ Server::Server(
        m_time_counter(0),
        m_time_of_day_send_timer(0),
        m_uptime(0),
-       m_mapsavedir(mapsavedir),
-       m_configpath(configpath),
        m_shutdown_requested(false),
        m_ignore_map_edit_events(false),
        m_ignore_map_edit_events_peer_id(0)
 {
+       infostream<<"Server created."<<std::endl;
+       infostream<<"- path_world  = "<<path_world<<std::endl;
+       infostream<<"- path_config = "<<path_config<<std::endl;
+       infostream<<"- gamename    = "<<gamename<<std::endl;
+
        m_liquid_transform_timer = 0.0;
        m_print_info_timer = 0.0;
        m_objectdata_timer = 0.0;
@@ -876,27 +883,35 @@ Server::Server(
        m_step_dtime_mutex.Init();
        m_step_dtime = 0.0;
 
-       JMutexAutoLock envlock(m_env_mutex);
-       JMutexAutoLock conlock(m_con_mutex);
+       // Figure out some paths
+       m_path_share = porting::path_share + DIR_DELIM + "server";
+       m_path_game = m_path_share + DIR_DELIM + "games" + DIR_DELIM + m_gamename;
 
        // Path to builtin.lua
-       std::string builtinpath = porting::path_data + DIR_DELIM + "builtin.lua";
+       std::string builtinpath = m_path_share + DIR_DELIM + "builtin.lua";
 
        // Add default global mod search path
-       m_modspaths.push_front(porting::path_data + DIR_DELIM + "mods");
+       m_modspaths.push_front(m_path_game + DIR_DELIM "mods");
        // Add world mod search path
-       m_modspaths.push_front(mapsavedir + DIR_DELIM + "worldmods");
-       // Add user mod search path
-       m_modspaths.push_front(porting::path_userdata + DIR_DELIM + "usermods");
+       m_modspaths.push_front(m_path_world + DIR_DELIM + "worldmods");
+       // Add addon mod search path
+       for(std::set<std::string>::const_iterator i = m_path_addons.begin();
+                       i != m_path_addons.end(); i++){
+               m_modspaths.push_front((*i) + DIR_DELIM + "mods");
+       }
        
        // Print out mod search paths
-       infostream<<"Mod search paths:"<<std::endl;
+       infostream<<"- mod search paths:"<<std::endl;
        for(core::list<std::string>::Iterator i = m_modspaths.begin();
                        i != m_modspaths.end(); i++){
                std::string modspath = *i;
                infostream<<"    "<<modspath<<std::endl;
        }
        
+       // Lock environment
+       JMutexAutoLock envlock(m_env_mutex);
+       JMutexAutoLock conlock(m_con_mutex);
+
        // Initialize scripting
        
        infostream<<"Server: Initializing scripting"<<std::endl;
@@ -936,7 +951,7 @@ Server::Server(
 
        // Initialize Environment
        
-       m_env = new ServerEnvironment(new ServerMap(mapsavedir, this), m_lua,
+       m_env = new ServerEnvironment(new ServerMap(path_world, this), m_lua,
                        this, this);
 
        // Give environment reference to scripting api
@@ -946,15 +961,15 @@ Server::Server(
        m_env->getMap().addEventReceiver(this);
 
        // If file exists, load environment metadata
-       if(fs::PathExists(m_mapsavedir+DIR_DELIM+"env_meta.txt"))
+       if(fs::PathExists(m_path_world+DIR_DELIM+"env_meta.txt"))
        {
                infostream<<"Server: Loading environment metadata"<<std::endl;
-               m_env->loadMeta(m_mapsavedir);
+               m_env->loadMeta(m_path_world);
        }
 
        // Load players
        infostream<<"Server: Loading players"<<std::endl;
-       m_env->deSerializePlayers(m_mapsavedir);
+       m_env->deSerializePlayers(m_path_world);
 
        /*
                Add some test ActiveBlockModifiers to environment
@@ -1002,13 +1017,13 @@ Server::~Server()
                        Save players
                */
                infostream<<"Server: Saving players"<<std::endl;
-               m_env->serializePlayers(m_mapsavedir);
+               m_env->serializePlayers(m_path_world);
 
                /*
                        Save environment metadata
                */
                infostream<<"Server: Saving environment metadata"<<std::endl;
-               m_env->saveMeta(m_mapsavedir);
+               m_env->saveMeta(m_path_world);
        }
                
        /*
@@ -1065,7 +1080,7 @@ void Server::start(unsigned short port)
        m_thread.setRun(true);
        m_thread.Start();
        
-       infostream<<"Server: Started on port "<<port<<std::endl;
+       infostream<<"Server started on port "<<port<<"."<<std::endl;
 }
 
 void Server::stop()
@@ -1108,7 +1123,6 @@ void Server::AsyncRunStep()
        }
        
        {
-               ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
                // Send blocks to clients
                SendBlocks(dtime);
        }
@@ -1246,7 +1260,7 @@ void Server::AsyncRunStep()
                                explosion.
                        */
                        player->m_last_good_position_age += dtime;
-                       if(player->m_last_good_position_age >= 2.0){
+                       if(player->m_last_good_position_age >= 1.0){
                                float age = player->m_last_good_position_age;
                                v3f diff = (player->getPosition() - player->m_last_good_position);
                                float d_vert = diff.Y;
@@ -1270,7 +1284,8 @@ void Server::AsyncRunStep()
                        /*
                                Handle player HPs (die if hp=0)
                        */
-                       HandlePlayerHP(player, 0);
+                       if(player->hp == 0 && player->m_hp_not_sent)
+                               DiePlayer(player);
 
                        /*
                                Send player inventories and HPs if necessary
@@ -1284,9 +1299,9 @@ void Server::AsyncRunStep()
                        }
 
                        /*
-                               Add to environment if is not in respawn screen
+                               Add to environment
                        */
-                       if(!player->m_is_in_environment && !player->m_respawn_active){
+                       if(!player->m_is_in_environment){
                                player->m_removed = false;
                                player->setId(0);
                                m_env->addActiveObject(player);
@@ -1787,6 +1802,7 @@ void Server::AsyncRunStep()
                if(counter >= g_settings->getFloat("server_map_save_interval"))
                {
                        counter = 0.0;
+                       JMutexAutoLock lock(m_env_mutex);
 
                        ScopeProfiler sp(g_profiler, "Server: saving stuff");
 
@@ -1794,21 +1810,18 @@ void Server::AsyncRunStep()
                        if(m_authmanager.isModified())
                                m_authmanager.save();
 
-                       //Bann stuff
+                       //Ban stuff
                        if(m_banmanager.isModified())
                                m_banmanager.save();
                        
-                       // Map
-                       JMutexAutoLock lock(m_env_mutex);
-
                        // Save changed parts of map
                        m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
 
                        // Save players
-                       m_env->serializePlayers(m_mapsavedir);
+                       m_env->serializePlayers(m_path_world);
                        
                        // Save environment metadata
-                       m_env->saveMeta(m_mapsavedir);
+                       m_env->saveMeta(m_path_world);
                }
        }
 }
@@ -1861,6 +1874,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        JMutexAutoLock envlock(m_env_mutex);
        JMutexAutoLock conlock(m_con_mutex);
        
+       ScopeProfiler sp(g_profiler, "Server::ProcessData");
+       
        try{
                Address address = m_con.GetPeerAddress(peer_id);
 
@@ -2129,6 +2144,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                // Send HP
                SendPlayerHP(player);
                
+               // Show death screen if necessary
+               if(player->hp == 0)
+                       SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
+
                // Send time of day
                {
                        SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
@@ -2159,11 +2178,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER");
                }
 
-               /*
-                       Check HP, respawn if necessary
-               */
-               HandlePlayerHP(player, 0);
-
                /*
                        Print out action
                */
@@ -2662,16 +2676,25 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                std::istringstream is(datastring, std::ios_base::binary);
                u8 damage = readU8(is);
 
+               ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
+
                if(g_settings->getBool("enable_damage"))
                {
                        actionstream<<player->getName()<<" damaged by "
                                        <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
                                        <<std::endl;
-                               
-                       HandlePlayerHP(player, damage);
+
+                       srp->setHP(srp->getHP() - damage);
+
+                       if(srp->getHP() == 0 && srp->m_hp_not_sent)
+                               DiePlayer(srp);
+
+                       if(srp->m_hp_not_sent)
+                               SendPlayerHP(player);
                }
                else
                {
+                       // Force send (to correct the client's predicted HP)
                        SendPlayerHP(player);
                }
        }
@@ -2751,8 +2774,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                if(player->hp != 0)
                        return;
                
-               srp->m_respawn_active = false;
-
                RespawnPlayer(player);
                
                actionstream<<player->getName()<<" respawns at "
@@ -2811,6 +2832,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                infostream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="<<item_i<<", pointed="<<pointed.dump()<<std::endl;
 
+               if(player->hp == 0)
+               {
+                       infostream<<"TOSERVER_INTERACT: "<<srp->getName()
+                               <<" tried to interact, but is dead!"<<std::endl;
+                       return;
+               }
+
                v3f player_pos = srp->m_last_good_position;
 
                // Update wielded item
@@ -2858,7 +2886,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                if(action == 0 || action == 2 || action == 3)
                {
                        float d = player_pos.getDistanceFrom(pointed_pos_under);
-                       float max_d = BS * 10; // Just some large enough value
+                       float max_d = BS * 14; // Just some large enough value
                        if(d > max_d){
                                actionstream<<"Player "<<player->getName()
                                                <<" tried to access "<<pointed.dump()
@@ -2921,8 +2949,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                actionstream<<player->getName()<<" punches object "
                                        <<pointed.object_id<<std::endl;
 
-                               // Do stuff
-                               pointed_object->punch(srp, srp->m_time_from_last_punch);
+                               ItemStack punchitem = srp->getWieldedItem();
+                               ToolCapabilities toolcap =
+                                               punchitem.getToolCapabilities(m_itemdef);
+                               v3f dir = (pointed_object->getBasePosition() -
+                                               (srp->getPosition() + srp->getEyeOffset())
+                                                       ).normalize();
+                               pointed_object->punch(dir, &toolcap, srp,
+                                               srp->m_time_from_last_punch);
                                srp->m_time_from_last_punch = 0;
                        }
 
@@ -3647,7 +3681,7 @@ void Server::SendBlocks(float dtime)
        JMutexAutoLock envlock(m_env_mutex);
        JMutexAutoLock conlock(m_con_mutex);
 
-       //TimeTaker timer("Server::SendBlocks");
+       ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
 
        core::array<PrioritySortedBlockTransfer> queue;
 
@@ -3968,26 +4002,14 @@ void Server::SendTexturesRequested(u16 peer_id,core::list<TextureRequest> tosend
        Something random
 */
 
-void Server::HandlePlayerHP(Player *player, s16 damage)
+void Server::DiePlayer(Player *player)
 {
        ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
 
-       if(srp->m_respawn_active)
-               return;
-       
-       if(player->hp > damage)
-       {
-               if(damage != 0){
-                       player->hp -= damage;
-                       SendPlayerHP(player);
-               }
-               return;
-       }
-
-       infostream<<"Server::HandlePlayerHP(): Player "
+       infostream<<"Server::DiePlayer(): Player "
                        <<player->getName()<<" dies"<<std::endl;
        
-       player->hp = 0;
+       srp->setHP(0);
        
        // Trigger scripted stuff
        scriptapi_on_dieplayer(m_lua, srp);
@@ -3999,24 +4021,13 @@ void Server::HandlePlayerHP(Player *player, s16 damage)
        }
 
        SendPlayerHP(player);
-       
-       RemoteClient *client = getClient(player->peer_id);
-       if(client->net_proto_version >= 3)
-       {
-               SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
-               srp->m_removed = true;
-               srp->m_respawn_active = true;
-       }
-       else
-       {
-               RespawnPlayer(player);
-       }
+       SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
 }
 
 void Server::RespawnPlayer(Player *player)
 {
-       player->hp = 20;
        ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
+       srp->setHP(20);
        bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
        if(!repositioned){
                v3f pos = findSpawnPos(m_env->getServerMap());
@@ -4114,8 +4125,8 @@ void Server::setPlayerPassword(const std::string &name, const std::wstring &pass
 // Saves g_settings to configpath given at initialization
 void Server::saveConfig()
 {
-       if(m_configpath != "")
-               g_settings->updateConfigFile(m_configpath.c_str());
+       if(m_path_config != "")
+               g_settings->updateConfigFile(m_path_config.c_str());
 }
 
 void Server::notifyPlayer(const char *name, const std::wstring msg)
@@ -4268,6 +4279,14 @@ ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
                // Got one.
                player->peer_id = peer_id;
                
+               // Re-add player to environment
+               if(player->m_removed)
+               {
+                       player->m_removed = false;
+                       player->setId(0);
+                       m_env->addActiveObject(player);
+               }
+
                // Reset inventory to creative if in creative mode
                if(g_settings->getBool("creative_mode"))
                {
@@ -4305,12 +4324,13 @@ ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
                v3f pos = findSpawnPos(m_env->getServerMap());
 
                player = new ServerRemotePlayer(m_env, pos, peer_id, name);
+               ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
 
                /* Add player to environment */
                m_env->addPlayer(player);
+               m_env->addActiveObject(srp);
 
                /* Run scripts */
-               ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
                scriptapi_on_newplayer(m_lua, srp);
 
                /* Add stuff to inventory */
@@ -4500,13 +4520,14 @@ void dedicated_server_loop(Server &server, bool &kill)
 
        for(;;)
        {
+               float steplen = g_settings->getFloat("dedicated_server_step");
                // This is kind of a hack but can be done like this
                // because server.step() is very light
                {
                        ScopeProfiler sp(g_profiler, "dedicated server sleep");
-                       sleep_ms(30);
+                       sleep_ms((int)(steplen*1000.0));
                }
-               server.step(0.030);
+               server.step(steplen);
 
                if(server.getShutdownRequested() || kill)
                {
@@ -4521,7 +4542,7 @@ void dedicated_server_loop(Server &server, bool &kill)
                                g_settings->getFloat("profiler_print_interval");
                if(profiler_print_interval != 0)
                {
-                       if(m_profiler_interval.step(0.030, profiler_print_interval))
+                       if(m_profiler_interval.step(steplen, profiler_print_interval))
                        {
                                infostream<<"Profiler:"<<std::endl;
                                g_profiler->print(infostream);