diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-12 02:40:00 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-12 02:40:00 -0500 |
| commit | e0fb66428a9b78b4c326df8d7e30429a5b271d74 (patch) | |
| tree | 0fd83fe790ecb7d5cd3cfb36535e45d1b7118098 /libs/basic_games_native/src/basicgameplugin.cpp | |
| parent | e985dc340097831d4e5625941bded217abaa57b8 (diff) | |
Remove dead plugin scaffolds and duplicate lib dirs
The *_native C++ ports were replaced by bundled Python + .py plugins in
de4db79, but the source dirs were left behind without any CMake wiring —
causing confusion when editing them appears to do nothing. Same story
for libs/dds_header (stale duplicate of libs/preview_dds, unrelated to
the actively-used libs/dds-header) and libs/game_gamebryo (superseded
by libs/game_bethesda/src/gamebryo).
Removes:
- libs/basic_games_native
- libs/form43_checker_native
- libs/installer_omod_native
- libs/preview_dds_native
- libs/rootbuilder_native
- libs/script_extender_checker_native
- libs/dds_header
- libs/game_gamebryo
Diffstat (limited to 'libs/basic_games_native/src/basicgameplugin.cpp')
| -rw-r--r-- | libs/basic_games_native/src/basicgameplugin.cpp | 448 |
1 files changed, 0 insertions, 448 deletions
diff --git a/libs/basic_games_native/src/basicgameplugin.cpp b/libs/basic_games_native/src/basicgameplugin.cpp deleted file mode 100644 index 5f41f3a..0000000 --- a/libs/basic_games_native/src/basicgameplugin.cpp +++ /dev/null @@ -1,448 +0,0 @@ -#include "basicgameplugin.h" -#include "steamutils.h" - -#include <uibase/utility.h> -#include <uibase/versioninfo.h> - -#include <uibase/log.h> - -#include <QDateTime> -#include <QDirIterator> -#include <QStandardPaths> - -// Simple ISaveGame implementation for basic games -class BasicSaveGame : public MOBase::ISaveGame -{ -public: - BasicSaveGame(const QString& filePath) - : m_filePath(filePath), m_fileInfo(filePath) - { - } - - QString getFilepath() const override { return m_filePath; } - - QDateTime getCreationTime() const override - { - return m_fileInfo.lastModified(); - } - - QString getName() const override - { - return m_fileInfo.completeBaseName(); - } - - QString getSaveGroupIdentifier() const override { return ""; } - - QStringList allFiles() const override { return {m_filePath}; } - -private: - QString m_filePath; - QFileInfo m_fileInfo; -}; - -BasicGamePlugin::BasicGamePlugin(const GameDefinition& def) : m_def(def) {} - -bool BasicGamePlugin::init(MOBase::IOrganizer* organizer) -{ - m_organizer = organizer; - return true; -} - -QString BasicGamePlugin::name() const -{ - return m_def.pluginName; -} - -QString BasicGamePlugin::localizedName() const -{ - return m_def.pluginName + " (Native)"; -} - -QString BasicGamePlugin::author() const -{ - return m_def.author; -} - -QString BasicGamePlugin::description() const -{ - return "Adds support for " + m_def.gameName; -} - -MOBase::VersionInfo BasicGamePlugin::version() const -{ - return MOBase::VersionInfo(m_def.version); -} - -QList<MOBase::PluginSetting> BasicGamePlugin::settings() const -{ - return {}; -} - -QString BasicGamePlugin::gameName() const -{ - return m_def.gameName; -} - -void BasicGamePlugin::detectGame() -{ - // Try Steam first - for (int steamId : m_def.steamAppIds) { - QString path = findSteamGamePath(steamId); - if (!path.isEmpty()) { - MOBase::log::debug("detectGame: '{}' found via Steam appid {} at '{}'", - m_def.gameName, steamId, path); - setGamePath(path); - return; - } - } - - // GOG via Heroic launcher - if (!m_def.gogAppIds.isEmpty()) { - // Check Heroic GOG installed games - QStringList heroicPaths = { - QDir::homePath() + "/.config/heroic/gog_store/installed.json", - QDir::homePath() + - "/.var/app/com.heroicgameslauncher.hgl/config/heroic/" - "gog_store/installed.json", - }; - for (const auto& heroicPath : heroicPaths) { - QFile file(heroicPath); - if (!file.open(QIODevice::ReadOnly)) - continue; - QByteArray data = file.readAll(); - // Simple JSON parsing for install_path - for (int gogId : m_def.gogAppIds) { - QString idStr = QString::number(gogId); - if (data.contains(idStr.toUtf8())) { - // Find the install_path for this entry - int idx = data.indexOf(idStr.toUtf8()); - int pathIdx = data.indexOf("install_path", idx); - if (pathIdx >= 0) { - // Find the value after "install_path" - int colonIdx = data.indexOf(':', pathIdx); - int quoteStart = data.indexOf('"', colonIdx + 1); - int quoteEnd = data.indexOf('"', quoteStart + 1); - if (quoteStart >= 0 && quoteEnd > quoteStart) { - QString path = - QString::fromUtf8(data.mid(quoteStart + 1, quoteEnd - quoteStart - 1)); - if (QDir(path).exists()) { - setGamePath(path); - return; - } - } - } - } - } - } - } -} - -void BasicGamePlugin::initializeProfile(const QDir& directory, - ProfileSettings settings) const -{ - // Create the profile directory if needed - if (!directory.exists()) { - directory.mkpath("."); - } -} - -std::vector<std::shared_ptr<const MOBase::ISaveGame>> -BasicGamePlugin::listSaves(QDir folder) const -{ - std::vector<std::shared_ptr<const MOBase::ISaveGame>> saves; - - if (!m_def.saveExtension.isEmpty() && folder.exists()) { - QStringList filters; - filters << "*." + m_def.saveExtension; - QStringList entries = folder.entryList(filters, QDir::Files, QDir::Time); - for (const auto& entry : entries) { - saves.push_back( - std::make_shared<BasicSaveGame>(folder.filePath(entry))); - } - } - - return saves; -} - -bool BasicGamePlugin::isInstalled() const -{ - return m_installed; -} - -QIcon BasicGamePlugin::gameIcon() const -{ - return MOBase::iconForExecutable( - gameDirectory().absoluteFilePath(binaryName())); -} - -QDir BasicGamePlugin::gameDirectory() const -{ - return QDir(m_gameDir); -} - -QDir BasicGamePlugin::dataDirectory() const -{ - QString dataDir = resolveVariables(m_def.dataDirectory); - if (dataDir.isEmpty()) { - return gameDirectory(); - } - QDir dir(dataDir); - if (dir.isAbsolute()) { - return dir; - } - return QDir(m_gameDir + "/" + dataDir); -} - -void BasicGamePlugin::setGamePath(const QString& path) -{ - m_gameDir = path; - m_installed = !path.isEmpty() && QDir(path).exists(); -} - -QDir BasicGamePlugin::documentsDirectory() const -{ - if (m_def.documentsDirectory.isEmpty()) { - // Default: try My Games/<gameName> then <gameName> under Documents - QString docs = - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - QDir myGames(docs + "/My Games/" + m_def.gameName); - if (myGames.exists()) - return myGames; - QDir plain(docs + "/" + m_def.gameName); - if (plain.exists()) - return plain; - return QDir(); - } - return QDir(resolveVariables(m_def.documentsDirectory)); -} - -QDir BasicGamePlugin::savesDirectory() const -{ - if (m_def.savesDirectory.isEmpty()) { - return documentsDirectory(); - } - return QDir(resolveVariables(m_def.savesDirectory)); -} - -QList<MOBase::ExecutableInfo> BasicGamePlugin::executables() const -{ - QList<MOBase::ExecutableInfo> list; - QDir dir = gameDirectory(); - QFileInfo binary(dir.filePath(m_def.binaryName)); - if (binary.exists()) { - list.append(MOBase::ExecutableInfo(m_def.gameName, binary)); - } - if (!m_def.launcherName.isEmpty()) { - QFileInfo launcher(dir.filePath(m_def.launcherName)); - if (launcher.exists()) { - list.append(MOBase::ExecutableInfo(m_def.gameName + " Launcher", launcher)); - } - } - return list; -} - -QList<MOBase::ExecutableForcedLoadSetting> -BasicGamePlugin::executableForcedLoads() const -{ - return {}; -} - -QString BasicGamePlugin::steamAPPId() const -{ - if (!m_def.steamAppIds.isEmpty()) { - return QString::number(m_def.steamAppIds.first()); - } - return ""; -} - -QStringList BasicGamePlugin::primaryPlugins() const -{ - return m_def.primaryPlugins; -} - -QStringList BasicGamePlugin::gameVariants() const -{ - return {}; -} - -void BasicGamePlugin::setGameVariant(const QString&) {} - -QString BasicGamePlugin::binaryName() const -{ - return m_def.binaryName; -} - -QString BasicGamePlugin::gameShortName() const -{ - return m_def.gameShortName; -} - -QStringList BasicGamePlugin::validShortNames() const -{ - return m_def.validShortNames; -} - -QString BasicGamePlugin::gameNexusName() const -{ - return m_def.gameNexusName; -} - -QStringList BasicGamePlugin::iniFiles() const -{ - QStringList resolved; - for (const auto& ini : m_def.iniFiles) { - resolved.append(resolveVariables(ini)); - } - return resolved; -} - -QStringList BasicGamePlugin::DLCPlugins() const -{ - return m_def.dlcPlugins; -} - -MOBase::IPluginGame::LoadOrderMechanism -BasicGamePlugin::loadOrderMechanism() const -{ - return m_def.loadOrderMechanism; -} - -MOBase::IPluginGame::SortMechanism BasicGamePlugin::sortMechanism() const -{ - return m_def.sortMechanism; -} - -int BasicGamePlugin::nexusGameID() const -{ - return m_def.nexusGameId; -} - -bool BasicGamePlugin::looksValid(QDir const& dir) const -{ - // Primary check: binary at game root. - // Use QFileInfo with the absolute path directly — QDir::exists() with - // relative paths containing subdirectories can have edge-case issues on - // some filesystems / Qt builds. - const QString absPath = dir.absoluteFilePath(m_def.binaryName); - if (QFileInfo::exists(absPath)) { - return true; - } - - // Case-insensitive fallback: Linux filesystems are case-sensitive but - // Steam sometimes creates directories with different casing than expected. - // Walk the path components and try case-insensitive matching. - if (m_def.binaryName.contains('/')) { - QStringList parts = QString(m_def.binaryName).replace('\\', '/').split('/'); - QString current = dir.absolutePath(); - bool found = true; - for (const QString& part : parts) { - QDir d(current); - if (d.exists(part)) { - current = d.absoluteFilePath(part); - continue; - } - // Try case-insensitive match - const QStringList entries = - d.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); - bool matched = false; - for (const QString& entry : entries) { - if (entry.compare(part, Qt::CaseInsensitive) == 0) { - current = d.absoluteFilePath(entry); - matched = true; - break; - } - } - if (!matched) { - found = false; - break; - } - } - if (found) { - MOBase::log::debug("looksValid: found '{}' via case-insensitive match in '{}'", - m_def.binaryName, dir.absolutePath()); - return true; - } - } - - // Fallback: check if the data directory exists relative to this path. - // Some UE5 games (e.g. Oblivion Remastered) have their root exe nested - // under a subdirectory even though the appmanifest installdir points one - // level up. If the unique data path resolves, it's the right directory. - if (!m_def.dataDirectory.isEmpty()) { - QString dataDir = m_def.dataDirectory; - dataDir.replace('\\', '/'); - // Only handle %GAME_PATH% here; other vars need context we don't have - if (!dataDir.contains('%') || dataDir.startsWith("%GAME_PATH%")) { - dataDir.replace("%GAME_PATH%", dir.absolutePath()); - if (!dataDir.contains('%') && QDir(dataDir).exists()) - return true; - } - } - - MOBase::log::debug("looksValid: '{}' not found in '{}'", m_def.binaryName, - dir.absolutePath()); - return false; -} - -QString BasicGamePlugin::gameVersion() const -{ - // On Linux we can't easily read PE version resources - // Return empty; MO2 will show "N/A" - return ""; -} - -QString BasicGamePlugin::getLauncherName() const -{ - return m_def.launcherName; -} - -QString BasicGamePlugin::getSupportURL() const -{ - return m_def.supportURL; -} - -QString BasicGamePlugin::resolveVariables(const QString& input) const -{ - if (input.isEmpty()) - return input; - - QString result = input; - - // Normalize backslashes to forward slashes first - result.replace('\\', '/'); - - // %DOCUMENTS% - if (result.contains("%DOCUMENTS%")) { - QString docs = - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - result.replace("%DOCUMENTS%", docs); - } - - // %USERPROFILE% - on Linux, resolve to the Wine prefix userprofile - if (result.contains("%USERPROFILE%")) { - QString userProfile; - // Try the global Fluorine prefix - QString prefixPath = - QDir::homePath() + - "/.local/share/fluorine/Prefix/pfx/drive_c/users/steamuser"; - if (QDir(prefixPath).exists()) { - userProfile = prefixPath; - } else { - // Fallback to home directory - userProfile = QDir::homePath(); - } - result.replace("%USERPROFILE%", userProfile); - } - - // %GAME_PATH% - if (result.contains("%GAME_PATH%")) { - result.replace("%GAME_PATH%", m_gameDir); - } - - // %GAME_DOCUMENTS% - if (result.contains("%GAME_DOCUMENTS%")) { - result.replace("%GAME_DOCUMENTS%", documentsDirectory().absolutePath()); - } - - return result; -} |
