1
0
Fork 0

Allow cmd line & add-ons to supply FGData extensions

Allow add-ons to define an FGData subdir, and support multiple —data=
command line arguments, to avoid the need to modify FG_ROOT (which might
be read-only). Allow additional data paths to be either higher or lower
priority than FG_ROOT, so that add-ons cannot replace files in FG_ROOT.
This commit is contained in:
James Turner 2020-06-30 17:08:29 +01:00
parent f97ea1f621
commit 9e00715079
6 changed files with 52 additions and 10 deletions

View file

@ -204,9 +204,16 @@ AddonManager::registerAddon(const SGPath& addonPath)
string msg = "Registered add-on '" + addon->getName() + "' (" + addonId +
") version " + addonVersion(addonId)->str() + "; "
"base path is '" + addonRealPath.utf8Str() + "'";
// This preserves the registration order
_registeredAddons.push_back(std::move(addon));
SG_LOG(SG_GENERAL, SG_INFO, msg);
auto dataPath = addonRealPath / "FGData";
if (dataPath.exists()) {
SG_LOG(SG_GENERAL, SG_INFO, "Registering data path for add-on: " << addon->getName());
globals->append_data_path(dataPath, true /* after FG_ROOT */);
}
// This preserves the registration order
_registeredAddons.push_back(addon);
SG_LOG(SG_GENERAL, SG_INFO, msg);
return addonId;
}

View file

@ -302,6 +302,7 @@ PathList FGGlobals::get_data_paths() const
{
PathList r(additional_data_paths);
r.push_back(fg_root);
r.insert(r.end(), _dataPathsAfterFGRoot.begin(), _dataPathsAfterFGRoot.end());
return r;
}
@ -318,13 +319,23 @@ PathList FGGlobals::get_data_paths(const std::string& suffix) const
return r;
}
void FGGlobals::append_data_path(const SGPath& path)
void FGGlobals::append_data_path(const SGPath& path, bool afterFGRoot)
{
if (!path.exists()) {
SG_LOG(SG_GENERAL, SG_WARN, "adding non-existant data path:" << path);
}
additional_data_paths.push_back(path);
using RM = simgear::ResourceManager;
auto resManager = RM::instance();
if (afterFGRoot) {
_dataPathsAfterFGRoot.push_back(path);
// after FG_ROOT
resManager->addBasePath(path, static_cast<RM::Priority>(RM::PRIORITY_DEFAULT - 10));
} else {
additional_data_paths.push_back(path);
// after NORMAL prioirty, but ahead of FG_ROOT
resManager->addBasePath(path, static_cast<RM::Priority>(RM::PRIORITY_DEFAULT + 10));
}
}
SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const
@ -342,8 +353,15 @@ SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const
return rootPath;
}
SG_LOG(SG_GENERAL, SG_WARN, "dir not found in any data path:" << pathSuffix);
return SGPath();
for (SGPath p : _dataPathsAfterFGRoot) {
p.append(pathSuffix);
if (p.exists()) {
return p;
}
}
SG_LOG(SG_IO, SG_WARN, "not found in any data path: '" << pathSuffix << "'");
return SGPath{};
}
void FGGlobals::append_fg_scenery (const PathList &paths)

View file

@ -101,6 +101,8 @@ private:
*/
PathList additional_data_paths;
PathList _dataPathsAfterFGRoot; ///< paths with a /lower/ prioirty than FGRoot
// Users home directory for data
SGPath fg_home;
@ -216,7 +218,7 @@ public:
*/
PathList get_data_paths(const std::string& suffix) const;
void append_data_path(const SGPath& path);
void append_data_path(const SGPath& path, bool afterFGRoot = false);
/**
* Given a path suffix (eg 'Textures' or 'AI/Traffic'), find the

View file

@ -173,7 +173,7 @@ static void initTerrasync()
// add the terrasync root as a data path so data can be retrieved from it
// (even if we are in read-only mode)
SGPath terraSyncDir(globals->get_terrasync_dir());
globals->append_data_path(terraSyncDir);
globals->append_data_path(terraSyncDir, false /* = ahead of FG_ROOT */);
if (fgGetBool("/sim/fghome-readonly", false)) {
return;

View file

@ -727,6 +727,20 @@ fgOptAddon(const char *arg)
return FG_OPTIONS_OK;
}
static int
fgOptAdditionalDataDir(const char* arg)
{
const SGPath dataPath = SGPath::fromUtf8(arg);
if (!dataPath.exists()) {
SG_LOG(SG_GENERAL, SG_ALERT, "--data path not found:'" << dataPath << "'");
flightgear::fatalMessageBoxWithoutExit("FlightGear", "Data path not found");
return FG_OPTIONS_EXIT;
}
globals->append_data_path(dataPath, false /* = before FG_ROOT */);
return FG_OPTIONS_OK;
}
static int
fgOptVOR( const char * arg )
{
@ -1821,6 +1835,7 @@ struct OptionDesc {
{"flight-plan", true, OPTION_STRING, "/autopilot/route-manager/file-path", false, "", NULL },
{"config", true, OPTION_IGNORE | OPTION_MULTI, "", false, "", 0 },
{"addon", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptAddon },
{"data", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptAdditionalDataDir },
{"aircraft", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
{"vehicle", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
{"failure", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptFailure },

View file

@ -753,7 +753,7 @@ bool FGGeneric::close() {
void
FGGeneric::reinit()
{
SGPath path = globals->resolve_maybe_aircraft_path("Protocol/" + file_name);
SGPath path = globals->find_data_dir("Protocol/" + file_name);
if (!path.exists()) {
SG_LOG(SG_NETWORK, SG_WARN, "Couldn't find protocol file for '" << file_name << "'");
return;