- 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:
Casper Warden
2018-10-20 14:32:33 +01:00
parent c291ed7eda
commit 4c6cbfc45b
14 changed files with 1144 additions and 34 deletions

View File

@@ -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
{

View File

@@ -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.');
});
}

View File

@@ -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;

View File

@@ -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])
{

View File

@@ -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);
}
});
}

View File

@@ -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 + '>';
}
}

View File

@@ -50,4 +50,8 @@ export class Vector2 extends vec2
buf.writeFloatLE(this.y, pos + 4);
}
}
toString(): string
{
return '<' + this.x + ', ' + this.y + '>';
}
}

View File

@@ -54,4 +54,8 @@ export class Vector3 extends vec3
buf.writeFloatLE(this.z, pos + 8);
}
}
toString(): string
{
return '<' + this.x + ', ' + this.y + ', ' + this.z + '>';
}
}

View File

@@ -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 + '>';
}
}

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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",