Cleaning up pusher
This commit is contained in:
parent
f40d8024f2
commit
ff17cb99d6
@ -1,138 +0,0 @@
|
|||||||
import { ConnectCallback, DisconnectCallback } from "./PusherRoom";
|
|
||||||
import { User } from "./User";
|
|
||||||
import {PositionInterface} from "_Model/PositionInterface";
|
|
||||||
import {Movable} from "_Model/Movable";
|
|
||||||
import {PositionDispatcher} from "_Model/PositionDispatcher";
|
|
||||||
import {gaugeManager} from "../Services/GaugeManager";
|
|
||||||
|
|
||||||
export class Group implements Movable {
|
|
||||||
static readonly MAX_PER_GROUP = 4;
|
|
||||||
|
|
||||||
private static nextId: number = 1;
|
|
||||||
|
|
||||||
private id: number;
|
|
||||||
private users: Set<User>;
|
|
||||||
private x!: number;
|
|
||||||
private y!: number;
|
|
||||||
private hasEditedGauge: boolean = false;
|
|
||||||
private wasDestroyed: boolean = false;
|
|
||||||
private roomId: string;
|
|
||||||
|
|
||||||
|
|
||||||
constructor(roomId: string, users: User[], private connectCallback: ConnectCallback, private disconnectCallback: DisconnectCallback, private positionNotifier: PositionDispatcher) {
|
|
||||||
this.roomId = roomId;
|
|
||||||
this.users = new Set<User>();
|
|
||||||
this.id = Group.nextId;
|
|
||||||
Group.nextId++;
|
|
||||||
//we only send a event for prometheus metrics if the group lives more than 5 seconds
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!this.wasDestroyed) {
|
|
||||||
this.hasEditedGauge = true;
|
|
||||||
gaugeManager.incNbGroupsPerRoomGauge(roomId);
|
|
||||||
}
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
users.forEach((user: User) => {
|
|
||||||
this.join(user);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
getUsers(): User[] {
|
|
||||||
return Array.from(this.users.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
getId() : number {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the barycenter of all users (i.e. the center of the group)
|
|
||||||
*/
|
|
||||||
getPosition(): PositionInterface {
|
|
||||||
return {
|
|
||||||
x: this.x,
|
|
||||||
y: this.y
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes the barycenter of all users (i.e. the center of the group)
|
|
||||||
*/
|
|
||||||
updatePosition(): void {
|
|
||||||
const oldX = this.x;
|
|
||||||
const oldY = this.y;
|
|
||||||
|
|
||||||
let x = 0;
|
|
||||||
let y = 0;
|
|
||||||
// Let's compute the barycenter of all users.
|
|
||||||
this.users.forEach((user: User) => {
|
|
||||||
const position = user.getPosition();
|
|
||||||
x += position.x;
|
|
||||||
y += position.y;
|
|
||||||
});
|
|
||||||
x /= this.users.size;
|
|
||||||
y /= this.users.size;
|
|
||||||
if (this.users.size === 0) {
|
|
||||||
throw new Error("EMPTY GROUP FOUND!!!");
|
|
||||||
}
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
|
|
||||||
if (oldX === undefined) {
|
|
||||||
this.positionNotifier.enter(this);
|
|
||||||
} else {
|
|
||||||
this.positionNotifier.updatePosition(this, {x, y}, {x: oldX, y: oldY});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isFull(): boolean {
|
|
||||||
return this.users.size >= Group.MAX_PER_GROUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
isEmpty(): boolean {
|
|
||||||
return this.users.size <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
join(user: User): void
|
|
||||||
{
|
|
||||||
// Broadcast on the right event
|
|
||||||
this.connectCallback(user, this);
|
|
||||||
this.users.add(user);
|
|
||||||
user.group = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
leave(user: User): void
|
|
||||||
{
|
|
||||||
const success = this.users.delete(user);
|
|
||||||
if (success === false) {
|
|
||||||
throw new Error("Could not find user "+user.id+" in the group "+this.id);
|
|
||||||
}
|
|
||||||
user.group = undefined;
|
|
||||||
|
|
||||||
if (this.users.size !== 0) {
|
|
||||||
this.updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Broadcast on the right event
|
|
||||||
this.disconnectCallback(user, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Let's kick everybody out.
|
|
||||||
* Usually used when there is only one user left.
|
|
||||||
*/
|
|
||||||
destroy(): void
|
|
||||||
{
|
|
||||||
if (this.hasEditedGauge) gaugeManager.decNbGroupsPerRoomGauge(this.roomId);
|
|
||||||
for (const user of this.users) {
|
|
||||||
this.leave(user);
|
|
||||||
}
|
|
||||||
this.wasDestroyed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get getSize(){
|
|
||||||
return this.users.size;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,10 @@
|
|||||||
import {PointInterface} from "./Websocket/PointInterface";
|
|
||||||
import {Group} from "./Group";
|
|
||||||
import {User} from "./User";
|
|
||||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
||||||
import {PositionInterface} from "_Model/PositionInterface";
|
|
||||||
import {Identificable} from "_Model/Websocket/Identificable";
|
|
||||||
import {PositionDispatcher} from "./PositionDispatcher";
|
import {PositionDispatcher} from "./PositionDispatcher";
|
||||||
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
||||||
import {Movable} from "_Model/Movable";
|
|
||||||
import {extractDataFromPrivateRoomId, extractRoomSlugPublicRoomId, isRoomAnonymous} from "./RoomIdentifier";
|
import {extractDataFromPrivateRoomId, extractRoomSlugPublicRoomId, isRoomAnonymous} from "./RoomIdentifier";
|
||||||
import {arrayIntersect} from "../Services/ArrayHelper";
|
import {arrayIntersect} from "../Services/ArrayHelper";
|
||||||
import {MAX_USERS_PER_ROOM} from "../Enum/EnvironmentVariable";
|
|
||||||
import {ZoneEventListener} from "_Model/Zone";
|
import {ZoneEventListener} from "_Model/Zone";
|
||||||
|
|
||||||
export type ConnectCallback = (user: User, group: Group) => void;
|
|
||||||
export type DisconnectCallback = (user: User, group: Group) => void;
|
|
||||||
|
|
||||||
export enum GameRoomPolicyTypes {
|
export enum GameRoomPolicyTypes {
|
||||||
ANONYMUS_POLICY = 1,
|
ANONYMUS_POLICY = 1,
|
||||||
MEMBERS_ONLY_POLICY,
|
MEMBERS_ONLY_POLICY,
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
import { Group } from "./Group";
|
|
||||||
import { PointInterface } from "./Websocket/PointInterface";
|
|
||||||
import {Zone} from "_Model/Zone";
|
|
||||||
import {Movable} from "_Model/Movable";
|
|
||||||
import {PositionInterface} from "_Model/PositionInterface";
|
|
||||||
import {PositionDispatcher} from "_Model/PositionDispatcher";
|
|
||||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
|
||||||
|
|
||||||
export class User implements Movable {
|
|
||||||
public listenedZones: Set<Zone>;
|
|
||||||
public group?: Group;
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
public id: number,
|
|
||||||
public uuid: string,
|
|
||||||
private position: PointInterface,
|
|
||||||
public silent: boolean,
|
|
||||||
private positionNotifier: PositionDispatcher,
|
|
||||||
public readonly socket: ExSocketInterface
|
|
||||||
) {
|
|
||||||
this.listenedZones = new Set<Zone>();
|
|
||||||
|
|
||||||
this.positionNotifier.enter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getPosition(): PointInterface {
|
|
||||||
return this.position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setPosition(position: PointInterface): void {
|
|
||||||
const oldPosition = this.position;
|
|
||||||
this.position = position;
|
|
||||||
this.positionNotifier.updatePosition(this, position, oldPosition);
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,9 +26,7 @@ import {
|
|||||||
SendUserMessage, JoinRoomMessage, CharacterLayerMessage, PusherToBackMessage
|
SendUserMessage, JoinRoomMessage, CharacterLayerMessage, PusherToBackMessage
|
||||||
} from "../Messages/generated/messages_pb";
|
} from "../Messages/generated/messages_pb";
|
||||||
import {PointInterface} from "../Model/Websocket/PointInterface";
|
import {PointInterface} from "../Model/Websocket/PointInterface";
|
||||||
import {User} from "../Model/User";
|
|
||||||
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
|
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
|
||||||
import {Group} from "../Model/Group";
|
|
||||||
import {cpuTracker} from "./CpuTracker";
|
import {cpuTracker} from "./CpuTracker";
|
||||||
import {GROUP_RADIUS, JITSI_ISS, MINIMUM_DISTANCE, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable";
|
import {GROUP_RADIUS, JITSI_ISS, MINIMUM_DISTANCE, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable";
|
||||||
import {Movable} from "../Model/Movable";
|
import {Movable} from "../Model/Movable";
|
||||||
@ -477,119 +475,6 @@ export class SocketManager implements ZoneEventListener {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
private emitCreateUpdateGroupEvent(client: ExSocketInterface, group: Group): void {
|
|
||||||
const position = group.getPosition();
|
|
||||||
const pointMessage = new PointMessage();
|
|
||||||
pointMessage.setX(Math.floor(position.x));
|
|
||||||
pointMessage.setY(Math.floor(position.y));
|
|
||||||
const groupUpdateMessage = new GroupUpdateMessage();
|
|
||||||
groupUpdateMessage.setGroupid(group.getId());
|
|
||||||
groupUpdateMessage.setPosition(pointMessage);
|
|
||||||
groupUpdateMessage.setGroupsize(group.getSize);
|
|
||||||
|
|
||||||
const subMessage = new SubMessage();
|
|
||||||
subMessage.setGroupupdatemessage(groupUpdateMessage);
|
|
||||||
|
|
||||||
emitInBatch(client, subMessage);
|
|
||||||
//socket.emit(SocketIoEvent.GROUP_CREATE_UPDATE, groupUpdateMessage.serializeBinary().buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private emitDeleteGroupEvent(client: ExSocketInterface, groupId: number): void {
|
|
||||||
const groupDeleteMessage = new GroupDeleteMessage();
|
|
||||||
groupDeleteMessage.setGroupid(groupId);
|
|
||||||
|
|
||||||
const subMessage = new SubMessage();
|
|
||||||
subMessage.setGroupdeletemessage(groupDeleteMessage);
|
|
||||||
|
|
||||||
emitInBatch(client, subMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private emitUserLeftEvent(client: ExSocketInterface, userId: number): void {
|
|
||||||
const userLeftMessage = new UserLeftMessage();
|
|
||||||
userLeftMessage.setUserid(userId);
|
|
||||||
|
|
||||||
const subMessage = new SubMessage();
|
|
||||||
subMessage.setUserleftmessage(userLeftMessage);
|
|
||||||
|
|
||||||
emitInBatch(client, subMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private joinWebRtcRoom(user: User, group: Group) {
|
|
||||||
/*const roomId: string = "webrtcroom"+group.getId();
|
|
||||||
if (user.socket.webRtcRoomId === roomId) {
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
for (const otherUser of group.getUsers()) {
|
|
||||||
if (user === otherUser) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let's send 2 messages: one to the user joining the group and one to the other user
|
|
||||||
const webrtcStartMessage1 = new WebRtcStartMessage();
|
|
||||||
webrtcStartMessage1.setUserid(otherUser.id);
|
|
||||||
webrtcStartMessage1.setName(otherUser.socket.name);
|
|
||||||
webrtcStartMessage1.setInitiator(true);
|
|
||||||
|
|
||||||
const serverToClientMessage1 = new ServerToClientMessage();
|
|
||||||
serverToClientMessage1.setWebrtcstartmessage(webrtcStartMessage1);
|
|
||||||
|
|
||||||
if (!user.socket.disconnecting) {
|
|
||||||
user.socket.send(serverToClientMessage1.serializeBinary().buffer, true);
|
|
||||||
//console.log('Sending webrtcstart initiator to '+user.socket.userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
const webrtcStartMessage2 = new WebRtcStartMessage();
|
|
||||||
webrtcStartMessage2.setUserid(user.id);
|
|
||||||
webrtcStartMessage2.setName(user.socket.name);
|
|
||||||
webrtcStartMessage2.setInitiator(false);
|
|
||||||
|
|
||||||
const serverToClientMessage2 = new ServerToClientMessage();
|
|
||||||
serverToClientMessage2.setWebrtcstartmessage(webrtcStartMessage2);
|
|
||||||
|
|
||||||
if (!otherUser.socket.disconnecting) {
|
|
||||||
otherUser.socket.send(serverToClientMessage2.serializeBinary().buffer, true);
|
|
||||||
//console.log('Sending webrtcstart to '+otherUser.socket.userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//disconnect user
|
|
||||||
private disConnectedUser(user: User, group: Group) {
|
|
||||||
// Most of the time, sending a disconnect event to one of the players is enough (the player will close the connection
|
|
||||||
// which will be shut for the other player).
|
|
||||||
// However! In the rare case where the WebRTC connection is not yet established, if we close the connection on one of the player,
|
|
||||||
// the other player will try connecting until a timeout happens (during this time, the connection icon will be displayed for nothing).
|
|
||||||
// So we also send the disconnect event to the other player.
|
|
||||||
for (const otherUser of group.getUsers()) {
|
|
||||||
if (user === otherUser) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const webrtcDisconnectMessage1 = new WebRtcDisconnectMessage();
|
|
||||||
webrtcDisconnectMessage1.setUserid(user.id);
|
|
||||||
|
|
||||||
const serverToClientMessage1 = new ServerToClientMessage();
|
|
||||||
serverToClientMessage1.setWebrtcdisconnectmessage(webrtcDisconnectMessage1);
|
|
||||||
|
|
||||||
if (!otherUser.socket.disconnecting) {
|
|
||||||
otherUser.socket.send(serverToClientMessage1.serializeBinary().buffer, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const webrtcDisconnectMessage2 = new WebRtcDisconnectMessage();
|
|
||||||
webrtcDisconnectMessage2.setUserid(otherUser.id);
|
|
||||||
|
|
||||||
const serverToClientMessage2 = new ServerToClientMessage();
|
|
||||||
serverToClientMessage2.setWebrtcdisconnectmessage(webrtcDisconnectMessage2);
|
|
||||||
|
|
||||||
if (!user.socket.disconnecting) {
|
|
||||||
user.socket.send(serverToClientMessage2.serializeBinary().buffer, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emitPlayGlobalMessage(client: ExSocketInterface, playglobalmessage: PlayGlobalMessage) {
|
emitPlayGlobalMessage(client: ExSocketInterface, playglobalmessage: PlayGlobalMessage) {
|
||||||
const pusherToBackMessage = new PusherToBackMessage();
|
const pusherToBackMessage = new PusherToBackMessage();
|
||||||
pusherToBackMessage.setPlayglobalmessage(playglobalmessage);
|
pusherToBackMessage.setPlayglobalmessage(playglobalmessage);
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
import "jasmine";
|
|
||||||
import {PusherRoom, ConnectCallback, DisconnectCallback } from "_Model/PusherRoom";
|
|
||||||
import {Point} from "_Model/Websocket/Point";
|
|
||||||
import { Group } from "../src/Model/Group";
|
|
||||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
|
||||||
import {User} from "_Model/User";
|
|
||||||
|
|
||||||
function createMockUser(userId: number): ExSocketInterface {
|
|
||||||
return {
|
|
||||||
userId
|
|
||||||
} as ExSocketInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("GameRoom", () => {
|
|
||||||
it("should connect user1 and user2", () => {
|
|
||||||
let connectCalledNumber: number = 0;
|
|
||||||
const connect: ConnectCallback = (user: User, group: Group): void => {
|
|
||||||
connectCalledNumber++;
|
|
||||||
}
|
|
||||||
const disconnect: DisconnectCallback = (user: User, group: Group): void => {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const world = new PusherRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
|
||||||
|
|
||||||
world.join(createMockUser(1), new Point(100, 100));
|
|
||||||
|
|
||||||
world.join(createMockUser(2), new Point(500, 100));
|
|
||||||
|
|
||||||
world.updatePosition({ userId: 2 }, new Point(261, 100));
|
|
||||||
|
|
||||||
expect(connectCalledNumber).toBe(0);
|
|
||||||
|
|
||||||
world.updatePosition({ userId: 2 }, new Point(101, 100));
|
|
||||||
|
|
||||||
expect(connectCalledNumber).toBe(2);
|
|
||||||
|
|
||||||
world.updatePosition({ userId: 2 }, new Point(102, 100));
|
|
||||||
expect(connectCalledNumber).toBe(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should connect 3 users", () => {
|
|
||||||
let connectCalled: boolean = false;
|
|
||||||
const connect: ConnectCallback = (user: User, group: Group): void => {
|
|
||||||
connectCalled = true;
|
|
||||||
}
|
|
||||||
const disconnect: DisconnectCallback = (user: User, group: Group): void => {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const world = new PusherRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
|
||||||
|
|
||||||
world.join(createMockUser(1), new Point(100, 100));
|
|
||||||
|
|
||||||
world.join(createMockUser(2), new Point(200, 100));
|
|
||||||
|
|
||||||
expect(connectCalled).toBe(true);
|
|
||||||
connectCalled = false;
|
|
||||||
|
|
||||||
// baz joins at the outer limit of the group
|
|
||||||
world.join(createMockUser(3), new Point(311, 100));
|
|
||||||
|
|
||||||
expect(connectCalled).toBe(false);
|
|
||||||
|
|
||||||
world.updatePosition({ userId: 3 }, new Point(309, 100));
|
|
||||||
|
|
||||||
expect(connectCalled).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should disconnect user1 and user2", () => {
|
|
||||||
let connectCalled: boolean = false;
|
|
||||||
let disconnectCallNumber: number = 0;
|
|
||||||
const connect: ConnectCallback = (user: User, group: Group): void => {
|
|
||||||
connectCalled = true;
|
|
||||||
}
|
|
||||||
const disconnect: DisconnectCallback = (user: User, group: Group): void => {
|
|
||||||
disconnectCallNumber++;
|
|
||||||
}
|
|
||||||
|
|
||||||
const world = new PusherRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
|
||||||
|
|
||||||
world.join(createMockUser(1), new Point(100, 100));
|
|
||||||
|
|
||||||
world.join(createMockUser(2), new Point(259, 100));
|
|
||||||
|
|
||||||
expect(connectCalled).toBe(true);
|
|
||||||
expect(disconnectCallNumber).toBe(0);
|
|
||||||
|
|
||||||
world.updatePosition({ userId: 2 }, new Point(100+160+160+1, 100));
|
|
||||||
|
|
||||||
expect(disconnectCallNumber).toBe(2);
|
|
||||||
|
|
||||||
world.updatePosition({ userId: 2 }, new Point(262, 100));
|
|
||||||
expect(disconnectCallNumber).toBe(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
@ -1,176 +0,0 @@
|
|||||||
import "jasmine";
|
|
||||||
import {PusherRoom, ConnectCallback, DisconnectCallback } from "_Model/PusherRoom";
|
|
||||||
import {Point} from "_Model/Websocket/Point";
|
|
||||||
import { Group } from "../src/Model/Group";
|
|
||||||
import {PositionDispatcher} from "_Model/PositionDispatcher";
|
|
||||||
import {User} from "../src/Model/User";
|
|
||||||
import {PointInterface} from "../src/Model/Websocket/PointInterface";
|
|
||||||
import {Zone} from "_Model/Zone";
|
|
||||||
import {Movable} from "_Model/Movable";
|
|
||||||
import {PositionInterface} from "_Model/PositionInterface";
|
|
||||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
|
||||||
|
|
||||||
|
|
||||||
describe("PositionNotifier", () => {
|
|
||||||
it("should receive notifications when player moves", () => {
|
|
||||||
let enterTriggered = false;
|
|
||||||
let moveTriggered = false;
|
|
||||||
let leaveTriggered = false;
|
|
||||||
|
|
||||||
const positionNotifier = new PositionDispatcher(300, 300, (thing: Movable) => {
|
|
||||||
enterTriggered = true;
|
|
||||||
}, (thing: Movable, position: PositionInterface) => {
|
|
||||||
moveTriggered = true;
|
|
||||||
}, (thing: Movable) => {
|
|
||||||
leaveTriggered = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const user1 = new User(1, 'test', {
|
|
||||||
x: 500,
|
|
||||||
y: 500,
|
|
||||||
moving: false,
|
|
||||||
direction: 'down'
|
|
||||||
}, false, positionNotifier, {} as ExSocketInterface);
|
|
||||||
|
|
||||||
const user2 = new User(2, 'test', {
|
|
||||||
x: -9999,
|
|
||||||
y: -9999,
|
|
||||||
moving: false,
|
|
||||||
direction: 'down'
|
|
||||||
}, false, positionNotifier, {} as ExSocketInterface);
|
|
||||||
|
|
||||||
positionNotifier.setViewport(user1, {
|
|
||||||
left: 200,
|
|
||||||
right: 600,
|
|
||||||
top: 100,
|
|
||||||
bottom: 500
|
|
||||||
});
|
|
||||||
|
|
||||||
user2.setPosition({x: 500, y: 500, direction: 'down', moving: false});
|
|
||||||
|
|
||||||
expect(enterTriggered).toBe(true);
|
|
||||||
expect(moveTriggered).toBe(false);
|
|
||||||
enterTriggered = false;
|
|
||||||
|
|
||||||
// Move inside the zone
|
|
||||||
user2.setPosition({x:501, y:500, direction: 'down', moving: false});
|
|
||||||
|
|
||||||
expect(enterTriggered).toBe(false);
|
|
||||||
expect(moveTriggered).toBe(true);
|
|
||||||
moveTriggered = false;
|
|
||||||
|
|
||||||
// Move out of the zone in a zone that we don't track
|
|
||||||
user2.setPosition({x: 901, y: 500, direction: 'down', moving: false});
|
|
||||||
|
|
||||||
expect(enterTriggered).toBe(false);
|
|
||||||
expect(moveTriggered).toBe(false);
|
|
||||||
expect(leaveTriggered).toBe(true);
|
|
||||||
leaveTriggered = false;
|
|
||||||
|
|
||||||
// Move back in
|
|
||||||
user2.setPosition({x: 500, y: 500, direction: 'down', moving: false});
|
|
||||||
expect(enterTriggered).toBe(true);
|
|
||||||
expect(moveTriggered).toBe(false);
|
|
||||||
expect(leaveTriggered).toBe(false);
|
|
||||||
enterTriggered = false;
|
|
||||||
|
|
||||||
// Move out of the zone in a zone that we do track
|
|
||||||
user2.setPosition({x: 200, y: 500, direction: 'down', moving: false});
|
|
||||||
expect(enterTriggered).toBe(false);
|
|
||||||
expect(moveTriggered).toBe(true);
|
|
||||||
expect(leaveTriggered).toBe(false);
|
|
||||||
moveTriggered = false;
|
|
||||||
|
|
||||||
// Leave the room
|
|
||||||
positionNotifier.leave(user2);
|
|
||||||
positionNotifier.removeViewport(user2);
|
|
||||||
expect(enterTriggered).toBe(false);
|
|
||||||
expect(moveTriggered).toBe(false);
|
|
||||||
expect(leaveTriggered).toBe(true);
|
|
||||||
leaveTriggered = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should receive notifications when camera moves", () => {
|
|
||||||
let enterTriggered = false;
|
|
||||||
let moveTriggered = false;
|
|
||||||
let leaveTriggered = false;
|
|
||||||
|
|
||||||
const positionNotifier = new PositionDispatcher(300, 300, (thing: Movable) => {
|
|
||||||
enterTriggered = true;
|
|
||||||
}, (thing: Movable, position: PositionInterface) => {
|
|
||||||
moveTriggered = true;
|
|
||||||
}, (thing: Movable) => {
|
|
||||||
leaveTriggered = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const user1 = new User(1, 'test', {
|
|
||||||
x: 500,
|
|
||||||
y: 500,
|
|
||||||
moving: false,
|
|
||||||
direction: 'down'
|
|
||||||
}, false, positionNotifier, {} as ExSocketInterface);
|
|
||||||
|
|
||||||
const user2 = new User(2, 'test', {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
moving: false,
|
|
||||||
direction: 'down'
|
|
||||||
}, false, positionNotifier, {} as ExSocketInterface);
|
|
||||||
|
|
||||||
let newUsers = positionNotifier.setViewport(user1, {
|
|
||||||
left: 200,
|
|
||||||
right: 600,
|
|
||||||
top: 100,
|
|
||||||
bottom: 500
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(newUsers.length).toBe(2);
|
|
||||||
expect(enterTriggered).toBe(true);
|
|
||||||
enterTriggered = false;
|
|
||||||
|
|
||||||
user2.setPosition({x: 500, y: 500, direction: 'down', moving: false});
|
|
||||||
|
|
||||||
expect(enterTriggered).toBe(false);
|
|
||||||
expect(moveTriggered).toBe(true);
|
|
||||||
moveTriggered = false;
|
|
||||||
|
|
||||||
// Move the viewport but the user stays inside.
|
|
||||||
positionNotifier.setViewport(user1, {
|
|
||||||
left: 201,
|
|
||||||
right: 601,
|
|
||||||
top: 100,
|
|
||||||
bottom: 500
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(enterTriggered).toBe(false);
|
|
||||||
expect(moveTriggered).toBe(false);
|
|
||||||
expect(leaveTriggered).toBe(false);
|
|
||||||
|
|
||||||
// Move the viewport out of the user.
|
|
||||||
positionNotifier.setViewport(user1, {
|
|
||||||
left: 901,
|
|
||||||
right: 1001,
|
|
||||||
top: 100,
|
|
||||||
bottom: 500
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(enterTriggered).toBe(false);
|
|
||||||
expect(moveTriggered).toBe(false);
|
|
||||||
expect(leaveTriggered).toBe(true);
|
|
||||||
leaveTriggered = false;
|
|
||||||
|
|
||||||
// Move the viewport back on the user.
|
|
||||||
newUsers = positionNotifier.setViewport(user1, {
|
|
||||||
left: 200,
|
|
||||||
right: 600,
|
|
||||||
top: 100,
|
|
||||||
bottom: 500
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(enterTriggered).toBe(true);
|
|
||||||
expect(moveTriggered).toBe(false);
|
|
||||||
expect(leaveTriggered).toBe(false);
|
|
||||||
enterTriggered = false;
|
|
||||||
expect(newUsers.length).toBe(2);
|
|
||||||
});
|
|
||||||
})
|
|
Loading…
Reference in New Issue
Block a user