( pathSource: string, pathTarget: string, userFlowOptions: UserFlowOptions, packName: string, sourcePack?: Pick<Pack, "packedFiles">, )
| 1353 | }; |
| 1354 | }; |
| 1355 | export const executeFlowsForPack = async ( |
| 1356 | pathSource: string, |
| 1357 | pathTarget: string, |
| 1358 | userFlowOptions: UserFlowOptions, |
| 1359 | packName: string, |
| 1360 | sourcePack?: Pick<Pack, "packedFiles">, |
| 1361 | ): Promise<{ createdPackPaths: string[]; hadErrors: boolean }> => { |
| 1362 | void pathTarget; |
| 1363 | const createdPackPaths = new Set<string>(); |
| 1364 | let hadErrors = false; |
| 1365 | const packStartTime = performance.now(); |
| 1366 | const isDebug = isFlowExecutionDebugEnabled(); |
| 1367 | const executionContext = createFlowExecutionContext(isDebug); |
| 1368 | try { |
| 1369 | console.log("Executing flows for pack:", packName); |
| 1370 | // Note: Counter tracking is NOT reset here - it's reset once at game launch level |
| 1371 | // This ensures counters are unique across all flows in all packs |
| 1372 | // Read the pack to get flow files |
| 1373 | const sourceMod = sourcePack ?? (await readPack(pathSource, { readFlows: true, skipParsingTables: true })); |
| 1374 | // Filter for flow files |
| 1375 | const flowFiles = sourceMod.packedFiles.filter((file) => file.name.startsWith("whmmflows\\")); |
| 1376 | if (flowFiles.length === 0) { |
| 1377 | console.log("No flow files found in pack"); |
| 1378 | return { createdPackPaths: Array.from(createdPackPaths), hadErrors }; |
| 1379 | } |
| 1380 | console.log(`Found ${flowFiles.length} flow files in pack`); |
| 1381 | // Get user options for this pack |
| 1382 | const packFlowOptions = userFlowOptions[packName] || {}; |
| 1383 | const preparedFlows: PreparedFlow[] = []; |
| 1384 | const prepareStartTime = performance.now(); |
| 1385 | for (const flowFile of flowFiles) { |
| 1386 | try { |
| 1387 | const flowContent = flowFile.text || (flowFile.buffer ? flowFile.buffer.toString("utf-8") : ""); |
| 1388 | if (!flowContent) { |
| 1389 | console.warn(`Flow file ${flowFile.name} has no content`); |
| 1390 | continue; |
| 1391 | } |
| 1392 | const flowFileName = flowFile.name; |
| 1393 | const flowData: SerializedNodeGraph = JSON.parse(flowContent); |
| 1394 | const flowOptions = packFlowOptions[flowFileName]; |
| 1395 | if (flowData.isGraphEnabled && flowOptions?.graphEnabled === false) { |
| 1396 | console.log(`Flow ${flowFileName} is disabled by user, skipping`); |
| 1397 | continue; |
| 1398 | } |
| 1399 | preparedFlows.push(prepareFlow(flowFileName, flowData, packName, flowOptions, isDebug)); |
| 1400 | } catch (error) { |
| 1401 | console.error(`Error preparing flow ${flowFile.name}:`, error); |
| 1402 | hadErrors = true; |
| 1403 | } |
| 1404 | } |
| 1405 | console.log( |
| 1406 | `Prepared ${preparedFlows.length}/${flowFiles.length} flow(s) in ${(performance.now() - prepareStartTime).toFixed(2)}ms`, |
| 1407 | ); |
| 1408 | for (const preparedFlow of preparedFlows) { |
| 1409 | const flowStartTime = performance.now(); |
| 1410 | try { |
| 1411 | const result = await executeNodeGraph({ |
| 1412 | nodes: preparedFlow.nodes, |
no test coverage detected