diff options
Diffstat (limited to 'src/content/mods.cpp')
-rw-r--r-- | src/content/mods.cpp | 146 |
1 files changed, 60 insertions, 86 deletions
diff --git a/src/content/mods.cpp b/src/content/mods.cpp index 95ab0290a..455506967 100644 --- a/src/content/mods.cpp +++ b/src/content/mods.cpp @@ -22,12 +22,37 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <json/json.h> #include <algorithm> #include "content/mods.h" +#include "database/database.h" #include "filesys.h" #include "log.h" #include "content/subgames.h" #include "settings.h" #include "porting.h" #include "convert_json.h" +#include "script/common/c_internal.h" + +void ModSpec::checkAndLog() const +{ + if (!string_allowed(name, MODNAME_ALLOWED_CHARS)) { + throw ModError("Error loading mod \"" + name + + "\": Mod name does not follow naming conventions: " + "Only characters [a-z0-9_] are allowed."); + } + + // Log deprecation messages + auto handling_mode = get_deprecated_handling_mode(); + if (!deprecation_msgs.empty() && handling_mode != DeprecatedHandlingMode::Ignore) { + std::ostringstream os; + os << "Mod " << name << " at " << path << ":" << std::endl; + for (auto msg : deprecation_msgs) + os << "\t" << msg << std::endl; + + if (handling_mode == DeprecatedHandlingMode::Error) + throw ModError(os.str()); + else + warningstream << os.str(); + } +} bool parseDependsString(std::string &dep, std::unordered_set<char> &symbols) { @@ -47,17 +72,6 @@ bool parseDependsString(std::string &dep, std::unordered_set<char> &symbols) void parseModContents(ModSpec &spec) { // NOTE: this function works in mutual recursion with getModsInPath - Settings info; - info.readConfigFile((spec.path + DIR_DELIM + "mod.conf").c_str()); - - if (info.exists("name")) - spec.name = info.get("name"); - - if (info.exists("author")) - spec.author = info.get("author"); - - if (info.exists("release")) - spec.release = info.getS32("release"); spec.depends.clear(); spec.optdepends.clear(); @@ -78,6 +92,20 @@ void parseModContents(ModSpec &spec) spec.modpack_content = getModsInPath(spec.path, true); } else { + Settings info; + info.readConfigFile((spec.path + DIR_DELIM + "mod.conf").c_str()); + + if (info.exists("name")) + spec.name = info.get("name"); + else + spec.deprecation_msgs.push_back("Mods not having a mod.conf file with the name is deprecated."); + + if (info.exists("author")) + spec.author = info.get("author"); + + if (info.exists("release")) + spec.release = info.getS32("release"); + // Attempt to load dependencies from mod.conf bool mod_conf_has_depends = false; if (info.exists("depends")) { @@ -109,6 +137,10 @@ void parseModContents(ModSpec &spec) std::vector<std::string> dependencies; std::ifstream is((spec.path + DIR_DELIM + "depends.txt").c_str()); + + if (is.good()) + spec.deprecation_msgs.push_back("depends.txt is deprecated, please use mod.conf instead."); + while (is.good()) { std::string dep; std::getline(is, dep); @@ -127,14 +159,10 @@ void parseModContents(ModSpec &spec) } } - if (info.exists("description")) { + if (info.exists("description")) spec.desc = info.get("description"); - } else { - std::ifstream is((spec.path + DIR_DELIM + "description.txt") - .c_str()); - spec.desc = std::string((std::istreambuf_iterator<char>(is)), - std::istreambuf_iterator<char>()); - } + else if (fs::ReadFile(spec.path + DIR_DELIM + "description.txt", spec.desc)) + spec.deprecation_msgs.push_back("description.txt is deprecated, please use mod.conf instead."); } } @@ -395,83 +423,29 @@ ClientModConfiguration::ClientModConfiguration(const std::string &path) : } #endif -ModMetadata::ModMetadata(const std::string &mod_name) : m_mod_name(mod_name) +ModMetadata::ModMetadata(const std::string &mod_name, ModMetadataDatabase *database): + m_mod_name(mod_name), m_database(database) { + m_database->getModEntries(m_mod_name, &m_stringvars); } void ModMetadata::clear() { + for (const auto &pair : m_stringvars) { + m_database->removeModEntry(m_mod_name, pair.first); + } Metadata::clear(); - m_modified = true; } -bool ModMetadata::save(const std::string &root_path) +bool ModMetadata::setString(const std::string &name, const std::string &var) { - Json::Value json; - for (StringMap::const_iterator it = m_stringvars.begin(); - it != m_stringvars.end(); ++it) { - json[it->first] = it->second; - } - - if (!fs::PathExists(root_path)) { - if (!fs::CreateAllDirs(root_path)) { - errorstream << "ModMetadata[" << m_mod_name - << "]: Unable to save. '" << root_path - << "' tree cannot be created." << std::endl; - return false; + if (Metadata::setString(name, var)) { + if (var.empty()) { + m_database->removeModEntry(m_mod_name, name); + } else { + m_database->setModEntry(m_mod_name, name, var); } - } else if (!fs::IsDir(root_path)) { - errorstream << "ModMetadata[" << m_mod_name << "]: Unable to save. '" - << root_path << "' is not a directory." << std::endl; - return false; + return true; } - - bool w_ok = fs::safeWriteToFile( - root_path + DIR_DELIM + m_mod_name, fastWriteJson(json)); - - if (w_ok) { - m_modified = false; - } else { - errorstream << "ModMetadata[" << m_mod_name << "]: failed write file." - << std::endl; - } - return w_ok; -} - -bool ModMetadata::load(const std::string &root_path) -{ - m_stringvars.clear(); - - std::ifstream is((root_path + DIR_DELIM + m_mod_name).c_str(), - std::ios_base::binary); - if (!is.good()) { - return false; - } - - Json::Value root; - Json::CharReaderBuilder builder; - builder.settings_["collectComments"] = false; - std::string errs; - - if (!Json::parseFromStream(builder, is, &root, &errs)) { - errorstream << "ModMetadata[" << m_mod_name - << "]: failed read data " - "(Json decoding failure). Message: " - << errs << std::endl; - return false; - } - - const Json::Value::Members attr_list = root.getMemberNames(); - for (const auto &it : attr_list) { - Json::Value attr_value = root[it]; - m_stringvars[it] = attr_value.asString(); - } - - return true; -} - -bool ModMetadata::setString(const std::string &name, const std::string &var) -{ - m_modified = Metadata::setString(name, var); - return m_modified; + return false; } |