Common mods support
authorPerttu Ahola <celeron55@gmail.com>
Thu, 21 Mar 2013 16:48:21 +0000 (18:48 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Thu, 21 Mar 2013 16:56:42 +0000 (18:56 +0200)
Implement "common mods", includeable from
  {$user,$share}/games/common/$modname
by using the game.conf setting
  common_mods = $modname,$modname2,...

src/mods.cpp
src/server.cpp
src/subgame.cpp
src/subgame.h

index ac2d9b17d666218a6e0c97aaa7275245f01802e4..6a7ab79aade2870804b74119d46f5bb381d3b64c 100644 (file)
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "log.h"
 #include "subgame.h"
 #include "settings.h"
+#include "strfnd.h"
 
 std::map<std::string, ModSpec> getModsInPath(std::string path)
 {
@@ -188,11 +189,58 @@ void ModConfiguration::addMods(std::vector<ModSpec> new_mods)
        }
 }
 
+// If failed, returned modspec has name==""
+static ModSpec findCommonMod(const std::string &modname)
+{
+       // Try to find in {$user,$share}/games/common/$modname
+       std::vector<std::string> find_paths;
+       find_paths.push_back(porting::path_user + DIR_DELIM + "games" +
+                       DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname);
+       find_paths.push_back(porting::path_share + DIR_DELIM + "games" +
+                       DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname);
+       for(u32 i=0; i<find_paths.size(); i++){
+               const std::string &try_path = find_paths[i];
+               if(fs::PathExists(try_path))
+                       return ModSpec(modname, try_path);
+       }
+       // Failed to find mod
+       return ModSpec();
+}
+
 ModConfiguration::ModConfiguration(std::string worldpath)
 {
+       SubgameSpec gamespec = findWorldSubgame(worldpath);
+
+       // Add common mods without dependency handling
+       std::vector<std::string> inexistent_common_mods;
+       Settings gameconf;
+       if(getGameConfig(gamespec.path, gameconf)){
+               if(gameconf.exists("common_mods")){
+                       Strfnd f(gameconf.get("common_mods"));
+                       while(!f.atend()){
+                               std::string modname = trim(f.next(","));
+                               if(modname.empty())
+                                       continue;
+                               ModSpec spec = findCommonMod(modname);
+                               if(spec.name.empty())
+                                       inexistent_common_mods.push_back(modname);
+                               else
+                                       m_sorted_mods.push_back(spec);
+                       }
+               }
+       }
+       if(!inexistent_common_mods.empty()){
+               std::string s = "Required common mods ";
+               for(u32 i=0; i<inexistent_common_mods.size(); i++){
+                       if(i != 0) s += ", ";
+                       s += std::string("\"") + inexistent_common_mods[i] + "\"";
+               }
+               s += " could not be found.";
+               throw ModError(s);
+       }
+
        // Add all world mods and all game mods
        addModsInPath(worldpath + DIR_DELIM + "worldmods");
-       SubgameSpec gamespec = findWorldSubgame(worldpath);
        addModsInPath(gamespec.gamemods_path);
 
        // check world.mt file for mods explicitely declared to be
@@ -217,6 +265,6 @@ ModConfiguration::ModConfiguration(std::string worldpath)
        }
 
        for(std::set<std::string>::const_iterator i = gamespec.addon_mods_paths.begin();
-               i != gamespec.addon_mods_paths.end(); ++i)
+                       i != gamespec.addon_mods_paths.end(); ++i)
                addModsInPathFiltered((*i),exclude_mod_names);
 }
index d699dc9d2ab633c0baf0792ee9f5eba21718a947..2dcab63b8c2e1c6f225c4140af259e4af1ca8fde 100644 (file)
@@ -736,10 +736,10 @@ Server::Server(
        }
        // complain about mods declared to be loaded, but not found
        for(std::vector<ModSpec>::iterator it = m_mods.begin();
-               it != m_mods.end(); ++it)
+                       it != m_mods.end(); ++it)
                load_mod_names.erase((*it).name);
        for(std::list<ModSpec>::iterator it = unsatisfied_mods.begin();
-               it != unsatisfied_mods.end(); ++it)
+                       it != unsatisfied_mods.end(); ++it)
                load_mod_names.erase((*it).name);
        if(!load_mod_names.empty())
        {               
index 3c8bf53c53989338d0aea89126e62281d44610a3..8678ae37fd03fe3fa1ab3364ed7adceeb631bd66 100644 (file)
@@ -24,12 +24,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "log.h"
 #include "util/string.h"
 
-std::string getGameName(const std::string &game_path)
+bool getGameConfig(const std::string &game_path, Settings &conf)
 {
        std::string conf_path = game_path + DIR_DELIM + "game.conf";
+       return conf.readConfigFile(conf_path.c_str());
+}
+
+std::string getGameName(const std::string &game_path)
+{
        Settings conf;
-       bool succeeded = conf.readConfigFile(conf_path.c_str());
-       if(!succeeded)
+       if(!getGameConfig(game_path, conf))
                return "";
        if(!conf.exists("name"))
                return "";
@@ -117,6 +121,11 @@ std::set<std::string> getAvailableGameIds()
                for(u32 j=0; j<dirlist.size(); j++){
                        if(!dirlist[j].dir)
                                continue;
+                       // If configuration file is not found or broken, ignore game
+                       Settings conf;
+                       if(!getGameConfig(*i + DIR_DELIM + dirlist[j].name, conf))
+                               continue;
+                       // Add it to result
                        const char *ends[] = {"_game", NULL};
                        std::string shorter = removeStringEnd(dirlist[j].name, ends);
                        if(shorter != "")
index 8561c1a52ce322effffba0130557baf266257169..996714be04accb6bb3c9ce285ec9990a7e8947a4 100644 (file)
@@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <set>
 #include <vector>
 
+class Settings;
+
 #define WORLDNAME_BLACKLISTED_CHARS "/\\"
 
 struct SubgameSpec
@@ -52,6 +54,8 @@ struct SubgameSpec
        }
 };
 
+bool getGameConfig(const std::string &game_path, Settings &conf);
+
 std::string getGameName(const std::string &game_path);
 
 SubgameSpec findSubgame(const std::string &id);