Skip to content

Commit

Permalink
Added Game type, Installed BepInEx fields for selected game
Browse files Browse the repository at this point in the history
  • Loading branch information
funlennysub committed Oct 15, 2022
1 parent 20caa19 commit ab44945
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 125 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
/.fleet
target
.fleet
Cargo.lock
45 changes: 45 additions & 0 deletions bepinex_helpers/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use std::{error, fmt::Display, io};

#[derive(Debug)]
pub enum ErrorCode {
Io(io::Error),
InvalidGameType,
}

impl Display for ErrorCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ErrorCode::Io(e) => write!(f, "{}", e),
ErrorCode::InvalidGameType => write!(f, "Invalid game type"),
}
}
}

#[derive(Debug)]
pub struct Error {
code: ErrorCode,
}

impl Error {
pub fn invalid_game_type() -> Self {
Error {
code: ErrorCode::InvalidGameType,
}
}
}

impl error::Error for Error {}

impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.code)
}
}

impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error {
code: ErrorCode::Io(e),
}
}
}
112 changes: 85 additions & 27 deletions bepinex_helpers/src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,55 @@ use semver::Version;
use std::{
error,
fmt::Display,
fs,
path::{Path, PathBuf},
str::FromStr,
};
use steamlocate::SteamDir;

use crate::error::Error;

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum GameType {
UnityMono,
UnityIL2CPP,
}

impl ToString for GameType {
fn to_string(&self) -> String {
match self {
Self::UnityMono => "UnityMono".into(),
Self::UnityIL2CPP => "UnityIL2CPP".into(),
}
}
}

impl FromStr for GameType {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"UnityMono" => Ok(Self::UnityMono),
"Mono" => Ok(Self::UnityMono),
"UnityIL2CPP" => Ok(Self::UnityIL2CPP),
"IL2CPP" => Ok(Self::UnityIL2CPP),
_ => Err(Error::invalid_game_type()),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
pub struct Game {
pub name: String,
pub arch: String,
pub path: PathBuf,
pub ty: Option<GameType>,
pub bepinex_version: Option<String>,
pub bepinex_version: Option<Version>,
}

impl Game {
pub fn set_bix(&mut self, bix: Option<String>) -> Game {
pub fn set_bix(&mut self, bix: Option<Version>) {
self.bepinex_version = bix;
self.to_owned()
}

pub fn set_arch(&mut self, arch: String) {
Expand All @@ -35,7 +61,7 @@ impl Game {
self.ty = ty;
}

pub fn get_installed_bepinex_version(&self) -> Option<String> {
pub fn get_installed_bepinex_version(&self) -> Option<Version> {
let core_path = self.path.join("BepInEx").join("core");
match core_path.exists() {
true => {
Expand All @@ -49,6 +75,30 @@ impl Game {
false => None,
}
}

pub fn get_game_type(&self) -> Option<GameType> {
let mono = "Managed";
let il2cpp = "il2cpp_data";

match fs::read_dir(&self.path) {
Ok(dir) => {
let data_dir = dir.filter_map(Result::ok).find(|el| {
el.file_name().to_str().unwrap().ends_with("_Data")
&& el.file_type().unwrap().is_dir()
});

let data_dir = data_dir.as_ref()?.path();
if data_dir.join(mono).exists() {
Some(GameType::UnityMono)
} else if data_dir.join(il2cpp).exists() {
Some(GameType::UnityIL2CPP)
} else {
None
}
}
_ => None,
}
}
}

impl Default for Game {
Expand All @@ -70,50 +120,58 @@ impl Display for Game {
}

pub fn get_unity_games() -> Result<Vec<Game>, Box<dyn error::Error>> {
let mut unity_games: Vec<Game> = Vec::new();

let mut steamapps = SteamDir::locate().unwrap_or_default();
let mut steamapps = SteamDir::locate().ok_or("Steam not found")?;
let apps = steamapps.apps();

apps.iter().for_each(|(_id, app)| match app {
Some(app) => {
let unity_games = apps
.iter()
.filter_map(|(_id, app)| app.as_ref())
.filter_map(|app| {
let path = Path::new(&app.path);
if path.join("UnityPlayer.dll").exists() {
let mut game = Game {
name: app.name.clone().unwrap_or_default(),
arch: "a".to_owned(),
path: app.path.to_owned(),
bepinex_version: None,
ty: None,
};
let bix_ver = game.get_installed_bepinex_version();
game.set_bix(bix_ver);

unity_games.push(game);
match path.join("UnityPlayer.dll").exists() {
true => {
let mut game = Game {
name: app.name.clone().unwrap_or_default(),
arch: "a".to_owned(),
path: app.path.to_owned(),
bepinex_version: None,
ty: None,
};

let bix_ver = game.get_installed_bepinex_version();
let game_type = game.get_game_type();
game.set_bix(bix_ver);
game.set_ty(game_type);

Some(game)
}
false => None,
}
}
None => {}
});
})
.collect::<Vec<_>>();
Ok(unity_games)
}

pub fn get_dll_version(path: PathBuf) -> Result<String, Box<dyn error::Error>> {
pub fn get_dll_version(path: PathBuf) -> Result<Version, Box<dyn error::Error>> {
let file = pelite::FileMap::open(path.as_path())?;
let img = pelite::PeFile::from_bytes(file.as_ref())?;
let resources = img.resources()?;
let version_info = resources.version_info()?;

let lang = version_info
.translation()
.get(0)
.ok_or("Failed to get lang")?;

let strings = version_info.file_info().strings;
let string = strings
.get(lang)
.ok_or("Failed to get strings for that lang")?;

let version = string
.get("ProductVersion")
.ok_or("Failed to get prod. version")?;

println!("{:?}", Version::parse(version));
Ok(version.to_owned())
// TODO: Do some proper handling of invalid semver that bix has in older versions 💀
Ok(Version::parse(version).unwrap())
}
1 change: 1 addition & 0 deletions bepinex_helpers/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod error;
pub mod game;
81 changes: 0 additions & 81 deletions bepinex_installer/src/error/mod.rs

This file was deleted.

Loading

0 comments on commit ab44945

Please sign in to comment.