Skip to content

Levalicious/MO2-Oracle

Repository files navigation

Automated Mod Dependency Inference

This plugin is NOT READY FOR SERIOUS USAGE. It's getting there. Still purely experimental, but mildly coherent and should generally refrain from setting everything on fire.

BACK UP YOUR LOAD ORDER (PLUGIN AND MOD) BEFORE TRYING THIS

BACK UP YOUR LOAD ORDER (PLUGIN AND MOD) BEFORE TRYING THIS

BACK UP YOUR LOAD ORDER (PLUGIN AND MOD) BEFORE TRYING THIS

We ID mods by file content, not by mod name, as we need to explicitly distinguish versions.

The IDs are calculated by taking hashes of the installation file/archive of each mod. For CC mods, we utilize the es[m,p,l] & bsa files, and for the game we just take the hash of the version.

The mod hashing can be fragile. If you make changes to your mod files between plugin samples, or you use the Merge strategy on mod install, there is a very high likelihood of this plugin's internal DB breaking irrecoverably.

Installation

To install this, clone the repo to plugin_oracle in your MO2 plugin folder.

What It Does

Automatically learns the dependency structure of your modlist, and with enough information, can generate load orders guaranteed to respect it.

Follow Sets

Each mod maintains a follow set - the set of mods that, in all seen load orders, must come after this mod. Given that we take into account only the current active modlist, this allows us to learn a preorder over mods, as opposed to a poset. This means that we can recognize and coherently handle "equivalencies" between mods, such as Open Animation Replacer and Dynamic Animation Replacer. At the moment this is a bit broken, and only the poset behavior is reliable, but fixing it is a priority.

We maintain follow sets for both positive and negative samples. Only the positive samples are 'correct' - however, the negative samples allow us to generate incomparability graphs, which are dual to the preorder generated by the positive samples. That means that we can learn from both negative samples and positive samples, although as with most ML, positive samples will be more informative.

Oracle

Clicking the Oracle plugin menu option will bring up a window. If your follow sets are refined enough, the window will render the graph of the dependencies it believes to exist. To be more specific, if the graph of the current active load order's dependencies has cycles in it, the window will instead display an error message.

The window also offers some buttons for interacting with the oracle.

Oracle > Predict

Predict provides a list of mod order relations A -> B that it believes are invalid. It will frequently generate spurious invalid relations - these will decrease as the fsets refine, and should be completely precluded under Oracle > Sample, but that's for later.

Give it a few runs. It'll learn.

Oracle > Sample Random

Utility method for testing load orders & building up a database. These are purely random orders. They will look nonsensical, and are likely to cause issues.

Oracle > Sample

Generates a load order, like above. However, here the goal isn't to generate a random order for testing (well it does randomize too but that's besides the point). Rather than randomly shuffle the active mods, if the graph is sufficiently refined (that is, it successfully renders), we'll perform a random topological sort of it to generate a load order. This means any dependencies we are aware of, we will respect.

BACK UP YOUR LOAD ORDER (PLUGIN AND MOD) BEFORE TRYING THIS

BACK UP YOUR LOAD ORDER (PLUGIN AND MOD) BEFORE TRYING THIS

BACK UP YOUR LOAD ORDER (PLUGIN AND MOD) BEFORE TRYING THIS

okay, I tried. I take no responsibility if you ignored the repeated warnings and I messed up your mods.

Future Plans

  1. This used to be probabilistic. It no longer is. Restoring the probabilistic behavior is planned & shouldn't be overly complex or cause any regressions in functionality or spurious inaccuracies. Basically, we can still definitively capture explicit dependency relations, given enough samples.

  2. I still want to network this. The People(tm) can play more hours of Skyrim per hour than I can alone. Also, now that dependency structure is explicit and we have an explicit formulation for testing it, this means that instances can check the data they are supplied and call out misbehaving network participants (i.e. reporting invalid follow sets).

  3. We handle mod priority weirdly. First we set the priority of each mod, then we sync the plugins to match it, excepting plugin-defined dependency structure which overrides our ordering, i.e. master flags. There's definitely more coherent ways to handle this, but I need to think more/get some input on how to treat plugin order in relation to mod order, or if I even can treat them as strongly related in the general case.

  4. Follow sets are big and ugly. They're currently extremely heavily redundant, and unnecessarily so. Training/sampling/refinement will eliminate a significant number of those redundancies, but many will remain. Before I even consider networking for real, the db impl will need to be changed so that at a minimum, on-disk size will be small so we have a compressed format to relay.

  5. Until this is networked, I need to make it pull in LOOT and/or provide an initial database for people to use for it. If people want to help with the latter, send me a mod order you consider 'working'. Feel free to remove mods you don't want the world to see from the order, so long as you don't rearrange the priorities. I've gotten started on some utilities to automatically test mod orders, by doing a bit of computer vision & taking over the keyboard & mouse, but that's far off from usability, much less usefulness.

  6. Currently we treat the game as a permutation oracle that returns a boolean response. This works and even has non-horrible sample complexities, but with additional feedback we can gain a lot more information per tested order. What additional feedback? Crash logs. If we can even occasionally attribute failures to specific mods or dependency issues, that means significantly fewer samples to identify dependencies. With a boolean responses, the query complexity is O(n^2) worst case, but with attribution we can do much better. I think O(nlogn) worst case? On top of that, the O(n^2) sampling requires that we utilize a specific sampling strategy, 'building up' a valid dependency graph. As is, such a sampling strategy is not implemented. It most likely won't be, as both n^2 and nlogn involves a few too many game runs for a single human to be willing to sit through. If I finish the automated testing & crash attribution, I'll revisit this.

About

Why haven't we been using old ML on mod load orders?

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages