ModOrganizer2 / modorganizer

Mod manager for various PC games. Discord Server: https://discord.gg/ewUVAqyrQX if you would like to be more involved
http://www.nexusmods.com/skyrimspecialedition/mods/6194
GNU General Public License v3.0
2.06k stars 155 forks source link

VFS is different if MO2 plugin using startApplication #1681

Open mdavis199 opened 2 years ago

mdavis199 commented 2 years ago

The problem:

VFS when MO2 is launched directly in a profile is different from the VFS when an MO2 plugin uses startApplication with a specified profile name.

Environment:

Details:

I am writing an MO2 plugin that allows a user to configure/edit/build multiple merges without leaving their base profile. It's basically a two-page wizard where the first page has various ways a user can select plugins and the second page allows the user to take various actions. It also allows the user to launch LOOT or zMerge for an existing MO2 profile (other than the one the user is currently using).

Attached is a screenshot of page 2 of my plugin if it helps. ![Screenshot 2022-03-31 17 01 21](https://user-images.githubusercontent.com/546489/161150301-36c75147-7076-4001-9bb5-eef7c73c0724.png)

Real-Life Senario

I have an existing MO2 profile called [Merge] Animals Merged.

Case 1: Using MO2 toolbar

I can launch MO2 directly into this profile and use it's tool bar to launch LOOT. LOOT tells me I have 18 active plugins out of 100.

Case 2: Using MO2 plugin startApplication

I open MO2 into a different profile, say 'Skyrim', launch my MO2 plugin. Using the plugin, I launch LOOT into profile [Merge] Animals Merged. This time LOOT tells me that I have 99 active plugins out of 100. My plugin made no changes to any files; it simply used startApplication with a specified profile name.

My code that calls startApplication ```python def launchLoot(self): profile = self.ui.selectedProfile.text() path = self.context.settings[Setting.LOOT_EXE] lootGameName = SUPPORTED_GAMES[self.context.profile.gameName].lootGameName args = ['--game="{}"'.format(lootGameName)] cwd = os.path.dirname(path) logging.info("Launching LOOT for profile: %s, ['%s' %s]", profile, path, args) handle = self.context.organizer.startApplication(path, args, cwd, profile) if handle < 0: return exitCode = self.context.organizer.waitForApplication(handle) self.logger.debug(self.tr("LOOT exited with code {}").format(exitCode)) ``` In the above code, I also tried changing the LOOT path to "LOOT" so that MO2 would pick up all settings from the toolbar. But nothing changed.

Link to Mod Organizer logs:

Logs for case 1

Logs for case 2

Note that in line 463 of case 2 - mod-interface.log the plugin requested to start an application using a specified profile.

AnyOldName3 commented 2 years ago

Is it possibly not setting up the mappings for the profile-specific files that live in the profile's directory?

mdavis199 commented 2 years ago

I don't think AnyOldName3's comment was for me. But I do want to add that in the "Skyrim" profile that I launched from there are 1169 active plugins (including the DLCs). So it does seem to pick up some of the files.

AnyOldName3 commented 2 years ago

No, the comment was meant to go here. If LOOT's seeing a different number of active files, a likely cause is that the load order, which is specified in profile-specific files, wasn't being set up in the same way, which could be because we're not mapping the files that control it.

mdavis199 commented 2 years ago

Just as AnyOldName3 said, it's in the file mapping. I don't have an C++ environment setup, so I can't test or submit patches or anything, but it seems the problem is here.

OrganizerCore::filemapping() https://github.com/ModOrganizer2/modorganizer/blob/88ee41ae85fa22f53a963a4ea950b91f1a7e7c73/src/organizercore.cpp#L2046-L2054

And here:

modorganizer-game-skyrimse ```cpp MappingType GameSkyrimSE::mappings() const { MappingType result; for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { result.push_back({ m_Organizer->profilePath() + "/" + profileFile, localAppFolder() + "/" + gameName() + "/" + profileFile, false }); } ``` https://github.com/ModOrganizer2/modorganizer-game_skyrimSE/blob/3512bdb0f4b12b3a2215394f6b7b383dd7f6b1c8/src/gameskyrimse.cpp#L272-L282

The Problem The game SkyrimSE has the path m_Organizer->profilePath() coded into the source mapping. And OrganizerCore.filemapping does not adjust it for the new profile path.

I suppose OrganizerCore::filemapping() could first check if the profile name passed into the function is different from the currentProfile, and if it is, patch up any mappings that match the current profile.

On a side note: the same function OrganizerCore::filemapping(), also sets up mappings for the "save" folder in the current profile, not the profile passed into the function.

OrganizerCore::filemapping() mapping save folders https://github.com/ModOrganizer2/modorganizer/blob/88ee41ae85fa22f53a963a4ea950b91f1a7e7c73/src/organizercore.cpp#L2027-L2037