Teleport and EventQueue reliability improvements. Start plumbing for stayPut()

This commit is contained in:
Casper Warden
2018-10-09 20:03:28 +01:00
parent 56f99d3ef3
commit da9fe9710c
46 changed files with 1382 additions and 666 deletions

9
dist/Bot.d.ts vendored
View File

@@ -4,6 +4,7 @@ import { Region } from './classes/Region';
import { ClientEvents } from './classes/ClientEvents';
import { ClientCommands } from './classes/ClientCommands';
import { BotOptionFlags } from './enums/BotOptionFlags';
import { Vector3 } from './classes/Vector3';
export declare class Bot {
private loginParams;
private currentRegion;
@@ -17,13 +18,17 @@ export declare class Bot {
clientEvents: ClientEvents;
clientCommands: ClientCommands;
private eventQueueWaits;
private stay;
private stayRegion;
private stayPosition;
constructor(login: LoginParameters, options: BotOptionFlags);
stayPut(stay: boolean, regionName?: string, position?: Vector3): void;
login(): Promise<LoginResponse>;
changeRegion(region: Region): Promise<void>;
changeRegion(region: Region, requested: boolean): Promise<void>;
waitForEventQueue(timeout?: number): Promise<void>;
private closeCircuit;
private kicked;
private disconnected;
close(): Promise<void>;
connectToSim(): Promise<void>;
connectToSim(requested: boolean): Promise<void>;
}

58
dist/Bot.js vendored
View File

@@ -26,6 +26,7 @@ const DisconnectEvent_1 = require("./events/DisconnectEvent");
const StartPingCheck_1 = require("./classes/messages/StartPingCheck");
const FilterResponse_1 = require("./enums/FilterResponse");
const UUID_1 = require("./classes/UUID");
const Vector3_1 = require("./classes/Vector3");
class Bot {
constructor(login, options) {
this.ping = null;
@@ -34,6 +35,9 @@ class Bot {
this.circuitSubscription = null;
this.eventQueueRunning = false;
this.eventQueueWaits = {};
this.stay = false;
this.stayRegion = '';
this.stayPosition = new Vector3_1.Vector3();
this.clientEvents = new ClientEvents_1.ClientEvents();
this.loginParams = login;
this.options = options;
@@ -49,6 +53,13 @@ class Bot {
}
});
}
stayPut(stay, regionName, position) {
this.stay = stay;
if (regionName !== undefined && position !== undefined) {
this.stayRegion = regionName;
this.stayPosition = position;
}
}
login() {
return __awaiter(this, void 0, void 0, function* () {
const loginHandler = new LoginHandler_1.LoginHandler(this.clientEvents, this.options);
@@ -59,15 +70,16 @@ class Bot {
return response;
});
}
changeRegion(region) {
changeRegion(region, requested) {
return __awaiter(this, void 0, void 0, function* () {
this.closeCircuit();
this.currentRegion = region;
this.clientCommands = new ClientCommands_1.ClientCommands(this.currentRegion, this.agent, this);
if (this.ping !== null) {
clearInterval(this.ping);
this.ping = null;
}
yield this.connectToSim();
yield this.connectToSim(requested);
});
}
waitForEventQueue(timeout = 1000) {
@@ -89,14 +101,13 @@ class Bot {
});
}
closeCircuit() {
this.agent.shutdown();
this.currentRegion.shutdown();
if (this.circuitSubscription !== null) {
this.circuitSubscription.unsubscribe();
this.circuitSubscription = null;
}
delete this.currentRegion;
delete this.agent;
this.clientCommands.shutdown();
delete this.clientCommands;
if (this.ping !== null) {
clearInterval(this.ping);
@@ -105,6 +116,8 @@ class Bot {
}
kicked(message) {
this.closeCircuit();
this.agent.shutdown();
delete this.agent;
this.disconnected(false, message);
}
disconnected(requested, message) {
@@ -125,12 +138,17 @@ class Bot {
};
circuit.sendMessage(msg, PacketFlags_1.PacketFlags.Reliable);
yield circuit.waitForMessage(Message_1.Message.LogoutReply, 5000);
this.stayRegion = '';
this.stayPosition = new Vector3_1.Vector3();
this.closeCircuit();
this.agent.shutdown();
delete this.agent;
this.disconnected(true, 'Logout completed');
});
}
connectToSim() {
connectToSim(requested) {
return __awaiter(this, void 0, void 0, function* () {
this.agent.setCurrentRegion(this.currentRegion);
const circuit = this.currentRegion.circuit;
circuit.init();
const msg = new UseCircuitCode_1.UseCircuitCodeMessage();
@@ -147,7 +165,19 @@ class Bot {
CircuitCode: circuit.circuitCode
};
circuit.sendMessage(agentMovement, PacketFlags_1.PacketFlags.Reliable);
yield circuit.waitForMessage(Message_1.Message.RegionHandshake, 10000);
let agentPosition = null;
let regionName = null;
circuit.waitForMessage(Message_1.Message.AgentMovementComplete, 10000).then((agentMovementMsg) => {
agentPosition = agentMovementMsg.Data.Position;
if (regionName !== null) {
if (this.stayRegion === '' || requested) {
this.stayPut(this.stay, regionName, agentPosition);
}
}
}).catch(() => {
console.error('Timed out waiting for AgentMovementComplete');
});
const handshakeMessage = yield circuit.waitForMessage(Message_1.Message.RegionHandshake, 10000);
const handshakeReply = new RegionHandshakeReply_1.RegionHandshakeReplyMessage();
handshakeReply.AgentData = {
AgentID: this.agent.agentID,
@@ -157,6 +187,17 @@ class Bot {
Flags: RegionProtocolFlags_1.RegionProtocolFlags.SelfAppearanceSupport | RegionProtocolFlags_1.RegionProtocolFlags.AgentAppearanceService
};
yield circuit.waitForAck(circuit.sendMessage(handshakeReply, PacketFlags_1.PacketFlags.Reliable), 10000);
this.currentRegion.handshake(handshakeMessage).then(() => {
regionName = this.currentRegion.regionName;
if (agentPosition !== null) {
if (this.stayRegion === '' || requested) {
this.stayPut(this.stay, regionName, agentPosition);
}
}
}).catch((error) => {
console.error('Timed out getting handshake');
console.error(error);
});
if (this.clientCommands !== null) {
this.clientCommands.network.setBandwidth(1536000);
}
@@ -193,7 +234,10 @@ class Bot {
}).bind(this, {
pingID: this.pingNumber,
timeSent: new Date().getTime()
}));
})).then(() => {
}).catch(() => {
console.error('Timeout waiting for ping from the simulator - possible disconnection');
});
if ((new Date().getTime() - this.lastSuccessfulPing) > 60000) {
this.kicked('Circuit Timeout');
}

2
dist/Bot.js.map vendored

File diff suppressed because one or more lines are too long

View File

@@ -60,8 +60,10 @@ export declare class Agent {
serialNumber: number;
};
agentUpdateTimer: number | null;
estateManager: boolean;
private clientEvents;
constructor(clientEvents: ClientEvents);
setIsEstateManager(is: boolean): void;
getSessionAgentCount(uuid: UUID): number;
addChatSession(uuid: UUID): void;
hasChatSession(uuid: UUID): boolean;

View File

@@ -29,6 +29,7 @@ class Agent {
this.home = {};
this.gestures = [];
this.agentUpdateTimer = null;
this.estateManager = false;
this.inventory = new Inventory_1.Inventory(clientEvents, this);
this.clientEvents = clientEvents;
this.clientEvents.onGroupChatAgentListUpdate.subscribe((event) => {
@@ -48,6 +49,9 @@ class Agent {
}
});
}
setIsEstateManager(is) {
this.estateManager = is;
}
getSessionAgentCount(uuid) {
const str = uuid.toString();
if (this.chatSessions[str] === undefined) {

File diff suppressed because one or more lines are too long

View File

@@ -12,6 +12,7 @@ export declare class Caps {
private capabilities;
private clientEvents;
private agent;
private active;
eventQueueClient: EventQueueClient | null;
constructor(agent: Agent, region: Region, seedURL: string, clientEvents: ClientEvents);
downloadAsset(uuid: UUID, type: HTTPAssets): Promise<Buffer>;

View File

@@ -9,6 +9,7 @@ class Caps {
this.onGotSeedCap = new Subject_1.Subject();
this.gotSeedCap = false;
this.capabilities = {};
this.active = false;
this.eventQueueClient = null;
this.agent = agent;
this.clientEvents = clientEvents;
@@ -102,6 +103,7 @@ class Caps {
req.push('ViewerMetrics');
req.push('ViewerStartAuction');
req.push('ViewerStats');
this.active = true;
this.request(seedURL, LLSD.LLSD.formatXML(req), 'application/llsd+xml').then((body) => {
this.capabilities = LLSD.LLSD.parseXML(body);
this.gotSeedCap = true;
@@ -173,6 +175,10 @@ class Caps {
}
getCapability(capability) {
return new Promise((resolve, reject) => {
if (!this.active) {
reject(new Error('Requesting getCapability to an inactive Caps instance'));
return;
}
this.waitForSeedCapability().then(() => {
if (this.capabilities[capability]) {
resolve(this.capabilities[capability]);
@@ -221,6 +227,7 @@ class Caps {
if (this.eventQueueClient) {
this.eventQueueClient.shutdown();
}
this.active = false;
}
}
exports.Caps = Caps;

File diff suppressed because one or more lines are too long

View File

@@ -29,6 +29,7 @@ export declare class Circuit {
receivedPackets: {
[key: number]: number;
};
active: boolean;
private clientEvents;
private onPacketReceived;
private onAckReceived;

View File

@@ -15,6 +15,7 @@ class Circuit {
this.sequenceNumber = 0;
this.awaitingAck = {};
this.receivedPackets = {};
this.active = false;
this.clientEvents = clientEvents;
this.onPacketReceived = new Subject_1.Subject();
this.onAckReceived = new Subject_1.Subject();
@@ -29,6 +30,9 @@ class Circuit {
}).subscribe(callback);
}
sendMessage(message, flags) {
if (!this.active) {
throw new Error('Attempting to send a message on a closed circuit');
}
const packet = new Packet_1.Packet();
packet.message = message;
packet.sequenceNumber = this.sequenceNumber++;
@@ -37,6 +41,10 @@ class Circuit {
return packet.sequenceNumber;
}
resend(sequenceNumber) {
if (!this.active) {
console.log('Resend triggered, but circuit is not active!');
return;
}
if (this.awaitingAck[sequenceNumber]) {
const toResend = this.awaitingAck[sequenceNumber].packet;
toResend.packetFlags = toResend.packetFlags | PacketFlags_1.PacketFlags.Resent;
@@ -84,6 +92,7 @@ class Circuit {
});
this.client.on('error', (error) => {
});
this.active = true;
}
shutdown() {
Object.keys(this.awaitingAck).forEach((sequenceNumber) => {
@@ -101,6 +110,7 @@ class Circuit {
this.onPacketReceived.complete();
this.onAckReceived.complete();
}
this.active = false;
}
waitForMessage(id, timeout, filter) {
return new Promise((resolve, reject) => {

File diff suppressed because one or more lines are too long

View File

@@ -23,4 +23,5 @@ export declare class ClientCommands {
group: GroupCommands;
inventory: InventoryCommands;
constructor(region: Region, agent: Agent, bot: Bot);
shutdown(): void;
}

View File

@@ -23,6 +23,18 @@ class ClientCommands {
this.group = new GroupCommands_1.GroupCommands(region, agent, bot);
this.inventory = new InventoryCommands_1.InventoryCommands(region, agent, bot);
}
shutdown() {
this.network.shutdown();
this.asset.shutdown();
this.teleport.shutdown();
this.region.shutdown();
this.parcel.shutdown();
this.grid.shutdown();
this.comms.shutdown();
this.agent.shutdown();
this.group.shutdown();
this.inventory.shutdown();
}
}
exports.ClientCommands = ClientCommands;
//# sourceMappingURL=ClientCommands.js.map

View File

@@ -1 +1 @@
{"version":3,"file":"ClientCommands.js","sourceRoot":"","sources":["../../lib/classes/ClientCommands.ts"],"names":[],"mappings":";;AAGA,gEAA2D;AAC3D,4DAAuD;AACvD,kEAA6D;AAC7D,8DAAyD;AACzD,0DAAqD;AACrD,8EAAyE;AACzE,4DAAuD;AACvD,4DAAuD;AACvD,oEAA+D;AAC/D,8DAAyD;AAEzD;IAaI,YAAY,MAAc,EAAE,KAAY,EAAE,GAAQ;QAE9C,IAAI,CAAC,OAAO,GAAG,IAAI,iCAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,IAAI,6BAAa,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,GAAG,IAAI,mCAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,GAAG,IAAI,+BAAc,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,GAAG,IAAI,+BAAc,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,IAAI,2BAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,+CAAsB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5D,IAAI,CAAC,KAAK,GAAG,IAAI,6BAAa,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG,IAAI,6BAAa,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,SAAS,GAAG,IAAI,qCAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;CACJ;AA1BD,wCA0BC"}
{"version":3,"file":"ClientCommands.js","sourceRoot":"","sources":["../../lib/classes/ClientCommands.ts"],"names":[],"mappings":";;AAGA,gEAA2D;AAC3D,4DAAuD;AACvD,kEAA6D;AAC7D,8DAAyD;AACzD,0DAAqD;AACrD,8EAAyE;AACzE,4DAAuD;AACvD,4DAAuD;AACvD,oEAA+D;AAC/D,8DAAyD;AAEzD;IAaI,YAAY,MAAc,EAAE,KAAY,EAAE,GAAQ;QAE9C,IAAI,CAAC,OAAO,GAAG,IAAI,iCAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,IAAI,6BAAa,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,GAAG,IAAI,mCAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,GAAG,IAAI,+BAAc,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,GAAG,IAAI,+BAAc,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,IAAI,2BAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,+CAAsB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5D,IAAI,CAAC,KAAK,GAAG,IAAI,6BAAa,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG,IAAI,6BAAa,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,SAAS,GAAG,IAAI,qCAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;IACD,QAAQ;QAEJ,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;IAC9B,CAAC;CACJ;AAvCD,wCAuCC"}

View File

@@ -20,13 +20,19 @@ class EventQueueClient {
this.clientEvents.onEventQueueStateChange.next(state);
}
shutdown() {
const state = new __1.EventQueueStateChangeEvent();
state.active = false;
this.clientEvents.onEventQueueStateChange.next(state);
this.done = true;
if (this.currentRequest !== null) {
this.currentRequest.abort();
}
this.done = true;
const req = {
'ack': this.ack,
'done': true
};
this.capsRequestXML('EventQueueGet', req).then((data) => {
const state = new __1.EventQueueStateChangeEvent();
state.active = false;
this.clientEvents.onEventQueueStateChange.next(state);
});
}
Get() {
const req = {
@@ -35,131 +41,136 @@ class EventQueueClient {
};
const startTime = new Date().getTime();
this.capsRequestXML('EventQueueGet', req).then((data) => {
if (data['events']) {
data['events'].forEach((event) => {
try {
if (event['message']) {
switch (event['message']) {
case 'EnableSimulator':
break;
case 'ParcelProperties':
break;
case 'AgentGroupDataUpdate':
break;
case 'AgentStateUpdate':
break;
case 'TeleportFailed':
{
const tpEvent = new __1.TeleportEvent();
tpEvent.message = event['body']['Info'][0]['Reason'];
tpEvent.eventType = TeleportEventType_1.TeleportEventType.TeleportFailed;
tpEvent.simIP = '';
tpEvent.simPort = 0;
tpEvent.seedCapability = '';
this.clientEvents.onTeleportEvent.next(tpEvent);
break;
}
case "ChatterBoxSessionStartReply":
{
if (event['body']) {
const gcsje = new __1.GroupChatSessionJoinEvent();
gcsje.sessionID = new UUID_1.UUID(event['body']['session_id'].toString());
gcsje.success = event['body']['success'];
if (gcsje.success) {
this.agent.addChatSession(gcsje.sessionID);
}
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
}
break;
}
case 'ChatterBoxInvitation':
{
if (event['body'] && event['body']['instantmessage'] && event['body']['instantmessage']['message_params'] && event['body']['instantmessage']['message_params']['id']) {
const messageParams = event['body']['instantmessage']['message_params'];
const imSessionID = messageParams['id'];
const groupChatEvent = new __1.GroupChatEvent();
groupChatEvent.from = new UUID_1.UUID(messageParams['from_id'].toString());
groupChatEvent.fromName = messageParams['from_name'];
groupChatEvent.groupID = new UUID_1.UUID(messageParams['id'].toString());
groupChatEvent.message = messageParams['message'];
const requestedFolders = {
'method': 'accept invitation',
'session-id': imSessionID
};
this.caps.capsRequestXML('ChatSessionRequest', requestedFolders).then((ignore) => {
this.agent.addChatSession(groupChatEvent.groupID);
const gcsje = new __1.GroupChatSessionJoinEvent();
gcsje.sessionID = groupChatEvent.groupID;
gcsje.success = true;
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
this.clientEvents.onGroupChat.next(groupChatEvent);
}).catch((err) => {
console.error(err);
});
}
break;
}
case 'ChatterBoxSessionAgentListUpdates':
{
if (event['body']) {
if (event['body']['agent_updates']) {
Object.keys(event['body']['agent_updates']).forEach((agentUpdate) => {
const updObj = event['body']['agent_updates'][agentUpdate];
const gcsale = new __1.GroupChatSessionAgentListEvent();
gcsale.agentID = new UUID_1.UUID(agentUpdate);
gcsale.groupID = new UUID_1.UUID(event['body']['session_id'].toString());
gcsale.canVoiceChat = false;
gcsale.isModerator = false;
gcsale.entered = (updObj['transition'] === 'ENTER');
if (updObj['can_voice_chat'] === true) {
gcsale.canVoiceChat = true;
}
if (updObj['is_moderator'] === true) {
gcsale.isModerator = true;
}
this.clientEvents.onGroupChatAgentListUpdate.next(gcsale);
});
}
}
break;
}
case 'TeleportFinish':
{
const info = event['body']['Info'][0];
if (info['LocationID']) {
info['LocationID'] = Buffer.from(info['LocationID'].toArray()).readUInt32LE(0);
const regionHandleBuf = Buffer.from(info['RegionHandle'].toArray());
info['RegionHandle'] = new Long(regionHandleBuf.readUInt32LE(0), regionHandleBuf.readUInt32LE(4), true);
info['SimIP'] = new IPAddress_1.IPAddress(Buffer.from(info['SimIP'].toArray()), 0).toString();
info['TeleportFlags'] = Buffer.from(info['TeleportFlags'].toArray()).readUInt32LE(0);
const tpEvent = new __1.TeleportEvent();
tpEvent.message = '';
tpEvent.eventType = TeleportEventType_1.TeleportEventType.TeleportCompleted;
tpEvent.simIP = info['SimIP'];
tpEvent.simPort = info['SimPort'];
tpEvent.seedCapability = info['SeedCapability'];
this.clientEvents.onTeleportEvent.next(tpEvent);
}
break;
}
default:
console.log('Unhandled event:');
console.log(JSON.stringify(event, null, 4));
}
}
}
catch (erro) {
console.error('Error handling cap');
console.error(erro);
}
});
}
if (data['id']) {
this.ack = data['id'];
}
else {
this.ack = undefined;
}
try {
if (data['events']) {
data['events'].forEach((event) => {
try {
if (event['message']) {
switch (event['message']) {
case 'EnableSimulator':
break;
case 'ParcelProperties':
break;
case 'AgentGroupDataUpdate':
break;
case 'AgentStateUpdate':
break;
case 'TeleportFailed':
{
const tpEvent = new __1.TeleportEvent();
tpEvent.message = event['body']['Info'][0]['Reason'];
tpEvent.eventType = TeleportEventType_1.TeleportEventType.TeleportFailed;
tpEvent.simIP = '';
tpEvent.simPort = 0;
tpEvent.seedCapability = '';
this.clientEvents.onTeleportEvent.next(tpEvent);
break;
}
case "ChatterBoxSessionStartReply":
{
if (event['body']) {
const gcsje = new __1.GroupChatSessionJoinEvent();
gcsje.sessionID = new UUID_1.UUID(event['body']['session_id'].toString());
gcsje.success = event['body']['success'];
if (gcsje.success) {
this.agent.addChatSession(gcsje.sessionID);
}
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
}
break;
}
case 'ChatterBoxInvitation':
{
if (event['body'] && event['body']['instantmessage'] && event['body']['instantmessage']['message_params'] && event['body']['instantmessage']['message_params']['id']) {
const messageParams = event['body']['instantmessage']['message_params'];
const imSessionID = messageParams['id'];
const groupChatEvent = new __1.GroupChatEvent();
groupChatEvent.from = new UUID_1.UUID(messageParams['from_id'].toString());
groupChatEvent.fromName = messageParams['from_name'];
groupChatEvent.groupID = new UUID_1.UUID(messageParams['id'].toString());
groupChatEvent.message = messageParams['message'];
const requestedFolders = {
'method': 'accept invitation',
'session-id': imSessionID
};
this.caps.capsRequestXML('ChatSessionRequest', requestedFolders).then((ignore) => {
this.agent.addChatSession(groupChatEvent.groupID);
const gcsje = new __1.GroupChatSessionJoinEvent();
gcsje.sessionID = groupChatEvent.groupID;
gcsje.success = true;
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
this.clientEvents.onGroupChat.next(groupChatEvent);
}).catch((err) => {
console.error(err);
});
}
break;
}
case 'ChatterBoxSessionAgentListUpdates':
{
if (event['body']) {
if (event['body']['agent_updates']) {
Object.keys(event['body']['agent_updates']).forEach((agentUpdate) => {
const updObj = event['body']['agent_updates'][agentUpdate];
const gcsale = new __1.GroupChatSessionAgentListEvent();
gcsale.agentID = new UUID_1.UUID(agentUpdate);
gcsale.groupID = new UUID_1.UUID(event['body']['session_id'].toString());
gcsale.canVoiceChat = false;
gcsale.isModerator = false;
gcsale.entered = (updObj['transition'] === 'ENTER');
if (updObj['can_voice_chat'] === true) {
gcsale.canVoiceChat = true;
}
if (updObj['is_moderator'] === true) {
gcsale.isModerator = true;
}
this.clientEvents.onGroupChatAgentListUpdate.next(gcsale);
});
}
}
break;
}
case 'TeleportFinish':
{
const info = event['body']['Info'][0];
if (info['LocationID']) {
info['LocationID'] = Buffer.from(info['LocationID'].toArray()).readUInt32LE(0);
const regionHandleBuf = Buffer.from(info['RegionHandle'].toArray());
info['RegionHandle'] = new Long(regionHandleBuf.readUInt32LE(0), regionHandleBuf.readUInt32LE(4), true);
info['SimIP'] = new IPAddress_1.IPAddress(Buffer.from(info['SimIP'].toArray()), 0).toString();
info['TeleportFlags'] = Buffer.from(info['TeleportFlags'].toArray()).readUInt32LE(0);
const tpEvent = new __1.TeleportEvent();
tpEvent.message = '';
tpEvent.eventType = TeleportEventType_1.TeleportEventType.TeleportCompleted;
tpEvent.simIP = info['SimIP'];
tpEvent.simPort = info['SimPort'];
tpEvent.seedCapability = info['SeedCapability'];
this.clientEvents.onTeleportEvent.next(tpEvent);
}
break;
}
default:
console.log('Unhandled event:');
console.log(JSON.stringify(event, null, 4));
}
}
}
catch (erro) {
console.error('Error handling cap');
console.error(erro);
}
});
}
}
catch (error) {
console.error(error);
}
if (!this.done) {
this.Get();
}
@@ -171,12 +182,14 @@ class EventQueueClient {
}
}
else {
console.error('Event queue aborted after ' + time + 'ms. Reconnecting in 5 seconds');
setTimeout(() => {
if (!this.done) {
this.Get();
}
}, 5000);
if (!this.done) {
console.error('Event queue aborted after ' + time + 'ms. Reconnecting in 5 seconds');
setTimeout(() => {
if (!this.done) {
this.Get();
}
}, 5000);
}
}
});
}
@@ -214,7 +227,7 @@ class EventQueueClient {
resolve(parsed);
}
else {
if (attempt < 3) {
if (attempt < 3 && capability !== 'EventQueueGet') {
return this.capsRequestXML(capability, data, ++attempt);
}
else {

File diff suppressed because one or more lines are too long

View File

@@ -4,10 +4,58 @@ import { Caps } from './Caps';
import { Comms } from './Comms';
import { ClientEvents } from './ClientEvents';
import { IObjectStore } from './interfaces/IObjectStore';
import { BotOptionFlags } from '..';
import { BotOptionFlags, UUID } from '..';
import { RegionFlags } from '../enums/RegionFlags';
import { RegionHandshakeMessage } from './messages/RegionHandshake';
import * as Long from 'long';
export declare class Region {
regionName: string;
regionOwner: UUID;
regionID: UUID;
regionHandle: Long;
xCoordinate: number;
yCoordinate: number;
estateID: number;
parentEstateID: number;
regionFlags: RegionFlags;
mapImage: UUID;
simAccess: number;
maxAgents: number;
billableFactor: number;
objectBonusFactor: number;
waterHeight: number;
terrainRaiseLimit: number;
terrainLowerLimit: number;
pricePerMeter: number;
redirectGridX: number;
redirectGridY: number;
useEstateSun: boolean;
sunHour: number;
productSKU: string;
productName: string;
maxAgents32: number;
hardMaxAgents: number;
hardMaxObjects: number;
cacheID: UUID;
cpuClassID: number;
cpuRatio: number;
coloName: string;
terrainBase0: UUID;
terrainBase1: UUID;
terrainBase2: UUID;
terrainBase3: UUID;
terrainDetail0: UUID;
terrainDetail1: UUID;
terrainDetail2: UUID;
terrainDetail3: UUID;
terrainStartHeight00: number;
terrainStartHeight01: number;
terrainStartHeight10: number;
terrainStartHeight11: number;
terrainHeightRange00: number;
terrainHeightRange01: number;
terrainHeightRange10: number;
terrainHeightRange11: number;
circuit: Circuit;
objects: IObjectStore;
caps: Caps;
@@ -17,5 +65,6 @@ export declare class Region {
agent: Agent;
constructor(agent: Agent, clientEvents: ClientEvents, options: BotOptionFlags);
activateCaps(seedURL: string): void;
handshake(handshake: RegionHandshakeMessage): Promise<void>;
shutdown(): void;
}

View File

@@ -1,4 +1,12 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const Circuit_1 = require("./Circuit");
const Caps_1 = require("./Caps");
@@ -6,6 +14,12 @@ const Comms_1 = require("./Comms");
const ObjectStoreFull_1 = require("./ObjectStoreFull");
const ObjectStoreLite_1 = require("./ObjectStoreLite");
const __1 = require("..");
const RequestRegionInfo_1 = require("./messages/RequestRegionInfo");
const Message_1 = require("../enums/Message");
const Utils_1 = require("./Utils");
const MapNameRequest_1 = require("./messages/MapNameRequest");
const GridLayerType_1 = require("../enums/GridLayerType");
const FilterResponse_1 = require("../enums/FilterResponse");
class Region {
constructor(agent, clientEvents, options) {
this.agent = agent;
@@ -23,6 +37,86 @@ class Region {
activateCaps(seedURL) {
this.caps = new Caps_1.Caps(this.agent, this, seedURL, this.clientEvents);
}
handshake(handshake) {
return __awaiter(this, void 0, void 0, function* () {
this.regionName = Utils_1.Utils.BufferToStringSimple(handshake.RegionInfo.SimName);
this.simAccess = handshake.RegionInfo.SimAccess;
this.regionFlags = handshake.RegionInfo.RegionFlags;
this.regionOwner = handshake.RegionInfo.SimOwner;
this.agent.setIsEstateManager(handshake.RegionInfo.IsEstateManager);
this.waterHeight = handshake.RegionInfo.WaterHeight;
this.billableFactor = handshake.RegionInfo.BillableFactor;
this.cacheID = handshake.RegionInfo.CacheID;
this.terrainBase0 = handshake.RegionInfo.TerrainBase0;
this.terrainBase1 = handshake.RegionInfo.TerrainBase1;
this.terrainBase2 = handshake.RegionInfo.TerrainBase2;
this.terrainBase3 = handshake.RegionInfo.TerrainBase3;
this.terrainDetail0 = handshake.RegionInfo.TerrainDetail0;
this.terrainDetail1 = handshake.RegionInfo.TerrainDetail1;
this.terrainDetail2 = handshake.RegionInfo.TerrainDetail2;
this.terrainDetail3 = handshake.RegionInfo.TerrainDetail3;
this.terrainStartHeight00 = handshake.RegionInfo.TerrainStartHeight00;
this.terrainStartHeight01 = handshake.RegionInfo.TerrainStartHeight01;
this.terrainStartHeight10 = handshake.RegionInfo.TerrainStartHeight10;
this.terrainStartHeight11 = handshake.RegionInfo.TerrainStartHeight11;
this.terrainHeightRange00 = handshake.RegionInfo.TerrainHeightRange00;
this.terrainHeightRange01 = handshake.RegionInfo.TerrainHeightRange01;
this.terrainHeightRange10 = handshake.RegionInfo.TerrainHeightRange10;
this.terrainHeightRange11 = handshake.RegionInfo.TerrainHeightRange11;
this.regionID = handshake.RegionInfo2.RegionID;
this.cpuClassID = handshake.RegionInfo3.CPUClassID;
this.cpuRatio = handshake.RegionInfo3.CPURatio;
this.coloName = Utils_1.Utils.BufferToStringSimple(handshake.RegionInfo3.ColoName);
this.productSKU = Utils_1.Utils.BufferToStringSimple(handshake.RegionInfo3.ProductSKU);
this.productName = Utils_1.Utils.BufferToStringSimple(handshake.RegionInfo3.ProductName);
const request = new RequestRegionInfo_1.RequestRegionInfoMessage();
request.AgentData = {
AgentID: this.agent.agentID,
SessionID: this.circuit.sessionID
};
this.circuit.sendMessage(request, __1.PacketFlags.Reliable);
const regionInfo = yield this.circuit.waitForMessage(Message_1.Message.RegionInfo, 10000);
this.estateID = regionInfo.RegionInfo.EstateID;
this.parentEstateID = regionInfo.RegionInfo.ParentEstateID;
this.maxAgents = regionInfo.RegionInfo.MaxAgents;
this.objectBonusFactor = regionInfo.RegionInfo.ObjectBonusFactor;
this.terrainRaiseLimit = regionInfo.RegionInfo.TerrainRaiseLimit;
this.terrainLowerLimit = regionInfo.RegionInfo.TerrainLowerLimit;
this.pricePerMeter = regionInfo.RegionInfo.PricePerMeter;
this.redirectGridX = regionInfo.RegionInfo.RedirectGridX;
this.redirectGridY = regionInfo.RegionInfo.RedirectGridY;
this.useEstateSun = regionInfo.RegionInfo.UseEstateSun;
this.sunHour = regionInfo.RegionInfo.SunHour;
this.maxAgents32 = regionInfo.RegionInfo2.MaxAgents32;
this.hardMaxAgents = regionInfo.RegionInfo2.HardMaxAgents;
this.hardMaxObjects = regionInfo.RegionInfo2.HardMaxObjects;
const msg = new MapNameRequest_1.MapNameRequestMessage();
msg.AgentData = {
AgentID: this.agent.agentID,
SessionID: this.circuit.sessionID,
Flags: GridLayerType_1.GridLayerType.Objects,
EstateID: 0,
Godlike: false
};
msg.NameData = {
Name: handshake.RegionInfo.SimName
};
this.circuit.sendMessage(msg, __1.PacketFlags.Reliable);
const reply = yield this.circuit.waitForMessage(Message_1.Message.MapBlockReply, 10000, (filterMsg) => {
for (const region of filterMsg.Data) {
const name = Utils_1.Utils.BufferToStringSimple(region.Name);
if (name.trim().toLowerCase() === this.regionName.trim().toLowerCase()) {
this.xCoordinate = region.X;
this.yCoordinate = region.Y;
this.mapImage = region.MapImageID;
this.regionHandle = Utils_1.Utils.RegionCoordinatesToHandle(this.xCoordinate, this.yCoordinate);
return FilterResponse_1.FilterResponse.Finish;
}
}
return FilterResponse_1.FilterResponse.NoMatch;
});
});
}
shutdown() {
this.comms.shutdown();
this.caps.shutdown();

File diff suppressed because one or more lines are too long

View File

@@ -8,4 +8,5 @@ export declare class CommandsBase {
protected bot: Bot;
protected circuit: Circuit;
constructor(region: Region, agent: Agent, bot: Bot);
shutdown(): void;
}

View File

@@ -7,6 +7,8 @@ class CommandsBase {
this.bot = bot;
this.circuit = this.currentRegion.circuit;
}
shutdown() {
}
}
exports.CommandsBase = CommandsBase;
//# sourceMappingURL=CommandsBase.js.map

View File

@@ -1 +1 @@
{"version":3,"file":"CommandsBase.js","sourceRoot":"","sources":["../../../lib/classes/commands/CommandsBase.ts"],"names":[],"mappings":";;AAKA;IAOI,YAAY,MAAc,EAAE,KAAY,EAAE,GAAQ;QAE9C,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;IAC9C,CAAC;CACJ;AAdD,oCAcC"}
{"version":3,"file":"CommandsBase.js","sourceRoot":"","sources":["../../../lib/classes/commands/CommandsBase.ts"],"names":[],"mappings":";;AAKA;IAOI,YAAY,MAAc,EAAE,KAAY,EAAE,GAAQ;QAE9C,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;IAC9C,CAAC;IACD,QAAQ;IAGR,CAAC;CACJ;AAlBD,oCAkBC"}

View File

@@ -1,8 +1,14 @@
import { CommandsBase } from './CommandsBase';
import { Region } from '../Region';
import { Vector3 } from '../Vector3';
import * as Long from 'long';
import { LureEvent, TeleportEvent } from '../..';
import { LureEvent, TeleportEvent, Bot } from '../..';
import { Agent } from '../Agent';
export declare class TeleportCommands extends CommandsBase {
private expectingTeleport;
private teleportSubscription;
constructor(region: Region, agent: Agent, bot: Bot);
shutdown(): void;
private awaitTeleportEvent;
acceptTeleport(lure: LureEvent): Promise<TeleportEvent>;
teleportToHandle(handle: Long, position: Vector3, lookAt: Vector3): Promise<TeleportEvent>;

View File

@@ -7,15 +7,48 @@ const TeleportLureRequest_1 = require("../messages/TeleportLureRequest");
const TeleportLocationRequest_1 = require("../messages/TeleportLocationRequest");
const __1 = require("../..");
class TeleportCommands extends CommandsBase_1.CommandsBase {
awaitTeleportEvent() {
constructor(region, agent, bot) {
super(region, agent, bot);
this.expectingTeleport = false;
this.teleportSubscription = this.bot.clientEvents.onTeleportEvent.subscribe((e) => {
if (e.eventType === TeleportEventType_1.TeleportEventType.TeleportCompleted) {
if (!this.expectingTeleport) {
if (e.simIP === 'local') {
return;
}
const newRegion = new Region_1.Region(this.agent, this.bot.clientEvents, this.currentRegion.options);
newRegion.circuit.circuitCode = this.currentRegion.circuit.circuitCode;
newRegion.circuit.secureSessionID = this.currentRegion.circuit.secureSessionID;
newRegion.circuit.sessionID = this.currentRegion.circuit.sessionID;
newRegion.circuit.udpBlacklist = this.currentRegion.circuit.udpBlacklist;
newRegion.circuit.ipAddress = e.simIP;
newRegion.circuit.port = e.simPort;
newRegion.activateCaps(e.seedCapability);
this.bot.changeRegion(newRegion, false).then(() => {
}).catch((error) => {
console.log('Failed to change region');
console.error(error);
});
}
}
});
}
shutdown() {
this.teleportSubscription.unsubscribe();
}
awaitTeleportEvent(requested) {
return new Promise((resolve, reject) => {
if (this.currentRegion.caps.eventQueueClient) {
if (this.bot.clientEvents === null) {
reject(new Error('ClientEvents is null'));
return;
}
this.expectingTeleport = true;
const subscription = this.bot.clientEvents.onTeleportEvent.subscribe((e) => {
if (e.eventType === TeleportEventType_1.TeleportEventType.TeleportFailed || e.eventType === TeleportEventType_1.TeleportEventType.TeleportCompleted) {
setTimeout(() => {
this.expectingTeleport = false;
});
subscription.unsubscribe();
}
if (e.eventType === TeleportEventType_1.TeleportEventType.TeleportFailed) {
@@ -30,7 +63,6 @@ class TeleportCommands extends CommandsBase_1.CommandsBase {
reject(new Error('ClientEvents is null'));
return;
}
this.currentRegion.shutdown();
const region = new Region_1.Region(this.agent, this.bot.clientEvents, this.currentRegion.options);
region.circuit.circuitCode = this.currentRegion.circuit.circuitCode;
region.circuit.secureSessionID = this.currentRegion.circuit.secureSessionID;
@@ -38,10 +70,8 @@ class TeleportCommands extends CommandsBase_1.CommandsBase {
region.circuit.udpBlacklist = this.currentRegion.circuit.udpBlacklist;
region.circuit.ipAddress = e.simIP;
region.circuit.port = e.simPort;
this.agent.setCurrentRegion(region);
this.currentRegion = region;
this.currentRegion.activateCaps(e.seedCapability);
this.bot.changeRegion(this.currentRegion).then(() => {
region.activateCaps(e.seedCapability);
this.bot.changeRegion(region, requested).then(() => {
resolve(e);
}).catch((error) => {
reject(error);
@@ -65,7 +95,7 @@ class TeleportCommands extends CommandsBase_1.CommandsBase {
TeleportFlags: __1.TeleportFlags.ViaLure
};
circuit.sendMessage(tlr, __1.PacketFlags.Reliable);
this.awaitTeleportEvent().then((event) => {
this.awaitTeleportEvent(true).then((event) => {
resolve(event);
}).catch((err) => {
reject(err);
@@ -85,7 +115,7 @@ class TeleportCommands extends CommandsBase_1.CommandsBase {
RegionHandle: handle
};
this.circuit.sendMessage(rtm, __1.PacketFlags.Reliable);
this.awaitTeleportEvent().then((event) => {
this.awaitTeleportEvent(true).then((event) => {
resolve(event);
}).catch((err) => {
reject(err);

File diff suppressed because one or more lines are too long

34
dist/enums/RegionFlags.d.ts vendored Normal file
View File

@@ -0,0 +1,34 @@
export declare enum RegionFlags {
None = 0,
AllowDamage = 1,
AllowLandmark = 2,
AllowSetHome = 4,
ResetHomeOnTeleport = 8,
SunFixed = 16,
TaxFree = 32,
BlockTerraform = 64,
BlockLandResell = 128,
Sandbox = 256,
NullLayer = 512,
SkipAgentAction = 1024,
SkipUpdateInterestList = 2048,
SkipCollisions = 4096,
SkipScripts = 8192,
SkipPhysics = 16384,
ExternallyVisible = 32768,
MainlandVisible = 65536,
PublicAllowed = 131072,
BlockDwell = 262144,
NoFly = 524288,
AllowDirectTeleport = 1048576,
EstateSkipScripts = 2097152,
RestrictPushObject = 4194304,
DenyAnonymous = 8388608,
DenyIdentified = 16777216,
DenyTransacted = 33554432,
AllowParcelChanges = 67108864,
AbuseEmailToEstateOwner = 134217728,
AllowVoice = 268435456,
BlockParcelSearch = 536870912,
DenyAgeUnverified = 1073741824
}

38
dist/enums/RegionFlags.js vendored Normal file
View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var RegionFlags;
(function (RegionFlags) {
RegionFlags[RegionFlags["None"] = 0] = "None";
RegionFlags[RegionFlags["AllowDamage"] = 1] = "AllowDamage";
RegionFlags[RegionFlags["AllowLandmark"] = 2] = "AllowLandmark";
RegionFlags[RegionFlags["AllowSetHome"] = 4] = "AllowSetHome";
RegionFlags[RegionFlags["ResetHomeOnTeleport"] = 8] = "ResetHomeOnTeleport";
RegionFlags[RegionFlags["SunFixed"] = 16] = "SunFixed";
RegionFlags[RegionFlags["TaxFree"] = 32] = "TaxFree";
RegionFlags[RegionFlags["BlockTerraform"] = 64] = "BlockTerraform";
RegionFlags[RegionFlags["BlockLandResell"] = 128] = "BlockLandResell";
RegionFlags[RegionFlags["Sandbox"] = 256] = "Sandbox";
RegionFlags[RegionFlags["NullLayer"] = 512] = "NullLayer";
RegionFlags[RegionFlags["SkipAgentAction"] = 1024] = "SkipAgentAction";
RegionFlags[RegionFlags["SkipUpdateInterestList"] = 2048] = "SkipUpdateInterestList";
RegionFlags[RegionFlags["SkipCollisions"] = 4096] = "SkipCollisions";
RegionFlags[RegionFlags["SkipScripts"] = 8192] = "SkipScripts";
RegionFlags[RegionFlags["SkipPhysics"] = 16384] = "SkipPhysics";
RegionFlags[RegionFlags["ExternallyVisible"] = 32768] = "ExternallyVisible";
RegionFlags[RegionFlags["MainlandVisible"] = 65536] = "MainlandVisible";
RegionFlags[RegionFlags["PublicAllowed"] = 131072] = "PublicAllowed";
RegionFlags[RegionFlags["BlockDwell"] = 262144] = "BlockDwell";
RegionFlags[RegionFlags["NoFly"] = 524288] = "NoFly";
RegionFlags[RegionFlags["AllowDirectTeleport"] = 1048576] = "AllowDirectTeleport";
RegionFlags[RegionFlags["EstateSkipScripts"] = 2097152] = "EstateSkipScripts";
RegionFlags[RegionFlags["RestrictPushObject"] = 4194304] = "RestrictPushObject";
RegionFlags[RegionFlags["DenyAnonymous"] = 8388608] = "DenyAnonymous";
RegionFlags[RegionFlags["DenyIdentified"] = 16777216] = "DenyIdentified";
RegionFlags[RegionFlags["DenyTransacted"] = 33554432] = "DenyTransacted";
RegionFlags[RegionFlags["AllowParcelChanges"] = 67108864] = "AllowParcelChanges";
RegionFlags[RegionFlags["AbuseEmailToEstateOwner"] = 134217728] = "AbuseEmailToEstateOwner";
RegionFlags[RegionFlags["AllowVoice"] = 268435456] = "AllowVoice";
RegionFlags[RegionFlags["BlockParcelSearch"] = 536870912] = "BlockParcelSearch";
RegionFlags[RegionFlags["DenyAgeUnverified"] = 1073741824] = "DenyAgeUnverified";
})(RegionFlags = exports.RegionFlags || (exports.RegionFlags = {}));
//# sourceMappingURL=RegionFlags.js.map

1
dist/enums/RegionFlags.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"RegionFlags.js","sourceRoot":"","sources":["../../lib/enums/RegionFlags.ts"],"names":[],"mappings":";;AAAA,IAAY,WAkCX;AAlCD,WAAY,WAAW;IAEnB,6CAAQ,CAAA;IACR,2DAAoB,CAAA;IACpB,+DAAsB,CAAA;IACtB,6DAAqB,CAAA;IACrB,2EAA4B,CAAA;IAC5B,sDAAiB,CAAA;IACjB,oDAAgB,CAAA;IAChB,kEAAuB,CAAA;IACvB,qEAAwB,CAAA;IACxB,qDAAgB,CAAA;IAChB,yDAAkB,CAAA;IAClB,sEAAyB,CAAA;IACzB,oFAAgC,CAAA;IAChC,oEAAwB,CAAA;IACxB,8DAAqB,CAAA;IACrB,+DAAqB,CAAA;IACrB,2EAA2B,CAAA;IAC3B,uEAAyB,CAAA;IACzB,oEAAuB,CAAA;IACvB,8DAAoB,CAAA;IACpB,oDAAe,CAAA;IACf,iFAA6B,CAAA;IAC7B,6EAA2B,CAAA;IAC3B,+EAA4B,CAAA;IAC5B,qEAAuB,CAAA;IACvB,wEAAwB,CAAA;IACxB,wEAAwB,CAAA;IACxB,gFAA4B,CAAA;IAC5B,2FAAiC,CAAA;IACjC,iEAAoB,CAAA;IACpB,+EAA2B,CAAA;IAC3B,gFAA2B,CAAA;AAC/B,CAAC,EAlCW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAkCtB"}

3
dist/index.d.ts vendored
View File

@@ -39,4 +39,5 @@ import { ParcelInfoFlags } from './enums/ParcelInfoFlags';
import { ParcelInfoReplyEvent } from './events/ParcelInfoReplyEvent';
import { ScriptDialogEvent } from './events/ScriptDialogEvent';
import { EventQueueStateChangeEvent } from './events/EventQueueStateChangeEvent';
export { Bot, LoginParameters, AssetType, HTTPAssets, ClientEvents, BVH, ChatSourceType, BotOptionFlags, UUID, Vector3, AgentFlags, CompressedFlags, ControlFlags, DecodeFlags, InstantMessageEventFlags, InventoryItemFlags, LoginFlags, MessageFlags, ParcelInfoFlags, PacketFlags, RegionProtocolFlags, SoundFlags, TeleportFlags, ChatEvent, DisconnectEvent, FriendRequestEvent, FriendResponseEvent, GroupChatEvent, GroupChatSessionAgentListEvent, GroupChatSessionJoinEvent, GroupInviteEvent, InstantMessageEvent, InventoryOfferedEvent, LureEvent, MapInfoRangeReplyEvent, MapInfoReplyEvent, ParcelInfoReplyEvent, RegionInfoReplyEvent, TeleportEvent, ScriptDialogEvent, EventQueueStateChangeEvent };
import { RegionFlags } from './enums/RegionFlags';
export { Bot, LoginParameters, AssetType, HTTPAssets, ClientEvents, BVH, ChatSourceType, BotOptionFlags, UUID, Vector3, AgentFlags, CompressedFlags, ControlFlags, DecodeFlags, InstantMessageEventFlags, InventoryItemFlags, LoginFlags, MessageFlags, ParcelInfoFlags, PacketFlags, RegionProtocolFlags, SoundFlags, TeleportFlags, RegionFlags, ChatEvent, DisconnectEvent, FriendRequestEvent, FriendResponseEvent, GroupChatEvent, GroupChatSessionAgentListEvent, GroupChatSessionJoinEvent, GroupInviteEvent, InstantMessageEvent, InventoryOfferedEvent, LureEvent, MapInfoRangeReplyEvent, MapInfoReplyEvent, ParcelInfoReplyEvent, RegionInfoReplyEvent, TeleportEvent, ScriptDialogEvent, EventQueueStateChangeEvent };

2
dist/index.js vendored
View File

@@ -82,4 +82,6 @@ const ScriptDialogEvent_1 = require("./events/ScriptDialogEvent");
exports.ScriptDialogEvent = ScriptDialogEvent_1.ScriptDialogEvent;
const EventQueueStateChangeEvent_1 = require("./events/EventQueueStateChangeEvent");
exports.EventQueueStateChangeEvent = EventQueueStateChangeEvent_1.EventQueueStateChangeEvent;
const RegionFlags_1 = require("./enums/RegionFlags");
exports.RegionFlags = RegionFlags_1.RegionFlags;
//# sourceMappingURL=index.js.map

2
dist/index.js.map vendored
View File

@@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AA4CtB,cA5CI,SAAG,CA4CJ;AA3CP,+DAA0D;AA4CtD,0BA5CI,iCAAe,CA4CJ;AA3CnB,yDAAoD;AA8ChD,uBA9CI,2BAAY,CA8CJ;AA7ChB,uCAAkC;AA8C9B,cA9CI,SAAG,CA8CJ;AA5CP,iDAA4C;AAyCxC,oBAzCI,qBAAS,CAyCJ;AAxCb,mDAA8C;AAyC1C,qBAzCI,uBAAU,CAyCJ;AAxCd,+EAA0E;AAqDtE,mCArDI,mDAAwB,CAqDJ;AApD5B,sEAAiE;AAuE7D,8BAvEI,yCAAmB,CAuEJ;AAtEvB,2DAAsD;AAyClD,yBAzCI,+BAAc,CAyCJ;AAxClB,2DAAsD;AAyClD,yBAzCI,+BAAc,CAyCJ;AAxClB,yCAAoC;AAyChC,eAzCI,WAAI,CAyCJ;AAxCR,+CAA0C;AAyCtC,kBAzCI,iBAAO,CAyCJ;AAxCX,kDAA6C;AA0DzC,oBA1DI,qBAAS,CA0DJ;AAzDb,gEAA2D;AAgEvD,2BAhEI,mCAAgB,CAgEJ;AA/DpB,oEAA+D;AA0D3D,6BA1DI,uCAAkB,CA0DJ;AAzDtB,sEAAiE;AA0D7D,8BA1DI,yCAAmB,CA0DJ;AAzDvB,kDAA6C;AAgEzC,oBAhEI,qBAAS,CAgEJ;AA/Db,0DAAqD;AAoEjD,wBApEI,6BAAa,CAoEJ;AAnEjB,8DAAyD;AAqDrD,0BArDI,iCAAe,CAqDJ;AApDnB,4DAAuD;AAuDnD,yBAvDI,+BAAc,CAuDJ;AAtDlB,kFAA6E;AAwDzE,oCAxDI,qDAAyB,CAwDJ;AAvD7B,4FAAuF;AAsDnF,yCAtDI,+DAA8B,CAsDJ;AArDlC,wEAAmE;AA8D/D,+BA9DI,2CAAoB,CA8DJ;AA7DxB,kEAA6D;AA2DzD,4BA3DI,qCAAiB,CA2DJ;AA1DrB,4EAAuE;AAyDnE,iCAzDI,+CAAsB,CAyDJ;AAxD1B,0EAAqE;AAsDjE,gCAtDI,6CAAqB,CAsDJ;AArDzB,mDAA8C;AA6B1C,qBA7BI,uBAAU,CA6BJ;AA5Bd,uDAAkD;AA8B9C,uBA9BI,2BAAY,CA8BJ;AA7BhB,mEAA8D;AAgC1D,6BAhCI,uCAAkB,CAgCJ;AA/BtB,mDAA8C;AAgC1C,qBAhCI,uBAAU,CAgCJ;AA/Bd,uDAAkD;AAgC9C,uBAhCI,2BAAY,CAgCJ;AA/BhB,qDAAgD;AAiC5C,sBAjCI,yBAAW,CAiCJ;AAhCf,qEAAgE;AAiC5D,8BAjCI,yCAAmB,CAiCJ;AAhCvB,mDAA8C;AAiC1C,qBAjCI,uBAAU,CAiCJ;AAhCd,yDAAoD;AAiChD,wBAjCI,6BAAa,CAiCJ;AAhCjB,6DAAwD;AAqBpD,0BArBI,iCAAe,CAqBJ;AApBnB,qDAAgD;AAsB5C,sBAtBI,yBAAW,CAsBJ;AArBf,6DAAwD;AA0BpD,0BA1BI,iCAAe,CA0BJ;AAzBnB,wEAAmE;AA6C/D,+BA7CI,2CAAoB,CA6CJ;AA5CxB,kEAA6D;AA+CzD,4BA/CI,qCAAiB,CA+CJ;AA9CrB,oFAA+E;AA+C3E,qCA/CI,uDAA0B,CA+CJ"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AA6CtB,cA7CI,SAAG,CA6CJ;AA5CP,+DAA0D;AA6CtD,0BA7CI,iCAAe,CA6CJ;AA5CnB,yDAAoD;AA+ChD,uBA/CI,2BAAY,CA+CJ;AA9ChB,uCAAkC;AA+C9B,cA/CI,SAAG,CA+CJ;AA7CP,iDAA4C;AA0CxC,oBA1CI,qBAAS,CA0CJ;AAzCb,mDAA8C;AA0C1C,qBA1CI,uBAAU,CA0CJ;AAzCd,+EAA0E;AAsDtE,mCAtDI,mDAAwB,CAsDJ;AArD5B,sEAAiE;AAyE7D,8BAzEI,yCAAmB,CAyEJ;AAxEvB,2DAAsD;AA0ClD,yBA1CI,+BAAc,CA0CJ;AAzClB,2DAAsD;AA0ClD,yBA1CI,+BAAc,CA0CJ;AAzClB,yCAAoC;AA0ChC,eA1CI,WAAI,CA0CJ;AAzCR,+CAA0C;AA0CtC,kBA1CI,iBAAO,CA0CJ;AAzCX,kDAA6C;AA4DzC,oBA5DI,qBAAS,CA4DJ;AA3Db,gEAA2D;AAkEvD,2BAlEI,mCAAgB,CAkEJ;AAjEpB,oEAA+D;AA4D3D,6BA5DI,uCAAkB,CA4DJ;AA3DtB,sEAAiE;AA4D7D,8BA5DI,yCAAmB,CA4DJ;AA3DvB,kDAA6C;AAkEzC,oBAlEI,qBAAS,CAkEJ;AAjEb,0DAAqD;AAsEjD,wBAtEI,6BAAa,CAsEJ;AArEjB,8DAAyD;AAuDrD,0BAvDI,iCAAe,CAuDJ;AAtDnB,4DAAuD;AAyDnD,yBAzDI,+BAAc,CAyDJ;AAxDlB,kFAA6E;AA0DzE,oCA1DI,qDAAyB,CA0DJ;AAzD7B,4FAAuF;AAwDnF,yCAxDI,+DAA8B,CAwDJ;AAvDlC,wEAAmE;AAgE/D,+BAhEI,2CAAoB,CAgEJ;AA/DxB,kEAA6D;AA6DzD,4BA7DI,qCAAiB,CA6DJ;AA5DrB,4EAAuE;AA2DnE,iCA3DI,+CAAsB,CA2DJ;AA1D1B,0EAAqE;AAwDjE,gCAxDI,6CAAqB,CAwDJ;AAvDzB,mDAA8C;AA8B1C,qBA9BI,uBAAU,CA8BJ;AA7Bd,uDAAkD;AA+B9C,uBA/BI,2BAAY,CA+BJ;AA9BhB,mEAA8D;AAiC1D,6BAjCI,uCAAkB,CAiCJ;AAhCtB,mDAA8C;AAiC1C,qBAjCI,uBAAU,CAiCJ;AAhCd,uDAAkD;AAiC9C,uBAjCI,2BAAY,CAiCJ;AAhChB,qDAAgD;AAkC5C,sBAlCI,yBAAW,CAkCJ;AAjCf,qEAAgE;AAkC5D,8BAlCI,yCAAmB,CAkCJ;AAjCvB,mDAA8C;AAkC1C,qBAlCI,uBAAU,CAkCJ;AAjCd,yDAAoD;AAkChD,wBAlCI,6BAAa,CAkCJ;AAjCjB,6DAAwD;AAsBpD,0BAtBI,iCAAe,CAsBJ;AArBnB,qDAAgD;AAuB5C,sBAvBI,yBAAW,CAuBJ;AAtBf,6DAAwD;AA2BpD,0BA3BI,iCAAe,CA2BJ;AA1BnB,wEAAmE;AA+C/D,+BA/CI,2CAAoB,CA+CJ;AA9CxB,kEAA6D;AAiDzD,4BAjDI,qCAAiB,CAiDJ;AAhDrB,oFAA+E;AAiD3E,qCAjDI,uDAA0B,CAiDJ;AAhD9B,qDAAgD;AA4B5C,sBA5BI,yBAAW,CA4BJ"}

View File

@@ -2,5 +2,5 @@
"firstName": "Username",
"lastName": "Resident",
"password": "YourPassword",
"start": "home" //home, last, or login uri
"start": "last" //first, last, or login uri like uri:<existing region name>&<x>&<y>&<z>
}

View File

@@ -12,7 +12,7 @@ const uuid = require('uuid');
loginParameters.firstName = parameters.firstName;
loginParameters.lastName = parameters.lastName;
loginParameters.password = parameters.password;
loginParameters.start = "last";
loginParameters.start = parameters.start;
//const options = nmv.BotOptionFlags.None;
@@ -37,7 +37,10 @@ bot.clientEvents.onLure.subscribe(async (lureEvent) =>
if (lureEvent.from.toString() === master)
{
console.log('Accepting teleport lure to ' + regionInfo.block.name + ' (' + regionInfo.avatars.length + ' avatar' + ((regionInfo.avatars.length === 1)?'':'s') + ' present) from ' + lureEvent.fromName + ' with message: ' + lureEvent.lureMessage);
bot.clientCommands.teleport.acceptTeleport(lureEvent).then(() => {});
bot.clientCommands.teleport.acceptTeleport(lureEvent).then(() => {}).catch((err) => {
console.error('Teleport error:');
console.error(err);
});
}
else
{
@@ -261,8 +264,8 @@ async function connect()
await bot.waitForEventQueue();
try
{
await bot.clientCommands.teleport.teleportTo('Izanagi', new nmv.Vector3([128, 128, 20]), new nmv.Vector3([ 0, 1.0, 0]));
console.log("Teleport completed");
//await bot.clientCommands.teleport.teleportTo('Izanagi', new nmv.Vector3([128, 128, 20]), new nmv.Vector3([ 0, 1.0, 0]));
//console.log("Teleport completed");
}
catch(error)
{

View File

@@ -30,6 +30,10 @@ import {FilterResponse} from './enums/FilterResponse';
import {LogoutReplyMessage} from './classes/messages/LogoutReply';
import {EventQueueStateChangeEvent} from './events/EventQueueStateChangeEvent';
import {UUID} from './classes/UUID';
import {Vector3} from './classes/Vector3';
import {RegionHandshakeMessage} from './classes/messages/RegionHandshake';
import {AgentMovementCompleteMessage} from './classes/messages/AgentMovementComplete';
import Long = require('long');
export class Bot
{
@@ -45,6 +49,9 @@ export class Bot
public clientEvents: ClientEvents;
public clientCommands: ClientCommands;
private eventQueueWaits: any = {};
private stay = false;
private stayRegion = '';
private stayPosition = new Vector3();
@@ -70,6 +77,16 @@ export class Bot
});
}
stayPut(stay: boolean, regionName?: string, position?: Vector3)
{
this.stay = stay;
if (regionName !== undefined && position !== undefined)
{
this.stayRegion = regionName;
this.stayPosition = position;
}
}
async login()
{
const loginHandler = new LoginHandler(this.clientEvents, this.options);
@@ -80,8 +97,9 @@ export class Bot
return response;
}
async changeRegion(region: Region)
async changeRegion(region: Region, requested: boolean)
{
this.closeCircuit();
this.currentRegion = region;
this.clientCommands = new ClientCommands(this.currentRegion, this.agent, this);
if (this.ping !== null)
@@ -90,7 +108,7 @@ export class Bot
this.ping = null;
}
await this.connectToSim();
await this.connectToSim(requested);
}
waitForEventQueue(timeout: number = 1000): Promise<void>
@@ -124,7 +142,6 @@ export class Bot
private closeCircuit()
{
this.agent.shutdown();
this.currentRegion.shutdown();
if (this.circuitSubscription !== null)
{
@@ -132,7 +149,8 @@ export class Bot
this.circuitSubscription = null;
}
delete this.currentRegion;
delete this.agent;
this.clientCommands.shutdown();
delete this.clientCommands;
if (this.ping !== null)
{
@@ -145,6 +163,8 @@ export class Bot
private kicked(message: string)
{
this.closeCircuit();
this.agent.shutdown();
delete this.agent;
this.disconnected(false, message);
}
@@ -169,13 +189,17 @@ export class Bot
};
circuit.sendMessage(msg, PacketFlags.Reliable);
await circuit.waitForMessage<LogoutReplyMessage>(Message.LogoutReply, 5000);
this.stayRegion = '';
this.stayPosition = new Vector3();
this.closeCircuit();
this.agent.shutdown();
delete this.agent;
this.disconnected(true, 'Logout completed');
}
async connectToSim()
async connectToSim(requested: boolean)
{
this.agent.setCurrentRegion(this.currentRegion);
const circuit = this.currentRegion.circuit;
circuit.init();
const msg: UseCircuitCodeMessage = new UseCircuitCodeMessage();
@@ -196,7 +220,25 @@ export class Bot
};
circuit.sendMessage(agentMovement, PacketFlags.Reliable);
await circuit.waitForMessage(Message.RegionHandshake, 10000);
let agentPosition: Vector3 | null = null;
let regionName: string | null = null;
circuit.waitForMessage<AgentMovementCompleteMessage>(Message.AgentMovementComplete, 10000).then((agentMovementMsg: AgentMovementCompleteMessage) =>
{
agentPosition = agentMovementMsg.Data.Position;
if (regionName !== null)
{
if (this.stayRegion === '' || requested)
{
this.stayPut(this.stay, regionName, agentPosition);
}
}
}).catch(() =>
{
console.error('Timed out waiting for AgentMovementComplete')
});
const handshakeMessage = await circuit.waitForMessage<RegionHandshakeMessage>(Message.RegionHandshake, 10000);
const handshakeReply: RegionHandshakeReplyMessage = new RegionHandshakeReplyMessage();
handshakeReply.AgentData = {
@@ -208,6 +250,22 @@ export class Bot
};
await circuit.waitForAck(circuit.sendMessage(handshakeReply, PacketFlags.Reliable), 10000);
this.currentRegion.handshake(handshakeMessage).then(() =>
{
regionName = this.currentRegion.regionName;
if (agentPosition !== null)
{
if (this.stayRegion === '' || requested)
{
this.stayPut(this.stay, regionName, agentPosition);
}
}
}).catch((error) =>
{
console.error('Timed out getting handshake');
console.error(error);
});
if (this.clientCommands !== null)
{
this.clientCommands.network.setBandwidth(1536000);
@@ -257,7 +315,13 @@ export class Bot
}).bind(this, {
pingID: this.pingNumber,
timeSent: new Date().getTime()
}));
})).then(() =>
{
// No action needed
}).catch(() =>
{
console.error('Timeout waiting for ping from the simulator - possible disconnection')
});
if ((new Date().getTime() - this.lastSuccessfulPing) > 60000)

View File

@@ -79,6 +79,7 @@ export class Agent
serialNumber: number
};
agentUpdateTimer: number | null = null;
estateManager = false;
private clientEvents: ClientEvents;
constructor(clientEvents: ClientEvents)
@@ -109,6 +110,11 @@ export class Agent
});
}
setIsEstateManager(is: boolean): void
{
this.estateManager = is;
}
getSessionAgentCount(uuid: UUID): number
{
const str = uuid.toString();

View File

@@ -17,6 +17,7 @@ export class Caps
private capabilities: { [key: string]: string } = {};
private clientEvents: ClientEvents;
private agent: Agent;
private active = false;
eventQueueClient: EventQueueClient | null = null;
constructor(agent: Agent, region: Region, seedURL: string, clientEvents: ClientEvents)
@@ -113,7 +114,7 @@ export class Caps
req.push('ViewerMetrics');
req.push('ViewerStartAuction');
req.push('ViewerStats');
this.active = true;
this.request(seedURL, LLSD.LLSD.formatXML(req), 'application/llsd+xml').then((body: string) =>
{
this.capabilities = LLSD.LLSD.parseXML(body);
@@ -211,6 +212,11 @@ export class Caps
{
return new Promise<string>((resolve, reject) =>
{
if (!this.active)
{
reject(new Error('Requesting getCapability to an inactive Caps instance'));
return;
}
this.waitForSeedCapability().then(() =>
{
if (this.capabilities[capability])
@@ -279,5 +285,6 @@ export class Caps
{
this.eventQueueClient.shutdown();
}
this.active = false;
}
}

View File

@@ -37,6 +37,7 @@ export class Circuit
receivedPackets: {
[key: number]: number
} = {};
active = false;
private clientEvents: ClientEvents;
private onPacketReceived: Subject<Packet>;
@@ -65,6 +66,10 @@ export class Circuit
sendMessage(message: MessageBase, flags: PacketFlags): number
{
if (!this.active)
{
throw new Error('Attempting to send a message on a closed circuit');
}
const packet: Packet = new Packet();
packet.message = message;
packet.sequenceNumber = this.sequenceNumber++;
@@ -75,6 +80,11 @@ export class Circuit
resend(sequenceNumber: number)
{
if (!this.active)
{
console.log('Resend triggered, but circuit is not active!');
return;
}
if (this.awaitingAck[sequenceNumber])
{
const toResend: Packet = this.awaitingAck[sequenceNumber].packet;
@@ -147,6 +157,7 @@ export class Circuit
{
});
this.active = true;
}
shutdown()
@@ -169,6 +180,7 @@ export class Circuit
this.onPacketReceived.complete();
this.onAckReceived.complete();
}
this.active = false;
}
waitForMessage<T extends MessageBase>(id: Message, timeout: number, filter?: (message: T) => FilterResponse): Promise<T>

View File

@@ -38,4 +38,17 @@ export class ClientCommands
this.group = new GroupCommands(region, agent, bot);
this.inventory = new InventoryCommands(region, agent, bot);
}
shutdown()
{
this.network.shutdown();
this.asset.shutdown();
this.teleport.shutdown();
this.region.shutdown();
this.parcel.shutdown();
this.grid.shutdown();
this.comms.shutdown();
this.agent.shutdown();
this.group.shutdown();
this.inventory.shutdown();
}
}

View File

@@ -36,14 +36,22 @@ export class EventQueueClient
}
shutdown()
{
const state = new EventQueueStateChangeEvent();
state.active = false;
this.clientEvents.onEventQueueStateChange.next(state);
// We must ACK any outstanding events
this.done = true;
if (this.currentRequest !== null)
{
this.currentRequest.abort();
}
this.done = true;
const req = {
'ack': this.ack,
'done': true
};
this.capsRequestXML('EventQueueGet', req).then((data) =>
{
const state = new EventQueueStateChangeEvent();
state.active = false;
this.clientEvents.onEventQueueStateChange.next(state);
});
}
Get()
{
@@ -54,340 +62,6 @@ export class EventQueueClient
const startTime = new Date().getTime();
this.capsRequestXML('EventQueueGet', req).then((data) =>
{
if (data['events'])
{
data['events'].forEach((event: any) =>
{
try
{
if (event['message'])
{
// noinspection TsLint
switch (event['message'])
{
case 'EnableSimulator':
/*
{
"body": {
"SimulatorInfo": [
{
"Handle": "AALoAAAECwA=",
"IP": "2FIqRA==",
"Port": 13029
}
]
},
"message": "EnableSimulator"
}
*/
break;
case 'ParcelProperties':
/*
{
"body": {
"AgeVerificationBlock": [
{
"RegionDenyAgeUnverified": true
}
],
"MediaData": [
{
"MediaDesc": "",
"MediaHeight": 0,
"MediaLoop": 0,
"MediaType": "text/html",
"MediaWidth": 0,
"ObscureMedia": 0,
"ObscureMusic": 0
}
],
"ParcelData": [
{
"AABBMax": [
256,
256,
50
],
"AABBMin": [
0,
0,
0
],
"AnyAVSounds": true,
"Area": 65536,
"AuctionID": "AAAAAA==",
"AuthBuyerID": "00000000-0000-0000-0000-000000000000",
"Bitmap": "/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8=",
"Category": 0,
"ClaimDate": 1333505995,
"ClaimPrice": 0,
"Desc": "adoption parent furry parent teen twin cub neko pets adult elf vamp toddleedoo baby child panel brother sister numbers meshmerized gacha adoptions adopt family mesh skin shape camp ngi youthspot foster kids mall zoo train kid primbay\ndupli
city onlinker",
"GroupAVSounds": true,
"GroupID": "f2b75b49-8ebc-2a9c-f345-aa2f91adc908",
"GroupPrims": 18677,
"IsGroupOwned": true,
"LandingType": 2,
"LocalID": 15,
"MaxPrims": 30000,
"MediaAutoScale": 1,
"MediaID": "6bd35c06-2b24-a83e-03f6-f547c65c8556",
"MediaURL": "",
"MusicURL": "http://142.4.209.63:8071",
"Name": "Next Gen Inc. Adoption Agency on the :::: KiD GRiD :::",
"OtherCleanTime": 0,
"OtherCount": 4096,
"OtherPrims": 312,
"OwnerID": "f2b75b49-8ebc-2a9c-f345-aa2f91adc908",
"OwnerPrims": 3,
"ParcelFlags": "NiAUSw==",
"ParcelPrimBonus": 1,
"PassHours": 10,
"PassPrice": 10,
"PublicCount": 0,
"RegionDenyAnonymous": true,
"RegionDenyIdentified": true,
"RegionDenyTransacted": true,
"RegionPushOverride": true,
"RentPrice": 0,
"RequestResult": 0,
"SalePrice": 1,
"SeeAVs": true,
"SelectedPrims": 1,
"SelfCount": 0,
"SequenceID": 0,
"SimWideMaxPrims": 30000,
"SimWideTotalPrims": 18993,
"SnapSelection": true,
"SnapshotID": "09c4101a-9406-2501-b9b7-dbb60260fd7a",
"Status": 0,
"TotalPrims": 18993,
"UserLocation": [
131.48399353027344,
171.41600036621094,
21.544700622558594
],
"UserLookAt": [
0.0325143001973629,
-0.9994710087776184,
0
]
}
],
"RegionAllowAccessBlock": [
{
"RegionAllowAccessOverride": true
}
]
},
"message": "ParcelProperties"
}
*/
break;
case 'AgentGroupDataUpdate':
/*
{
"body": {
"AgentData": [
{
"AgentID": "49cc9041-5c53-4c1c-8490-e6bb84cdbacd"
}
],
"GroupData": [
{
"AcceptNotices": true,
"Contribution": 0,
"GroupID": "06459c46-069f-4de1-c297-c966bd55ab91",
"GroupInsigniaID": "8dacb5c9-80bc-aae4-6a12-d792b6eb7dc4",
"GroupName": "Jez Ember Estates",
"GroupPowers": "AAAgAAQAAAA="
},
{
"AcceptNotices": true,
"Contribution": 0,
"GroupID": "539b5be0-bb18-d0ef-6c07-3326e0130aaf",
"GroupInsigniaID": "7d7d0b4a-bf5b-dc51-3869-5e0eaa6ad41d",
"GroupName": "**BOY BEARS MALL**",
"GroupPowers": "AAAIABgBAAA="
}
],
"NewGroupData": [
{
"ListInProfile": true
},
{
"ListInProfile": true
}
]
},
"message": "AgentGroupDataUpdate"
}
*/
break;
case 'AgentStateUpdate':
/*
{
"body": {
"can_modify_navmesh": true,
"has_modified_navmesh": true,
"preferences": {
"access_prefs": {
"max": "PG"
},
"default_object_perm_masks": {
"Everyone": 0,
"Group": 0,
"NextOwner": 532480
},
"god_level": 0,
"hover_height": 0,
"language": "",
"language_is_public": true
}
},
"message": "AgentStateUpdate"
}
*/
break;
case 'TeleportFailed':
{
const tpEvent = new TeleportEvent();
tpEvent.message = event['body']['Info'][0]['Reason'];
tpEvent.eventType = TeleportEventType.TeleportFailed;
tpEvent.simIP = '';
tpEvent.simPort = 0;
tpEvent.seedCapability = '';
this.clientEvents.onTeleportEvent.next(tpEvent);
break;
}
case "ChatterBoxSessionStartReply":
{
if (event['body'])
{
const gcsje = new GroupChatSessionJoinEvent();
gcsje.sessionID = new UUID(event['body']['session_id'].toString());
gcsje.success = event['body']['success'];
if (gcsje.success)
{
this.agent.addChatSession(gcsje.sessionID);
}
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
}
break;
}
case 'ChatterBoxInvitation':
{
if (event['body'] && event['body']['instantmessage'] && event['body']['instantmessage']['message_params'] && event['body']['instantmessage']['message_params']['id'])
{
const messageParams = event['body']['instantmessage']['message_params'];
const imSessionID = messageParams['id'];
const groupChatEvent = new GroupChatEvent();
groupChatEvent.from = new UUID(messageParams['from_id'].toString());
groupChatEvent.fromName = messageParams['from_name'];
groupChatEvent.groupID = new UUID(messageParams['id'].toString());
groupChatEvent.message = messageParams['message'];
const requestedFolders = {
'method': 'accept invitation',
'session-id': imSessionID
};
this.caps.capsRequestXML('ChatSessionRequest', requestedFolders).then((ignore: any) =>
{
this.agent.addChatSession(groupChatEvent.groupID);
const gcsje = new GroupChatSessionJoinEvent();
gcsje.sessionID = groupChatEvent.groupID;
gcsje.success = true;
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
this.clientEvents.onGroupChat.next(groupChatEvent);
}).catch((err) =>
{
console.error(err);
});
}
break;
}
case 'ChatterBoxSessionAgentListUpdates':
{
if (event['body'])
{
if (event['body']['agent_updates'])
{
Object.keys(event['body']['agent_updates']).forEach((agentUpdate) =>
{
const updObj = event['body']['agent_updates'][agentUpdate];
const gcsale = new GroupChatSessionAgentListEvent();
gcsale.agentID = new UUID(agentUpdate);
gcsale.groupID = new UUID(event['body']['session_id'].toString());
gcsale.canVoiceChat = false;
gcsale.isModerator = false;
gcsale.entered = (updObj['transition'] === 'ENTER');
if (updObj['can_voice_chat'] === true)
{
gcsale.canVoiceChat = true;
}
if (updObj['is_moderator'] === true)
{
gcsale.isModerator = true;
}
this.clientEvents.onGroupChatAgentListUpdate.next(gcsale);
});
}
}
break;
}
case 'TeleportFinish':
{
const info = event['body']['Info'][0];
if (info['LocationID'])
{
info['LocationID'] = Buffer.from(info['LocationID'].toArray()).readUInt32LE(0);
const regionHandleBuf = Buffer.from(info['RegionHandle'].toArray());
info['RegionHandle'] = new Long(regionHandleBuf.readUInt32LE(0), regionHandleBuf.readUInt32LE(4), true);
info['SimIP'] = new IPAddress(Buffer.from(info['SimIP'].toArray()), 0).toString();
info['TeleportFlags'] = Buffer.from(info['TeleportFlags'].toArray()).readUInt32LE(0);
const tpEvent = new TeleportEvent();
tpEvent.message = '';
tpEvent.eventType = TeleportEventType.TeleportCompleted;
tpEvent.simIP = info['SimIP'];
tpEvent.simPort = info['SimPort'];
tpEvent.seedCapability = info['SeedCapability'];
this.clientEvents.onTeleportEvent.next(tpEvent);
}
break;
}
default:
console.log('Unhandled event:');
console.log(JSON.stringify(event, null, 4));
}
}
}
catch (erro)
{
console.error('Error handling cap');
console.error(erro);
}
});
}
if (data['id'])
{
this.ack = data['id'];
@@ -396,6 +70,347 @@ export class EventQueueClient
{
this.ack = undefined;
}
try
{
if (data['events'])
{
data['events'].forEach((event: any) =>
{
try
{
if (event['message'])
{
// noinspection TsLint
switch (event['message'])
{
case 'EnableSimulator':
/*
{
"body": {
"SimulatorInfo": [
{
"Handle": "AALoAAAECwA=",
"IP": "2FIqRA==",
"Port": 13029
}
]
},
"message": "EnableSimulator"
}
*/
break;
case 'ParcelProperties':
/*
{
"body": {
"AgeVerificationBlock": [
{
"RegionDenyAgeUnverified": true
}
],
"MediaData": [
{
"MediaDesc": "",
"MediaHeight": 0,
"MediaLoop": 0,
"MediaType": "text/html",
"MediaWidth": 0,
"ObscureMedia": 0,
"ObscureMusic": 0
}
],
"ParcelData": [
{
"AABBMax": [
256,
256,
50
],
"AABBMin": [
0,
0,
0
],
"AnyAVSounds": true,
"Area": 65536,
"AuctionID": "AAAAAA==",
"AuthBuyerID": "00000000-0000-0000-0000-000000000000",
"Bitmap": "/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8=",
"Category": 0,
"ClaimDate": 1333505995,
"ClaimPrice": 0,
"Desc": "adoption parent furry parent teen twin cub neko pets adult elf vamp toddleedoo baby child panel brother sister numbers meshmerized gacha adoptions adopt family mesh skin shape camp ngi youthspot foster kids mall zoo train kid primbay\ndupli
city onlinker",
"GroupAVSounds": true,
"GroupID": "f2b75b49-8ebc-2a9c-f345-aa2f91adc908",
"GroupPrims": 18677,
"IsGroupOwned": true,
"LandingType": 2,
"LocalID": 15,
"MaxPrims": 30000,
"MediaAutoScale": 1,
"MediaID": "6bd35c06-2b24-a83e-03f6-f547c65c8556",
"MediaURL": "",
"MusicURL": "http://142.4.209.63:8071",
"Name": "Next Gen Inc. Adoption Agency on the :::: KiD GRiD :::",
"OtherCleanTime": 0,
"OtherCount": 4096,
"OtherPrims": 312,
"OwnerID": "f2b75b49-8ebc-2a9c-f345-aa2f91adc908",
"OwnerPrims": 3,
"ParcelFlags": "NiAUSw==",
"ParcelPrimBonus": 1,
"PassHours": 10,
"PassPrice": 10,
"PublicCount": 0,
"RegionDenyAnonymous": true,
"RegionDenyIdentified": true,
"RegionDenyTransacted": true,
"RegionPushOverride": true,
"RentPrice": 0,
"RequestResult": 0,
"SalePrice": 1,
"SeeAVs": true,
"SelectedPrims": 1,
"SelfCount": 0,
"SequenceID": 0,
"SimWideMaxPrims": 30000,
"SimWideTotalPrims": 18993,
"SnapSelection": true,
"SnapshotID": "09c4101a-9406-2501-b9b7-dbb60260fd7a",
"Status": 0,
"TotalPrims": 18993,
"UserLocation": [
131.48399353027344,
171.41600036621094,
21.544700622558594
],
"UserLookAt": [
0.0325143001973629,
-0.9994710087776184,
0
]
}
],
"RegionAllowAccessBlock": [
{
"RegionAllowAccessOverride": true
}
]
},
"message": "ParcelProperties"
}
*/
break;
case 'AgentGroupDataUpdate':
/*
{
"body": {
"AgentData": [
{
"AgentID": "49cc9041-5c53-4c1c-8490-e6bb84cdbacd"
}
],
"GroupData": [
{
"AcceptNotices": true,
"Contribution": 0,
"GroupID": "06459c46-069f-4de1-c297-c966bd55ab91",
"GroupInsigniaID": "8dacb5c9-80bc-aae4-6a12-d792b6eb7dc4",
"GroupName": "Jez Ember Estates",
"GroupPowers": "AAAgAAQAAAA="
},
{
"AcceptNotices": true,
"Contribution": 0,
"GroupID": "539b5be0-bb18-d0ef-6c07-3326e0130aaf",
"GroupInsigniaID": "7d7d0b4a-bf5b-dc51-3869-5e0eaa6ad41d",
"GroupName": "**BOY BEARS MALL**",
"GroupPowers": "AAAIABgBAAA="
}
],
"NewGroupData": [
{
"ListInProfile": true
},
{
"ListInProfile": true
}
]
},
"message": "AgentGroupDataUpdate"
}
*/
break;
case 'AgentStateUpdate':
/*
{
"body": {
"can_modify_navmesh": true,
"has_modified_navmesh": true,
"preferences": {
"access_prefs": {
"max": "PG"
},
"default_object_perm_masks": {
"Everyone": 0,
"Group": 0,
"NextOwner": 532480
},
"god_level": 0,
"hover_height": 0,
"language": "",
"language_is_public": true
}
},
"message": "AgentStateUpdate"
}
*/
break;
case 'TeleportFailed':
{
const tpEvent = new TeleportEvent();
tpEvent.message = event['body']['Info'][0]['Reason'];
tpEvent.eventType = TeleportEventType.TeleportFailed;
tpEvent.simIP = '';
tpEvent.simPort = 0;
tpEvent.seedCapability = '';
this.clientEvents.onTeleportEvent.next(tpEvent);
break;
}
case "ChatterBoxSessionStartReply":
{
if (event['body'])
{
const gcsje = new GroupChatSessionJoinEvent();
gcsje.sessionID = new UUID(event['body']['session_id'].toString());
gcsje.success = event['body']['success'];
if (gcsje.success)
{
this.agent.addChatSession(gcsje.sessionID);
}
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
}
break;
}
case 'ChatterBoxInvitation':
{
if (event['body'] && event['body']['instantmessage'] && event['body']['instantmessage']['message_params'] && event['body']['instantmessage']['message_params']['id'])
{
const messageParams = event['body']['instantmessage']['message_params'];
const imSessionID = messageParams['id'];
const groupChatEvent = new GroupChatEvent();
groupChatEvent.from = new UUID(messageParams['from_id'].toString());
groupChatEvent.fromName = messageParams['from_name'];
groupChatEvent.groupID = new UUID(messageParams['id'].toString());
groupChatEvent.message = messageParams['message'];
const requestedFolders = {
'method': 'accept invitation',
'session-id': imSessionID
};
this.caps.capsRequestXML('ChatSessionRequest', requestedFolders).then((ignore: any) =>
{
this.agent.addChatSession(groupChatEvent.groupID);
const gcsje = new GroupChatSessionJoinEvent();
gcsje.sessionID = groupChatEvent.groupID;
gcsje.success = true;
this.clientEvents.onGroupChatSessionJoin.next(gcsje);
this.clientEvents.onGroupChat.next(groupChatEvent);
}).catch((err) =>
{
console.error(err);
});
}
break;
}
case 'ChatterBoxSessionAgentListUpdates':
{
if (event['body'])
{
if (event['body']['agent_updates'])
{
Object.keys(event['body']['agent_updates']).forEach((agentUpdate) =>
{
const updObj = event['body']['agent_updates'][agentUpdate];
const gcsale = new GroupChatSessionAgentListEvent();
gcsale.agentID = new UUID(agentUpdate);
gcsale.groupID = new UUID(event['body']['session_id'].toString());
gcsale.canVoiceChat = false;
gcsale.isModerator = false;
gcsale.entered = (updObj['transition'] === 'ENTER');
if (updObj['can_voice_chat'] === true)
{
gcsale.canVoiceChat = true;
}
if (updObj['is_moderator'] === true)
{
gcsale.isModerator = true;
}
this.clientEvents.onGroupChatAgentListUpdate.next(gcsale);
});
}
}
break;
}
case 'TeleportFinish':
{
const info = event['body']['Info'][0];
if (info['LocationID'])
{
info['LocationID'] = Buffer.from(info['LocationID'].toArray()).readUInt32LE(0);
const regionHandleBuf = Buffer.from(info['RegionHandle'].toArray());
info['RegionHandle'] = new Long(regionHandleBuf.readUInt32LE(0), regionHandleBuf.readUInt32LE(4), true);
info['SimIP'] = new IPAddress(Buffer.from(info['SimIP'].toArray()), 0).toString();
info['TeleportFlags'] = Buffer.from(info['TeleportFlags'].toArray()).readUInt32LE(0);
const tpEvent = new TeleportEvent();
tpEvent.message = '';
tpEvent.eventType = TeleportEventType.TeleportCompleted;
tpEvent.simIP = info['SimIP'];
tpEvent.simPort = info['SimPort'];
tpEvent.seedCapability = info['SeedCapability'];
this.clientEvents.onTeleportEvent.next(tpEvent);
}
break;
}
default:
console.log('Unhandled event:');
console.log(JSON.stringify(event, null, 4));
}
}
}
catch (erro)
{
console.error('Error handling cap');
console.error(erro);
}
});
}
}
catch (error)
{
console.error(error);
}
if (!this.done)
{
this.Get();
@@ -413,16 +428,19 @@ export class EventQueueClient
}
else
{
console.error('Event queue aborted after ' + time + 'ms. Reconnecting in 5 seconds');
// Wait 5 seconds before retrying
setTimeout(() =>
if (!this.done)
{
if (!this.done)
console.error('Event queue aborted after ' + time + 'ms. Reconnecting in 5 seconds');
// Wait 5 seconds before retrying
setTimeout(() =>
{
this.Get();
}
}, 5000);
if (!this.done)
{
this.Get();
}
}, 5000);
}
}
});
}
@@ -474,7 +492,7 @@ export class EventQueueClient
else
{
// Retry caps request three times before giving up
if (attempt < 3)
if (attempt < 3 && capability !== 'EventQueueGet')
{
return this.capsRequestXML(capability, data, ++attempt);
}

View File

@@ -6,12 +6,71 @@ import {ClientEvents} from './ClientEvents';
import {IObjectStore} from './interfaces/IObjectStore';
import {ObjectStoreFull} from './ObjectStoreFull';
import {ObjectStoreLite} from './ObjectStoreLite';
import {BotOptionFlags} from '..';
import {BotOptionFlags, PacketFlags, UUID} from '..';
import {RequestRegionInfoMessage} from './messages/RequestRegionInfo';
import {RegionInfoMessage} from './messages/RegionInfo';
import {Message} from '../enums/Message';
import {Utils} from './Utils';
import {RegionFlags} from '../enums/RegionFlags';
import {RegionHandshakeMessage} from './messages/RegionHandshake';
import {MapNameRequestMessage} from './messages/MapNameRequest';
import {GridLayerType} from '../enums/GridLayerType';
import {MapBlockReplyMessage} from './messages/MapBlockReply';
import {FilterResponse} from '../enums/FilterResponse';
import * as Long from 'long';
export class Region
{
regionName: string;
regionOwner: UUID;
regionID: UUID;
regionHandle: Long;
xCoordinate: number;
yCoordinate: number;
estateID: number;
parentEstateID: number;
regionFlags: RegionFlags;
mapImage: UUID;
simAccess: number;
maxAgents: number;
billableFactor: number;
objectBonusFactor: number;
waterHeight: number;
terrainRaiseLimit: number;
terrainLowerLimit: number;
pricePerMeter: number;
redirectGridX: number;
redirectGridY: number;
useEstateSun: boolean;
sunHour: number;
productSKU: string;
productName: string;
maxAgents32: number;
hardMaxAgents: number;
hardMaxObjects: number;
cacheID: UUID;
cpuClassID: number;
cpuRatio: number;
coloName: string;
terrainBase0: UUID;
terrainBase1: UUID;
terrainBase2: UUID;
terrainBase3: UUID;
terrainDetail0: UUID;
terrainDetail1: UUID;
terrainDetail2: UUID;
terrainDetail3: UUID;
terrainStartHeight00: number;
terrainStartHeight01: number;
terrainStartHeight10: number;
terrainStartHeight11: number;
terrainHeightRange00: number;
terrainHeightRange01: number;
terrainHeightRange10: number;
terrainHeightRange11: number;
circuit: Circuit;
objects: IObjectStore;
caps: Caps;
@@ -40,6 +99,93 @@ export class Region
{
this.caps = new Caps(this.agent, this, seedURL, this.clientEvents);
}
async handshake(handshake: RegionHandshakeMessage)
{
this.regionName = Utils.BufferToStringSimple(handshake.RegionInfo.SimName);
this.simAccess = handshake.RegionInfo.SimAccess;
this.regionFlags = handshake.RegionInfo.RegionFlags;
this.regionOwner = handshake.RegionInfo.SimOwner;
this.agent.setIsEstateManager(handshake.RegionInfo.IsEstateManager);
this.waterHeight = handshake.RegionInfo.WaterHeight;
this.billableFactor = handshake.RegionInfo.BillableFactor;
this.cacheID = handshake.RegionInfo.CacheID;
this.terrainBase0 = handshake.RegionInfo.TerrainBase0;
this.terrainBase1 = handshake.RegionInfo.TerrainBase1;
this.terrainBase2 = handshake.RegionInfo.TerrainBase2;
this.terrainBase3 = handshake.RegionInfo.TerrainBase3;
this.terrainDetail0 = handshake.RegionInfo.TerrainDetail0;
this.terrainDetail1 = handshake.RegionInfo.TerrainDetail1;
this.terrainDetail2 = handshake.RegionInfo.TerrainDetail2;
this.terrainDetail3 = handshake.RegionInfo.TerrainDetail3;
this.terrainStartHeight00 = handshake.RegionInfo.TerrainStartHeight00;
this.terrainStartHeight01 = handshake.RegionInfo.TerrainStartHeight01;
this.terrainStartHeight10 = handshake.RegionInfo.TerrainStartHeight10;
this.terrainStartHeight11 = handshake.RegionInfo.TerrainStartHeight11;
this.terrainHeightRange00 = handshake.RegionInfo.TerrainHeightRange00;
this.terrainHeightRange01 = handshake.RegionInfo.TerrainHeightRange01;
this.terrainHeightRange10 = handshake.RegionInfo.TerrainHeightRange10;
this.terrainHeightRange11 = handshake.RegionInfo.TerrainHeightRange11;
this.regionID = handshake.RegionInfo2.RegionID;
this.cpuClassID = handshake.RegionInfo3.CPUClassID;
this.cpuRatio = handshake.RegionInfo3.CPURatio;
this.coloName = Utils.BufferToStringSimple(handshake.RegionInfo3.ColoName);
this.productSKU = Utils.BufferToStringSimple(handshake.RegionInfo3.ProductSKU);
this.productName = Utils.BufferToStringSimple(handshake.RegionInfo3.ProductName);
const request: RequestRegionInfoMessage = new RequestRegionInfoMessage();
request.AgentData = {
AgentID: this.agent.agentID,
SessionID: this.circuit.sessionID
};
this.circuit.sendMessage(request, PacketFlags.Reliable);
const regionInfo: RegionInfoMessage = await this.circuit.waitForMessage<RegionInfoMessage>(Message.RegionInfo, 10000);
this.estateID = regionInfo.RegionInfo.EstateID;
this.parentEstateID = regionInfo.RegionInfo.ParentEstateID;
this.maxAgents = regionInfo.RegionInfo.MaxAgents;
this.objectBonusFactor = regionInfo.RegionInfo.ObjectBonusFactor;
this.terrainRaiseLimit = regionInfo.RegionInfo.TerrainRaiseLimit;
this.terrainLowerLimit = regionInfo.RegionInfo.TerrainLowerLimit;
this.pricePerMeter = regionInfo.RegionInfo.PricePerMeter;
this.redirectGridX = regionInfo.RegionInfo.RedirectGridX;
this.redirectGridY = regionInfo.RegionInfo.RedirectGridY;
this.useEstateSun = regionInfo.RegionInfo.UseEstateSun;
this.sunHour = regionInfo.RegionInfo.SunHour;
this.maxAgents32 = regionInfo.RegionInfo2.MaxAgents32;
this.hardMaxAgents = regionInfo.RegionInfo2.HardMaxAgents;
this.hardMaxObjects = regionInfo.RegionInfo2.HardMaxObjects;
const msg: MapNameRequestMessage = new MapNameRequestMessage();
msg.AgentData = {
AgentID: this.agent.agentID,
SessionID: this.circuit.sessionID,
Flags: GridLayerType.Objects,
EstateID: 0,
Godlike: false
};
msg.NameData = {
Name: handshake.RegionInfo.SimName
};
this.circuit.sendMessage(msg, PacketFlags.Reliable);
const reply: MapBlockReplyMessage = await this.circuit.waitForMessage<MapBlockReplyMessage>(Message.MapBlockReply, 10000, (filterMsg: MapBlockReplyMessage): FilterResponse =>
{
for (const region of filterMsg.Data)
{
const name = Utils.BufferToStringSimple(region.Name);
if (name.trim().toLowerCase() === this.regionName.trim().toLowerCase())
{
this.xCoordinate = region.X;
this.yCoordinate = region.Y;
this.mapImage = region.MapImageID;
this.regionHandle = Utils.RegionCoordinatesToHandle(this.xCoordinate, this.yCoordinate);
return FilterResponse.Finish;
}
}
return FilterResponse.NoMatch;
});
}
shutdown()
{
this.comms.shutdown();

View File

@@ -17,4 +17,8 @@ export class CommandsBase
this.bot = bot;
this.circuit = this.currentRegion.circuit;
}
}
shutdown()
{
}
}

View File

@@ -5,11 +5,57 @@ import {TeleportLureRequestMessage} from '../messages/TeleportLureRequest';
import {Vector3} from '../Vector3';
import {TeleportLocationRequestMessage} from '../messages/TeleportLocationRequest';
import * as Long from 'long';
import {LureEvent, PacketFlags, RegionInfoReplyEvent, TeleportEvent, TeleportFlags} from '../..';
import {LureEvent, PacketFlags, RegionInfoReplyEvent, TeleportEvent, TeleportFlags, Bot} from '../..';
import {Agent} from '../Agent';
import {Subscription} from 'rxjs/Subscription';
export class TeleportCommands extends CommandsBase
{
private awaitTeleportEvent(): Promise<TeleportEvent>
private expectingTeleport = false;
private teleportSubscription: Subscription;
constructor(region: Region, agent: Agent, bot: Bot)
{
super(region, agent, bot);
this.teleportSubscription = this.bot.clientEvents.onTeleportEvent.subscribe((e: TeleportEvent) =>
{
if (e.eventType === TeleportEventType.TeleportCompleted)
{
if (!this.expectingTeleport)
{
if (e.simIP === 'local')
{
// Local TP - no need for any other shindiggery
return;
}
const newRegion: Region = new Region(this.agent, this.bot.clientEvents, this.currentRegion.options);
newRegion.circuit.circuitCode = this.currentRegion.circuit.circuitCode;
newRegion.circuit.secureSessionID = this.currentRegion.circuit.secureSessionID;
newRegion.circuit.sessionID = this.currentRegion.circuit.sessionID;
newRegion.circuit.udpBlacklist = this.currentRegion.circuit.udpBlacklist;
newRegion.circuit.ipAddress = e.simIP;
newRegion.circuit.port = e.simPort;
newRegion.activateCaps(e.seedCapability);
this.bot.changeRegion(newRegion, false).then(() =>
{
// Change region successful
}).catch((error) =>
{
console.log('Failed to change region');
console.error(error);
});
}
}
});
}
shutdown()
{
this.teleportSubscription.unsubscribe();
}
private awaitTeleportEvent(requested: boolean): Promise<TeleportEvent>
{
return new Promise<TeleportEvent>((resolve, reject) =>
{
@@ -20,10 +66,15 @@ export class TeleportCommands extends CommandsBase
reject(new Error('ClientEvents is null'));
return;
}
this.expectingTeleport = true;
const subscription = this.bot.clientEvents.onTeleportEvent.subscribe((e: TeleportEvent) =>
{
if (e.eventType === TeleportEventType.TeleportFailed || e.eventType === TeleportEventType.TeleportCompleted)
{
setTimeout(() =>
{
this.expectingTeleport = false;
});
subscription.unsubscribe();
}
if (e.eventType === TeleportEventType.TeleportFailed)
@@ -46,7 +97,6 @@ export class TeleportCommands extends CommandsBase
}
// Successful teleport! First, rip apart circuit
this.currentRegion.shutdown();
const region: Region = new Region(this.agent, this.bot.clientEvents, this.currentRegion.options);
region.circuit.circuitCode = this.currentRegion.circuit.circuitCode;
region.circuit.secureSessionID = this.currentRegion.circuit.secureSessionID;
@@ -54,11 +104,9 @@ export class TeleportCommands extends CommandsBase
region.circuit.udpBlacklist = this.currentRegion.circuit.udpBlacklist;
region.circuit.ipAddress = e.simIP;
region.circuit.port = e.simPort;
this.agent.setCurrentRegion(region);
this.currentRegion = region;
this.currentRegion.activateCaps(e.seedCapability);
region.activateCaps(e.seedCapability);
this.bot.changeRegion(this.currentRegion).then(() =>
this.bot.changeRegion(region, requested).then(() =>
{
resolve(e);
}).catch((error) =>
@@ -88,7 +136,7 @@ export class TeleportCommands extends CommandsBase
TeleportFlags: TeleportFlags.ViaLure
};
circuit.sendMessage(tlr, PacketFlags.Reliable);
this.awaitTeleportEvent().then((event: TeleportEvent) =>
this.awaitTeleportEvent(true).then((event: TeleportEvent) =>
{
resolve(event);
}).catch((err) =>
@@ -113,7 +161,7 @@ export class TeleportCommands extends CommandsBase
RegionHandle: handle
};
this.circuit.sendMessage(rtm, PacketFlags.Reliable);
this.awaitTeleportEvent().then((event: TeleportEvent) =>
this.awaitTeleportEvent(true).then((event: TeleportEvent) =>
{
resolve(event);
}).catch((err) =>

35
lib/enums/RegionFlags.ts Normal file
View File

@@ -0,0 +1,35 @@
export enum RegionFlags
{
None = 0,
AllowDamage = 1 << 0,
AllowLandmark = 1 << 1,
AllowSetHome = 1 << 2,
ResetHomeOnTeleport = 1 << 3,
SunFixed = 1 << 4,
TaxFree = 1 << 5,
BlockTerraform = 1 << 6,
BlockLandResell = 1 << 7,
Sandbox = 1 << 8,
NullLayer = 1 << 9,
SkipAgentAction = 1 << 10,
SkipUpdateInterestList = 1 << 11,
SkipCollisions = 1 << 12,
SkipScripts = 1 << 13,
SkipPhysics = 1 << 14,
ExternallyVisible = 1 << 15,
MainlandVisible = 1 << 16,
PublicAllowed = 1 << 17,
BlockDwell = 1 << 18,
NoFly = 1 << 19,
AllowDirectTeleport = 1 << 20,
EstateSkipScripts = 1 << 21,
RestrictPushObject = 1 << 22,
DenyAnonymous = 1 << 23,
DenyIdentified = 1 << 24,
DenyTransacted = 1 << 25,
AllowParcelChanges = 1 << 26,
AbuseEmailToEstateOwner = 1 << 27,
AllowVoice = 1 << 28,
BlockParcelSearch = 1 << 29,
DenyAgeUnverified = 1 << 30
}

View File

@@ -40,6 +40,7 @@ import {ParcelInfoFlags} from './enums/ParcelInfoFlags';
import {ParcelInfoReplyEvent} from './events/ParcelInfoReplyEvent';
import {ScriptDialogEvent} from './events/ScriptDialogEvent';
import {EventQueueStateChangeEvent} from './events/EventQueueStateChangeEvent';
import {RegionFlags} from './enums/RegionFlags';
export {
Bot,
@@ -67,6 +68,7 @@ export {
RegionProtocolFlags,
SoundFlags,
TeleportFlags,
RegionFlags,
// Events
ChatEvent,

268
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "@caspertech/node-metaverse",
"version": "0.4.5",
"version": "0.4.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -9,8 +9,8 @@
"resolved": "https://registry.npmjs.org/@caspertech/llsd/-/llsd-1.0.0.tgz",
"integrity": "sha1-Dyr7xO+JzsXonSAqBAmt0smaml0=",
"requires": {
"abab": "1.0.4",
"xmldom": "0.1.27"
"abab": "^1.0.4",
"xmldom": "^0.1.27"
}
},
"@types/caseless": {
@@ -28,7 +28,7 @@
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
"integrity": "sha1-7is7jqoRwJOCiZU2BrdFtzjFSx4=",
"requires": {
"@types/node": "8.10.34"
"@types/node": "*"
}
},
"@types/long": {
@@ -52,10 +52,10 @@
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.47.1.tgz",
"integrity": "sha512-TV3XLvDjQbIeVxJ1Z3oCTDk/KuYwwcNKVwz2YaT0F5u86Prgc4syDAp6P96rkTQQ4bIdh+VswQIC9zS6NjY7/g==",
"requires": {
"@types/caseless": "0.12.1",
"@types/form-data": "2.2.1",
"@types/node": "8.10.34",
"@types/tough-cookie": "2.3.3"
"@types/caseless": "*",
"@types/form-data": "*",
"@types/node": "*",
"@types/tough-cookie": "*"
}
},
"@types/tough-cookie": {
@@ -68,7 +68,7 @@
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz",
"integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==",
"requires": {
"@types/node": "8.10.34"
"@types/node": "*"
}
},
"@types/validator": {
@@ -81,7 +81,7 @@
"resolved": "https://registry.npmjs.org/@types/xml/-/xml-1.0.2.tgz",
"integrity": "sha1-LCELmjupz5RFILMOraMRwjZ3wfw=",
"requires": {
"@types/node": "8.10.34"
"@types/node": "*"
}
},
"@types/xmlrpc": {
@@ -89,8 +89,8 @@
"resolved": "https://registry.npmjs.org/@types/xmlrpc/-/xmlrpc-1.3.5.tgz",
"integrity": "sha512-0WaXC+u5gsiOAd2I9D95g5CPq3LbM15OK+c6IpNvOuUFyXoF1yVt0qhGEn3gQ6XRAxxOFQrU6Irm76U2Nvccgw==",
"requires": {
"@types/events": "1.2.0",
"@types/node": "8.10.34"
"@types/events": "*",
"@types/node": "*"
}
},
"abab": {
@@ -103,10 +103,10 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
"requires": {
"co": "4.6.0",
"fast-deep-equal": "1.1.0",
"fast-json-stable-stringify": "2.0.0",
"json-schema-traverse": "0.3.1"
"co": "^4.6.0",
"fast-deep-equal": "^1.0.0",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.3.0"
}
},
"ansi-regex": {
@@ -127,7 +127,7 @@
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "1.0.3"
"sprintf-js": "~1.0.2"
}
},
"arrify": {
@@ -141,7 +141,7 @@
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
"requires": {
"safer-buffer": "2.1.2"
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
@@ -170,9 +170,9 @@
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"dev": true,
"requires": {
"chalk": "1.1.3",
"esutils": "2.0.2",
"js-tokens": "3.0.2"
"chalk": "^1.1.3",
"esutils": "^2.0.2",
"js-tokens": "^3.0.2"
},
"dependencies": {
"chalk": {
@@ -202,7 +202,7 @@
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
"tweetnacl": "^0.14.3"
}
},
"brace-expansion": {
@@ -211,7 +211,7 @@
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "1.0.0",
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
@@ -244,9 +244,9 @@
"integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=",
"dev": true,
"requires": {
"ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
"supports-color": "4.5.0"
"ansi-styles": "^3.1.0",
"escape-string-regexp": "^1.0.5",
"supports-color": "^4.0.0"
},
"dependencies": {
"ansi-styles": {
@@ -255,7 +255,7 @@
"integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
"dev": true,
"requires": {
"color-convert": "1.9.0"
"color-convert": "^1.9.0"
}
},
"supports-color": {
@@ -264,7 +264,7 @@
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true,
"requires": {
"has-flag": "2.0.0"
"has-flag": "^2.0.0"
}
}
}
@@ -280,7 +280,7 @@
"integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=",
"dev": true,
"requires": {
"color-name": "1.1.3"
"color-name": "^1.1.1"
}
},
"color-name": {
@@ -294,7 +294,7 @@
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
"requires": {
"delayed-stream": "1.0.0"
"delayed-stream": "~1.0.0"
}
},
"commander": {
@@ -319,7 +319,7 @@
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "1.0.0"
"assert-plus": "^1.0.0"
}
},
"debug": {
@@ -348,7 +348,7 @@
"integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=",
"dev": true,
"requires": {
"esutils": "1.1.6",
"esutils": "^1.1.6",
"isarray": "0.0.1"
},
"dependencies": {
@@ -366,8 +366,8 @@
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"optional": true,
"requires": {
"jsbn": "0.1.1",
"safer-buffer": "2.1.2"
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"escape-string-regexp": {
@@ -418,9 +418,9 @@
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
"requires": {
"asynckit": "0.4.0",
"asynckit": "^0.4.0",
"combined-stream": "1.0.6",
"mime-types": "2.1.20"
"mime-types": "^2.1.12"
},
"dependencies": {
"combined-stream": {
@@ -428,7 +428,7 @@
"resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
"requires": {
"delayed-stream": "1.0.0"
"delayed-stream": "~1.0.0"
}
}
}
@@ -444,7 +444,7 @@
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "1.0.0"
"assert-plus": "^1.0.0"
}
},
"glob": {
@@ -453,12 +453,12 @@
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"growl": {
@@ -477,8 +477,8 @@
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
"requires": {
"ajv": "5.5.2",
"har-schema": "2.0.0"
"ajv": "^5.3.0",
"har-schema": "^2.0.0"
}
},
"has-ansi": {
@@ -487,7 +487,7 @@
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"dev": true,
"requires": {
"ansi-regex": "2.1.1"
"ansi-regex": "^2.0.0"
}
},
"has-flag": {
@@ -508,7 +508,7 @@
"integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=",
"dev": true,
"requires": {
"parse-passwd": "1.0.0"
"parse-passwd": "^1.0.0"
}
},
"http-signature": {
@@ -516,9 +516,9 @@
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "1.0.0",
"jsprim": "1.4.1",
"sshpk": "1.14.2"
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"inflight": {
@@ -527,8 +527,8 @@
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
@@ -570,8 +570,8 @@
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
"dev": true,
"requires": {
"argparse": "1.0.10",
"esprima": "4.0.1"
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"jsbn": {
@@ -627,7 +627,7 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
"integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
"requires": {
"mime-db": "1.36.0"
"mime-db": "~1.36.0"
}
},
"minimatch": {
@@ -636,7 +636,7 @@
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"dev": true,
"requires": {
"brace-expansion": "1.1.11"
"brace-expansion": "^1.1.7"
}
},
"minimist": {
@@ -698,12 +698,12 @@
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"supports-color": {
@@ -712,7 +712,7 @@
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"dev": true,
"requires": {
"has-flag": "2.0.0"
"has-flag": "^2.0.0"
}
}
}
@@ -734,7 +734,7 @@
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1.0.2"
"wrappy": "1"
}
},
"parse-passwd": {
@@ -780,26 +780,26 @@
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
"requires": {
"aws-sign2": "0.7.0",
"aws4": "1.8.0",
"caseless": "0.12.0",
"combined-stream": "1.0.7",
"extend": "3.0.2",
"forever-agent": "0.6.1",
"form-data": "2.3.2",
"har-validator": "5.1.0",
"http-signature": "1.2.0",
"is-typedarray": "1.0.0",
"isstream": "0.1.2",
"json-stringify-safe": "5.0.1",
"mime-types": "2.1.20",
"oauth-sign": "0.9.0",
"performance-now": "2.1.0",
"qs": "6.5.2",
"safe-buffer": "5.1.2",
"tough-cookie": "2.4.3",
"tunnel-agent": "0.6.0",
"uuid": "3.3.2"
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.0",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.4.3",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"dependencies": {
"safe-buffer": {
@@ -815,7 +815,7 @@
"integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
"dev": true,
"requires": {
"path-parse": "1.0.6"
"path-parse": "^1.0.5"
}
},
"rxjs": {
@@ -859,8 +859,8 @@
"integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==",
"dev": true,
"requires": {
"buffer-from": "1.1.1",
"source-map": "0.6.1"
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"sprintf-js": {
@@ -874,15 +874,15 @@
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
"requires": {
"asn1": "0.2.4",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.2",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.2",
"getpass": "0.1.7",
"jsbn": "0.1.1",
"safer-buffer": "2.1.2",
"tweetnacl": "0.14.5"
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"strip-ansi": {
@@ -922,8 +922,8 @@
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
"requires": {
"psl": "1.1.29",
"punycode": "1.4.1"
"psl": "^1.1.24",
"punycode": "^1.4.1"
}
},
"ts-node": {
@@ -932,16 +932,16 @@
"integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=",
"dev": true,
"requires": {
"arrify": "1.0.1",
"chalk": "2.3.0",
"diff": "3.4.0",
"make-error": "1.3.0",
"minimist": "1.2.0",
"mkdirp": "0.5.1",
"source-map-support": "0.4.18",
"tsconfig": "6.0.0",
"v8flags": "3.0.1",
"yn": "2.0.0"
"arrify": "^1.0.0",
"chalk": "^2.0.0",
"diff": "^3.1.0",
"make-error": "^1.1.1",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"source-map-support": "^0.4.0",
"tsconfig": "^6.0.0",
"v8flags": "^3.0.0",
"yn": "^2.0.0"
},
"dependencies": {
"source-map": {
@@ -956,7 +956,7 @@
"integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=",
"dev": true,
"requires": {
"source-map": "0.5.7"
"source-map": "^0.5.6"
}
}
}
@@ -967,8 +967,8 @@
"integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=",
"dev": true,
"requires": {
"strip-bom": "3.0.0",
"strip-json-comments": "2.0.1"
"strip-bom": "^3.0.0",
"strip-json-comments": "^2.0.0"
}
},
"tslib": {
@@ -983,18 +983,18 @@
"integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=",
"dev": true,
"requires": {
"babel-code-frame": "6.26.0",
"builtin-modules": "1.1.1",
"chalk": "2.3.0",
"commander": "2.18.0",
"diff": "3.4.0",
"glob": "7.1.3",
"js-yaml": "3.12.0",
"minimatch": "3.0.4",
"resolve": "1.8.1",
"semver": "5.5.1",
"tslib": "1.8.0",
"tsutils": "2.29.0"
"babel-code-frame": "^6.22.0",
"builtin-modules": "^1.1.1",
"chalk": "^2.3.0",
"commander": "^2.12.1",
"diff": "^3.2.0",
"glob": "^7.1.1",
"js-yaml": "^3.7.0",
"minimatch": "^3.0.4",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.8.0",
"tsutils": "^2.27.2"
}
},
"tslint-eslint-rules": {
@@ -1003,9 +1003,9 @@
"integrity": "sha1-fDDniC8mvCdr/5HSOEl1xp2viLo=",
"dev": true,
"requires": {
"doctrine": "0.7.2",
"tslib": "1.8.0",
"tsutils": "1.9.1"
"doctrine": "^0.7.2",
"tslib": "^1.0.0",
"tsutils": "^1.4.0"
},
"dependencies": {
"tsutils": {
@@ -1022,7 +1022,7 @@
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"dev": true,
"requires": {
"tslib": "1.9.3"
"tslib": "^1.8.1"
},
"dependencies": {
"tslib": {
@@ -1038,7 +1038,7 @@
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "5.1.1"
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
@@ -1064,7 +1064,7 @@
"integrity": "sha1-3Oj8N5wX2fLJ6e142JzgAFKxt2s=",
"dev": true,
"requires": {
"homedir-polyfill": "1.0.1"
"homedir-polyfill": "^1.0.1"
}
},
"validator": {
@@ -1077,9 +1077,9 @@
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "1.0.0",
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "1.3.0"
"extsprintf": "^1.2.0"
}
},
"wrappy": {
@@ -1108,8 +1108,8 @@
"resolved": "https://registry.npmjs.org/xmlrpc/-/xmlrpc-1.3.2.tgz",
"integrity": "sha1-JrLqNHhI0Ciqx+dRS1NRl23j6D0=",
"requires": {
"sax": "1.2.4",
"xmlbuilder": "8.2.2"
"sax": "1.2.x",
"xmlbuilder": "8.2.x"
}
},
"yn": {