Ping / circuit latency, break out commands, add typing function for IM, add thinkingTime and charactersPerSecond parameters to typing functions
This commit is contained in:
344
dist/Bot.js
vendored
344
dist/Bot.js
vendored
@@ -1,31 +1,25 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const LoginHandler_1 = require("./LoginHandler");
|
||||
const UUID_1 = require("./classes/UUID");
|
||||
const PacketFlags_1 = require("./enums/PacketFlags");
|
||||
const UseCircuitCode_1 = require("./classes/messages/UseCircuitCode");
|
||||
const CompleteAgentMovement_1 = require("./classes/messages/CompleteAgentMovement");
|
||||
const Message_1 = require("./enums/Message");
|
||||
const Region_1 = require("./classes/Region");
|
||||
const LogoutRequest_1 = require("./classes/messages/LogoutRequest");
|
||||
const Utils_1 = require("./classes/Utils");
|
||||
const RegionHandshakeReply_1 = require("./classes/messages/RegionHandshakeReply");
|
||||
const RegionProtocolFlags_1 = require("./enums/RegionProtocolFlags");
|
||||
const AgentThrottle_1 = require("./classes/messages/AgentThrottle");
|
||||
const AgentDataUpdateRequest_1 = require("./classes/messages/AgentDataUpdateRequest");
|
||||
const RegionHandleRequest_1 = require("./classes/messages/RegionHandleRequest");
|
||||
const MapItemRequest_1 = require("./classes/messages/MapItemRequest");
|
||||
const GridItemType_1 = require("./enums/GridItemType");
|
||||
const MapBlockRequest_1 = require("./classes/messages/MapBlockRequest");
|
||||
const MapInfoReply_1 = require("./events/MapInfoReply");
|
||||
const TeleportLureRequest_1 = require("./classes/messages/TeleportLureRequest");
|
||||
const TeleportFlags_1 = require("./enums/TeleportFlags");
|
||||
const LLSD = require("llsd");
|
||||
const TeleportEvent_1 = require("./events/TeleportEvent");
|
||||
const TeleportEventType_1 = require("./enums/TeleportEventType");
|
||||
const ClientCommands_1 = require("./classes/ClientCommands");
|
||||
const DisconnectEvent_1 = require("./events/DisconnectEvent");
|
||||
const StartPingCheck_1 = require("./classes/messages/StartPingCheck");
|
||||
class Bot {
|
||||
constructor(login) {
|
||||
this.throttleGenCounter = 0;
|
||||
this.ping = null;
|
||||
this.pingNumber = 0;
|
||||
this.lastSuccessfulPing = 0;
|
||||
this.clientEvents = null;
|
||||
this.loginParams = login;
|
||||
}
|
||||
@@ -36,12 +30,24 @@ class Bot {
|
||||
this.clientEvents = response.clientEvents;
|
||||
this.currentRegion = response.region;
|
||||
this.agent = response.agent;
|
||||
this.clientCommands = new ClientCommands_1.ClientCommands(response.region, response.agent, this);
|
||||
resolve(response);
|
||||
}).catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
changeRegion(region) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.currentRegion = region;
|
||||
this.clientCommands = new ClientCommands_1.ClientCommands(this.currentRegion, this.agent, this);
|
||||
this.connectToSim().then(() => {
|
||||
resolve();
|
||||
}).catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
close() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const circuit = this.currentRegion.circuit;
|
||||
@@ -59,195 +65,18 @@ class Bot {
|
||||
this.currentRegion.shutdown();
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
setBandwidth(total) {
|
||||
const circuit = this.currentRegion.circuit;
|
||||
const agentThrottle = new AgentThrottle_1.AgentThrottleMessage();
|
||||
agentThrottle.AgentData = {
|
||||
AgentID: this.agent.agentID,
|
||||
SessionID: circuit.sessionID,
|
||||
CircuitCode: circuit.circuitCode
|
||||
};
|
||||
const throttleData = Buffer.allocUnsafe(28);
|
||||
let pos = 0;
|
||||
const resendThrottle = total * 0.1;
|
||||
const landThrottle = total * 0.172;
|
||||
const windThrottle = total * 0.05;
|
||||
const cloudThrottle = total * 0.05;
|
||||
const taskThrottle = total * 0.234;
|
||||
const textureThrottle = total * 0.234;
|
||||
const assetThrottle = total * 0.160;
|
||||
throttleData.writeFloatLE(resendThrottle, pos);
|
||||
pos += 4;
|
||||
throttleData.writeFloatLE(landThrottle, pos);
|
||||
pos += 4;
|
||||
throttleData.writeFloatLE(windThrottle, pos);
|
||||
pos += 4;
|
||||
throttleData.writeFloatLE(cloudThrottle, pos);
|
||||
pos += 4;
|
||||
throttleData.writeFloatLE(taskThrottle, pos);
|
||||
pos += 4;
|
||||
throttleData.writeFloatLE(textureThrottle, pos);
|
||||
pos += 4;
|
||||
throttleData.writeFloatLE(assetThrottle, pos);
|
||||
agentThrottle.Throttle = {
|
||||
GenCounter: this.throttleGenCounter++,
|
||||
Throttles: throttleData
|
||||
};
|
||||
circuit.sendMessage(agentThrottle, PacketFlags_1.PacketFlags.Reliable);
|
||||
}
|
||||
acceptTeleport(lure) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const circuit = this.currentRegion.circuit;
|
||||
const tlr = new TeleportLureRequest_1.TeleportLureRequestMessage();
|
||||
tlr.Info = {
|
||||
AgentID: this.agent.agentID,
|
||||
SessionID: circuit.sessionID,
|
||||
LureID: lure.lureID,
|
||||
TeleportFlags: TeleportFlags_1.TeleportFlags.ViaLure
|
||||
};
|
||||
circuit.sendMessage(tlr, PacketFlags_1.PacketFlags.Reliable);
|
||||
if (this.currentRegion.caps.eventQueueClient) {
|
||||
if (this.clientEvents === null) {
|
||||
reject(new Error('ClientEvents is null'));
|
||||
return;
|
||||
delete this.clientCommands;
|
||||
if (this.ping !== null) {
|
||||
clearInterval(this.ping);
|
||||
this.ping = null;
|
||||
}
|
||||
const subscription = this.clientEvents.onTeleportEvent.subscribe((e) => {
|
||||
if (e.eventType === TeleportEventType_1.TeleportEventType.TeleportFailed || e.eventType === TeleportEventType_1.TeleportEventType.TeleportCompleted) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
if (e.eventType === TeleportEventType_1.TeleportEventType.TeleportFailed) {
|
||||
reject(e);
|
||||
}
|
||||
else if (e.eventType === TeleportEventType_1.TeleportEventType.TeleportCompleted) {
|
||||
if (e.simIP === 'local') {
|
||||
resolve(e);
|
||||
return;
|
||||
}
|
||||
if (this.clientEvents === null) {
|
||||
reject(new Error('ClientEvents is null'));
|
||||
return;
|
||||
}
|
||||
this.currentRegion.shutdown();
|
||||
const region = new Region_1.Region(this.agent, this.clientEvents);
|
||||
region.circuit.circuitCode = this.currentRegion.circuit.circuitCode;
|
||||
region.circuit.secureSessionID = this.currentRegion.circuit.secureSessionID;
|
||||
region.circuit.sessionID = this.currentRegion.circuit.sessionID;
|
||||
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.connectToSim().then(() => {
|
||||
resolve(e);
|
||||
}).catch((error) => {
|
||||
reject(e);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
getRegionHandle(regionID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const circuit = this.currentRegion.circuit;
|
||||
const msg = new RegionHandleRequest_1.RegionHandleRequestMessage();
|
||||
msg.RequestBlock = {
|
||||
RegionID: regionID,
|
||||
};
|
||||
circuit.sendMessage(msg, PacketFlags_1.PacketFlags.Reliable);
|
||||
circuit.waitForMessage(Message_1.Message.RegionIDAndHandleReply, 10000, (packet) => {
|
||||
const filterMsg = packet.message;
|
||||
return (filterMsg.ReplyBlock.RegionID.toString() === regionID.toString());
|
||||
}).then((packet) => {
|
||||
const responseMsg = packet.message;
|
||||
resolve(responseMsg.ReplyBlock.RegionHandle);
|
||||
});
|
||||
});
|
||||
}
|
||||
getRegionMapInfo(gridX, gridY) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const circuit = this.currentRegion.circuit;
|
||||
const response = new MapInfoReply_1.MapInfoReply();
|
||||
const msg = new MapBlockRequest_1.MapBlockRequestMessage();
|
||||
msg.AgentData = {
|
||||
AgentID: this.agent.agentID,
|
||||
SessionID: circuit.sessionID,
|
||||
Flags: 65536,
|
||||
EstateID: 0,
|
||||
Godlike: true
|
||||
};
|
||||
msg.PositionData = {
|
||||
MinX: (gridX / 256),
|
||||
MaxX: (gridX / 256),
|
||||
MinY: (gridY / 256),
|
||||
MaxY: (gridY / 256)
|
||||
};
|
||||
circuit.sendMessage(msg, PacketFlags_1.PacketFlags.Reliable);
|
||||
circuit.waitForMessage(Message_1.Message.MapBlockReply, 10000, (packet) => {
|
||||
const filterMsg = packet.message;
|
||||
let found = false;
|
||||
filterMsg.Data.forEach((data) => {
|
||||
if (data.X === (gridX / 256) && data.Y === (gridY / 256)) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
return found;
|
||||
}).then((packet) => {
|
||||
const responseMsg = packet.message;
|
||||
responseMsg.Data.forEach((data) => {
|
||||
if (data.X === (gridX / 256) && data.Y === (gridY / 256)) {
|
||||
response.name = Utils_1.Utils.BufferToStringSimple(data.Name);
|
||||
response.accessFlags = data.Access;
|
||||
response.mapImage = data.MapImageID;
|
||||
}
|
||||
});
|
||||
const regionHandle = Utils_1.Utils.RegionCoordinatesToHandle(gridX, gridY);
|
||||
const mi = new MapItemRequest_1.MapItemRequestMessage();
|
||||
mi.AgentData = {
|
||||
AgentID: this.agent.agentID,
|
||||
SessionID: circuit.sessionID,
|
||||
Flags: 2,
|
||||
EstateID: 0,
|
||||
Godlike: false
|
||||
};
|
||||
mi.RequestData = {
|
||||
ItemType: GridItemType_1.GridItemType.AgentLocations,
|
||||
RegionHandle: regionHandle
|
||||
};
|
||||
circuit.sendMessage(mi, PacketFlags_1.PacketFlags.Reliable);
|
||||
const minX = Math.floor(gridX / 256) * 256;
|
||||
const maxX = minX + 256;
|
||||
const minY = Math.floor(gridY / 256) * 256;
|
||||
const maxY = minY + 256;
|
||||
response.avatars = [];
|
||||
circuit.waitForMessage(Message_1.Message.MapItemReply, 10000, (packet) => {
|
||||
const filterMsg = packet.message;
|
||||
let found = false;
|
||||
filterMsg.Data.forEach((data) => {
|
||||
if (data.X >= minX && data.X <= maxX && data.Y >= minY && data.Y <= maxY) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
return found;
|
||||
}).then((packet2) => {
|
||||
const responseMsg2 = packet2.message;
|
||||
responseMsg2.Data.forEach((data) => {
|
||||
response.avatars.push({
|
||||
X: data.X,
|
||||
Y: data.Y
|
||||
});
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
}).catch((err) => {
|
||||
reject(err);
|
||||
const disconnectEvent = new DisconnectEvent_1.DisconnectEvent();
|
||||
disconnectEvent.requested = true;
|
||||
disconnectEvent.message = 'Logout completed';
|
||||
if (this.clientEvents) {
|
||||
this.clientEvents.onDisconnected.next(disconnectEvent);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -281,7 +110,9 @@ class Bot {
|
||||
};
|
||||
return circuit.waitForAck(circuit.sendMessage(handshakeReply, PacketFlags_1.PacketFlags.Reliable), 10000);
|
||||
}).then(() => {
|
||||
this.setBandwidth(1536000);
|
||||
if (this.clientCommands !== null) {
|
||||
this.clientCommands.network.setBandwidth(1536000);
|
||||
}
|
||||
const agentRequest = new AgentDataUpdateRequest_1.AgentDataUpdateRequestMessage();
|
||||
agentRequest.AgentData = {
|
||||
AgentID: this.agent.agentID,
|
||||
@@ -290,6 +121,51 @@ class Bot {
|
||||
circuit.sendMessage(agentRequest, PacketFlags_1.PacketFlags.Reliable);
|
||||
this.agent.setInitialAppearance();
|
||||
this.agent.circuitActive();
|
||||
this.lastSuccessfulPing = new Date().getTime();
|
||||
this.ping = setInterval(() => {
|
||||
this.pingNumber++;
|
||||
if (this.pingNumber > 255) {
|
||||
this.pingNumber = 0;
|
||||
}
|
||||
const ping = new StartPingCheck_1.StartPingCheckMessage();
|
||||
ping.PingID = {
|
||||
PingID: this.pingNumber,
|
||||
OldestUnacked: this.currentRegion.circuit.getOldestUnacked()
|
||||
};
|
||||
circuit.sendMessage(ping, PacketFlags_1.PacketFlags.Reliable);
|
||||
circuit.waitForMessage(Message_1.Message.CompletePingCheck, 10000, ((pingData, packet) => {
|
||||
const cpc = packet.message;
|
||||
if (cpc.PingID.PingID === pingData.pingID) {
|
||||
this.lastSuccessfulPing = new Date().getTime();
|
||||
const pingTime = this.lastSuccessfulPing - pingData.timeSent;
|
||||
if (this.clientEvents !== null) {
|
||||
this.clientEvents.onCircuitLatency.next(pingTime);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}).bind(this, {
|
||||
pingID: this.pingNumber,
|
||||
timeSent: new Date().getTime()
|
||||
}));
|
||||
if ((new Date().getTime() - this.lastSuccessfulPing) > 60000) {
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
if (this.ping !== null) {
|
||||
clearInterval(this.ping);
|
||||
this.ping = null;
|
||||
}
|
||||
const disconnectEvent = new DisconnectEvent_1.DisconnectEvent();
|
||||
disconnectEvent.requested = false;
|
||||
disconnectEvent.message = 'Circuit timeout';
|
||||
if (this.clientEvents) {
|
||||
this.clientEvents.onDisconnected.next(disconnectEvent);
|
||||
}
|
||||
}
|
||||
}, 5000);
|
||||
circuit.subscribeToMessages([
|
||||
Message_1.Message.TeleportFailed,
|
||||
Message_1.Message.TeleportFinish,
|
||||
@@ -297,9 +173,7 @@ class Bot {
|
||||
Message_1.Message.TeleportStart,
|
||||
Message_1.Message.TeleportProgress,
|
||||
Message_1.Message.TeleportCancel,
|
||||
Message_1.Message.SoundTrigger,
|
||||
Message_1.Message.AttachedSound,
|
||||
Message_1.Message.AvatarAnimation
|
||||
Message_1.Message.KickUser
|
||||
], (packet) => {
|
||||
switch (packet.message.id) {
|
||||
case Message_1.Message.TeleportLocal:
|
||||
@@ -350,21 +224,24 @@ class Bot {
|
||||
this.clientEvents.onTeleportEvent.next(tpEvent);
|
||||
break;
|
||||
}
|
||||
case Message_1.Message.SoundTrigger:
|
||||
case Message_1.Message.KickUser:
|
||||
{
|
||||
const soundTrigger = packet.message;
|
||||
const soundID = soundTrigger.SoundData.SoundID;
|
||||
break;
|
||||
}
|
||||
case Message_1.Message.AttachedSound:
|
||||
{
|
||||
const attachedSound = packet.message;
|
||||
const soundID = attachedSound.DataBlock.SoundID;
|
||||
break;
|
||||
}
|
||||
case Message_1.Message.AvatarAnimation:
|
||||
{
|
||||
const avatarAnimation = packet.message;
|
||||
const kickUser = packet.message;
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
if (this.ping !== null) {
|
||||
clearInterval(this.ping);
|
||||
this.ping = null;
|
||||
}
|
||||
const disconnectEvent = new DisconnectEvent_1.DisconnectEvent();
|
||||
disconnectEvent.requested = false;
|
||||
disconnectEvent.message = Utils_1.Utils.BufferToStringSimple(kickUser.UserInfo.Reason);
|
||||
if (this.clientEvents) {
|
||||
this.clientEvents.onDisconnected.next(disconnectEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -375,37 +252,6 @@ class Bot {
|
||||
});
|
||||
});
|
||||
}
|
||||
downloadAsset(type, uuid) {
|
||||
return this.currentRegion.caps.downloadAsset(uuid, type);
|
||||
}
|
||||
uploadAsset(type, data, name, description) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.agent && this.agent.inventory && this.agent.inventory.main && this.agent.inventory.main.root) {
|
||||
this.currentRegion.caps.capsRequestXML('NewFileAgentInventory', {
|
||||
'folder_id': new LLSD.UUID(this.agent.inventory.main.root.toString()),
|
||||
'asset_type': type,
|
||||
'inventory_type': Utils_1.Utils.HTTPAssetTypeToInventoryType(type),
|
||||
'name': name,
|
||||
'description': description,
|
||||
'everyone_mask': (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19),
|
||||
'group_mask': (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19),
|
||||
'next_owner_mask': (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19),
|
||||
'expected_upload_cost': 0
|
||||
}).then((response) => {
|
||||
if (response['state'] === 'upload') {
|
||||
const uploadURL = response['uploader'];
|
||||
this.currentRegion.caps.capsRequestUpload(uploadURL, data).then((responseUpload) => {
|
||||
resolve(new UUID_1.UUID(responseUpload['new_asset'].toString()));
|
||||
}).catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.Bot = Bot;
|
||||
//# sourceMappingURL=Bot.js.map
|
||||
Reference in New Issue
Block a user