Add set_breath and get_breath to lua API.
[oweals/minetest.git] / src / server.cpp
index 12695e1b4fc4469a95a784707b72280c5ba86782..3bba193da5365c903a4d297d9ee9afba6a669369 100644 (file)
@@ -639,7 +639,8 @@ Server::Server(
        m_simple_singleplayer_mode(simple_singleplayer_mode),
        m_async_fatal_error(""),
        m_env(NULL),
-       m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
+       m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
+             g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"), this),
        m_banmanager(path_world+DIR_DELIM+"ipban.txt"),
        m_rollback(NULL),
        m_rollback_sink_enabled(true),
@@ -806,7 +807,12 @@ Server::Server(
        ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
        m_env = new ServerEnvironment(servermap, m_script, this, this);
        
-       m_emerge->initMapgens(servermap->getMapgenParams());
+       // Run some callbacks after the MG params have been set up but before activation
+       MapgenParams *mgparams = servermap->getMapgenParams();
+       m_script->environment_OnMapgenInit(mgparams);
+       
+       // Initialize mapgens
+       m_emerge->initMapgens(mgparams);
 
        // Give environment reference to scripting api
        m_script->initializeEnvironment(m_env);
@@ -1133,6 +1139,13 @@ void Server::AsyncRunStep()
                                        SendPlayerHP(client->peer_id);
                        }
 
+                       /*
+                               Send player breath if changed
+                       */
+                       if(playersao->m_breath_not_sent){
+                               SendPlayerBreath(client->peer_id);
+                       }
+
                        /*
                                Send player inventories if necessary
                        */
@@ -1231,7 +1244,7 @@ void Server::AsyncRunStep()
                float &counter = m_masterserver_timer;
                if((!counter || counter >= 300.0) && g_settings->getBool("server_announce") == true)
                {
-                       ServerList::sendAnnounce(!counter ? "start" : "update", m_clients_number, m_uptime.get(), m_gamespec.id);
+                       ServerList::sendAnnounce(!counter ? "start" : "update", m_clients_number, m_uptime.get(), m_gamespec.id, m_mods);
                        counter = 0.01;
                }
                counter += dtime;
@@ -1916,6 +1929,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        return;
                }
 
+               if(!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0)
+               {
+                       actionstream<<"Server: Player with an invalid name "
+                                       <<"tried to connect from "<<addr_s<<std::endl;
+                       SendAccessDenied(m_con, peer_id,
+                                       L"Name is not allowed");
+                       return;
+               }
+
                infostream<<"Server: New connection: \""<<playername<<"\" from "
                                <<m_con.GetPeerAddress(peer_id).serializeString()<<std::endl;
 
@@ -2090,6 +2112,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                if(g_settings->getBool("enable_damage"))
                        SendPlayerHP(peer_id);
 
+               // Send Breath
+               SendPlayerBreath(peer_id);
+
                // Send detached inventories
                sendDetachedInventories(peer_id);
 
@@ -2153,7 +2178,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                os<<player->getName()<<" ";
                        }
 
-                       actionstream<<player->getName()<<" joins game. List of players: "
+                       actionstream<<player->getName()<<" ["<<addr_s<<"] "<<" joins game. List of players: "
                                        <<os.str()<<std::endl;
                }
 
@@ -2401,6 +2426,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                        setInventoryModified(da->from_inv);
 
+                       /*
+                               Disable dropping items out of craftpreview
+                       */
+                       if(da->from_list == "craftpreview")
+                       {
+                               infostream<<"Ignoring IDropAction from "
+                                               <<(da->from_inv.dump())<<":"<<da->from_list
+                                               <<" because src is "<<da->from_list<<std::endl;
+                               delete a;
+                               return;
+                       }
+
                        // Disallow dropping items if not allowed to interact
                        if(!checkPriv(player->getName(), "interact"))
                        {
@@ -2556,6 +2593,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                SendPlayerHP(peer_id);
                }
        }
+       else if(command == TOSERVER_BREATH)
+       {
+               std::string datastring((char*)&data[2], datasize-2);
+               std::istringstream is(datastring, std::ios_base::binary);
+               u16 breath = readU16(is);
+               playersao->setBreath(breath);
+       }
        else if(command == TOSERVER_PASSWORD)
        {
                /*
@@ -3299,6 +3343,21 @@ void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
        con.Send(peer_id, 0, data, true);
 }
 
+void Server::SendBreath(con::Connection &con, u16 peer_id, u16 breath)
+{
+       DSTACK(__FUNCTION_NAME);
+       std::ostringstream os(std::ios_base::binary);
+
+       writeU16(os, TOCLIENT_BREATH);
+       writeU16(os, breath);
+
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+       // Send as reliable
+       con.Send(peer_id, 0, data, true);
+}
+
 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
                const std::wstring &reason)
 {
@@ -3687,6 +3746,22 @@ void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
        m_con.Send(peer_id, 0, data, true);
 }
 
+void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
+{
+       std::ostringstream os(std::ios_base::binary);
+
+       // Write command
+       writeU16(os, TOCLIENT_HUD_SET_PARAM);
+       writeU16(os, param);
+       os<<serializeString(value);
+
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
+       // Send as reliable
+       m_con.Send(peer_id, 0, data, true);
+}
+
 void Server::BroadcastChatMessage(const std::wstring &message)
 {
        for(std::map<u16, RemoteClient*>::iterator
@@ -3712,6 +3787,15 @@ void Server::SendPlayerHP(u16 peer_id)
        SendHP(m_con, peer_id, playersao->getHP());
 }
 
+void Server::SendPlayerBreath(u16 peer_id)
+{
+       DSTACK(__FUNCTION_NAME);
+       PlayerSAO *playersao = getPlayerSAO(peer_id);
+       assert(playersao);
+       playersao->m_breath_not_sent = false;
+       SendBreath(m_con, peer_id, playersao->getBreath());
+}
+
 void Server::SendMovePlayer(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
@@ -4684,6 +4768,18 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
        return true;
 }
 
+bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
+       if (!player)
+               return false;
+       if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
+               return false;
+
+       std::ostringstream os(std::ios::binary);
+       writeS32(os, hotbar_itemcount);
+       SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
+       return true;
+}
+
 void Server::notifyPlayers(const std::wstring msg)
 {
        BroadcastChatMessage(msg);