Receive and respond to friend requests and inventory offers

This commit is contained in:
Casper Warden
2017-12-19 19:59:06 +00:00
parent 6cbe790657
commit 70fd5a99ce
23 changed files with 382 additions and 11 deletions

View File

@@ -9,6 +9,7 @@ import {DisconnectEvent} from '../events/DisconnectEvent';
import {GroupChatEvent} from '../events/GroupChatEvent';
import {GroupChatSessionJoinEvent} from '../events/GroupChatSessionJoinEvent';
import {GroupChatSessionAgentListEvent} from '../events/GroupChatSessionAgentListEvent';
import {InventoryOfferedEvent} from '../events/InventoryOfferedEvent';
export class ClientEvents
{
@@ -16,6 +17,7 @@ export class ClientEvents
onInstantMessage: Subject<InstantMessageEvent> = new Subject<InstantMessageEvent>();
onGroupInvite: Subject<GroupInviteEvent> = new Subject<GroupInviteEvent>();
onFriendRequest: Subject<FriendRequestEvent> = new Subject<FriendRequestEvent>();
onInventoryOffered: Subject<InventoryOfferedEvent> = new Subject<InventoryOfferedEvent>();
onLure: Subject<LureEvent> = new Subject<LureEvent>();
onTeleportEvent: Subject<TeleportEvent> = new Subject<TeleportEvent>();
onDisconnected: Subject<DisconnectEvent> = new Subject<DisconnectEvent>();

View File

@@ -15,6 +15,8 @@ import {ChatSourceType} from '../enums/ChatSourceType';
import {InstantMessageEventFlags} from '../enums/InstantMessageEventFlags';
import {GroupInviteEvent} from '../events/GroupInviteEvent';
import {GroupChatEvent} from '../events/GroupChatEvent';
import {FriendRequestEvent} from '../events/FriendRequestEvent';
import {InventoryOfferedEvent} from '../events/InventoryOfferedEvent';
export class Comms
{
@@ -63,13 +65,38 @@ export class Comms
this.clientEvents.onGroupInvite.next(giEvent);
break;
case InstantMessageDialog.InventoryOffered:
{
const fromName = Utils.BufferToStringSimple(im.MessageBlock.FromAgentName);
const message = Utils.BufferToStringSimple(im.MessageBlock.Message);
const ioEvent = new InventoryOfferedEvent();
ioEvent.from = im.AgentData.AgentID;
ioEvent.fromName = fromName;
ioEvent.message = message;
ioEvent.requestID = im.MessageBlock.ID;
ioEvent.source = ChatSourceType.Agent;
this.clientEvents.onInventoryOffered.next(ioEvent);
break;
}
case InstantMessageDialog.InventoryAccepted:
break;
case InstantMessageDialog.InventoryDeclined:
break;
case InstantMessageDialog.TaskInventoryOffered:
{
const fromName = Utils.BufferToStringSimple(im.MessageBlock.FromAgentName);
const message = Utils.BufferToStringSimple(im.MessageBlock.Message);
const ioEvent = new InventoryOfferedEvent();
ioEvent.from = im.AgentData.AgentID;
ioEvent.fromName = fromName;
ioEvent.message = message;
ioEvent.requestID = im.MessageBlock.ID;
ioEvent.source = ChatSourceType.Object;
ioEvent.type = im.MessageBlock.BinaryBucket.readUInt8(0);
this.clientEvents.onInventoryOffered.next(ioEvent);
break;
}
case InstantMessageDialog.TaskInventoryAccepted:
break;
case InstantMessageDialog.TaskInventoryDeclined:
@@ -136,7 +163,19 @@ export class Comms
case InstantMessageDialog.GroupNoticeRequested:
break;
case InstantMessageDialog.FriendshipOffered:
{
const fromName = Utils.BufferToStringSimple(im.MessageBlock.FromAgentName);
const message = Utils.BufferToStringSimple(im.MessageBlock.Message);
const frEvent = new FriendRequestEvent();
frEvent.from = im.AgentData.AgentID;
frEvent.fromName = fromName;
frEvent.message = message;
frEvent.requestID = im.MessageBlock.ID;
this.clientEvents.onFriendRequest.next(frEvent);
break;
}
case InstantMessageDialog.FriendshipAccepted:
break;
case InstantMessageDialog.FriendshipDeclined:

View File

@@ -1,11 +1,12 @@
import {UUID} from './UUID';
import {ClientEvents} from './ClientEvents';
import {AssetType} from '../enums/AssetType';
export class Inventory
{
main: {
skeleton: {
typeDefault: number,
typeDefault: AssetType,
version: number,
name: string,
folderID: UUID,
@@ -34,4 +35,24 @@ export class Inventory
{
this.clientEvents = clientEvents;
}
findFolderForType(type: AssetType): UUID
{
if (this.main.root === undefined)
{
return UUID.zero();
}
if (type === AssetType.Folder)
{
return this.main.root;
}
let found = UUID.zero();
this.main.skeleton.forEach((folder) =>
{
if (folder.typeDefault === type)
{
found = folder.folderID;
}
});
return found;
}
}

View File

@@ -9,6 +9,12 @@ import {ChatType} from '../../enums/ChatType';
import {InstantMessageDialog} from '../../enums/InstantMessageDialog';
import Timer = NodeJS.Timer;
import {GroupChatSessionJoinEvent} from '../../events/GroupChatSessionJoinEvent';
import {FriendRequestEvent} from '../../events/FriendRequestEvent';
import {AcceptFriendshipMessage} from '../messages/AcceptFriendship';
import {AssetType} from '../../enums/AssetType';
import {DeclineFriendshipMessage} from '../messages/DeclineFriendship';
import {InventoryOfferedEvent} from '../../events/InventoryOfferedEvent';
import {ChatSourceType} from '../../enums/ChatSourceType';
export class CommunicationsCommands extends CommandsBase
{
@@ -358,6 +364,98 @@ export class CommunicationsCommands extends CommandsBase
});
}
acceptFriendRequest(event: FriendRequestEvent): Promise<void>
{
const accept: AcceptFriendshipMessage = new AcceptFriendshipMessage();
accept.AgentData = {
AgentID: this.agent.agentID,
SessionID: this.circuit.sessionID
};
accept.TransactionBlock = {
TransactionID: event.requestID
};
accept.FolderData = [];
accept.FolderData.push(
{
'FolderID': this.agent.inventory.findFolderForType(AssetType.CallingCard)
}
);
const sequenceNo = this.circuit.sendMessage(accept, PacketFlags.Reliable);
return this.circuit.waitForAck(sequenceNo, 10000);
}
private respondToInventoryOffer(event: InventoryOfferedEvent, response: InstantMessageDialog): Promise<void>
{
const agentName = this.agent.firstName + ' ' + this.agent.lastName;
const im: ImprovedInstantMessageMessage = new ImprovedInstantMessageMessage();
const folder = this.agent.inventory.findFolderForType(event.type);
const binary = Buffer.allocUnsafe(16);
folder.writeToBuffer(binary, 0);
im.AgentData = {
AgentID: this.agent.agentID,
SessionID: this.circuit.sessionID
};
im.MessageBlock = {
FromGroup: false,
ToAgentID: event.from,
ParentEstateID: 0,
RegionID: UUID.zero(),
Position: Vector3.getZero(),
Offline: 0,
Dialog: response,
ID: event.requestID,
Timestamp: Math.floor(new Date().getTime() / 1000),
FromAgentName: Utils.StringToBuffer(agentName),
Message: Utils.StringToBuffer(''),
BinaryBucket: binary
};
im.EstateBlock = {
EstateID: 0
};
const sequenceNo = this.circuit.sendMessage(im, PacketFlags.Reliable);
return this.circuit.waitForAck(sequenceNo, 10000);
}
acceptInventoryOffer(event: InventoryOfferedEvent): Promise<void>
{
if (event.source === ChatSourceType.Object)
{
return this.respondToInventoryOffer(event, InstantMessageDialog.TaskInventoryAccepted);
}
else
{
return this.respondToInventoryOffer(event, InstantMessageDialog.InventoryAccepted);
}
}
rejectInventoryOffer(event: InventoryOfferedEvent): Promise<void>
{
if (event.source === ChatSourceType.Object)
{
return this.respondToInventoryOffer(event, InstantMessageDialog.TaskInventoryDeclined);
}
else
{
return this.respondToInventoryOffer(event, InstantMessageDialog.InventoryDeclined);
}
}
rejectFriendRequest(event: FriendRequestEvent): Promise<void>
{
const reject: DeclineFriendshipMessage = new DeclineFriendshipMessage();
reject.AgentData = {
AgentID: this.agent.agentID,
SessionID: this.circuit.sessionID
};
reject.TransactionBlock = {
TransactionID: event.requestID
};
const sequenceNo = this.circuit.sendMessage(reject, PacketFlags.Reliable);
return this.circuit.waitForAck(sequenceNo, 10000);
}
sendGroupMessage(groupID: UUID | string, message: string): Promise<number>
{
return new Promise<number>((resolve, reject) =>