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-11-13 18:00:22 +01:00
import { ZoneSocket } from "../RoomManager" ;
2020-09-15 10:06:11 +02:00
2020-11-13 18:00:22 +01:00
export type EntersCallback = ( thing : Movable , fromZone : Zone | null , listener : ZoneSocket ) = > void ;
export type MovesCallback = ( thing : Movable , position : PositionInterface , listener : ZoneSocket ) = > void ;
export type LeavesCallback = ( thing : Movable , newZone : Zone | null , listener : ZoneSocket ) = > 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 > ( ) ;
2020-11-13 18:00:22 +01:00
private listeners : Set < ZoneSocket > = new Set < ZoneSocket > ( ) ;
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
* /
2020-11-13 18:00:22 +01:00
constructor ( private onEnters : EntersCallback , private onMoves : MovesCallback , private onLeaves : LeavesCallback , public readonly x : number , public readonly 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 ) {
2020-09-25 15:25:06 +02:00
throw new Error ( 'Could not find user in zone ' + thing . id ) ;
2020-09-25 13:48:02 +02:00
}
if ( thing instanceof Group ) {
2020-09-25 15:25:06 +02:00
throw new Error ( 'Could not find group ' + thing . getId ( ) + ' in zone (' + this . x + ',' + this . y + '). Position of group: (' + thing . getPosition ( ) . x + ',' + thing . getPosition ( ) . y + ')' ) ;
2020-09-25 13:48:02 +02:00
}
}
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-11-13 18:00:22 +01:00
//if (listener !== thing && (newZone === null || !listener.listenedZones.has(newZone))) {
this . onLeaves ( thing , newZone , 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-11-13 18:00:22 +01:00
/ * i f ( l i s t e n e r = = = t h i n g ) {
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-11-13 18:00:22 +01:00
} * /
this . onEnters ( thing , oldZone , listener ) ;
2020-09-15 10:06:11 +02:00
}
}
2020-11-13 18:00:22 +01: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-11-13 18:00:22 +01:00
//if (listener !== thing) {
2020-09-16 16:06:43 +02:00
this . onMoves ( thing , position , listener ) ;
2020-11-13 18:00:22 +01:00
//}
2020-09-15 10:06:11 +02:00
}
}
2020-11-13 18:00:22 +01:00
/ * p u b l i c s t a r t L i s t e n i n g ( l i s t e n e r : U s e r ) : v o i d {
2020-09-16 16:06:43 +02:00
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-11-13 18:00:22 +01:00
} * /
2020-09-15 16:21:41 +02:00
2020-09-16 16:06:43 +02:00
public getThings ( ) : Set < Movable > {
return this . things ;
2020-09-15 10:06:11 +02:00
}
2020-11-13 18:00:22 +01:00
public addListener ( socket : ZoneSocket ) : void {
this . listeners . add ( socket ) ;
// TODO: here, we should trigger in some way the sending of current items
}
public removeListener ( socket : ZoneSocket ) : void {
this . listeners . delete ( socket ) ;
}
2020-09-15 10:06:11 +02:00
}