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

Implemented a WIP Download Manager and reworked the UI for it #10

Merged
merged 35 commits into from
Jun 11, 2022

Conversation

Erdragh
Copy link
Contributor

@Erdragh Erdragh commented Jun 9, 2022

Disclaimer: This is a very WIP feature/overhaul, which is why I marked this as a draft. It is my first major thing built in rust, only my second ever project working with vue and my first time using tauri. If there are any things anybody would like to have changed or advise me about, I very much welcome it, as this is a pretty big opportunity to learn for me.

Here's a short demo of what I've been working on:

tmm.mp4

What I did / am doing here:

  • Rework the UI a bit to be responsive and make the window resizable
  • Implement the ModDownloader, ModManager and ModInstaller in seperate vue sfc files to keep things organized
  • Built a download backend in rust that can do single- and multithreaded downloads and communicate with the frontend based off of https://github.com/mattgathu/duma with modifications and omissions for this project
  • Build support for storing game download and mod files somewhere else than in the user's .config directory based off of game specific config files (which could also be implemented as a single large config file as a collection of all game profiles, not sure about that yet)

I also added features and planned features to the README on my branch to reflect the changes I'm working on: README.md

There is no support for Nexus Mod's "Mod Manager Download" yet and I don't know whether it will be easy to implement, but I don't think so, as you need to store user credentials etc. This means the download manager is at best only a commodity right now, but it's a WIP proof of concept.

Any criticism is also welcome, because - like I said - this is a learning opportunity for me :)

@MathiewMay MathiewMay marked this pull request as ready for review June 10, 2022 00:05
@MathiewMay
Copy link
Owner

MathiewMay commented Jun 10, 2022

Hi, thanks for the pull request, i like the ui changes you have made in, i was wondering how are you thinking of implement a nexus mods integration?

@@ -35,23 +38,70 @@ pub fn deploy(mods: Vec<Mod>, game: Game) {
pub fn scan_games() -> Vec<String> {
let mut steam_games: Vec<String> = Vec::new();
let steam_apps = SteamDir::locate().unwrap().apps().clone();

let mut known_path_extensions_json = dirs::config_dir().unwrap().join("tmm_stage").join("known_path_extensions");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crashes on scan games : No such file or directory of this type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned this in the README.md. I'm currently storing the known_path_extensions.json and the supported_games.json in the config dir and not handling what happens if they don't exist. I plan on moving them to the tauri dist folder, so they're bundled with the application when building. Since this is my first application with tauri though, I will still have to learn how to do that.

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 10, 2022

I turned the supported-games and known-path-extensions back into a single file and reworked its formatting to support multiple already known executables.

My game struct has a Vec/List of all known executables which is transmitted to the front end. This way an eventual launcher can select from the known binaries.

@Erdragh Erdragh requested a review from MathiewMay June 10, 2022 19:16
@jSQrD-dev
Copy link
Contributor

Looking at some of the indev issues on @Erdragh fork TMM needs a way to determine if a mod contains a data folder in the archive and if so use it. Would an MO2 like manual fix popup be a good solution?

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 10, 2022

I think there should be some default options the mod manager should be able to resolve for itself, but yes in my personal opinion such a popup would be a good idea. However there's also the issue with support fomod installers and the sort, which is another big topic, also for another time in another PR.

Copy link
Owner

@MathiewMay MathiewMay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mods do not deploy in path_extension, they deploy in the root of the game, maybe a bug or an oversight?

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 10, 2022

That is indeed weird, but I don't have time for anymore programming today, sadly. I will look into this tomorrow.

@MathiewMay
Copy link
Owner

That is indeed weird, but I don't have time for anymore programming today, sadly. I will look into this tomorrow.

no worries i will take a look now.

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 11, 2022

no worries i will take a look now.

Did you find anything? I'm currently looking into this and in ofs.rs the previous code looks like this:

impl OFSLogic {
  pub fn exec(&self) {
    let mut mod_paths: Vec<PathBuf> = Vec::new();
    let upper_path: PathBuf = PathBuf::new().join(&self.game.path);
    let work_path: PathBuf = dirs::home_dir().unwrap().join(&self.game.work_path);
    
    for elem in &self.mods {
      mod_paths.push(PathBuf::new().join(&elem.path));
    }

    init_overlay_fs(mod_paths, &upper_path, &upper_path, &work_path);
  }
}

And my code like this:

impl OFSLogic {
  pub fn exec(&self) {
    let mut mod_paths: Vec<PathBuf> = Vec::new();
    let upper_path: PathBuf = PathBuf::new().join(&self.game.install_path);
    let work_path: PathBuf = PathBuf::new().join(&self.game.work_path);
    
    for elem in &self.mods {
      mod_paths.push(PathBuf::new().join(&self.game.profile_path.join("mods").join(&elem.name)));
    }

    init_overlay_fs(mod_paths, &upper_path, &upper_path, &work_path);
  }
}

From what I can tell the same bug should be present in the current version also, shouldn't it? To quote my version of README.md:

For games with path extensions, some mods may have the extension folder already in their archive, some may not. This means that sometimes a mod has the extension folder, sometimes it doesn't. In the end this would resoult in the Game not reading some mods, because they're essentially in the wrong folder (e.g. data/data/)

Maybe it's a variation of that issue, but that a mod looks like ~/.config/tmm/profiles/GAME_APPID/mods/MOD_NAME/MOD_PLUGIN.esp instead of ~/.config/tmm/profiles/GAME_APPID/mods/MOD_NAME/Data/MOD_PLUGIN.esp

If that's the case it should be decided whether we want mods in their folder to look like the former or the latter. Because if it's the former then the path_extension should be added to the path of the OFS and if it's the latter then the path_extension should probably be added when uncompressing a mod. Referring back to my quote from earlier, the problem is that some mods have a data folder, some don't and some are FOMOD installers, where you have to select options and the mod will be installed depending on those options.


If I overlooked something or misunderstood something please let me know.

@MathiewMay
Copy link
Owner

MathiewMay commented Jun 11, 2022

no worries i will take a look now.

Did you find anything? I'm currently looking into this and in ofs.rs the previous code looks like this:

impl OFSLogic {
  pub fn exec(&self) {
    let mut mod_paths: Vec<PathBuf> = Vec::new();
    let upper_path: PathBuf = PathBuf::new().join(&self.game.path);
    let work_path: PathBuf = dirs::home_dir().unwrap().join(&self.game.work_path);
    
    for elem in &self.mods {
      mod_paths.push(PathBuf::new().join(&elem.path));
    }

    init_overlay_fs(mod_paths, &upper_path, &upper_path, &work_path);
  }
}

And my code like this:

impl OFSLogic {
  pub fn exec(&self) {
    let mut mod_paths: Vec<PathBuf> = Vec::new();
    let upper_path: PathBuf = PathBuf::new().join(&self.game.install_path);
    let work_path: PathBuf = PathBuf::new().join(&self.game.work_path);
    
    for elem in &self.mods {
      mod_paths.push(PathBuf::new().join(&self.game.profile_path.join("mods").join(&elem.name)));
    }

    init_overlay_fs(mod_paths, &upper_path, &upper_path, &work_path);
  }
}

From what I can tell the same bug should be present in the current version also, shouldn't it? To quote my version of README.md:

For games with path extensions, some mods may have the extension folder already in their archive, some may not. This means that sometimes a mod has the extension folder, sometimes it doesn't. In the end this would resoult in the Game not reading some mods, because they're essentially in the wrong folder (e.g. data/data/)

Maybe it's a variation of that issue, but that a mod looks like ~/.config/tmm/profiles/GAME_APPID/mods/MOD_NAME/MOD_PLUGIN.esp instead of ~/.config/tmm/profiles/GAME_APPID/mods/MOD_NAME/Data/MOD_PLUGIN.esp

If that's the case it should be decided whether we want mods in their folder to look like the former or the latter. Because if it's the former then the path_extension should be added to the path of the OFS and if it's the latter then the path_extension should probably be added when uncompressing a mod. Referring back to my quote from earlier, the problem is that some mods have a data folder, some don't and some are FOMOD installers, where you have to select options and the mod will be installed depending on those options.

If I overlooked something or misunderstood something please let me know.

the differance is in where i uncompress the archive files, i don't just uncompress them in mod/mod_name/, its in mod/mod_name/path_extension/

i think it would be better to implement it in the OFS to future proof.

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 11, 2022

So basically turning

let upper_path: PathBuf = PathBuf::new().join(&self.game.install_path);

into

let upper_path: PathBuf = PathBuf::new().join(&self.game.install_path).join(&self.game.path_extension);

?

@MathiewMay
Copy link
Owner

So basically turning

let upper_path: PathBuf = PathBuf::new().join(&self.game.install_path);

into

let upper_path: PathBuf = PathBuf::new().join(&self.game.install_path).join(&self.game.path_extension);

?

that would output /Data/ or what ever the extension is i don't remebr why exactly but i had a simillar issue.

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 11, 2022

What do you mean, upper_path just being "/Data/"?

@MathiewMay
Copy link
Owner

What do you mean, upper_path just being "/Data/"?

yes its a weird thing

` let mut mod_paths: Vec = Vec::new();
let upper_path: PathBuf = PathBuf::new().join(&self.game.install_path).join(&self.game.path_extension);
let work_path: PathBuf = PathBuf::new().join(&self.game.work_path);
println!("{:?}", upper_path);

for elem in &self.mods {
  mod_paths.push(PathBuf::new().join(&self.game.profile_path.join("mods").join(&elem.name)));
}

println!("{:?}", mod_paths);
init_overlay_fs(mod_paths, &upper_path, &upper_path, &work_path);`

the output is

"/Data/" ["/home/*/.config/tmm/profiles/489830/mods/Unofficial Skyrim Special Edition Patch-266-4-2-6a-1636838663"]

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 11, 2022

How about

let upper_path: PathBuf = PathBuf::new().join(format!("{}{}", &self.game.install_path, &self.game.path_extension);

?

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 11, 2022

I think the issue is that the Path Extension is saved as /Data/ instead of Data/ and the PathBuf assumes the / in the beginning signifies it to be the filesystem root? This is just a far out guess.

@MathiewMay
Copy link
Owner

I think the issue is that the Path Extension is saved as /Data/ instead of Data/ and the PathBuf assumes the / in the beginning signifies it to be the filesystem root? This is just a far out guess.

yes now that i think of it that is the issue.

@MathiewMay
Copy link
Owner

I will review the changes soon.

@MathiewMay MathiewMay self-requested a review June 11, 2022 19:00
@MathiewMay
Copy link
Owner

If you are ready i can merge your pull request @Erdragh

@Erdragh
Copy link
Contributor Author

Erdragh commented Jun 11, 2022

I don't have anything more for this PR, I say go for it!

@MathiewMay MathiewMay merged commit 507bdfe into MathiewMay:master Jun 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants