Handle disconnects gracefully! Handle KillObject to prevent perpetually inflating object store. Unsubscribe from rxjs subscription in bot.ts on disconnect. Stop ping timer. Don't re-create clientEvents on each login.
This commit is contained in:
3
dist/Bot.d.ts
vendored
3
dist/Bot.d.ts
vendored
@@ -9,7 +9,8 @@ export declare class Bot {
|
||||
private ping;
|
||||
private pingNumber;
|
||||
private lastSuccessfulPing;
|
||||
clientEvents: ClientEvents | null;
|
||||
private circuitSubscription;
|
||||
clientEvents: ClientEvents;
|
||||
clientCommands: ClientCommands;
|
||||
constructor(login: LoginParameters);
|
||||
login(): Promise<{}>;
|
||||
|
||||
25
dist/Bot.js
vendored
25
dist/Bot.js
vendored
@@ -11,6 +11,7 @@ const RegionHandshakeReply_1 = require("./classes/messages/RegionHandshakeReply"
|
||||
const RegionProtocolFlags_1 = require("./enums/RegionProtocolFlags");
|
||||
const AgentDataUpdateRequest_1 = require("./classes/messages/AgentDataUpdateRequest");
|
||||
const TeleportEvent_1 = require("./events/TeleportEvent");
|
||||
const ClientEvents_1 = require("./classes/ClientEvents");
|
||||
const TeleportEventType_1 = require("./enums/TeleportEventType");
|
||||
const ClientCommands_1 = require("./classes/ClientCommands");
|
||||
const DisconnectEvent_1 = require("./events/DisconnectEvent");
|
||||
@@ -20,14 +21,14 @@ class Bot {
|
||||
this.ping = null;
|
||||
this.pingNumber = 0;
|
||||
this.lastSuccessfulPing = 0;
|
||||
this.clientEvents = null;
|
||||
this.circuitSubscription = null;
|
||||
this.clientEvents = new ClientEvents_1.ClientEvents();
|
||||
this.loginParams = login;
|
||||
}
|
||||
login() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const loginHandler = new LoginHandler_1.LoginHandler();
|
||||
const loginHandler = new LoginHandler_1.LoginHandler(this.clientEvents);
|
||||
loginHandler.Login(this.loginParams).then((response) => {
|
||||
this.clientEvents = response.clientEvents;
|
||||
this.currentRegion = response.region;
|
||||
this.agent = response.agent;
|
||||
this.clientCommands = new ClientCommands_1.ClientCommands(response.region, response.agent, this);
|
||||
@@ -41,6 +42,10 @@ class Bot {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.currentRegion = region;
|
||||
this.clientCommands = new ClientCommands_1.ClientCommands(this.currentRegion, this.agent, this);
|
||||
if (this.ping !== null) {
|
||||
clearInterval(this.ping);
|
||||
this.ping = null;
|
||||
}
|
||||
this.connectToSim().then(() => {
|
||||
resolve();
|
||||
}).catch((error) => {
|
||||
@@ -63,6 +68,10 @@ class Bot {
|
||||
}).then(() => {
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
if (this.circuitSubscription !== null) {
|
||||
this.circuitSubscription.unsubscribe();
|
||||
this.circuitSubscription = null;
|
||||
}
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
@@ -151,6 +160,10 @@ class Bot {
|
||||
if ((new Date().getTime() - this.lastSuccessfulPing) > 60000) {
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
if (this.circuitSubscription !== null) {
|
||||
this.circuitSubscription.unsubscribe();
|
||||
this.circuitSubscription = null;
|
||||
}
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
@@ -166,7 +179,7 @@ class Bot {
|
||||
}
|
||||
}
|
||||
}, 5000);
|
||||
circuit.subscribeToMessages([
|
||||
this.circuitSubscription = circuit.subscribeToMessages([
|
||||
Message_1.Message.TeleportFailed,
|
||||
Message_1.Message.TeleportFinish,
|
||||
Message_1.Message.TeleportLocal,
|
||||
@@ -229,6 +242,10 @@ class Bot {
|
||||
const kickUser = packet.message;
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
if (this.circuitSubscription !== null) {
|
||||
this.circuitSubscription.unsubscribe();
|
||||
this.circuitSubscription = null;
|
||||
}
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
|
||||
2
dist/Bot.js.map
vendored
2
dist/Bot.js.map
vendored
File diff suppressed because one or more lines are too long
3
dist/LoginHandler.d.ts
vendored
3
dist/LoginHandler.d.ts
vendored
@@ -1,6 +1,9 @@
|
||||
import { LoginParameters } from './classes/LoginParameters';
|
||||
import { LoginResponse } from './classes/LoginResponse';
|
||||
import { ClientEvents } from './classes/ClientEvents';
|
||||
export declare class LoginHandler {
|
||||
private clientEvents;
|
||||
static GenerateMAC(): string;
|
||||
constructor(ce: ClientEvents);
|
||||
Login(params: LoginParameters): Promise<LoginResponse>;
|
||||
}
|
||||
|
||||
9
dist/LoginHandler.js
vendored
9
dist/LoginHandler.js
vendored
@@ -17,6 +17,9 @@ class LoginHandler {
|
||||
}
|
||||
return macAddress;
|
||||
}
|
||||
constructor(ce) {
|
||||
this.clientEvents = ce;
|
||||
}
|
||||
Login(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const secureClientOptions = {
|
||||
@@ -30,7 +33,7 @@ class LoginHandler {
|
||||
{
|
||||
'first': params.firstName,
|
||||
'last': params.lastName,
|
||||
'passwd': '$1$' + crypto.createHash('md5').update(params.password).digest('hex'),
|
||||
'passwd': '$1$' + crypto.createHash('md5').update(params.password.substr(0, 16)).digest('hex'),
|
||||
'start': 'home',
|
||||
'major': '0',
|
||||
'minor': '0',
|
||||
@@ -57,7 +60,7 @@ class LoginHandler {
|
||||
'global-textures'
|
||||
]
|
||||
}
|
||||
], function (error, value) {
|
||||
], (error, value) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
@@ -66,7 +69,7 @@ class LoginHandler {
|
||||
reject(new Error(value['message']));
|
||||
}
|
||||
else {
|
||||
const response = new LoginResponse_1.LoginResponse(value);
|
||||
const response = new LoginResponse_1.LoginResponse(value, this.clientEvents);
|
||||
resolve(response);
|
||||
}
|
||||
}
|
||||
|
||||
2
dist/LoginHandler.js.map
vendored
2
dist/LoginHandler.js.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"LoginHandler.js","sourceRoot":"","sources":["../lib/LoginHandler.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"LoginHandler.js","sourceRoot":"","sources":["../lib/LoginHandler.ts"],"names":[],"mappings":";;AAAA,iCAAiC;AACjC,iCAAiC;AAEjC,2DAAsD;AAEtD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAE7B;IAII,MAAM,CAAC,WAAW;QAEd,MAAM,SAAS,GAAG,kBAAkB,CAAC;QACrC,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAC1B,CAAC;YACG,UAAU,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;YAC/D,UAAU,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;YAC/D,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACZ,CAAC;gBACG,UAAU,IAAI,GAAG,CAAC;YACtB,CAAC;QACL,CAAC;QAED,MAAM,CAAC,UAAU,CAAC;IACtB,CAAC;IAED,YAAY,EAAgB;QAExB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAuB;QAEzB,MAAM,CAAC,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAElD,MAAM,mBAAmB,GAAG;gBACxB,IAAI,EAAE,0BAA0B;gBAChC,IAAI,EAAE,GAAG;gBACT,IAAI,EAAE,oBAAoB;gBAC1B,kBAAkB,EAAE,KAAK;aAC5B,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;YAC9D,MAAM,CAAC,UAAU,CAAC,oBAAoB,EAClC;gBACI;oBACI,OAAO,EAAE,MAAM,CAAC,SAAS;oBACzB,MAAM,EAAE,MAAM,CAAC,QAAQ;oBACvB,QAAQ,EAAE,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC9F,OAAO,EAAE,MAAM;oBACf,OAAO,EAAE,GAAG;oBACZ,OAAO,EAAE,GAAG;oBACZ,OAAO,EAAE,GAAG;oBACZ,OAAO,EAAE,GAAG;oBACZ,UAAU,EAAE,KAAK;oBACjB,KAAK,EAAE,YAAY,CAAC,WAAW,EAAE;oBACjC,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE;oBAC1B,YAAY,EAAE,KAAK;oBACnB,QAAQ,EAAE,sBAAsB;oBAChC,SAAS,EAAE;wBACP,gBAAgB;wBAChB,oBAAoB;wBACpB,oBAAoB;wBACpB,qBAAqB;wBACrB,oBAAoB;wBACpB,UAAU;wBACV,kBAAkB;wBAClB,qBAAqB;wBACrB,uBAAuB;wBACvB,YAAY;wBACZ,WAAW;wBACX,aAAa;wBACb,iBAAiB;qBACpB;iBACJ;aACJ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBAEhB,EAAE,CAAC,CAAC,KAAK,CAAC,CACV,CAAC;oBACG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAClB,CAAC;gBACD,IAAI,CACJ,CAAC;oBACG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAClD,CAAC;wBACG,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;oBACxC,CAAC;oBACD,IAAI,CACJ,CAAC;wBACG,MAAM,QAAQ,GAAG,IAAI,6BAAa,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;wBAC7D,OAAO,CAAC,QAAQ,CAAC,CAAC;oBACtB,CAAC;gBACL,CAAC;YACL,CAAC,CACJ,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;CAEJ;AA5FD,oCA4FC"}
|
||||
2
dist/classes/Comms.js
vendored
2
dist/classes/Comms.js
vendored
@@ -24,7 +24,6 @@ class Comms {
|
||||
switch (im.MessageBlock.Dialog) {
|
||||
case InstantMessageDialog_1.InstantMessageDialog.MessageFromAgent:
|
||||
{
|
||||
console.log(im);
|
||||
const imEvent = new InstantMessageEvent_1.InstantMessageEvent();
|
||||
imEvent.source = ChatSourceType_1.ChatSourceType.Agent;
|
||||
imEvent.from = im.AgentData.AgentID;
|
||||
@@ -53,7 +52,6 @@ class Comms {
|
||||
break;
|
||||
case InstantMessageDialog_1.InstantMessageDialog.MessageFromObject:
|
||||
{
|
||||
console.log(im);
|
||||
const imEvent = new InstantMessageEvent_1.InstantMessageEvent();
|
||||
imEvent.source = ChatSourceType_1.ChatSourceType.Object;
|
||||
imEvent.owner = im.AgentData.AgentID;
|
||||
|
||||
2
dist/classes/Comms.js.map
vendored
2
dist/classes/Comms.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/classes/LoginResponse.d.ts
vendored
2
dist/classes/LoginResponse.d.ts
vendored
@@ -30,5 +30,5 @@ export declare class LoginResponse {
|
||||
private static toRegionHandle(x_global, y_global);
|
||||
private static parseVector3(str);
|
||||
private static parseHome(str);
|
||||
constructor(json: any);
|
||||
constructor(json: any, ce: ClientEvents);
|
||||
}
|
||||
|
||||
5
dist/classes/LoginResponse.js
vendored
5
dist/classes/LoginResponse.js
vendored
@@ -6,9 +6,8 @@ const Region_1 = require("./Region");
|
||||
const LoginFlags_1 = require("../enums/LoginFlags");
|
||||
const Vector3_1 = require("./Vector3");
|
||||
const Long = require("long");
|
||||
const ClientEvents_1 = require("./ClientEvents");
|
||||
class LoginResponse {
|
||||
constructor(json) {
|
||||
constructor(json, ce) {
|
||||
this.events = {
|
||||
categories: []
|
||||
};
|
||||
@@ -16,7 +15,7 @@ class LoginResponse {
|
||||
categories: []
|
||||
};
|
||||
this.textures = {};
|
||||
this.clientEvents = new ClientEvents_1.ClientEvents();
|
||||
this.clientEvents = ce;
|
||||
this.agent = new Agent_1.Agent(this.clientEvents);
|
||||
this.region = new Region_1.Region(this.agent, this.clientEvents);
|
||||
Object.keys(json).forEach((key) => {
|
||||
|
||||
2
dist/classes/LoginResponse.js.map
vendored
2
dist/classes/LoginResponse.js.map
vendored
File diff suppressed because one or more lines are too long
5
dist/classes/ObjectStore.d.ts
vendored
5
dist/classes/ObjectStore.d.ts
vendored
@@ -2,8 +2,8 @@
|
||||
import { Circuit } from './Circuit';
|
||||
import { Agent } from './Agent';
|
||||
import { GameObject } from './Object';
|
||||
import { NameValue } from "./NameValue";
|
||||
import { ClientEvents } from "./ClientEvents";
|
||||
import { NameValue } from './NameValue';
|
||||
import { ClientEvents } from './ClientEvents';
|
||||
export declare class ObjectStore {
|
||||
private circuit;
|
||||
private agent;
|
||||
@@ -12,6 +12,7 @@ export declare class ObjectStore {
|
||||
private objectsByParent;
|
||||
private clientEvents;
|
||||
constructor(circuit: Circuit, agent: Agent, clientEvents: ClientEvents);
|
||||
deleteObject(objectID: number): void;
|
||||
readExtraParams(buf: Buffer, pos: number, o: GameObject): number;
|
||||
getObjectsByParent(parentID: number): GameObject[];
|
||||
parseNameValues(str: string): {
|
||||
|
||||
33
dist/classes/ObjectStore.js
vendored
33
dist/classes/ObjectStore.js
vendored
@@ -23,7 +23,8 @@ class ObjectStore {
|
||||
Message_1.Message.ObjectUpdateCached,
|
||||
Message_1.Message.ObjectUpdateCompressed,
|
||||
Message_1.Message.ImprovedTerseObjectUpdate,
|
||||
Message_1.Message.MultipleObjectUpdate
|
||||
Message_1.Message.MultipleObjectUpdate,
|
||||
Message_1.Message.KillObject
|
||||
], (packet) => {
|
||||
switch (packet.message.id) {
|
||||
case Message_1.Message.ObjectUpdate:
|
||||
@@ -269,9 +270,39 @@ class ObjectStore {
|
||||
const multipleObjectUpdate = packet.message;
|
||||
console.error('TODO: MultipleObjectUpdate');
|
||||
break;
|
||||
case Message_1.Message.KillObject:
|
||||
const killObj = packet.message;
|
||||
killObj.ObjectData.forEach((obj) => {
|
||||
const objectID = obj.ID;
|
||||
this.deleteObject(objectID);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
deleteObject(objectID) {
|
||||
if (this.objects[objectID]) {
|
||||
if (this.objectsByParent[objectID]) {
|
||||
this.objectsByParent[objectID].forEach((childObjID) => {
|
||||
this.deleteObject(childObjID);
|
||||
});
|
||||
}
|
||||
delete this.objectsByParent[objectID];
|
||||
const objct = this.objects[objectID];
|
||||
const uuid = objct.FullID.toString();
|
||||
if (this.objectsByUUID[uuid]) {
|
||||
delete this.objectsByUUID[uuid];
|
||||
}
|
||||
const parentID = objct.ParentID;
|
||||
if (this.objectsByParent[parentID]) {
|
||||
const ind = this.objectsByParent[parentID].indexOf(objectID);
|
||||
if (ind !== -1) {
|
||||
this.objectsByParent[parentID].splice(ind, 1);
|
||||
}
|
||||
}
|
||||
delete this.objects[objectID];
|
||||
}
|
||||
}
|
||||
readExtraParams(buf, pos, o) {
|
||||
if (pos >= buf.length) {
|
||||
return 0;
|
||||
|
||||
2
dist/classes/ObjectStore.js.map
vendored
2
dist/classes/ObjectStore.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -13,42 +13,54 @@ const bot = new nmv.Bot(loginParameters);
|
||||
|
||||
let resp = null;
|
||||
|
||||
const master = 'd1cd5b71-6209-4595-9bf0-771bf689ce00';
|
||||
|
||||
bot.clientEvents.onLure.subscribe((lureEvent) =>
|
||||
{
|
||||
bot.clientCommands.grid.getRegionMapInfo(lureEvent.gridX, lureEvent.gridY).then((regionInfo) =>
|
||||
{
|
||||
if (lureEvent.from.toString() === master)
|
||||
{
|
||||
console.log('Accepting teleport lure to ' + regionInfo.name + ' (' + regionInfo.avatars.length + ' avatar' + ((regionInfo.avatars.length === 1)?'':'s') + ' present) from ' + lureEvent.fromName + ' with message: ' + lureEvent.lureMessage);
|
||||
bot.clientCommands.teleport.acceptTeleport(lureEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log('Ignoring teleport lure to ' + regionInfo.name + ' (' + regionInfo.avatars.length + ' avatar' + ((regionInfo.avatars.length === 1)?'':'s') + ' present) from ' + lureEvent.fromName + ' with message: ' + lureEvent.lureMessage);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
bot.clientEvents.onInstantMessage.subscribe((IMEvent) =>
|
||||
{
|
||||
if (IMEvent.source === nmv.ChatSourceType.Agent)
|
||||
{
|
||||
if (!(IMEvent.flags & nmv.InstantMessageEventFlags.startTyping || IMEvent.flags & nmv.InstantMessageEventFlags.finishTyping))
|
||||
{
|
||||
bot.clientCommands.comms.typeInstantMessage(IMEvent.from, 'Thanks for the message! This account is a scripted agent (bot), so cannot reply to your query. Sorry!');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bot.clientEvents.onDisconnected.subscribe((DisconnectEvent) =>
|
||||
{
|
||||
console.log("Disconnected from simulator: "+DisconnectEvent.message);
|
||||
if (!DisconnectEvent.requested)
|
||||
{
|
||||
setTimeout(() =>
|
||||
{
|
||||
console.log("Reconnecting");
|
||||
connect();
|
||||
}, 5000)
|
||||
}
|
||||
});
|
||||
|
||||
function connect()
|
||||
{
|
||||
console.log("Logging in..");
|
||||
bot.login().then((response) =>
|
||||
{
|
||||
bot.clientEvents.onLure.subscribe((lureEvent) =>
|
||||
{
|
||||
bot.clientCommands.grid.getRegionMapInfo(lureEvent.gridX, lureEvent.gridY).then((regionInfo) =>
|
||||
{
|
||||
console.log('Auto-accepting teleport lure to ' + regionInfo.name + ' (' + regionInfo.avatars.length + ' avatar' + ((regionInfo.avatars.length === 1)?'':'s') + ' present) from ' + lureEvent.fromName + ' with message: ' + lureEvent.lureMessage);
|
||||
//bot.clientCommands.teleport.acceptTeleport(lureEvent);
|
||||
});
|
||||
});
|
||||
|
||||
bot.clientEvents.onInstantMessage.subscribe((IMEvent) =>
|
||||
{
|
||||
if (IMEvent.source === nmv.ChatSourceType.Agent)
|
||||
{
|
||||
if (!(IMEvent.flags & nmv.InstantMessageEventFlags.startTyping || IMEvent.flags & nmv.InstantMessageEventFlags.finishTyping))
|
||||
{
|
||||
bot.clientCommands.comms.typeInstantMessage(IMEvent.from, 'Thanks for the message! This account is a scripted agent (bot), so cannot reply to your query. Sorry!');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bot.clientEvents.onDisconnected.subscribe((DisconnectEvent) =>
|
||||
{
|
||||
console.log("Disconnected from simulator: "+DisconnectEvent.message);
|
||||
if (!DisconnectEvent.requested)
|
||||
{
|
||||
setTimeout(() =>
|
||||
{
|
||||
console.log("Reconnecting");
|
||||
connect();
|
||||
}, 5000)
|
||||
}
|
||||
});
|
||||
console.log("Login complete");
|
||||
|
||||
//Establish circuit wit region
|
||||
resp = response;
|
||||
|
||||
30
lib/Bot.ts
30
lib/Bot.ts
@@ -24,6 +24,7 @@ import {KickUserMessage} from './classes/messages/KickUser';
|
||||
import {StartPingCheckMessage} from './classes/messages/StartPingCheck';
|
||||
import {CompletePingCheckMessage} from './classes/messages/CompletePingCheck';
|
||||
import Timer = NodeJS.Timer;
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
|
||||
export class Bot
|
||||
{
|
||||
@@ -33,11 +34,13 @@ export class Bot
|
||||
private ping: Timer | null = null;
|
||||
private pingNumber = 0;
|
||||
private lastSuccessfulPing = 0;
|
||||
public clientEvents: ClientEvents | null = null;
|
||||
private circuitSubscription: Subscription | null = null
|
||||
public clientEvents: ClientEvents;
|
||||
public clientCommands: ClientCommands;
|
||||
|
||||
constructor(login: LoginParameters)
|
||||
{
|
||||
this.clientEvents = new ClientEvents();
|
||||
this.loginParams = login;
|
||||
}
|
||||
|
||||
@@ -45,10 +48,9 @@ export class Bot
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
const loginHandler = new LoginHandler();
|
||||
const loginHandler = new LoginHandler(this.clientEvents);
|
||||
loginHandler.Login(this.loginParams).then((response: LoginResponse) =>
|
||||
{
|
||||
this.clientEvents = response.clientEvents;
|
||||
this.currentRegion = response.region;
|
||||
this.agent = response.agent;
|
||||
this.clientCommands = new ClientCommands(response.region, response.agent, this);
|
||||
@@ -66,6 +68,11 @@ export class Bot
|
||||
{
|
||||
this.currentRegion = region;
|
||||
this.clientCommands = new ClientCommands(this.currentRegion, this.agent, this);
|
||||
if (this.ping !== null)
|
||||
{
|
||||
clearInterval(this.ping);
|
||||
this.ping = null;
|
||||
}
|
||||
this.connectToSim().then(() =>
|
||||
{
|
||||
resolve();
|
||||
@@ -97,6 +104,11 @@ export class Bot
|
||||
{
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
if (this.circuitSubscription !== null)
|
||||
{
|
||||
this.circuitSubscription.unsubscribe();
|
||||
this.circuitSubscription = null;
|
||||
}
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
@@ -208,6 +220,11 @@ export class Bot
|
||||
// We're dead, jim
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
if (this.circuitSubscription !== null)
|
||||
{
|
||||
this.circuitSubscription.unsubscribe();
|
||||
this.circuitSubscription = null;
|
||||
}
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
@@ -228,7 +245,7 @@ export class Bot
|
||||
|
||||
}, 5000);
|
||||
|
||||
circuit.subscribeToMessages(
|
||||
this.circuitSubscription = circuit.subscribeToMessages(
|
||||
[
|
||||
Message.TeleportFailed,
|
||||
Message.TeleportFinish,
|
||||
@@ -305,6 +322,11 @@ export class Bot
|
||||
const kickUser = packet.message as KickUserMessage;
|
||||
this.agent.shutdown();
|
||||
this.currentRegion.shutdown();
|
||||
if (this.circuitSubscription !== null)
|
||||
{
|
||||
this.circuitSubscription.unsubscribe();
|
||||
this.circuitSubscription = null;
|
||||
}
|
||||
delete this.currentRegion;
|
||||
delete this.agent;
|
||||
delete this.clientCommands;
|
||||
|
||||
@@ -2,10 +2,13 @@ import * as xmlrpc from 'xmlrpc';
|
||||
import * as crypto from 'crypto';
|
||||
import {LoginParameters} from './classes/LoginParameters';
|
||||
import {LoginResponse} from './classes/LoginResponse';
|
||||
import {ClientEvents} from './classes/ClientEvents';
|
||||
const uuid = require('uuid');
|
||||
|
||||
export class LoginHandler
|
||||
{
|
||||
private clientEvents: ClientEvents;
|
||||
|
||||
static GenerateMAC(): string
|
||||
{
|
||||
const hexDigits = '0123456789ABCDEF';
|
||||
@@ -22,6 +25,12 @@ export class LoginHandler
|
||||
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
constructor(ce: ClientEvents)
|
||||
{
|
||||
this.clientEvents = ce;
|
||||
}
|
||||
|
||||
Login(params: LoginParameters): Promise<LoginResponse>
|
||||
{
|
||||
return new Promise<LoginResponse>((resolve, reject) =>
|
||||
@@ -38,7 +47,7 @@ export class LoginHandler
|
||||
{
|
||||
'first': params.firstName,
|
||||
'last': params.lastName,
|
||||
'passwd': '$1$' + crypto.createHash('md5').update(params.password).digest('hex'),
|
||||
'passwd': '$1$' + crypto.createHash('md5').update(params.password.substr(0, 16)).digest('hex'),
|
||||
'start': 'home',
|
||||
'major': '0',
|
||||
'minor': '0',
|
||||
@@ -65,7 +74,7 @@ export class LoginHandler
|
||||
'global-textures'
|
||||
]
|
||||
}
|
||||
], function(error, value)
|
||||
], (error, value) =>
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
@@ -79,9 +88,8 @@ export class LoginHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
const response = new LoginResponse(value);
|
||||
const response = new LoginResponse(value, this.clientEvents);
|
||||
resolve(response);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ export class Comms
|
||||
{
|
||||
case InstantMessageDialog.MessageFromAgent:
|
||||
{
|
||||
console.log(im);
|
||||
const imEvent = new InstantMessageEvent();
|
||||
imEvent.source = ChatSourceType.Agent;
|
||||
imEvent.from = im.AgentData.AgentID;
|
||||
@@ -69,7 +68,6 @@ export class Comms
|
||||
break;
|
||||
case InstantMessageDialog.MessageFromObject:
|
||||
{
|
||||
console.log(im);
|
||||
const imEvent = new InstantMessageEvent();
|
||||
imEvent.source = ChatSourceType.Object;
|
||||
imEvent.owner = im.AgentData.AgentID;
|
||||
|
||||
@@ -88,9 +88,9 @@ export class LoginResponse
|
||||
return result;
|
||||
}
|
||||
|
||||
constructor(json: any)
|
||||
constructor(json: any, ce: ClientEvents)
|
||||
{
|
||||
this.clientEvents = new ClientEvents();
|
||||
this.clientEvents = ce;
|
||||
this.agent = new Agent(this.clientEvents);
|
||||
this.region = new Region(this.agent, this.clientEvents);
|
||||
Object.keys(json).forEach((key: string) =>
|
||||
|
||||
@@ -15,18 +15,18 @@ import {Vector3} from './Vector3';
|
||||
import {CompressedFlags} from '../enums/CompressedFlags';
|
||||
import {ExtraParamType} from '../enums/ExtraParamType';
|
||||
import {Utils} from './Utils';
|
||||
import {SoundFlags} from '../enums/SoundFlags';
|
||||
import {PCode} from '../enums/PCode';
|
||||
import {NameValue} from "./NameValue";
|
||||
import {ClientEvents} from "./ClientEvents";
|
||||
import {NameValue} from './NameValue';
|
||||
import {ClientEvents} from './ClientEvents';
|
||||
import {KillObjectMessage} from './messages/KillObject';
|
||||
|
||||
export class ObjectStore
|
||||
{
|
||||
private circuit: Circuit;
|
||||
private agent: Agent;
|
||||
private objects: {[key: number]: GameObject} = {};
|
||||
private objectsByUUID: {[key: string]: number} = {};
|
||||
private objectsByParent: {[key: number]: number[]} = {};
|
||||
private objects: { [key: number]: GameObject } = {};
|
||||
private objectsByUUID: { [key: string]: number } = {};
|
||||
private objectsByParent: { [key: number]: number[] } = {};
|
||||
private clientEvents: ClientEvents;
|
||||
|
||||
constructor(circuit: Circuit, agent: Agent, clientEvents: ClientEvents)
|
||||
@@ -35,11 +35,12 @@ export class ObjectStore
|
||||
this.circuit = circuit;
|
||||
this.agent = agent;
|
||||
this.circuit.subscribeToMessages([
|
||||
Message.ObjectUpdate,
|
||||
Message.ObjectUpdateCached,
|
||||
Message.ObjectUpdateCompressed,
|
||||
Message.ImprovedTerseObjectUpdate,
|
||||
Message.MultipleObjectUpdate
|
||||
Message.ObjectUpdate,
|
||||
Message.ObjectUpdateCached,
|
||||
Message.ObjectUpdateCompressed,
|
||||
Message.ImprovedTerseObjectUpdate,
|
||||
Message.MultipleObjectUpdate,
|
||||
Message.KillObject
|
||||
], (packet: Packet) =>
|
||||
{
|
||||
switch (packet.message.id)
|
||||
@@ -148,8 +149,8 @@ export class ObjectStore
|
||||
objectUpdateCached.ObjectData.forEach((obj) =>
|
||||
{
|
||||
rmo.ObjectData.push({
|
||||
CacheMissType: 0,
|
||||
ID: obj.ID
|
||||
CacheMissType: 0,
|
||||
ID: obj.ID
|
||||
});
|
||||
});
|
||||
circuit.sendMessage(rmo, 0);
|
||||
@@ -342,9 +343,53 @@ export class ObjectStore
|
||||
// TODO: multipleObjectUpdate
|
||||
console.error('TODO: MultipleObjectUpdate');
|
||||
break;
|
||||
case Message.KillObject:
|
||||
const killObj = packet.message as KillObjectMessage;
|
||||
killObj.ObjectData.forEach((obj) =>
|
||||
{
|
||||
const objectID = obj.ID;
|
||||
this.deleteObject(objectID);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
deleteObject(objectID: number)
|
||||
{
|
||||
if (this.objects[objectID])
|
||||
{
|
||||
// First, kill all children
|
||||
if (this.objectsByParent[objectID])
|
||||
{
|
||||
this.objectsByParent[objectID].forEach((childObjID) =>
|
||||
{
|
||||
this.deleteObject(childObjID);
|
||||
});
|
||||
}
|
||||
delete this.objectsByParent[objectID];
|
||||
|
||||
// Now delete this object
|
||||
const objct = this.objects[objectID];
|
||||
const uuid = objct.FullID.toString();
|
||||
|
||||
if (this.objectsByUUID[uuid])
|
||||
{
|
||||
delete this.objectsByUUID[uuid];
|
||||
}
|
||||
const parentID = objct.ParentID;
|
||||
if (this.objectsByParent[parentID])
|
||||
{
|
||||
const ind = this.objectsByParent[parentID].indexOf(objectID);
|
||||
if (ind !== -1)
|
||||
{
|
||||
this.objectsByParent[parentID].splice(ind, 1);
|
||||
}
|
||||
}
|
||||
delete this.objects[objectID];
|
||||
}
|
||||
}
|
||||
|
||||
readExtraParams(buf: Buffer, pos: number, o: GameObject): number
|
||||
{
|
||||
if (pos >= buf.length)
|
||||
@@ -364,6 +409,7 @@ export class ObjectStore
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
getObjectsByParent(parentID: number): GameObject[]
|
||||
{
|
||||
const list = this.objectsByParent[parentID];
|
||||
@@ -378,9 +424,10 @@ export class ObjectStore
|
||||
});
|
||||
return result;
|
||||
}
|
||||
parseNameValues(str: string): {[key: string]: NameValue}
|
||||
|
||||
parseNameValues(str: string): { [key: string]: NameValue }
|
||||
{
|
||||
const nv: {[key: string]: NameValue} = {};
|
||||
const nv: { [key: string]: NameValue } = {};
|
||||
const lines = str.split('\n');
|
||||
lines.forEach((line) =>
|
||||
{
|
||||
@@ -389,7 +436,7 @@ export class ObjectStore
|
||||
let kv = line.split(/[\t ]/);
|
||||
if (kv.length > 5)
|
||||
{
|
||||
for(let x = 5; x < kv.length; x++)
|
||||
for (let x = 5; x < kv.length; x++)
|
||||
{
|
||||
kv[4] += ' ' + kv[x];
|
||||
}
|
||||
@@ -413,6 +460,7 @@ export class ObjectStore
|
||||
});
|
||||
return nv;
|
||||
}
|
||||
|
||||
shutdown()
|
||||
{
|
||||
this.objects = {};
|
||||
|
||||
Reference in New Issue
Block a user