Plugin PositionNotifier into the main application.
This commit is contained in:
parent
f8d462b0d7
commit
d24ec0bd75
10 changed files with 170 additions and 62 deletions
|
@ -34,10 +34,14 @@ export class PositionNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
public setViewport(user: UserInterface, viewport: ViewportInterface): void {
|
||||
/**
|
||||
* Sets the viewport coordinates.
|
||||
* Returns the list of new users to add
|
||||
*/
|
||||
public setViewport(user: UserInterface, viewport: ViewportInterface): UserInterface[] {
|
||||
if (viewport.left > viewport.right || viewport.top > viewport.bottom) {
|
||||
console.warn('Invalid viewport received: ', viewport);
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
const oldZones = user.listenedZones;
|
||||
|
@ -55,12 +59,17 @@ export class PositionNotifier {
|
|||
const addedZones = [...newZones].filter(x => !oldZones.has(x));
|
||||
const removedZones = [...oldZones].filter(x => !newZones.has(x));
|
||||
|
||||
|
||||
let users: UserInterface[] = [];
|
||||
for (const zone of addedZones) {
|
||||
zone.startListening(user);
|
||||
users = users.concat(Array.from(zone.getPlayers()))
|
||||
}
|
||||
for (const zone of removedZones) {
|
||||
zone.stopListening(user);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public updatePosition(user: UserInterface, userPosition: PointInterface): void {
|
||||
|
@ -87,6 +96,11 @@ export class PositionNotifier {
|
|||
const oldZoneDesc = this.getZoneDescriptorFromCoordinates(user.position.x, user.position.y);
|
||||
const oldZone = this.getZone(oldZoneDesc.i, oldZoneDesc.j);
|
||||
oldZone.leave(user, null);
|
||||
|
||||
// Also, let's stop listening on viewports
|
||||
for (const zone of user.listenedZones) {
|
||||
zone.stopListening(user);
|
||||
}
|
||||
}
|
||||
|
||||
private getZone(i: number, j: number): Zone {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import * as tg from "generic-type-guard";
|
||||
import {isPointInterface} from "./PointInterface";
|
||||
import {isViewport} from "./ViewportMessage";
|
||||
|
||||
export const isJoinRoomMessageInterface =
|
||||
new tg.IsInterface().withProperties({
|
||||
roomId: tg.isString,
|
||||
position: isPointInterface,
|
||||
viewport: isViewport
|
||||
}).get();
|
||||
export type JoinRoomMessageInterface = tg.GuardedType<typeof isJoinRoomMessageInterface>;
|
||||
|
|
|
@ -6,7 +6,9 @@ import {UserInterface} from "./UserInterface";
|
|||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
||||
import {PositionInterface} from "_Model/PositionInterface";
|
||||
import {Identificable} from "_Model/Websocket/Identificable";
|
||||
import {Zone} from "_Model/Zone";
|
||||
import {UserEntersCallback, UserLeavesCallback, UserMovesCallback, Zone} from "_Model/Zone";
|
||||
import {PositionNotifier} from "./PositionNotifier";
|
||||
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
||||
|
||||
export type ConnectCallback = (user: string, group: Group) => void;
|
||||
export type DisconnectCallback = (user: string, group: Group) => void;
|
||||
|
@ -28,12 +30,17 @@ export class World {
|
|||
private readonly groupUpdatedCallback: GroupUpdatedCallback;
|
||||
private readonly groupDeletedCallback: GroupDeletedCallback;
|
||||
|
||||
private readonly positionNotifier: PositionNotifier;
|
||||
|
||||
constructor(connectCallback: ConnectCallback,
|
||||
disconnectCallback: DisconnectCallback,
|
||||
minDistance: number,
|
||||
groupRadius: number,
|
||||
groupUpdatedCallback: GroupUpdatedCallback,
|
||||
groupDeletedCallback: GroupDeletedCallback)
|
||||
groupDeletedCallback: GroupDeletedCallback,
|
||||
onUserEnters: UserEntersCallback,
|
||||
onUserMoves: UserMovesCallback,
|
||||
onUserLeaves: UserLeavesCallback)
|
||||
{
|
||||
this.users = new Map<string, UserInterface>();
|
||||
this.groups = new Set<Group>();
|
||||
|
@ -43,6 +50,8 @@ export class World {
|
|||
this.groupRadius = groupRadius;
|
||||
this.groupUpdatedCallback = groupUpdatedCallback;
|
||||
this.groupDeletedCallback = groupDeletedCallback;
|
||||
// A zone is 10 sprites wide.
|
||||
this.positionNotifier = new PositionNotifier(320, 320, onUserEnters, onUserMoves, onUserLeaves);
|
||||
}
|
||||
|
||||
public getGroups(): Group[] {
|
||||
|
@ -73,6 +82,10 @@ export class World {
|
|||
this.leaveGroup(userObj);
|
||||
}
|
||||
this.users.delete(user.userId);
|
||||
|
||||
if (userObj !== undefined) {
|
||||
this.positionNotifier.leave(userObj);
|
||||
}
|
||||
}
|
||||
|
||||
public isEmpty(): boolean {
|
||||
|
@ -85,6 +98,8 @@ export class World {
|
|||
return;
|
||||
}
|
||||
|
||||
this.positionNotifier.updatePosition(user, userPosition);
|
||||
|
||||
user.position = userPosition;
|
||||
|
||||
if (user.silent) {
|
||||
|
@ -318,4 +333,12 @@ export class World {
|
|||
}
|
||||
return 0;
|
||||
}*/
|
||||
setViewport(socket : Identificable, viewport: ViewportInterface): UserInterface[] {
|
||||
const user = this.users.get(socket.userId);
|
||||
if(typeof user === 'undefined') {
|
||||
console.warn('In setViewport, could not find user with ID "'+socket.userId+'" in world.');
|
||||
return [];
|
||||
}
|
||||
return this.positionNotifier.setViewport(user, viewport);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import {UserInterface} from "./UserInterface";
|
|||
import {PointInterface} from "_Model/Websocket/PointInterface";
|
||||
import {PositionInterface} from "_Model/PositionInterface";
|
||||
|
||||
export type UserEntersCallback = (user: UserInterface) => void;
|
||||
export type UserMovesCallback = (user: UserInterface, position: PointInterface) => void;
|
||||
export type UserLeavesCallback = (user: UserInterface) => void;
|
||||
export type UserEntersCallback = (user: UserInterface, listener: UserInterface) => void;
|
||||
export type UserMovesCallback = (user: UserInterface, position: PointInterface, listener: UserInterface) => void;
|
||||
export type UserLeavesCallback = (user: UserInterface, listener: UserInterface) => void;
|
||||
|
||||
export class Zone {
|
||||
private players: Set<UserInterface> = new Set<UserInterface>();
|
||||
|
@ -27,7 +27,7 @@ export class Zone {
|
|||
private notifyUserLeft(user: UserInterface, newZone: Zone|null) {
|
||||
for (const listener of this.listeners) {
|
||||
if (listener !== user && (newZone === null || !listener.listenedZones.has(newZone))) {
|
||||
this.onUserLeaves(user);
|
||||
this.onUserLeaves(user, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,40 +46,51 @@ export class Zone {
|
|||
continue;
|
||||
}
|
||||
if (oldZone === null || !listener.listenedZones.has(oldZone)) {
|
||||
this.onUserEnters(user);
|
||||
this.onUserEnters(user, listener);
|
||||
} else {
|
||||
this.onUserMoves(user, position);
|
||||
this.onUserMoves(user, position, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public move(user: UserInterface, position: PointInterface) {
|
||||
if (!this.players.has(user)) {
|
||||
this.players.add(user);
|
||||
const foo = this.players;
|
||||
this.notifyUserEnter(user, null, position);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const listener of this.listeners) {
|
||||
if (listener !== user) {
|
||||
this.onUserMoves(user,position);
|
||||
this.onUserMoves(user,position, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public startListening(user: UserInterface): void {
|
||||
public startListening(listener: UserInterface): void {
|
||||
for (const player of this.players) {
|
||||
if (player !== user) {
|
||||
this.onUserEnters(user);
|
||||
if (player !== listener) {
|
||||
this.onUserEnters(player, listener);
|
||||
}
|
||||
}
|
||||
|
||||
this.listeners.add(user);
|
||||
user.listenedZones.add(this);
|
||||
this.listeners.add(listener);
|
||||
listener.listenedZones.add(this);
|
||||
}
|
||||
|
||||
public stopListening(user: UserInterface): void {
|
||||
public stopListening(listener: UserInterface): void {
|
||||
for (const player of this.players) {
|
||||
if (player !== user) {
|
||||
this.onUserLeaves(user);
|
||||
if (player !== listener) {
|
||||
this.onUserLeaves(player, listener);
|
||||
}
|
||||
}
|
||||
|
||||
this.listeners.delete(user);
|
||||
user.listenedZones.delete(this);
|
||||
this.listeners.delete(listener);
|
||||
listener.listenedZones.delete(this);
|
||||
}
|
||||
|
||||
public getPlayers(): Set<UserInterface> {
|
||||
return this.players;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue