From ad3a8c8e2e34d821148bbec4955c7fc74eb577f1 Mon Sep 17 00:00:00 2001 From: Casper Warden <216465704+casperwardensl@users.noreply.github.com> Date: Wed, 22 Nov 2023 02:09:57 +0000 Subject: [PATCH] Inventory item copy --- examples/Inventory/Inventory.ts | 8 ++++- lib/classes/InventoryItem.ts | 61 +++++++++++++++++++++++++++++++++ package-lock.json | 4 +-- package.json | 2 +- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/examples/Inventory/Inventory.ts b/examples/Inventory/Inventory.ts index f062635..06d9305 100644 --- a/examples/Inventory/Inventory.ts +++ b/examples/Inventory/Inventory.ts @@ -8,6 +8,7 @@ import { InventoryType } from '../../lib/enums/InventoryType'; import { PermissionMask } from '../../lib/enums/PermissionMask'; import { InventoryResponseEvent } from '../../lib/events/InventoryResponseEvent'; import { InventoryOfferedEvent } from '../../lib/events/InventoryOfferedEvent'; +import { UUID } from '../../lib'; class Inventory extends ExampleBot { @@ -63,10 +64,15 @@ class Inventory extends ExampleBot } // Set notecard to transfer only - exampleNotecard.permissions.nextOwnerMask = PermissionMask.Transfer | PermissionMask.Modify; await exampleNotecard.update(); + // Make a copy of the notecard + const copy = await exampleNotecard.copyTo(exampleFolder, exampleNotecard.name + ' - The comeback ' + UUID.random().toString().substring(0, 8)); + + // Delete the copy + await copy.delete(); + let exampleScript = exampleFolder.items.find(f => f.name === exampleScriptName); if (exampleScript === undefined) { diff --git a/lib/classes/InventoryItem.ts b/lib/classes/InventoryItem.ts index 5b45849..3bd6d9e 100644 --- a/lib/classes/InventoryItem.ts +++ b/lib/classes/InventoryItem.ts @@ -1,6 +1,7 @@ import * as LLSD from '@caspertech/llsd'; import { Subscription } from 'rxjs'; import * as builder from 'xmlbuilder'; +import * as crypto from 'crypto'; import { GameObject } from '..'; import { AssetType } from '../enums/AssetType'; import { AssetTypeLL } from '../enums/AssetTypeLL'; @@ -28,6 +29,8 @@ import { Utils } from './Utils'; import { UUID } from './UUID'; import { Vector3 } from './Vector3'; import Timeout = NodeJS.Timeout; +import { CopyInventoryItemMessage } from './messages/CopyInventoryItem'; +import { BulkUpdateInventoryEvent } from '../events/BulkUpdateInventoryEvent'; export class InventoryItem { @@ -1109,6 +1112,64 @@ export class InventoryItem return this.agent.currentRegion.circuit.waitForAck(this.agent.currentRegion.circuit.sendMessage(msg, PacketFlags.Reliable), 10000); } + private async waitForCallbackID(callbackID: number): Promise + { + if (!this.agent) + { + throw new Error('No active agent'); + } + return Utils.waitOrTimeOut(this.agent.currentRegion.clientEvents.onBulkUpdateInventoryEvent, 10000, (event: BulkUpdateInventoryEvent) => + { + for (const item of event.itemData) + { + if (item.callbackID === callbackID) + { + return FilterResponse.Finish; + } + } + return FilterResponse.NoMatch; + }); + } + + public async copyTo(target: InventoryFolder, name: string): Promise + { + const msg = new CopyInventoryItemMessage(); + if (this.agent === undefined) + { + throw new Error('No active agent'); + } + msg.AgentData = { + AgentID: this.agent.agentID, + SessionID: this.agent.currentRegion.circuit.sessionID + }; + + const bytes = crypto.randomBytes(4); + const callbackID = bytes.readUInt32LE(0); + msg.InventoryData = [{ + CallbackID: callbackID, + OldAgentID: this.agent.agentID, + OldItemID: this.itemID, + NewFolderID: target.folderID, + NewName: Utils.StringToBuffer(name) + }]; + this.agent.currentRegion.circuit.sendMessage(msg, PacketFlags.Reliable); + const cbMsg = await this.waitForCallbackID(callbackID); + + for (const cbItem of cbMsg.itemData) + { + if (cbItem.callbackID === callbackID) + { + const item = await this.agent.inventory.fetchInventoryItem(cbItem.itemID); + if (item !== null) + { + return item; + } + } + } + + throw new Error('Unable to locate inventory item after copy'); + } + async updateScript(scriptAsset: Buffer): Promise { if (this.agent === undefined) diff --git a/package-lock.json b/package-lock.json index 36bf3d7..12b5ba6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@caspertech/node-metaverse", - "version": "0.7.9", + "version": "0.7.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@caspertech/node-metaverse", - "version": "0.7.9", + "version": "0.7.11", "license": "MIT", "dependencies": { "@caspertech/llsd": "^1.0.5", diff --git a/package.json b/package.json index 2c92bc8..3d06dd8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@caspertech/node-metaverse", - "version": "0.7.9", + "version": "0.7.11", "description": "A node.js interface for Second Life.", "main": "dist/lib/index.js", "types": "dist/lib/index.d.ts",