]> git.lizzy.rs Git - minetest.git/blobdiff - src/content/mods.cpp
Translated using Weblate (French)
[minetest.git] / src / content / mods.cpp
index 694bbcca8d7e970d23c5c30d2f9357345435ed6e..455506967d6d1f22a0dfb5d0f3b7b351758a06d8 100644 (file)
@@ -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,14 +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");
 
        spec.depends.clear();
        spec.optdepends.clear();
@@ -63,14 +80,32 @@ void parseModContents(ModSpec &spec)
 
        // Handle modpacks (defined by containing modpack.txt)
        std::ifstream modpack_is((spec.path + DIR_DELIM + "modpack.txt").c_str());
-       if (modpack_is.good()) {    // a modpack, recursively get the mods in it
-               modpack_is.close(); // We don't actually need the file
+       std::ifstream modpack2_is((spec.path + DIR_DELIM + "modpack.conf").c_str());
+       if (modpack_is.good() || modpack2_is.good()) {
+               if (modpack_is.good())
+                       modpack_is.close();
+
+               if (modpack2_is.good())
+                       modpack2_is.close();
+
                spec.is_modpack = true;
                spec.modpack_content = getModsInPath(spec.path, true);
-               // modpacks have no dependencies; they are defined and
-               // tracked separately for each mod in the modpack
 
        } 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")) {
@@ -102,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);
@@ -120,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.");
        }
 }
 
@@ -160,7 +195,7 @@ std::map<std::string, ModSpec> getModsInPath(
        return result;
 }
 
-std::vector<ModSpec> flattenMods(std::map<std::string, ModSpec> mods)
+std::vector<ModSpec> flattenMods(const std::map<std::string, ModSpec> &mods)
 {
        std::vector<ModSpec> result;
        for (const auto &it : mods) {
@@ -267,7 +302,8 @@ void ModConfiguration::addModsFromConfig(
        conf.readConfigFile(settings_path.c_str());
        std::vector<std::string> names = conf.getNames();
        for (const std::string &name : names) {
-               if (name.compare(0, 9, "load_mod_") == 0 && conf.getBool(name))
+               if (name.compare(0, 9, "load_mod_") == 0 && conf.get(name) != "false" &&
+                               conf.get(name) != "nil")
                        load_mod_names.insert(name.substr(9));
        }
 
@@ -387,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;
-       }
-
-       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;
        }
-
-       return true;
-}
-
-bool ModMetadata::setString(const std::string &name, const std::string &var)
-{
-       m_modified = Metadata::setString(name, var);
-       return m_modified;
+       return false;
 }