fix: also add post scripts

This commit is contained in:
2025-05-09 21:45:59 +00:00
parent 469ba5f574
commit 67872bc4d1
12 changed files with 119 additions and 55 deletions

View File

@ -1,8 +1,13 @@
## 0.20.0
## 0.20.1
- Added user-customizable pre-launch scripts
- Added japanese localization
- Fixed the file editor not updating state properly
- Added user-customizable scripts
- The launch script runs directly before the game, and is equivalent to adding lines above `start "AM Daemon" ...` in start.bat
- The end script runs after the game has closed for any reason, and is equivalent to adding lines below `taskkill /f /im amdaemon.exe ...` in start.bat
- This functionality is needed for cursed things such as brokenithm
- Fixed the file editor not updating its state properly
- Fixed diagnostic exports not exporting paths
- Fixed "Install recommended packages" not enabling the segatools hook
## 0.19.1

View File

@ -255,7 +255,7 @@ impl Profile {
let mut game_builder;
let mut amd_builder;
let mut prelaunch = None;
let mut prescript = None;
let target_path = PathBuf::from(&self.data.sgt.target);
let exe_dir = target_path.parent().ok_or_else(|| anyhow!("Invalid target path"))?;
@ -265,17 +265,6 @@ impl Profile {
{
game_builder = Command::new(sgt_dir.join(self.meta.game.inject_exe()));
amd_builder = Command::new("cmd.exe");
let prelaunch_path = self.config_dir().join("prelaunch.bat");
if prelaunch_path.exists() {
let mut c = Command::new("cmd");
c.args(["/C", "start"]);
c.raw_arg("\"STARTLINER Prelaunch\"");
c.args(["cmd", "/C"]);
c.arg(prelaunch_path);
log::debug!("Prelaunch: {:?}", c);
prelaunch = Some(c.spawn()?);
}
}
#[cfg(target_os = "linux")]
{
@ -284,14 +273,12 @@ impl Profile {
game_builder.arg(sgt_dir.join(self.meta.game.inject_exe()));
amd_builder.arg("cmd.exe");
}
let prelaunch_path = self.config_dir().join("prelaunch.sh");
if prelaunch_path.exists() {
prelaunch_builder = Some(Command::new("sh"));
c.arg(prelaunch_path);
log::debug!("Prelaunch: {:?}", c);
prelaunch = Some(c.spawn()?);
}
let script_ext = if cfg!(target_os = "windows") { "bat" } else { "sh" };
let prescript_path = self.config_dir().join(format!("pre.{script_ext}"));
if prescript_path.exists() {
prescript = util::spawn_script(prescript_path, &exe_dir, "\"STARTLINER launch script\"");
}
amd_builder.env(
@ -440,11 +427,11 @@ impl Profile {
util::pkill("amdaemon.exe").await;
}
if let Some(mut _child) = prelaunch {
if let Some(mut _child) = prescript {
#[cfg(target_os = "windows")]
{
// child.kill() doesn't work
util::pkill_title("STARTLINER Prelaunch").await;
util::pkill_title("STARTLINER launch script").await;
}
#[cfg(target_os = "linux")]
{
@ -452,6 +439,11 @@ impl Profile {
}
}
let postscript_path = self.config_dir().join(format!("post.{script_ext}"));
if postscript_path.exists() {
_ = util::spawn_script(postscript_path, &exe_dir, "\"STARTLINER end script\"");
}
set.join_next().await.expect("No spawn").expect("No result");
log::debug!("Fin");

View File

@ -49,15 +49,17 @@ impl Profile {
{
let sgt = &mut prf.data.sgt;
sgt.target = PathBuf::new();
if sgt.amfs.is_absolute() {
sgt.amfs = PathBuf::new();
}
if sgt.option.is_absolute() {
sgt.option = PathBuf::new();
}
if sgt.appdata.is_absolute() {
sgt.appdata = PathBuf::new();
if !is_diagnostic {
sgt.target = PathBuf::new();
if sgt.amfs.is_absolute() {
sgt.amfs = PathBuf::new();
}
if sgt.option.is_absolute() {
sgt.option = PathBuf::new();
}
if sgt.appdata.is_absolute() {
sgt.appdata = PathBuf::new();
}
}
}

View File

@ -220,4 +220,38 @@ pub fn create_shortcut(
file.Save(Some(lnk_path.to_str().ok_or_else(|| anyhow!("Illegal shortcut path"))?), true)?;
Ok(())
}
pub fn spawn_script(path: impl AsRef<Path>, cwd: impl AsRef<Path>, title: &str) -> Option<tokio::process::Child> {
// Seems? like this autism is needed to:
// 1. pop up a cmd window
// 2. launch the batch
// 3. die afterwards
let mut c;
#[cfg(target_os = "windows")]
{
c = Command::new("cmd");
c.args(["/C", "start"]);
c.raw_arg(title);
c.args(["cmd", "/C"]);
c.arg(path.as_ref());
c.current_dir(cwd);
}
#[cfg(target_os = "linux")]
{
c = Command::new("sh");
c.arg(path.as_ref());
c.current_dir(cwd);
}
log::debug!("Script launch: {:?}", c);
match c.spawn() {
Ok(child) => Some(child),
Err(e) => {
log::error!("unable to launch {:?}: {e}", path.as_ref());
None
}
}
}

View File

@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "STARTLINER",
"version": "0.20.0",
"version": "0.20.1",
"identifier": "zip.patafour.startliner",
"build": {
"beforeDevCommand": "bun run dev",

View File

@ -12,8 +12,8 @@ invoke('get_changelog').then((s) => (changelog.value = s as string));
<template>
<h1>About</h1>
STARTLINER is a launcher, configuration tool and mod manager for
O.N.G.E.K.I. and CHUNITHM.
STARTLINER is a configuration tool, mod manager and start.bat automation
engine for O.N.G.E.K.I. and CHUNITHM.
<h1>Changelog</h1>
<ScrollPanel style="height: 200px">
<div class="markdown">

View File

@ -71,10 +71,12 @@ const recommendedTooltip = computed(() => {
const installRecommended = () => {
if (prf.current?.meta.game === 'ongeki') {
pkgs.installFromKey('segatools-mu3hook');
prf.current.data.sgt.hook = 'segatools-mu3hook';
}
if (prf.current?.meta.game === 'chunithm') {
pkgs.installFromKey('segatools-chusanhook');
pkgs.installFromKey('mempatcher-mempatcher');
prf.current.data.sgt.hook = 'segatools-chusanhook';
}
};
</script>

View File

@ -29,10 +29,17 @@ const files = new Set<string>();
).includes('chunithm');
})();
const fileList = {
ongeki: ['aime.txt', 'inohara.cfg', 'mu3.ini', 'segatools-base.ini'],
chunithm: ['aime.txt', 'saekawa.toml', 'segatools-base.ini'],
};
const fileList = [
'aime.txt',
'inohara.cfg',
'saekawa.toml',
'mu3.ini',
'segatools-base.ini',
'pre.sh',
'pre.bat',
'post.sh',
'post.bat',
];
const diagnosticList = {
ongeki: ['mu3.ini', 'segatools-base.ini'],
@ -62,8 +69,7 @@ const fileListCurrent: Ref<string[]> = ref([]);
const recalcFileList = async () => {
const res: string[] = [];
files.clear();
for (const idx in fileList[prf.current!.meta.game]) {
const f = fileList[prf.current!.meta.game][idx];
for (const f of fileList) {
const p = await path.join(await prf.configDir, f);
if (await invoke('file_exists', { path: p })) {
res.push(f);

View File

@ -41,18 +41,33 @@ const prf = usePrfStore();
<FileEditor filename="segatools-base.ini" />
</OptionRow>
<OptionRow
:title="t('cfg.misc.prelaunch')"
:tooltip="t('cfg.misc.prelaunchTooltip')"
:title="t('cfg.misc.prescript')"
:tooltip="t('cfg.misc.prescriptTooltip')"
>
<FileEditor
v-if="extension === 'bat'"
filename="prelaunch.bat"
:defaultValue="`@echo off\n\nREM This script will be launched alongside the game\n`"
filename="pre.bat"
:defaultValue="`@echo off\n\nREM This script will launch before (and alongside) the game\n`"
/>
<FileEditor
v-else-if="extension === 'sh'"
filename="prelaunch.sh"
:defaultValue="`#!/bin/sh\n\n# This script will be launched alongside the game\n`"
filename="pre.sh"
:defaultValue="`#!/bin/sh\n\n# This script will launch before (and alongside) the game\n`"
/>
</OptionRow>
<OptionRow
:title="t('cfg.misc.postscript')"
:tooltip="t('cfg.misc.postscriptTooltip')"
>
<FileEditor
v-if="extension === 'bat'"
filename="post.bat"
:defaultValue="`@echo off\n\nREM This script will launch after the game has died\n`"
/>
<FileEditor
v-else-if="extension === 'sh'"
filename="post.sh"
:defaultValue="`#!/bin/sh\n\n# This script will launch after the game has died\n`"
/>
</OptionRow>
</OptionCategory>

View File

@ -166,8 +166,11 @@ export default {
other: 'Other segatools options',
otherTooltip:
'Advanced or situational options not covered by STARTLINER',
prelaunch: 'Prelaunch script',
prelaunchTooltip: 'Optional script that runs before the game.',
prescript: 'Launch script',
prescriptTooltip: 'Optional script that runs before the game.',
postscript: 'End script',
postscriptTooltip:
'Optional script that runs after the game has ended.',
},
extensions: {
title: 'Extensions',

View File

@ -144,7 +144,7 @@ export default {
general: '一般',
builtIn: 'segatools内蔵エミュレーション',
targetTooltip:
'STARTLINERはそれ以外のクリーンなデータに解凍された実行可能ファイルを期待する。',
'STARTLINERはそれ以外のクリーンなデータにクラック実行可能ファイルを期待する。',
hooks: 'フック',
ioModules: 'IOモジュール',
ioModulesDesc: 'これは望ましい入力方法と一致するはずです。',
@ -206,8 +206,10 @@ export default {
intelTooltip: '代わりにamdaemonにパッチを当てることを推奨する。',
other: 'その他segatools設定',
otherTooltip: 'STARTLINERに含まれない上級者向けまたは状況別設定',
prelaunch: 'スタート前スクリプト',
prelaunchTooltip: 'ゲームの前に実行されるスクリプト',
prescript: '起動前のスクリプト',
prescriptTooltip: 'ゲームの前に実行されるスクリプト',
postscript: '終了後のスクリプト',
postscriptTooltip: 'ゲーム終了後に実行されるスクリプト',
},
extensions: {
title: 'エクステンション',

View File

@ -206,8 +206,11 @@ export default {
other: 'Inne opcje segatools',
otherTooltip:
'Zaawansowane lub sytuacyjne opcje, które nie są objęte przez STARTLINERA',
prelaunch: 'Skrypt przedstartowy',
prelaunchTooltip: 'Opcjonalny skrypt uruchamiany przed grą.',
prescript: 'Skrypt startowy',
prescriptTooltip: 'Opcjonalny skrypt uruchamiany przed grą.',
postscript: 'Skrypt końcowy',
postscriptTooltip:
'Opcjonalny skrypt uruchamiany po zakończeniu gry.',
},
extensions: {
title: 'Rozszerzenia',