Applying Prettier on pusher and back

This commit is contained in:
David Négrier 2021-06-24 10:09:10 +02:00
parent 06b7f5ba2f
commit 10c3d6dee2
71 changed files with 1848 additions and 1652 deletions

View file

@ -1,8 +1,8 @@
import {PositionInterface} from "_Model/PositionInterface";
import { PositionInterface } from "_Model/PositionInterface";
/**
* A physical object that can be placed into a Zone
*/
export interface Movable {
getPosition(): PositionInterface
getPosition(): PositionInterface;
}

View file

@ -8,9 +8,9 @@
* The PositionNotifier is important for performance. It allows us to send the position of players only to a restricted
* number of players around the current player.
*/
import {Zone, ZoneEventListener} from "./Zone";
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
import { Zone, ZoneEventListener } from "./Zone";
import { ViewportInterface } from "_Model/Websocket/ViewportMessage";
import { ExSocketInterface } from "_Model/Websocket/ExSocketInterface";
//import Debug from "debug";
//const debug = Debug('positiondispatcher');
@ -21,19 +21,22 @@ interface ZoneDescriptor {
}
export class PositionDispatcher {
// TODO: we need a way to clean the zones if noone is in the zone and noone listening (to free memory!)
private zones: Zone[][] = [];
constructor(public readonly roomId: string, private zoneWidth: number, private zoneHeight: number, private socketListener: ZoneEventListener) {
}
constructor(
public readonly roomId: string,
private zoneWidth: number,
private zoneHeight: number,
private socketListener: ZoneEventListener
) {}
private getZoneDescriptorFromCoordinates(x: number, y: number): ZoneDescriptor {
return {
i: Math.floor(x / this.zoneWidth),
j: Math.floor(y / this.zoneHeight),
}
};
}
/**
@ -41,7 +44,7 @@ export class PositionDispatcher {
*/
public setViewport(socket: ExSocketInterface, viewport: ViewportInterface): void {
if (viewport.left > viewport.right || viewport.top > viewport.bottom) {
console.warn('Invalid viewport received: ', viewport);
console.warn("Invalid viewport received: ", viewport);
return;
}
@ -57,8 +60,8 @@ export class PositionDispatcher {
}
}
const addedZones = [...newZones].filter(x => !oldZones.has(x));
const removedZones = [...oldZones].filter(x => !newZones.has(x));
const addedZones = [...newZones].filter((x) => !oldZones.has(x));
const removedZones = [...oldZones].filter((x) => !newZones.has(x));
for (const zone of addedZones) {
zone.startListening(socket);

View file

@ -1,4 +1,4 @@
export interface PositionInterface {
x: number,
y: number
x: number;
y: number;
}

View file

@ -1,9 +1,9 @@
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
import {PositionDispatcher} from "./PositionDispatcher";
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
import {extractDataFromPrivateRoomId, extractRoomSlugPublicRoomId, isRoomAnonymous} from "./RoomIdentifier";
import {arrayIntersect} from "../Services/ArrayHelper";
import {ZoneEventListener} from "_Model/Zone";
import { ExSocketInterface } from "_Model/Websocket/ExSocketInterface";
import { PositionDispatcher } from "./PositionDispatcher";
import { ViewportInterface } from "_Model/Websocket/ViewportMessage";
import { extractDataFromPrivateRoomId, extractRoomSlugPublicRoomId, isRoomAnonymous } from "./RoomIdentifier";
import { arrayIntersect } from "../Services/ArrayHelper";
import { ZoneEventListener } from "_Model/Zone";
export enum GameRoomPolicyTypes {
ANONYMUS_POLICY = 1,
@ -17,13 +17,11 @@ export class PusherRoom {
public tags: string[];
public policyType: GameRoomPolicyTypes;
public readonly roomSlug: string;
public readonly worldSlug: string = '';
public readonly organizationSlug: string = '';
public readonly worldSlug: string = "";
public readonly organizationSlug: string = "";
private versionNumber: number = 1;
constructor(public readonly roomId: string,
private socketListener: ZoneEventListener)
{
constructor(public readonly roomId: string, private socketListener: ZoneEventListener) {
this.public = isRoomAnonymous(roomId);
this.tags = [];
this.policyType = GameRoomPolicyTypes.ANONYMUS_POLICY;
@ -31,7 +29,7 @@ export class PusherRoom {
if (this.public) {
this.roomSlug = extractRoomSlugPublicRoomId(this.roomId);
} else {
const {organizationSlug, worldSlug, roomSlug} = extractDataFromPrivateRoomId(this.roomId);
const { organizationSlug, worldSlug, roomSlug } = extractDataFromPrivateRoomId(this.roomId);
this.roomSlug = roomSlug;
this.organizationSlug = organizationSlug;
this.worldSlug = worldSlug;
@ -41,11 +39,11 @@ export class PusherRoom {
this.positionNotifier = new PositionDispatcher(this.roomId, 320, 320, this.socketListener);
}
public setViewport(socket : ExSocketInterface, viewport: ViewportInterface): void {
public setViewport(socket: ExSocketInterface, viewport: ViewportInterface): void {
this.positionNotifier.setViewport(socket, viewport);
}
public leave(socket : ExSocketInterface){
public leave(socket: ExSocketInterface) {
this.positionNotifier.removeViewport(socket);
}

View file

@ -1,30 +1,30 @@
//helper functions to parse room IDs
export const isRoomAnonymous = (roomID: string): boolean => {
if (roomID.startsWith('_/')) {
if (roomID.startsWith("_/")) {
return true;
} else if(roomID.startsWith('@/')) {
} else if (roomID.startsWith("@/")) {
return false;
} else {
throw new Error('Incorrect room ID: '+roomID);
throw new Error("Incorrect room ID: " + roomID);
}
}
};
export const extractRoomSlugPublicRoomId = (roomId: string): string => {
const idParts = roomId.split('/');
if (idParts.length < 3) throw new Error('Incorrect roomId: '+roomId);
return idParts.slice(2).join('/');
}
const idParts = roomId.split("/");
if (idParts.length < 3) throw new Error("Incorrect roomId: " + roomId);
return idParts.slice(2).join("/");
};
export interface extractDataFromPrivateRoomIdResponse {
organizationSlug: string;
worldSlug: string;
roomSlug: string;
}
export const extractDataFromPrivateRoomId = (roomId: string): extractDataFromPrivateRoomIdResponse => {
const idParts = roomId.split('/');
if (idParts.length < 4) throw new Error('Incorrect roomId: '+roomId);
const idParts = roomId.split("/");
if (idParts.length < 4) throw new Error("Incorrect roomId: " + roomId);
const organizationSlug = idParts[1];
const worldSlug = idParts[2];
const roomSlug = idParts[3];
return {organizationSlug, worldSlug, roomSlug}
}
return { organizationSlug, worldSlug, roomSlug };
};

View file

@ -1,21 +1,22 @@
import {PointInterface} from "./PointInterface";
import {Identificable} from "./Identificable";
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
import { PointInterface } from "./PointInterface";
import { Identificable } from "./Identificable";
import { ViewportInterface } from "_Model/Websocket/ViewportMessage";
import {
AdminPusherToBackMessage,
BatchMessage,
PusherToBackMessage, ServerToAdminClientMessage,
PusherToBackMessage,
ServerToAdminClientMessage,
ServerToClientMessage,
SubMessage
SubMessage,
} from "../../Messages/generated/messages_pb";
import {WebSocket} from "uWebSockets.js"
import {CharacterTexture} from "../../Services/AdminApi";
import {ClientDuplexStream} from "grpc";
import {Zone} from "_Model/Zone";
import { WebSocket } from "uWebSockets.js";
import { CharacterTexture } from "../../Services/AdminApi";
import { ClientDuplexStream } from "grpc";
import { Zone } from "_Model/Zone";
export type AdminConnection = ClientDuplexStream<AdminPusherToBackMessage, ServerToAdminClientMessage>;
export interface ExAdminSocketInterface extends WebSocket {
adminConnection: AdminConnection,
disconnecting: boolean,
adminConnection: AdminConnection;
disconnecting: boolean;
}

View file

@ -1,23 +1,23 @@
import {PointInterface} from "./PointInterface";
import {Identificable} from "./Identificable";
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
import { PointInterface } from "./PointInterface";
import { Identificable } from "./Identificable";
import { ViewportInterface } from "_Model/Websocket/ViewportMessage";
import {
BatchMessage,
CompanionMessage,
PusherToBackMessage,
ServerToClientMessage,
SubMessage
SubMessage,
} from "../../Messages/generated/messages_pb";
import {WebSocket} from "uWebSockets.js"
import {CharacterTexture} from "../../Services/AdminApi";
import {ClientDuplexStream} from "grpc";
import {Zone} from "_Model/Zone";
import { WebSocket } from "uWebSockets.js";
import { CharacterTexture } from "../../Services/AdminApi";
import { ClientDuplexStream } from "grpc";
import { Zone } from "_Model/Zone";
export type BackConnection = ClientDuplexStream<PusherToBackMessage, ServerToClientMessage>;
export interface CharacterLayer {
name: string,
url: string|undefined
name: string;
url: string | undefined;
}
export interface ExSocketInterface extends WebSocket, Identificable {
@ -36,12 +36,12 @@ export interface ExSocketInterface extends WebSocket, Identificable {
*/
emitInBatch: (payload: SubMessage) => void;
batchedMessages: BatchMessage;
batchTimeout: NodeJS.Timeout|null;
disconnecting: boolean,
messages: unknown,
tags: string[],
visitCardUrl: string|null,
textures: CharacterTexture[],
backConnection: BackConnection,
batchTimeout: NodeJS.Timeout | null;
disconnecting: boolean;
messages: unknown;
tags: string[];
visitCardUrl: string | null;
textures: CharacterTexture[];
backConnection: BackConnection;
listenedZones: Set<Zone>;
}

View file

@ -1,10 +1,11 @@
import * as tg from "generic-type-guard";
export const isItemEventMessageInterface =
new tg.IsInterface().withProperties({
export const isItemEventMessageInterface = new tg.IsInterface()
.withProperties({
itemId: tg.isNumber,
event: tg.isString,
state: tg.isUnknown,
parameters: tg.isUnknown,
}).get();
})
.get();
export type ItemEventMessageInterface = tg.GuardedType<typeof isItemEventMessageInterface>;

View file

@ -1,6 +1,10 @@
import {PointInterface} from "./PointInterface";
import { PointInterface } from "./PointInterface";
export class Point implements PointInterface{
constructor(public x : number, public y : number, public direction : string = "none", public moving : boolean = false) {
}
export class Point implements PointInterface {
constructor(
public x: number,
public y: number,
public direction: string = "none",
public moving: boolean = false
) {}
}

View file

@ -7,11 +7,12 @@ import * as tg from "generic-type-guard";
readonly moving: boolean;
}*/
export const isPointInterface =
new tg.IsInterface().withProperties({
export const isPointInterface = new tg.IsInterface()
.withProperties({
x: tg.isNumber,
y: tg.isNumber,
direction: tg.isString,
moving: tg.isBoolean
}).get();
moving: tg.isBoolean,
})
.get();
export type PointInterface = tg.GuardedType<typeof isPointInterface>;

View file

@ -1,34 +1,33 @@
import {PointInterface} from "./PointInterface";
import { PointInterface } from "./PointInterface";
import {
CharacterLayerMessage,
ItemEventMessage,
PointMessage,
PositionMessage
PositionMessage,
} from "../../Messages/generated/messages_pb";
import {CharacterLayer, ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
import { CharacterLayer, ExSocketInterface } from "_Model/Websocket/ExSocketInterface";
import Direction = PositionMessage.Direction;
import {ItemEventMessageInterface} from "_Model/Websocket/ItemEventMessage";
import {PositionInterface} from "_Model/PositionInterface";
import { ItemEventMessageInterface } from "_Model/Websocket/ItemEventMessage";
import { PositionInterface } from "_Model/PositionInterface";
export class ProtobufUtils {
public static toPositionMessage(point: PointInterface): PositionMessage {
let direction: Direction;
switch (point.direction) {
case 'up':
case "up":
direction = Direction.UP;
break;
case 'down':
case "down":
direction = Direction.DOWN;
break;
case 'left':
case "left":
direction = Direction.LEFT;
break;
case 'right':
case "right":
direction = Direction.RIGHT;
break;
default:
throw new Error('unexpected direction');
throw new Error("unexpected direction");
}
const position = new PositionMessage();
@ -44,16 +43,16 @@ export class ProtobufUtils {
let direction: string;
switch (position.getDirection()) {
case Direction.UP:
direction = 'up';
direction = "up";
break;
case Direction.DOWN:
direction = 'down';
direction = "down";
break;
case Direction.LEFT:
direction = 'left';
direction = "left";
break;
case Direction.RIGHT:
direction = 'right';
direction = "right";
break;
default:
throw new Error("Unexpected direction");
@ -82,7 +81,7 @@ export class ProtobufUtils {
event: itemEventMessage.getEvent(),
parameters: JSON.parse(itemEventMessage.getParametersjson()),
state: JSON.parse(itemEventMessage.getStatejson()),
}
};
}
public static toItemEventProtobuf(itemEvent: ItemEventMessageInterface): ItemEventMessage {
@ -96,7 +95,7 @@ export class ProtobufUtils {
}
public static toCharacterLayerMessages(characterLayers: CharacterLayer[]): CharacterLayerMessage[] {
return characterLayers.map(function(characterLayer): CharacterLayerMessage {
return characterLayers.map(function (characterLayer): CharacterLayerMessage {
const message = new CharacterLayerMessage();
message.setName(characterLayer.name);
if (characterLayer.url) {

View file

@ -1,10 +1,11 @@
import * as tg from "generic-type-guard";
export const isViewport =
new tg.IsInterface().withProperties({
export const isViewport = new tg.IsInterface()
.withProperties({
left: tg.isNumber,
top: tg.isNumber,
right: tg.isNumber,
bottom: tg.isNumber,
}).get();
})
.get();
export type ViewportInterface = tg.GuardedType<typeof isViewport>;

View file

@ -1,16 +1,23 @@
import {ExSocketInterface} from "./Websocket/ExSocketInterface";
import {apiClientRepository} from "../Services/ApiClientRepository";
import { ExSocketInterface } from "./Websocket/ExSocketInterface";
import { apiClientRepository } from "../Services/ApiClientRepository";
import {
BatchToPusherMessage,
CharacterLayerMessage, GroupLeftZoneMessage, GroupUpdateMessage, GroupUpdateZoneMessage,
PointMessage, PositionMessage, UserJoinedMessage,
UserJoinedZoneMessage, UserLeftZoneMessage, UserMovedMessage,
CharacterLayerMessage,
GroupLeftZoneMessage,
GroupUpdateMessage,
GroupUpdateZoneMessage,
PointMessage,
PositionMessage,
UserJoinedMessage,
UserJoinedZoneMessage,
UserLeftZoneMessage,
UserMovedMessage,
ZoneMessage,
EmoteEventMessage,
CompanionMessage
CompanionMessage,
} from "../Messages/generated/messages_pb";
import {ClientReadableStream} from "grpc";
import {PositionDispatcher} from "_Model/PositionDispatcher";
import { ClientReadableStream } from "grpc";
import { PositionDispatcher } from "_Model/PositionDispatcher";
import Debug from "debug";
const debug = Debug("zone");
@ -30,24 +37,38 @@ export type MovesCallback = (thing: Movable, position: PositionInterface, listen
export type LeavesCallback = (thing: Movable, listener: User) => void;*/
export class UserDescriptor {
private constructor(public readonly userId: number, private name: string, private characterLayers: CharacterLayerMessage[], private position: PositionMessage, private visitCardUrl: string | null, private companion?: CompanionMessage) {
private constructor(
public readonly userId: number,
private name: string,
private characterLayers: CharacterLayerMessage[],
private position: PositionMessage,
private visitCardUrl: string | null,
private companion?: CompanionMessage
) {
if (!Number.isInteger(this.userId)) {
throw new Error('UserDescriptor.userId is not an integer: '+this.userId);
throw new Error("UserDescriptor.userId is not an integer: " + this.userId);
}
}
public static createFromUserJoinedZoneMessage(message: UserJoinedZoneMessage): UserDescriptor {
const position = message.getPosition();
if (position === undefined) {
throw new Error('Missing position');
throw new Error("Missing position");
}
return new UserDescriptor(message.getUserid(), message.getName(), message.getCharacterlayersList(), position, message.getVisitcardurl(), message.getCompanion());
return new UserDescriptor(
message.getUserid(),
message.getName(),
message.getCharacterlayersList(),
position,
message.getVisitcardurl(),
message.getCompanion()
);
}
public update(userMovedMessage: UserMovedMessage) {
const position = userMovedMessage.getPosition();
if (position === undefined) {
throw new Error('Missing position');
throw new Error("Missing position");
}
this.position = position;
}
@ -78,13 +99,12 @@ export class UserDescriptor {
}
export class GroupDescriptor {
private constructor(public readonly groupId: number, private groupSize: number, private position: PointMessage) {
}
private constructor(public readonly groupId: number, private groupSize: number, private position: PointMessage) {}
public static createFromGroupUpdateZoneMessage(message: GroupUpdateZoneMessage): GroupDescriptor {
const position = message.getPosition();
if (position === undefined) {
throw new Error('Missing position');
throw new Error("Missing position");
}
return new GroupDescriptor(message.getGroupid(), message.getGroupsize(), position);
}
@ -97,7 +117,7 @@ export class GroupDescriptor {
public toGroupUpdateMessage(): GroupUpdateMessage {
const groupUpdateMessage = new GroupUpdateMessage();
if (!Number.isInteger(this.groupId)) {
throw new Error('GroupDescriptor.groupId is not an integer: '+this.groupId);
throw new Error("GroupDescriptor.groupId is not an integer: " + this.groupId);
}
groupUpdateMessage.setGroupid(this.groupId);
groupUpdateMessage.setGroupsize(this.groupSize);
@ -108,8 +128,8 @@ export class GroupDescriptor {
}
interface ZoneDescriptor {
x: number,
y: number
x: number;
y: number;
}
export class Zone {
@ -120,21 +140,26 @@ export class Zone {
private backConnection!: ClientReadableStream<BatchToPusherMessage>;
private isClosing: boolean = false;
constructor(private positionDispatcher: PositionDispatcher, private socketListener: ZoneEventListener, public readonly x: number, public readonly y: number, private onBackFailure: (e: Error|null, zone: Zone) => void) {
}
constructor(
private positionDispatcher: PositionDispatcher,
private socketListener: ZoneEventListener,
public readonly x: number,
public readonly y: number,
private onBackFailure: (e: Error | null, zone: Zone) => void
) {}
/**
* Creates a connection to the back server to track the users.
*/
public async init(): Promise<void> {
debug('Opening connection to zone %d, %d on back server', this.x, this.y);
debug("Opening connection to zone %d, %d on back server", this.x, this.y);
const apiClient = await apiClientRepository.getClient(this.positionDispatcher.roomId);
const zoneMessage = new ZoneMessage();
zoneMessage.setRoomid(this.positionDispatcher.roomId);
zoneMessage.setX(this.x);
zoneMessage.setY(this.y);
this.backConnection = apiClient.listenZone(zoneMessage);
this.backConnection.on('data', (batch: BatchToPusherMessage) => {
this.backConnection.on("data", (batch: BatchToPusherMessage) => {
for (const message of batch.getPayloadList()) {
if (message.hasUserjoinedzonemessage()) {
const userJoinedZoneMessage = message.getUserjoinedzonemessage() as UserJoinedZoneMessage;
@ -179,33 +204,32 @@ export class Zone {
const userDescriptor = this.users.get(userId);
if (userDescriptor === undefined) {
console.error('Unexpected move message received for user "'+userId+'"');
console.error('Unexpected move message received for user "' + userId + '"');
return;
}
userDescriptor.update(userMovedMessage);
this.notifyUserMove(userDescriptor);
} else if(message.hasEmoteeventmessage()) {
} else if (message.hasEmoteeventmessage()) {
const emoteEventMessage = message.getEmoteeventmessage() as EmoteEventMessage;
this.notifyEmote(emoteEventMessage);
} else {
throw new Error('Unexpected message');
throw new Error("Unexpected message");
}
}
});
this.backConnection.on('error', (e) => {
this.backConnection.on("error", (e) => {
if (!this.isClosing) {
debug('Error on back connection')
debug("Error on back connection");
this.close();
this.onBackFailure(e, this);
}
});
this.backConnection.on('close', () => {
this.backConnection.on("close", () => {
if (!this.isClosing) {
debug('Close on back connection')
debug("Close on back connection");
this.close();
this.onBackFailure(null, this);
}
@ -213,7 +237,7 @@ export class Zone {
}
public close(): void {
debug('Closing connection to zone %d, %d on back server', this.x, this.y);
debug("Closing connection to zone %d, %d on back server", this.x, this.y);
this.isClosing = true;
this.backConnection.cancel();
}
@ -225,7 +249,7 @@ export class Zone {
/**
* Notify listeners of this zone that this user entered
*/
private notifyUserEnter(user: UserDescriptor, oldZone: ZoneDescriptor|undefined) {
private notifyUserEnter(user: UserDescriptor, oldZone: ZoneDescriptor | undefined) {
for (const listener of this.listeners) {
if (listener.userId === user.userId) {
continue;
@ -241,7 +265,7 @@ export class Zone {
/**
* Notify listeners of this zone that this group entered
*/
private notifyGroupEnter(group: GroupDescriptor, oldZone: ZoneDescriptor|undefined) {
private notifyGroupEnter(group: GroupDescriptor, oldZone: ZoneDescriptor | undefined) {
for (const listener of this.listeners) {
if (oldZone === undefined || !this.isListeningZone(listener, oldZone.x, oldZone.y)) {
this.socketListener.onGroupEnters(group, listener);
@ -254,7 +278,7 @@ export class Zone {
/**
* Notify listeners of this zone that this user left
*/
private notifyUserLeft(userId: number, newZone: ZoneDescriptor|undefined) {
private notifyUserLeft(userId: number, newZone: ZoneDescriptor | undefined) {
for (const listener of this.listeners) {
if (listener.userId === userId) {
continue;
@ -279,7 +303,7 @@ export class Zone {
/**
* Notify listeners of this zone that this group left
*/
private notifyGroupLeft(groupId: number, newZone: ZoneDescriptor|undefined) {
private notifyGroupLeft(groupId: number, newZone: ZoneDescriptor | undefined) {
for (const listener of this.listeners) {
if (listener.groupId === groupId) {
continue;