Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse unmanaged file location when creating ModInfoForeign #2053

Merged
merged 9 commits into from
Jun 22, 2024
18 changes: 10 additions & 8 deletions src/modinfoforeign.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "modinfoforeign.h"

#include "iplugingame.h"
#include "organizercore.h"
#include "utility.h"

#include <QApplication>
Expand All @@ -13,13 +14,6 @@ QDateTime ModInfoForeign::creationTime() const
return m_CreationTime;
}

QString ModInfoForeign::absolutePath() const
{
// I ought to store this, it's used elsewhere
IPluginGame const* game = qApp->property("managed_game").value<IPluginGame*>();
return game->dataDirectory().absolutePath();
}

std::vector<ModInfo::EFlag> ModInfoForeign::getFlags() const
{
std::vector<ModInfo::EFlag> result = ModInfoWithConflictInfo::getFlags();
Expand Down Expand Up @@ -49,7 +43,15 @@ ModInfoForeign::ModInfoForeign(const QString& modName, const QString& referenceF
: ModInfoWithConflictInfo(core), m_ReferenceFile(referenceFile),
m_Archives(archives), m_ModType(modType)
{
m_CreationTime = QFileInfo(referenceFile).birthTime();
m_CreationTime = QFileInfo(referenceFile).birthTime();
IPluginGame const* game = core.managedGame();
QList<QDir> directories = {game->dataDirectory()};
directories.append(game->secondaryDataDirectories().values());
for (QDir directory : directories) {
if (referenceFile.startsWith(directory.absolutePath(), Qt::CaseInsensitive)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there is a better way in Qt to check if a file is under a directory?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick search didn't find anything but there may be a way.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still haven't found a better solution for this. It seems to work.

m_BaseDirectory = directory.absolutePath();
}
}
switch (modType) {
case ModInfo::EModType::MOD_DLC:
m_Name = tr("DLC: ") + modName;
Expand Down
3 changes: 2 additions & 1 deletion src/modinfoforeign.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ModInfoForeign : public ModInfoWithConflictInfo
virtual QString comments() const override { return ""; }
virtual QString notes() const override { return ""; }
virtual QDateTime creationTime() const override;
virtual QString absolutePath() const override;
virtual QString absolutePath() const override { return m_BaseDirectory; }
virtual MOBase::VersionInfo newestVersion() const override { return QString(); }
virtual MOBase::VersionInfo ignoredVersion() const override { return QString(); }
virtual QString installationFile() const override { return ""; }
Expand Down Expand Up @@ -108,6 +108,7 @@ class ModInfoForeign : public ModInfoWithConflictInfo
QString m_Name;
QString m_InternalName;
QString m_ReferenceFile;
QString m_BaseDirectory;
QStringList m_Archives;
QDateTime m_CreationTime;
int m_Priority;
Expand Down
17 changes: 13 additions & 4 deletions src/modinfowithconflictinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,15 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co
bool providesAnything = false;
bool hasHiddenFiles = false;

int dataID = 0;
std::vector<int> dataIDs;
if (m_Core.directoryStructure()->originExists(L"data")) {
dataID = m_Core.directoryStructure()->getOriginByName(L"data").getID();
dataIDs.push_back(m_Core.directoryStructure()->getOriginByName(L"data").getID());
}
for (const auto& origin : m_Core.managedGame()->secondaryDataDirectories().keys()) {
if (m_Core.directoryStructure()->originExists(origin.toStdWString())) {
dataIDs.push_back(
m_Core.directoryStructure()->getOriginByName(origin.toStdWString()).getID());
}
}

std::wstring name = ToWString(this->name());
Expand Down Expand Up @@ -145,7 +151,9 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co
}

auto alternatives = file->getAlternatives();
if ((alternatives.size() == 0) || (alternatives.back().originID() == dataID)) {
if ((alternatives.size() == 0) ||
std::find(dataIDs.begin(), dataIDs.end(), alternatives.back().originID()) !=
dataIDs.end()) {
// no alternatives -> no conflict
providesAnything = true;
} else {
Expand Down Expand Up @@ -181,7 +189,8 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co

// Sort out the alternatives
for (const auto& altInfo : alternatives) {
if ((altInfo.originID() != dataID) &&
if (!(std::find(dataIDs.begin(), dataIDs.end(),
alternatives.back().originID()) != dataIDs.end()) &&
(altInfo.originID() != origin.getID())) {
FilesOrigin& altOrigin =
m_Core.directoryStructure()->getOriginByID(altInfo.originID());
Expand Down
75 changes: 26 additions & 49 deletions src/pluginlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,14 +1102,7 @@ void PluginList::generatePluginIndexes()
continue;
}
if (mediumPluginsSupported && m_ESPs[i].isMediumFlagged) {
if (mediumPluginsSupported && m_ESPs[i].forceLoaded) {
// Starfield core medium plugins are loaded in memory addresses after custom
// medium plugins
coreMediumPlugins.push_back(i);
++numSkipped;
continue;
}
int ESHpos = 253 + ((numESHs + 1) / 256);
int ESHpos = 253 + (numESHs / 256);
m_ESPs[i].index = QString("%1:%2")
.arg(ESHpos, 2, 16, QChar('0'))
.arg(numESHs % 256, 2, 16, QChar('0'))
Expand All @@ -1118,15 +1111,7 @@ void PluginList::generatePluginIndexes()

} else if (lightPluginsSupported &&
(m_ESPs[i].hasLightExtension || m_ESPs[i].isLightFlagged)) {
// Starfield core light plugins are loaded in memory addresses after custom light
// plugins
if (mediumPluginsSupported && m_ESPs[i].forceLoaded) {
coreLightPlugins.push_back(i);
++numSkipped;
continue;
}

int ESLpos = 254 + ((numESLs + 1) / 4096);
int ESLpos = 254 + (numESLs / 4096);
m_ESPs[i].index = QString("%1:%2")
.arg(ESLpos, 2, 16, QChar('0'))
.arg(numESLs % 4096, 3, 16, QChar('0'))
Expand All @@ -1138,22 +1123,6 @@ void PluginList::generatePluginIndexes()
.toUpper();
}
}
for (auto pluginIndex : coreMediumPlugins) {
int ESHpos = 253 + ((numESHs + 1) / 4096);
m_ESPs[pluginIndex].index = QString("%1:%2")
.arg(ESHpos, 2, 16, QChar('0'))
.arg(numESHs % 256, 2, 16, QChar('0'))
.toUpper();
++numESHs;
}
for (auto pluginIndex : coreLightPlugins) {
int ESLpos = 254 + ((numESLs + 1) / 4096);
m_ESPs[pluginIndex].index = QString("%1:%2")
.arg(ESLpos, 2, 16, QChar('0'))
.arg(numESLs % 4096, 3, 16, QChar('0'))
.toUpper();
++numESLs;
}
emit esplist_changed();
}

Expand Down Expand Up @@ -1283,10 +1252,10 @@ QVariant PluginList::fontData(const QModelIndex& modelIndex) const
if (m_ESPs[index].hasMasterExtension || m_ESPs[index].isMasterFlagged ||
m_ESPs[index].hasLightExtension)
result.setWeight(QFont::Bold);
if (m_ESPs[index].isMediumFlagged)
result.setUnderline(true);
if (m_ESPs[index].isLightFlagged || m_ESPs[index].hasLightExtension)
result.setItalic(true);
else if (m_ESPs[index].isMediumFlagged)
result.setUnderline(true);

return result;
}
Expand Down Expand Up @@ -1372,13 +1341,6 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const
"be added to your game settings, overwriting in case of conflicts.");
}

if (esp.isMediumFlagged && esp.hasMasterExtension) {
toolTip += "<br><br>" +
tr("This ESM is flagged as a medium plugin (ESH). It adheres to the ESM "
"load order but loads records in ESH space (FD). You can have 256 "
"medium plugins in addition to other plugin types.");
}

if (esp.isLightFlagged && !esp.hasLightExtension) {
QString type = esp.hasMasterExtension ? "ESM" : "ESP";
toolTip +=
Expand All @@ -1387,6 +1349,19 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const
"order but the records will be loaded in ESL space (FE/FF). You can have up "
"to 4096 light plugins in addition to other plugin types.")
.arg(type);
} else if (esp.isMediumFlagged && esp.hasMasterExtension) {
toolTip += "<br><br>" +
tr("This ESM is flagged as a medium plugin (ESH). It adheres to the ESM "
"load order but loads records in ESH space (FD). You can have 256 "
"medium plugins in addition to other plugin types.");
}

if (esp.isLightFlagged && esp.isMediumFlagged) {
toolTip +=
"<br><br>" +
tr("WARNING: This plugin is both light and medium flagged. "
"This could indicate that the file was saved improperly "
"and may have mismatched record references. Use it at your own risk.");
}

if (esp.hasNoRecords) {
Expand Down Expand Up @@ -1515,14 +1490,17 @@ QVariant PluginList::iconData(const QModelIndex& modelIndex) const
result.append(":/MO/gui/archive_conflict_neutral");
}

if (esp.isMediumFlagged) {
result.append(":/MO/gui/run");
}

if (esp.isLightFlagged && !esp.hasLightExtension) {
result.append(":/MO/gui/awaiting");
}

if (esp.isMediumFlagged) {
result.append(":/MO/gui/run");
if (esp.isLightFlagged) {
result.append(":/MO/gui/warning");
}
}

if (esp.hasNoRecords) {
result.append(":/MO/gui/unchecked-checkbox");
}
Expand Down Expand Up @@ -1851,10 +1829,9 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool forceLoaded, bool forceEn
hasMasterExtension = (extension == "esm");
hasLightExtension = (extension == "esl");
isMasterFlagged = file.isMaster();
isLightFlagged = lightSupported && file.isLight(mediumSupported);
isMediumFlagged = mediumSupported && file.isMedium();
isLightFlagged =
lightSupported && !isMediumFlagged && file.isLight(mediumSupported);
hasNoRecords = file.isDummy();
hasNoRecords = file.isDummy();

author = QString::fromLatin1(file.author().c_str());
description = QString::fromLatin1(file.description().c_str());
Expand Down
Loading