[Suggestion] Better dependency resolution and display
Geode Version
v5.0.0
Related Problem
Motivation
- the current dependency system has unintuitive names on the developer sides, and lacks granular control
- the current dependency system does not sufficiently inform users what mods they are installing
Your Solution
Suggestion is to change how dependencies work both on the backend and in the UI.
Backend
A dependency, defined in the mod.json, may be one of 4 different types:
-
required: the user is not allowed to opt out of uninstalling this dependency if they want to use the mod; links with the dependency -
recommended: the user is prompted to install the dependency with it being checked by default (explained in the UI section); does not link with the dependency -
suggested: the user is prompted to install the dependency with it being unchecked by default; does not link with the dependency -
optional: the user does not see this at all, only used so that developers can use the mod's API to ensure compatibility if they need to; does not link with the dependency
UI
When a mod is being installed (perhaps even when enabling a disabled mod, maybe only if a required dependency is not satisfied), if a mod has non-optional dependencies, create a new popup that contains a series of checkboxes with the mod's dependencies, such that:
required dependencies are displayed in the list, but their checkbox is grayed out and cannot be unchecked
recommended dependencies are displayed in the list, their checkbox is checked by default, and the user may choose to uncheck it
suggested dependencies are displayed in the list, their checkbox is unchecked by default, and the user may choose to check it
optional dependencies are not displayed at all, and the mod is not installed automatically
If a mod does not have any non-optional dependencies, the popup is skipped and the mod is installed normally.
In the popup, the user may choose to abort the installation, in which case, nothing is done.
If the user chooses to install the mod, the mod, along with its (checked) dependencies, is installed.
Additional Information
Reasoning
This implementation makes it easier on developers, since they can use a mod's api without needing to suggest a dependency, where this would not count as an actual "suggestion". They are also given more granular control over the dependencies, helping make their intent with dependencies clear.
It also gives end-users more useful information; since they can see all the dependencies prior to the mod being installed, they can abort the installation if a mod needs to install a dependency they do not wish to use. They can also uncheck non-required dependencies without having to install mods without knowledge of what they install first and manually looking through the installed mods to figure out what a mod installation did.
Note
Obviously, not all (nor any, for that matter) of the ideas I throw around in this issue need to be implemented, I am just putting them here so that the specifics can be discussed later. Maybe it's worthwhile splitting this into multiple issues?
Kind of related: #1348
Additionally, since there would be a dependency installation popup if this were implemented, maybe it would be worth adding a message key to non-optional dependencies, which would be displayed in the popup next to the mod, informing the end-user what the dependency is used for.
How to deal with multiple dependency chains?
My idea is, if a dependency installation popup is confirmed, and the dependencies have their own dependencies, a separate dependency installation popup is opened for them.
This popup would be special in the sense that all the previously checked mods would have their checks grayed out (would act as if they are required, because they were accepted previously). This way, if you previously accepted a dependency, and another dependency depends on the same dependency, you cannot bring yourself into a nonsensical situation where a dependency is accepted once, and then denied later.
Another option would be to not display previously accepted dependencies at all, but I don't necessarily like that idea because it potentially hides information from the user, given that (assuming the message key is added), different mods may have different reasons for wanting a dependency, and I think all of those should be visible to the user.
One thing I do not know, because I haven't looked at the implementation; when loading mods currently, how does Geode deal with dependency cycles when making the dependency graph?
Explicitly/implicitly installed mods
Internally marking mods as explicitly installed or installed as dependencies. This would allow us to prompt uninstallation of mods that were not explicitly installed by the user and that do not have any dependents once a user uninstalls a dependent. Of course, give the user the ability to override this, and mark a mod as explicitly installed if need be.
Potentially also allow disabling dependencies of a mod if they are not required dependencies of another mod at the time of disabling. If they are non-required dependencies of another mod, allow disabling them, but add notes for which other mods are recommending/suggesting the mod you are allowed to disable, if there are any. The same would be done for uninstallation, except the mods would be prompted to be uninstalled instead of just disabled.
Apply the inverse for enabling; if there are any disabled dependencies, prompt enabling them (force enabling them if they are required).
Additionally, all of these should respect incompatibilities as well, where breaking acts as required but for a lack of a dependency, and conflicting acts as recommended but for a lack of a dependency. Not too sure about this, I haven't accounted for incompatibilities at all when thinking of this system; open to ideas on this one. Do incompatibilities need to be reworked in some way as well to work with the core suggestion of this issue?
Mod page changes
Allow viewing the dependencies of a mod in the mod page, to enable/disable/install/uninstall dependencies.
Going back to the initial idea of having nested dependencies creating multiple popups, maybe it would be a better idea to resolve the entire dependency chain first, and display all of them in the same popup. The resolution should take into account both dependencies and incompatibilities in this way:
- If a mod is
requiredat any point in the chain, require it to be installed; unless it is marked asbreakingwith another mod in the dependency chain (or a mod that the user has installed already), in which case, the installation cannot be completed, and we should warn the user about which action needs to be taken (maybe add an option to uninstall/disable the offending mod inside the popup as well, if it could cause the resolution to succeed). - If a mod is
recommendedat any point in the chain, enable its installation by default, unless it is marked asbreakingorconflictingwith another mod. Ifbreaking, disallow installing it (have the checkbox grayed out and unchecked) and emit a warning; ifconflicting, emit a warning and treat the mod as if it'ssuggested(i.e. unchecked by default). - If a mod is
suggestedat any point in the chain, disable its installation by default, unless it is marked asbreakingwith another mod. Ifbreaking, disallow installing it in the same was as in step 2 and emit a warning. - If a dependency cycle is detected, I'm not sure what to do, maybe abort the entire installation?
Essentially, incompatibilities should take priority over dependencies if they exist, given that a potential breakage is probably more important than a mod not having a non-required dependency (it was marked as non-required, after all).
Is there unaccounted for behavior in any of these steps?
(Edit: Oops, accidentally mentioned issue number 2, sorry)