Skip to content

Commit

Permalink
Parse unmanaged file location when creating ModInfoForeign (#2053)
Browse files Browse the repository at this point in the history
* Parse unmanaged file location when creating ModInfoForeign
- Fixes issues with secondaryDataDirectories
* Revert SF memory address changes
- CCC implementation prevents the need to determine core plugin LO by dependency chains
* The light flag wins over the medium flag
- I had expected the opposite, but apparently the light flag still wins if both are set. This shouldn't really happen but it's possible, even with the CK
* Update display to account for multi-flagged plugins
- Show both icons, warn if both set
  • Loading branch information
Silarn authored Jun 22, 2024
1 parent d3b647a commit a4f6298
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 62 deletions.
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)) {
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

0 comments on commit a4f6298

Please sign in to comment.