feat: initial support for segatools pkgs
This commit is contained in:
@ -45,11 +45,15 @@ pub async fn kill() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn install_package(state: State<'_, tokio::sync::Mutex<AppData>>, key: PkgKey) -> Result<InstallResult, String> {
|
||||
pub async fn install_package(
|
||||
state: State<'_, tokio::sync::Mutex<AppData>>,
|
||||
key: PkgKey,
|
||||
force: bool
|
||||
) -> Result<InstallResult, String> {
|
||||
log::debug!("invoke: install_package({})", key);
|
||||
|
||||
let mut appd = state.lock().await;
|
||||
appd.pkgs.install_package(&key, true, true)
|
||||
appd.pkgs.install_package(&key, force, true)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
use std::path::PathBuf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::pkg::PkgKey;
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
pub struct Segatools {
|
||||
pub target: PathBuf,
|
||||
pub hook: Option<PkgKey>,
|
||||
pub io: Option<PkgKey>,
|
||||
pub amfs: PathBuf,
|
||||
pub option: PathBuf,
|
||||
pub appdata: PathBuf,
|
||||
@ -15,6 +18,8 @@ impl Default for Segatools {
|
||||
fn default() -> Self {
|
||||
Segatools {
|
||||
target: PathBuf::default(),
|
||||
hook: Some(PkgKey("segatools-mu3hook".to_owned())),
|
||||
io: None,
|
||||
amfs: PathBuf::default(),
|
||||
option: PathBuf::default(),
|
||||
appdata: PathBuf::from("appdata"),
|
||||
|
@ -1,14 +1,16 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use serde::Deserialize;
|
||||
use crate::pkg::PkgKeyVersion;
|
||||
|
||||
// manifest.json
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
pub struct PackageManifest {
|
||||
pub name: String,
|
||||
pub version_number: String,
|
||||
pub description: String,
|
||||
pub dependencies: BTreeSet<PkgKeyVersion>
|
||||
}
|
||||
pub dependencies: BTreeSet<PkgKeyVersion>,
|
||||
|
||||
#[serde(default)]
|
||||
pub installers: Vec<BTreeMap<String, serde_json::Value>>
|
||||
}
|
@ -1,9 +1,5 @@
|
||||
pub fn segatools_base() -> String {
|
||||
"; mu3io is TBD
|
||||
[mu3io]
|
||||
path=
|
||||
|
||||
[vfd]
|
||||
"[vfd]
|
||||
; Enable VFD emulation. Disable to use a real VFD
|
||||
; GP1232A02A FUTABA assembly.
|
||||
enable=1
|
||||
|
@ -57,6 +57,14 @@ impl Segatools {
|
||||
.set("enable", "0");
|
||||
}
|
||||
|
||||
if let Some(io) = &self.io {
|
||||
ini_out.with_section(Some("mu3io"))
|
||||
.set("path", util::pkg_dir().join(io.to_string()).join("mu3io.dll").stringify()?);
|
||||
} else {
|
||||
ini_out.with_section(Some("mu3io"))
|
||||
.set("path", "");
|
||||
}
|
||||
|
||||
log::debug!("option dir: {:?} -> {:?}", opt_dir_in, opt_dir_out);
|
||||
|
||||
if !opt_dir_out.exists() {
|
||||
|
@ -3,7 +3,7 @@ use derive_more::Display;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::BTreeSet, path::{Path, PathBuf}};
|
||||
use tokio::fs;
|
||||
use crate::{model::{local, rainy}, util};
|
||||
use crate::{model::{local::{self, PackageManifest}, rainy}, util};
|
||||
|
||||
// {namespace}-{name}
|
||||
#[derive(Eq, Hash, PartialEq, PartialOrd, Ord, Clone, Serialize, Deserialize, Display)]
|
||||
@ -27,8 +27,10 @@ pub struct Package {
|
||||
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Kind {
|
||||
Unchecked,
|
||||
Unsupported,
|
||||
#[default] Mod,
|
||||
Unsupported
|
||||
Hook,
|
||||
IO,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
@ -84,6 +86,7 @@ impl Package {
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
|
||||
let kind = Self::parse_kind(&mft);
|
||||
let dependencies = Self::sanitize_deps(mft.dependencies);
|
||||
|
||||
Ok(Package {
|
||||
@ -94,7 +97,7 @@ impl Package {
|
||||
loc: Some(Local {
|
||||
version: mft.version_number,
|
||||
path: dir.to_owned(),
|
||||
kind: Kind::Mod,
|
||||
kind,
|
||||
dependencies
|
||||
}),
|
||||
rmt: None
|
||||
@ -166,4 +169,25 @@ impl Package {
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn parse_kind(mft: &PackageManifest) -> Kind {
|
||||
if mft.installers.len() == 0 {
|
||||
return Kind::Mod;//Unchecked
|
||||
} else if mft.installers.len() == 1 {
|
||||
if let Some(serde_json::Value::String(id)) = &mft.installers[0].get("identifier") {
|
||||
if id == "rainycolor" {
|
||||
return Kind::Mod
|
||||
} else if id == "segatools" {
|
||||
if let Some(serde_json::Value::String(module)) = mft.installers[0].get("module") {
|
||||
if module.ends_with("hook") {
|
||||
return Kind::Hook;
|
||||
} else if module.ends_with("io") {
|
||||
return Kind::IO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Kind::Unsupported
|
||||
}
|
||||
}
|
@ -120,13 +120,14 @@ impl PackageStore {
|
||||
}
|
||||
|
||||
pub async fn install_package(&mut self, key: &PkgKey, force: bool, install_deps: bool) -> Result<InstallResult> {
|
||||
log::debug!("Installing {}", key);
|
||||
log::info!("installation request: {}/{}/{}", key, force, install_deps);
|
||||
|
||||
let pkg = self.store.get(key)
|
||||
.ok_or_else(|| anyhow!("Attempted to install a nonexistent pkg"))?
|
||||
.clone();
|
||||
|
||||
if pkg.loc.is_some() && !force {
|
||||
log::debug!("installation skipped");
|
||||
return Ok(InstallResult::Ready);
|
||||
}
|
||||
|
||||
@ -152,7 +153,7 @@ impl PackageStore {
|
||||
|
||||
if !zip_path.exists() {
|
||||
self.dlh.download_zip(&zip_path, &pkg)?;
|
||||
log::debug!("Deferring {}", key);
|
||||
log::debug!("deferring {}", key);
|
||||
return Ok(InstallResult::Deferred);
|
||||
}
|
||||
|
||||
@ -170,13 +171,13 @@ impl PackageStore {
|
||||
pkg: key.to_owned()
|
||||
})?;
|
||||
|
||||
log::info!("Installed {}", key);
|
||||
log::info!("installed {}", key);
|
||||
|
||||
Ok(InstallResult::Ready)
|
||||
}
|
||||
|
||||
pub async fn delete_package(&mut self, key: &PkgKey, force: bool) -> Result<()> {
|
||||
log::debug!("Will delete {} {}", key, force);
|
||||
log::debug!("will delete {} {}", key, force);
|
||||
|
||||
let pkg = self.store.get_mut(key)
|
||||
.ok_or_else(|| anyhow!("Attempted to delete a nonexistent pkg"))?;
|
||||
@ -191,7 +192,7 @@ impl PackageStore {
|
||||
self.app.emit("install-end", Payload {
|
||||
pkg: key.to_owned()
|
||||
})?;
|
||||
log::info!("Deleted {}", key);
|
||||
log::info!("deleted {}", key);
|
||||
}
|
||||
rv
|
||||
} else {
|
||||
@ -216,7 +217,7 @@ impl PackageStore {
|
||||
if path.exists() {
|
||||
tokio::fs::remove_dir_all(path)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Could not delete /{}: {}", name, e))?;
|
||||
.map_err(|e| anyhow!("could not delete {}: {}", name, e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -237,6 +238,7 @@ impl PackageStore {
|
||||
// todo case sensitivity for linux
|
||||
Self::clean_up_dir(&path, "app").await?;
|
||||
Self::clean_up_dir(&path, "option").await?;
|
||||
Self::clean_up_dir(&path, "segatools").await?;
|
||||
Self::clean_up_file(&path, "icon.png", true).await?;
|
||||
Self::clean_up_file(&path, "manifest.json", true).await?;
|
||||
Self::clean_up_file(&path, "README.md", true).await?;
|
||||
|
@ -3,7 +3,7 @@ use ongeki::OngekiProfile;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::AppHandle;
|
||||
use std::{collections::BTreeSet, path::{Path, PathBuf}};
|
||||
use crate::{model::{config::Display, misc::Game}, modules::package::prepare_packages, pkg::PkgKey, util};
|
||||
use crate::{model::misc::Game, modules::package::prepare_packages, pkg::PkgKey, util};
|
||||
|
||||
pub mod ongeki;
|
||||
|
||||
@ -72,14 +72,15 @@ impl AnyProfile {
|
||||
}
|
||||
pub async fn line_up(&self, pkg_hash: String, _app: AppHandle) -> Result<()> {
|
||||
match self {
|
||||
Self::OngekiProfile(p) => {
|
||||
Self::OngekiProfile(_p) => {
|
||||
#[cfg(target_os = "windows")]
|
||||
let info = p.display.line_up()?;
|
||||
let info = _p.display.line_up()?;
|
||||
|
||||
let res = self.line_up_the_rest(pkg_hash).await;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Some(info) = info {
|
||||
use crate::model::config::Display;
|
||||
if res.is_ok() {
|
||||
Display::wait_for_exit(_app, info);
|
||||
} else {
|
||||
|
@ -88,10 +88,13 @@ impl Profile for OngekiProfile {
|
||||
|
||||
let target_path = PathBuf::from(&self.sgt.target);
|
||||
let exe_dir = target_path.parent().ok_or_else(|| anyhow!("Invalid target path"))?;
|
||||
let sgt_dir = util::pkg_dir()
|
||||
.join(self.sgt.hook.as_ref().ok_or_else(|| anyhow!("No hook"))?.to_string())
|
||||
.join("segatools");
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
game_builder = Command::new(exe_dir.join("inject.exe"));
|
||||
game_builder = Command::new(sgt_dir.join("inject.exe"));
|
||||
amd_builder = Command::new("cmd.exe");
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -99,7 +102,7 @@ impl Profile for OngekiProfile {
|
||||
game_builder = Command::new(&self.wine.runtime);
|
||||
amd_builder = Command::new(&self.wine.runtime);
|
||||
|
||||
game_builder.arg(exe_dir.join("inject.exe"));
|
||||
game_builder.arg(sgt_dir.join("inject.exe"));
|
||||
amd_builder.arg("cmd.exe");
|
||||
}
|
||||
|
||||
@ -109,10 +112,10 @@ impl Profile for OngekiProfile {
|
||||
)
|
||||
.current_dir(&exe_dir)
|
||||
.arg("/C")
|
||||
.arg(&exe_dir.join("inject.exe"))
|
||||
.args([
|
||||
"-d", "-k", "mu3hook.dll",
|
||||
"amdaemon.exe", "-f", "-c", "config_common.json", "config_server.json", "config_client.json"
|
||||
.arg(&sgt_dir.join("inject.exe"))
|
||||
.args(["-d", "-k"])
|
||||
.arg(sgt_dir.join("mu3hook.dll"))
|
||||
.args(["amdaemon.exe", "-f", "-c", "config_common.json", "config_server.json", "config_client.json"
|
||||
]);
|
||||
game_builder
|
||||
.env(
|
||||
@ -124,8 +127,9 @@ impl Profile for OngekiProfile {
|
||||
self.config_dir().join("inohara.cfg"),
|
||||
)
|
||||
.current_dir(&exe_dir)
|
||||
.args(["-d", "-k"])
|
||||
.arg(sgt_dir.join("mu3hook.dll"))
|
||||
.args([
|
||||
"-d", "-k", "mu3hook.dll",
|
||||
"mu3.exe", "-monitor 1",
|
||||
"-screen-width", &self.display.rez.0.to_string(),
|
||||
"-screen-height", &self.display.rez.1.to_string(),
|
||||
|
Reference in New Issue
Block a user