Common mods support
Implement "common mods", includeable from {$user,$share}/games/common/$modname by using the game.conf setting common_mods = $modname,$modname2,...master
parent
9b5bb5c755
commit
306d1ab866
52
src/mods.cpp
52
src/mods.cpp
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "subgame.h"
|
#include "subgame.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "strfnd.h"
|
||||||
|
|
||||||
std::map<std::string, ModSpec> getModsInPath(std::string path)
|
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)
|
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
|
// Add all world mods and all game mods
|
||||||
addModsInPath(worldpath + DIR_DELIM + "worldmods");
|
addModsInPath(worldpath + DIR_DELIM + "worldmods");
|
||||||
SubgameSpec gamespec = findWorldSubgame(worldpath);
|
|
||||||
addModsInPath(gamespec.gamemods_path);
|
addModsInPath(gamespec.gamemods_path);
|
||||||
|
|
||||||
// check world.mt file for mods explicitely declared to be
|
// 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();
|
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);
|
addModsInPathFiltered((*i),exclude_mod_names);
|
||||||
}
|
}
|
||||||
|
|
|
@ -736,10 +736,10 @@ Server::Server(
|
||||||
}
|
}
|
||||||
// complain about mods declared to be loaded, but not found
|
// complain about mods declared to be loaded, but not found
|
||||||
for(std::vector<ModSpec>::iterator it = m_mods.begin();
|
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);
|
load_mod_names.erase((*it).name);
|
||||||
for(std::list<ModSpec>::iterator it = unsatisfied_mods.begin();
|
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);
|
load_mod_names.erase((*it).name);
|
||||||
if(!load_mod_names.empty())
|
if(!load_mod_names.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,12 +24,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util/string.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";
|
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;
|
Settings conf;
|
||||||
bool succeeded = conf.readConfigFile(conf_path.c_str());
|
if(!getGameConfig(game_path, conf))
|
||||||
if(!succeeded)
|
|
||||||
return "";
|
return "";
|
||||||
if(!conf.exists("name"))
|
if(!conf.exists("name"))
|
||||||
return "";
|
return "";
|
||||||
|
@ -117,6 +121,11 @@ std::set<std::string> getAvailableGameIds()
|
||||||
for(u32 j=0; j<dirlist.size(); j++){
|
for(u32 j=0; j<dirlist.size(); j++){
|
||||||
if(!dirlist[j].dir)
|
if(!dirlist[j].dir)
|
||||||
continue;
|
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};
|
const char *ends[] = {"_game", NULL};
|
||||||
std::string shorter = removeStringEnd(dirlist[j].name, ends);
|
std::string shorter = removeStringEnd(dirlist[j].name, ends);
|
||||||
if(shorter != "")
|
if(shorter != "")
|
||||||
|
|
|
@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class Settings;
|
||||||
|
|
||||||
#define WORLDNAME_BLACKLISTED_CHARS "/\\"
|
#define WORLDNAME_BLACKLISTED_CHARS "/\\"
|
||||||
|
|
||||||
struct SubgameSpec
|
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);
|
std::string getGameName(const std::string &game_path);
|
||||||
|
|
||||||
SubgameSpec findSubgame(const std::string &id);
|
SubgameSpec findSubgame(const std::string &id);
|
||||||
|
|
Loading…
Reference in New Issue