Update inventory texture too
[oweals/minetest.git] / src / server.cpp
index 75fb7cd72f87f33de51f16e1d07e940162e3b7cc..44c66447c3eda6a35bde5f5e283759ca59bbe10d 100644 (file)
@@ -43,7 +43,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "scriptapi.h"
 #include "nodedef.h"
 #include "tooldef.h"
-#include "content_tool.h" // For content_tool_init
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -945,6 +944,35 @@ u32 PIChecksum(core::list<PlayerInfo> &l)
        return checksum;
 }
 
+struct ModSpec
+{
+       std::string name;
+       std::string path;
+
+       ModSpec(const std::string &name_="", const std::string path_=""):
+               name(name_),
+               path(path_)
+       {}
+};
+
+static core::list<ModSpec> getMods(core::list<std::string> &modspaths)
+{
+       core::list<ModSpec> mods;
+       for(core::list<std::string>::Iterator i = modspaths.begin();
+                       i != modspaths.end(); i++){
+               std::string modspath = *i;
+               std::vector<fs::DirListNode> dirlist = fs::GetDirListing(modspath);
+               for(u32 j=0; j<dirlist.size(); j++){
+                       if(!dirlist[j].dir)
+                               continue;
+                       std::string modname = dirlist[j].name;
+                       std::string modpath = modspath + DIR_DELIM + modname;
+                       mods.push_back(ModSpec(modname, modpath));
+               }
+       }
+       return mods;
+}
+
 /*
        Server
 */
@@ -987,11 +1015,11 @@ Server::Server(
 
        infostream<<"m_nodemgr="<<m_nodemgr<<std::endl;
        
-       // Initialize default tool definitions
-       content_tool_init(m_toolmgr);
-
        // Initialize default node definitions
        content_mapnode_init(NULL, m_nodemgr);
+       
+       // Add default global mod path
+       m_modspaths.push_back(porting::path_data + DIR_DELIM + "mods");
 
        // Initialize scripting
        
@@ -1001,13 +1029,18 @@ Server::Server(
        // Export API
        scriptapi_export(m_lua, this);
        // Load and run scripts
-       std::string defaultscript = porting::path_data + DIR_DELIM
-                       + "scripts" + DIR_DELIM + "default.lua";
-       bool success = script_load(m_lua, defaultscript.c_str());
-       if(!success){
-               errorstream<<"Server: Failed to load and run "
-                               <<defaultscript<<std::endl;
-               assert(0);
+       core::list<ModSpec> mods = getMods(m_modspaths);
+       for(core::list<ModSpec>::Iterator i = mods.begin();
+                       i != mods.end(); i++){
+               ModSpec mod = *i;
+               infostream<<"Server: Loading mod \""<<mod.name<<"\""<<std::endl;
+               std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
+               bool success = script_load(m_lua, scriptpath.c_str());
+               if(!success){
+                       errorstream<<"Server: Failed to load and run "
+                                       <<scriptpath<<std::endl;
+                       assert(0);
+               }
        }
        
        // Initialize Environment
@@ -2105,6 +2138,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                /*
                        Send some initialization data
                */
+
+               // Send textures
+               SendTextures(peer_id);
+               
+               // Send tool definitions
+               SendToolDef(m_con, peer_id, m_toolmgr);
                
                // Send player info to all players
                SendPlayerInfos();
@@ -3594,6 +3633,29 @@ void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
        con.Send(peer_id, 0, data, true);
 }
 
+void Server::SendToolDef(con::Connection &con, u16 peer_id,
+               IToolDefManager *tooldef)
+{
+       DSTACK(__FUNCTION_NAME);
+       std::ostringstream os(std::ios_base::binary);
+
+       /*
+               u16 command
+               u32 length of the next item
+               serialized ToolDefManager
+       */
+       writeU16(os, TOCLIENT_TOOLDEF);
+       std::ostringstream tmp_os(std::ios::binary);
+       tooldef->serialize(tmp_os);
+       os<<serializeLongString(tmp_os.str());
+
+       // 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);
+}
+
 /*
        Non-static send methods
 */
@@ -4044,6 +4106,105 @@ void Server::SendBlocks(float dtime)
        }
 }
 
+struct SendableTexture
+{
+       std::string name;
+       std::string path;
+       std::string data;
+
+       SendableTexture(const std::string &name_="", const std::string path_="",
+                       const std::string &data_=""):
+               name(name_),
+               path(path_),
+               data(data_)
+       {}
+};
+
+void Server::SendTextures(u16 peer_id)
+{
+       DSTACK(__FUNCTION_NAME);
+
+       infostream<<"Server::SendTextures(): Sending textures to client"<<std::endl;
+       
+       /* Read textures */
+       
+       core::list<SendableTexture> textures;
+       core::list<ModSpec> mods = getMods(m_modspaths);
+       for(core::list<ModSpec>::Iterator i = mods.begin();
+                       i != mods.end(); i++){
+               ModSpec mod = *i;
+               std::string texturepath = mod.path + DIR_DELIM + "textures";
+               std::vector<fs::DirListNode> dirlist = fs::GetDirListing(texturepath);
+               for(u32 j=0; j<dirlist.size(); j++){
+                       if(dirlist[j].dir) // Ignode dirs
+                               continue;
+                       std::string tname = dirlist[j].name;
+                       std::string tpath = texturepath + DIR_DELIM + tname;
+                       // Read data
+                       std::ifstream fis(tpath.c_str(), std::ios_base::binary);
+                       if(fis.good() == false){
+                               errorstream<<"Server::SendTextures(): Could not open \""
+                                               <<tname<<"\" for reading"<<std::endl;
+                               continue;
+                       }
+                       std::ostringstream tmp_os(std::ios_base::binary);
+                       bool bad = false;
+                       for(;;){
+                               char buf[1024];
+                               fis.read(buf, 1024);
+                               std::streamsize len = fis.gcount();
+                               tmp_os.write(buf, len);
+                               if(fis.eof())
+                                       break;
+                               if(!fis.good()){
+                                       bad = true;
+                                       break;
+                               }
+                       }
+                       if(bad){
+                               errorstream<<"Server::SendTextures(): Failed to read \""
+                                               <<tname<<"\""<<std::endl;
+                               continue;
+                       }
+                       errorstream<<"Server::SendTextures(): Loaded \""
+                                       <<tname<<"\""<<std::endl;
+                       // Put in list
+                       textures.push_back(SendableTexture(tname, tpath, tmp_os.str()));
+               }
+       }
+
+       /* Create and send packet */
+
+       /*
+               u16 command
+               u32 number of textures
+               for each texture {
+                       u16 length of name
+                       string name
+                       u32 length of data
+                       data
+               }
+       */
+       std::ostringstream os(std::ios_base::binary);
+
+       writeU16(os, TOCLIENT_TEXTURES);
+       writeU32(os, textures.size());
+       
+       for(core::list<SendableTexture>::Iterator i = textures.begin();
+                       i != textures.end(); i++){
+               os<<serializeString(i->name);
+               os<<serializeLongString(i->data);
+       }
+       
+       // Make data buffer
+       std::string s = os.str();
+       infostream<<"Server::SendTextures(): number of textures: "
+                       <<textures.size()<<", data size: "<<s.size()<<std::endl;
+       SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+       // Send as reliable
+       m_con.Send(peer_id, 0, data, true);
+}
+
 /*
        Something random
 */
@@ -4214,6 +4375,15 @@ ITextureSource* Server::getTextureSource()
        return NULL;
 }
 
+IWritableToolDefManager* Server::getWritableToolDefManager()
+{
+       return m_toolmgr;
+}
+IWritableNodeDefManager* Server::getWritableNodeDefManager()
+{
+       return m_nodemgr;
+}
+
 v3f findSpawnPos(ServerMap &map)
 {
        //return v3f(50,50,50)*BS;