#include "filesys.h"
#include "settings.h"
#include "log.h"
+#include "util/strfnd.h"
+#include "defaultsettings.h" // for override_default_settings
+#include "mapgen/mapgen.h" // for MapgenParams
+#include "util/string.h"
+
#ifndef SERVER
-#include "tile.h" // getImagePath
+ #include "client/tile.h" // getImagePath
#endif
-#include "util/string.h"
bool getGameMinetestConfig(const std::string &game_path, Settings &conf)
{
{}
};
+std::string getSubgamePathEnv()
+{
+ char *subgame_path = getenv("MINETEST_SUBGAME_PATH");
+ return subgame_path ? std::string(subgame_path) : "";
+}
+
SubgameSpec findSubgame(const std::string &id)
{
- if(id == "")
+ if (id.empty())
return SubgameSpec();
std::string share = porting::path_share;
std::string user = porting::path_user;
std::vector<GameFindPath> find_paths;
- find_paths.push_back(GameFindPath(
- user + DIR_DELIM + "games" + DIR_DELIM + id + "_game", true));
- find_paths.push_back(GameFindPath(
- user + DIR_DELIM + "games" + DIR_DELIM + id, true));
- find_paths.push_back(GameFindPath(
- share + DIR_DELIM + "games" + DIR_DELIM + id + "_game", false));
- find_paths.push_back(GameFindPath(
- share + DIR_DELIM + "games" + DIR_DELIM + id, false));
+
+ Strfnd search_paths(getSubgamePathEnv());
+
+ while (!search_paths.at_end()) {
+ std::string path = search_paths.next(PATH_DELIM);
+ find_paths.emplace_back(path + DIR_DELIM + id, false);
+ find_paths.emplace_back(path + DIR_DELIM + id + "_game", false);
+ }
+
+ find_paths.emplace_back(user + DIR_DELIM + "games" + DIR_DELIM + id + "_game", true);
+ find_paths.emplace_back(user + DIR_DELIM + "games" + DIR_DELIM + id, true);
+ find_paths.emplace_back(share + DIR_DELIM + "games" + DIR_DELIM + id + "_game",
+ false);
+ find_paths.emplace_back(share + DIR_DELIM + "games" + DIR_DELIM + id, false);
// Find game directory
std::string game_path;
bool user_game = true; // Game is in user's directory
- for(u32 i=0; i<find_paths.size(); i++){
- const std::string &try_path = find_paths[i].path;
- if(fs::PathExists(try_path)){
+ for (const GameFindPath &find_path : find_paths) {
+ const std::string &try_path = find_path.path;
+ if (fs::PathExists(try_path)) {
game_path = try_path;
- user_game = find_paths[i].user_specific;
+ user_game = find_path.user_specific;
break;
}
}
- if(game_path == "")
+ if (game_path.empty())
return SubgameSpec();
std::string gamemod_path = game_path + DIR_DELIM + "mods";
// Find mod directories
if(user != share || user_game)
mods_paths.insert(user + DIR_DELIM + "mods");
std::string game_name = getGameName(game_path);
- if(game_name == "")
+ if (game_name.empty())
game_name = id;
std::string menuicon_path;
#ifndef SERVER
gamespec.path = world_gamepath;
gamespec.gamemods_path= world_gamepath + DIR_DELIM + "mods";
gamespec.name = getGameName(world_gamepath);
- if(gamespec.name == "")
+ if (gamespec.name.empty())
gamespec.name = "unknown";
return gamespec;
}
std::set<std::string> gamespaths;
gamespaths.insert(porting::path_share + DIR_DELIM + "games");
gamespaths.insert(porting::path_user + DIR_DELIM + "games");
- for(std::set<std::string>::const_iterator i = gamespaths.begin();
- i != gamespaths.end(); i++){
- std::vector<fs::DirListNode> dirlist = fs::GetDirListing(*i);
- for(u32 j=0; j<dirlist.size(); j++){
- if(!dirlist[j].dir)
+
+ Strfnd search_paths(getSubgamePathEnv());
+
+ while (!search_paths.at_end())
+ gamespaths.insert(search_paths.next(PATH_DELIM));
+
+ for (const std::string &gamespath : gamespaths) {
+ std::vector<fs::DirListNode> dirlist = fs::GetDirListing(gamespath);
+ for (const fs::DirListNode &dln : dirlist) {
+ if(!dln.dir)
continue;
// If configuration file is not found or broken, ignore game
Settings conf;
- if(!getGameConfig(*i + DIR_DELIM + dirlist[j].name, conf))
+ if(!getGameConfig(gamespath + DIR_DELIM + dln.name, conf))
continue;
// Add it to result
const char *ends[] = {"_game", NULL};
- std::string shorter = removeStringEnd(dirlist[j].name, ends);
- if(shorter != "")
+ std::string shorter = removeStringEnd(dln.name, ends);
+ if (!shorter.empty())
gameids.insert(shorter);
else
- gameids.insert(dirlist[j].name);
+ gameids.insert(dln.name);
}
}
return gameids;
{
std::vector<SubgameSpec> specs;
std::set<std::string> gameids = getAvailableGameIds();
- for(std::set<std::string>::const_iterator i = gameids.begin();
- i != gameids.end(); i++)
- specs.push_back(findSubgame(*i));
+ for (const auto &gameid : gameids)
+ specs.push_back(findSubgame(gameid));
return specs;
}
return conf.get("gameid");
}
+std::string getWorldPathEnv()
+{
+ char *world_path = getenv("MINETEST_WORLD_PATH");
+ return world_path ? std::string(world_path) : "";
+}
+
std::vector<WorldSpec> getAvailableWorlds()
{
std::vector<WorldSpec> worlds;
std::set<std::string> worldspaths;
+
+ Strfnd search_paths(getWorldPathEnv());
+
+ while (!search_paths.at_end())
+ worldspaths.insert(search_paths.next(PATH_DELIM));
+
worldspaths.insert(porting::path_user + DIR_DELIM + "worlds");
- infostream<<"Searching worlds..."<<std::endl;
- for(std::set<std::string>::const_iterator i = worldspaths.begin();
- i != worldspaths.end(); i++){
- infostream<<" In "<<(*i)<<": "<<std::endl;
- std::vector<fs::DirListNode> dirvector = fs::GetDirListing(*i);
- for(u32 j=0; j<dirvector.size(); j++){
- if(!dirvector[j].dir)
+ infostream << "Searching worlds..." << std::endl;
+ for (const std::string &worldspath : worldspaths) {
+ infostream << " In " << worldspath << ": " <<std::endl;
+ std::vector<fs::DirListNode> dirvector = fs::GetDirListing(worldspath);
+ for (const fs::DirListNode &dln : dirvector) {
+ if(!dln.dir)
continue;
- std::string fullpath = *i + DIR_DELIM + dirvector[j].name;
- std::string name = dirvector[j].name;
+ std::string fullpath = worldspath + DIR_DELIM + dln.name;
+ std::string name = dln.name;
// Just allow filling in the gameid always for now
bool can_be_legacy = true;
std::string gameid = getWorldGameId(fullpath, can_be_legacy);
WorldSpec spec(fullpath, name, gameid);
infostream<<"Old world found."<<std::endl;
worlds.push_back(spec);
- }while(0);
+ }while(false);
infostream<<worlds.size()<<" found."<<std::endl;
return worlds;
}
-bool initializeWorld(const std::string &path, const std::string &gameid)
+bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamespec)
{
- infostream<<"Initializing world at "<<path<<std::endl;
+ // Override defaults with those provided by the game.
+ // We clear and reload the defaults because the defaults
+ // might have been overridden by other subgame config
+ // files that were loaded before.
+ g_settings->clearDefaults();
+ set_default_settings(g_settings);
+ Settings game_defaults;
+ getGameMinetestConfig(gamespec.path, game_defaults);
+ override_default_settings(g_settings, &game_defaults);
+
+ infostream << "Initializing world at " << path << std::endl;
+
+ fs::CreateAllDirs(path);
+
// Create world.mt if does not already exist
- std::string worldmt_path = path + DIR_DELIM + "world.mt";
- if(!fs::PathExists(worldmt_path)){
- infostream<<"Creating world.mt ("<<worldmt_path<<")"<<std::endl;
+ std::string worldmt_path = path + DIR_DELIM "world.mt";
+ if (!fs::PathExists(worldmt_path)) {
+ Settings conf;
+
+ conf.set("gameid", gamespec.id);
+ conf.set("backend", "sqlite3");
+ conf.set("player_backend", "sqlite3");
+ conf.setBool("creative_mode", g_settings->getBool("creative_mode"));
+ conf.setBool("enable_damage", g_settings->getBool("enable_damage"));
+
+ if (!conf.updateConfigFile(worldmt_path.c_str()))
+ return false;
+ }
+
+ // Create map_meta.txt if does not already exist
+ std::string map_meta_path = path + DIR_DELIM + "map_meta.txt";
+ if (!fs::PathExists(map_meta_path)){
+ verbosestream << "Creating map_meta.txt (" << map_meta_path << ")" << std::endl;
fs::CreateAllDirs(path);
- std::ostringstream ss(std::ios_base::binary);
- ss<<"gameid = "<<gameid<< "\nbackend = sqlite3\n";
- fs::safeWriteToFile(worldmt_path, ss.str());
+ std::ostringstream oss(std::ios_base::binary);
+
+ Settings conf;
+ MapgenParams params;
+
+ params.readParams(g_settings);
+ params.writeParams(&conf);
+ conf.writeLines(oss);
+ oss << "[end_of_params]\n";
+
+ fs::safeWriteToFile(map_meta_path, oss.str());
}
return true;
}
-