- Support Settings inventory objects

- Add some missing caps and flags
- Fix prims out of order when fetching and building
This commit is contained in:
Casper Warden
2021-09-23 16:37:54 +01:00
parent 6ecad4db55
commit 2c4833baf7
13 changed files with 247 additions and 120 deletions

View File

@@ -62,6 +62,13 @@ export class AssetMap
item: InventoryItem | null
}
} = {};
settings: {
[key: string]: {
name?: string,
description?: string,
item: InventoryItem | null
}
} = {};
notecards: {
[key: string]: {
name?: string,

View File

@@ -52,6 +52,7 @@ export class Caps
req.push('EstateAccess');
req.push('EstateChangeInfo');
req.push('EventQueueGet');
req.push('ExtEnvironment');
req.push('FetchLib2');
req.push('FetchLibDescendents2');
req.push('FetchInventory2');
@@ -69,7 +70,9 @@ export class Caps
req.push('UpdateExperience');
req.push('IsExperienceAdmin');
req.push('IsExperienceContributor');
req.push('InventoryAPIv3');
req.push('RegionExperiences');
req.push('ExperienceQuery');
req.push('GetMetadata');
req.push('GetObjectCost');
req.push('GetObjectPhysicsData');
@@ -120,13 +123,15 @@ export class Caps
req.push('UpdateNotecardTaskInventory');
req.push('UpdateScriptAgent');
req.push('UpdateScriptTask');
req.push('UpdateSettingsAgentInventory');
req.push('UpdateSettingsTaskInventory');
req.push('UploadBakedTexture');
req.push('UserInfo');
req.push('ViewerAsset');
req.push('ViewerBenefits');
req.push('ViewerMetrics');
req.push('ViewerStartAuction');
req.push('ViewerStats');
req.push('InventoryAPIv3');
this.active = true;
this.request(seedURL, LLSD.LLSD.formatXML(req), 'application/llsd+xml').then((resp: ICapResponse) =>

View File

@@ -2,10 +2,10 @@ import * as LLSD from '@caspertech/llsd';
import * as fsSync from 'fs';
import * as fs from 'fs/promises';
import * as path from 'path';
import { LLMesh } from '..';
import { AssetType } from '../enums/AssetType';
import { FilterResponse } from '../enums/FilterResponse';
import { FolderType } from '../enums/FolderType';
import { InventoryItemFlags } from '../enums/InventoryItemFlags';
import { InventoryLibrary } from '../enums/InventoryLibrary';
import { InventorySortOrder } from '../enums/InventorySortOrder';
import { InventoryType } from '../enums/InventoryType';
@@ -22,6 +22,7 @@ import { CreateInventoryFolderMessage } from './messages/CreateInventoryFolder';
import { CreateInventoryItemMessage } from './messages/CreateInventoryItem';
import { RequestXferMessage } from './messages/RequestXfer';
import { UpdateCreateInventoryItemMessage } from './messages/UpdateCreateInventoryItem';
import { LLMesh } from './public/LLMesh';
import { Utils } from './Utils';
import { UUID } from './UUID';
@@ -414,7 +415,7 @@ export class InventoryFolder
});
}
private uploadInventoryAssetLegacy(assetType: AssetType, inventoryType: InventoryType, data: Buffer, name: string, description: string): Promise<UUID>
private uploadInventoryAssetLegacy(assetType: AssetType, inventoryType: InventoryType, data: Buffer, name: string, description: string, flags: InventoryItemFlags): Promise<UUID>
{
return new Promise<UUID>(async (resolve, reject) =>
{
@@ -440,6 +441,14 @@ export class InventoryFolder
const wearable = new LLWearable(data.toString('utf-8'));
wearableType = wearable.type;
}
else
{
const wearableInFlags = flags & InventoryItemFlags.FlagsSubtypeMask;
if (wearableInFlags > 0)
{
wearableType = wearableInFlags;
}
}
createMsg.AgentData = {
AgentID: this.agent.agentID,
@@ -493,11 +502,16 @@ export class InventoryFolder
});
}
private uploadInventoryItem(assetType: AssetType, inventoryType: InventoryType, data: Buffer, name: string, description: string): Promise<UUID>
private uploadInventoryItem(assetType: AssetType, inventoryType: InventoryType, data: Buffer, name: string, description: string, flags: InventoryItemFlags): Promise<UUID>
{
return new Promise<UUID>((resolve, reject) =>
{
const wearableType = WearableType.Shape;
let wearableType = WearableType.Shape;
const wearableInFlags = flags & InventoryItemFlags.FlagsSubtypeMask;
if (wearableInFlags > 0)
{
wearableType = wearableInFlags;
}
const transactionID = UUID.zero();
const callbackID = ++this.callbackID;
@@ -566,6 +580,41 @@ export class InventoryFolder
});
break;
}
case InventoryType.Settings:
{
this.agent.currentRegion.caps.capsPostXML('UpdateSettingsAgentInventory', {
'item_id': new LLSD.UUID(createInventoryMsg.InventoryData[0].ItemID.toString()),
}).then((result: any) =>
{
if (result['uploader'])
{
const uploader = result['uploader'];
this.agent.currentRegion.caps.capsRequestUpload(uploader, data).then((uploadResult: any) =>
{
if (uploadResult['state'] && uploadResult['state'] === 'complete')
{
const itemID: UUID = createInventoryMsg.InventoryData[0].ItemID;
resolve(itemID);
}
else
{
reject(new Error('Asset upload failed'))
}
}).catch((err) =>
{
reject(err);
});
}
else
{
reject(new Error('Invalid response when attempting to request upload URL for notecard'));
}
}).catch((err) =>
{
reject(err);
});
break;
}
case InventoryType.Gesture:
{
this.agent.currentRegion.caps.isCapAvailable('UpdateGestureAgentInventory').then((available) =>
@@ -606,7 +655,7 @@ export class InventoryFolder
}
else
{
this.uploadInventoryAssetLegacy(assetType, inventoryType, data, name, description).then((invItemID: UUID) =>
this.uploadInventoryAssetLegacy(assetType, inventoryType, data, name, description, flags).then((invItemID: UUID) =>
{
resolve(invItemID);
}).catch((err: Error) =>
@@ -667,7 +716,7 @@ export class InventoryFolder
});
}
uploadAsset(type: AssetType, inventoryType: InventoryType, data: Buffer, name: string, description: string): Promise<InventoryItem>
uploadAsset(type: AssetType, inventoryType: InventoryType, data: Buffer, name: string, description: string, flags: InventoryItemFlags = InventoryItemFlags.None): Promise<InventoryItem>
{
return new Promise<InventoryItem>((resolve, reject) =>
{
@@ -676,7 +725,7 @@ export class InventoryFolder
case InventoryType.Wearable:
case InventoryType.Bodypart:
// Wearables have to be uploaded using the legacy method and then created
this.uploadInventoryAssetLegacy(type, inventoryType, data, name, description).then((invItemID: UUID) =>
this.uploadInventoryAssetLegacy(type, inventoryType, data, name, description, flags).then((invItemID: UUID) =>
{
this.agent.inventory.fetchInventoryItem(invItemID).then((item: InventoryItem | null) =>
{
@@ -705,8 +754,9 @@ export class InventoryFolder
case InventoryType.Gesture:
case InventoryType.Script:
case InventoryType.LSL:
case InventoryType.Settings:
// These types must be created first and then modified
this.uploadInventoryItem(type, inventoryType, data, name, description).then((invItemID: UUID) =>
this.uploadInventoryItem(type, inventoryType, data, name, description, flags).then((invItemID: UUID) =>
{
this.agent.inventory.fetchInventoryItem(invItemID).then((item: InventoryItem | null) =>
{

View File

@@ -1,33 +1,33 @@
import { UUID } from './UUID';
import { InventoryType } from '../enums/InventoryType';
import { PermissionMask } from '../enums/PermissionMask';
import { InventoryItemFlags } from '../enums/InventoryItemFlags';
import { AssetType } from '../enums/AssetType';
import * as builder from 'xmlbuilder';
import { Utils } from './Utils';
import { AttachmentPoint } from '../enums/AttachmentPoint';
import { RezSingleAttachmentFromInvMessage } from './messages/RezSingleAttachmentFromInv';
import { GameObject } from '..';
import { Agent } from './Agent';
import { Subscription } from 'rxjs';
import { DetachAttachmentIntoInvMessage } from './messages/DetachAttachmentIntoInv';
import { Vector3 } from './Vector3';
import { RezObjectMessage } from './messages/RezObject';
import { NewObjectEvent } from '../events/NewObjectEvent';
import { InventoryFolder } from './InventoryFolder';
import { MoveInventoryItemMessage } from './messages/MoveInventoryItem';
import { RemoveInventoryItemMessage } from './messages/RemoveInventoryItem';
import { SaleTypeLL } from '../enums/SaleTypeLL';
import { AssetTypeLL } from '../enums/AssetTypeLL';
import { UpdateTaskInventoryMessage } from './messages/UpdateTaskInventory';
import { PacketFlags } from '../enums/PacketFlags';
import Timeout = NodeJS.Timeout;
import * as LLSD from '@caspertech/llsd';
import { MoveTaskInventoryMessage } from './messages/MoveTaskInventory';
import { UpdateCreateInventoryItemMessage } from './messages/UpdateCreateInventoryItem';
import { Message } from '../enums/Message';
import { Subscription } from 'rxjs';
import * as builder from 'xmlbuilder';
import { GameObject } from '..';
import { AssetType } from '../enums/AssetType';
import { AssetTypeLL } from '../enums/AssetTypeLL';
import { AttachmentPoint } from '../enums/AttachmentPoint';
import { FilterResponse } from '../enums/FilterResponse';
import { InventoryItemFlags } from '../enums/InventoryItemFlags';
import { InventoryType } from '../enums/InventoryType';
import { Message } from '../enums/Message';
import { PacketFlags } from '../enums/PacketFlags';
import { PermissionMask } from '../enums/PermissionMask';
import { SaleTypeLL } from '../enums/SaleTypeLL';
import { NewObjectEvent } from '../events/NewObjectEvent';
import { Agent } from './Agent';
import { InventoryFolder } from './InventoryFolder';
import { DetachAttachmentIntoInvMessage } from './messages/DetachAttachmentIntoInv';
import { MoveInventoryItemMessage } from './messages/MoveInventoryItem';
import { MoveTaskInventoryMessage } from './messages/MoveTaskInventory';
import { RemoveInventoryItemMessage } from './messages/RemoveInventoryItem';
import { RezObjectMessage } from './messages/RezObject';
import { RezSingleAttachmentFromInvMessage } from './messages/RezSingleAttachmentFromInv';
import { UpdateCreateInventoryItemMessage } from './messages/UpdateCreateInventoryItem';
import { UpdateInventoryItemMessage } from './messages/UpdateInventoryItem';
import { UpdateTaskInventoryMessage } from './messages/UpdateTaskInventory';
import { Utils } from './Utils';
import { UUID } from './UUID';
import { Vector3 } from './Vector3';
import Timeout = NodeJS.Timeout;
export class InventoryItem
{
@@ -235,14 +235,10 @@ export class InventoryItem
case 'root':
item.inventoryType = InventoryType.RootCategory;
break;
case 'script':
item.inventoryType = InventoryType.Script;
break;
case 'snapshot':
item.inventoryType = InventoryType.Snapshot;
break;
case 'LSL':
case 'lsl':
case 'script':
item.inventoryType = InventoryType.LSL;
break;
case 'attach':
@@ -260,6 +256,15 @@ export class InventoryItem
case 'mesh':
item.inventoryType = InventoryType.Mesh;
break;
case 'settings':
item.inventoryType = InventoryType.Settings;
break;
case 'widget':
item.inventoryType = InventoryType.Widget;
break;
case 'person':
item.inventoryType = InventoryType.Person;
break;
default:
console.error('Unknown inventory type: ' + typeString);
}

View File

@@ -828,6 +828,9 @@ export class ObjectStoreLite implements IObjectStore
result.push(this.objects[localID]);
}
}
result.sort((a: GameObject, b: GameObject) => {
return a.ID - b.ID;
});
return result;
}

View File

@@ -1,17 +1,16 @@
import * as Long from 'long';
import { Quaternion } from './Quaternion';
import { GlobalPosition } from './public/interfaces/GlobalPosition';
import { HTTPAssets } from '../enums/HTTPAssets';
import { Vector3 } from './Vector3';
import { Subject, Subscription } from 'rxjs';
import { AssetType } from '../enums/AssetType';
import { InventoryType } from '../enums/InventoryType';
import { FilterResponse } from '../enums/FilterResponse';
import { Logger } from './Logger';
import * as zlib from 'zlib';
import * as xml2js from 'xml2js';
import * as zlib from 'zlib';
import { AssetType } from '../enums/AssetType';
import { FilterResponse } from '../enums/FilterResponse';
import { HTTPAssets } from '../enums/HTTPAssets';
import { InventoryType } from '../enums/InventoryType';
import { Logger } from './Logger';
import { GlobalPosition } from './public/interfaces/GlobalPosition';
import { Quaternion } from './Quaternion';
import { Vector3 } from './Vector3';
import Timeout = NodeJS.Timeout;
export class Utils
@@ -177,7 +176,13 @@ export class Utils
case InventoryType.Mesh:
return 'mesh';
case InventoryType.LSL:
return 'LSL';
return 'script';
case InventoryType.Widget:
return 'widget';
case InventoryType.Person:
return 'person';
case InventoryType.Settings:
return 'settings';
default:
console.error('Unknown inventory type: ' + InventoryType[type]);
return 'texture';
@@ -216,6 +221,12 @@ export class Utils
return AssetType.Bodypart;
case HTTPAssets.ASSET_MESH:
return AssetType.Mesh;
case HTTPAssets.ASSET_SETTINGS:
return AssetType.Settings;
case HTTPAssets.ASSET_WIDGET:
return AssetType.Widget;
case HTTPAssets.ASSET_PERSON:
return AssetType.Person;
default:
return 0;
}
@@ -253,6 +264,12 @@ export class Utils
return HTTPAssets.ASSET_BODYPART;
case AssetType.Mesh:
return HTTPAssets.ASSET_MESH;
case AssetType.Settings:
return HTTPAssets.ASSET_SETTINGS;
case AssetType.Person:
return HTTPAssets.ASSET_PERSON;
case AssetType.Widget:
return HTTPAssets.ASSET_WIDGET;
default:
return HTTPAssets.ASSET_TEXTURE;
}
@@ -276,7 +293,7 @@ export class Utils
case HTTPAssets.ASSET_CALLINGCARD:
return InventoryType.CallingCard;
case HTTPAssets.ASSET_SCRIPT:
return InventoryType.Script;
return InventoryType.LSL;
case HTTPAssets.ASSET_CLOTHING:
return InventoryType.Wearable;
case HTTPAssets.ASSET_OBJECT:
@@ -284,9 +301,9 @@ export class Utils
case HTTPAssets.ASSET_NOTECARD:
return InventoryType.Notecard;
case HTTPAssets.ASSET_LSL_TEXT:
return InventoryType.Script;
return InventoryType.LSL;
case HTTPAssets.ASSET_LSL_BYTECODE:
return InventoryType.Script;
return InventoryType.LSL;
case HTTPAssets.ASSET_BODYPART:
return InventoryType.Wearable;
case HTTPAssets.ASSET_MESH:

View File

@@ -1,40 +1,40 @@
import { CommandsBase } from './CommandsBase';
import { UUID } from '../UUID';
import { RegionHandleRequestMessage } from '../messages/RegionHandleRequest';
import { Message } from '../../enums/Message';
import { FilterResponse } from '../../enums/FilterResponse';
import { RegionIDAndHandleReplyMessage } from '../messages/RegionIDAndHandleReply';
import { ObjectGrabMessage } from '../messages/ObjectGrab';
import { ObjectDeGrabMessage } from '../messages/ObjectDeGrab';
import { ObjectGrabUpdateMessage } from '../messages/ObjectGrabUpdate';
import { ObjectSelectMessage } from '../messages/ObjectSelect';
import { ObjectPropertiesMessage } from '../messages/ObjectProperties';
import { Utils } from '../Utils';
import { ObjectDeselectMessage } from '../messages/ObjectDeselect';
import { ObjectAddMessage } from '../messages/ObjectAdd';
import { Quaternion } from '../Quaternion';
import { PacketFlags } from '../../enums/PacketFlags';
import { GameObject } from '../public/GameObject';
import { PCode } from '../../enums/PCode';
import { PrimFlags } from '../../enums/PrimFlags';
import { NewObjectEvent } from '../../events/NewObjectEvent';
import { Vector3 } from '../Vector3';
import { Parcel } from '../public/Parcel';
import { Subscription } from 'rxjs';
import { SculptType } from '../..';
import { AssetMap } from '../AssetMap';
import { InventoryType } from '../../enums/InventoryType';
import { BuildMap } from '../BuildMap';
import { ObjectResolver } from '../ObjectResolver';
import { Avatar } from '../public/Avatar';
import { EstateOwnerMessageMessage } from '../messages/EstateOwnerMessage';
import * as LLSD from '@caspertech/llsd';
import * as Long from 'long';
import * as micromatch from 'micromatch';
import * as LLSD from '@caspertech/llsd';
import { Subscription } from 'rxjs';
import { SculptType } from '../../enums/SculptType';
import { FilterResponse } from '../../enums/FilterResponse';
import { InventoryType } from '../../enums/InventoryType';
import { Message } from '../../enums/Message';
import { PacketFlags } from '../../enums/PacketFlags';
import { PCode } from '../../enums/PCode';
import { PrimFlags } from '../../enums/PrimFlags';
import { NewObjectEvent } from '../../events/NewObjectEvent';
import { AssetMap } from '../AssetMap';
import { BuildMap } from '../BuildMap';
import { EstateOwnerMessageMessage } from '../messages/EstateOwnerMessage';
import { ObjectAddMessage } from '../messages/ObjectAdd';
import { ObjectDeGrabMessage } from '../messages/ObjectDeGrab';
import { ObjectDeselectMessage } from '../messages/ObjectDeselect';
import { ObjectGrabMessage } from '../messages/ObjectGrab';
import { ObjectGrabUpdateMessage } from '../messages/ObjectGrabUpdate';
import { ObjectPropertiesMessage } from '../messages/ObjectProperties';
import { ObjectSelectMessage } from '../messages/ObjectSelect';
import { RegionHandleRequestMessage } from '../messages/RegionHandleRequest';
import { RegionIDAndHandleReplyMessage } from '../messages/RegionIDAndHandleReply';
import { ObjectResolver } from '../ObjectResolver';
import { Avatar } from '../public/Avatar';
import { GameObject } from '../public/GameObject';
import { Parcel } from '../public/Parcel';
import { Quaternion } from '../Quaternion';
import { Utils } from '../Utils';
import { UUID } from '../UUID';
import { Vector3 } from '../Vector3';
import { CommandsBase } from './CommandsBase';
import Timeout = NodeJS.Timeout;
import Timer = NodeJS.Timer;
import Timeout = NodeJS.Timeout;
export class RegionCommands extends CommandsBase
{
@@ -820,6 +820,18 @@ export class RegionCommands extends CommandsBase
}
break;
}
case InventoryType.Settings:
{
if (buildMap.assetMap.settings[invItem.assetID.toString()] !== undefined)
{
const item = buildMap.assetMap.settings[invItem.assetID.toString()].item;
if (item !== null)
{
await object.dropInventoryIntoContents(item);
}
}
break;
}
case InventoryType.Wearable:
case InventoryType.Bodypart:
{
@@ -1068,7 +1080,7 @@ export class RegionCommands extends CommandsBase
}
case InventoryType.Gesture:
{
if (buildMap.assetMap.clothing[assetID.toString()] === undefined)
if (buildMap.assetMap.gestures[assetID.toString()] === undefined)
{
buildMap.assetMap.gestures[assetID.toString()] = {
name: j.name,
@@ -1136,6 +1148,18 @@ export class RegionCommands extends CommandsBase
}
break;
}
case InventoryType.Settings:
{
if (buildMap.assetMap.settings[assetID.toString()] === undefined)
{
buildMap.assetMap.settings[assetID.toString()] = {
name: j.name,
description: j.description,
item: null
};
}
break;
}
default:
console.error('Unsupported inventory type: ' + j.inventoryType);
break;
@@ -1167,7 +1191,8 @@ export class RegionCommands extends CommandsBase
'8e915e25-31d1-cc95-ae08-d58a47488251',
'9742065b-19b5-297c-858a-29711d539043',
'03642e83-2bd1-4eb9-34b4-4c47ed586d2d',
'edd51b77-fc10-ce7a-4b3d-011dfc349e4f'
'edd51b77-fc10-ce7a-4b3d-011dfc349e4f',
'c228d1cf-4b5d-4ba8-84f4-899a0796aa97' // 'non existent asset'
];
for (const bomTexture of bomTextures)
{
@@ -1251,7 +1276,10 @@ export class RegionCommands extends CommandsBase
const parts = [];
parts.push(async () =>
{
return await this.buildPart(obj, Vector3.getZero(), Quaternion.getIdentity(), buildMap, true);
return {
index: 1,
object: await this.buildPart(obj, Vector3.getZero(), Quaternion.getIdentity(), buildMap, true)
}
});
if (obj.children)
@@ -1264,26 +1292,36 @@ export class RegionCommands extends CommandsBase
{
obj.Rotation = Quaternion.getIdentity();
}
let childIndex = 2;
for (const child of obj.children)
{
if (child.Position !== undefined && child.Rotation !== undefined)
{
const index = childIndex++;
parts.push(async () =>
{
return await this.buildPart(child, new Vector3(obj.Position), new Quaternion(obj.Rotation), buildMap, false);
return {
index,
object: await this.buildPart(child, new Vector3(obj.Position), new Quaternion(obj.Rotation), buildMap, false)
}
});
}
}
}
let results: {
results: GameObject[],
results: {
index: number,
object: GameObject
}[],
errors: Error[]
} = {
results: [],
errors: []
};
results = await Utils.promiseConcurrent<GameObject>(parts, 5, 0);
results = await Utils.promiseConcurrent<{
index: number,
object: GameObject
}>(parts, 5, 0);
if (results.errors.length > 0)
{
for (const err of results.errors)
@@ -1295,9 +1333,9 @@ export class RegionCommands extends CommandsBase
let rootObj: GameObject | null = null;
for (const childObject of results.results)
{
if (childObject.isMarkedRoot)
if (childObject.object.isMarkedRoot)
{
rootObj = childObject;
rootObj = childObject.object;
break;
}
}
@@ -1307,11 +1345,15 @@ export class RegionCommands extends CommandsBase
}
const childPrims: GameObject[] = [];
results.results.sort((a: {index: number, object: GameObject}, b: {index: number, object: GameObject}) =>
{
return a.index - b.index;
});
for (const childObject of results.results)
{
if (childObject !== rootObj)
if (childObject.object !== rootObj)
{
childPrims.push(childObject);
childPrims.push(childObject.object);
}
}
try

View File

@@ -10,30 +10,23 @@ export enum AssetType
Object = 6,
Notecard = 7,
Folder = 8,
RootFolder = 9,
Category = 8,
LSLText = 10,
LSLBytecode = 11,
TextureTGA = 12,
Bodypart = 13,
TrashFolder = 14,
SnapshotFolder = 15,
LostAndFoundFolder = 16,
SoundWAV = 17,
ImageTGA = 18,
ImageJPEG = 19,
Animation = 20,
Gesture = 21,
Simstate = 22,
FavoriteFolder = 23,
Link = 24,
LinkFolder = 25,
EnsembleStart = 26,
EnsembleEnd = 45,
CurrentOutfitFolder = 46,
OutfitFolder = 47,
MyOutfitsFolder = 48,
MarketplaceFolder = 26,
Widget = 40,
Person = 46,
Mesh = 49,
Inbox = 50,
Outbox = 51,
BasicRoot = 51
Settings = 56
}

View File

@@ -21,5 +21,8 @@ export enum AssetTypeLL
simstate = 22,
link = 24,
link_f = 25,
mesh = 49
}
widget = 40,
person = 45,
mesh = 49,
settings = 56,
}

View File

@@ -20,5 +20,6 @@ export enum HTTPAssets
ASSET_MESH = 'mesh',
ASSET_WIDGET = 'widget',
ASSET_PERSON = 'person',
ASSET_MATERIAL = 'material'
ASSET_MATERIAL = 'material',
ASSET_SETTINGS = 'settings',
}

View File

@@ -1,6 +1,7 @@
export enum InventoryItemFlags
{
None = 0,
LandmarkVisited = 1,
ObjectSlamPerm = 0x100,
ObjectSlamSale = 0x1000,
ObjectOverwriteBase = 0x010000,
@@ -9,5 +10,6 @@ export enum InventoryItemFlags
ObjectOverwriteEveryone = 0x080000,
ObjectOverwriteNextOwner = 0x100000,
ObjectHasMultipleItems = 0x200000,
FlagsSubtypeMask = 0x0000FF,
SharedSingleReference = 0x40000000
}

View File

@@ -13,15 +13,14 @@ export enum InventoryType
Folder = 8,
RootCategory = 9,
LSL = 10,
LSLBytecode = 11,
TextureTGA = 12,
Bodypart = 13,
Trash = 14,
Snapshot = 15,
LostAndFound = 16,
Attachment = 17,
Wearable = 18,
Animation = 19,
Gesture = 20,
Mesh = 22
Mesh = 22,
Widget = 23,
Person = 24,
Settings = 25
}

View File

@@ -1,6 +1,6 @@
{
"name": "@caspertech/node-metaverse",
"version": "0.5.25",
"version": "0.5.26",
"description": "A node.js interface for Second Life.",
"main": "dist/lib/index.js",
"types": "dist/lib/index.d.ts",