import { Subject, type Subscription } from 'rxjs'; import type { GroupChatClosedEvent } from '../events/GroupChatClosedEvent'; import type { NewObjectEvent } from '../events/NewObjectEvent'; import type { ObjectUpdatedEvent } from '../events/ObjectUpdatedEvent'; import type { ObjectKilledEvent } from '../events/ObjectKilledEvent'; import type { SelectedObjectEvent } from '../events/SelectedObjectEvent'; import type { ChatEvent } from '../events/ChatEvent'; import type { InstantMessageEvent } from '../events/InstantMessageEvent'; import type { GroupInviteEvent } from '../events/GroupInviteEvent'; import type { FriendRequestEvent } from '../events/FriendRequestEvent'; import type { InventoryOfferedEvent } from '../events/InventoryOfferedEvent'; import type { LureEvent } from '../events/LureEvent'; import type { TeleportEvent } from '../events/TeleportEvent'; import type { DisconnectEvent } from '../events/DisconnectEvent'; import type { GroupChatEvent } from '../events/GroupChatEvent'; import type { GroupNoticeEvent } from '../events/GroupNoticeEvent'; import type { GroupChatSessionJoinEvent } from '../events/GroupChatSessionJoinEvent'; import type { GroupChatSessionAgentListEvent } from '../events/GroupChatSessionAgentListEvent'; import type { FriendResponseEvent } from '../events/FriendResponseEvent'; import type { ScriptDialogEvent } from '../events/ScriptDialogEvent'; import type { EventQueueStateChangeEvent } from '../events/EventQueueStateChangeEvent'; import type { FriendOnlineEvent } from '../events/FriendOnlineEvent'; import type { FriendRightsEvent } from '../events/FriendRightsEvent'; import type { FriendRemovedEvent } from '../events/FriendRemovedEvent'; import type { ObjectPhysicsDataEvent } from '../events/ObjectPhysicsDataEvent'; import type { ParcelPropertiesEvent } from '../events/ParcelPropertiesEvent'; import type { ObjectResolvedEvent } from '../events/ObjectResolvedEvent'; import type { Avatar } from './public/Avatar'; import type { BulkUpdateInventoryEvent } from '../events/BulkUpdateInventoryEvent'; import type { InventoryResponseEvent } from '../events/InventoryResponseEvent'; import type { LandStatsEvent } from '../events/LandStatsEvent'; import type { SimStatsEvent } from '../events/SimStatsEvent'; import type { BalanceUpdatedEvent } from '../events/BalanceUpdatedEvent'; import { TimeoutError } from './TimeoutError'; import { FilterResponse } from '../enums/FilterResponse'; import type { UUID } from './UUID'; export class ClientEvents { public onNearbyChat: Subject = new Subject(); public onInstantMessage: Subject = new Subject(); public onGroupInvite: Subject = new Subject(); public onFriendRequest: Subject = new Subject(); public onInventoryOffered: Subject = new Subject(); public onLure: Subject = new Subject(); public onTeleportEvent: Subject = new Subject(); public onDisconnected: Subject = new Subject(); public onCircuitLatency: Subject = new Subject(); public onGroupChat: Subject = new Subject(); public onGroupChatClosed: Subject = new Subject(); public onGroupNotice: Subject = new Subject(); public onGroupChatSessionJoin: Subject = new Subject(); public onGroupChatAgentListUpdate: Subject = new Subject(); public onFriendResponse: Subject = new Subject(); public onInventoryResponse: Subject = new Subject(); public onScriptDialog: Subject = new Subject(); public onEventQueueStateChange: Subject = new Subject(); public onFriendOnline: Subject = new Subject(); public onFriendRights: Subject = new Subject(); public onFriendRemoved: Subject = new Subject(); public onPhysicsDataEvent: Subject = new Subject(); public onParcelPropertiesEvent: Subject = new Subject(); public onNewObjectEvent: Subject = new Subject(); public onObjectUpdatedEvent: Subject = new Subject(); public onObjectUpdatedTerseEvent: Subject = new Subject(); public onObjectKilledEvent: Subject = new Subject(); public onSelectedObjectEvent: Subject = new Subject(); public onObjectResolvedEvent: Subject = new Subject(); public onAvatarEnteredRegion: Subject = new Subject(); public onRegionTimeDilation: Subject = new Subject(); public onBulkUpdateInventoryEvent: Subject = new Subject(); public onLandStatReplyEvent: Subject = new Subject(); public onSimStats: Subject = new Subject(); public onBalanceUpdated: Subject = new Subject(); public onScriptRunningReply = new Subject<{ ItemID: UUID, Mono: boolean, ObjectID: UUID, Running: boolean }>(); public async waitForEvent(subj: Subject, messageFilter?: (message: T) => FilterResponse, timeout = 10000): Promise { return new Promise((resolve, reject) => { const handleObj: { timeout: NodeJS.Timeout | null, subscription: Subscription | null } = { timeout: null, subscription: null }; const timeoutFunc = (): void => { if (handleObj.subscription !== null) { handleObj.subscription.unsubscribe(); reject(new TimeoutError('Timeout waiting for event')); } }; handleObj.timeout = setTimeout(timeoutFunc, timeout); handleObj.subscription = subj.subscribe((item: T) => { let finish = false; if (messageFilter === undefined) { finish = true; } else { try { const filterResult = messageFilter(item); if (filterResult === FilterResponse.Finish) { finish = true; } else if (filterResult === FilterResponse.Match) { // Extend if (handleObj.timeout !== null) { clearTimeout(handleObj.timeout); } handleObj.timeout = setTimeout(timeoutFunc, timeout); } } catch(e: unknown) { if (handleObj.timeout !== null) { clearTimeout(handleObj.timeout); handleObj.timeout = null; } if (handleObj.subscription !== null) { handleObj.subscription.unsubscribe(); handleObj.subscription = null; } if (e instanceof Error) { reject(e); } else { reject(new Error('Failed running event filter')); } } } if (finish) { if (handleObj.timeout !== null) { clearTimeout(handleObj.timeout); handleObj.timeout = null; } if (handleObj.subscription !== null) { handleObj.subscription.unsubscribe(); handleObj.subscription = null; } resolve(item); } }); }); } }