diff --git a/lib/classes/ObjectResolver.ts b/lib/classes/ObjectResolver.ts index 66e9052..f7c7e20 100644 --- a/lib/classes/ObjectResolver.ts +++ b/lib/classes/ObjectResolver.ts @@ -18,15 +18,20 @@ export class ObjectResolver private onObjectResolveRan: Subject = new Subject(); - constructor(private region: Region) + constructor(private region?: Region) { } resolveObjects(objects: GameObject[], forceResolve: boolean = false, skipInventory = false, log = false): Promise { - return new Promise((resolve) => + return new Promise((resolve, reject) => { + if (!this.region) + { + reject(new Error('Region is going away')); + return; + } if (log) { // console.log('[RESOLVER] Scanning ' + objects.length + ' objects, skipInventory: ' + skipInventory); @@ -265,6 +270,11 @@ export class ObjectResolver private async doResolve(jobs: IResolveJob[]): Promise { + if (!this.region) + { + return; + } + const resolveTime = new Date().getTime() / 1000; const objectList = []; let totalRemaining = 0; @@ -296,6 +306,10 @@ export class ObjectResolver for (const job of jobs) { + if (!this.region) + { + return; + } if (!job.skipInventory) { const o = job.object; @@ -363,6 +377,10 @@ export class ObjectResolver const that = this; const getCosts = async function(objIDs: UUID[]): Promise { + if (!that.region) + { + return; + } const result = await that.region.caps.capsPostXML('GetObjectCost', { 'object_ids': objIDs }); @@ -426,4 +444,9 @@ export class ObjectResolver } } } + + public shutdown(): void + { + delete this.region; + } } diff --git a/lib/classes/ObjectStoreFull.ts b/lib/classes/ObjectStoreFull.ts index 29850ae..8710e4b 100644 --- a/lib/classes/ObjectStoreFull.ts +++ b/lib/classes/ObjectStoreFull.ts @@ -212,6 +212,10 @@ export class ObjectStoreFull extends ObjectStoreLite implements IObjectStore protected objectUpdateCached(objectUpdateCached: ObjectUpdateCachedMessage): void { + if (!this.circuit) + { + return; + } const rmo = new RequestMultipleObjectsMessage(); rmo.AgentData = { AgentID: this.agent.agentID, @@ -230,6 +234,10 @@ export class ObjectStoreFull extends ObjectStoreLite implements IObjectStore } if (rmo.ObjectData.length > 0) { + if (!this.circuit) + { + return; + } this.circuit.sendMessage(rmo, 0); } } diff --git a/lib/classes/ObjectStoreLite.ts b/lib/classes/ObjectStoreLite.ts index 89aa72b..ce5c48e 100644 --- a/lib/classes/ObjectStoreLite.ts +++ b/lib/classes/ObjectStoreLite.ts @@ -41,7 +41,7 @@ import Timer = NodeJS.Timer; export class ObjectStoreLite implements IObjectStore { - protected circuit: Circuit; + protected circuit?: Circuit; protected agent: Agent; protected objects: { [key: number]: GameObject } = {}; protected objectsByUUID: { [key: string]: number } = {}; @@ -141,6 +141,10 @@ export class ObjectStoreLite implements IObjectStore this.selectedChecker = setInterval(() => { + if (this.circuit === undefined) + { + return; + } try { let selectObjects = []; @@ -251,6 +255,10 @@ export class ObjectStoreLite implements IObjectStore { return; } + if (this.circuit === undefined) + { + return; + } this.requestedObjects[localID] = true; const rmo = new RequestMultipleObjectsMessage(); rmo.AgentData = { @@ -300,23 +308,30 @@ export class ObjectStoreLite implements IObjectStore } else { + if (!this.circuit) + { + return; + } console.error('Error retrieving missing object after 5 attempts: ' + localID); console.error(error); } } finally { - const deselectObject = new ObjectDeselectMessage(); - deselectObject.AgentData = { - AgentID: this.agent.agentID, - SessionID: this.circuit.sessionID - }; - deselectObject.ObjectData = [ - { - 'ObjectLocalID': localID - } - ]; - this.circuit.sendMessage(selectObject, PacketFlags.Reliable); + if (this.circuit) + { + const deselectObject = new ObjectDeselectMessage(); + deselectObject.AgentData = { + AgentID: this.agent.agentID, + SessionID: this.circuit.sessionID + }; + deselectObject.ObjectData = [ + { + 'ObjectLocalID': localID + } + ]; + this.circuit.sendMessage(selectObject, PacketFlags.Reliable); + } } } @@ -563,6 +578,10 @@ export class ObjectStoreLite implements IObjectStore protected objectUpdateCached(objectUpdateCached: ObjectUpdateCachedMessage): void { + if (this.circuit === undefined) + { + return; + } const rmo = new RequestMultipleObjectsMessage(); rmo.AgentData = { AgentID: this.agent.agentID, @@ -894,6 +913,7 @@ export class ObjectStoreLite implements IObjectStore } this.objectsByUUID = {}; this.objectsByParent = {}; + delete this.circuit; } protected findParent(go: GameObject): GameObject @@ -906,7 +926,10 @@ export class ObjectStoreLite implements IObjectStore { if (go.ParentID !== undefined && go.ParentID !== 0 && !this.objects[go.ParentID]) { - this.requestMissingObject(go.ParentID); + this.requestMissingObject(go.ParentID).catch((e: unknown) => + { + Logger.Error(e); + }); } return go; } diff --git a/lib/classes/Region.ts b/lib/classes/Region.ts index 20e2b3a..9b7859f 100644 --- a/lib/classes/Region.ts +++ b/lib/classes/Region.ts @@ -1412,7 +1412,7 @@ export class Region this.comms.shutdown(); this.caps.shutdown(); this.objects.shutdown(); + this.resolver.shutdown(); this.circuit.shutdown(); - } } diff --git a/package.json b/package.json index 201072a..fb8cd16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@caspertech/node-metaverse", - "version": "0.5.35", + "version": "0.5.36", "description": "A node.js interface for Second Life.", "main": "dist/lib/index.js", "types": "dist/lib/index.d.ts",