Added rollWorker so that multiple dice rolls can happen simultaneously
This commit is contained in:
		
							parent
							
								
									7391a0fd68
								
							
						
					
					
						commit
						1f4d1e3ef6
					
				|  | @ -1,7 +1,7 @@ | |||
| { | ||||
|   "compilerOptions": { | ||||
|     "allowJs": true, | ||||
|     "lib": ["deno.window"], | ||||
|     "lib": ["deno.worker"], | ||||
|     "strict": true | ||||
|   }, | ||||
|   "lint": { | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import { | |||
| } from '../../deps.ts'; | ||||
| import solver from '../solver/_index.ts'; | ||||
| import { SolvedRoll } from '../solver/solver.d.ts'; | ||||
| import { RollModifiers } from '../mod.d.ts'; | ||||
| import { generateCountDetailsEmbed, generateDMFailed, generateRollEmbed, infoColor1, warnColor } from '../commandUtils.ts'; | ||||
| import rollFuncs from './roll/_index.ts'; | ||||
| 
 | ||||
|  | @ -59,60 +60,92 @@ export const roll = async (message: DiscordenoMessage, args: string[], command: | |||
| 
 | ||||
| 		// Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in
 | ||||
| 		const rollCmd = `${command} ${args.join(' ')}`; | ||||
| 		const returnmsg = solver.parseRoll(rollCmd, modifiers) || <SolvedRoll> { error: true, errorCode: 'EmptyMessage', errorMsg: 'Error: Empty message' }; | ||||
| 		// const returnmsg = solver.parseRoll(rollCmd, modifiers) || <SolvedRoll>{ error: true, errorCode: 'EmptyMessage', errorMsg: 'Error: Empty message' };
 | ||||
| 
 | ||||
| 		const pubEmbedDetails = await generateRollEmbed(message.authorId, returnmsg, modifiers); | ||||
| 		const gmEmbedDetails = await generateRollEmbed(message.authorId, returnmsg, gmModifiers); | ||||
| 		const countEmbed = generateCountDetailsEmbed(returnmsg.counts); | ||||
| 		const rollWorker = new Worker(new URL('../solver/rollWorker.ts', import.meta.url).href, { type: 'module' }); | ||||
| 
 | ||||
| 		// If there was an error, report it to the user in hopes that they can determine what they did wrong
 | ||||
| 		if (returnmsg.error) { | ||||
| 			m.edit({ embeds: [pubEmbedDetails.embed] }); | ||||
| 		const workerTimeout = setTimeout(async () => { | ||||
| 			rollWorker.terminate(); | ||||
| 			m.edit({ | ||||
| 				embeds: [ | ||||
| 					(await generateRollEmbed( | ||||
| 						message.authorId, | ||||
| 						<SolvedRoll>{ | ||||
| 							error: true, | ||||
| 							errorCode: 'TooComplex', | ||||
| 							errorMsg: 'Error: Roll Too Complex, try breaking roll down into simpler parts', | ||||
| 						}, | ||||
| 						<RollModifiers>{}, | ||||
| 					)).embed, | ||||
| 				], | ||||
| 			}); | ||||
| 		}, 60000); | ||||
| 
 | ||||
| 			if (DEVMODE && config.logRolls) { | ||||
| 				// If enabled, log rolls so we can see what went wrong
 | ||||
| 				dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, returnmsg.errorCode, m.id]).catch((e) => { | ||||
| 					log(LT.ERROR, `Failed to insert into DB: ${JSON.stringify(e)}`); | ||||
| 				}); | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Determine if we are to send a GM roll or a normal roll
 | ||||
| 			if (modifiers.gmRoll) { | ||||
| 				// Send the public embed to correct channel
 | ||||
| 				m.edit({ embeds: [pubEmbedDetails.embed] }); | ||||
| 		rollWorker.postMessage({ | ||||
| 			rollCmd, | ||||
| 			modifiers, | ||||
| 		}); | ||||
| 
 | ||||
| 				// And message the full details to each of the GMs, alerting roller of every GM that could not be messaged
 | ||||
| 				modifiers.gms.forEach(async (gm) => { | ||||
| 					log(LT.LOG, `Messaging GM ${gm}`); | ||||
| 					// Attempt to DM the GM and send a warning if it could not DM a GM
 | ||||
| 					await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), { | ||||
| 						embeds: modifiers.count ? [gmEmbedDetails.embed, countEmbed] : [gmEmbedDetails.embed], | ||||
| 					}).then(async () => { | ||||
| 						// Check if we need to attach a file and send it after the initial details sent
 | ||||
| 						if (gmEmbedDetails.hasAttachment) { | ||||
| 		rollWorker.addEventListener('message', async (e) => { | ||||
| 			try { | ||||
| 				clearTimeout(workerTimeout); | ||||
| 				const returnmsg = e.data; | ||||
| 				const pubEmbedDetails = await generateRollEmbed(message.authorId, returnmsg, modifiers); | ||||
| 				const gmEmbedDetails = await generateRollEmbed(message.authorId, returnmsg, gmModifiers); | ||||
| 				const countEmbed = generateCountDetailsEmbed(returnmsg.counts); | ||||
| 
 | ||||
| 				// If there was an error, report it to the user in hopes that they can determine what they did wrong
 | ||||
| 				if (returnmsg.error) { | ||||
| 					m.edit({ embeds: [pubEmbedDetails.embed] }); | ||||
| 
 | ||||
| 					if (DEVMODE && config.logRolls) { | ||||
| 						// If enabled, log rolls so we can see what went wrong
 | ||||
| 						dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, returnmsg.errorCode, m.id]).catch((e) => { | ||||
| 							log(LT.ERROR, `Failed to insert into DB: ${JSON.stringify(e)}`); | ||||
| 						}); | ||||
| 					} | ||||
| 				} else { | ||||
| 					// Determine if we are to send a GM roll or a normal roll
 | ||||
| 					if (modifiers.gmRoll) { | ||||
| 						// Send the public embed to correct channel
 | ||||
| 						m.edit({ embeds: [pubEmbedDetails.embed] }); | ||||
| 
 | ||||
| 						// And message the full details to each of the GMs, alerting roller of every GM that could not be messaged
 | ||||
| 						modifiers.gms.forEach(async (gm) => { | ||||
| 							log(LT.LOG, `Messaging GM ${gm}`); | ||||
| 							// Attempt to DM the GM and send a warning if it could not DM a GM
 | ||||
| 							await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), { | ||||
| 								file: gmEmbedDetails.attachment, | ||||
| 								embeds: modifiers.count ? [gmEmbedDetails.embed, countEmbed] : [gmEmbedDetails.embed], | ||||
| 							}).then(async () => { | ||||
| 								// Check if we need to attach a file and send it after the initial details sent
 | ||||
| 								if (gmEmbedDetails.hasAttachment) { | ||||
| 									await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), { | ||||
| 										file: gmEmbedDetails.attachment, | ||||
| 									}).catch(() => { | ||||
| 										message.reply(generateDMFailed(gm)); | ||||
| 									}); | ||||
| 								} | ||||
| 							}).catch(() => { | ||||
| 								message.reply(generateDMFailed(gm)); | ||||
| 							}); | ||||
| 						}); | ||||
| 					} else { | ||||
| 						// Not a gm roll, so just send normal embed to correct channel
 | ||||
| 						const n = await m.edit({ | ||||
| 							embeds: modifiers.count ? [pubEmbedDetails.embed, countEmbed] : [pubEmbedDetails.embed], | ||||
| 						}); | ||||
| 						if (pubEmbedDetails.hasAttachment) { | ||||
| 							// Attachment requires you to send a new message
 | ||||
| 							n.reply({ | ||||
| 								file: pubEmbedDetails.attachment, | ||||
| 							}); | ||||
| 						} | ||||
| 					}).catch(() => { | ||||
| 						message.reply(generateDMFailed(gm)); | ||||
| 					}); | ||||
| 				}); | ||||
| 			} else { | ||||
| 				// Not a gm roll, so just send normal embed to correct channel
 | ||||
| 				await m.edit({ | ||||
| 					embeds: modifiers.count ? [pubEmbedDetails.embed, countEmbed] : [pubEmbedDetails.embed], | ||||
| 				}); | ||||
| 				if (pubEmbedDetails.hasAttachment) { | ||||
| 					// Attachment requires you to send a new message
 | ||||
| 					message.send({ | ||||
| 						file: pubEmbedDetails.attachment, | ||||
| 					}); | ||||
| 					} | ||||
| 				} | ||||
| 			} catch (e) { | ||||
| 				log(LT.ERROR, `Unddandled Error: ${JSON.stringify(e)}`); | ||||
| 			} | ||||
| 		} | ||||
| 		}); | ||||
| 	} catch (e) { | ||||
| 		log(LT.ERROR, `Undandled Error: ${JSON.stringify(e)}`); | ||||
| 	} | ||||
|  |  | |||
|  | @ -17,6 +17,19 @@ import { fullSolver } from './solver.ts'; | |||
| export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => { | ||||
| 	const returnmsg = <SolvedRoll> { | ||||
| 		error: false, | ||||
| 		errorCode: '', | ||||
| 		errorMsg: '', | ||||
| 		line1: '', | ||||
| 		line2: '', | ||||
| 		line3: '', | ||||
| 		counts: { | ||||
| 			total: 0, | ||||
| 			successful: 0, | ||||
| 			failed: 0, | ||||
| 			rerolled: 0, | ||||
| 			dropped: 0, | ||||
| 			exploded: 0, | ||||
| 		}, | ||||
| 	}; | ||||
| 
 | ||||
| 	// Whole function lives in a try-catch to allow safe throwing of errors on purpose
 | ||||
|  | @ -25,7 +38,14 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll | |||
| 		const sepRolls = fullCmd.split(config.prefix); | ||||
| 
 | ||||
| 		const tempReturnData: ReturnData[] = []; | ||||
| 		const tempCountDetails: CountDetails[] = []; | ||||
| 		const tempCountDetails: CountDetails[] = [{ | ||||
| 			total: 0, | ||||
| 			successful: 0, | ||||
| 			failed: 0, | ||||
| 			rerolled: 0, | ||||
| 			dropped: 0, | ||||
| 			exploded: 0, | ||||
| 		}]; | ||||
| 
 | ||||
| 		// Loop thru all roll/math ops
 | ||||
| 		for (const sepRoll of sepRolls) { | ||||
|  | @ -75,6 +95,21 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll | |||
| 						containsCrit: false, | ||||
| 						containsFail: false, | ||||
| 					}; | ||||
| 				} else if (mathConf[i].toString().toLowerCase() === 'fart' || mathConf[i].toString().toLowerCase() === '💩') { | ||||
| 					mathConf[i] = { | ||||
| 						total: 7, | ||||
| 						details: '💩', | ||||
| 						containsCrit: false, | ||||
| 						containsFail: false, | ||||
| 					}; | ||||
| 				} else if (mathConf[i].toString().toLowerCase() === 'inf' || mathConf[i].toString().toLowerCase() === 'infinity' || mathConf[i].toString().toLowerCase() === '∞') { | ||||
| 					// If the operand is the constant Infinity, create a SolvedStep for it
 | ||||
| 					mathConf[i] = { | ||||
| 						total: Infinity, | ||||
| 						details: '∞', | ||||
| 						containsCrit: false, | ||||
| 						containsFail: false, | ||||
| 					}; | ||||
| 				} else if (mathConf[i].toString().toLowerCase() === 'pi' || mathConf[i].toString().toLowerCase() === '𝜋') { | ||||
| 					// If the operand is the constant pi, create a SolvedStep for it
 | ||||
| 					mathConf[i] = { | ||||
|  |  | |||
|  | @ -0,0 +1,23 @@ | |||
| import { parseRoll } from './parser.ts'; | ||||
| 
 | ||||
| self.onmessage = async (e: any) => { | ||||
| 	const payload = e.data; | ||||
| 	const returnmsg = parseRoll(payload.rollCmd, payload.modifiers) || { | ||||
| 		error: true, | ||||
| 		errorCode: 'EmptyMessage', | ||||
| 		errorMsg: 'Error: Empty message', | ||||
| 		line1: '', | ||||
| 		line2: '', | ||||
| 		line3: '', | ||||
| 		counts: { | ||||
| 			total: 0, | ||||
| 			successful: 0, | ||||
| 			failed: 0, | ||||
| 			rerolled: 0, | ||||
| 			dropped: 0, | ||||
| 			exploded: 0, | ||||
| 		}, | ||||
| 	}; | ||||
| 	self.postMessage(returnmsg); | ||||
| 	self.close(); | ||||
| }; | ||||
|  | @ -83,6 +83,10 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea | |||
| 	rollConf.dieSize = parseInt(remains.slice(0, afterDieIdx)); | ||||
| 	remains = remains.slice(afterDieIdx); | ||||
| 
 | ||||
| 	if (!rollConf.dieCount || !rollConf.dieSize) { | ||||
| 		throw new Error('YouNeedAD'); | ||||
| 	} | ||||
| 
 | ||||
| 	log(LT.LOG, `Handling roll ${rollStr} | Parsed Die Count: ${rollConf.dieCount}`); | ||||
| 	log(LT.LOG, `Handling roll ${rollStr} | Parsed Die Size: ${rollConf.dieSize}`); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue