mirror of https://github.com/minetest/minetest.git
Merge 625601bc0c
into c4703a7f19
This commit is contained in:
commit
d251abd968
|
@ -95,11 +95,22 @@ local function start_install(package, reason)
|
|||
if result.msg then
|
||||
gamedata.errormessage = result.msg
|
||||
else
|
||||
local delete_old_dir
|
||||
if package.path then
|
||||
local name = pkgmgr.normalize_game_id(package.path:match("[^/\\]+[/\\]?$"))
|
||||
if name ~= package.name then
|
||||
delete_old_dir = package.path
|
||||
package.path = core.get_gamepath() .. DIR_DELIM .. package.name
|
||||
end
|
||||
end
|
||||
local path, msg = pkgmgr.install_dir(package.type, result.path, package.name, package.path)
|
||||
core.delete_dir(result.path)
|
||||
if not path then
|
||||
gamedata.errormessage = fgettext_ne("Error installing \"$1\": $2", package.title, msg)
|
||||
else
|
||||
if delete_old_dir then
|
||||
core.delete_dir(delete_old_dir)
|
||||
end
|
||||
core.log("action", "Installed package to " .. path)
|
||||
|
||||
local conf_path
|
||||
|
@ -131,6 +142,16 @@ local function start_install(package, reason)
|
|||
end
|
||||
conf:set("author", package.author)
|
||||
conf:set("release", package.release)
|
||||
if package.aliases then
|
||||
local gameid_aliases = {}
|
||||
for _, alias in ipairs(package.aliases) do
|
||||
local alias_cut = alias:match("[^/]+$")
|
||||
if alias_cut ~= package.name then
|
||||
gameid_aliases[#gameid_aliases + 1] = alias_cut
|
||||
end
|
||||
end
|
||||
conf:set("aliases", table.concat(gameid_aliases, ","))
|
||||
end
|
||||
conf:write()
|
||||
end
|
||||
end
|
||||
|
@ -388,10 +409,11 @@ local function fetch_pkgs(params)
|
|||
package.url_part = core.urlencode(package.author) .. "/" .. core.urlencode(package.name)
|
||||
|
||||
if package.aliases then
|
||||
local suffix = "/" .. package.name
|
||||
local suf_len = #suffix
|
||||
local is_game = package.type == "game"
|
||||
for _, alias in ipairs(package.aliases) do
|
||||
-- We currently don't support name changing
|
||||
local suffix = "/" .. package.name
|
||||
if alias:sub(-#suffix) == suffix then
|
||||
if is_game or alias:sub(suf_len) == suffix then
|
||||
aliases[alias:lower()] = package.id
|
||||
end
|
||||
end
|
||||
|
|
|
@ -828,6 +828,13 @@ function pkgmgr.get_contentdb_id(content)
|
|||
return nil
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Normalizes ID of a game
|
||||
function pkgmgr.normalize_game_id(name)
|
||||
return name:match("(.*)_game$") or name
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- read initial data
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
|
@ -78,7 +78,15 @@ local function init_globals()
|
|||
end,
|
||||
-- Filter function
|
||||
function(element, gameid)
|
||||
return element.gameid == gameid
|
||||
if element.gameid == gameid then
|
||||
return true
|
||||
end
|
||||
for _, alias in ipairs(pkgmgr.find_by_gameid(gameid).aliases) do
|
||||
if pkgmgr.normalize_game_id(element.gameid) == pkgmgr.normalize_game_id(alias) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
)
|
||||
|
||||
|
|
|
@ -357,6 +357,19 @@ local function main_button_handler(this, fields, name, tabdata)
|
|||
local game_obj
|
||||
if world then
|
||||
game_obj = pkgmgr.find_by_gameid(world.gameid)
|
||||
if not game_obj then
|
||||
local function try_to_find_alias(world)
|
||||
for _, game in ipairs(pkgmgr.games) do
|
||||
for _, alias in pairs(game.aliases) do
|
||||
if pkgmgr.normalize_game_id(alias) == pkgmgr.normalize_game_id(world.gameid) then
|
||||
world.gameid = game.id
|
||||
return game
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
game_obj = try_to_find_alias(world)
|
||||
end
|
||||
core.settings:set("menu_last_game", game_obj.id)
|
||||
end
|
||||
|
||||
|
|
|
@ -93,6 +93,10 @@ The game directory can contain the following files:
|
|||
an internal ID used to track versions.
|
||||
* `textdomain`: Textdomain used to translate description. Defaults to game id.
|
||||
See [Translating content meta](#translating-content-meta).
|
||||
* `aliases = <comma-separated aliases>`
|
||||
e.g. `aliases = aa,bb` (game has been named "aa" and then "bb" before)
|
||||
This allows automatic loading of worlds using a gameid from this list.
|
||||
This is intended to allow a full rename of a game, including its id.
|
||||
* `minetest.conf`:
|
||||
Used to set default settings when running this game.
|
||||
* `settingtypes.txt`:
|
||||
|
|
|
@ -101,6 +101,15 @@ SubgameSpec findSubgame(const std::string &id)
|
|||
std::string share = porting::path_share;
|
||||
std::string user = porting::path_user;
|
||||
|
||||
auto normalize_game_id = [&](std::string_view name){
|
||||
if (str_ends_with(name, "_game"))
|
||||
return name.substr(0, name.size() - 5);
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
std::string idv = static_cast<std::string>(normalize_game_id(trim(id)));
|
||||
|
||||
// Get games install locations
|
||||
Strfnd search_paths(getSubgamePathEnv());
|
||||
|
||||
|
@ -134,8 +143,53 @@ SubgameSpec findSubgame(const std::string &id)
|
|||
}
|
||||
}
|
||||
|
||||
if (game_path.empty())
|
||||
return SubgameSpec();
|
||||
// Failed to find the game, try to find aliased game
|
||||
if (game_path.empty()) {
|
||||
std::vector<GameFindPath> gamespaths;
|
||||
gamespaths.emplace_back(share + DIR_DELIM + "games", false);
|
||||
gamespaths.emplace_back(user + DIR_DELIM + "games", true);
|
||||
|
||||
Strfnd search_paths(getSubgamePathEnv());
|
||||
|
||||
while (!search_paths.at_end())
|
||||
gamespaths.emplace_back(search_paths.next(PATH_DELIM), false);
|
||||
|
||||
auto look_for_alias = [&](){
|
||||
for (const GameFindPath &gamespath : gamespaths) {
|
||||
const std::string &path = gamespath.path;
|
||||
std::vector<fs::DirListNode> dirlist = fs::GetDirListing(path);
|
||||
for (const fs::DirListNode &dln : dirlist) {
|
||||
if (!dln.dir)
|
||||
continue;
|
||||
|
||||
// If configuration file is not found or broken, ignore game
|
||||
Settings conf;
|
||||
std::string conf_path = path + DIR_DELIM + dln.name +
|
||||
DIR_DELIM + "game.conf";
|
||||
if (!conf.readConfigFile(conf_path.c_str()))
|
||||
continue;
|
||||
|
||||
if (conf.exists("aliases")) {
|
||||
std::vector<std::string> aliases = str_split(conf.get("aliases"), ',');
|
||||
for (const std::string &alias_raw : aliases) {
|
||||
std::string_view alias = normalize_game_id(trim(alias_raw));
|
||||
if (alias == idv) {
|
||||
idv = dln.name;
|
||||
game_path = path + DIR_DELIM + dln.name;
|
||||
user_game = gamespath.user_specific;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
look_for_alias();
|
||||
|
||||
if (game_path.empty()) // Failed to find the game taking aliases into account
|
||||
return SubgameSpec();
|
||||
}
|
||||
// Found the game, proceed
|
||||
|
||||
std::string gamemod_path = game_path + DIR_DELIM + "mods";
|
||||
|
||||
|
@ -160,7 +214,7 @@ SubgameSpec findSubgame(const std::string &id)
|
|||
else if (conf.exists("name"))
|
||||
game_title = conf.get("name");
|
||||
else
|
||||
game_title = id;
|
||||
game_title = idv;
|
||||
|
||||
std::string game_author;
|
||||
if (conf.exists("author"))
|
||||
|
@ -170,6 +224,14 @@ SubgameSpec findSubgame(const std::string &id)
|
|||
if (conf.exists("release"))
|
||||
game_release = conf.getS32("release");
|
||||
|
||||
std::unordered_set<std::string> aliases;
|
||||
if (conf.exists("aliases"))
|
||||
{
|
||||
std::vector<std::string> aliases_raw = str_split(conf.get("aliases"), ',');
|
||||
for (const std::string &alias : aliases_raw)
|
||||
aliases.insert(static_cast<std::string>(normalize_game_id(trim(alias))));
|
||||
}
|
||||
|
||||
std::string menuicon_path;
|
||||
#ifndef SERVER
|
||||
menuicon_path = getImagePath(
|
||||
|
@ -177,7 +239,7 @@ SubgameSpec findSubgame(const std::string &id)
|
|||
#endif
|
||||
|
||||
SubgameSpec spec(id, game_path, gamemod_path, mods_paths, game_title,
|
||||
menuicon_path, game_author, game_release);
|
||||
menuicon_path, game_author, game_release, aliases);
|
||||
|
||||
if (conf.exists("name") && !conf.exists("title"))
|
||||
spec.deprecation_msgs.push_back("\"name\" setting in game.conf is deprecated, please use \"title\" instead");
|
||||
|
|
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <string>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
class Settings;
|
||||
|
@ -41,6 +42,8 @@ struct SubgameSpec
|
|||
std::unordered_map<std::string, std::string> addon_mods_paths;
|
||||
std::string menuicon_path;
|
||||
|
||||
std::unordered_set<std::string> aliases;
|
||||
|
||||
// For logging purposes
|
||||
std::vector<const char *> deprecation_msgs;
|
||||
|
||||
|
@ -49,11 +52,12 @@ struct SubgameSpec
|
|||
const std::unordered_map<std::string, std::string> &addon_mods_paths = {},
|
||||
const std::string &title = "",
|
||||
const std::string &menuicon_path = "",
|
||||
const std::string &author = "", int release = 0) :
|
||||
const std::string &author = "", int release = 0,
|
||||
const std::unordered_set<std::string> &aliases = {}) :
|
||||
id(id),
|
||||
title(title), author(author), release(release), path(path),
|
||||
gamemods_path(gamemods_path), addon_mods_paths(addon_mods_paths),
|
||||
menuicon_path(menuicon_path)
|
||||
menuicon_path(menuicon_path), aliases(aliases)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -332,6 +332,18 @@ int ModApiMainMenu::l_get_games(lua_State *L)
|
|||
lua_pushstring(L, game.menuicon_path.c_str());
|
||||
lua_settable(L, top_lvl2);
|
||||
|
||||
lua_pushstring(L, "aliases");
|
||||
lua_newtable(L);
|
||||
int table_aliases = lua_gettop(L);
|
||||
int alias_index = 1;
|
||||
for (const auto &alias : game.aliases) {
|
||||
lua_pushnumber(L, alias_index);
|
||||
lua_pushstring(L, alias.c_str());
|
||||
lua_settable(L, table_aliases);
|
||||
alias_index++;
|
||||
}
|
||||
lua_settable(L, top_lvl2);
|
||||
|
||||
lua_pushstring(L, "addon_mods_paths");
|
||||
lua_newtable(L);
|
||||
int table2 = lua_gettop(L);
|
||||
|
|
Loading…
Reference in New Issue