[game_morrowind] Merge pull request #31 from ModOrganizer2/dev/format-and-gh-actions

This commit is contained in:
Mikaël Capelle
2024-06-09 13:41:40 +02:00
committed by GitHub
24 changed files with 421 additions and 376 deletions
+41
View File
@@ -0,0 +1,41 @@
---
# We'll use defaults from the LLVM style, but with 4 columns indentation.
BasedOnStyle: LLVM
IndentWidth: 2
---
Language: Cpp
DeriveLineEnding: false
UseCRLF: true
DerivePointerAlignment: false
PointerAlignment: Left
AlignConsecutiveAssignments: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Empty
AlwaysBreakTemplateDeclarations: Yes
AccessModifierOffset: -2
AlignTrailingComments: true
SpacesBeforeTrailingComments: 2
NamespaceIndentation: Inner
MaxEmptyLinesToKeep: 1
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
ColumnLimit: 88
ForEachMacros: ['Q_FOREACH', 'foreach']
@@ -0,0 +1 @@
ee98ea2db30bca29fc57d7abc96039ba7fe7ef94
+7
View File
@@ -0,0 +1,7 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.cpp text eol=crlf
*.h text eol=crlf
+16
View File
@@ -0,0 +1,16 @@
name: Build Morrowind Plugin
on:
push:
branches: master
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
runs-on: windows-2022
steps:
- name: Build Morrowind Plugin
uses: ModOrganizer2/build-with-mob-action@master
with:
mo2-dependencies: cmake_common uibase game_gamebryo
+16
View File
@@ -0,0 +1,16 @@
name: Lint Morrowind Plugin
on:
push:
pull_request:
types: [opened, synchronize, reopened]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Check format
uses: ModOrganizer2/check-formatting-action@master
with:
check-path: "."
-40
View File
@@ -1,40 +0,0 @@
version: 1.0.{build}
skip_branch_with_pr: true
image: Visual Studio 2019
environment:
WEBHOOK_URL:
secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw=
build_script:
- pwsh: >-
$ErrorActionPreference = 'Stop'
git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella
New-Item -ItemType Directory -Path c:\projects\modorganizer-build
cd c:\projects\modorganizer-umbrella
($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH)
git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch}
C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME}
if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) }
artifacts:
- path: vsbuild\src\RelWithDebInfo\game_morrowind.dll
name: game_morrowind_dll
- path: vsbuild\src\RelWithDebInfo\game_morrowind.pdb
name: game_morrowind_pdb
- path: vsbuild\src\RelWithDebInfo\game_morrowind.lib
name: game_morrowind_lib
on_success:
- ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER
- ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1
- ps: ./send.ps1 success $env:WEBHOOK_URL
on_failure:
- ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER
- ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log
- ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log
- ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1
- ps: ./send.ps1 failure $env:WEBHOOK_URL
+31 -30
View File
@@ -4,10 +4,10 @@
#include "morrowinddataarchives.h"
#include "morrowindgameplugins.h"
#include "morrowindlocalsavegames.h"
#include "morrowindsavegame.h"
#include "morrowindsavegameinfo.h"
#include "morrowindmoddatachecker.h"
#include "morrowindmoddatacontent.h"
#include "morrowindsavegame.h"
#include "morrowindsavegameinfo.h"
#include "executableinfo.h"
#include "pluginsetting.h"
@@ -32,23 +32,22 @@
using namespace MOBase;
GameMorrowind::GameMorrowind()
{
}
GameMorrowind::GameMorrowind() {}
bool GameMorrowind::init(IOrganizer *moInfo)
bool GameMorrowind::init(IOrganizer* moInfo)
{
if (!GameGamebryo::init(moInfo)) {
return false;
}
auto dataArchives = std::make_shared<MorrowindDataArchives>(this);
registerFeature(dataArchives);
registerFeature(std::make_shared<MorrowindBSAInvalidation>(dataArchives.get(), this));
registerFeature(std::make_shared<MorrowindSaveGameInfo>(this));
registerFeature(std::make_shared<MorrowindLocalSavegames>(this));
registerFeature(std::make_shared<MorrowindModDataChecker>(this));
registerFeature(std::make_shared<MorrowindModDataContent>(m_Organizer->gameFeatures()));
registerFeature(
std::make_shared<MorrowindModDataContent>(m_Organizer->gameFeatures()));
registerFeature(std::make_shared<MorrowindGamePlugins>(moInfo));
registerFeature(std::make_shared<GamebryoUnmangedMods>(this));
@@ -83,12 +82,13 @@ QDir GameMorrowind::documentsDirectory() const
QList<ExecutableInfo> GameMorrowind::executables() const
{
return QList<ExecutableInfo>()
<< ExecutableInfo("MWSE (Launcher Method)", findInGameFolder("MWSE Launcher.exe"))
<< ExecutableInfo("Morrowind", findInGameFolder(binaryName()))
<< ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName()))
<< ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe"))
<< ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Morrowind\"")
;
<< ExecutableInfo("MWSE (Launcher Method)",
findInGameFolder("MWSE Launcher.exe"))
<< ExecutableInfo("Morrowind", findInGameFolder(binaryName()))
<< ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName()))
<< ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe"))
<< ExecutableInfo("LOOT", QFileInfo(getLootPath()))
.withArgument("--game=\"Morrowind\"");
}
QList<ExecutableForcedLoadSetting> GameMorrowind::executableForcedLoads() const
@@ -106,7 +106,6 @@ QString GameMorrowind::localizedName() const
return tr("Morrowind Support Plugin");
}
QString GameMorrowind::author() const
{
return "Schilduin & MO2 Team";
@@ -115,7 +114,8 @@ QString GameMorrowind::author() const
QString GameMorrowind::description() const
{
return tr("Adds support for the game Morrowind.\n"
"Splash by %1").arg("AnyOldName3");
"Splash by %1")
.arg("AnyOldName3");
}
MOBase::VersionInfo GameMorrowind::version() const
@@ -128,7 +128,7 @@ QList<PluginSetting> GameMorrowind::settings() const
return QList<PluginSetting>();
}
void GameMorrowind::initializeProfile(const QDir &path, ProfileSettings settings) const
void GameMorrowind::initializeProfile(const QDir& path, ProfileSettings settings) const
{
if (settings.testFlag(IPluginGame::MODS)) {
copyToProfile(localAppFolder() + "/Morrowind", path, "plugins.txt");
@@ -149,7 +149,8 @@ QString GameMorrowind::savegameSEExtension() const
return "mwse";
}
std::shared_ptr<const GamebryoSaveGame> GameMorrowind::makeSaveGame(QString filePath) const
std::shared_ptr<const GamebryoSaveGame>
GameMorrowind::makeSaveGame(QString filePath) const
{
return std::make_shared<const MorrowindSaveGame>(filePath, this);
}
@@ -161,7 +162,7 @@ QString GameMorrowind::steamAPPId() const
QStringList GameMorrowind::primaryPlugins() const
{
return { "morrowind.esm" };
return {"morrowind.esm"};
}
QString GameMorrowind::binaryName() const
@@ -179,15 +180,14 @@ QString GameMorrowind::gameNexusName() const
return "Morrowind";
}
QStringList GameMorrowind::iniFiles() const
{
return { "morrowind.ini" };
return {"morrowind.ini"};
}
QStringList GameMorrowind::DLCPlugins() const
{
return { "Tribunal.esm", "Bloodmoon.esm" };
return {"Tribunal.esm", "Bloodmoon.esm"};
}
MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const
@@ -195,15 +195,16 @@ MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const
return SortMechanism::LOOT;
}
namespace {
//Note: This is ripped off from shared/util. And in an upcoming move, the fomod
//installer requires something similar. I suspect I should abstract this out
//into gamebryo (or lower level)
namespace
{
// Note: This is ripped off from shared/util. And in an upcoming move, the fomod
// installer requires something similar. I suspect I should abstract this out
// into gamebryo (or lower level)
VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName)
VS_FIXEDFILEINFO GetFileVersion(const std::wstring& fileName)
{
DWORD handle = 0UL;
DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle);
DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle);
if (size == 0) {
throw std::runtime_error("failed to determine file version info size");
}
@@ -214,7 +215,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName)
throw std::runtime_error("failed to determine file version info");
}
void *versionInfoPtr = nullptr;
void* versionInfoPtr = nullptr;
UINT versionInfoLength = 0;
if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) {
throw std::runtime_error("failed to determine file version");
@@ -223,7 +224,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName)
return *static_cast<VS_FIXEDFILEINFO*>(versionInfoPtr);
}
}
} // namespace
int GameMorrowind::nexusModOrganizerID() const
{
+12 -15
View File
@@ -9,29 +9,29 @@
class GameMorrowind : public GameGamebryo
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json")
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json")
#endif
friend class MorrowindSaveGameInfo;
friend class MorrowindSaveGameInfoWidget;
public:
GameMorrowind();
virtual bool init(MOBase::IOrganizer *moInfo) override;
public: // IPluginGame interface
virtual bool init(MOBase::IOrganizer* moInfo) override;
public: // IPluginGame interface
virtual QString gameName() const override;
virtual QString getLauncherName() const override;
virtual QDir dataDirectory() const override;
virtual QDir savesDirectory() const override;
virtual QDir documentsDirectory() const override;
virtual QList<MOBase::ExecutableInfo> executables() const override;
virtual QList<MOBase::ExecutableForcedLoadSetting> executableForcedLoads() const override;
virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override;
virtual QList<MOBase::ExecutableForcedLoadSetting>
executableForcedLoads() const override;
virtual void initializeProfile(const QDir& path,
ProfileSettings settings) const override;
virtual QString steamAPPId() const override;
virtual QStringList primaryPlugins() const override;
virtual QString binaryName() const override;
@@ -44,8 +44,7 @@ public: // IPluginGame interface
virtual int nexusGameID() const override;
virtual QString identifyGamePath() const;
public: // IPlugin interface
public: // IPlugin interface
virtual QString name() const override;
virtual QString localizedName() const override;
virtual QString author() const override;
@@ -54,12 +53,10 @@ public: // IPlugin interface
virtual QList<MOBase::PluginSetting> settings() const override;
protected:
virtual QString savegameExtension() const override;
virtual QString savegameSEExtension() const override;
virtual std::shared_ptr<const GamebryoSaveGame> makeSaveGame(QString filepath) const override;
virtual std::shared_ptr<const GamebryoSaveGame>
makeSaveGame(QString filepath) const override;
};
#endif // GAMEMORROWIND_H
#endif // GAMEMORROWIND_H
@@ -1,9 +1,9 @@
#include "morrowindbsainvalidation.h"
MorrowindBSAInvalidation::MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game)
: GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game)
{
}
MorrowindBSAInvalidation::MorrowindBSAInvalidation(MOBase::DataArchives* dataArchives,
MOBase::IPluginGame const* game)
: GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game)
{}
QString MorrowindBSAInvalidation::invalidationBSAName() const
{
@@ -1,7 +1,6 @@
#ifndef MORROWINDBSAINVALIDATION_H
#define MORROWINDBSAINVALIDATION_H
#include "gamebryobsainvalidation.h"
#include "morrowinddataarchives.h"
@@ -10,14 +9,12 @@
class MorrowindBSAInvalidation : public GamebryoBSAInvalidation
{
public:
MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game);
MorrowindBSAInvalidation(MOBase::DataArchives* dataArchives,
MOBase::IPluginGame const* game);
private:
virtual QString invalidationBSAName() const override;
virtual unsigned long bsaVersion() const override;
};
#endif // MORROWINDBSAINVALIDATION_H
#endif // MORROWINDBSAINVALIDATION_H
@@ -1,19 +1,20 @@
#include "morrowinddataarchives.h"
#include <utility.h>
#include "registry.h"
#include <utility.h>
MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame *game)
: GamebryoDataArchives(QDir()) // m_LocalGameDir is not used as it's determined too soon
, m_GamePlugin(game)
{
}
MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame* game)
: GamebryoDataArchives(
QDir()) // m_LocalGameDir is not used as it's determined too soon
,
m_GamePlugin(game)
{}
QStringList MorrowindDataArchives::vanillaArchives() const
{
return { "Morrowind.bsa" };
return {"Morrowind.bsa"};
}
QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const
QStringList MorrowindDataArchives::getArchives(const QString& iniFile) const
{
wchar_t buffer[256];
QStringList result;
@@ -22,42 +23,52 @@ QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const
errno = 0;
QString key = "Archive ";
int i=0;
while (::GetPrivateProfileStringW(L"Archives", (key+QString::number(i)).toStdWString().c_str(),
L"", buffer, 256, iniFileW.c_str()) != 0) {
int i = 0;
while (::GetPrivateProfileStringW(L"Archives",
(key + QString::number(i)).toStdWString().c_str(),
L"", buffer, 256, iniFileW.c_str()) != 0) {
result.append(QString::fromStdWString(buffer).trimmed());
i++;
i++;
}
return result;
}
void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringList &list)
void MorrowindDataArchives::setArchives(const QString& iniFile, const QStringList& list)
{
::WritePrivateProfileSectionW(L"Archives", NULL, iniFile.toStdWString().c_str());
QString key = "Archive ";
QString key = "Archive ";
int writtenCount = 0;
foreach(const QString &value, list) {
if (!MOBase::WriteRegistryValue(L"Archives", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) {
foreach (const QString& value, list) {
if (!MOBase::WriteRegistryValue(
L"Archives", (key + QString::number(writtenCount)).toStdWString().c_str(),
value.toStdWString().c_str(), iniFile.toStdWString().c_str())) {
qWarning("failed to set archives in \"%s\"", qUtf8Printable(iniFile));
}
++writtenCount;
++writtenCount;
}
}
QStringList MorrowindDataArchives::archives(const MOBase::IProfile *profile) const
QStringList MorrowindDataArchives::archives(const MOBase::IProfile* profile) const
{
QStringList result;
QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
QString iniFile =
profile->localSettingsEnabled()
? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini")
: m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
result.append(getArchives(iniFile));
return result;
}
void MorrowindDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before)
void MorrowindDataArchives::writeArchiveList(MOBase::IProfile* profile,
const QStringList& before)
{
QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
QString iniFile =
profile->localSettingsEnabled()
? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini")
: m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini");
setArchives(iniFile, before);
}
+12 -16
View File
@@ -1,36 +1,32 @@
#ifndef MORROWINDDATAARCHIVES_H
#define MORROWINDDATAARCHIVES_H
#include <gamebryodataarchives.h>
#include <iprofile.h>
#include <iplugingame.h>
#include <QDir>
#include <QString>
#include <QStringList>
#include <QDir>
#include <gamebryodataarchives.h>
#include <iplugingame.h>
#include <iprofile.h>
class MorrowindDataArchives : public GamebryoDataArchives
{
public:
MorrowindDataArchives(const MOBase::IPluginGame *game);
MorrowindDataArchives(const MOBase::IPluginGame* game);
public:
virtual QStringList vanillaArchives() const override;
virtual QStringList archives(const MOBase::IProfile *profile) const override;
virtual QStringList archives(const MOBase::IProfile* profile) const override;
protected:
QStringList getArchives(const QString& iniFile) const;
void setArchives(const QString& iniFile, const QStringList& list);
QStringList getArchives(const QString &iniFile) const;
void setArchives(const QString &iniFile, const QStringList &list);
private:
virtual void writeArchiveList(MOBase::IProfile* profile,
const QStringList& before) override;
virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override;
const MOBase::IPluginGame *m_GamePlugin;
const MOBase::IPluginGame* m_GamePlugin;
};
#endif // MORROWINDDATAARCHIVES_H
#endif // MORROWINDDATAARCHIVES_H
@@ -1,44 +1,41 @@
#include "morrowindgameplugins.h"
#include <Windows.h>
#include <utility.h>
#include <report.h>
#include <ipluginlist.h>
#include <iplugingame.h>
#include <imodinterface.h>
#include <scopeguard.h>
#include "registry.h"
#include <Windows.h>
#include <imodinterface.h>
#include <iplugingame.h>
#include <ipluginlist.h>
#include <report.h>
#include <scopeguard.h>
#include <utility.h>
#include <QDateTime>
#include <QDir>
#include <QStringList>
#include <QString>
#include <QStringEncoder>
#include <QDateTime>
#include <QStringList>
using MOBase::IOrganizer;
using MOBase::IPluginList;
using MOBase::reportError;
MorrowindGamePlugins::MorrowindGamePlugins(IOrganizer *organizer) :
GamebryoGamePlugins(organizer)
{
}
MorrowindGamePlugins::MorrowindGamePlugins(IOrganizer* organizer)
: GamebryoGamePlugins(organizer)
{}
void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) {
void MorrowindGamePlugins::writePluginLists(const IPluginList* pluginList)
{
if (!m_LastRead.isValid()) {
// attempt to write uninitialized plugin lists
return;
}
if (organizer()->profile()->localSettingsEnabled()) {
writePluginList(
pluginList,
organizer()->profile()->absolutePath() + "/Morrowind.ini"
);
writePluginList(pluginList,
organizer()->profile()->absolutePath() + "/Morrowind.ini");
} else {
writePluginList(
pluginList,
organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"
);
writePluginList(pluginList,
organizer()->managedGame()->gameDirectory().absolutePath() +
"/Morrowind.ini");
}
writeLoadOrderList(pluginList,
@@ -47,20 +44,20 @@ void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) {
m_LastRead = QDateTime::currentDateTime();
}
void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) {
QString loadOrderPath =
organizer()->profile()->absolutePath() + "/loadorder.txt";
void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList* pluginList)
{
QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt";
QString pluginsPath = organizer()->profile()->absolutePath() + "/Morrowind.ini";
if (!organizer()->profile()->localSettingsEnabled()) {
pluginsPath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
pluginsPath =
organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
}
bool loadOrderIsNew = !m_LastRead.isValid() ||
!QFileInfo(loadOrderPath).exists() ||
QFileInfo(loadOrderPath).lastModified() > m_LastRead;
bool pluginsIsNew = !m_LastRead.isValid() ||
QFileInfo(pluginsPath).lastModified() > m_LastRead;
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
@@ -68,7 +65,8 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) {
pluginList->setLoadOrder(loadOrder);
readPluginList(pluginList);
} else {
// If the plugins is new but not loadorder, we must reparse the load order from the plugin files
// 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);
}
@@ -76,35 +74,41 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) {
m_LastRead = QDateTime::currentDateTime();
}
void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList *pluginList,
const QString &filePath) {
void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList* pluginList,
const QString& filePath)
{
return writeList(pluginList, filePath, false);
}
void MorrowindGamePlugins::writeList(const IPluginList *pluginList,
const QString &filePath, bool loadOrder) {
QStringEncoder encoder = loadOrder ? QStringEncoder(QStringConverter::Encoding::Utf8) : QStringEncoder(QStringConverter::Encoding::System);
void MorrowindGamePlugins::writeList(const IPluginList* pluginList,
const QString& filePath, bool loadOrder)
{
QStringEncoder encoder = loadOrder
? QStringEncoder(QStringConverter::Encoding::Utf8)
: QStringEncoder(QStringConverter::Encoding::System);
::WritePrivateProfileSectionW(L"Game Files", NULL, filePath.toStdWString().c_str());
bool invalidFileNames = false;
int writtenCount = 0;
int writtenCount = 0;
QStringList plugins = pluginList->pluginNames();
std::sort(plugins.begin(), plugins.end(),
[pluginList](const QString &lhs, const QString &rhs) {
[pluginList](const QString& lhs, const QString& rhs) {
return pluginList->priority(lhs) < pluginList->priority(rhs);
});
QString key = "GameFile";
for (const QString &pluginName : plugins) {
if (loadOrder ||
(pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) {
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 {
if (!MOBase::WriteRegistryValue(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) {
if (!MOBase::WriteRegistryValue(
L"Game Files",
(key + QString::number(writtenCount)).toStdWString().c_str(),
pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) {
qWarning("failed to set game files in \"%s\"", qUtf8Printable(filePath));
}
}
@@ -125,15 +129,17 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList,
}
}
QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList) {
QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList* pluginList)
{
QStringList primary = organizer()->managedGame()->primaryPlugins();
for (const QString &pluginName : primary) {
for (const QString& pluginName : primary) {
if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) {
pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
}
}
QStringList plugins = pluginList->pluginNames();
// Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins".
// Do not sort the primary plugins. Their load order should be locked as defined in
// "primaryPlugins".
const QStringList pluginsClone(plugins);
for (QString plugin : pluginsClone) {
if (primary.contains(plugin, Qt::CaseInsensitive))
@@ -141,24 +147,27 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList
}
// 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();
});
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();
});
QString filePath = organizer()->profile()->absolutePath() + "/Morrowind.ini";
if (!organizer()->profile()->localSettingsEnabled()) {
filePath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
filePath =
organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini";
}
wchar_t buffer[256];
QStringList result;
@@ -169,9 +178,10 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList
QStringList activePlugins;
QStringList inactivePlugins;
QString key = "GameFile";
int i = 0;
while (::GetPrivateProfileStringW(L"Game Files", (key + QString::number(i)).toStdWString().c_str(),
L"", buffer, 256, iniFileW.c_str()) != 0) {
int i = 0;
while (::GetPrivateProfileStringW(L"Game Files",
(key + QString::number(i)).toStdWString().c_str(),
L"", buffer, 256, iniFileW.c_str()) != 0) {
QString pluginName;
pluginName = QString::fromStdWString(buffer).trimmed();
pluginList->setState(pluginName, IPluginList::STATE_ACTIVE);
@@ -180,11 +190,11 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList
}
// we removed each plugin found in the file, so what's left are inactive mods
for (const QString &pluginName : plugins)
for (const QString& pluginName : plugins)
if (!activePlugins.contains(pluginName))
inactivePlugins.push_back(pluginName);
for (const QString &pluginName : inactivePlugins)
for (const QString& pluginName : inactivePlugins)
pluginList->setState(pluginName, IPluginList::STATE_INACTIVE);
return primary + plugins;
+12 -12
View File
@@ -7,22 +7,22 @@ class MorrowindGamePlugins : public GamebryoGamePlugins
{
public:
MorrowindGamePlugins(MOBase::IOrganizer *organizer);
virtual void writePluginLists(const MOBase::IPluginList *pluginList) override;
virtual void readPluginLists(MOBase::IPluginList *pluginList) override;
MorrowindGamePlugins(MOBase::IOrganizer* organizer);
virtual void writePluginLists(const MOBase::IPluginList* pluginList) override;
virtual void readPluginLists(MOBase::IPluginList* pluginList) override;
protected:
virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override;
virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override;
virtual void writePluginList(const MOBase::IPluginList* pluginList,
const QString& filePath) override;
virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override;
private:
virtual void writeList(const MOBase::IPluginList *pluginList, const QString &filePath,
bool loadOrder);
virtual void writeList(const MOBase::IPluginList* pluginList, const QString& filePath,
bool loadOrder);
private:
QDateTime m_LastRead;
};
#endif // MORROWINDGAMEPLUGINS_H
#endif // MORROWINDGAMEPLUGINS_H
@@ -16,20 +16,18 @@ 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 "morrowindlocalsavegames.h"
#include <iprofile.h>
#include <QtDebug>
#include <windows.h>
#include <iprofile.h>
#include <stddef.h>
#include <string>
#include <windows.h>
MorrowindLocalSavegames::MorrowindLocalSavegames(const MOBase::IPluginGame *game)
: m_GamePlugin(game)
MorrowindLocalSavegames::MorrowindLocalSavegames(const MOBase::IPluginGame* game)
: m_GamePlugin(game)
{}
bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile)
bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile* profile)
{
bool dirty = false;
@@ -52,13 +50,8 @@ bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile)
return dirty;
}
MappingType MorrowindLocalSavegames::mappings(const QDir &profileSaveDir) const
MappingType MorrowindLocalSavegames::mappings(const QDir& profileSaveDir) const
{
return {{
profileSaveDir.absolutePath(),
m_GamePlugin->gameDirectory().absoluteFilePath("Saves"),
true,
true
}};
}
return {{profileSaveDir.absolutePath(),
m_GamePlugin->gameDirectory().absoluteFilePath("Saves"), true, true}};
}
@@ -16,31 +16,26 @@ 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 MORROWINDLOCALSAVEGAMES_H
#define MORROWINDLOCALSAVEGAMES_H
#include <localsavegames.h>
#include "iplugingame.h"
#include <QDir>
#include <QString>
#include "iplugingame.h"
class MorrowindLocalSavegames : public MOBase::LocalSavegames
{
public:
MorrowindLocalSavegames(const MOBase::IPluginGame *game);
MorrowindLocalSavegames(const MOBase::IPluginGame* game);
virtual MappingType mappings(const QDir &profileSaveDir) const override;
virtual bool prepareProfile(MOBase::IProfile *profile) override;
virtual MappingType mappings(const QDir& profileSaveDir) const override;
virtual bool prepareProfile(MOBase::IProfile* profile) override;
private:
const MOBase::IPluginGame *m_GamePlugin;
const MOBase::IPluginGame* m_GamePlugin;
};
#endif // MORROWINDLOCALSAVEGAMES_H
#endif // MORROWINDLOCALSAVEGAMES_H
@@ -9,19 +9,18 @@ public:
using GamebryoModDataChecker::GamebryoModDataChecker;
protected:
virtual const FileNameSet& possibleFolderNames() const override {
static FileNameSet result{
"fonts", "meshes", "music", "shaders", "sound", "textures", "video",
"mwse", "distantland", "mits", "icons", "bookart", "splash"
};
virtual const FileNameSet& possibleFolderNames() const override
{
static FileNameSet result{"fonts", "meshes", "music", "shaders", "sound",
"textures", "video", "mwse", "distantland", "mits",
"icons", "bookart", "splash"};
return result;
}
virtual const FileNameSet& possibleFileExtensions() const override {
static FileNameSet result{
"esp", "esm", "bsa", "modgroups"
};
virtual const FileNameSet& possibleFileExtensions() const override
{
static FileNameSet result{"esp", "esm", "bsa", "modgroups"};
return result;
}
};
#endif // MORROWIND_MODATACHECKER_H
#endif // MORROWIND_MODATACHECKER_H
@@ -4,20 +4,21 @@
#include <gamebryomoddatacontent.h>
#include <ifiletree.h>
class MorrowindModDataContent : public GamebryoModDataContent {
class MorrowindModDataContent : public GamebryoModDataContent
{
public:
/**
*
*/
MorrowindModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) {
MorrowindModDataContent(MOBase::IGameFeatures const* gameFeatures)
: GamebryoModDataContent(gameFeatures)
{
// Just need to disable some contents:
m_Enabled[CONTENT_MCM] = false;
m_Enabled[CONTENT_SKYPROC] = false;
m_Enabled[CONTENT_MCM] = false;
m_Enabled[CONTENT_SKYPROC] = false;
m_Enabled[CONTENT_INTERFACE] = false;
m_Enabled[CONTENT_SCRIPT] = false;
m_Enabled[CONTENT_SCRIPT] = false;
}
};
#endif // MORROWIND_MODDATACONTENT_H
#endif // MORROWIND_MODDATACONTENT_H
+54 -58
View File
@@ -1,12 +1,12 @@
#include "morrowindsavegame.h"
#include <Windows.h>
#include <QPixmap>
#include <QRegularExpression>
#include <Windows.h>
#include <filesystem>
MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind const *game) :
GamebryoSaveGame(fileName, game)
MorrowindSaveGame::MorrowindSaveGame(QString const& fileName, GameMorrowind const* game)
: GamebryoSaveGame(fileName, game)
{
std::filesystem::path realFile(fileName.toStdWString());
QString realFileName = QString::fromStdWString(realFile.filename().wstring());
@@ -14,16 +14,13 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind cons
FileWrapper file(fileName, "TES3");
QStringList dummyPlugins;
fetchInformationFields(file, m_SaveName, dummyPlugins,
m_PCCurrentHealth, m_PCCMaxHealth, m_PCLocation, m_GameDays, m_PCName);
fetchInformationFields(file, m_SaveName, dummyPlugins, m_PCCurrentHealth,
m_PCCMaxHealth, m_PCLocation, m_GameDays, m_PCName);
}
QString MorrowindSaveGame::getName() const
{
return QString("%1, #%2, %3")
.arg(m_PCName)
.arg(m_SaveNumber)
.arg(m_PCLocation);
return QString("%1, #%2, %3").arg(m_PCName).arg(m_SaveNumber).arg(m_PCLocation);
}
unsigned short MorrowindSaveGame::getPCLevel() const
@@ -31,53 +28,53 @@ unsigned short MorrowindSaveGame::getPCLevel() const
return dynamic_cast<MorrowindDataFields*>(m_DataFields.value().get())->PCLevel;
}
// Fetch easy-to-access information.
void MorrowindSaveGame::fetchInformationFields(FileWrapper& file,
QString& saveName,
QStringList& plugins,
float& playerCurrentHealth,
float& playerMaxHealth,
QString& playerLocation,
float& gameDays,
QString& playerName) const
void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, QString& saveName,
QStringList& plugins,
float& playerCurrentHealth,
float& playerMaxHealth,
QString& playerLocation, float& gameDays,
QString& playerName) const
{
file.skip<uint32_t>(3); // data size
file.skip<unsigned char>(4); // HEDR tag
file.skip<uint32_t>(); // header size
file.skip<float>(); // header version
file.skip<uint32_t>(); // following data chunk size? seems to be 9 groupings of 32 bytes
file.skip<unsigned char>(32); // Author empty for save files
std::vector<char> saveNameBuffer(256); // 31 char save name with a null terminator
file.skip<uint32_t>(3); // data size
file.skip<unsigned char>(4); // HEDR tag
file.skip<uint32_t>(); // header size
file.skip<float>(); // header version
file.skip<uint32_t>(); // following data chunk size? seems to be 9 groupings of 32
// bytes
file.skip<unsigned char>(32); // Author empty for save files
std::vector<char> saveNameBuffer(256); // 31 char save name with a null terminator
file.read(saveNameBuffer.data(), 256);
saveName = QString::fromLatin1(saveNameBuffer.data(), 256).trimmed(); // The defined save name. This is technically the description, but is likely only 31+\0 chars max.
file.skip<uint32_t>(); // NumRecords (for the entire save)
saveName = QString::fromLatin1(saveNameBuffer.data(), 256)
.trimmed(); // The defined save name. This is technically the
// description, but is likely only 31+\0 chars max.
file.skip<uint32_t>(); // NumRecords (for the entire save)
std::vector<char> buffer(255);
file.read(buffer.data(), 4);
// Parse the MAST/DATA records
while (QString::fromLatin1(buffer.data(), 4) == "MAST") {
uint32_t len;
file.read(len); // Length of master name
file.read(buffer.data(), len); // Name of master
file.read(len); // Length of master name
file.read(buffer.data(), len); // Name of master
QString name = QString::fromLatin1(buffer.data(), len - 1);
file.skip<unsigned char>(4); // DATA record
file.read(len); // Length
file.skip<unsigned char>(len); // Typically size 8 - contains length of master data for version checking
file.skip<unsigned char>(4); // DATA record
file.read(len); // Length
file.skip<unsigned char>(
len); // Typically size 8 - contains length of master data for version checking
file.read(buffer.data(), 4); // Get next record type
file.read(buffer.data(), 4); // Get next record type
plugins.push_back(name);
}
// Start of GMDT
file.skip<uint32_t>(); // size of record
file.skip<uint32_t>(); // size of record
file.read(playerCurrentHealth);
file.read(playerMaxHealth);
file.skip<double>(); // current stam?
file.skip<double>(); // max stam?
//file.skip<double>(2); // unknown values
file.skip<double>(); // current stam?
file.skip<double>(); // max stam?
// file.skip<double>(2); // unknown values
file.read(buffer.data(), 64);
playerLocation = QString::fromLatin1(buffer.data(), 64).trimmed();
@@ -100,29 +97,29 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
{
QString dummy;
float dummyF;
fetchInformationFields(file, dummy, fields->Plugins,
dummyF, dummyF, dummy, dummyF, dummy);
fetchInformationFields(file, dummy, fields->Plugins, dummyF, dummyF, dummy, dummyF,
dummy);
}
file.skip<unsigned char>(28); // Skip the SCRD
// I believe this tells the engine what color each pixel represents and the bitness of the image
file.skip<unsigned char>(28); // Skip the SCRD
// I believe this tells the engine what color each pixel represents and the bitness of
// the image
// Start of screenshot
file.skip<unsigned char>(4); // SCRS
file.skip<uint32_t>(); // Size of screenshot always 65536 (128x128x4) RGBA8888
file.skip<unsigned char>(4); // SCRS
file.skip<uint32_t>(); // Size of screenshot always 65536 (128x128x4) RGBA8888
QImage image = readImageBGRA(file, 128, 128, 0, 1);
QImage image = readImageBGRA(file, 128, 128, 0, 1);
fields->Screenshot = image.scaled(252, 192);
//definitively have to use another method to access the player level
//it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record
// definitively have to use another method to access the player level
// it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record
//Globals, Scripts, Regions
//file.skip<unsigned char>();
// Globals, Scripts, Regions
// file.skip<unsigned char>();
std::vector<char> buff(4);
file.read(buff.data(), 4);
while (QString::fromLatin1(buff.data(), 4) != "NPC_")
{
while (QString::fromLatin1(buff.data(), 4) != "NPC_") {
uint32_t len;
file.read(len);
file.skip<unsigned char>(8 + len);
@@ -137,8 +134,7 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
file.read(buffer.data(), len);
if (QString::fromLatin1(buffer.data(), len - 1) == "player") {
file.read(buff.data(), 4);
while (QString::fromLatin1(buff.data(), 4) != "NPDT")
{
while (QString::fromLatin1(buff.data(), 4) != "NPDT") {
uint32_t len;
file.read(len);
file.skip<unsigned char>(len);
@@ -146,9 +142,7 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
}
file.skip<unsigned long>();
file.read(fields->PCLevel);
}
else
{
} else {
file.skip<unsigned char>(size - len - 8);
}
}
@@ -156,7 +150,9 @@ std::unique_ptr<GamebryoSaveGame::DataFields> MorrowindSaveGame::fetchDataFields
return fields;
}
QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale = 0, bool alpha = false) const
QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper& file,
unsigned long width, unsigned long height,
int scale = 0, bool alpha = false) const
{
QImage image(width, height, QImage::Format_RGBA8888);
for (unsigned long h = 0; h < width; h++) {
@@ -178,4 +174,4 @@ QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, uns
return image.copy().scaledToWidth(scale);
else
return image.copy();
}
}
+16 -20
View File
@@ -4,15 +4,17 @@
#include "gamebryosavegame.h"
#include "gamemorrowind.h"
namespace MOBase { class IPluginGame; }
namespace MOBase
{
class IPluginGame;
}
class MorrowindSaveGame : public GamebryoSaveGame
{
public:
MorrowindSaveGame(QString const &fileName, GameMorrowind const *game);
public: // ISaveGame interface
MorrowindSaveGame(QString const& fileName, GameMorrowind const* game);
public: // ISaveGame interface
// We need to override getName() because we do not read the level at
// the beginning.
virtual QString getName() const override;
@@ -21,7 +23,7 @@ public: // ISaveGame interface
unsigned short getPCLevel() const override;
public:
//Simple getters
// Simple getters
QString getSaveName() const { return m_SaveName; }
float getPCCurrentHealth() const { return m_PCCurrentHealth; }
float getPCMaxHealth() const { return m_PCCMaxHealth; }
@@ -34,28 +36,22 @@ protected:
float m_GameDays;
protected:
QImage readImageBGRA(
GamebryoSaveGame::FileWrapper &file, unsigned long width,
unsigned long height, int scale, bool alpha) const;
QImage readImageBGRA(GamebryoSaveGame::FileWrapper& file, unsigned long width,
unsigned long height, int scale, bool alpha) const;
// We need to add the PC level here.
struct MorrowindDataFields : public DataFields {
struct MorrowindDataFields : public DataFields
{
unsigned short PCLevel = 0;
};
// Fetch easy-to-access information.
void fetchInformationFields(
FileWrapper& file,
QString& saveName,
QStringList& plugins,
float& playerCurrentHealth,
float& playerMaxHealth,
QString& playerLocation,
float& gameDays,
QString& playerName) const;
void fetchInformationFields(FileWrapper& file, QString& saveName,
QStringList& plugins, float& playerCurrentHealth,
float& playerMaxHealth, QString& playerLocation,
float& gameDays, QString& playerName) const;
std::unique_ptr<DataFields> fetchDataFields() const override;
};
#endif // MORROWINDSAVEGAME_H
#endif // MORROWINDSAVEGAME_H

Some files were not shown because too many files have changed in this diff Show More