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

Load Order v1 #2248

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open

Load Order v1 #2248

wants to merge 36 commits into from

Conversation

Al12rs
Copy link
Contributor

@Al12rs Al12rs commented Nov 13, 2024

This PR implements a first implementation of load order backend and barebones ui for REDmod sorting.

System overview:

Games will expose a list of ISortableItemProviderFactory, one for each Load Order that the game has (e.g. RedMods and .archives for Cyberpunk).

ISortableItemProviderFactory exposes GetLoadoutSortableItemProvider() method that returns a ILoadoutSortableItemProvider, which can be thought of as load order manager for a specific loadout.

ISortableItemProviderFactory implementations should be instantiated on game instance creation (e.g. in the game class constructor), as it needs to listen to Loadouts changes to setup the ILoadoutSortableItemProviders.

For now the loadout providers only expose a collection of sortable items, to be used in the ui, and a SetRelativePosition() method to change the order.

The ILoadoutSortableItemProvider implementations will be in charge of updating the sorting as changes are made to the loadout (e.g. additions or removals of RedMods).

Db Models

The sorting information is persisted in the database in the form of two new models:

  • SortOrder
  • SortableEntry

SortOrder contains a reference to the Loadout that it applies to and serves as the containing group for the SortableEntrys.
This is similar enough to a LoaodutItemGroup but for now it isn't one.

SortableEntry represent an item being sorted and contains the SortIndex attribute. Should be extended with implementations that contain the game specific identifier used by the game (e.g. red mod folder name, bg3 .pak uuids, bethesda plugin names).

The SortingIndex is kept separate from the actual LoadoutItems that are being sorted, since we can actually have multiple LoadoutItems at the same position in the load order, what is being sorted depends on what ID the game uses. E.g. for bethesda, what the LoadOrder defines is the sorting of plugin names, not LoadoutItems.

Keeping SortingIndex separate from the actual items allows the possibility of storing backups of load orders that are not bound to a specific configuration of LoadoutItems. This also allows keeping the order in case of mod updates, since the SortingIndex is not lost on removal of the LoadoutItem but is instead kept on a separate db entity that only has the game specific id (e.g. red mod folder name).

Issues and Next steps:

Determining active state and conflict winners

Current implementation is not dealing with conflicts between mods and only approximatively checks if a redmod is actually getting deployed. Data regarding which mod is providing a specific mod in the load order might not be accurate.

Drag&Drop support

Current ui prototype only allows changing the order through up and down buttons. We want Drag&Drop support, but that will require a writable list that will then need to be kept synchronized. More complexity.

Generated load order files

Cyberpunk .archives and BG3 pak files load orders require wiring out a file containing the order that the game will then use.
Regenerating these files every loadout change and backing up those files in our file store would just create a lot fo churn and should be avoided.
Basically supporting Load Order there requires implementing a new file type GeneratedFiles in the synchronizer.
We had some early concepts of this in our codebase before, but they were removed since they weren't used at the time.

Eventual consistency nature of load orders

The providers listen to DB changes to know when a new mod is added or removed from the loadout that might matter for the loadorder, this means that when a new mod is added, the commit that adds the mod to the Loadout will not contain the loadorder information for the files inside that mod. That data will only be available in a future commit and there is no way to determine which one.

This can cause issues for systems that also listen to changes in the db and would like to get load order information for newly added files (e.g. diagnostics).

Multiple solutions could be considered:

  • Updating the sorting as part of the commits changing the loadout, this will require the transaction being passed around from wherever items are added or removed from the loadout.
  • Updating the sorting as a separate transaction but communicating the end of a change in the loadorder with a method that doesn't rely on the state of the DB (hooks, events, messages, etc).
  • Versioning the SortOrder to specific revisions of the Loadout, to create a link between SortOrders and the data they are being computed over. This might require a monotonically increasing revision attribute on the Loadouts to reference, and considering whether we would want to recompute the sorting for every Loadout change, or just the latest available.

Either of these require non insignificant changes in the code and our general approach when it comes to changing the loadout and reacting to it.

halgari and others added 30 commits October 7, 2024 10:23
# Conflicts:
#	src/Games/NexusMods.Games.RedEngine/RedModDeployTool.cs
- separate sorting data from the items being sorted, allowing more control
- Use ObservableList as base, and persist when it changes
- fix oderlist resetting DB on starup
# Conflicts:
#	NexusMods.App.sln
#	src/Abstractions/NexusMods.Abstractions.Games/RunGameTool.cs
#	src/Abstractions/NexusMods.Abstractions.Loadouts/ISynchronizerService.cs
#	src/Games/NexusMods.Games.RedEngine/RedModDeployTool.cs
#	src/NexusMods.App.UI/LeftMenu/Items/ApplyControlViewModel.cs
#	src/NexusMods.App.UI/LeftMenu/Items/LaunchButtonViewModel.cs
#	src/NexusMods.App.UI/NexusMods.App.UI.csproj
#	src/NexusMods.DataModel/Synchronizer/SynchronizerService.cs
- Have RedModDeployTool use the Provider rather than trying to get the order themselves
- add comments
… they are too susceptible irrelevant variations
# Conflicts:
#	tests/NexusMods.DataModel.SchemaVersions.Tests/LegacyDatabaseSupportTests.TestDatabase_name=SDV.4_11_2024.rocksdb.zip.verified.txt
#	tests/NexusMods.DataModel.SchemaVersions.Tests/Schema.verified.md
@Al12rs Al12rs self-assigned this Nov 13, 2024
@Al12rs Al12rs requested a review from a team November 13, 2024 16:27
@github-actions github-actions bot added the status-needs-rebase Set by CI do not remove label Nov 14, 2024
Copy link
Contributor

This PR conflicts with main. You need to rebase the PR before it can be merged.

# Conflicts:
#	src/NexusMods.App.UI/Pages/CollectionDownload/CollectionDownloadViewModel.cs
#	src/NexusMods.App.UI/Pages/LibraryPage/NexusModsFileMetadataLibraryItemModel.cs
Copy link
Contributor

This PR doesn't conflict with main anymore. It can be merged after all status checks have passed and it has been reviewed.

@github-actions github-actions bot removed the status-needs-rebase Set by CI do not remove label Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Review
Development

Successfully merging this pull request may close these issues.

2 participants