1.2.0
- added sessions manager
This commit is contained in:
parent
7ba4b13c04
commit
7e7db30de4
9 changed files with 404 additions and 2 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "anime-launcher-sdk"
|
name = "anime-launcher-sdk"
|
||||||
version = "1.1.6"
|
version = "1.2.0"
|
||||||
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -40,10 +40,11 @@ components = ["dep:wincompatlib", "dep:lazy_static"]
|
||||||
game = ["components", "config"]
|
game = ["components", "config"]
|
||||||
discord-rpc = ["dep:discord-rich-presence"]
|
discord-rpc = ["dep:discord-rich-presence"]
|
||||||
sandbox = []
|
sandbox = []
|
||||||
|
sessions = []
|
||||||
|
|
||||||
# Genshin-specific features
|
# Genshin-specific features
|
||||||
environment-emulation = []
|
environment-emulation = []
|
||||||
fps-unlocker = ["dep:md-5"]
|
fps-unlocker = ["dep:md-5"]
|
||||||
|
|
||||||
all = ["states", "config", "components", "game", "discord-rpc", "sandbox", "environment-emulation", "fps-unlocker"]
|
all = ["states", "config", "components", "game", "discord-rpc", "sandbox", "sessions", "environment-emulation", "fps-unlocker"]
|
||||||
default = ["all"]
|
default = ["all"]
|
||||||
|
|
|
@ -14,3 +14,6 @@ pub mod fps_unlocker;
|
||||||
|
|
||||||
#[cfg(feature = "game")]
|
#[cfg(feature = "game")]
|
||||||
pub mod game;
|
pub mod game;
|
||||||
|
|
||||||
|
#[cfg(feature = "sessions")]
|
||||||
|
pub mod sessions;
|
||||||
|
|
105
src/games/genshin/sessions.rs
Normal file
105
src/games/genshin/sessions.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::sessions::{
|
||||||
|
SessionsExt,
|
||||||
|
Sessions as SessionsDescriptor
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::consts::launcher_dir;
|
||||||
|
|
||||||
|
/// Get default sessions file path
|
||||||
|
///
|
||||||
|
/// `$HOME/.local/share/anime-game-launcher/sessions.json`
|
||||||
|
#[inline]
|
||||||
|
pub fn sessions_file() -> anyhow::Result<PathBuf> {
|
||||||
|
launcher_dir().map(|dir| dir.join("sessions.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SessionData {
|
||||||
|
// [Software\\miHoYo\\Genshin Impact]
|
||||||
|
pub game_reg: String,
|
||||||
|
|
||||||
|
// [Software\\miHoYoSDK]
|
||||||
|
pub sdk_reg: String
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sessions;
|
||||||
|
|
||||||
|
impl SessionsExt for Sessions {
|
||||||
|
type SessionData = SessionData;
|
||||||
|
|
||||||
|
fn get_sessions() -> anyhow::Result<SessionsDescriptor<Self::SessionData>> {
|
||||||
|
let path = sessions_file()?;
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
tracing::warn!("Session file doesn't exist. Returning default value");
|
||||||
|
|
||||||
|
return Ok(SessionsDescriptor::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(serde_json::from_slice(&std::fs::read(path)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_sessions(sessions: SessionsDescriptor<Self::SessionData>) -> anyhow::Result<()> {
|
||||||
|
Ok(std::fs::write(sessions_file()?, serde_json::to_string_pretty(&sessions)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||||
|
let mut sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
tracing::info!("Updating session '{name}' from prefix: {:?}", prefix.as_ref());
|
||||||
|
|
||||||
|
let mut new_session = Self::SessionData {
|
||||||
|
game_reg: String::new(),
|
||||||
|
sdk_reg: String::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
for entry in std::fs::read_to_string(prefix.as_ref().join("user.reg"))?.split("\n\n") {
|
||||||
|
if entry.starts_with("[Software\\\\miHoYo\\\\Genshin Impact]") {
|
||||||
|
new_session.game_reg = entry.to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if entry.starts_with("[Software\\\\miHoYoSDK]") {
|
||||||
|
new_session.sdk_reg = entry.to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.sessions.insert(name, new_session);
|
||||||
|
|
||||||
|
Self::set_sessions(sessions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||||
|
let sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
let Some(session) = sessions.sessions.get(&name) else {
|
||||||
|
anyhow::bail!("Session with given name doesn't exist");
|
||||||
|
};
|
||||||
|
|
||||||
|
tracing::info!("Applying session '{name}' to prefix: {:?}", prefix.as_ref());
|
||||||
|
|
||||||
|
let entries: String = std::fs::read_to_string(prefix.as_ref().join("user.reg"))?
|
||||||
|
.split("\n\n")
|
||||||
|
.map(|entry| {
|
||||||
|
let new_entry = if entry.starts_with("[Software\\\\miHoYo\\\\Genshin Impact]") {
|
||||||
|
session.game_reg.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
else if entry.starts_with("[Software\\\\miHoYoSDK]") {
|
||||||
|
session.sdk_reg.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
entry.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
new_entry + "\n\n"
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(std::fs::write(prefix.as_ref().join("user.reg"), format!("{}\n", entries.trim_end()))?)
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,3 +8,6 @@ pub mod states;
|
||||||
|
|
||||||
#[cfg(feature = "game")]
|
#[cfg(feature = "game")]
|
||||||
pub mod game;
|
pub mod game;
|
||||||
|
|
||||||
|
#[cfg(feature = "sessions")]
|
||||||
|
pub mod sessions;
|
||||||
|
|
105
src/games/honkai/sessions.rs
Normal file
105
src/games/honkai/sessions.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::sessions::{
|
||||||
|
SessionsExt,
|
||||||
|
Sessions as SessionsDescriptor
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::consts::launcher_dir;
|
||||||
|
|
||||||
|
/// Get default sessions file path
|
||||||
|
///
|
||||||
|
/// `$HOME/.local/share/honkers-launcher/sessions.json`
|
||||||
|
#[inline]
|
||||||
|
pub fn sessions_file() -> anyhow::Result<PathBuf> {
|
||||||
|
launcher_dir().map(|dir| dir.join("sessions.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SessionData {
|
||||||
|
// [Software\\miHoYo\\Honkai Impact 3rd]
|
||||||
|
pub game_reg: String,
|
||||||
|
|
||||||
|
// [Software\\miHoYoSDK]
|
||||||
|
pub sdk_reg: String
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sessions;
|
||||||
|
|
||||||
|
impl SessionsExt for Sessions {
|
||||||
|
type SessionData = SessionData;
|
||||||
|
|
||||||
|
fn get_sessions() -> anyhow::Result<SessionsDescriptor<Self::SessionData>> {
|
||||||
|
let path = sessions_file()?;
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
tracing::warn!("Session file doesn't exist. Returning default value");
|
||||||
|
|
||||||
|
return Ok(SessionsDescriptor::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(serde_json::from_slice(&std::fs::read(path)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_sessions(sessions: SessionsDescriptor<Self::SessionData>) -> anyhow::Result<()> {
|
||||||
|
Ok(std::fs::write(sessions_file()?, serde_json::to_string_pretty(&sessions)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||||
|
let mut sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
tracing::info!("Updating session '{name}' from prefix: {:?}", prefix.as_ref());
|
||||||
|
|
||||||
|
let mut new_session = Self::SessionData {
|
||||||
|
game_reg: String::new(),
|
||||||
|
sdk_reg: String::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
for entry in std::fs::read_to_string(prefix.as_ref().join("user.reg"))?.split("\n\n") {
|
||||||
|
if entry.starts_with("[Software\\\\miHoYo\\\\Honkai Impact 3rd]") {
|
||||||
|
new_session.game_reg = entry.to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if entry.starts_with("[Software\\\\miHoYoSDK]") {
|
||||||
|
new_session.sdk_reg = entry.to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.sessions.insert(name, new_session);
|
||||||
|
|
||||||
|
Self::set_sessions(sessions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||||
|
let sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
let Some(session) = sessions.sessions.get(&name) else {
|
||||||
|
anyhow::bail!("Session with given name doesn't exist");
|
||||||
|
};
|
||||||
|
|
||||||
|
tracing::info!("Applying session '{name}' to prefix: {:?}", prefix.as_ref());
|
||||||
|
|
||||||
|
let entries: String = std::fs::read_to_string(prefix.as_ref().join("user.reg"))?
|
||||||
|
.split("\n\n")
|
||||||
|
.map(|entry| {
|
||||||
|
let new_entry = if entry.starts_with("[Software\\\\miHoYo\\\\Honkai Impact 3rd]") {
|
||||||
|
session.game_reg.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
else if entry.starts_with("[Software\\\\miHoYoSDK]") {
|
||||||
|
session.sdk_reg.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
entry.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
new_entry + "\n\n"
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(std::fs::write(prefix.as_ref().join("user.reg"), format!("{}\n", entries.trim_end()))?)
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,3 +8,6 @@ pub mod states;
|
||||||
|
|
||||||
#[cfg(feature = "game")]
|
#[cfg(feature = "game")]
|
||||||
pub mod game;
|
pub mod game;
|
||||||
|
|
||||||
|
#[cfg(feature = "sessions")]
|
||||||
|
pub mod sessions;
|
||||||
|
|
105
src/games/star_rail/sessions.rs
Normal file
105
src/games/star_rail/sessions.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::sessions::{
|
||||||
|
SessionsExt,
|
||||||
|
Sessions as SessionsDescriptor
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::consts::launcher_dir;
|
||||||
|
|
||||||
|
/// Get default sessions file path
|
||||||
|
///
|
||||||
|
/// `$HOME/.local/share/honkers-railway-launcher/sessions.json`
|
||||||
|
#[inline]
|
||||||
|
pub fn sessions_file() -> anyhow::Result<PathBuf> {
|
||||||
|
launcher_dir().map(|dir| dir.join("sessions.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SessionData {
|
||||||
|
// [Software\\Cognosphere\\Star Rail]
|
||||||
|
pub game_reg: String,
|
||||||
|
|
||||||
|
// [Software\\miHoYoSDK]
|
||||||
|
pub sdk_reg: String
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sessions;
|
||||||
|
|
||||||
|
impl SessionsExt for Sessions {
|
||||||
|
type SessionData = SessionData;
|
||||||
|
|
||||||
|
fn get_sessions() -> anyhow::Result<SessionsDescriptor<Self::SessionData>> {
|
||||||
|
let path = sessions_file()?;
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
tracing::warn!("Session file doesn't exist. Returning default value");
|
||||||
|
|
||||||
|
return Ok(SessionsDescriptor::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(serde_json::from_slice(&std::fs::read(path)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_sessions(sessions: SessionsDescriptor<Self::SessionData>) -> anyhow::Result<()> {
|
||||||
|
Ok(std::fs::write(sessions_file()?, serde_json::to_string_pretty(&sessions)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||||
|
let mut sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
tracing::info!("Updating session '{name}' from prefix: {:?}", prefix.as_ref());
|
||||||
|
|
||||||
|
let mut new_session = Self::SessionData {
|
||||||
|
game_reg: String::new(),
|
||||||
|
sdk_reg: String::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
for entry in std::fs::read_to_string(prefix.as_ref().join("user.reg"))?.split("\n\n") {
|
||||||
|
if entry.starts_with("[Software\\\\Cognosphere\\\\Star Rail]") {
|
||||||
|
new_session.game_reg = entry.to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if entry.starts_with("[Software\\\\miHoYoSDK]") {
|
||||||
|
new_session.sdk_reg = entry.to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.sessions.insert(name, new_session);
|
||||||
|
|
||||||
|
Self::set_sessions(sessions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||||
|
let sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
let Some(session) = sessions.sessions.get(&name) else {
|
||||||
|
anyhow::bail!("Session with given name doesn't exist");
|
||||||
|
};
|
||||||
|
|
||||||
|
tracing::info!("Applying session '{name}' to prefix: {:?}", prefix.as_ref());
|
||||||
|
|
||||||
|
let entries: String = std::fs::read_to_string(prefix.as_ref().join("user.reg"))?
|
||||||
|
.split("\n\n")
|
||||||
|
.map(|entry| {
|
||||||
|
let new_entry = if entry.starts_with("[Software\\\\Cognosphere\\\\Star Rail]") {
|
||||||
|
session.game_reg.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
else if entry.starts_with("[Software\\\\miHoYoSDK]") {
|
||||||
|
session.sdk_reg.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
entry.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
new_entry + "\n\n"
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(std::fs::write(prefix.as_ref().join("user.reg"), format!("{}\n", entries.trim_end()))?)
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,9 @@ pub mod components;
|
||||||
#[cfg(feature = "discord-rpc")]
|
#[cfg(feature = "discord-rpc")]
|
||||||
pub mod discord_rpc;
|
pub mod discord_rpc;
|
||||||
|
|
||||||
|
#[cfg(feature = "sessions")]
|
||||||
|
pub mod sessions;
|
||||||
|
|
||||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
/// Check if specified binary is available
|
/// Check if specified binary is available
|
||||||
|
|
74
src/sessions.rs
Normal file
74
src/sessions.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
use std::path::Path;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct Sessions<SessionData> {
|
||||||
|
pub current: Option<String>,
|
||||||
|
pub sessions: HashMap<String, SessionData>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Sessions<T> {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
current: None,
|
||||||
|
sessions: HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait SessionsExt {
|
||||||
|
type SessionData;
|
||||||
|
|
||||||
|
/// Get sessions descriptor
|
||||||
|
///
|
||||||
|
/// If it doesn't exist, then default values will be returned
|
||||||
|
fn get_sessions() -> anyhow::Result<Sessions<Self::SessionData>>;
|
||||||
|
|
||||||
|
/// Update sessions descriptor
|
||||||
|
fn set_sessions(sessions: Sessions<Self::SessionData>) -> anyhow::Result<()>;
|
||||||
|
|
||||||
|
/// Get current session name
|
||||||
|
fn get_current() -> anyhow::Result<Option<String>> {
|
||||||
|
Ok(Self::get_sessions()?.current)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set current session name
|
||||||
|
fn set_current(name: String) -> anyhow::Result<()> {
|
||||||
|
let mut sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
sessions.current = Some(name);
|
||||||
|
|
||||||
|
Self::set_sessions(sessions)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List available sessions
|
||||||
|
fn list() -> anyhow::Result<HashMap<String, Self::SessionData>> {
|
||||||
|
Ok(Self::get_sessions()?.sessions)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove session with given name
|
||||||
|
///
|
||||||
|
/// Sets current session to `None` if its name passed
|
||||||
|
fn remove(name: impl AsRef<str>) -> anyhow::Result<()> {
|
||||||
|
let mut sessions = Self::get_sessions()?;
|
||||||
|
|
||||||
|
if let Some(current) = &sessions.current {
|
||||||
|
if current == name.as_ref() {
|
||||||
|
sessions.current = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.sessions.remove(name.as_ref());
|
||||||
|
|
||||||
|
Self::set_sessions(sessions)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update saved session using files from the wine prefix
|
||||||
|
fn update(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()>;
|
||||||
|
|
||||||
|
/// Apply saved session to the wine prefix
|
||||||
|
fn apply(name: String, prefix: impl AsRef<Path>) -> anyhow::Result<()>;
|
||||||
|
}
|
Loading…
Reference in a new issue