aboutsummaryrefslogtreecommitdiff
path: root/libs/game_gamebryo/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/game_gamebryo/src')
-rw-r--r--libs/game_gamebryo/src/creation/CMakeLists.txt10
-rw-r--r--libs/game_gamebryo/src/creation/creationgameplugins.cpp183
-rw-r--r--libs/game_gamebryo/src/creation/creationgameplugins.h22
-rw-r--r--libs/game_gamebryo/src/creation/game_creation_en.ts12
-rw-r--r--libs/game_gamebryo/src/gamebryo/CMakeLists.txt10
-rw-r--r--libs/game_gamebryo/src/gamebryo/dummybsa.cpp192
-rw-r--r--libs/game_gamebryo/src/gamebryo/dummybsa.h59
-rw-r--r--libs/game_gamebryo/src/gamebryo/game_gamebryo_en.ts170
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.cpp133
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.h36
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryodataarchives.cpp80
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryodataarchives.h37
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryogameplugins.cpp248
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryogameplugins.h38
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.cpp142
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.h54
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.cpp76
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.h46
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.cpp116
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.h75
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryosavegame.cpp606
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryosavegame.h240
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.cpp100
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.h23
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.cpp199
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.h30
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.ui209
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.cpp46
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.h31
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.cpp51
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.h26
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamegamebryo.cpp478
-rw-r--r--libs/game_gamebryo/src/gamebryo/gamegamebryo.h151
-rw-r--r--libs/game_gamebryo/src/gamebryo/vdf_parser.h739
34 files changed, 0 insertions, 4668 deletions
diff --git a/libs/game_gamebryo/src/creation/CMakeLists.txt b/libs/game_gamebryo/src/creation/CMakeLists.txt
deleted file mode 100644
index f2dce97..0000000
--- a/libs/game_gamebryo/src/creation/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-
-add_library(game_creation STATIC)
-mo2_configure_library(game_creation
- WARNINGS OFF
- TRANSLATIONS ON
- PUBLIC_DEPENDS uibase
- PRIVATE_DEPENDS lz4)
-target_link_libraries(game_creation PUBLIC game_gamebryo)
-mo2_install_target(game_creation)
diff --git a/libs/game_gamebryo/src/creation/creationgameplugins.cpp b/libs/game_gamebryo/src/creation/creationgameplugins.cpp
deleted file mode 100644
index f5cef62..0000000
--- a/libs/game_gamebryo/src/creation/creationgameplugins.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-#include "creationgameplugins.h"
-#include <ipluginlist.h>
-#include <report.h>
-#include <safewritefile.h>
-#include <scopeguard.h>
-
-#include <QDir>
-#include <QSet>
-#include <QStringEncoder>
-#include <QStringList>
-
-using MOBase::IOrganizer;
-using MOBase::IPluginGame;
-using MOBase::IPluginList;
-using MOBase::reportError;
-using MOBase::SafeWriteFile;
-
-CreationGamePlugins::CreationGamePlugins(IOrganizer* organizer)
- : GamebryoGamePlugins(organizer)
-{}
-
-QStringList CreationGamePlugins::getLoadOrder()
-{
- QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt";
- QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt";
-
- bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() ||
- QFileInfo(loadOrderPath).lastModified() > m_LastRead;
- bool pluginsIsNew =
- !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead;
-
- if (loadOrderIsNew || !pluginsIsNew) {
- return readLoadOrderList(m_Organizer->pluginList(), loadOrderPath);
- } else {
- return readPluginList(m_Organizer->pluginList());
- }
-}
-
-void CreationGamePlugins::writePluginList(const IPluginList* pluginList,
- const QString& filePath)
-{
- SafeWriteFile file(filePath);
-
- QStringEncoder encoder(QStringConverter::Encoding::System);
-
- file->resize(0);
-
- file->write(
- encoder.encode("# This file was automatically generated by Mod Organizer.\r\n"));
-
- bool invalidFileNames = false;
- int writtenCount = 0;
-
- QStringList plugins = pluginList->pluginNames();
- std::sort(plugins.begin(), plugins.end(),
- [pluginList](const QString& lhs, const QString& rhs) {
- return pluginList->priority(lhs) < pluginList->priority(rhs);
- });
-
- QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins();
- QStringList DLCPlugins = organizer()->managedGame()->DLCPlugins();
- QSet<QString> ManagedMods =
- QSet<QString>(PrimaryPlugins.begin(), PrimaryPlugins.end());
- QSet<QString> DLCSet = QSet<QString>(DLCPlugins.begin(), DLCPlugins.end());
- ManagedMods.subtract(DLCSet);
- PrimaryPlugins.append(QList<QString>(ManagedMods.begin(), ManagedMods.end()));
-
- // TODO: do not write plugins in OFFICIAL_FILES container
- for (const QString& pluginName : plugins) {
- if (!PrimaryPlugins.contains(pluginName, Qt::CaseInsensitive)) {
- if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) {
- auto result = encoder.encode(pluginName);
- if (encoder.hasError()) {
- invalidFileNames = true;
- qCritical("invalid plugin name %s", qUtf8Printable(pluginName));
- } else {
- file->write("*");
- file->write(result);
- }
- file->write("\r\n");
- ++writtenCount;
- } else {
- auto result = encoder.encode(pluginName);
- if (encoder.hasError()) {
- invalidFileNames = true;
- qCritical("invalid plugin name %s", qUtf8Printable(pluginName));
- } else {
- file->write(result);
- }
- file->write("\r\n");
- ++writtenCount;
- }
- }
- }
-
- if (invalidFileNames) {
- reportError(QObject::tr("Some of your plugins have invalid names! These "
- "plugins can not be loaded by the game. Please see "
- "mo_interface.log for a list of affected plugins "
- "and rename them."));
- }
-
- file->commit();
-}
-
-QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList* pluginList)
-{
- const auto plugins = pluginList->pluginNames();
- const auto primaryPlugins = organizer()->managedGame()->primaryPlugins();
- QStringList loadOrder(primaryPlugins);
-
- for (const QString& pluginName : loadOrder) {
- if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) {
- pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
- }
- }
-
- QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt";
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- qWarning("%s not found", qUtf8Printable(filePath));
- return loadOrder;
- }
- ON_BLOCK_EXIT([&]() {
- file.close();
- });
-
- if (file.size() == 0) {
- // MO stores at least a header in the file. if it's completely empty the
- // file is broken
- qWarning("%s empty", qUtf8Printable(filePath));
- return loadOrder;
- }
-
- QStringList pluginsFound;
- while (!file.atEnd()) {
- QByteArray line = file.readLine();
- QString pluginName;
- if ((line.size() > 0) && (line.at(0) != '#')) {
- pluginName = QStringEncoder(QStringConverter::Encoding::System)
- .encode(line.trimmed().constData());
- }
- if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) {
- if (pluginName.startsWith('*')) {
- pluginName.remove(0, 1);
- if (pluginName.size() > 0) {
- pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
- pluginsFound.append(pluginName);
- if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) {
- loadOrder.append(pluginName);
- }
- }
- } else {
- if (pluginName.size() > 0) {
- pluginList->setState(pluginName, IPluginList::STATE_INACTIVE);
- pluginsFound.append(pluginName);
- if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) {
- loadOrder.append(pluginName);
- }
- }
- }
- } else {
- pluginName.remove(0, 1);
- pluginsFound.append(pluginName);
- }
- }
-
- file.close();
-
- // set all plugins not found inactive
- for (const auto& pluginName : plugins) {
- if (!pluginsFound.contains(pluginName, Qt::CaseInsensitive)) {
- pluginList->setState(pluginName, IPluginList::STATE_INACTIVE);
- }
- }
-
- return loadOrder;
-}
-
-bool CreationGamePlugins::lightPluginsAreSupported()
-{
- return true;
-}
diff --git a/libs/game_gamebryo/src/creation/creationgameplugins.h b/libs/game_gamebryo/src/creation/creationgameplugins.h
deleted file mode 100644
index f7afd80..0000000
--- a/libs/game_gamebryo/src/creation/creationgameplugins.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef CREATIONGAMEPLUGINS_H
-#define CREATIONGAMEPLUGINS_H
-
-#include <gamebryogameplugins.h>
-#include <imoinfo.h>
-#include <iplugingame.h>
-#include <map>
-
-class CreationGamePlugins : public GamebryoGamePlugins
-{
-public:
- CreationGamePlugins(MOBase::IOrganizer* organizer);
-
-protected:
- virtual void writePluginList(const MOBase::IPluginList* pluginList,
- const QString& filePath) override;
- virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override;
- virtual QStringList getLoadOrder() override;
- virtual bool lightPluginsAreSupported() override;
-};
-
-#endif // CREATIONGAMEPLUGINS_H
diff --git a/libs/game_gamebryo/src/creation/game_creation_en.ts b/libs/game_gamebryo/src/creation/game_creation_en.ts
deleted file mode 100644
index f217448..0000000
--- a/libs/game_gamebryo/src/creation/game_creation_en.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="en_US">
-<context>
- <name>QObject</name>
- <message>
- <location filename="creationgameplugins.cpp" line="97"/>
- <source>Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/libs/game_gamebryo/src/gamebryo/CMakeLists.txt b/libs/game_gamebryo/src/gamebryo/CMakeLists.txt
deleted file mode 100644
index cff88fc..0000000
--- a/libs/game_gamebryo/src/gamebryo/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-
-add_library(game_gamebryo STATIC)
-mo2_configure_library(game_gamebryo
- WARNINGS OFF
- TRANSLATIONS ON
- AUTOMOC ON
- PUBLIC_DEPENDS uibase
- PRIVATE_DEPENDS zlib lz4)
-mo2_install_target(game_gamebryo)
diff --git a/libs/game_gamebryo/src/gamebryo/dummybsa.cpp b/libs/game_gamebryo/src/gamebryo/dummybsa.cpp
deleted file mode 100644
index ba6f766..0000000
--- a/libs/game_gamebryo/src/gamebryo/dummybsa.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "dummybsa.h"
-#include <QFile>
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-static void writeUlong(unsigned char* buffer, int offset, unsigned long value)
-{
- union
- {
- unsigned long ulValue;
- unsigned char cValue[4];
- };
- ulValue = value;
- memcpy(buffer + offset, cValue, 4);
-}
-
-static void writeUlonglong(unsigned char* buffer, int offset, unsigned long long value)
-{
- union
- {
- unsigned long long ullValue;
- unsigned char cValue[8];
- };
- ullValue = value;
- memcpy(buffer + offset, cValue, 8);
-}
-
-static unsigned long genHashInt(const unsigned char* pos, const unsigned char* end)
-{
- unsigned long hash = 0;
- for (; pos < end; ++pos) {
- hash *= 0x1003f;
- hash += *pos;
- }
- return hash;
-}
-
-static unsigned long long genHash(const char* fileName)
-{
- char fileNameLower[MAX_PATH + 1];
- int i = 0;
- for (; i < MAX_PATH && fileName[i] != '\0'; ++i) {
- fileNameLower[i] = static_cast<char>(tolower(fileName[i]));
- if (fileNameLower[i] == '\\') {
- fileNameLower[i] = '/';
- }
- }
- fileNameLower[i] = '\0';
-
- unsigned char* fileNameLowerU = reinterpret_cast<unsigned char*>(fileNameLower);
-
- char* ext = strrchr(fileNameLower, '.');
- if (ext == nullptr) {
- ext = fileNameLower + strlen(fileNameLower);
- }
- unsigned char* extU = reinterpret_cast<unsigned char*>(ext);
-
- int length = ext - fileNameLower;
-
- unsigned long long hash = 0ULL;
-
- if (length > 0) {
- hash = *(extU - 1) | ((length > 2 ? *(ext - 2) : 0) << 8) | (length << 16) |
- (fileNameLowerU[0] << 24);
- }
-
- if (strlen(ext) > 0) {
- if (strcmp(ext + 1, "kf") == 0) {
- hash |= 0x80;
- } else if (strcmp(ext + 1, "nif") == 0) {
- hash |= 0x8000;
- } else if (strcmp(ext + 1, "dds") == 0) {
- hash |= 0x8080;
- } else if (strcmp(ext + 1, "wav") == 0) {
- hash |= 0x80000000;
- }
-
- unsigned long long temp =
- static_cast<unsigned long long>(genHashInt(fileNameLowerU + 1, extU - 2));
- temp += static_cast<unsigned long long>(genHashInt(extU, extU + strlen(ext)));
-
- hash |= (temp & 0xFFFFFFFF) << 32;
- }
- return hash;
-}
-
-DummyBSA::DummyBSA(unsigned long bsaVersion)
- : m_Version(bsaVersion), m_FolderName(""), m_FileName("dummy.dds"),
- m_TotalFileNameLength(0)
-{}
-
-void DummyBSA::writeHeader(QFile& file)
-{
- unsigned char header[] = {
- 'B', 'S', 'A', '\0', // magic string
- 0xDE, 0xAD, 0xBE, 0xEF, // version - insert later
- 0x24, 0x00, 0x00, 0x00, // offset to folder recors. header size is static
- 0xDE, 0xAD, 0xBE, 0xEF, // archive flags - insert later
- 0x01, 0x00, 0x00, 0x00, // folder count
- 0x01, 0x00, 0x00, 0x00, // file count
- 0xDE, 0xAD, 0xBE, 0xEF, // total folder names length - insert later
- 0xDE, 0xAD, 0xBE, 0xEF, // total file names length - insert later
- 0xDE, 0xAD, 0xBE, 0xEF // file flags - insert later
- };
-
- writeUlong(header, 4, m_Version);
- writeUlong(header, 12, 0x01 | 0x02); // has directories and has files.
- writeUlong(header, 24,
- static_cast<unsigned long>(m_FolderName.length()) +
- 1); // empty folder name
- writeUlong(header, 28, m_TotalFileNameLength); // single character file name
-
- writeUlong(header, 32, 2); // has dds
-
- file.write(reinterpret_cast<char*>(header), sizeof(header));
-}
-
-void DummyBSA::writeFolderRecord(QFile& file, const std::string& folderName)
-{
- unsigned char folderRecord[] = {
- 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // folder hash
- 0x01, 0x00, 0x00, 0x00, // file count
- 0xDE, 0xAD, 0xBE, 0xEF, // offset to folder name
- };
- // we'd usually have to sort folders be the hash value generated here
- writeUlonglong(folderRecord, 0, genHash(folderName.c_str()));
- writeUlong(folderRecord, 12,
- 0x34 + m_TotalFileNameLength); // TODO: this should be calculated properly
-
- file.write(reinterpret_cast<char*>(folderRecord), sizeof(folderRecord));
-}
-
-void DummyBSA::writeFileRecord(QFile& file, const std::string& fileName)
-{
- unsigned char fileRecord[] = {
- 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // file name hash
- 0xDE, 0xAD, 0xBE, 0xEF, // size
- 0xDE, 0xAD, 0xBE, 0xEF, // offset to file data
- };
-
- // we'd usually have to sort files by the value generated here
- writeUlonglong(fileRecord, 0, genHash(fileName.c_str()));
- writeUlong(fileRecord, 8, 0);
- writeUlong(
- fileRecord, 12,
- 0x44 + static_cast<unsigned long>(fileName.length() + 1) +
- 4); // after this record we expect the filename and 4 bytes of file size
-
- file.write(reinterpret_cast<char*>(fileRecord), sizeof(fileRecord));
-}
-
-void DummyBSA::writeFileRecordBlocks(QFile& file, const std::string& folderName)
-{
- file.write(folderName.c_str(), folderName.length() + 1);
-
- writeFileRecord(file, m_FileName);
-}
-
-void DummyBSA::write(const QString& fileName)
-{
- QFile file(fileName);
- file.open(QIODevice::WriteOnly);
-
- m_TotalFileNameLength = static_cast<unsigned long>(m_FileName.length() + 1);
-
- writeHeader(file);
- writeFolderRecord(file, m_FolderName);
- writeFileRecordBlocks(file, m_FolderName);
- file.write(m_FileName.c_str(), m_FileName.length() + 1);
- char fileSize[] = {0x00, 0x00, 0x00, 0x00};
- file.write(fileSize, sizeof(fileSize));
- file.close();
-}
diff --git a/libs/game_gamebryo/src/gamebryo/dummybsa.h b/libs/game_gamebryo/src/gamebryo/dummybsa.h
deleted file mode 100644
index 8ea071b..0000000
--- a/libs/game_gamebryo/src/gamebryo/dummybsa.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DUMMYBSA_H
-#define DUMMYBSA_H
-
-#include <QFile>
-#include <QString>
-
-/**
- * @brief Class for creating a dummy bsa used for archive invalidation
- **/
-class DummyBSA
-{
-
-public:
- /**
- * @brief constructor
- *
- **/
- DummyBSA(unsigned long bsaVersion);
-
- /**
- * @brief write to the specified file
- *
- * @param fileName name of the file to write to
- **/
- void write(const QString& fileName);
-
-private:
- void writeHeader(QFile& file);
- void writeFolderRecord(QFile& file, const std::string& folderName);
- void writeFileRecord(QFile& file, const std::string& fileName);
- void writeFileRecordBlocks(QFile& file, const std::string& folderName);
-
-private:
- unsigned long m_Version;
- std::string m_FolderName;
- std::string m_FileName;
- unsigned long m_TotalFileNameLength;
-};
-
-#endif // DUMMYBSA_H
diff --git a/libs/game_gamebryo/src/gamebryo/game_gamebryo_en.ts b/libs/game_gamebryo/src/gamebryo/game_gamebryo_en.ts
deleted file mode 100644
index f924131..0000000
--- a/libs/game_gamebryo/src/gamebryo/game_gamebryo_en.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="en_US">
-<context>
- <name>GamebryoModDataContent</name>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="15"/>
- <source>Plugins (ESP/ESM/ESL)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="16"/>
- <source>Optional Plugins</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="17"/>
- <source>Interface</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="18"/>
- <source>Meshes</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="19"/>
- <source>Bethesda Archive</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="20"/>
- <source>Scripts (Papyrus)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="21"/>
- <source>Script Extender Plugin</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="22"/>
- <source>Script Extender Files</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="23"/>
- <source>SkyProc Patcher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="24"/>
- <source>Sound or Music</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="25"/>
- <source>Textures</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="26"/>
- <source>MCM Configuration</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="27"/>
- <source>INI Files</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="28"/>
- <source>FaceGen Data</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryomoddatacontent.cpp" line="29"/>
- <source>ModGroup Files</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>GamebryoSaveGameInfoWidget</name>
- <message>
- <location filename="gamebryosavegameinfowidget.ui" line="39"/>
- <source>Save #</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.ui" line="51"/>
- <source>Character</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.ui" line="63"/>
- <source>Level</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.ui" line="75"/>
- <source>Location</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.ui" line="87"/>
- <source>Date</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.cpp" line="78"/>
- <source>Has Script Extender Data</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.cpp" line="83"/>
- <source>Missing ESPs</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.cpp" line="116"/>
- <location filename="gamebryosavegameinfowidget.cpp" line="154"/>
- <location filename="gamebryosavegameinfowidget.cpp" line="193"/>
- <source>None</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.cpp" line="122"/>
- <source>Missing ESHs</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegameinfowidget.cpp" line="161"/>
- <source>Missing ESLs</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <location filename="gamebryogameplugins.cpp" line="130"/>
- <source>Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegame.cpp" line="48"/>
- <source>%1, #%2, Level %3, %4</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegame.cpp" line="102"/>
- <source>failed to open %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamebryosavegame.cpp" line="112"/>
- <source>wrong file format - expected %1 got &apos;%2&apos; for %3</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamegamebryo.cpp" line="318"/>
- <source>failed to query registry path (preflight): %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="gamegamebryo.cpp" line="326"/>
- <source>failed to query registry path (read): %1</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.cpp b/libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.cpp
deleted file mode 100644
index 1b7144b..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "gamebryobsainvalidation.h"
-
-#include "dummybsa.h"
-#include "iplugingame.h"
-#include "iprofile.h"
-#include "registry.h"
-#include <imoinfo.h>
-#include <utility.h>
-
-#include <QDir>
-#include <QStringList>
-
-#include <Windows.h>
-
-GamebryoBSAInvalidation::GamebryoBSAInvalidation(MOBase::DataArchives* dataArchives,
- const QString& iniFilename,
- MOBase::IPluginGame const* game)
- : m_DataArchives(dataArchives), m_IniFileName(iniFilename), m_Game(game)
-{}
-
-bool GamebryoBSAInvalidation::isInvalidationBSA(const QString& bsaName)
-{
- static QStringList invalidation{invalidationBSAName()};
-
- for (const QString& file : invalidation) {
- if (file.compare(bsaName, Qt::CaseInsensitive) == 0) {
- return true;
- }
- }
- return false;
-}
-
-void GamebryoBSAInvalidation::deactivate(MOBase::IProfile* profile)
-{
- prepareProfile(profile);
-}
-
-void GamebryoBSAInvalidation::activate(MOBase::IProfile* profile)
-{
- prepareProfile(profile);
-}
-
-bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile* profile)
-{
- bool dirty = false;
- QString basePath = profile->localSettingsEnabled()
- ? profile->absolutePath()
- : m_Game->documentsDirectory().absolutePath();
- QString iniFilePath = basePath + "/" + m_IniFileName;
- WCHAR setting[MAX_PATH];
-
- // write bInvalidateOlderFiles = 1, if needed
- if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting,
- MAX_PATH, iniFilePath.toStdWString().c_str()) ||
- wcstol(setting, nullptr, 10) != 1) {
- dirty = true;
- if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1",
- iniFilePath.toStdWString().c_str())) {
- qWarning("failed to activate BSA invalidation in \"%s\"",
- qUtf8Printable(m_IniFileName));
- }
- }
-
- if (profile->invalidationActive(nullptr)) {
-
- // add the dummy bsa to the archive string, if needed
- QStringList archives = m_DataArchives->archives(profile);
- bool bsaInstalled = false;
- for (const QString& archive : archives) {
- if (isInvalidationBSA(archive)) {
- bsaInstalled = true;
- break;
- }
- }
- if (!bsaInstalled) {
- m_DataArchives->addArchive(profile, 0, invalidationBSAName());
- dirty = true;
- }
-
- // create the dummy bsa if necessary
- QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName());
- if (!QFile::exists(bsaFile)) {
- DummyBSA bsa(bsaVersion());
- bsa.write(bsaFile);
- dirty = true;
- }
-
- // write SInvalidationFile = "", if needed
- if (::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile",
- L"ArchiveInvalidation.txt", setting, MAX_PATH,
- iniFilePath.toStdWString().c_str()) ||
- wcscmp(setting, L"") != 0) {
- dirty = true;
- if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"",
- iniFilePath.toStdWString().c_str())) {
- qWarning("failed to activate BSA invalidation in \"%s\"",
- qUtf8Printable(m_IniFileName));
- }
- }
- } else {
-
- // remove the dummy bsa from the archive string, if needed
- QStringList archivesBefore = m_DataArchives->archives(profile);
- for (const QString& archive : archivesBefore) {
- if (isInvalidationBSA(archive)) {
- m_DataArchives->removeArchive(profile, archive);
- dirty = true;
- }
- }
-
- // delete the dummy bsa, if needed
- QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName());
- if (QFile::exists(bsaFile)) {
- MOBase::shellDeleteQuiet(bsaFile);
- dirty = true;
- }
-
- // write SInvalidationFile = "ArchiveInvalidation.txt", if needed
- if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", setting,
- MAX_PATH, iniFilePath.toStdWString().c_str()) ||
- wcscmp(setting, L"ArchiveInvalidation.txt") != 0) {
- dirty = true;
- if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile",
- L"ArchiveInvalidation.txt",
- iniFilePath.toStdWString().c_str())) {
- qWarning("failed to activate BSA invalidation in \"%s\"",
- qUtf8Printable(m_IniFileName));
- }
- }
- }
-
- return dirty;
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.h b/libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.h
deleted file mode 100644
index efd3d7b..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryobsainvalidation.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef GAMEBRYOBSAINVALIDATION_H
-#define GAMEBRYOBSAINVALIDATION_H
-
-#include <QString>
-#include <bsainvalidation.h>
-#include <dataarchives.h>
-#include <memory>
-
-namespace MOBase
-{
-class IPluginGame;
-}
-
-class GamebryoBSAInvalidation : public MOBase::BSAInvalidation
-{
-public:
- GamebryoBSAInvalidation(MOBase::DataArchives* dataArchives,
- const QString& iniFilename, MOBase::IPluginGame const* game);
-
- virtual bool isInvalidationBSA(const QString& bsaName) override;
- virtual void deactivate(MOBase::IProfile* profile) override;
- virtual void activate(MOBase::IProfile* profile) override;
- virtual bool prepareProfile(MOBase::IProfile* profile) override;
-
-private:
- virtual QString invalidationBSAName() const = 0;
- virtual unsigned long
- bsaVersion() const = 0; // 0x67 for oblivion, 0x68 for everything else
-
-private:
- MOBase::DataArchives* m_DataArchives;
- QString m_IniFileName;
- MOBase::IPluginGame const* m_Game;
-};
-
-#endif // GAMEBRYOBSAINVALIDATION_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryodataarchives.cpp b/libs/game_gamebryo/src/gamebryo/gamebryodataarchives.cpp
deleted file mode 100644
index 3dcba8a..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryodataarchives.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "gamebryodataarchives.h"
-
-#include <Windows.h>
-
-#include <registry.h>
-#include <utility.h>
-
-#include "gamegamebryo.h"
-
-GamebryoDataArchives::GamebryoDataArchives(const GameGamebryo* game) : m_Game{game} {}
-
-QDir GamebryoDataArchives::gameDirectory() const
-{
- return QDir(m_Game->gameDirectory()).absolutePath();
-}
-
-QDir GamebryoDataArchives::localGameDirectory() const
-{
- return QDir(m_Game->myGamesPath()).absolutePath();
-}
-
-QStringList GamebryoDataArchives::getArchivesFromKey(const QString& iniFile,
- const QString& key,
- const int size) const
-{
- wchar_t* buffer = new wchar_t[size];
- QStringList result;
- std::wstring iniFileW = QDir::toNativeSeparators(iniFile).toStdWString();
-
- // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a
- // fail since the return value has a different meaning (number of bytes copied).
- // HOWEVER, it will not set errno to 0 if NO error occured
- errno = 0;
-
- if (::GetPrivateProfileStringW(L"Archive", key.toStdWString().c_str(), L"", buffer,
- size, iniFileW.c_str()) != 0) {
- result.append(QString::fromStdWString(buffer).split(','));
- }
-
- for (int i = 0; i < result.count(); ++i) {
- result[i] = result[i].trimmed();
- }
- delete[] buffer;
- return result;
-}
-
-void GamebryoDataArchives::setArchivesToKey(const QString& iniFile, const QString& key,
- const QString& value)
-{
- if (!MOBase::WriteRegistryValue(L"Archive", key.toStdWString().c_str(),
- value.toStdWString().c_str(),
- iniFile.toStdWString().c_str())) {
- qWarning("failed to set archives in \"%s\"", qUtf8Printable(iniFile));
- }
-}
-
-void GamebryoDataArchives::addArchive(MOBase::IProfile* profile, int index,
- const QString& archiveName)
-{
- QStringList current = archives(profile);
- if (current.contains(archiveName, Qt::CaseInsensitive)) {
- return;
- }
-
- current.insert(index != INT_MAX ? index : current.size(), archiveName);
-
- writeArchiveList(profile, current);
-}
-
-void GamebryoDataArchives::removeArchive(MOBase::IProfile* profile,
- const QString& archiveName)
-{
- QStringList current = archives(profile);
- if (!current.contains(archiveName, Qt::CaseInsensitive)) {
- return;
- }
- current.removeAll(archiveName);
-
- writeArchiveList(profile, current);
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryodataarchives.h b/libs/game_gamebryo/src/gamebryo/gamebryodataarchives.h
deleted file mode 100644
index 13f4130..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryodataarchives.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef GAMEBRYODATAARCHIVES_H
-#define GAMEBRYODATAARCHIVES_H
-
-#include <QDir>
-
-#include "dataarchives.h"
-
-class GameGamebryo;
-
-class GamebryoDataArchives : public MOBase::DataArchives
-{
-
-public:
- GamebryoDataArchives(const GameGamebryo* game);
-
- virtual void addArchive(MOBase::IProfile* profile, int index,
- const QString& archiveName) override;
- virtual void removeArchive(MOBase::IProfile* profile,
- const QString& archiveName) override;
-
-protected:
- QDir gameDirectory() const;
- QDir localGameDirectory() const;
-
- QStringList getArchivesFromKey(const QString& iniFile, const QString& key,
- int size = 256) const;
- void setArchivesToKey(const QString& iniFile, const QString& key,
- const QString& value);
-
-private:
- const GameGamebryo* m_Game;
-
- virtual void writeArchiveList(MOBase::IProfile* profile,
- const QStringList& before) = 0;
-};
-
-#endif // GAMEBRYODATAARCHIVES_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryogameplugins.cpp b/libs/game_gamebryo/src/gamebryo/gamebryogameplugins.cpp
deleted file mode 100644
index 83ad50f..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryogameplugins.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-#include "gamebryogameplugins.h"
-#include <imodinterface.h>
-#include <iplugingame.h>
-#include <ipluginlist.h>
-#include <report.h>
-#include <safewritefile.h>
-#include <scopeguard.h>
-#include <utility.h>
-
-#include <QDateTime>
-#include <QDir>
-#include <QString>
-#include <QStringEncoder>
-#include <QStringList>
-
-using MOBase::IOrganizer;
-using MOBase::IPluginList;
-using MOBase::reportError;
-using MOBase::SafeWriteFile;
-
-GamebryoGamePlugins::GamebryoGamePlugins(IOrganizer* organizer) : m_Organizer(organizer)
-{}
-
-void GamebryoGamePlugins::writePluginLists(const IPluginList* pluginList)
-{
- if (!m_LastRead.isValid()) {
- // attempt to write uninitialized plugin lists
- return;
- }
-
- writePluginList(pluginList, m_Organizer->profile()->absolutePath() + "/plugins.txt");
- writeLoadOrderList(pluginList,
- m_Organizer->profile()->absolutePath() + "/loadorder.txt");
-
- m_LastRead = QDateTime::currentDateTime();
-}
-
-void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList* pluginList)
-{
- QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt";
- QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt";
-
- bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() ||
- QFileInfo(loadOrderPath).lastModified() > m_LastRead;
- bool pluginsIsNew =
- !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead;
-
- if (loadOrderIsNew || !pluginsIsNew) {
- // read both files if they are both new or both older than the last read
- QStringList loadOrder = readLoadOrderList(pluginList, loadOrderPath);
- pluginList->setLoadOrder(loadOrder);
- readPluginList(pluginList);
- } else {
- // If the plugins is new but not loadorder, we must reparse the load order from the
- // plugin files
- QStringList loadOrder = readPluginList(pluginList);
- pluginList->setLoadOrder(loadOrder);
- }
-
- m_LastRead = QDateTime::currentDateTime();
-}
-
-QStringList GamebryoGamePlugins::getLoadOrder()
-{
- QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt";
- QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt";
-
- bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() ||
- QFileInfo(loadOrderPath).lastModified() > m_LastRead;
- bool pluginsIsNew =
- !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead;
-
- if (loadOrderIsNew || !pluginsIsNew) {
- return readLoadOrderList(m_Organizer->pluginList(), loadOrderPath);
- } else {
- return readPluginList(m_Organizer->pluginList());
- }
-}
-
-void GamebryoGamePlugins::writePluginList(const MOBase::IPluginList* pluginList,
- const QString& filePath)
-{
- return writeList(pluginList, filePath, false);
-}
-
-void GamebryoGamePlugins::writeLoadOrderList(const MOBase::IPluginList* pluginList,
- const QString& filePath)
-{
- return writeList(pluginList, filePath, true);
-}
-
-void GamebryoGamePlugins::writeList(const IPluginList* pluginList,
- const QString& filePath, bool loadOrder)
-{
- SafeWriteFile file(filePath);
-
- QStringEncoder encoder = loadOrder
- ? QStringEncoder(QStringConverter::Encoding::Utf8)
- : QStringEncoder(QStringConverter::Encoding::System);
-
- file->resize(0);
-
- file->write(
- encoder.encode("# This file was automatically generated by Mod Organizer.\r\n"));
-
- bool invalidFileNames = false;
- int writtenCount = 0;
-
- QStringList plugins = pluginList->pluginNames();
- std::sort(plugins.begin(), plugins.end(),
- [pluginList](const QString& lhs, const QString& rhs) {
- return pluginList->priority(lhs) < pluginList->priority(rhs);
- });
-
- for (const QString& pluginName : plugins) {
- if (loadOrder || (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) {
- auto result = encoder.encode(pluginName);
- if (encoder.hasError()) {
- invalidFileNames = true;
- qCritical("invalid plugin name %s", qUtf8Printable(pluginName));
- } else {
- file->write(result);
- }
- file->write("\r\n");
- ++writtenCount;
- }
- }
-
- if (invalidFileNames) {
- reportError(QObject::tr("Some of your plugins have invalid names! These "
- "plugins can not be loaded by the game. Please see "
- "mo_interface.log for a list of affected plugins "
- "and rename them."));
- }
-
- if (writtenCount == 0) {
- qWarning("plugin list would be empty, this is almost certainly wrong. Not "
- "saving.");
- } else {
- file->commit();
- }
-}
-
-QStringList GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList* pluginList,
- const QString& filePath)
-{
- QStringList pluginNames = organizer()->managedGame()->primaryPlugins();
-
- std::set<QString> pluginLookup;
- for (auto&& name : pluginNames) {
- pluginLookup.insert(name.toLower());
- }
-
- const auto b = MOBase::forEachLineInFile(filePath, [&](QString s) {
- if (!pluginLookup.contains(s.toLower())) {
- pluginLookup.insert(s);
- pluginNames.push_back(std::move(s));
- }
- });
-
- if (!b) {
- return readPluginList(pluginList);
- }
-
- return pluginNames;
-}
-
-QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList* pluginList)
-{
- QStringList primary = organizer()->managedGame()->primaryPlugins();
- for (const QString& pluginName : primary) {
- if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) {
- pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
- }
- }
- QStringList plugins = pluginList->pluginNames();
- QStringList pluginsClone(plugins);
- // Do not sort the primary plugins. Their load order should be locked as defined in
- // "primaryPlugins".
- for (const auto& plugin : pluginsClone) {
- if (primary.contains(plugin, Qt::CaseInsensitive))
- plugins.removeAll(plugin);
- }
-
- // Always use filetime loadorder to get the actual load order
- std::sort(plugins.begin(), plugins.end(),
- [&](const QString& lhs, const QString& rhs) {
- MOBase::IModInterface* lhm =
- organizer()->modList()->getMod(pluginList->origin(lhs));
- MOBase::IModInterface* rhm =
- organizer()->modList()->getMod(pluginList->origin(rhs));
- QDir lhd = organizer()->managedGame()->dataDirectory();
- QDir rhd = organizer()->managedGame()->dataDirectory();
- if (lhm != nullptr)
- lhd = lhm->absolutePath();
- if (rhm != nullptr)
- rhd = rhm->absolutePath();
- QString lhp = lhd.absoluteFilePath(lhs);
- QString rhp = rhd.absoluteFilePath(rhs);
- return QFileInfo(lhp).lastModified() < QFileInfo(rhp).lastModified();
- });
-
- // Determine plugin active state by the plugins.txt file.
- bool pluginsTxtExists = true;
- QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt";
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- pluginsTxtExists = false;
- }
- ON_BLOCK_EXIT([&]() {
- file.close();
- });
-
- if (file.size() == 0) {
- // MO stores at least a header in the file. if it's completely empty the
- // file is broken
- pluginsTxtExists = false;
- }
-
- QStringList activePlugins;
- QStringList inactivePlugins;
- if (pluginsTxtExists) {
- while (!file.atEnd()) {
- QByteArray line = file.readLine();
- QString pluginName;
- if ((line.size() > 0) && (line.at(0) != '#')) {
- QStringEncoder encoder(QStringConverter::Encoding::System);
- pluginName = encoder.encode(line.trimmed().constData());
- }
- if (pluginName.size() > 0) {
- pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
- activePlugins.push_back(pluginName);
- }
- }
-
- for (const auto& pluginName : plugins) {
- if (!activePlugins.contains(pluginName, Qt::CaseInsensitive)) {
- pluginList->setState(pluginName, IPluginList::STATE_INACTIVE);
- }
- }
- } else {
- for (const QString& pluginName : plugins) {
- pluginList->setState(pluginName, IPluginList::STATE_INACTIVE);
- }
- }
-
- return primary + plugins;
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryogameplugins.h b/libs/game_gamebryo/src/gamebryo/gamebryogameplugins.h
deleted file mode 100644
index ca70c75..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryogameplugins.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef GAMEBRYOGAMEPLUGINS_H
-#define GAMEBRYOGAMEPLUGINS_H
-
-#include <QDateTime>
-#include <QStringList>
-#include <gameplugins.h>
-#include <imoinfo.h>
-
-class GamebryoGamePlugins : public MOBase::GamePlugins
-{
-public:
- GamebryoGamePlugins(MOBase::IOrganizer* organizer);
-
- virtual void writePluginLists(const MOBase::IPluginList* pluginList) override;
- virtual void readPluginLists(MOBase::IPluginList* pluginList) override;
- virtual QStringList getLoadOrder() override;
-
-protected:
- MOBase::IOrganizer* organizer() const { return m_Organizer; }
-
- virtual void writePluginList(const MOBase::IPluginList* pluginList,
- const QString& filePath);
- virtual void writeLoadOrderList(const MOBase::IPluginList* pluginList,
- const QString& filePath);
- virtual QStringList readLoadOrderList(MOBase::IPluginList* pluginList,
- const QString& filePath);
- virtual QStringList readPluginList(MOBase::IPluginList* pluginList);
-
-protected:
- MOBase::IOrganizer* m_Organizer;
- QDateTime m_LastRead;
-
-private:
- void writeList(const MOBase::IPluginList* pluginList, const QString& filePath,
- bool loadOrder);
-};
-
-#endif // GAMEBRYOGAMEPLUGINS_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.cpp b/libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.cpp
deleted file mode 100644
index d0cc2ef..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 3 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#include "gamebryolocalsavegames.h"
-#include "registry.h"
-#include <QtDebug>
-#include <iprofile.h>
-#include <stddef.h>
-#include <string>
-#include <windows.h>
-
-#include "gamegamebryo.h"
-
-GamebryoLocalSavegames::GamebryoLocalSavegames(const GameGamebryo* game,
- const QString& iniFileName)
- : m_Game{game}, m_IniFileName(iniFileName)
-{}
-
-MappingType GamebryoLocalSavegames::mappings(const QDir& profileSaveDir) const
-{
- return {{profileSaveDir.absolutePath(), localSavesDirectory().absolutePath(), true,
- true}};
-}
-
-QString GamebryoLocalSavegames::localSavesDummy() const
-{
- return "__MO_Saves\\";
-}
-
-QDir GamebryoLocalSavegames::localSavesDirectory() const
-{
- QString dummy = localSavesDummy();
- dummy.replace("\\", "/");
- return QDir(m_Game->myGamesPath()).absoluteFilePath(dummy);
-}
-
-QDir GamebryoLocalSavegames::localGameDirectory() const
-{
- return QDir(m_Game->myGamesPath()).absolutePath();
-}
-
-bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile)
-{
- bool enable = profile->localSavesEnabled();
-
- QString basePath = profile->localSettingsEnabled()
- ? profile->absolutePath()
- : localGameDirectory().absolutePath();
- QString iniFilePath = basePath + "/" + m_IniFileName;
- QString saveIni = profile->absolutePath() + "/" + "savepath.ini";
-
- // Get the current sLocalSavePath
- WCHAR currentPath[MAX_PATH];
- GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath,
- MAX_PATH, iniFilePath.toStdWString().c_str());
- bool alreadyEnabled =
- wcscmp(currentPath, localSavesDummy().toStdWString().c_str()) == 0;
-
- // Get the current bUseMyGamesDirectory
- WCHAR currentMyGames[MAX_PATH];
- GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME",
- currentMyGames, MAX_PATH,
- iniFilePath.toStdWString().c_str());
-
- // Create the __MO_Saves directory if local saves are enabled and it doesn't exist
- if (enable) {
- QDir saves = localSavesDirectory();
- if (!saves.exists()) {
- saves.mkdir(".");
- }
- }
-
- // Set the path to __MO_Saves if it's not already
- if (enable && !alreadyEnabled) {
- // If the path is not blank, save it to savepath.ini
- if (wcscmp(currentPath, L"SKIP_ME") != 0) {
- MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath,
- saveIni.toStdWString().c_str());
- }
- if (wcscmp(currentMyGames, L"SKIP_ME") != 0) {
- MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames,
- saveIni.toStdWString().c_str());
- }
- MOBase::WriteRegistryValue(L"General", L"sLocalSavePath",
- localSavesDummy().toStdWString().c_str(),
- iniFilePath.toStdWString().c_str());
- MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1",
- iniFilePath.toStdWString().c_str());
- }
-
- // Get rid of the local saves setting if it's still there
- if (!enable && alreadyEnabled) {
- // If savepath.ini exists, use it and delete it
- if (QFile::exists(saveIni)) {
- WCHAR savedPath[MAX_PATH];
- WCHAR savedMyGames[MAX_PATH];
- GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath,
- MAX_PATH, saveIni.toStdWString().c_str());
- GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME",
- savedMyGames, MAX_PATH, saveIni.toStdWString().c_str());
- if (wcscmp(savedPath, L"DELETE_ME") != 0) {
- MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath,
- iniFilePath.toStdWString().c_str());
- } else {
- MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL,
- iniFilePath.toStdWString().c_str());
- }
- if (wcscmp(savedMyGames, L"DELETE_ME") != 0) {
- MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames,
- iniFilePath.toStdWString().c_str());
- } else {
- MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL,
- iniFilePath.toStdWString().c_str());
- }
- QFile::remove(saveIni);
- }
- // Otherwise just delete the setting
- else {
- MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL,
- iniFilePath.toStdWString().c_str());
- MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL,
- iniFilePath.toStdWString().c_str());
- }
- }
-
- return enable != alreadyEnabled;
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.h b/libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.h
deleted file mode 100644
index e5f2a92..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryolocalsavegames.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 3 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#ifndef GAMEBRYOLOCALSAVEGAMES_H
-#define GAMEBRYOLOCALSAVEGAMES_H
-
-#include <localsavegames.h>
-
-#include <QDir>
-#include <QString>
-
-class GameGamebryo;
-
-class GamebryoLocalSavegames : public MOBase::LocalSavegames
-{
-
-public:
- GamebryoLocalSavegames(const GameGamebryo* game, const QString& iniFileName);
-
- virtual MappingType mappings(const QDir& profileSaveDir) const override;
- virtual bool prepareProfile(MOBase::IProfile* profile) override;
-
-protected:
- // return the path from the local game directory to the local saves folder
- //
- // this is virtual so game plugins for complete game overhauld (Enderal, Nehrim, etc.)
- // can override it properly
- //
- virtual QString localSavesDummy() const;
-
- QDir localSavesDirectory() const;
- QDir localGameDirectory() const;
-
-private:
- const GameGamebryo* m_Game;
- QString m_IniFileName;
-};
-
-#endif // GAMEBRYOLOCALSAVEGAMES_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.cpp b/libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.cpp
deleted file mode 100644
index b5bace6..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-#include <ifiletree.h>
-
-#include "gamebryomoddatachecker.h"
-
-/**
- * @return the list of possible folder names in data.
- */
-auto GamebryoModDataChecker::possibleFolderNames() const -> const FileNameSet&
-{
- static FileNameSet result{"fonts",
- "interface",
- "menus",
- "meshes",
- "music",
- "scripts",
- "shaders",
- "sound",
- "strings",
- "textures",
- "trees",
- "video",
- "facegen",
- "materials",
- "skse",
- "obse",
- "mwse",
- "nvse",
- "fose",
- "f4se",
- "distantlod",
- "asi",
- "SkyProc Patchers",
- "Tools",
- "MCM",
- "icons",
- "bookart",
- "distantland",
- "mits",
- "splash",
- "dllplugins",
- "CalienteTools",
- "NetScriptFramework",
- "shadersfx"};
- return result;
-}
-
-/**
- * @return the extensions of possible files in data.
- */
-auto GamebryoModDataChecker::possibleFileExtensions() const -> const FileNameSet&
-{
- static FileNameSet result{"esp", "esm", "esl", "bsa", "ba2", "modgroups", "ini"};
- return result;
-}
-
-GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game) : m_Game(game)
-{}
-
-GamebryoModDataChecker::CheckReturn GamebryoModDataChecker::dataLooksValid(
- std::shared_ptr<const MOBase::IFileTree> fileTree) const
-{
- auto& folders = possibleFolderNames();
- auto& suffixes = possibleFileExtensions();
- for (auto entry : *fileTree) {
- if (entry->isDir()) {
- if (folders.count(entry->name()) > 0) {
- return CheckReturn::VALID;
- }
- } else {
- if (suffixes.count(entry->suffix()) > 0) {
- return CheckReturn::VALID;
- }
- }
- }
- return CheckReturn::INVALID;
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.h b/libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.h
deleted file mode 100644
index e0b0733..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryomoddatachecker.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef GAMEBRYO_MODATACHECKER_H
-#define GAMEBRYO_MODATACHECKER_H
-
-#include <ifiletree.h>
-#include <moddatachecker.h>
-
-class GameGamebryo;
-
-/**
- * @brief ModDataChecker for GameBryo games that look at folder and files in the "data"
- * directory.
- *
- * The default implementation is game-agnostic and uses the list of folders and file
- * extensions that were used before the ModDataChecker feature was added. It is possible
- * to inherit the class to provide custom list of folders or filenames.
- */
-class GamebryoModDataChecker : public MOBase::ModDataChecker
-{
-public:
- /**
- * @brief Construct a new mod-data checker for GameBryo games.
- */
- GamebryoModDataChecker(const GameGamebryo* game);
-
- virtual CheckReturn
- dataLooksValid(std::shared_ptr<const MOBase::IFileTree> fileTree) const override;
-
-protected:
- GameGamebryo const* const m_Game;
-
- using FileNameSet = std::set<QString, MOBase::FileNameComparator>;
-
- const GameGamebryo* game() const { return m_Game; }
-
- /**
- * @return the list of possible folder names in data.
- */
- virtual const FileNameSet& possibleFolderNames() const;
-
- /**
- * @return the extensions of possible files in data.
- */
- virtual const FileNameSet& possibleFileExtensions() const;
-};
-
-#endif // GAMEBRYO_MODATACHECKER_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.cpp b/libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.cpp
deleted file mode 100644
index 85b66b0..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-#include "gamebryomoddatacontent.h"
-
-#include <igamefeatures.h>
-#include <scriptextender.h>
-
-GamebryoModDataContent::GamebryoModDataContent(
- MOBase::IGameFeatures const* gameFeatures)
- : m_GameFeatures(gameFeatures), m_Enabled(CONTENT_MODGROUP + 1, true)
-{}
-
-std::vector<GamebryoModDataContent::Content>
-GamebryoModDataContent::getAllContents() const
-{
- static std::vector<Content> GAMEBRYO_CONTENTS{
- {CONTENT_PLUGIN, QT_TR_NOOP("Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"},
- {CONTENT_OPTIONAL, QT_TR_NOOP("Optional Plugins"), "", true},
- {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"},
- {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"},
- {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"},
- {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"},
- {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"},
- {CONTENT_SKSE_FILES, QT_TR_NOOP("Script Extender Files"), "", true},
- {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"},
- {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"},
- {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"},
- {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"},
- {CONTENT_INI, QT_TR_NOOP("INI Files"), ":/MO/gui/content/inifile"},
- {CONTENT_FACEGEN, QT_TR_NOOP("FaceGen Data"), ":/MO/gui/content/facegen"},
- {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup Files"), ":/MO/gui/content/modgroup"}};
-
- // Copy the list of enabled contents:
- std::vector<Content> contents;
- std::copy_if(std::begin(GAMEBRYO_CONTENTS), std::end(GAMEBRYO_CONTENTS),
- std::back_inserter(contents), [this](auto e) {
- return m_Enabled[e.id()];
- });
- return contents;
-}
-
-std::vector<int> GamebryoModDataContent::getContentsFor(
- std::shared_ptr<const MOBase::IFileTree> fileTree) const
-{
- std::vector<int> contents;
-
- for (auto e : *fileTree) {
- if (e->isFile()) {
- auto suffix = e->suffix().toLower();
- if (m_Enabled[CONTENT_PLUGIN] &&
- (suffix == "esp" || suffix == "esm" || suffix == "esl")) {
- contents.push_back(CONTENT_PLUGIN);
- } else if (m_Enabled[CONTENT_BSA] && (suffix == "bsa" || suffix == "ba2")) {
- contents.push_back(CONTENT_BSA);
- } else if (m_Enabled[CONTENT_INI] && suffix == "ini" &&
- e->compare("meta.ini") != 0) {
- contents.push_back(CONTENT_INI);
- } else if (m_Enabled[CONTENT_MODGROUP] && suffix == "modgroups") {
- contents.push_back(CONTENT_MODGROUP);
- }
- } else {
- if (m_Enabled[CONTENT_TEXTURE] &&
- (e->compare("textures") == 0 || e->compare("icons") == 0 ||
- e->compare("bookart") == 0)) {
- contents.push_back(CONTENT_TEXTURE);
- } else if (m_Enabled[CONTENT_MESH] && e->compare("meshes") == 0) {
- contents.push_back(CONTENT_MESH);
- } else if (m_Enabled[CONTENT_INTERFACE] &&
- (e->compare("interface") == 0 || e->compare("menus") == 0)) {
- contents.push_back(CONTENT_INTERFACE);
- } else if (m_Enabled[CONTENT_SOUND] && e->compare("music") == 0 ||
- e->compare("sound") == 0) {
- contents.push_back(CONTENT_SOUND);
- } else if (m_Enabled[CONTENT_SCRIPT] && e->compare("scripts") == 0) {
- contents.push_back(CONTENT_SCRIPT);
- } else if (m_Enabled[CONTENT_SKYPROC] && e->compare("SkyProc Patchers") == 0) {
- contents.push_back(CONTENT_SKYPROC);
- } else if (m_Enabled[CONTENT_MCM] && e->compare("MCM") == 0) {
- contents.push_back(CONTENT_MCM);
- } else if (m_Enabled[CONTENT_OPTIONAL] && e->compare("Optional") == 0 &&
- e->astree()->size() > 0) {
- contents.push_back(CONTENT_OPTIONAL);
- }
- }
- }
-
- if (m_Enabled[CONTENT_FACEGEN]) {
- auto e1 = fileTree->findDirectory("meshes/actors/character/facegendata");
- if (e1) {
- contents.push_back(CONTENT_FACEGEN);
- } else {
- auto e2 = fileTree->findDirectory("textures/actors/character/facegendata");
- if (e2) {
- contents.push_back(CONTENT_FACEGEN);
- }
- }
- }
-
- auto extender = m_GameFeatures->gameFeature<MOBase::ScriptExtender>();
- if (extender != nullptr) {
- auto e = fileTree->findDirectory(extender->PluginPath());
- if (e) {
- if (m_Enabled[CONTENT_SKSE_FILES]) {
- contents.push_back(CONTENT_SKSE_FILES);
- }
- if (m_Enabled[CONTENT_SKSE]) {
- for (auto f : *e) {
- if (f->hasSuffix("dll")) {
- contents.push_back(CONTENT_SKSE);
- break;
- }
- }
- }
- }
- }
-
- return contents;
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.h b/libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.h
deleted file mode 100644
index be02331..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryomoddatacontent.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef GAMEBRYO_MODDATACONTENT_H
-#define GAMEBRYO_MODDATACONTENT_H
-
-#include <ifiletree.h>
-#include <moddatacontent.h>
-
-namespace MOBase
-{
-class IGameFeatures;
-}
-
-/**
- * @brief ModDataContent for GameBryo games.
- *
- */
-class GamebryoModDataContent : public MOBase::ModDataContent
-{
-protected:
- /**
- * Note: These are used to index m_Enabled so should have standard
- * enum values, not custom ones.
- */
- enum EContent
- {
- CONTENT_PLUGIN,
- CONTENT_OPTIONAL,
- CONTENT_TEXTURE,
- CONTENT_MESH,
- CONTENT_BSA,
- CONTENT_INTERFACE,
- CONTENT_SOUND,
- CONTENT_SCRIPT,
- CONTENT_SKSE,
- CONTENT_SKSE_FILES,
- CONTENT_SKYPROC,
- CONTENT_MCM,
- CONTENT_INI,
- CONTENT_FACEGEN,
- CONTENT_MODGROUP
- };
-
- /**
- * This is the first value that can be used for game-specific contents.
- */
- constexpr static auto CONTENT_NEXT_VALUE = CONTENT_MODGROUP + 1;
-
-public:
- /**
- *
- */
- GamebryoModDataContent(const MOBase::IGameFeatures* gameFeatures);
-
- /**
- * @return the list of all possible contents for the corresponding game.
- */
- virtual std::vector<Content> getAllContents() const override;
-
- /**
- * @brief Retrieve the list of contents in the given tree.
- *
- * @param fileTree The tree corresponding to the mod to retrieve contents for.
- *
- * @return the IDs of the content in the given tree.
- */
- virtual std::vector<int>
- getContentsFor(std::shared_ptr<const MOBase::IFileTree> fileTree) const override;
-
-protected:
- MOBase::IGameFeatures const* const m_GameFeatures;
-
- // List of enabled contents:
- std::vector<bool> m_Enabled;
-};
-
-#endif // GAMEBRYO_MODDATACONTENT_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryosavegame.cpp b/libs/game_gamebryo/src/gamebryo/gamebryosavegame.cpp
deleted file mode 100644
index 596b19b..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryosavegame.cpp
+++ /dev/null
@@ -1,606 +0,0 @@
-#include "gamebryosavegame.h"
-
-#include "iplugingame.h"
-#include "log.h"
-#include "scriptextender.h"
-
-#include <QDate>
-#include <QFile>
-#include <QFileInfo>
-#include <QScopedArrayPointer>
-#include <QTime>
-
-#include <Windows.h>
-#include <lz4.h>
-#include <zlib.h>
-
-#include <stdexcept>
-#include <vector>
-
-#include "gamegamebryo.h"
-#include "imoinfo.h"
-
-#define CHUNK 16384
-
-GamebryoSaveGame::GamebryoSaveGame(QString const& file, GameGamebryo const* game,
- bool const lightEnabled, bool const mediumEnabled)
- : m_FileName(file), m_CreationTime(QFileInfo(file).lastModified()), m_Game(game),
- m_MediumEnabled(mediumEnabled), m_LightEnabled(lightEnabled),
- m_DataFields([this]() {
- return fetchDataFields();
- })
-{}
-
-GamebryoSaveGame::~GamebryoSaveGame() {}
-
-QString GamebryoSaveGame::getFilepath() const
-{
- return m_FileName;
-}
-
-QDateTime GamebryoSaveGame::getCreationTime() const
-{
- return m_CreationTime;
-}
-
-QString GamebryoSaveGame::getName() const
-{
- return QObject::tr("%1, #%2, Level %3, %4")
- .arg(m_PCName)
- .arg(m_SaveNumber)
- .arg(m_PCLevel)
- .arg(m_PCLocation);
-}
-
-QString GamebryoSaveGame::getSaveGroupIdentifier() const
-{
- return m_PCName;
-}
-
-QStringList GamebryoSaveGame::allFiles() const
-{
- // This returns all valid files associated with this game
- QStringList res = {m_FileName};
- auto e = m_Game->m_Organizer->gameFeatures()->gameFeature<MOBase::ScriptExtender>();
- if (e != nullptr) {
- QFileInfo file(m_FileName);
- QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." +
- m_Game->savegameSEExtension());
- if (SEfile.exists()) {
- res.push_back(SEfile.absoluteFilePath());
- }
- }
- return res;
-}
-
-bool GamebryoSaveGame::hasScriptExtenderFile() const
-{
- QFileInfo file(m_FileName);
- QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." +
- m_Game->savegameSEExtension());
- return SEfile.exists();
-}
-
-void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const& ctime)
-{
- QDate date;
- date.setDate(ctime.wYear, ctime.wMonth, ctime.wDay);
- QTime time;
- time.setHMS(ctime.wHour, ctime.wMinute, ctime.wSecond, ctime.wMilliseconds);
-
- m_CreationTime = QDateTime(date, time, Qt::UTC);
-}
-
-GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath,
- QString const& expected)
- : m_File(filepath), m_HasFieldMarkers(false),
- m_PluginString(StringType::TYPE_WSTRING),
- m_PluginStringFormat(StringFormat::UTF8), m_NextChunk(0)
-{
- if (!m_File.open(QIODevice::ReadOnly)) {
- throw std::runtime_error(
- QObject::tr("failed to open %1").arg(filepath).toUtf8().constData());
- }
-
- std::vector<char> fileID(expected.length() + 1);
- m_File.read(fileID.data(), expected.length());
- fileID[expected.length()] = '\0';
-
- QString id(fileID.data());
- if (expected != id) {
- throw std::runtime_error(
- QObject::tr("wrong file format - expected %1 got \'%2\' for %3")
- .arg(expected)
- .arg(id)
- .arg(filepath)
- .toUtf8()
- .constData());
- }
-}
-
-void GamebryoSaveGame::FileWrapper::setHasFieldMarkers(bool state)
-{
- m_HasFieldMarkers = state;
-}
-
-void GamebryoSaveGame::FileWrapper::setPluginString(StringType type)
-{
- m_PluginString = type;
-}
-
-void GamebryoSaveGame::FileWrapper::setPluginStringFormat(StringFormat type)
-{
- m_PluginStringFormat = type;
-}
-
-void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, void* buff,
- std::size_t length)
-{
- int read = data.readRawData(static_cast<char*>(buff), static_cast<int>(length));
- bool result = true;
- if (read != length && m_CompressionType == 1) {
- bool result = readNextChunk();
- if (result) {
- read += data.readRawData(static_cast<char*>(buff) + read,
- static_cast<int>(length - read));
- }
- }
- if (read != length || !result) {
- throw std::runtime_error("unexpected end of file");
- }
-}
-
-template <typename T>
-void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, T& value)
-{
- static_assert(std::is_trivial_v<T> && std::is_standard_layout_v<T>);
- readQDataStream(data, &value, sizeof(T));
-}
-
-void GamebryoSaveGame::FileWrapper::skipQDataStream(QDataStream& data,
- std::size_t length)
-{
- int skip = data.skipRawData(static_cast<int>(length));
- bool result = true;
- if (skip != length && m_CompressionType == 1) {
- result = readNextChunk();
- if (result) {
- skip += data.skipRawData(static_cast<int>(length - skip));
- }
- }
- if (skip != length || !result) {
- throw std::runtime_error("unexpected end of file");
- }
-}
-
-template <>
-void GamebryoSaveGame::FileWrapper::read<QString>(QString& value)
-{
- if (m_CompressionType == 0) {
- unsigned short length;
- if (m_PluginString == StringType::TYPE_BSTRING ||
- m_PluginString == StringType::TYPE_BZSTRING) {
- unsigned char len;
- read(len);
- length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len;
- } else {
- read(length);
- }
-
- if (m_HasFieldMarkers) {
- skip<char>();
- }
-
- QByteArray buffer;
- buffer.resize(length);
-
- read(buffer.data(),
- m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length);
-
- if (m_PluginString == StringType::TYPE_BZSTRING)
- buffer[length - 1] = '\0';
-
- if (m_HasFieldMarkers) {
- skip<char>();
- }
-
- if (m_PluginStringFormat == StringFormat::UTF8)
- value = QString::fromUtf8(buffer.constData());
- else
- value = QString::fromLocal8Bit(buffer.constData());
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- unsigned short length;
- if (m_PluginString == StringType::TYPE_BSTRING ||
- m_PluginString == StringType::TYPE_BZSTRING) {
- unsigned char len;
- readQDataStream(*m_Data, len);
- length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len;
- } else {
- readQDataStream(*m_Data, length);
- }
-
- if (m_HasFieldMarkers) {
- skip<char>();
- }
-
- QByteArray buffer;
- buffer.resize(length);
-
- readQDataStream(*m_Data, buffer.data(),
- m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length);
-
- if (m_PluginString == StringType::TYPE_BZSTRING)
- buffer[length - 1] = '\0';
-
- if (m_HasFieldMarkers) {
- m_Data->skipRawData(1);
- }
-
- if (m_PluginStringFormat == StringFormat::UTF8)
- value = QString::fromUtf8(buffer.constData());
- else
- value = QString::fromLocal8Bit(buffer.constData());
- } else {
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
- }
-}
-
-void GamebryoSaveGame::FileWrapper::read(void* buff, std::size_t length)
-{
- int read = m_File.read(static_cast<char*>(buff), length);
- if (read != length) {
- throw std::runtime_error("unexpected end of file");
- }
-}
-
-QImage GamebryoSaveGame::FileWrapper::readImage(int scale, bool alpha)
-{
- unsigned long width;
- read(width);
- unsigned long height;
- read(height);
- return readImage(width, height, scale, alpha);
-}
-
-QImage GamebryoSaveGame::FileWrapper::readImage(unsigned long width,
- unsigned long height, int scale,
- bool alpha)
-{
- int bpp = alpha ? 4 : 3;
- QScopedArrayPointer<unsigned char> buffer(new unsigned char[width * height * bpp]);
- read(buffer.data(), width * height * bpp);
- QImage image(buffer.data(), width, height,
- alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGB888);
-
- // We need to copy the image here because QImage does not make a copy of the
- // buffer when constructed.
- if (scale != 0) {
- return image.copy().scaledToWidth(scale);
- } else {
- return image.copy();
- }
-}
-
-void GamebryoSaveGame::FileWrapper::setCompressionType(uint16_t compressionType)
-{
- m_CompressionType = compressionType;
-}
-
-void GamebryoSaveGame::FileWrapper::closeCompressedData()
-{
- if (m_CompressionType == 0) {
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- m_NextChunk = 0;
- m_UncompressedSize = 0;
- m_Data->device()->close();
- delete m_Data;
- } else
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
-}
-
-bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- return false;
- } else if (m_CompressionType == 1) {
- read(m_NextChunk);
- read(m_UncompressedSize);
- QByteArray placeholder;
- m_Data = new QDataStream(placeholder);
- bool result = readNextChunk();
- if (result)
- skipQDataStream(*m_Data, bytesToIgnore);
- return result;
- } else if (m_CompressionType == 2) {
- uint32_t uncompressedSize;
- read(uncompressedSize);
- uint32_t compressedSize;
- read(compressedSize);
- QByteArray compressed;
- compressed.resize(compressedSize);
- read(compressed.data(), compressedSize);
- QByteArray decompressed;
- decompressed.resize(uncompressedSize);
- LZ4_decompress_safe_partial(compressed.data(), decompressed.data(), compressedSize,
- uncompressedSize, uncompressedSize);
- compressed.clear();
-
- m_Data = new QDataStream(decompressed);
- skipQDataStream(*m_Data, bytesToIgnore);
-
- return true;
- } else {
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
- return false;
- }
-}
-
-bool GamebryoSaveGame::FileWrapper::readNextChunk()
-{
- uint32_t have;
- uint64_t read = 0;
- std::unique_ptr<char[]> inBuffer = std::make_unique<char[]>(CHUNK);
- std::unique_ptr<char[]> outBuffer = std::make_unique<char[]>(CHUNK);
- QByteArray finalData;
- m_Data->device()->close();
- delete m_Data;
- z_stream stream{};
- try {
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.avail_in = 0;
- stream.next_in = Z_NULL;
- if (m_NextChunk >= m_File.size() || finalData.size() == m_UncompressedSize)
- return false;
- m_File.seek(m_NextChunk);
- int zlibRet = inflateInit2(&stream, 15 + 32);
- if (zlibRet != Z_OK) {
- return false;
- }
- do {
- stream.avail_in = m_File.read(inBuffer.get(), CHUNK);
- read += stream.avail_in;
- if (!m_File.isReadable()) {
- (void)inflateEnd(&stream);
- return false;
- }
- if (stream.avail_in == 0)
- break;
- stream.next_in = reinterpret_cast<Bytef*>(inBuffer.get());
- do {
- stream.avail_out = CHUNK;
- stream.next_out = reinterpret_cast<Bytef*>(outBuffer.get());
- zlibRet = inflate(&stream, Z_NO_FLUSH);
- if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) &&
- (zlibRet != Z_BUF_ERROR)) {
- return false;
- }
- have = CHUNK - stream.avail_out;
- finalData += QByteArray::fromRawData(outBuffer.get(), have);
- } while (stream.avail_out == 0);
- read -= stream.avail_in;
- } while (zlibRet != Z_STREAM_END);
- inflateEnd(&stream);
- uint64_t remainder = (m_NextChunk + read) % 16;
- uint64_t next = m_NextChunk + read + 16 - (remainder == 0 ? 16 : remainder);
- m_NextChunk = next;
- } catch (const std::exception&) {
- inflateEnd(&stream);
- return false;
- }
- m_Data = new QDataStream(finalData);
- return true;
-}
-
-uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- uint8_t version;
- read(version);
- return version;
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- // decompression already done by readSaveGameVersion
- skipQDataStream(*m_Data, bytesToIgnore);
-
- uint8_t version;
- readQDataStream(*m_Data, version);
- return version;
-
- } else {
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
- return 0;
- }
-}
-
-uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- uint16_t size;
- read(size);
- return size;
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- // decompression already done by readSaveGameVersion
- skipQDataStream(*m_Data, bytesToIgnore);
-
- uint16_t size;
- readQDataStream(*m_Data, size);
- return size;
- } else {
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
- return 0;
- }
-}
-
-uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- uint32_t size;
- read(size);
- return size;
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- // decompression already done by readSaveGameVersion
- skipQDataStream(*m_Data, bytesToIgnore);
-
- uint32_t size;
- readQDataStream(*m_Data, size);
- return size;
- } else {
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
- return 0;
- }
-}
-
-uint64_t GamebryoSaveGame::FileWrapper::readLong(int bytesToIgnore)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- uint64_t size;
- read(size);
- return size;
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- // decompression already done by readSaveGameVersion
- skipQDataStream(*m_Data, bytesToIgnore);
-
- uint64_t size;
- readQDataStream(*m_Data, size);
- return size;
- } else {
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
- return 0;
- }
-}
-
-float_t GamebryoSaveGame::FileWrapper::readFloat(int bytesToIgnore)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- float_t value;
- read(value);
- return value;
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- // decompression already done by readSaveGameVersion
- skipQDataStream(*m_Data, bytesToIgnore);
-
- float_t value;
- readQDataStream(*m_Data, value);
- return value;
- } else {
- MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown "
- "Compressed\" with your savefile attached");
- return 0;
- }
-}
-
-QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore, int extraData,
- const QStringList& corePlugins)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- uint8_t count;
- read(count);
- return readPluginData(count, extraData, corePlugins);
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- skipQDataStream(*m_Data, bytesToIgnore);
- uint8_t count;
- readQDataStream(*m_Data, count);
- return readPluginData(count, extraData, corePlugins);
- }
- return {};
-}
-
-QStringList
-GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore, int extraData,
- const QStringList& corePlugins)
-{
- if (m_CompressionType == 0) {
- if (bytesToIgnore > 0) // Just to make certain
- skip<char>(bytesToIgnore);
- uint16_t count;
- read(count);
- return readPluginData(count, extraData, corePlugins);
- } else if (m_CompressionType == 1 || m_CompressionType == 2) {
- skipQDataStream(*m_Data, bytesToIgnore);
- uint16_t count;
- readQDataStream(*m_Data, count);
- return readPluginData(count, extraData, corePlugins);
- }
- return {};
-}
-
-QStringList
-GamebryoSaveGame::FileWrapper::readMediumPlugins(int bytesToIgnore, int extraData,
- const QStringList& corePlugins)
-{
- if (m_CompressionType != 1) {
- return {};
- } else {
- skipQDataStream(*m_Data, bytesToIgnore);
- uint32_t count;
- readQDataStream(*m_Data, count);
- return readPluginData(count, extraData, corePlugins);
- }
-}
-
-QStringList GamebryoSaveGame::FileWrapper::readPluginData(uint32_t count, int extraData,
- const QStringList corePlugins)
-{
- QStringList plugins;
- plugins.reserve(count);
- if (m_CompressionType == 0) {
- for (std::size_t i = 0; i < count; ++i) {
- QString name;
- read(name);
- plugins.push_back(name);
- }
- } else {
- for (std::size_t i = 0; i < count; ++i) {
- QString name;
- read(name);
- plugins.push_back(name);
- bool isCustomPlugin;
- if (extraData) {
- if (extraData > 1) {
- readQDataStream(*m_Data, isCustomPlugin);
- } else {
- isCustomPlugin = !corePlugins.contains(name);
- }
- if (isCustomPlugin) {
- QString creationName;
- QString creationId;
- uint16_t flagsSize;
- uint8_t isCreation;
- read(creationName);
- read(creationId);
- readQDataStream(*m_Data, flagsSize);
- skipQDataStream(*m_Data, flagsSize);
- readQDataStream(*m_Data, isCreation);
- }
- }
- }
- }
- return plugins;
-}
-
-void GamebryoSaveGame::FileWrapper::close()
-{
- m_File.close();
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryosavegame.h b/libs/game_gamebryo/src/gamebryo/gamebryosavegame.h
deleted file mode 100644
index 44d0584..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryosavegame.h
+++ /dev/null
@@ -1,240 +0,0 @@
-#ifndef GAMEBRYOSAVEGAME_H
-#define GAMEBRYOSAVEGAME_H
-
-#include "isavegame.h"
-#include "memoizedlock.h"
-
-#include <QDateTime>
-#include <QFile>
-#include <QImage>
-#include <QString>
-#include <QStringList>
-
-#include <stddef.h>
-#include <stdexcept>
-
-struct _SYSTEMTIME;
-
-namespace MOBase
-{
-class IPluginGame;
-} // namespace MOBase
-
-class GameGamebryo;
-
-class GamebryoSaveGame : public MOBase::ISaveGame
-{
-public:
- GamebryoSaveGame(QString const& file, GameGamebryo const* game,
- bool const lightEnabled = false, bool const mediumEnabled = false);
-
- virtual ~GamebryoSaveGame();
-
-public: // ISaveGame interface
- virtual QString getFilepath() const override;
- virtual QDateTime getCreationTime() const override;
- virtual QString getName() const override;
- virtual QString getSaveGroupIdentifier() const override;
- virtual QStringList allFiles() const override;
-
-public:
- bool hasScriptExtenderFile() const;
-
- // Simple getters
- virtual QString getPCName() const { return m_PCName; }
- virtual unsigned short getPCLevel() const { return m_PCLevel; }
- virtual QString getPCLocation() const { return m_PCLocation; }
- virtual unsigned long getSaveNumber() const { return m_SaveNumber; }
-
- QStringList const& getPlugins() const { return m_DataFields.value()->Plugins; }
- QStringList const& getMediumPlugins() const
- {
- return m_DataFields.value()->MediumPlugins;
- }
- QStringList const& getLightPlugins() const
- {
- return m_DataFields.value()->LightPlugins;
- }
- QImage const& getScreenshot() const { return m_DataFields.value()->Screenshot; }
-
- bool isMediumEnabled() const { return m_MediumEnabled; }
-
- bool isLightEnabled() const { return m_LightEnabled; }
-
- enum class StringType
- {
- TYPE_BZSTRING,
- TYPE_BSTRING,
- TYPE_WSTRING
- };
-
- enum class StringFormat
- {
- UTF8,
- LOCAL8BIT
- };
-
-protected:
- friend class FileWrapper;
-
- class FileWrapper
- {
- public:
- /**
- * @brief Construct the save file information.
- *
- * @param filepath The path to the save file.
- * @params expected Expecte bytes at start of file.
- *
- **/
- FileWrapper(QString const& filepath, QString const& expected);
-
- /** Set this for save games that have a marker at the end of each
- * field. Specifically fallout
- **/
- void setHasFieldMarkers(bool);
-
- /** Set bz string mode (1 byte length, null terminated)
- **/
- void setPluginString(StringType);
-
- /** Set string format (utf-8, windows local 8 bit strings)
- **/
- void setPluginStringFormat(StringFormat);
-
- template <typename T>
- void skip(int count = 1)
- {
- if (!m_File.seek(m_File.pos() + count * sizeof(T))) {
- throw std::runtime_error("unexpected end of file");
- }
- }
-
- template <typename T>
- void read(T& value)
- {
- int read = m_File.read(reinterpret_cast<char*>(&value), sizeof(T));
- if (read != sizeof(T)) {
- throw std::runtime_error("unexpected end of file");
- }
- if (m_HasFieldMarkers) {
- skip<char>();
- }
- }
-
- template <>
- void read<QString>(QString& value);
-
- void seek(unsigned long pos)
- {
- if (!m_File.seek(pos)) {
- throw std::runtime_error("unexpected end of file");
- }
- }
-
- void read(void* buff, std::size_t length);
-
- /* Reads RGB image from save
- * Assumes picture dimentions come immediately before the save
- */
- QImage readImage(int scale = 0, bool alpha = false);
-
- /* Reads RGB image from save */
- QImage readImage(unsigned long width, unsigned long height, int scale = 0,
- bool alpha = false);
-
- /* Sets the compression type. */
- void setCompressionType(uint16_t type);
-
- /* uncompress the begining of the compressed block */
- bool openCompressedData(int bytesToIgnore = 0);
-
- /* read the next compressed block */
- bool readNextChunk();
-
- /* frees the uncompressed block */
- void closeCompressedData();
-
- /* Read the save game version in the compressed block */
- uint8_t readChar(int bytesToIgnore = 0);
-
- uint16_t readShort(int bytesToIgnore = 0);
-
- uint32_t readInt(int bytesToIgnore = 0);
-
- uint64_t readLong(int bytesToIgnore = 0);
-
- float_t readFloat(int bytesToIgnore = 0);
-
- /* Read the plugin list */
- QStringList readPlugins(int bytesToIgnore = 0, int extraData = 0,
- const QStringList& corePlugins = {});
-
- /* Read the light plugin list */
- QStringList readLightPlugins(int bytesToIgnore = 0, int extraData = 0,
- const QStringList& corePlugins = {});
-
- /* Read the medium plugin list */
- QStringList readMediumPlugins(int bytesToIgnore = 0, int extraData = 0,
- const QStringList& corePlugins = {});
-
- void close();
-
- private:
- QFile m_File;
- uint64_t m_NextChunk;
- uint64_t m_UncompressedSize;
- bool m_HasFieldMarkers;
- StringType m_PluginString;
- StringFormat m_PluginStringFormat;
- QDataStream* m_Data;
- uint16_t m_CompressionType = 0;
-
- private:
- template <typename T>
- void readQDataStream(QDataStream& data, T& value);
-
- void readQDataStream(QDataStream& data, void* buff, std::size_t length);
-
- void skipQDataStream(QDataStream& data, std::size_t length);
-
- QStringList readPluginData(uint32_t count, int extraData,
- const QStringList corePlugins);
- };
-
- void setCreationTime(_SYSTEMTIME const& time);
-
- GameGamebryo const* m_Game;
- bool m_MediumEnabled;
- bool m_LightEnabled;
-
- QString m_FileName;
- QString m_PCName;
- unsigned short m_PCLevel;
- QString m_PCLocation;
- unsigned long m_SaveNumber;
- QDateTime m_CreationTime;
-
- // Those three fields are usually much slower to fetch than
- // the other, so we do not fetch them if not needed.
- //
- // This is virtual so child class can add fields if those are
- // hard to access.
- struct DataFields
- {
- QStringList Plugins;
- QStringList LightPlugins;
- QStringList MediumPlugins;
- QImage Screenshot;
-
- // We need this constructor.
- DataFields() {}
- virtual ~DataFields() {}
- };
- MOBase::MemoizedLocked<std::unique_ptr<DataFields>> m_DataFields;
-
- // Fetch the field.
- virtual std::unique_ptr<DataFields> fetchDataFields() const = 0;
-};
-
-#endif // GAMEBRYOSAVEGAME_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.cpp b/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.cpp
deleted file mode 100644
index 6d1289a..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "gamebryosavegameinfo.h"
-
-#include "gamebryosavegame.h"
-#include "gamebryosavegameinfowidget.h"
-#include "gamegamebryo.h"
-#include "imodinterface.h"
-#include "imoinfo.h"
-#include "iplugingame.h"
-#include "ipluginlist.h"
-
-#include <QDir>
-#include <QString>
-#include <QStringList>
-
-GamebryoSaveGameInfo::GamebryoSaveGameInfo(GameGamebryo const* game) : m_Game(game) {}
-
-GamebryoSaveGameInfo::~GamebryoSaveGameInfo() {}
-
-GamebryoSaveGameInfo::MissingAssets
-GamebryoSaveGameInfo::getMissingAssets(MOBase::ISaveGame const& save) const
-{
- GamebryoSaveGame const& gamebryoSave = dynamic_cast<GamebryoSaveGame const&>(save);
- MOBase::IOrganizer* organizerCore = m_Game->m_Organizer;
-
- // collect the list of missing plugins
- MissingAssets missingAssets;
-
- for (QString const& pluginName : gamebryoSave.getPlugins()) {
- switch (organizerCore->pluginList()->state(pluginName)) {
- case MOBase::IPluginList::STATE_INACTIVE:
- missingAssets[pluginName] =
- ProvidingModules{organizerCore->pluginList()->origin(pluginName)};
- break;
- case MOBase::IPluginList::STATE_MISSING:
- missingAssets[pluginName] = ProvidingModules();
- break;
- }
- }
-
- for (QString const& pluginName : gamebryoSave.getLightPlugins()) {
- switch (organizerCore->pluginList()->state(pluginName)) {
- case MOBase::IPluginList::STATE_INACTIVE:
- missingAssets[pluginName] =
- ProvidingModules{organizerCore->pluginList()->origin(pluginName)};
- break;
- case MOBase::IPluginList::STATE_MISSING:
- missingAssets[pluginName] = ProvidingModules();
- break;
- }
- }
-
- // Find out any other mods that might contain the esp/esm
- QStringList espFilter({"*.esp", "*.esl", "*.esm"});
-
- QString dataDir(organizerCore->managedGame()->dataDirectory().absolutePath());
-
- // Search normal mods. A note: This will also find mods in data.
- for (QString const& mod : organizerCore->modList()->allModsByProfilePriority()) {
- MOBase::IModInterface* modInfo = organizerCore->modList()->getMod(mod);
- QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter);
- for (QString const& esp : esps) {
- MissingAssets::iterator iter = missingAssets.find(esp);
- if (modInfo->absolutePath() == dataDir) {
- // We have to prune esps that reside in the data directory, otherwise
- // you get all the unmanaged mods listed as potential candidates for
- // enabling
- if (modInfo->name() != organizerCore->pluginList()->origin(esp)) {
- continue;
- }
- }
- if (iter != missingAssets.end()) {
- if (!iter->contains(modInfo->name())) {
- iter->push_back(modInfo->name());
- }
- }
- }
- }
-
- // search in overwrite
- {
- QDir overwriteDir(organizerCore->overwritePath());
- QStringList esps = overwriteDir.entryList(espFilter);
- for (const QString& esp : esps) {
- MissingAssets::iterator iter = missingAssets.find(esp);
- if (iter != missingAssets.end()) {
- if (!iter->contains("<overwrite>")) {
- iter->push_back("<overwrite>");
- }
- }
- }
- }
-
- return missingAssets;
-}
-
-MOBase::ISaveGameInfoWidget*
-GamebryoSaveGameInfo::getSaveGameWidget(QWidget* parent) const
-{
- return new GamebryoSaveGameInfoWidget(this, parent);
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.h b/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.h
deleted file mode 100644
index e214293..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfo.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef GAMEBRYOSAVEGAMEINFO_H
-#define GAMEBRYOSAVEGAMEINFO_H
-
-#include "savegameinfo.h"
-
-class GameGamebryo;
-
-class GamebryoSaveGameInfo : public MOBase::SaveGameInfo
-{
-public:
- GamebryoSaveGameInfo(GameGamebryo const* game);
- ~GamebryoSaveGameInfo();
-
- virtual MissingAssets getMissingAssets(MOBase::ISaveGame const& save) const override;
-
- virtual MOBase::ISaveGameInfoWidget* getSaveGameWidget(QWidget*) const override;
-
-protected:
- friend class GamebryoSaveGameInfoWidget;
- GameGamebryo const* m_Game;
-};
-
-#endif // GAMEBRYOSAVEGAMEINFO_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.cpp b/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.cpp
deleted file mode 100644
index 8c95dad..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-#include "gamebryosavegameinfowidget.h"
-#include "ui_gamebryosavegameinfowidget.h"
-
-#include "gamebryosavegame.h"
-#include "gamebryosavegameinfo.h"
-#include "gamegamebryo.h"
-#include "imoinfo.h"
-#include "ipluginlist.h"
-
-#include <QDate>
-#include <QDateTime>
-#include <QFont>
-#include <QFrame>
-#include <QLabel>
-#include <QLayout>
-#include <QLayoutItem>
-#include <QPixmap>
-#include <QString>
-#include <QStyle>
-#include <QTime>
-#include <QVBoxLayout>
-
-#include <Qt>
-#include <QtGlobal>
-
-#include <memory>
-
-GamebryoSaveGameInfoWidget::GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const* info,
- QWidget* parent)
- : MOBase::ISaveGameInfoWidget(parent), ui(new Ui::GamebryoSaveGameInfoWidget),
- m_Info(info)
-{
- ui->setupUi(this);
- this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget);
- setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) /
- qreal(255.0));
- ui->gameFrame->setStyleSheet("background-color: transparent;");
-
- QVBoxLayout* gameLayout = new QVBoxLayout();
- gameLayout->setContentsMargins(0, 0, 0, 0);
- gameLayout->setSpacing(2);
- ui->gameFrame->setLayout(gameLayout);
-}
-
-GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget()
-{
- delete ui;
-}
-
-void GamebryoSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save)
-{
- auto& gamebryoSave = dynamic_cast<GamebryoSaveGame const&>(save);
- ui->saveNumLabel->setText(QString("%1").arg(gamebryoSave.getSaveNumber()));
- ui->characterLabel->setText(gamebryoSave.getPCName());
- ui->locationLabel->setText(gamebryoSave.getPCLocation());
- ui->levelLabel->setText(QString("%1").arg(gamebryoSave.getPCLevel()));
- // This somewhat contorted code is because on my system at least, the
- // old way of doing this appears to give short date and long time.
- QDateTime t = gamebryoSave.getCreationTime().toLocalTime();
- ui->dateLabel->setText(
- QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " +
- QLocale::system().toString(t.time()));
- ui->screenshotLabel->setPixmap(QPixmap::fromImage(gamebryoSave.getScreenshot()));
- if (ui->gameFrame->layout() != nullptr) {
- QLayoutItem* item = nullptr;
- while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) {
- delete item->widget();
- delete item;
- }
- ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize);
- }
-
- // Resize box to new content
- this->resize(0, 0);
-
- QLayout* layout = ui->gameFrame->layout();
- if (gamebryoSave.hasScriptExtenderFile()) {
- QLabel* scriptExtender = new QLabel(tr("Has Script Extender Data"));
- QFont headerFont = scriptExtender->font();
- headerFont.setBold(true);
- layout->addWidget(scriptExtender);
- }
- QLabel* header = new QLabel(tr("Missing ESPs"));
- QFont headerFont = header->font();
- QFont contentFont = headerFont;
- headerFont.setItalic(true);
- contentFont.setBold(true);
- contentFont.setPointSize(7);
- header->setFont(headerFont);
- layout->addWidget(header);
- int count = 0;
- MOBase::IPluginList* pluginList = m_Info->m_Game->m_Organizer->pluginList();
- for (QString const& pluginName : gamebryoSave.getPlugins()) {
- if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) {
- continue;
- }
-
- ++count;
-
- if (count > 7) {
- break;
- }
-
- QLabel* pluginLabel = new QLabel(pluginName);
- pluginLabel->setIndent(10);
- pluginLabel->setFont(contentFont);
- layout->addWidget(pluginLabel);
- }
- if (count > 7) {
- QLabel* dotDotLabel = new QLabel("...");
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
- if (count == 0) {
- QLabel* dotDotLabel = new QLabel(tr("None"));
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
- if (gamebryoSave.isMediumEnabled()) {
- QLabel* headerEsh = new QLabel(tr("Missing ESHs"));
- QFont headerEshFont = headerEsh->font();
- QFont contentEshFont = headerEshFont;
- headerEshFont.setItalic(true);
- contentEshFont.setBold(true);
- contentEshFont.setPointSize(7);
- headerEsh->setFont(headerEshFont);
- layout->addWidget(headerEsh);
- int countEsh = 0;
- for (QString const& pluginName : gamebryoSave.getMediumPlugins()) {
- if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) {
- continue;
- }
-
- ++countEsh;
-
- if (countEsh > 7) {
- break;
- }
-
- QLabel* pluginLabel = new QLabel(pluginName);
- pluginLabel->setIndent(10);
- pluginLabel->setFont(contentFont);
- layout->addWidget(pluginLabel);
- }
- if (countEsh > 7) {
- QLabel* dotDotLabel = new QLabel("...");
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
- if (countEsh == 0) {
- QLabel* dotDotLabel = new QLabel(tr("None"));
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
- }
- if (gamebryoSave.isLightEnabled()) {
- QLabel* headerEsl = new QLabel(tr("Missing ESLs"));
- QFont headerEslFont = headerEsl->font();
- QFont contentEslFont = headerEslFont;
- headerEslFont.setItalic(true);
- contentEslFont.setBold(true);
- contentEslFont.setPointSize(7);
- headerEsl->setFont(headerEslFont);
- layout->addWidget(headerEsl);
- int countEsl = 0;
- for (QString const& pluginName : gamebryoSave.getLightPlugins()) {
- if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) {
- continue;
- }
-
- ++countEsl;
-
- if (countEsl > 7) {
- break;
- }
-
- QLabel* pluginLabel = new QLabel(pluginName);
- pluginLabel->setIndent(10);
- pluginLabel->setFont(contentFont);
- layout->addWidget(pluginLabel);
- }
- if (countEsl > 7) {
- QLabel* dotDotLabel = new QLabel("...");
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
- if (countEsl == 0) {
- QLabel* dotDotLabel = new QLabel(tr("None"));
- dotDotLabel->setIndent(10);
- dotDotLabel->setFont(contentFont);
- layout->addWidget(dotDotLabel);
- }
- }
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.h b/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.h
deleted file mode 100644
index 6642863..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef GAMEBRYOSAVEGAMEINFOWIDGET_H
-#define GAMEBRYOSAVEGAMEINFOWIDGET_H
-
-#include "isavegameinfowidget.h"
-
-#include <QObject>
-
-class GamebryoSaveGameInfo;
-
-namespace Ui
-{
-class GamebryoSaveGameInfoWidget;
-}
-
-class GamebryoSaveGameInfoWidget : public MOBase::ISaveGameInfoWidget
-{
- Q_OBJECT
-
-public:
- GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const* info, QWidget* parent);
- ~GamebryoSaveGameInfoWidget();
-
- virtual void setSave(MOBase::ISaveGame const&) override;
-
-private:
- Ui::GamebryoSaveGameInfoWidget* ui;
- GamebryoSaveGameInfo const* m_Info;
-};
-
-#endif // GAMEBRYOSAVEGAMEINFOWIDGET_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.ui b/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.ui
deleted file mode 100644
index ea45d10..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryosavegameinfowidget.ui
+++ /dev/null
@@ -1,209 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>GamebryoSaveGameInfoWidget</class>
- <widget class="QWidget" name="GamebryoSaveGameInfoWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>300</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <property name="toolTip">
- <string notr="true"/>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Save #</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Character</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_4">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Level</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_3">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Location</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_5">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Date</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="saveNumLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="characterLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="levelLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="locationLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QLabel" name="dateLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QFrame" name="gameFrame">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="screenshotLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.cpp b/libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.cpp
deleted file mode 100644
index e3f709a..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "gamebryoscriptextender.h"
-
-#include "gamegamebryo.h"
-
-#include "utility.h"
-
-#include <QDir>
-#include <QString>
-
-GamebryoScriptExtender::GamebryoScriptExtender(const GameGamebryo* game) : m_Game(game)
-{}
-
-GamebryoScriptExtender::~GamebryoScriptExtender() {}
-
-QString GamebryoScriptExtender::loaderName() const
-{
- return BinaryName();
-}
-
-QString GamebryoScriptExtender::loaderPath() const
-{
- return m_Game->gameDirectory().absoluteFilePath(loaderName());
-}
-
-QString GamebryoScriptExtender::savegameExtension() const
-{
- return m_Game->savegameSEExtension();
-}
-
-bool GamebryoScriptExtender::isInstalled() const
-{
- // A note: It is possibly also OK if xxse_steam_loader.dll exists, but it's
- // not clear why that would exist and the exe not if you'd installed it per
- // instructions, and it'd mess up NCC installs a treat.
- return m_Game->gameDirectory().exists(loaderName());
-}
-
-QString GamebryoScriptExtender::getExtenderVersion() const
-{
- return MOBase::getFileVersion(m_Game->gameDirectory().absoluteFilePath(loaderName()));
-}
-
-WORD GamebryoScriptExtender::getArch() const
-{
- return m_Game->getArch(loaderName());
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.h b/libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.h
deleted file mode 100644
index 7ab4f1d..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryoscriptextender.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef GAMEBRYOSCRIPTEXTENDER_H
-#define GAMEBRYOSCRIPTEXTENDER_H
-
-#include "scriptextender.h"
-
-class GameGamebryo;
-
-class GamebryoScriptExtender : public MOBase::ScriptExtender
-{
-public:
- GamebryoScriptExtender(GameGamebryo const* game);
-
- virtual ~GamebryoScriptExtender();
-
- virtual QString loaderName() const override;
-
- virtual QString loaderPath() const override;
-
- virtual QString savegameExtension() const override;
-
- virtual bool isInstalled() const override;
-
- virtual QString getExtenderVersion() const override;
-
- virtual WORD getArch() const override;
-
-protected:
- GameGamebryo const* const m_Game;
-};
-
-#endif // GAMEBRYOSCRIPTEXTENDER_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.cpp b/libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.cpp
deleted file mode 100644
index e5c7608..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "gamebryounmanagedmods.h"
-#include "gamegamebryo.h"
-#include <pluginsetting.h>
-
-GamebryoUnmangedMods::GamebryoUnmangedMods(const GameGamebryo* game) : m_Game(game) {}
-
-GamebryoUnmangedMods::~GamebryoUnmangedMods() {}
-
-QStringList GamebryoUnmangedMods::mods(bool onlyOfficial) const
-{
- QStringList result;
-
- QStringList dlcPlugins = m_Game->DLCPlugins();
- QStringList mainPlugins = m_Game->primaryPlugins();
-
- QDir dataDir(m_Game->dataDirectory());
- for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) {
- if (!mainPlugins.contains(fileName, Qt::CaseInsensitive) &&
- (!onlyOfficial || dlcPlugins.contains(fileName, Qt::CaseInsensitive))) {
- result.append(fileName.chopped(4)); // trims the extension off
- }
- }
-
- return result;
-}
-
-QString GamebryoUnmangedMods::displayName(const QString& modName) const
-{
- return modName;
-}
-
-QFileInfo GamebryoUnmangedMods::referenceFile(const QString& modName) const
-{
- QFileInfoList files =
- m_Game->dataDirectory().entryInfoList(QStringList() << modName + ".es*");
- if (files.size() > 0) {
- return files.at(0);
- } else {
- return QFileInfo();
- }
-}
-
-QStringList GamebryoUnmangedMods::secondaryFiles(const QString& modName) const
-{
- QStringList archives;
- QDir dataDir = m_Game->dataDirectory();
- for (const QString& archiveName : dataDir.entryList({modName + "*.bsa"})) {
- archives.append(dataDir.absoluteFilePath(archiveName));
- }
- return archives;
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.h b/libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.h
deleted file mode 100644
index 38e2ba5..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamebryounmanagedmods.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef GAMEBRYOUNMANAGEDMODS_H
-#define GAMEBRYOUNMANAGEDMODS_H
-
-#include <unmanagedmods.h>
-
-class GameGamebryo;
-
-class GamebryoUnmangedMods : public MOBase::UnmanagedMods
-{
-public:
- GamebryoUnmangedMods(const GameGamebryo* game);
- ~GamebryoUnmangedMods();
-
- virtual QStringList mods(bool onlyOfficial) const override;
- virtual QString displayName(const QString& modName) const override;
- virtual QFileInfo referenceFile(const QString& modName) const override;
- virtual QStringList secondaryFiles(const QString& modName) const override;
-
-protected:
- const GameGamebryo* game() const { return m_Game; }
-
-private:
- const GameGamebryo* m_Game;
-};
-
-#endif // GAMEBRYOUNMANAGEDMODS_H
diff --git a/libs/game_gamebryo/src/gamebryo/gamegamebryo.cpp b/libs/game_gamebryo/src/gamebryo/gamegamebryo.cpp
deleted file mode 100644
index 347c2d8..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamegamebryo.cpp
+++ /dev/null
@@ -1,478 +0,0 @@
-#include "gamegamebryo.h"
-
-#include "bsainvalidation.h"
-#include "dataarchives.h"
-#include "gamebryomoddatacontent.h"
-#include "gamebryosavegame.h"
-#include "gameplugins.h"
-#include "iprofile.h"
-#include "log.h"
-#include "registry.h"
-#include "savegameinfo.h"
-#include "scopeguard.h"
-#include "scriptextender.h"
-#include "utility.h"
-#include "vdf_parser.h"
-
-#include <QDir>
-#include <QDirIterator>
-#include <QFile>
-#include <QFileInfo>
-#include <QIcon>
-#include <QJsonDocument>
-#include <QJsonValue>
-
-#include <QtDebug>
-#include <QtGlobal>
-
-#include <Knownfolders.h>
-#include <Shlobj.h>
-#include <Windows.h>
-#include <winreg.h>
-#include <winver.h>
-
-#include <optional>
-#include <string>
-#include <vector>
-
-GameGamebryo::GameGamebryo() {}
-
-void GameGamebryo::detectGame()
-{
- m_GamePath = identifyGamePath();
- m_MyGamesPath = determineMyGamesPath(gameName());
-}
-
-bool GameGamebryo::init(MOBase::IOrganizer* moInfo)
-{
- m_Organizer = moInfo;
- m_Organizer->onAboutToRun([this](const auto& binary) {
- return prepareIni(binary);
- });
- return true;
-}
-
-bool GameGamebryo::isInstalled() const
-{
- return !m_GamePath.isEmpty();
-}
-
-QIcon GameGamebryo::gameIcon() const
-{
- return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(binaryName()));
-}
-
-QDir GameGamebryo::gameDirectory() const
-{
- return QDir(m_GamePath);
-}
-
-QDir GameGamebryo::dataDirectory() const
-{
- return gameDirectory().absoluteFilePath("data");
-}
-
-void GameGamebryo::setGamePath(const QString& path)
-{
- m_GamePath = path;
-}
-
-QDir GameGamebryo::documentsDirectory() const
-{
- return m_MyGamesPath;
-}
-
-QDir GameGamebryo::savesDirectory() const
-{
- return QDir(myGamesPath() + "/Saves");
-}
-
-std::vector<std::shared_ptr<const MOBase::ISaveGame>>
-GameGamebryo::listSaves(QDir folder) const
-{
- QStringList filters;
- filters << QString("*.") + savegameExtension();
-
- std::vector<std::shared_ptr<const MOBase::ISaveGame>> saves;
- for (auto info : folder.entryInfoList(filters, QDir::Files)) {
- try {
- saves.push_back(makeSaveGame(info.filePath()));
- } catch (std::exception& e) {
- MOBase::log::error("{}", e.what());
- continue;
- }
- }
-
- return saves;
-}
-
-void GameGamebryo::setGameVariant(const QString& variant)
-{
- m_GameVariant = variant;
-}
-
-QString GameGamebryo::binaryName() const
-{
- return gameShortName() + ".exe";
-}
-
-MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::loadOrderMechanism() const
-{
- return LoadOrderMechanism::FileTime;
-}
-
-MOBase::IPluginGame::SortMechanism GameGamebryo::sortMechanism() const
-{
- return SortMechanism::LOOT;
-}
-
-bool GameGamebryo::looksValid(QDir const& path) const
-{
- // Check for <prog>.exe for now.
- return path.exists(binaryName());
-}
-
-QString GameGamebryo::gameVersion() const
-{
- // We try the file version, but if it looks invalid (starts with the fallback
- // version), we look the product version instead. If the product version is
- // not empty, we use it.
- QString binaryAbsPath = gameDirectory().absoluteFilePath(binaryName());
- QString version = MOBase::getFileVersion(binaryAbsPath);
- if (version.startsWith(FALLBACK_GAME_VERSION)) {
- QString pversion = MOBase::getProductVersion(binaryAbsPath);
- if (!pversion.isEmpty()) {
- version = pversion;
- }
- }
- return version;
-}
-
-QString GameGamebryo::getLauncherName() const
-{
- return gameShortName() + "Launcher.exe";
-}
-
-WORD GameGamebryo::getArch(QString const& program) const
-{
- WORD arch = 0;
- // This *really* needs to be factored out
- std::wstring app_name =
- L"\\\\?\\" +
- QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program))
- .toStdWString();
-
- WIN32_FIND_DATAW FindFileData;
- HANDLE hFind = ::FindFirstFileW(app_name.c_str(), &FindFileData);
-
- // exit if the binary was not found
- if (hFind == INVALID_HANDLE_VALUE)
- return arch;
-
- HANDLE hFile = INVALID_HANDLE_VALUE;
- HANDLE hMapping = INVALID_HANDLE_VALUE;
- LPVOID addrHeader = nullptr;
- PIMAGE_NT_HEADERS peHdr = nullptr;
-
- hFile = CreateFileW(app_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
- if (hFile == INVALID_HANDLE_VALUE)
- goto cleanup;
-
- hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0,
- program.toStdWString().c_str());
- if (hMapping == INVALID_HANDLE_VALUE)
- goto cleanup;
-
- addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
- if (addrHeader == NULL)
- goto cleanup; // couldn't memory map the file
-
- peHdr = ImageNtHeader(addrHeader);
- if (peHdr == NULL)
- goto cleanup; // couldn't read the header
-
- arch = peHdr->FileHeader.Machine;
-
-cleanup: // release all of our handles
- FindClose(hFind);
- if (hFile != INVALID_HANDLE_VALUE)
- CloseHandle(hFile);
- if (hMapping != INVALID_HANDLE_VALUE)
- CloseHandle(hMapping);
- return arch;
-}
-
-QFileInfo GameGamebryo::findInGameFolder(const QString& relativePath) const
-{
- return QFileInfo(m_GamePath + "/" + relativePath);
-}
-
-QString GameGamebryo::identifyGamePath() const
-{
- QString path = "Software\\Bethesda Softworks\\" + gameShortName();
- return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(),
- L"Installed Path");
-}
-
-bool GameGamebryo::prepareIni(const QString& exec)
-{
- MOBase::IProfile* profile = m_Organizer->profile();
-
- QString basePath = profile->localSettingsEnabled()
- ? profile->absolutePath()
- : documentsDirectory().absolutePath();
-
- if (!iniFiles().isEmpty()) {
-
- QString profileIni = basePath + "/" + iniFiles()[0];
-
- WCHAR setting[512];
- if (!GetPrivateProfileStringW(L"Launcher", L"bEnableFileSelection", L"0", setting,
- 512, profileIni.toStdWString().c_str()) ||
- wcstol(setting, nullptr, 10) != 1) {
- MOBase::WriteRegistryValue(L"Launcher", L"bEnableFileSelection", L"1",
- profileIni.toStdWString().c_str());
- }
- }
-
- return true;
-}
-
-QString GameGamebryo::selectedVariant() const
-{
- return m_GameVariant;
-}
-
-QString GameGamebryo::myGamesPath() const
-{
- return m_MyGamesPath;
-}
-
-/*static*/ QString GameGamebryo::getLootPath()
-{
- return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") +
- "/Loot.exe";
-}
-
-QString GameGamebryo::localAppFolder()
-{
- QString result = getKnownFolderPath(FOLDERID_LocalAppData, false);
- if (result.isEmpty()) {
- // fallback: try the registry
- result = getSpecialPath("Local AppData");
- }
- return result;
-}
-
-void GameGamebryo::copyToProfile(QString const& sourcePath,
- QDir const& destinationDirectory,
- QString const& sourceFileName)
-{
- copyToProfile(sourcePath, destinationDirectory, sourceFileName, sourceFileName);
-}
-
-void GameGamebryo::copyToProfile(QString const& sourcePath,
- QDir const& destinationDirectory,
- QString const& sourceFileName,
- QString const& destinationFileName)
-{
- QString filePath = destinationDirectory.absoluteFilePath(destinationFileName);
- if (!QFileInfo(filePath).exists()) {
- if (!MOBase::shellCopy(sourcePath + "/" + sourceFileName, filePath)) {
- // if copy file fails, create the file empty
- QFile(filePath).open(QIODevice::WriteOnly);
- }
- }
-}
-
-MappingType GameGamebryo::mappings() const
-{
- MappingType result;
-
- for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) {
- result.push_back({m_Organizer->profilePath() + "/" + profileFile,
- localAppFolder() + "/" + gameShortName() + "/" + profileFile,
- false});
- }
-
- return result;
-}
-
-std::unique_ptr<BYTE[]> GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWSTR value,
- DWORD flags, LPDWORD type = nullptr)
-{
- DWORD size = 0;
- HKEY subKey;
- LONG res = ::RegOpenKeyExW(key, path, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey);
- if (res != ERROR_SUCCESS) {
- res = ::RegOpenKeyExW(key, path, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &subKey);
- if (res != ERROR_SUCCESS)
- return std::unique_ptr<BYTE[]>();
- }
- res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size);
- if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) {
- return std::unique_ptr<BYTE[]>();
- }
- if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
- throw MOBase::MyException(
- QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16));
- }
-
- std::unique_ptr<BYTE[]> result(new BYTE[size]);
- res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size);
-
- if (res != ERROR_SUCCESS) {
- throw MOBase::MyException(
- QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16));
- }
-
- return result;
-}
-
-QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value)
-{
- std::unique_ptr<BYTE[]> buffer =
- getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND);
-
- return QString::fromUtf16(reinterpret_cast<const ushort*>(buffer.get()));
-}
-
-QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault)
-{
- PWSTR path = nullptr;
- ON_BLOCK_EXIT([&]() {
- if (path != nullptr)
- ::CoTaskMemFree(path);
- });
-
- if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL,
- &path) == S_OK) {
- return QDir::fromNativeSeparators(QString::fromWCharArray(path));
- } else {
- return QString();
- }
-}
-
-QString GameGamebryo::getSpecialPath(const QString& name)
-{
- QString base = findInRegistry(
- HKEY_CURRENT_USER,
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
- name.toStdWString().c_str());
-
- WCHAR temp[MAX_PATH];
- if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) {
- return QString::fromWCharArray(temp);
- } else {
- return base;
- }
-}
-
-QString GameGamebryo::determineMyGamesPath(const QString& gameName)
-{
- const QString pattern = "%1/My Games/" + gameName;
-
- auto tryDir = [&](const QString& dir) -> std::optional<QString> {
- if (dir.isEmpty()) {
- return {};
- }
-
- const auto path = pattern.arg(dir);
- if (!QFileInfo(path).exists()) {
- return {};
- }
-
- return path;
- };
-
- // a) this is the way it should work. get the configured My Documents directory
- if (auto d = tryDir(getKnownFolderPath(FOLDERID_Documents, false))) {
- return *d;
- }
-
- // b) if there is no <game> directory there, look in the default directory
- if (auto d = tryDir(getKnownFolderPath(FOLDERID_Documents, true))) {
- return *d;
- }
-
- // c) finally, look in the registry. This is discouraged
- if (auto d = tryDir(getSpecialPath("Personal"))) {
- return *d;
- }
-
- return {};
-}
-
-QString GameGamebryo::parseEpicGamesLocation(const QStringList& manifests)
-{
- // Use the registry entry to find the EGL Data dir first, just in case something
- // changes
- QString manifestDir = findInRegistry(
- HKEY_LOCAL_MACHINE, L"Software\\Epic Games\\EpicGamesLauncher", L"AppDataPath");
- if (manifestDir.isEmpty())
- manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) +
- "\\Epic\\EpicGamesLauncher\\Data\\";
- manifestDir += "Manifests";
- QDir epicManifests(manifestDir, "*.item",
- QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files);
- if (epicManifests.exists()) {
- QDirIterator it(epicManifests);
- while (it.hasNext()) {
- QString manifestFile = it.next();
- QFile manifest(manifestFile);
-
- if (!manifest.open(QIODevice::ReadOnly)) {
- qWarning("Couldn't open Epic Games manifest file.");
- continue;
- }
-
- QByteArray manifestData = manifest.readAll();
-
- QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData));
-
- if (manifests.contains(manifestJson["AppName"].toString())) {
- return manifestJson["InstallLocation"].toString();
- }
- }
- }
- return "";
-}
-
-QString GameGamebryo::parseSteamLocation(const QString& appid,
- const QString& directoryName)
-{
- QString path = "Software\\Valve\\Steam";
- QString steamLocation =
- findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"SteamPath");
- if (!steamLocation.isEmpty()) {
- QString steamLibraryLocation;
- QString steamLibraries(steamLocation + "\\" + "config" + "\\" +
- "libraryfolders.vdf");
- if (QFile(steamLibraries).exists()) {
- std::ifstream file(steamLibraries.toStdString());
- auto root = tyti::vdf::read(file);
- for (auto child : root.childs) {
- tyti::vdf::object* library = child.second.get();
- auto apps = library->childs["apps"];
- if (apps->attribs.contains(appid.toStdString())) {
- steamLibraryLocation = QString::fromStdString(library->attribs["path"]);
- break;
- }
- }
- }
- if (!steamLibraryLocation.isEmpty()) {
- QString gameLocation = steamLibraryLocation + "\\" + "steamapps" + "\\" +
- "common" + "\\" + directoryName;
- if (QDir(gameLocation).exists())
- return gameLocation;
- }
- }
- return "";
-}
-
-void GameGamebryo::registerFeature(std::shared_ptr<MOBase::GameFeature> feature)
-{
- // priority does not matter, this is a game plugin so will get lowest priority in MO2
- m_Organizer->gameFeatures()->registerFeature(this, feature, 0, true);
-}
diff --git a/libs/game_gamebryo/src/gamebryo/gamegamebryo.h b/libs/game_gamebryo/src/gamebryo/gamegamebryo.h
deleted file mode 100644
index 2ff07db..0000000
--- a/libs/game_gamebryo/src/gamebryo/gamegamebryo.h
+++ /dev/null
@@ -1,151 +0,0 @@
-#ifndef GAMEGAMEBRYO_H
-#define GAMEGAMEBRYO_H
-
-#include "iplugingame.h"
-
-class BSAInvalidation;
-class DataArchives;
-class LocalSavegames;
-class SaveGameInfo;
-class BSAInvalidation;
-class LocalSavegames;
-class ScriptExtender;
-class GamePlugins;
-class UnmanagedMods;
-
-#include <QObject>
-#include <QString>
-#include <ShlObj.h>
-#include <dbghelp.h>
-#include <ipluginfilemapper.h>
-#include <iplugingame.h>
-#include <memory>
-
-#include "gamebryosavegame.h"
-#include "igamefeatures.h"
-
-class GameGamebryo : public MOBase::IPluginGame, public MOBase::IPluginFileMapper
-{
- Q_OBJECT
- Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginFileMapper)
-
- friend class GamebryoScriptExtender;
- friend class GamebryoSaveGameInfo;
- friend class GamebryoSaveGameInfoWidget;
- friend class GamebryoSaveGame;
-
- /**
- * Some Bethesda games do not have a valid file version but a valid product
- * version. If the file version starts with FALLBACK_GAME_VERSION, the product
- * version will be tried.
- */
- static constexpr const char* FALLBACK_GAME_VERSION = "1.0.0";
-
-public:
- GameGamebryo();
-
- void detectGame() override;
- bool init(MOBase::IOrganizer* moInfo) override;
-
-public: // IPluginGame interface
- // getName
- // initializeProfile
- virtual std::vector<std::shared_ptr<const MOBase::ISaveGame>>
- listSaves(QDir folder) const override;
-
- virtual bool isInstalled() const override;
- virtual QIcon gameIcon() const override;
- virtual QDir gameDirectory() const override;
- virtual QDir dataDirectory() const override;
- // secondaryDataDirectories
- virtual void setGamePath(const QString& path) override;
- virtual QDir documentsDirectory() const override;
- virtual QDir savesDirectory() const override;
- // executables
- // steamAPPId
- // primaryPlugins
- // enabledPlugins
- // gameVariants
- virtual void setGameVariant(const QString& variant) override;
- virtual QString binaryName() const override;
- // gameShortName
- // primarySources
- // validShortNames
- // iniFiles
- // DLCPlugins
- // CCPlugins
- virtual LoadOrderMechanism loadOrderMechanism() const override;
- virtual SortMechanism sortMechanism() const override;
- // nexusModOrganizerID
- // nexusGameID
- virtual bool looksValid(QDir const&) const override;
- virtual QString gameVersion() const override;
- virtual QString getLauncherName() const override;
-
-public: // IPluginFileMapper interface
- virtual MappingType mappings() const;
-
-public: // Other (e.g. for game features)
- QString myGamesPath() const;
-
-protected:
- // Retrieve the saves extension for the game.
- virtual QString savegameExtension() const = 0;
- virtual QString savegameSEExtension() const = 0;
-
- // Create a save game.
- virtual std::shared_ptr<const GamebryoSaveGame>
- makeSaveGame(QString filepath) const = 0;
-
- QFileInfo findInGameFolder(const QString& relativePath) const;
- QString selectedVariant() const;
- WORD getArch(QString const& program) const;
-
- static QString localAppFolder();
- // Arguably this shouldn't really be here but every gamebryo program seems to
- // use it
- static QString getLootPath();
-
- // This function is not terribly well named as it copies exactly where it's told
- // to, irrespective of whether it's in the profile...
- static void copyToProfile(const QString& sourcePath, const QDir& destinationDirectory,
- const QString& sourceFileName);
-
- static void copyToProfile(const QString& sourcePath, const QDir& destinationDirectory,
- const QString& sourceFileName,
- const QString& destinationFileName);
-
- virtual QString identifyGamePath() const;
-
- virtual bool prepareIni(const QString& exec);
-
- static std::unique_ptr<BYTE[]> getRegValue(HKEY key, LPCWSTR path, LPCWSTR value,
- DWORD flags, LPDWORD type);
-
- static QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value);
-
- static QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault);
-
- static QString getSpecialPath(const QString& name);
-
- static QString determineMyGamesPath(const QString& gameName);
-
- static QString parseEpicGamesLocation(const QStringList& manifests);
-
- static QString parseSteamLocation(const QString& appid, const QString& directoryName);
-
-protected:
- void registerFeature(std::shared_ptr<MOBase::GameFeature> feature);
-
-protected:
- // to access organizer for game features, avoid having to pass it to all saves since
- // we already pass the game
- friend class GamebryoSaveGame;
-
- QString m_GamePath;
- QString m_MyGamesPath;
- QString m_GameVariant;
- MOBase::IOrganizer* m_Organizer;
-};
-
-#endif // GAMEGAMEBRYO_H
diff --git a/libs/game_gamebryo/src/gamebryo/vdf_parser.h b/libs/game_gamebryo/src/gamebryo/vdf_parser.h
deleted file mode 100644
index 32d4d27..0000000
--- a/libs/game_gamebryo/src/gamebryo/vdf_parser.h
+++ /dev/null
@@ -1,739 +0,0 @@
-// MIT License
-//
-// Copyright(c) 2016 Matthias Moeller
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files(the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions :
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#ifndef __TYTI_STEAM_VDF_PARSER_H__
-#define __TYTI_STEAM_VDF_PARSER_H__
-
-#include <algorithm>
-#include <fstream>
-#include <functional>
-#include <iterator>
-#include <map>
-#include <memory>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-#include <exception>
-#include <system_error>
-
-// for wstring support
-#include <locale>
-#include <string>
-
-// internal
-#include <stack>
-
-// VS < 2015 has only partial C++11 support
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#ifndef CONSTEXPR
-#define CONSTEXPR
-#endif
-
-#ifndef NOEXCEPT
-#define NOEXCEPT
-#endif
-#else
-#ifndef CONSTEXPR
-#define CONSTEXPR constexpr
-#define TYTI_UNDEF_CONSTEXPR
-#endif
-
-#ifndef NOEXCEPT
-#define NOEXCEPT noexcept
-#define TYTI_UNDEF_NOEXCEPT
-#endif
-
-#endif
-
-namespace tyti
-{
-namespace vdf
-{
- namespace detail
- {
- ///////////////////////////////////////////////////////////////////////////
- // Helper functions selecting the right encoding (char/wchar_T)
- ///////////////////////////////////////////////////////////////////////////
-
- template <typename T>
- struct literal_macro_help
- {
- static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT
- {
- return c;
- }
- static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT
- {
- return c;
- }
- };
-
- template <>
- struct literal_macro_help<wchar_t>
- {
- static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT
- {
- return wc;
- }
- static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT
- {
- return wc;
- }
- };
-#define TYTI_L(type, text) vdf::detail::literal_macro_help<type>::result(text, L##text)
-
- inline std::string string_converter(const std::string& w) NOEXCEPT
- {
- return w;
- }
-
- // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert
- // from cppreference
- template <class Facet>
- struct deletable_facet : Facet
- {
- template <class... Args>
- deletable_facet(Args&&... args) : Facet(std::forward<Args>(args)...)
- {}
- ~deletable_facet() {}
- };
-
- inline std::string string_converter(const std::wstring& w) // todo: use us-locale
- {
- std::wstring_convert<deletable_facet<std::codecvt<wchar_t, char, std::mbstate_t>>>
- conv1;
- return conv1.to_bytes(w);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Writer helper functions
- ///////////////////////////////////////////////////////////////////////////
-
- template <typename charT>
- class tabs
- {
- const size_t t;
-
- public:
- explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {}
- std::basic_string<charT> print() const
- {
- return std::basic_string<charT>(t, TYTI_L(charT, '\t'));
- }
- inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT { return tabs(t + i); }
- };
-
- template <typename oStreamT>
- oStreamT& operator<<(oStreamT& s, const tabs<typename oStreamT::char_type> t)
- {
- s << t.print();
- return s;
- }
- } // end namespace detail
-
- ///////////////////////////////////////////////////////////////////////////
- // Interface
- ///////////////////////////////////////////////////////////////////////////
-
- /// custom objects and their corresponding write functions
-
- /// basic object node. Every object has a name and can contains attributes saved as
- /// key_value pairs or childrens
- template <typename CharT>
- struct basic_object
- {
- typedef CharT char_type;
- std::basic_string<char_type> name;
- std::unordered_map<std::basic_string<char_type>, std::basic_string<char_type>>
- attribs;
- std::unordered_map<std::basic_string<char_type>,
- std::shared_ptr<basic_object<char_type>>>
- childs;
-
- void add_attribute(std::basic_string<char_type> key,
- std::basic_string<char_type> value)
- {
- attribs.emplace(std::move(key), std::move(value));
- }
- void add_child(std::unique_ptr<basic_object<char_type>> child)
- {
- std::shared_ptr<basic_object<char_type>> obj{child.release()};
- childs.emplace(obj->name, obj);
- }
- void set_name(std::basic_string<char_type> n) { name = std::move(n); }
- };
-
- template <typename CharT>
- struct basic_multikey_object
- {
- typedef CharT char_type;
- std::basic_string<char_type> name;
- std::unordered_multimap<std::basic_string<char_type>, std::basic_string<char_type>>
- attribs;
- std::unordered_multimap<std::basic_string<char_type>,
- std::shared_ptr<basic_multikey_object<char_type>>>
- childs;
-
- void add_attribute(std::basic_string<char_type> key,
- std::basic_string<char_type> value)
- {
- attribs.emplace(std::move(key), std::move(value));
- }
- void add_child(std::unique_ptr<basic_multikey_object<char_type>> child)
- {
- std::shared_ptr<basic_multikey_object<char_type>> obj{child.release()};
- childs.emplace(obj->name, obj);
- }
- void set_name(std::basic_string<char_type> n) { name = std::move(n); }
- };
-
- typedef basic_object<char> object;
- typedef basic_object<wchar_t> wobject;
- typedef basic_multikey_object<char> multikey_object;
- typedef basic_multikey_object<wchar_t> wmultikey_object;
-
- struct Options
- {
- bool strip_escape_symbols;
- bool ignore_all_platform_conditionals;
- bool ignore_includes;
-
- Options()
- : strip_escape_symbols(true), ignore_all_platform_conditionals(false),
- ignore_includes(false)
- {}
- };
-
- // forward decls
- // forward decl
- template <typename OutputT, typename iStreamT>
- OutputT read(iStreamT& inStream, const Options& opt = Options{});
-
- /** \brief writes given object tree in vdf format to given stream.
- Output is prettyfied, using tabs
- */
- template <typename oStreamT, typename T>
- void write(oStreamT& s, const T& r,
- const detail::tabs<typename oStreamT::char_type> tab =
- detail::tabs<typename oStreamT::char_type>(0))
- {
- typedef typename oStreamT::char_type charT;
- using namespace detail;
- s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab
- << TYTI_L(charT, "{\n");
- for (const auto& i : r.attribs)
- s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"")
- << i.second << TYTI_L(charT, "\"\n");
- for (const auto& i : r.childs)
- if (i.second)
- write(s, *i.second, tab + 1);
- s << tab << TYTI_L(charT, "}\n");
- }
-
- namespace detail
- {
- template <typename iStreamT>
- std::basic_string<typename iStreamT::char_type> read_file(iStreamT& inStream)
- {
- // cache the file
- typedef typename iStreamT::char_type charT;
- std::basic_string<charT> str;
- inStream.seekg(0, std::ios::end);
- str.resize(static_cast<size_t>(inStream.tellg()));
- if (str.empty())
- return str;
-
- inStream.seekg(0, std::ios::beg);
- inStream.read(&str[0], str.size());
- return str;
- }
-
- /** \brief Read VDF formatted sequences defined by the range [first, last).
- If the file is mailformatted, parser will try to read it until it can.
- @param first begin iterator
- @param end end iterator
- @param exclude_files list of files which cant be included anymore.
- prevents circular includes
-
- can thow:
- - "std::runtime_error" if a parsing error occured
- - "std::bad_alloc" if not enough memory coup be allocated
- */
- template <typename OutputT, typename IterT>
- std::vector<std::unique_ptr<OutputT>>
- read_internal(IterT first, const IterT last,
- std::unordered_set<std::basic_string<
- typename std::iterator_traits<IterT>::value_type>>& exclude_files,
- const Options& opt)
- {
- static_assert(std::is_default_constructible<OutputT>::value,
- "Output Type must be default constructible (provide constructor "
- "without arguments)");
- static_assert(std::is_move_constructible<OutputT>::value,
- "Output Type must be move constructible");
-
- typedef typename std::iterator_traits<IterT>::value_type charT;
-
- const std::basic_string<charT> comment_end_str = TYTI_L(charT, "*/");
- const std::basic_string<charT> whitespaces = TYTI_L(charT, " \n\v\f\r\t");
-
-#ifdef WIN32
- std::function<bool(const std::basic_string<charT>&)> is_platform_str =
- [](const std::basic_string<charT>& in) {
- return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS");
- };
-#elif __APPLE__
- // WIN32 stands for pc in general
- std::function<bool(const std::basic_string<charT>&)> is_platform_str =
- [](const std::basic_string<charT>& in) {
- return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") ||
- in == TYTI_L(charT, "$OSX");
- };
-
-#elif __linux__
- // WIN32 stands for pc in general
- std::function<bool(const std::basic_string<charT>&)> is_platform_str =
- [](const std::basic_string<charT>& in) {
- return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") ||
- in == TYTI_L(charT, "$LINUX");
- };
-#else
- std::function<bool(const std::basic_string<charT>&)> is_platform_str =
- [](const std::basic_string<charT>& in) {
- return false;
- };
-#endif
-
- if (opt.ignore_all_platform_conditionals)
- is_platform_str = [](const std::basic_string<charT>&) {
- return false;
- };
-
- // function for skipping a comment block
- // iter: iterator poition to the position after a '/'
- auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT {
- ++iter;
- if (iter != last) {
- if (*iter == TYTI_L(charT, '/')) {
- // line comment, skip whole line
- iter = std::find(iter + 1, last, TYTI_L(charT, '\n'));
- }
-
- if (*iter == '*') {
- // block comment, skip until next occurance of "*\"
- iter = std::search(iter + 1, last, std::begin(comment_end_str),
- std::end(comment_end_str));
- iter += 2;
- }
- }
- return iter;
- };
-
- auto end_quote = [](IterT iter, const IterT& last) -> IterT {
- const auto begin = iter;
- auto last_esc = iter;
- do {
- ++iter;
- iter = std::find(iter, last, TYTI_L(charT, '\"'));
- if (iter == last)
- break;
-
- last_esc = std::prev(iter);
- while (last_esc != begin && *last_esc == '\\')
- --last_esc;
- } while (!(std::distance(last_esc, iter) % 2));
- if (iter == last)
- throw std::runtime_error{"quote was opened but not closed."};
- return iter;
- };
-
- auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT {
- const auto begin = iter;
- auto last_esc = iter;
- do {
- ++iter;
- iter = std::find_first_of(iter, last, std::begin(whitespaces),
- std::end(whitespaces));
- if (iter == last)
- break;
-
- last_esc = std::prev(iter);
- while (last_esc != begin && *last_esc == '\\')
- --last_esc;
- } while (!(std::distance(last_esc, iter) % 2));
- // if (iter == last)
- // throw std::runtime_error{ "word wasnt properly ended" };
- return iter;
- };
-
- auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT {
- iter = std::find_if_not(iter, last, [&whitespaces](charT c) {
- // return true if whitespace
- return std::any_of(std::begin(whitespaces), std::end(whitespaces),
- [c](charT pc) {
- return pc == c;
- });
- });
- return iter;
- };
-
- std::function<void(std::basic_string<charT>&)> strip_escape_symbols =
- [](std::basic_string<charT>& s) {
- auto quote_searcher = [&s](size_t pos) {
- return s.find(TYTI_L(charT, "\\\""), pos);
- };
- auto p = quote_searcher(0);
- while (p != s.npos) {
- s.replace(p, 2, TYTI_L(charT, "\""));
- p = quote_searcher(p);
- }
- auto searcher = [&s](size_t pos) {
- return s.find(TYTI_L(charT, "\\\\"), pos);
- };
- p = searcher(0);
- while (p != s.npos) {
- s.replace(p, 2, TYTI_L(charT, "\\"));
- p = searcher(p);
- }
- };
-
- if (!opt.strip_escape_symbols)
- strip_escape_symbols = [](std::basic_string<charT>&) {};
-
- auto conditional_fullfilled = [&skip_whitespaces,
- &is_platform_str](IterT& iter, const IterT& last) {
- iter = skip_whitespaces(iter, last);
- if (*iter == '[') {
- ++iter;
- const auto end = std::find(iter, last, ']');
- const bool negate = *iter == '!';
- if (negate)
- ++iter;
- auto conditional = std::basic_string<charT>(iter, end);
-
- const bool is_platform = is_platform_str(conditional);
- iter = end + 1;
-
- return static_cast<bool>(is_platform ^ negate);
- }
- return true;
- };
-
- // read header
- // first, quoted name
- std::unique_ptr<OutputT> curObj = nullptr;
- std::vector<std::unique_ptr<OutputT>> roots;
- std::stack<std::unique_ptr<OutputT>> lvls;
- auto curIter = first;
-
- while (curIter != last && *curIter != '\0') {
- // find first starting attrib/child, or ending
- curIter = skip_whitespaces(curIter, last);
- if (curIter == last || *curIter == '\0')
- break;
- if (*curIter == TYTI_L(charT, '/')) {
- curIter = skip_comments(curIter, last);
- } else if (*curIter != TYTI_L(charT, '}')) {
-
- // get key
- const auto keyEnd = (*curIter == TYTI_L(charT, '\"'))
- ? end_quote(curIter, last)
- : end_word(curIter, last);
- if (*curIter == TYTI_L(charT, '\"'))
- ++curIter;
- std::basic_string<charT> key(curIter, keyEnd);
- strip_escape_symbols(key);
- curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0);
-
- curIter = skip_whitespaces(curIter, last);
-
- auto conditional = conditional_fullfilled(curIter, last);
- if (!conditional)
- continue;
-
- while (*curIter == TYTI_L(charT, '/')) {
-
- curIter = skip_comments(curIter, last);
- if (curIter == last || *curIter == '}')
- throw std::runtime_error{"key declared, but no value"};
- curIter = skip_whitespaces(curIter, last);
- if (curIter == last || *curIter == '}')
- throw std::runtime_error{"key declared, but no value"};
- }
- // get value
- if (*curIter != '{') {
- const auto valueEnd = (*curIter == TYTI_L(charT, '\"'))
- ? end_quote(curIter, last)
- : end_word(curIter, last);
- if (*curIter == TYTI_L(charT, '\"'))
- ++curIter;
-
- auto value = std::basic_string<charT>(curIter, valueEnd);
- strip_escape_symbols(value);
- curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0);
-
- auto conditional = conditional_fullfilled(curIter, last);
- if (!conditional)
- continue;
-
- // process value
- if (key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) {
- if (curObj) {
- curObj->add_attribute(std::move(key), std::move(value));
- } else {
- throw std::runtime_error{"unexpected key without object"};
- }
- } else {
- if (!opt.ignore_includes &&
- exclude_files.find(value) == exclude_files.end()) {
- exclude_files.insert(value);
- std::basic_ifstream<charT> i(detail::string_converter(value));
- auto str = read_file(i);
- auto file_objs =
- read_internal<OutputT>(str.begin(), str.end(), exclude_files, opt);
- for (auto& n : file_objs) {
- if (curObj)
- curObj->add_child(std::move(n));
- else
- roots.push_back(std::move(n));
- }
- exclude_files.erase(value);
- }
- }
- } else if (*curIter == '{') {
- if (curObj)
- lvls.push(std::move(curObj));
- curObj = std::make_unique<OutputT>();
- curObj->set_name(std::move(key));
- ++curIter;
- }
- }
- // end of new object
- else if (curObj && *curIter == TYTI_L(charT, '}')) {
- if (!lvls.empty()) {
- // get object before
- std::unique_ptr<OutputT> prev{std::move(lvls.top())};
- lvls.pop();
-
- // add finished obj to obj before and release it from processing
- prev->add_child(std::move(curObj));
- curObj = std::move(prev);
- } else {
- roots.push_back(std::move(curObj));
- curObj.reset();
- }
- ++curIter;
- } else {
- throw std::runtime_error{"unexpected '}'"};
- }
- }
- if (curObj != nullptr || !lvls.empty()) {
- throw std::runtime_error{"object is not closed with '}'"};
- }
-
- return roots;
- }
-
- } // namespace detail
-
- /** \brief Read VDF formatted sequences defined by the range [first, last).
- If the file is mailformatted, parser will try to read it until it can.
- @param first begin iterator
- @param end end iterator
-
- can thow:
- - "std::runtime_error" if a parsing error occured
- - "std::bad_alloc" if not enough memory coup be allocated
- */
- template <typename OutputT, typename IterT>
- OutputT read(IterT first, const IterT last, const Options& opt = Options{})
- {
- auto exclude_files = std::unordered_set<
- std::basic_string<typename std::iterator_traits<IterT>::value_type>>{};
- auto roots = detail::read_internal<OutputT>(first, last, exclude_files, opt);
-
- OutputT result;
- if (roots.size() > 1) {
- for (auto& i : roots)
- result.add_child(std::move(i));
- } else if (roots.size() == 1)
- result = std::move(*roots[0]);
-
- return result;
- }
-
- /** \brief Read VDF formatted sequences defined by the range [first, last).
- If the file is mailformatted, parser will try to read it until it can.
- @param first begin iterator
- @param end end iterator
- @param ec output bool. 0 if ok, otherwise, holds an system error code
-
- Possible error codes:
- std::errc::protocol_error: file is mailformatted
- std::errc::not_enough_memory: not enough space
- std::errc::invalid_argument: iterators throws e.g. out of range
- */
- template <typename OutputT, typename IterT>
- OutputT read(IterT first, IterT last, std::error_code& ec,
- const Options& opt = Options{}) NOEXCEPT
-
- {
- ec.clear();
- OutputT r{};
- try {
- r = read<OutputT>(first, last, opt);
- } catch (std::runtime_error&) {
- ec = std::make_error_code(std::errc::protocol_error);
- } catch (std::bad_alloc&) {
- ec = std::make_error_code(std::errc::not_enough_memory);
- } catch (...) {
- ec = std::make_error_code(std::errc::invalid_argument);
- }
- return r;
- }
-
- /** \brief Read VDF formatted sequences defined by the range [first, last).
- If the file is mailformatted, parser will try to read it until it can.
- @param first begin iterator
- @param end end iterator
- @param ok output bool. true, if parser successed, false, if parser failed
- */
- template <typename OutputT, typename IterT>
- OutputT read(IterT first, const IterT last, bool* ok,
- const Options& opt = Options{}) NOEXCEPT
- {
- std::error_code ec;
- auto r = read<OutputT>(first, last, ec, opt);
- if (ok)
- *ok = !ec;
- return r;
- }
-
- template <typename IterT>
- inline auto read(IterT first, const IterT last, bool* ok,
- const Options& opt = Options{}) NOEXCEPT
- ->basic_object<typename std::iterator_traits<IterT>::value_type>
- {
- return read<basic_object<typename std::iterator_traits<IterT>::value_type>>(
- first, last, ok, opt);
- }
-
- template <typename IterT>
- inline auto read(IterT first, IterT last, std::error_code& ec,
- const Options& opt = Options{}) NOEXCEPT
- ->basic_object<typename std::iterator_traits<IterT>::value_type>
- {
- return read<basic_object<typename std::iterator_traits<IterT>::value_type>>(
- first, last, ec, opt);
- }
-
- template <typename IterT>
- inline auto read(IterT first, const IterT last, const Options& opt = Options{})
- -> basic_object<typename std::iterator_traits<IterT>::value_type>
- {
- return read<basic_object<typename std::iterator_traits<IterT>::value_type>>(
- first, last, opt);
- }
-
- /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf
- formatted data. throws "std::bad_alloc" if file buffer could not be allocated
- */
- template <typename OutputT, typename iStreamT>
- OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{})
- {
- // cache the file
- typedef typename iStreamT::char_type charT;
- std::basic_string<charT> str = detail::read_file(inStream);
-
- // parse it
- return read<OutputT>(str.begin(), str.end(), ec, opt);
- }
-
- template <typename iStreamT>
- inline basic_object<typename iStreamT::char_type>
- read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{})
- {
- return read<basic_object<typename iStreamT::char_type>>(inStream, ec, opt);
- }
-
- /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf
- formatted data. throws "std::bad_alloc" if file buffer could not be allocated ok ==
- false, if a parsing error occured
- */
- template <typename OutputT, typename iStreamT>
- OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{})
- {
- std::error_code ec;
- const auto r = read<OutputT>(inStream, ec, opt);
- if (ok)
- *ok = !ec;
- return r;
- }
-
- template <typename iStreamT>
- inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream, bool* ok,
- const Options& opt = Options{})
- {
- return read<basic_object<typename iStreamT::char_type>>(inStream, ok, opt);
- }
-
- /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf
- formatted data. throws "std::bad_alloc" if file buffer could not be allocated
- throws "std::runtime_error" if a parsing error occured
- */
- template <typename OutputT, typename iStreamT>
- OutputT read(iStreamT& inStream, const Options& opt)
- {
-
- // cache the file
- typedef typename iStreamT::char_type charT;
- std::basic_string<charT> str = detail::read_file(inStream);
- // parse it
- return read<OutputT>(str.begin(), str.end(), opt);
- }
-
- template <typename iStreamT>
- inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream,
- const Options& opt = Options{})
- {
- return read<basic_object<typename iStreamT::char_type>>(inStream, opt);
- }
-
-} // namespace vdf
-} // namespace tyti
-#ifndef TYTI_NO_L_UNDEF
-#undef TYTI_L
-#endif
-
-#ifdef TYTI_UNDEF_CONSTEXPR
-#undef CONSTEXPR
-#undef TYTI_NO_L_UNDEF
-#endif
-
-#ifdef TYTI_UNDEF_NOTHROW
-#undef NOTHROW
-#undef TYTI_UNDEF_NOTHROW
-#endif
-
-#endif //__TYTI_STEAM_VDF_PARSER_H__