Last active
September 15, 2022 16:35
-
-
Save Alynva/6803004270a714de99b42ab9941243fa to your computer and use it in GitHub Desktop.
G-Node utility to wait until a packet is intercepted with promise and timeout.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { EventEmitter } from 'node:events' | |
import { Extension, HDirection, HMessage } from "gnode-api" | |
const sleep = ms => new Promise(res => setTimeout(res, ms)) | |
/** | |
* Usage: | |
* ``` | |
* const waiter = new Waiter(ext) | |
* waiter.timeout = 60 * 1000 // optional, defaults to 10.000 | |
* waiter.when(HDirection.TOSERVER, "MoveAvatar") | |
* .then(hMessage => console.log(hMessage)) | |
* .catch(err => console.error(err)) | |
* ``` | |
*/ | |
export default class Waiter { | |
/** @type {Extension} */ | |
#ext | |
#events = new EventEmitter() | |
timeout = 10 * 1000 | |
/** @param {Extension} ext */ | |
constructor(ext) { | |
if (!ext) throw new Error("You must pass the extension when creating a new Waiter.") | |
this.#ext = ext | |
ext.interceptAll(HDirection.TOCLIENT, this.#interceptHandler.bind(this)) | |
ext.interceptAll(HDirection.TOSERVER, this.#interceptHandler.bind(this)) | |
} | |
/** @param {HMessage} message */ | |
#interceptHandler(message) { | |
const packetNames = this.#getPacketNames(message) | |
if (!packetNames || !packetNames.length) { | |
console.warn(`Not packet info available or unknown packet.`) | |
} | |
for (const name of packetNames) { | |
this.#events.emit(name, message) | |
} | |
} | |
/** @param {HMessage} message */ | |
#getPacketNames(message) { | |
const direction = message.getDestination() | |
const packet = message.getPacket() | |
const packetInfoManager = this.#ext.getPacketInfoManager() | |
if (!packetInfoManager) { | |
return | |
} | |
const packetInfos = packetInfoManager.getAllPacketInfoFromHeaderId(direction, packet.headerId()) | |
const packetNames = packetInfos | |
.filter((x, i, a) => i.name !== null && i === a.indexOf(x)) | |
.map(i => `${i.name}`) | |
return packetNames | |
} | |
/** | |
* @param {HDirection} direction | |
* @param {String} packetName | |
*/ | |
async when(direction, packetName) { | |
/** @type {Promise<HMessage>} */ | |
const promise = Promise(async (res, rej) => { | |
let completed = false | |
/** @param {HMessage} message */ | |
function listener(message) { | |
if (message.getDestination() === direction) { | |
completed = true | |
res(message) | |
} | |
} | |
this.#events.once(packetName, listener) | |
await sleep(this.timeout) | |
this.#events.removeListener(packetName, listener) | |
if (completed) return | |
rej(new Error(`Waiting for ${packetName} timed out.`)) | |
}) | |
return promise | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment