@@ -44,6 +44,7 @@ import {
44
44
import {
45
45
appendFileLog ,
46
46
appendGameLog ,
47
+ appendGamePlayLog ,
47
48
appendRunnerLog ,
48
49
initFileLog ,
49
50
initGameLog ,
@@ -1306,6 +1307,86 @@ async function getWinePath({
1306
1307
return stdout . trim ( )
1307
1308
}
1308
1309
1310
+ async function runBeforeLaunchScript (
1311
+ gameInfo : GameInfo ,
1312
+ gameSettings : GameSettings
1313
+ ) {
1314
+ if ( ! gameSettings . beforeLaunchScriptPath ) {
1315
+ return true
1316
+ }
1317
+
1318
+ appendGamePlayLog (
1319
+ gameInfo ,
1320
+ `Running script before ${ gameInfo . title } (${ gameSettings . beforeLaunchScriptPath } )\n`
1321
+ )
1322
+
1323
+ return runScriptForGame ( gameInfo , gameSettings . beforeLaunchScriptPath )
1324
+ }
1325
+
1326
+ async function runAfterLaunchScript (
1327
+ gameInfo : GameInfo ,
1328
+ gameSettings : GameSettings
1329
+ ) {
1330
+ if ( ! gameSettings . afterLaunchScriptPath ) {
1331
+ return true
1332
+ }
1333
+
1334
+ appendGamePlayLog (
1335
+ gameInfo ,
1336
+ `Running script after ${ gameInfo . title } (${ gameSettings . afterLaunchScriptPath } )\n`
1337
+ )
1338
+ return runScriptForGame ( gameInfo , gameSettings . afterLaunchScriptPath )
1339
+ }
1340
+
1341
+ /* Execute script before launch/after exit, wait until the script
1342
+ * exits to continue
1343
+ *
1344
+ * The script can start sub-processes with `bash another-command &`
1345
+ * if `another-command` should run asynchronously
1346
+ *
1347
+ * For example:
1348
+ *
1349
+ * ```
1350
+ * #!/bin/bash
1351
+ *
1352
+ * echo "this runs before/after the game"
1353
+ * bash ./another.bash & # this is launched before/after the game but is not waited
1354
+ * echo "this also runs before/after the game too" > someoutput.txt
1355
+ * ```
1356
+ *
1357
+ * Notes:
1358
+ * - Output and logs are printed in the game's log
1359
+ * - Make sure the script is executable
1360
+ * - Make sure any async process is not stuck running in the background forever,
1361
+ * use the after script to kill any running process if that's the case
1362
+ */
1363
+ async function runScriptForGame (
1364
+ gameInfo : GameInfo ,
1365
+ scriptPath : string
1366
+ ) : Promise < boolean | string > {
1367
+ return new Promise ( ( resolve , reject ) => {
1368
+ const child = spawn ( scriptPath , { cwd : gameInfo . install . install_path } )
1369
+
1370
+ child . stdout . on ( 'data' , ( data ) => {
1371
+ appendGamePlayLog ( gameInfo , data . toString ( ) )
1372
+ } )
1373
+
1374
+ child . stderr . on ( 'data' , ( data ) => {
1375
+ appendGamePlayLog ( gameInfo , data . toString ( ) )
1376
+ } )
1377
+
1378
+ child . on ( 'exit' , ( ) => {
1379
+ resolve ( true )
1380
+ } )
1381
+
1382
+ child . on ( 'error' , ( err : Error ) => {
1383
+ appendGamePlayLog ( gameInfo , err . message )
1384
+ if ( err . stack ) appendGamePlayLog ( gameInfo , err . stack )
1385
+ reject ( err . message )
1386
+ } )
1387
+ } )
1388
+ }
1389
+
1309
1390
export {
1310
1391
prepareLaunch ,
1311
1392
launchCleanup ,
@@ -1317,5 +1398,7 @@ export {
1317
1398
runWineCommand ,
1318
1399
callRunner ,
1319
1400
getRunnerCallWithoutCredentials ,
1320
- getWinePath
1401
+ getWinePath ,
1402
+ runAfterLaunchScript ,
1403
+ runBeforeLaunchScript
1321
1404
}
0 commit comments