- When resolving objects, populate object costs (land impact)
- Add a function to find objects by name (regex or micromatch *glob style)
This commit is contained in:
@@ -295,7 +295,7 @@ async function connect()
|
||||
bot.clientCommands.agent.setCamera(
|
||||
new nmv.Vector3([128, 128, height]),
|
||||
new nmv.Vector3([128, 128, 0]),
|
||||
5000,
|
||||
256,
|
||||
new nmv.Vector3([-1.0, 0, 0]),
|
||||
new nmv.Vector3([0.0, 1.0, 0]));
|
||||
|
||||
@@ -351,27 +351,34 @@ async function connect()
|
||||
let totalObjects = 0;
|
||||
let totalLandImpact = 0;
|
||||
|
||||
const getLandImpact = function(obj)
|
||||
{
|
||||
let li = 0;
|
||||
if (obj.ownershipCost !== undefined && obj.ParentID === 0)
|
||||
{
|
||||
li += obj.ownershipCost;
|
||||
}
|
||||
/*for (const child of obj.children)
|
||||
{
|
||||
li += getLandImpact(child);
|
||||
}*/
|
||||
return li;
|
||||
};
|
||||
|
||||
for (const obj of objs)
|
||||
{
|
||||
totalObjects += (1 + obj.totalChildren);
|
||||
totalLandImpact += getLandImpact(obj);
|
||||
if (obj.landImpact)
|
||||
{
|
||||
totalLandImpact += obj.landImpact;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Found ' + objs.length + ' linksets with ' + totalObjects + ' objects in ' + (tmr2 - tmr) + 'ms. Land impact: ' + totalLandImpact);
|
||||
|
||||
let searchResults = await bot.clientCommands.region.findObjectsByName('FINDME-*');
|
||||
console.log('Found ' + searchResults.length + ' objects containing the string FINDME-*');
|
||||
for (const obj of searchResults)
|
||||
{
|
||||
console.log('Object: ' + obj.name + ', ' + obj.FullID.toString() + ', position: ' + obj.Position.toString() + ', land impact: ' + obj.ownershipCost)
|
||||
}
|
||||
|
||||
searchResults = await bot.clientCommands.region.findObjectsByName('rezcubes');
|
||||
console.log('Found ' + searchResults.length + ' objects containing the string rezcubes');
|
||||
for (const obj of searchResults)
|
||||
{
|
||||
console.log('Object: ' + obj.name + ', ' + obj.FullID.toString() + ', position: ' + obj.Position.toString() + ', land impact: ' + obj.ownershipCost)
|
||||
for (const k of Object.keys(obj.NameValue))
|
||||
{
|
||||
console.log(k + ': ' + obj.NameValue[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -300,7 +300,8 @@ export class Bot
|
||||
this.clientCommands.teleport.teleportTo(this.stayRegion, this.stayPosition, this.stayPosition).then(() =>
|
||||
{
|
||||
console.log('I found my way home.');
|
||||
}).catch(() => {
|
||||
}).catch(() =>
|
||||
{
|
||||
console.log('Cannot teleport home right now.');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@ export class GameObject
|
||||
resolvedAt?: number;
|
||||
totalChildren?: number;
|
||||
|
||||
landImpact?: number;
|
||||
physicaImpact?: number;
|
||||
resourceImpact?: number;
|
||||
linkResourceImpact?: number;
|
||||
linkPhysicsImpact?: number;
|
||||
limitingType?: string;
|
||||
|
||||
children?: GameObject[];
|
||||
rtreeEntry?: ITreeBoundingBox;
|
||||
|
||||
@@ -248,6 +248,15 @@ export class ObjectStoreFull extends ObjectStoreLite implements IObjectStore
|
||||
this.readExtraParams(objData.ExtraParams, 0, this.objects[localID]);
|
||||
this.objects[localID].NameValue = this.parseNameValues(Utils.BufferToStringSimple(objData.NameValue));
|
||||
|
||||
if (this.objects[localID].NameValue['AttachItemID'])
|
||||
{
|
||||
this.objects[localID].IsAttachment = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.objects[localID].IsAttachment = false;
|
||||
}
|
||||
|
||||
this.objectsByUUID[objData.FullID.toString()] = localID;
|
||||
if (!this.objectsByParent[parentID])
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ import {ObjectUpdateMessage} from './messages/ObjectUpdate';
|
||||
import {ObjectUpdateCachedMessage} from './messages/ObjectUpdateCached';
|
||||
import {ObjectUpdateCompressedMessage} from './messages/ObjectUpdateCompressed';
|
||||
import {ImprovedTerseObjectUpdateMessage} from './messages/ImprovedTerseObjectUpdate';
|
||||
import {MultipleObjectUpdateMessage} from './messages/MultipleObjectUpdate';
|
||||
import {RequestMultipleObjectsMessage} from './messages/RequestMultipleObjects';
|
||||
import {Agent} from './Agent';
|
||||
import {UUID} from './UUID';
|
||||
@@ -45,7 +44,6 @@ export class ObjectStoreLite implements IObjectStore
|
||||
Message.ObjectUpdateCached,
|
||||
Message.ObjectUpdateCompressed,
|
||||
Message.ImprovedTerseObjectUpdate,
|
||||
Message.MultipleObjectUpdate,
|
||||
Message.KillObject
|
||||
], (packet: Packet) =>
|
||||
{
|
||||
@@ -69,10 +67,6 @@ export class ObjectStoreLite implements IObjectStore
|
||||
const objectUpdateTerse = packet.message as ImprovedTerseObjectUpdateMessage;
|
||||
this.objectUpdateTerse(objectUpdateTerse);
|
||||
break;
|
||||
case Message.MultipleObjectUpdate:
|
||||
const multipleObjectUpdate = packet.message as MultipleObjectUpdateMessage;
|
||||
this.objectUpdateMultiple(multipleObjectUpdate);
|
||||
break;
|
||||
case Message.KillObject:
|
||||
const killObj = packet.message as KillObjectMessage;
|
||||
this.killObject(killObj);
|
||||
@@ -118,6 +112,15 @@ export class ObjectStoreLite implements IObjectStore
|
||||
|
||||
this.objects[localID].NameValue = this.parseNameValues(Utils.BufferToStringSimple(objData.NameValue));
|
||||
|
||||
if (this.objects[localID].NameValue['AttachItemID'])
|
||||
{
|
||||
this.objects[localID].IsAttachment = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.objects[localID].IsAttachment = false;
|
||||
}
|
||||
|
||||
if (objData.PCode === PCode.Avatar && this.objects[localID].FullID.toString() === this.agent.agentID.toString())
|
||||
{
|
||||
this.agent.localID = localID;
|
||||
@@ -354,15 +357,15 @@ export class ObjectStoreLite implements IObjectStore
|
||||
protected objectUpdateTerse(objectUpdateTerse: ImprovedTerseObjectUpdateMessage)
|
||||
{ }
|
||||
|
||||
protected objectUpdateMultiple(objectUpdateMultiple: MultipleObjectUpdateMessage)
|
||||
{ }
|
||||
|
||||
protected killObject(killObj: KillObjectMessage)
|
||||
{
|
||||
killObj.ObjectData.forEach((obj) =>
|
||||
{
|
||||
const objectID = obj.ID;
|
||||
this.deleteObject(objectID);
|
||||
if (this.objects[objectID])
|
||||
{
|
||||
this.deleteObject(objectID);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -36,4 +36,8 @@ export class Quaternion extends quat
|
||||
buf.writeFloatLE(q.y, pos + 4);
|
||||
buf.writeFloatLE(q.z, pos + 8);
|
||||
}
|
||||
toString(): string
|
||||
{
|
||||
return '<' + this.x + ', ' + this.y + ', ' + this.z + ', ' + this.w + '>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,4 +50,8 @@ export class Vector2 extends vec2
|
||||
buf.writeFloatLE(this.y, pos + 4);
|
||||
}
|
||||
}
|
||||
toString(): string
|
||||
{
|
||||
return '<' + this.x + ', ' + this.y + '>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,4 +54,8 @@ export class Vector3 extends vec3
|
||||
buf.writeFloatLE(this.z, pos + 8);
|
||||
}
|
||||
}
|
||||
toString(): string
|
||||
{
|
||||
return '<' + this.x + ', ' + this.y + ', ' + this.z + '>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,4 +33,8 @@ export class Vector4 extends vec4
|
||||
buf.writeFloatLE(this.z, pos + 8);
|
||||
buf.writeFloatLE(this.w, pos + 12);
|
||||
}
|
||||
toString(): string
|
||||
{
|
||||
return '<' + this.x + ', ' + this.y + ', ' + this.z + ', ' + this.w + '>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,10 +54,12 @@ export class AgentCommands extends CommandsBase
|
||||
{
|
||||
this.agent.cameraUpAxis = upAxis;
|
||||
}
|
||||
this.agent.sendAgentUpdate();
|
||||
}
|
||||
|
||||
setViewDistance(viewDistance: number)
|
||||
{
|
||||
this.agent.cameraFar = viewDistance;
|
||||
this.agent.sendAgentUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {RegionHandleRequestMessage} from '../messages/RegionHandleRequest';
|
||||
import {Message} from '../../enums/Message';
|
||||
import {FilterResponse} from '../../enums/FilterResponse';
|
||||
import {RegionIDAndHandleReplyMessage} from '../messages/RegionIDAndHandleReply';
|
||||
import {PacketFlags, Vector3} from '../..';
|
||||
import {PacketFlags, PCode, Vector3} from '../..';
|
||||
import {ObjectGrabMessage} from '../messages/ObjectGrab';
|
||||
import {ObjectDeGrabMessage} from '../messages/ObjectDeGrab';
|
||||
import {ObjectGrabUpdateMessage} from '../messages/ObjectGrabUpdate';
|
||||
@@ -14,7 +14,8 @@ import {ObjectSelectMessage} from '../messages/ObjectSelect';
|
||||
import {ObjectPropertiesMessage} from '../messages/ObjectProperties';
|
||||
import {Utils} from '../Utils';
|
||||
import {ObjectDeselectMessage} from '../messages/ObjectDeselect';
|
||||
import {PCode} from '../../enums/PCode';
|
||||
import * as micromatch from 'micromatch';
|
||||
import * as LLSD from "@caspertech/llsd";
|
||||
|
||||
export class RegionCommands extends CommandsBase
|
||||
{
|
||||
@@ -299,9 +300,104 @@ export class RegionCommands extends CommandsBase
|
||||
console.error(totalRemaining + ' objects could not be resolved');
|
||||
}
|
||||
}
|
||||
const that = this;
|
||||
const getCosts = async function(objIDs: UUID[])
|
||||
{
|
||||
const result = await that.currentRegion.caps.capsRequestXML('GetObjectCost', {
|
||||
'object_ids': objIDs
|
||||
});
|
||||
const uuids = Object.keys(result);
|
||||
for (const key of uuids)
|
||||
{
|
||||
const costs = result[key];
|
||||
const obj: GameObject = that.currentRegion.objects.getObjectByUUID(new UUID(key));
|
||||
obj.linkPhysicsImpact = parseFloat(costs['linked_set_physics_cost']);
|
||||
obj.linkResourceImpact = parseFloat(costs['linked_set_resource_cost']);
|
||||
obj.physicaImpact = parseFloat(costs['physics_cost']);
|
||||
obj.resourceImpact = parseFloat(costs['resource_cost']);
|
||||
|
||||
obj.landImpact = Math.ceil(obj.linkPhysicsImpact);
|
||||
if (obj.linkResourceImpact > obj.linkPhysicsImpact)
|
||||
{
|
||||
obj.landImpact = Math.ceil(obj.linkResourceImpact);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let ids: UUID[] = [];
|
||||
const promises: Promise<void>[] = [];
|
||||
for (const obj of objects)
|
||||
{
|
||||
ids.push(new LLSD.UUID(obj.FullID));
|
||||
if (ids.length > 255)
|
||||
{
|
||||
promises.push(getCosts(ids));
|
||||
ids = [];
|
||||
}
|
||||
}
|
||||
if (ids.length > 0)
|
||||
{
|
||||
promises.push(getCosts(ids));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
||||
async findObjectsByName(pattern: string | RegExp, minX?: number, maxX?: number, minY?: number, maxY?: number, minZ?: number, maxZ?: number): Promise<GameObject[]>
|
||||
{
|
||||
let objects: GameObject[] = [];
|
||||
if (minX !== undefined && maxX !== undefined && minY !== undefined && maxY !== undefined && minZ !== undefined && maxZ !== undefined)
|
||||
{
|
||||
objects = await this.getObjectsInArea(minX, maxX, minY, maxY, minZ, maxZ, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
objects = await this.getAllObjects(true);
|
||||
}
|
||||
const idCheck: {[key: string]: boolean} = {};
|
||||
const matches: GameObject[] = [];
|
||||
const it = function(go: GameObject)
|
||||
{
|
||||
if (go.name !== undefined)
|
||||
{
|
||||
let match = false;
|
||||
if (pattern instanceof RegExp)
|
||||
{
|
||||
if (pattern.test(go.name))
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match = micromatch.isMatch(go.name, pattern, {nocase: true});
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
const uuid = go.FullID.toString();
|
||||
if (!idCheck[uuid])
|
||||
{
|
||||
matches.push(go);
|
||||
idCheck[uuid] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (go.children && go.children.length > 0)
|
||||
{
|
||||
for (const child of go.children)
|
||||
{
|
||||
it(child);
|
||||
}
|
||||
}
|
||||
};
|
||||
for (const go of objects)
|
||||
{
|
||||
it(go);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
async getAllObjects(resolve: boolean = false): Promise<GameObject[]>
|
||||
{
|
||||
const objs = this.currentRegion.objects.getAllObjects();
|
||||
|
||||
@@ -54,6 +54,7 @@ import {ParticleDataFlags} from './enums/ParticleDataFlags';
|
||||
import {TextureFlags} from './enums/TextureFlags';
|
||||
import {SourcePattern} from './enums/SourcePattern';
|
||||
import {BlendFunc} from './enums/BlendFunc';
|
||||
import {PCode} from './enums/PCode';
|
||||
|
||||
export {
|
||||
Bot,
|
||||
@@ -88,6 +89,7 @@ export {
|
||||
TextureFlags,
|
||||
SourcePattern,
|
||||
BlendFunc,
|
||||
PCode,
|
||||
|
||||
// Events
|
||||
ChatEvent,
|
||||
|
||||
976
package-lock.json
generated
976
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/long": "^4.0.0",
|
||||
"@types/micromatch": "^3.1.0",
|
||||
"@types/mocha": "^5.2.5",
|
||||
"@types/node": "^10.11.6",
|
||||
"@types/request": "^2.47.1",
|
||||
@@ -43,6 +44,7 @@
|
||||
"@caspertech/llsd": "^1.0.0",
|
||||
"ipaddr.js": "^1.8.1",
|
||||
"long": "^4.0.0",
|
||||
"micromatch": "^3.1.10",
|
||||
"rbush-3d": "0.0.4",
|
||||
"request": "^2.88.0",
|
||||
"rxjs": "^6.3.3",
|
||||
|
||||
Reference in New Issue
Block a user