summaryrefslogtreecommitdiff
path: root/src/content
diff options
context:
space:
mode:
Diffstat (limited to 'src/content')
-rw-r--r--src/content/mods.cpp146
-rw-r--r--src/content/mods.h15
-rw-r--r--src/content/subgames.cpp32
-rw-r--r--src/content/subgames.h2
4 files changed, 91 insertions, 104 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;
}
diff --git a/src/content/mods.h b/src/content/mods.h
index b3500fbc8..dd3b6e0e6 100644
--- a/src/content/mods.h
+++ b/src/content/mods.h
@@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "config.h"
#include "metadata.h"
+class ModMetadataDatabase;
+
#define MODNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
struct ModSpec
@@ -49,6 +51,9 @@ struct ModSpec
bool part_of_modpack = false;
bool is_modpack = false;
+ // For logging purposes
+ std::vector<const char *> deprecation_msgs;
+
// if modpack:
std::map<std::string, ModSpec> modpack_content;
ModSpec(const std::string &name = "", const std::string &path = "") :
@@ -59,6 +64,8 @@ struct ModSpec
name(name), path(path), part_of_modpack(part_of_modpack)
{
}
+
+ void checkAndLog() const;
};
// Retrieves depends, optdepends, is_modpack and modpack_content
@@ -144,20 +151,16 @@ class ModMetadata : public Metadata
{
public:
ModMetadata() = delete;
- ModMetadata(const std::string &mod_name);
+ ModMetadata(const std::string &mod_name, ModMetadataDatabase *database);
~ModMetadata() = default;
virtual void clear();
- bool save(const std::string &root_path);
- bool load(const std::string &root_path);
-
- bool isModified() const { return m_modified; }
const std::string &getModName() const { return m_mod_name; }
virtual bool setString(const std::string &name, const std::string &var);
private:
std::string m_mod_name;
- bool m_modified = false;
+ ModMetadataDatabase *m_database;
};
diff --git a/src/content/subgames.cpp b/src/content/subgames.cpp
index e9dc609b0..62e82e0e4 100644
--- a/src/content/subgames.cpp
+++ b/src/content/subgames.cpp
@@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "util/strfnd.h"
#include "defaultsettings.h" // for set_default_settings
-#include "mapgen/mapgen.h" // for MapgenParams
+#include "map_settings_manager.h"
#include "util/string.h"
#ifndef SERVER
@@ -113,6 +113,10 @@ SubgameSpec findSubgame(const std::string &id)
if (user != share || user_game)
mods_paths.insert(user + DIR_DELIM + "mods");
+ for (const std::string &mod_path : getEnvModPaths()) {
+ mods_paths.insert(mod_path);
+ }
+
// Get meta
std::string conf_path = game_path + DIR_DELIM + "game.conf";
Settings conf;
@@ -354,6 +358,7 @@ void loadGameConfAndInitWorld(const std::string &path, const std::string &name,
conf.set("backend", "sqlite3");
conf.set("player_backend", "sqlite3");
conf.set("auth_backend", "sqlite3");
+ conf.set("mod_storage_backend", "sqlite3");
conf.setBool("creative_mode", g_settings->getBool("creative_mode"));
conf.setBool("enable_damage", g_settings->getBool("enable_damage"));
@@ -365,22 +370,25 @@ void loadGameConfAndInitWorld(const std::string &path, const std::string &name,
// Create map_meta.txt if does not already exist
std::string map_meta_path = final_path + DIR_DELIM + "map_meta.txt";
if (!fs::PathExists(map_meta_path)) {
- verbosestream << "Creating map_meta.txt (" << map_meta_path << ")"
- << std::endl;
- std::ostringstream oss(std::ios_base::binary);
-
- Settings conf;
- MapgenParams params;
+ MapSettingsManager mgr(map_meta_path);
- params.readParams(g_settings);
- params.writeParams(&conf);
- conf.writeLines(oss);
- oss << "[end_of_params]\n";
+ mgr.setMapSetting("seed", g_settings->get("fixed_map_seed"));
- fs::safeWriteToFile(map_meta_path, oss.str());
+ mgr.makeMapgenParams();
+ mgr.saveMapMeta();
}
// The Settings object is no longer needed for created worlds
if (new_game_settings)
delete game_settings;
}
+
+std::vector<std::string> getEnvModPaths()
+{
+ const char *c_mod_path = getenv("MINETEST_MOD_PATH");
+ std::vector<std::string> paths;
+ Strfnd search_paths(c_mod_path ? c_mod_path : "");
+ while (!search_paths.at_end())
+ paths.push_back(search_paths.next(PATH_DELIM));
+ return paths;
+}
diff --git a/src/content/subgames.h b/src/content/subgames.h
index 60392639b..4a50803e8 100644
--- a/src/content/subgames.h
+++ b/src/content/subgames.h
@@ -58,6 +58,8 @@ SubgameSpec findWorldSubgame(const std::string &world_path);
std::set<std::string> getAvailableGameIds();
std::vector<SubgameSpec> getAvailableGames();
+// Get the list of paths to mods in the environment variable $MINETEST_MOD_PATH
+std::vector<std::string> getEnvModPaths();
bool getWorldExists(const std::string &world_path);
//! Try to get the displayed name of a world