workadventure/back/src/Model/Zone.ts

121 lines
4 KiB
TypeScript
Raw Normal View History

2021-06-24 10:09:10 +02:00
import { User } from "./User";
import { PositionInterface } from "_Model/PositionInterface";
import { Movable } from "./Movable";
import { Group } from "./Group";
import { ZoneSocket } from "../RoomManager";
import {
EmoteEventMessage,
SetPlayerDetailsMessage,
PlayerDetailsUpdatedMessage,
} from "../Messages/generated/messages_pb";
2021-06-24 10:09:10 +02:00
export type EntersCallback = (thing: Movable, fromZone: Zone | null, listener: ZoneSocket) => void;
export type MovesCallback = (thing: Movable, position: PositionInterface, listener: ZoneSocket) => void;
2021-06-24 10:09:10 +02:00
export type LeavesCallback = (thing: Movable, newZone: Zone | null, listener: ZoneSocket) => void;
export type EmoteCallback = (emoteEventMessage: EmoteEventMessage, listener: ZoneSocket) => void;
export type PlayerDetailsUpdatedCallback = (
playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage,
listener: ZoneSocket
) => void;
export class Zone {
2020-09-16 16:06:43 +02:00
private things: Set<Movable> = new Set<Movable>();
private listeners: Set<ZoneSocket> = new Set<ZoneSocket>();
2021-06-24 10:09:10 +02:00
constructor(
private onEnters: EntersCallback,
private onMoves: MovesCallback,
private onLeaves: LeavesCallback,
private onEmote: EmoteCallback,
private onPlayerDetailsUpdated: PlayerDetailsUpdatedCallback,
2021-06-24 10:09:10 +02:00
public readonly x: number,
public readonly y: number
) {}
/**
2020-09-16 16:06:43 +02:00
* A user/thing leaves the zone
*/
2021-06-24 10:09:10 +02:00
public leave(thing: Movable, newZone: Zone | null) {
const result = this.things.delete(thing);
if (!result) {
if (thing instanceof User) {
2021-12-23 15:27:17 +01:00
throw new Error(`Could not find user in zone ${thing.id}`);
}
if (thing instanceof Group) {
2021-06-24 10:09:10 +02:00
throw new Error(
2021-12-23 15:27:17 +01:00
`Could not find group ${thing.getId()} in zone (${this.x},${this.y}). Position of group: (${
thing.getPosition().x
},${thing.getPosition().y})`
2021-06-24 10:09:10 +02:00
);
}
}
2020-09-16 16:06:43 +02:00
this.notifyLeft(thing, newZone);
}
/**
2020-09-16 16:06:43 +02:00
* Notify listeners of this zone that this user/thing left
*/
2021-06-24 10:09:10 +02:00
private notifyLeft(thing: Movable, newZone: Zone | null) {
for (const listener of this.listeners) {
this.onLeaves(thing, newZone, listener);
}
}
2021-06-24 10:09:10 +02:00
public enter(thing: Movable, oldZone: Zone | null, position: PositionInterface) {
2020-09-16 16:06:43 +02:00
this.things.add(thing);
this.notifyEnter(thing, oldZone, position);
}
/**
* Notify listeners of this zone that this user entered
*/
2021-06-24 10:09:10 +02:00
private notifyEnter(thing: Movable, oldZone: Zone | null, position: PositionInterface) {
for (const listener of this.listeners) {
this.onEnters(thing, oldZone, listener);
}
}
2020-09-16 16:06:43 +02:00
public move(thing: Movable, position: PositionInterface) {
if (!this.things.has(thing)) {
this.things.add(thing);
this.notifyEnter(thing, null, position);
return;
}
for (const listener of this.listeners) {
//if (listener !== thing) {
2021-06-24 10:09:10 +02:00
this.onMoves(thing, position, listener);
//}
}
}
2020-09-16 16:06:43 +02:00
public getThings(): Set<Movable> {
return this.things;
}
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);
}
public emitEmoteEvent(emoteEventMessage: EmoteEventMessage) {
for (const listener of this.listeners) {
this.onEmote(emoteEventMessage, listener);
}
}
public updatePlayerDetails(user: User, playerDetails: SetPlayerDetailsMessage) {
const playerDetailsUpdatedMessage = new PlayerDetailsUpdatedMessage();
playerDetailsUpdatedMessage.setUserid(user.id);
playerDetailsUpdatedMessage.setDetails(playerDetails);
for (const listener of this.listeners) {
this.onPlayerDetailsUpdated(playerDetailsUpdatedMessage, listener);
}
}
}