mickael9 / fac

Command-line mod manager for Factorio (install, update...)
MIT License
50 stars 17 forks source link

[RFC] Things to include in a prefix PR #16

Open jmerdich opened 6 years ago

jmerdich commented 6 years ago

I've been managing multiple instances of factorio for a while (for multiple servers with different versions and mod packs), and recently discovered this tool. While super-awesome (and having quite high-quality code, kudos to @mickael9), it doesn't quite fit my use case. I want to write a PR to manage multiple instances of factorio (call it prefixes, environments, modpacks, whatever), but anything this sweeping should involve some input from the original devs and community, not just having me vomit code everywhere (and having this wall of text under a comment seemed bad). If the response here is negative, I will try to oblige users' opinions or else keep a separate fork under a different name.

Desired features:

Points of Debate:

Selecting a Prefix:

  1. Command line flag fac -p <prefix> <command> This is the easiest to implement by far, but involves using a flag for every invocation of fac. This must be added every time, and missing the flag will result in applying the command to the default prefix. It is, however, very obvious and requires no magic or bash/zsh wizardry.

  2. Prefix activation via shell fac activate <prefix> This is the most convenient, but relies on the user having a compatible shell and involves additional setup. We'd need to force users to include the zsh script (and probably introduce a bash equivalent for compatibility). The active prefix is stored in an environment variable, and is unique per shell session. We also lose all hope of including windows users in a convenient fashion.

  1. Prefix activation via file fac activate <prefix> Like 2, but doesn't use shell functions but rather saves the current prefix to the config file. Far more compatible, but it introduces some non-obvious behavior since the prefix is global (per-user) rather than session-specific.

I am personally in favor of implementing both 1 and 2. Comments welcome!

Storing prefix configuration

Python's ConfigParser (what's currently used) has some really nice features for default and fallback values that can be used very well for prefixes..... but the current config file layout won't work well for this, since it wasn't designed with this in mind.

Note: things of the syntax ${foo} are left as-is in the config.ini and are handled automatically since Python is awesome.

Current Layout

[mods]
hold =

[paths]
data-path =
write-path =
  1. Tack it on and handle defaults manually
    
    [mods]
    hold =

[paths] data-path = write-path =

[some_prefix] write-path = hold =

data-path is noted to be missing, and manually read from [paths]

Each prefix gets a new section, and the old sections (mods/paths) stay. We'd need to manually handle fallbacks to default, though, which means special-casing each current variable. Alternatively, require all variables in every prefix (defaults looking like `data-path=${paths:data-path}`)

2. Change to let ConfigParser handle everything

New:

auto-generated during first run.

[DEFAULTS] hold = data-path = write-path =

[some_prefix] write-path = hold =

data-path falls back to DEFAULTS


Migrated:

From previous version

[mods] hold =

[paths] data-path = write-path =

auto-generated during migration.

[DEFAULTS] hold = ${mods:hold} data-path = ${paths:data-path} write-path = ${paths:write-path}

[some_prefix] write-path = hold =

data-path falls back to DEFAULTS, which points to [paths]

Each prefix gets a new section, and the old sections (mods/paths) stay. More future-proof and less code bloat, but we'd need to add the DEFAULT section with pointers to migrate existing config files.

## What should be shared between prefixes?

Should settings be different between them (ie, separate write-path?). If factorio introduces another breaking change in config/ (last was 0.14 -> 0.15, last I checked), things will get migrated without warning and older versions won't be happy. Factorio is backwards-compatible, but not always forwards-compatible. Ditto for save files, although those should only occur on opening the save. Presumably, this should be able to be manually selected (ie. separate mod-path from write-path), but should the default be separate or combined?

## New variables and defaults

No matter the defaults above, some new variables should be included:
 - `executable-path`: Path to factorio binary (since we have to have a run-from-prefix option, yeah?). Optionally overridden per prefix. Default: `${data-path}/../bin/x64/factorio[.exe]`
 - `mod-path`: Path to mods directory. Should definitely be overridden per prefix. Default: `${prefix-base-path}/[prefix-name]/mods`
 - `prefix-base-path`: Prefix storage directory, relative to fac config directory. Global. Default `prefixes/`
 - `game-base-path`: Factorio version storage directory, relative to fac config directory. Useful if you want to store it on a different drive. Global. Default `game_versions/`
 - `username`: Factorio credentials, used for game downloads. Global and optional.
 - `password`: Factorio credentials, used for game downloads. Global and optional. Also insecure, but hey, it's convenient. 
 - `password_cmd`: Command to obtain the factorio password, presumably through some password manager or the system keychain. Mac users may get a default using `/usr/bin/security`, but someone will have to help testing there, since I don't own one. 

This leaves the following directory layout. Thoughts?

FAC_DIR/ |--- config.ini |--- prefixes/ (default prefix-base-path) | |--- prefix_1/ (separate game config) | | |--- mods/ | | |--- player_data.json | | |--- config/ | |--- prefix_2/ (combined game config) | |--- mods/ |--- game_versions/ (default game-base-path) |--- 0.15.4/ |--- 0.16.20/ |--- 0.16.20-headless/



## Commands

The PR is going to add a lot of subcommands:
 - Creating prefixes 
 - Listing prefixes
 - Removing prefixes
 - Switching to prefixes (depending on answers above)
 - Running the game in a prefix
 - Downloading/Updating current factorio version
 - Listing installed factorio versions
 - Removing a factorio version (or all unused)
 - (Eventually) syncing prefix from multiplayer server

That leaves a whopping 23 subcommands, and things like 'install' will get pretty ambiguous pretty quick. Is a restructure necessary ("fac mods enable modname", "fac game update 0.14", "fac prefix create prefixname", etc?). If so, this is a very breaking change. I'm going to use commands assuming no restructure like "fac makeprefix" in the meantime, but this should be considered.