2020-09-16 16:06:43 +02:00
import { User } from "./User" ;
2020-09-15 10:06:11 +02:00
import { PositionInterface } from "_Model/PositionInterface" ;
2020-09-25 13:48:02 +02:00
import { Movable } from "./Movable" ;
import { Group } from "./Group" ;
2020-09-15 10:06:11 +02:00
2020-09-16 16:06:43 +02:00
export type EntersCallback = ( thing : Movable , listener : User ) = > void ;
export type MovesCallback = ( thing : Movable , position : PositionInterface , listener : User ) = > void ;
export type LeavesCallback = ( thing : Movable , listener : User ) = > void ;
2020-09-15 10:06:11 +02:00
export class Zone {
2020-09-16 16:06:43 +02:00
private things : Set < Movable > = new Set < Movable > ( ) ;
private listeners : Set < User > = new Set < User > ( ) ;
2020-09-15 10:06:11 +02:00
2020-09-25 13:48:02 +02:00
/ * *
* @param x For debugging purpose only
* @param y For debugging purpose only
* /
constructor ( private onEnters : EntersCallback , private onMoves : MovesCallback , private onLeaves : LeavesCallback , private x : number , private y : number ) {
2020-09-15 10:06:11 +02:00
}
/ * *
2020-09-16 16:06:43 +02:00
* A user / thing leaves the zone
2020-09-15 10:06:11 +02:00
* /
2020-09-16 16:06:43 +02:00
public leave ( thing : Movable , newZone : Zone | null ) {
2020-09-25 13:48:02 +02:00
const result = this . things . delete ( thing ) ;
if ( ! result ) {
if ( thing instanceof User ) {
console . error ( 'Could not find user in zone ' + thing . id ) ;
}
if ( thing instanceof Group ) {
console . error ( 'Could not find group ' + thing . getId ( ) + ' in zone (' + this . x + ',' + this . y + '). Position of group: (' + thing . getPosition ( ) . x + ',' + thing . getPosition ( ) . y + ')' ) ;
}
}
2020-09-16 16:06:43 +02:00
this . notifyLeft ( thing , newZone ) ;
2020-09-15 10:06:11 +02:00
}
/ * *
2020-09-16 16:06:43 +02:00
* Notify listeners of this zone that this user / thing left
2020-09-15 10:06:11 +02:00
* /
2020-09-16 16:06:43 +02:00
private notifyLeft ( thing : Movable , newZone : Zone | null ) {
2020-09-15 10:06:11 +02:00
for ( const listener of this . listeners ) {
2020-09-16 16:06:43 +02:00
if ( listener !== thing && ( newZone === null || ! listener . listenedZones . has ( newZone ) ) ) {
this . onLeaves ( thing , listener ) ;
2020-09-15 10:06:11 +02:00
}
}
}
2020-09-16 16:06:43 +02:00
public enter ( thing : Movable , oldZone : Zone | null , position : PositionInterface ) {
this . things . add ( thing ) ;
2020-09-25 13:48:02 +02:00
this . notifyEnter ( thing , oldZone , position ) ;
2020-09-15 10:06:11 +02:00
}
/ * *
* Notify listeners of this zone that this user entered
* /
2020-09-25 13:48:02 +02:00
private notifyEnter ( thing : Movable , oldZone : Zone | null , position : PositionInterface ) {
2020-09-15 10:06:11 +02:00
for ( const listener of this . listeners ) {
2020-09-16 16:06:43 +02:00
if ( listener === thing ) {
2020-09-15 10:06:11 +02:00
continue ;
}
if ( oldZone === null || ! listener . listenedZones . has ( oldZone ) ) {
2020-09-16 16:06:43 +02:00
this . onEnters ( thing , listener ) ;
2020-09-15 10:06:11 +02:00
} else {
2020-09-16 16:06:43 +02:00
this . onMoves ( thing , position , listener ) ;
2020-09-15 10:06:11 +02:00
}
}
}
2020-09-16 16:06:43 +02:00
public move ( thing : Movable , position : PositionInterface ) {
if ( ! this . things . has ( thing ) ) {
this . things . add ( thing ) ;
2020-09-25 13:48:02 +02:00
this . notifyEnter ( thing , null , position ) ;
2020-09-15 16:21:41 +02:00
return ;
}
2020-09-15 10:06:11 +02:00
for ( const listener of this . listeners ) {
2020-09-16 16:06:43 +02:00
if ( listener !== thing ) {
this . onMoves ( thing , position , listener ) ;
2020-09-15 10:06:11 +02:00
}
}
}
2020-09-16 16:06:43 +02:00
public startListening ( listener : User ) : void {
for ( const thing of this . things ) {
if ( thing !== listener ) {
this . onEnters ( thing , listener ) ;
2020-09-15 10:06:11 +02:00
}
}
2020-09-15 16:21:41 +02:00
this . listeners . add ( listener ) ;
listener . listenedZones . add ( this ) ;
2020-09-15 10:06:11 +02:00
}
2020-09-16 16:06:43 +02:00
public stopListening ( listener : User ) : void {
for ( const thing of this . things ) {
if ( thing !== listener ) {
this . onLeaves ( thing , listener ) ;
2020-09-15 10:06:11 +02:00
}
}
2020-09-15 16:21:41 +02:00
this . listeners . delete ( listener ) ;
listener . listenedZones . delete ( this ) ;
}
2020-09-16 16:06:43 +02:00
public getThings ( ) : Set < Movable > {
return this . things ;
2020-09-15 10:06:11 +02:00
}
}