import { EVENTS } from "../../constants/events"; import { Weapon } from "../../models/Weapon"; import { Logger } from "../../utils/Logger"; import { GameState } from "../gamestate/GameState"; import { DifferBase, DiffOptions, EmitterContext } from "./DifferBase"; export interface WeaponDifferOptions { logger?: Logger | null; } export class WeaponDiffer extends DifferBase { protected logger: Logger | Console; constructor({ logger = null }: WeaponDifferOptions = {}) { super(); this.logger = (logger ?? { child: () => console }).child("WeaponDiffer"); this.logger.log("βš™οΈ instantiated correctly."); } /** * Compara cambios en el arma activa y emite eventos de Change of ammoClip y ammoReserve. * * @param {GameState} prev State anterior del juego * @param {GameState} curr State actual del juego * @param {Object} emitter Contexto de emisiΓ³n de eventos * @param {Object} [options] Opcional. Objeto con { previously, added } */ diff( prev: GameState, curr: GameState, emitter: EmitterContext, options: DiffOptions = {} ) { if (this.logger instanceof Logger) { this.logger.verbose("πŸ” diff() called"); } this.diffAllPlayers(prev, curr, emitter); if (!prev?.player && !curr?.player) return; const prevWeapon = prev.player.activeWeapon; const currWeapon = curr.player.activeWeapon; if (this.logger instanceof Logger) { this.logger.verbose("πŸ” prevWeapon:", prevWeapon); this.logger.verbose("πŸ” currWeapon:", currWeapon); } if (!currWeapon || currWeapon.ammo_clip === undefined) { this.logger.warn( "⚠️ Current active weapon incomplete or missing ammo_clip." ); return; } if (!prevWeapon || prevWeapon.ammo_clip === undefined) { if (this.logger instanceof Logger) { this.logger.verbose( "ℹ️ No prevWeapon or ammoClip in prev. Waiting for next diff." ); } return; } if (prevWeapon.ammo_clip !== currWeapon.ammo_clip) { this.logger.log( `πŸš€ ammoClip change: ${prevWeapon.ammo_clip} β†’ ${currWeapon.ammo_clip}` ); this.emitWithContext(emitter, EVENTS.player.ammoClipChanged, { previous: prevWeapon.ammo_clip, current: currWeapon.ammo_clip, }); } if (prevWeapon.ammo_reserve !== currWeapon.ammo_reserve) { this.logger.log( `πŸš€ ammoReserve change: ${prevWeapon.ammo_reserve} β†’ ${currWeapon.ammo_reserve}` ); this.emitWithContext(emitter, EVENTS.player.ammoReserveChanged, { previous: prevWeapon.ammo_reserve, current: currWeapon.ammo_reserve, }); } if (prevWeapon.name !== currWeapon.name) { this.logger.log( `πŸš€ Weapon changed: ${prevWeapon.name} β†’ ${currWeapon.name}` ); this.emitWithContext(emitter, EVENTS.player.weaponChanged, { previous: prevWeapon, current: currWeapon, }); } } diffAllPlayers(prev: GameState, curr: GameState, emitter: EmitterContext) { if (!prev?.allPlayers && !curr?.allPlayers) return; const prevSteamids = prev.allPlayers.getAllSteamids(); const currSteamids = curr.allPlayers.getAllSteamids(); const allSteamids = new Set([...currSteamids, ...prevSteamids]); for (const steamid of allSteamids) { const currPlayer = curr.allPlayers.getBySteamid(steamid); const prevPlayer = prev.allPlayers.getBySteamid(steamid); if (!currPlayer || !prevPlayer) continue; const prevWeapon = prevPlayer.activeWeapon; const currWeapon = currPlayer.activeWeapon; if (this.logger instanceof Logger) { this.logger.verbose("πŸ” prevWeapon:", prevWeapon); this.logger.verbose("πŸ” currWeapon:", currWeapon); } if (!currWeapon || currWeapon.ammo_clip === undefined) { this.logger.warn( "⚠️ Current active weapon incomplete or missing ammo_clip for player " + steamid ); return; } if (!prevWeapon || prevWeapon.ammo_clip === undefined) { if (this.logger instanceof Logger) { this.logger.verbose( "ℹ️ No prevWeapon or ammoClip in prev. Waiting for next diff." ); } return; } if (prevWeapon.ammo_clip !== currWeapon.ammo_clip) { this.logger.log( `πŸš€ ammoClip change: ${prevWeapon.ammo_clip} β†’ ${currWeapon.ammo_clip}` ); this.emitWithContext(emitter, EVENTS.allPlayers.ammoClipChanged, steamid, { previous: prevWeapon.ammo_clip, current: currWeapon.ammo_clip, }); this.emitWithContext(emitter, `${EVENTS.allPlayers.ammoClipChanged}@${steamid}`, { previous: prevWeapon.ammo_clip, current: currWeapon.ammo_clip, }); } if (prevWeapon.ammo_reserve !== currWeapon.ammo_reserve) { this.logger.log( `πŸš€ ammoReserve change: ${prevWeapon.ammo_reserve} β†’ ${currWeapon.ammo_reserve}` ); this.emitWithContext(emitter, EVENTS.allPlayers.ammoReserveChanged, steamid, { previous: prevWeapon.ammo_reserve, current: currWeapon.ammo_reserve, }); this.emitWithContext(emitter, `${EVENTS.allPlayers.ammoReserveChanged}@${steamid}`, { previous: prevWeapon.ammo_reserve, current: currWeapon.ammo_reserve, }); } if (prevWeapon.name !== currWeapon.name) { this.logger.log( `πŸš€ Weapon changed: ${prevWeapon.name} β†’ ${currWeapon.name}` ); this.emitWithContext(emitter, EVENTS.allPlayers.weaponChanged, steamid, { previous: prevWeapon, current: currWeapon, }); this.emitWithContext(emitter, `${EVENTS.allPlayers.weaponChanged}@${steamid}`, { previous: prevWeapon, current: currWeapon, }); } } } }