Merge branch 'develop' of github.com:thecodingmachine/workadventure
This commit is contained in:
commit
579d6991bd
@ -68,14 +68,14 @@
|
||||
"@types/mkdirp": "^1.0.1",
|
||||
"@types/redis": "^2.8.31",
|
||||
"@types/uuidv4": "^5.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.26.0",
|
||||
"@typescript-eslint/parser": "^2.26.0",
|
||||
"eslint": "^6.8.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.8.0",
|
||||
"@typescript-eslint/parser": "^5.8.0",
|
||||
"eslint": "^8.5.0",
|
||||
"jasmine": "^3.5.0",
|
||||
"lint-staged": "^11.0.0",
|
||||
"prettier": "^2.3.1",
|
||||
"ts-node-dev": "^1.0.0-pre.44",
|
||||
"typescript": "^3.8.3"
|
||||
"ts-node-dev": "^1.1.8",
|
||||
"typescript": "^4.5.4"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.ts": [
|
||||
|
@ -10,6 +10,6 @@ App.listen(HTTP_PORT, () => console.log(`WorkAdventure HTTP API starting on port
|
||||
const server = new grpc.Server();
|
||||
server.addService<IRoomManagerServer>(RoomManagerService, roomManager);
|
||||
|
||||
server.bind('0.0.0.0:'+GRPC_PORT, grpc.ServerCredentials.createInsecure());
|
||||
server.bind(`0.0.0.0:${GRPC_PORT}`, grpc.ServerCredentials.createInsecure());
|
||||
server.start();
|
||||
console.log('WorkAdventure HTTP/2 API starting on port %d!', GRPC_PORT);
|
||||
|
@ -36,10 +36,12 @@ export class DebugController {
|
||||
return "BatchedMessages";
|
||||
}
|
||||
if (value instanceof Map) {
|
||||
const obj: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
const obj: { [key: string | number]: unknown } = {};
|
||||
for (const [mapKey, mapValue] of value.entries()) {
|
||||
if (typeof mapKey === "number" || typeof mapKey === "string") {
|
||||
obj[mapKey] = mapValue;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
} else if (value instanceof Set) {
|
||||
const obj: Array<unknown> = [];
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { App } from "../Server/sifrr.server";
|
||||
import { HttpRequest, HttpResponse } from "uWebSockets.js";
|
||||
const register = require("prom-client").register;
|
||||
const collectDefaultMetrics = require("prom-client").collectDefaultMetrics;
|
||||
import { register, collectDefaultMetrics } from "prom-client";
|
||||
|
||||
export class PrometheusController {
|
||||
constructor(private App: App) {
|
||||
collectDefaultMetrics({
|
||||
timeout: 10000,
|
||||
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5], // These are the default buckets.
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,13 @@ import { PointInterface } from "./Websocket/PointInterface";
|
||||
import { Group } from "./Group";
|
||||
import { User, UserSocket } from "./User";
|
||||
import { PositionInterface } from "_Model/PositionInterface";
|
||||
import { EmoteCallback, EntersCallback, LeavesCallback, MovesCallback } from "_Model/Zone";
|
||||
import {
|
||||
EmoteCallback,
|
||||
EntersCallback,
|
||||
LeavesCallback,
|
||||
MovesCallback,
|
||||
PlayerDetailsUpdatedCallback,
|
||||
} from "_Model/Zone";
|
||||
import { PositionNotifier } from "./PositionNotifier";
|
||||
import { Movable } from "_Model/Movable";
|
||||
import {
|
||||
@ -11,6 +17,7 @@ import {
|
||||
EmoteEventMessage,
|
||||
ErrorMessage,
|
||||
JoinRoomMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
SubToPusherRoomMessage,
|
||||
VariableMessage,
|
||||
VariableWithTagMessage,
|
||||
@ -27,6 +34,7 @@ import { ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
||||
import { LocalUrlError } from "../Services/LocalUrlError";
|
||||
import { emitErrorOnRoomSocket } from "../Services/MessageHelpers";
|
||||
import { VariableError } from "../Services/VariableError";
|
||||
import { isRoomRedirect } from "../Services/AdminApi/RoomRedirect";
|
||||
|
||||
export type ConnectCallback = (user: User, group: Group) => void;
|
||||
export type DisconnectCallback = (user: User, group: Group) => void;
|
||||
@ -56,10 +64,19 @@ export class GameRoom {
|
||||
onEnters: EntersCallback,
|
||||
onMoves: MovesCallback,
|
||||
onLeaves: LeavesCallback,
|
||||
onEmote: EmoteCallback
|
||||
onEmote: EmoteCallback,
|
||||
onPlayerDetailsUpdated: PlayerDetailsUpdatedCallback
|
||||
) {
|
||||
// A zone is 10 sprites wide.
|
||||
this.positionNotifier = new PositionNotifier(320, 320, onEnters, onMoves, onLeaves, onEmote);
|
||||
this.positionNotifier = new PositionNotifier(
|
||||
320,
|
||||
320,
|
||||
onEnters,
|
||||
onMoves,
|
||||
onLeaves,
|
||||
onEmote,
|
||||
onPlayerDetailsUpdated
|
||||
);
|
||||
}
|
||||
|
||||
public static async create(
|
||||
@ -71,7 +88,8 @@ export class GameRoom {
|
||||
onEnters: EntersCallback,
|
||||
onMoves: MovesCallback,
|
||||
onLeaves: LeavesCallback,
|
||||
onEmote: EmoteCallback
|
||||
onEmote: EmoteCallback,
|
||||
onPlayerDetailsUpdated: PlayerDetailsUpdatedCallback
|
||||
): Promise<GameRoom> {
|
||||
const mapDetails = await GameRoom.getMapDetails(roomUrl);
|
||||
|
||||
@ -85,7 +103,8 @@ export class GameRoom {
|
||||
onEnters,
|
||||
onMoves,
|
||||
onLeaves,
|
||||
onEmote
|
||||
onEmote,
|
||||
onPlayerDetailsUpdated
|
||||
);
|
||||
|
||||
return gameRoom;
|
||||
@ -180,6 +199,14 @@ export class GameRoom {
|
||||
this.updateUserGroup(user);
|
||||
}
|
||||
|
||||
updatePlayerDetails(user: User, playerDetailsMessage: SetPlayerDetailsMessage) {
|
||||
if (playerDetailsMessage.getRemoveoutlinecolor()) {
|
||||
user.outlineColor = undefined;
|
||||
} else {
|
||||
user.outlineColor = playerDetailsMessage.getOutlinecolor();
|
||||
}
|
||||
}
|
||||
|
||||
private updateUserGroup(user: User): void {
|
||||
user.group?.updatePosition();
|
||||
user.group?.searchForNearbyUsers();
|
||||
@ -256,9 +283,7 @@ export class GameRoom {
|
||||
this.positionNotifier.leave(group);
|
||||
group.destroy();
|
||||
if (!this.groups.has(group)) {
|
||||
throw new Error(
|
||||
"Could not find group " + group.getId() + " referenced by user " + user.id + " in World."
|
||||
);
|
||||
throw new Error(`Could not find group ${group.getId()} referenced by user ${user.id} in World.`);
|
||||
}
|
||||
this.groups.delete(group);
|
||||
//todo: is the group garbage collected?
|
||||
@ -459,9 +484,9 @@ export class GameRoom {
|
||||
}
|
||||
|
||||
const result = await adminApi.fetchMapDetails(roomUrl);
|
||||
if (!isMapDetailsData(result)) {
|
||||
console.error("Unexpected room details received from server", result);
|
||||
throw new Error("Unexpected room details received from server");
|
||||
if (isRoomRedirect(result)) {
|
||||
console.error("Unexpected room redirect received while querying map details", result);
|
||||
throw new Error("Unexpected room redirect received while querying map details");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ export class Group implements Movable {
|
||||
leave(user: User): void {
|
||||
const success = this.users.delete(user);
|
||||
if (success === false) {
|
||||
throw new Error("Could not find user " + user.id + " in the group " + this.id);
|
||||
throw new Error(`Could not find user ${user.id} in the group ${this.id}`);
|
||||
}
|
||||
user.group = undefined;
|
||||
|
||||
|
@ -8,12 +8,19 @@
|
||||
* 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 { EmoteCallback, EntersCallback, LeavesCallback, MovesCallback, Zone } from "./Zone";
|
||||
import {
|
||||
EmoteCallback,
|
||||
EntersCallback,
|
||||
LeavesCallback,
|
||||
MovesCallback,
|
||||
PlayerDetailsUpdatedCallback,
|
||||
Zone,
|
||||
} from "./Zone";
|
||||
import { Movable } from "_Model/Movable";
|
||||
import { PositionInterface } from "_Model/PositionInterface";
|
||||
import { ZoneSocket } from "../RoomManager";
|
||||
import { User } from "../Model/User";
|
||||
import { EmoteEventMessage } from "../Messages/generated/messages_pb";
|
||||
import { EmoteEventMessage, SetPlayerDetailsMessage } from "../Messages/generated/messages_pb";
|
||||
|
||||
interface ZoneDescriptor {
|
||||
i: number;
|
||||
@ -42,7 +49,8 @@ export class PositionNotifier {
|
||||
private onUserEnters: EntersCallback,
|
||||
private onUserMoves: MovesCallback,
|
||||
private onUserLeaves: LeavesCallback,
|
||||
private onEmote: EmoteCallback
|
||||
private onEmote: EmoteCallback,
|
||||
private onPlayerDetailsUpdated: PlayerDetailsUpdatedCallback
|
||||
) {}
|
||||
|
||||
private getZoneDescriptorFromCoordinates(x: number, y: number): ZoneDescriptor {
|
||||
@ -98,7 +106,15 @@ export class PositionNotifier {
|
||||
|
||||
let zone = this.zones[j][i];
|
||||
if (zone === undefined) {
|
||||
zone = new Zone(this.onUserEnters, this.onUserMoves, this.onUserLeaves, this.onEmote, i, j);
|
||||
zone = new Zone(
|
||||
this.onUserEnters,
|
||||
this.onUserMoves,
|
||||
this.onUserLeaves,
|
||||
this.onEmote,
|
||||
this.onPlayerDetailsUpdated,
|
||||
i,
|
||||
j
|
||||
);
|
||||
this.zones[j][i] = zone;
|
||||
}
|
||||
return zone;
|
||||
@ -132,4 +148,11 @@ export class PositionNotifier {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public updatePlayerDetails(user: User, playerDetails: SetPlayerDetailsMessage) {
|
||||
const position = user.getPosition();
|
||||
const zoneDesc = this.getZoneDescriptorFromCoordinates(position.x, position.y);
|
||||
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
||||
zone.updatePlayerDetails(user, playerDetails);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
CompanionMessage,
|
||||
PusherToBackMessage,
|
||||
ServerToClientMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
SubMessage,
|
||||
} from "../Messages/generated/messages_pb";
|
||||
import { CharacterLayer } from "_Model/Websocket/CharacterLayer";
|
||||
@ -31,7 +32,8 @@ export class User implements Movable {
|
||||
public readonly visitCardUrl: string | null,
|
||||
public readonly name: string,
|
||||
public readonly characterLayers: CharacterLayer[],
|
||||
public readonly companion?: CompanionMessage
|
||||
public readonly companion?: CompanionMessage,
|
||||
private _outlineColor?: number | undefined
|
||||
) {
|
||||
this.listenedZones = new Set<Zone>();
|
||||
|
||||
@ -69,4 +71,17 @@ export class User implements Movable {
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
public set outlineColor(value: number | undefined) {
|
||||
this._outlineColor = value;
|
||||
|
||||
const playerDetails = new SetPlayerDetailsMessage();
|
||||
if (value === undefined) {
|
||||
playerDetails.setRemoveoutlinecolor(true);
|
||||
} else {
|
||||
playerDetails.setOutlinecolor(value);
|
||||
}
|
||||
|
||||
this.positionNotifier.updatePlayerDetails(this, playerDetails);
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,20 @@ import { PositionInterface } from "_Model/PositionInterface";
|
||||
import { Movable } from "./Movable";
|
||||
import { Group } from "./Group";
|
||||
import { ZoneSocket } from "../RoomManager";
|
||||
import { EmoteEventMessage } from "../Messages/generated/messages_pb";
|
||||
import {
|
||||
EmoteEventMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
PlayerDetailsUpdatedMessage,
|
||||
} from "../Messages/generated/messages_pb";
|
||||
|
||||
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;
|
||||
export type EmoteCallback = (emoteEventMessage: EmoteEventMessage, listener: ZoneSocket) => void;
|
||||
export type PlayerDetailsUpdatedCallback = (
|
||||
playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage,
|
||||
listener: ZoneSocket
|
||||
) => void;
|
||||
|
||||
export class Zone {
|
||||
private things: Set<Movable> = new Set<Movable>();
|
||||
@ -19,6 +27,7 @@ export class Zone {
|
||||
private onMoves: MovesCallback,
|
||||
private onLeaves: LeavesCallback,
|
||||
private onEmote: EmoteCallback,
|
||||
private onPlayerDetailsUpdated: PlayerDetailsUpdatedCallback,
|
||||
public readonly x: number,
|
||||
public readonly y: number
|
||||
) {}
|
||||
@ -30,21 +39,13 @@ export class Zone {
|
||||
const result = this.things.delete(thing);
|
||||
if (!result) {
|
||||
if (thing instanceof User) {
|
||||
throw new Error("Could not find user in zone " + thing.id);
|
||||
throw new Error(`Could not find user in zone ${thing.id}`);
|
||||
}
|
||||
if (thing instanceof Group) {
|
||||
throw new Error(
|
||||
"Could not find group " +
|
||||
thing.getId() +
|
||||
" in zone (" +
|
||||
this.x +
|
||||
"," +
|
||||
this.y +
|
||||
"). Position of group: (" +
|
||||
thing.getPosition().x +
|
||||
"," +
|
||||
thing.getPosition().y +
|
||||
")"
|
||||
`Could not find group ${thing.getId()} in zone (${this.x},${this.y}). Position of group: (${
|
||||
thing.getPosition().x
|
||||
},${thing.getPosition().y})`
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -106,4 +107,14 @@ export class Zone {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
AdminPusherToBackMessage,
|
||||
AdminRoomMessage,
|
||||
BanMessage,
|
||||
BanUserMessage,
|
||||
BatchToPusherMessage,
|
||||
BatchToPusherRoomMessage,
|
||||
EmotePromptMessage,
|
||||
@ -16,7 +17,9 @@ import {
|
||||
QueryJitsiJwtMessage,
|
||||
RefreshRoomPromptMessage,
|
||||
RoomMessage,
|
||||
SendUserMessage,
|
||||
ServerToAdminClientMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
SilentMessage,
|
||||
UserMovesMessage,
|
||||
VariableMessage,
|
||||
@ -118,14 +121,17 @@ const roomManager: IRoomManagerServer = {
|
||||
);
|
||||
} else if (message.hasSendusermessage()) {
|
||||
const sendUserMessage = message.getSendusermessage();
|
||||
if (sendUserMessage !== undefined) {
|
||||
socketManager.handlerSendUserMessage(user, sendUserMessage);
|
||||
}
|
||||
socketManager.handleSendUserMessage(user, sendUserMessage as SendUserMessage);
|
||||
} else if (message.hasBanusermessage()) {
|
||||
const banUserMessage = message.getBanusermessage();
|
||||
if (banUserMessage !== undefined) {
|
||||
socketManager.handlerBanUserMessage(room, user, banUserMessage);
|
||||
}
|
||||
socketManager.handlerBanUserMessage(room, user, banUserMessage as BanUserMessage);
|
||||
} else if (message.hasSetplayerdetailsmessage()) {
|
||||
const setPlayerDetailsMessage = message.getSetplayerdetailsmessage();
|
||||
socketManager.handleSetPlayerDetails(
|
||||
room,
|
||||
user,
|
||||
setPlayerDetailsMessage as SetPlayerDetailsMessage
|
||||
);
|
||||
} else {
|
||||
throw new Error("Unhandled message type");
|
||||
}
|
||||
@ -160,7 +166,7 @@ const roomManager: IRoomManagerServer = {
|
||||
socketManager
|
||||
.addZoneListener(call, zoneMessage.getRoomid(), zoneMessage.getX(), zoneMessage.getY())
|
||||
.catch((e) => {
|
||||
emitErrorOnZoneSocket(call, e.toString());
|
||||
emitErrorOnZoneSocket(call, e);
|
||||
});
|
||||
|
||||
call.on("cancelled", () => {
|
||||
@ -190,7 +196,7 @@ const roomManager: IRoomManagerServer = {
|
||||
const roomMessage = call.request;
|
||||
|
||||
socketManager.addRoomListener(call, roomMessage.getRoomid()).catch((e) => {
|
||||
emitErrorOnRoomSocket(call, e.toString());
|
||||
emitErrorOnRoomSocket(call, e);
|
||||
});
|
||||
|
||||
call.on("cancelled", () => {
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable */
|
||||
|
||||
import { Readable } from "stream";
|
||||
import { us_listen_socket_close, TemplatedApp, HttpResponse, HttpRequest } from "uWebSockets.js";
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable */
|
||||
|
||||
import { createWriteStream } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
import Busboy from "busboy";
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable */
|
||||
|
||||
import { ReadStream } from "fs";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ADMIN_API_TOKEN, ADMIN_API_URL } from "../Enum/EnvironmentVariable";
|
||||
import Axios from "axios";
|
||||
import { MapDetailsData } from "./AdminApi/MapDetailsData";
|
||||
import { RoomRedirect } from "./AdminApi/RoomRedirect";
|
||||
import { isMapDetailsData, MapDetailsData } from "./AdminApi/MapDetailsData";
|
||||
import { isRoomRedirect, RoomRedirect } from "./AdminApi/RoomRedirect";
|
||||
|
||||
class AdminApi {
|
||||
async fetchMapDetails(playUri: string): Promise<MapDetailsData | RoomRedirect> {
|
||||
@ -17,6 +17,12 @@ class AdminApi {
|
||||
headers: { Authorization: `${ADMIN_API_TOKEN}` },
|
||||
params,
|
||||
});
|
||||
|
||||
if (!isMapDetailsData(res.data) && !isRoomRedirect(res.data)) {
|
||||
console.error("Unexpected answer from the /api/map admin endpoint.", res.data);
|
||||
throw new Error("Unexpected answer from the /api/map admin endpoint.");
|
||||
}
|
||||
|
||||
return res.data;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
const EventEmitter = require("events");
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
const clientJoinEvent = "clientJoin";
|
||||
const clientLeaveEvent = "clientLeave";
|
||||
|
@ -32,7 +32,7 @@ class MapFetcher {
|
||||
//throw new Error("Invalid map format for map " + mapUrl);
|
||||
console.error("Invalid map format for map " + mapUrl);
|
||||
}
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-unsafe-return */
|
||||
return res.data;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,19 @@ import {
|
||||
import { UserSocket } from "_Model/User";
|
||||
import { RoomSocket, ZoneSocket } from "../RoomManager";
|
||||
|
||||
export function emitError(Client: UserSocket, message: string): void {
|
||||
function getMessageFromError(error: unknown): string {
|
||||
if (error instanceof Error) {
|
||||
return error.message;
|
||||
} else if (typeof error === "string") {
|
||||
return error;
|
||||
} else {
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
export function emitError(Client: UserSocket, error: unknown): void {
|
||||
const message = getMessageFromError(error);
|
||||
|
||||
const errorMessage = new ErrorMessage();
|
||||
errorMessage.setMessage(message);
|
||||
|
||||
@ -23,8 +35,9 @@ export function emitError(Client: UserSocket, message: string): void {
|
||||
console.warn(message);
|
||||
}
|
||||
|
||||
export function emitErrorOnRoomSocket(Client: RoomSocket, message: string): void {
|
||||
console.error(message);
|
||||
export function emitErrorOnRoomSocket(Client: RoomSocket, error: unknown): void {
|
||||
console.error(error);
|
||||
const message = getMessageFromError(error);
|
||||
|
||||
const errorMessage = new ErrorMessage();
|
||||
errorMessage.setMessage(message);
|
||||
@ -41,8 +54,9 @@ export function emitErrorOnRoomSocket(Client: RoomSocket, message: string): void
|
||||
console.warn(message);
|
||||
}
|
||||
|
||||
export function emitErrorOnZoneSocket(Client: ZoneSocket, message: string): void {
|
||||
console.error(message);
|
||||
export function emitErrorOnZoneSocket(Client: ZoneSocket, error: unknown): void {
|
||||
console.error(error);
|
||||
const message = getMessageFromError(error);
|
||||
|
||||
const errorMessage = new ErrorMessage();
|
||||
errorMessage.setMessage(message);
|
||||
|
@ -33,6 +33,8 @@ import {
|
||||
VariableMessage,
|
||||
BatchToPusherRoomMessage,
|
||||
SubToPusherRoomMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
PlayerDetailsUpdatedMessage,
|
||||
} from "../Messages/generated/messages_pb";
|
||||
import { User, UserSocket } from "../Model/User";
|
||||
import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils";
|
||||
@ -151,20 +153,9 @@ export class SocketManager {
|
||||
//room.setViewport(client, client.viewport);
|
||||
}
|
||||
|
||||
// Useless now, will be useful again if we allow editing details in game
|
||||
/*handleSetPlayerDetails(client: UserSocket, playerDetailsMessage: SetPlayerDetailsMessage) {
|
||||
const playerDetails = {
|
||||
name: playerDetailsMessage.getName(),
|
||||
characterLayers: playerDetailsMessage.getCharacterlayersList()
|
||||
};
|
||||
//console.log(SocketIoEvent.SET_PLAYER_DETAILS, playerDetails);
|
||||
if (!isSetPlayerDetailsMessage(playerDetails)) {
|
||||
emitError(client, 'Invalid SET_PLAYER_DETAILS message received: ');
|
||||
return;
|
||||
handleSetPlayerDetails(room: GameRoom, user: User, playerDetailsMessage: SetPlayerDetailsMessage) {
|
||||
room.updatePlayerDetails(user, playerDetailsMessage);
|
||||
}
|
||||
client.name = playerDetails.name;
|
||||
client.characterLayers = SocketManager.mergeCharacterLayersAndCustomTextures(playerDetails.characterLayers, client.textures);
|
||||
}*/
|
||||
|
||||
handleSilentMessage(room: GameRoom, user: User, silentMessage: SilentMessage) {
|
||||
room.setSilent(user, silentMessage.getSilent());
|
||||
@ -206,7 +197,7 @@ export class SocketManager {
|
||||
webrtcSignalToClient.setSignal(data.getSignal());
|
||||
// TODO: only compute credentials if data.signal.type === "offer"
|
||||
if (TURN_STATIC_AUTH_SECRET !== "") {
|
||||
const { username, password } = this.getTURNCredentials("" + user.id, TURN_STATIC_AUTH_SECRET);
|
||||
const { username, password } = this.getTURNCredentials(user.id.toString(), TURN_STATIC_AUTH_SECRET);
|
||||
webrtcSignalToClient.setWebrtcusername(username);
|
||||
webrtcSignalToClient.setWebrtcpassword(password);
|
||||
}
|
||||
@ -236,7 +227,7 @@ export class SocketManager {
|
||||
webrtcSignalToClient.setSignal(data.getSignal());
|
||||
// TODO: only compute credentials if data.signal.type === "offer"
|
||||
if (TURN_STATIC_AUTH_SECRET !== "") {
|
||||
const { username, password } = this.getTURNCredentials("" + user.id, TURN_STATIC_AUTH_SECRET);
|
||||
const { username, password } = this.getTURNCredentials(user.id.toString(), TURN_STATIC_AUTH_SECRET);
|
||||
webrtcSignalToClient.setWebrtcusername(username);
|
||||
webrtcSignalToClient.setWebrtcpassword(password);
|
||||
}
|
||||
@ -282,7 +273,9 @@ export class SocketManager {
|
||||
(thing: Movable, newZone: Zone | null, listener: ZoneSocket) =>
|
||||
this.onClientLeave(thing, newZone, listener),
|
||||
(emoteEventMessage: EmoteEventMessage, listener: ZoneSocket) =>
|
||||
this.onEmote(emoteEventMessage, listener)
|
||||
this.onEmote(emoteEventMessage, listener),
|
||||
(playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage, listener: ZoneSocket) =>
|
||||
this.onPlayerDetailsUpdated(playerDetailsUpdatedMessage, listener)
|
||||
)
|
||||
.then((gameRoom) => {
|
||||
gaugeManager.incNbRoomGauge();
|
||||
@ -317,7 +310,7 @@ export class SocketManager {
|
||||
if (thing instanceof User) {
|
||||
const userJoinedZoneMessage = new UserJoinedZoneMessage();
|
||||
if (!Number.isInteger(thing.id)) {
|
||||
throw new Error("clientUser.userId is not an integer " + thing.id);
|
||||
throw new Error(`clientUser.userId is not an integer ${thing.id}`);
|
||||
}
|
||||
userJoinedZoneMessage.setUserid(thing.id);
|
||||
userJoinedZoneMessage.setUseruuid(thing.uuid);
|
||||
@ -329,6 +322,12 @@ export class SocketManager {
|
||||
userJoinedZoneMessage.setVisitcardurl(thing.visitCardUrl);
|
||||
}
|
||||
userJoinedZoneMessage.setCompanion(thing.companion);
|
||||
if (thing.outlineColor === undefined) {
|
||||
userJoinedZoneMessage.setHasoutline(false);
|
||||
} else {
|
||||
userJoinedZoneMessage.setHasoutline(true);
|
||||
userJoinedZoneMessage.setOutlinecolor(thing.outlineColor);
|
||||
}
|
||||
|
||||
const subMessage = new SubToPusherMessage();
|
||||
subMessage.setUserjoinedzonemessage(userJoinedZoneMessage);
|
||||
@ -378,6 +377,13 @@ export class SocketManager {
|
||||
emitZoneMessage(subMessage, client);
|
||||
}
|
||||
|
||||
private onPlayerDetailsUpdated(playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage, client: ZoneSocket) {
|
||||
const subMessage = new SubToPusherMessage();
|
||||
subMessage.setPlayerdetailsupdatedmessage(playerDetailsUpdatedMessage);
|
||||
|
||||
emitZoneMessage(subMessage, client);
|
||||
}
|
||||
|
||||
private emitCreateUpdateGroupEvent(client: ZoneSocket, fromZone: Zone | null, group: Group): void {
|
||||
const position = group.getPosition();
|
||||
const pointMessage = new PointMessage();
|
||||
@ -440,7 +446,10 @@ export class SocketManager {
|
||||
webrtcStartMessage1.setUserid(otherUser.id);
|
||||
webrtcStartMessage1.setInitiator(true);
|
||||
if (TURN_STATIC_AUTH_SECRET !== "") {
|
||||
const { username, password } = this.getTURNCredentials("" + otherUser.id, TURN_STATIC_AUTH_SECRET);
|
||||
const { username, password } = this.getTURNCredentials(
|
||||
otherUser.id.toString(),
|
||||
TURN_STATIC_AUTH_SECRET
|
||||
);
|
||||
webrtcStartMessage1.setWebrtcusername(username);
|
||||
webrtcStartMessage1.setWebrtcpassword(password);
|
||||
}
|
||||
@ -454,7 +463,7 @@ export class SocketManager {
|
||||
webrtcStartMessage2.setUserid(user.id);
|
||||
webrtcStartMessage2.setInitiator(false);
|
||||
if (TURN_STATIC_AUTH_SECRET !== "") {
|
||||
const { username, password } = this.getTURNCredentials("" + user.id, TURN_STATIC_AUTH_SECRET);
|
||||
const { username, password } = this.getTURNCredentials(user.id.toString(), TURN_STATIC_AUTH_SECRET);
|
||||
webrtcStartMessage2.setWebrtcusername(username);
|
||||
webrtcStartMessage2.setWebrtcpassword(password);
|
||||
}
|
||||
@ -478,7 +487,7 @@ export class SocketManager {
|
||||
hmac.setEncoding("base64");
|
||||
hmac.write(username);
|
||||
hmac.end();
|
||||
const password = hmac.read();
|
||||
const password = hmac.read() as string;
|
||||
return {
|
||||
username: username,
|
||||
password: password,
|
||||
@ -572,7 +581,7 @@ export class SocketManager {
|
||||
user.socket.write(serverToClientMessage);
|
||||
}
|
||||
|
||||
public handlerSendUserMessage(user: User, sendUserMessageToSend: SendUserMessage) {
|
||||
public handleSendUserMessage(user: User, sendUserMessageToSend: SendUserMessage) {
|
||||
const sendUserMessage = new SendUserMessage();
|
||||
sendUserMessage.setMessage(sendUserMessageToSend.getMessage());
|
||||
sendUserMessage.setType(sendUserMessageToSend.getType());
|
||||
|
@ -101,11 +101,11 @@ export class VariablesManager {
|
||||
}
|
||||
|
||||
// We store a copy of the object (to make it immutable)
|
||||
objects.set(object.name, this.iTiledObjectToVariable(object));
|
||||
objects.set(object.name as string, this.iTiledObjectToVariable(object));
|
||||
}
|
||||
}
|
||||
} else if (layer.type === "group") {
|
||||
for (const innerLayer of layer.layers) {
|
||||
for (const innerLayer of layer.layers as ITiledMapLayer[]) {
|
||||
this.recursiveFindVariablesInLayer(innerLayer, objects);
|
||||
}
|
||||
}
|
||||
@ -116,7 +116,7 @@ export class VariablesManager {
|
||||
|
||||
if (object.properties) {
|
||||
for (const property of object.properties) {
|
||||
const value = property.value;
|
||||
const value = property.value as unknown;
|
||||
switch (property.name) {
|
||||
case "default":
|
||||
variable.defaultValue = JSON.stringify(value);
|
||||
|
@ -51,7 +51,8 @@ describe("GameRoom", () => {
|
||||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
emote
|
||||
emote,
|
||||
() => {}
|
||||
);
|
||||
|
||||
const user1 = world.join(createMockUserSocket(), createJoinRoomMessage("1", 100, 100));
|
||||
@ -86,7 +87,8 @@ describe("GameRoom", () => {
|
||||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
emote
|
||||
emote,
|
||||
() => {}
|
||||
);
|
||||
|
||||
const user1 = world.join(createMockUserSocket(), createJoinRoomMessage("1", 100, 100));
|
||||
@ -125,7 +127,8 @@ describe("GameRoom", () => {
|
||||
() => {},
|
||||
() => {},
|
||||
() => {},
|
||||
emote
|
||||
emote,
|
||||
() => {}
|
||||
);
|
||||
|
||||
const user1 = world.join(createMockUserSocket(), createJoinRoomMessage("1", 100, 100));
|
||||
|
@ -19,7 +19,8 @@ describe("PositionNotifier", () => {
|
||||
moveTriggered = true;
|
||||
}, (thing: Movable) => {
|
||||
leaveTriggered = true;
|
||||
}, () => {});
|
||||
}, () => {},
|
||||
() => {});
|
||||
|
||||
const user1 = new User(1, 'test', '10.0.0.2', {
|
||||
x: 500,
|
||||
@ -94,7 +95,8 @@ describe("PositionNotifier", () => {
|
||||
moveTriggered = true;
|
||||
}, (thing: Movable) => {
|
||||
leaveTriggered = true;
|
||||
}, () => {});
|
||||
}, () => {},
|
||||
() => {});
|
||||
|
||||
const user1 = new User(1, 'test', '10.0.0.2', {
|
||||
x: 500,
|
||||
|
2668
back/yarn.lock
2668
back/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -106,3 +106,25 @@ Example :
|
||||
```javascript
|
||||
WA.player.onPlayerMove(console.log);
|
||||
```
|
||||
|
||||
### Set the outline color of the player
|
||||
```
|
||||
WA.player.setOutlineColor(red: number, green: number, blue: number): Promise<void>;
|
||||
WA.player.removeOutlineColor(): Promise<void>;
|
||||
```
|
||||
|
||||
You can display a thin line around your player's name (the "outline").
|
||||
|
||||
Use `setOutlineColor` to set the outline and `removeOutlineColor` to remove it.
|
||||
|
||||
Colors are expressed in RGB. Each parameter is an integer between 0 and 255.
|
||||
|
||||
```typescript
|
||||
// Let's add a red outline to our player
|
||||
WA.player.setOutlineColor(255, 0, 0);
|
||||
```
|
||||
|
||||
When you set the outline on your player, other players will see the outline too (the outline color is shared across
|
||||
browsers automatically).
|
||||
|
||||
![](images/outlines.png)
|
||||
|
@ -47,6 +47,7 @@
|
||||
"@types/socket.io-client": "^1.4.32",
|
||||
"axios": "^0.21.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"deep-copy-ts": "^0.5.0",
|
||||
"generic-type-guard": "^3.2.0",
|
||||
"google-protobuf": "^3.13.0",
|
||||
"nes.css": "^2.3.0",
|
||||
|
13
front/src/Api/Events/ColorEvent.ts
Normal file
13
front/src/Api/Events/ColorEvent.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
|
||||
export const isColorEvent = new tg.IsInterface()
|
||||
.withProperties({
|
||||
red: tg.isNumber,
|
||||
green: tg.isNumber,
|
||||
blue: tg.isNumber,
|
||||
})
|
||||
.get();
|
||||
/**
|
||||
* A message sent from the iFrame to the game to dynamically set the outline of the player.
|
||||
*/
|
||||
export type ColorEvent = tg.GuardedType<typeof isColorEvent>;
|
@ -29,6 +29,7 @@ import { isMessageReferenceEvent, isTriggerActionMessageEvent } from "./ui/Trigg
|
||||
import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEvent";
|
||||
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
||||
import type { ChangeZoneEvent } from "./ChangeZoneEvent";
|
||||
import { isColorEvent } from "./ColorEvent";
|
||||
import { isGetPropertyEvent } from "./GetPropertyEvent";
|
||||
|
||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||
@ -157,6 +158,14 @@ export const iframeQueryMapTypeGuards = {
|
||||
query: isCreateEmbeddedWebsiteEvent,
|
||||
answer: tg.isUndefined,
|
||||
},
|
||||
setPlayerOutline: {
|
||||
query: isColorEvent,
|
||||
answer: tg.isUndefined,
|
||||
},
|
||||
removePlayerOutline: {
|
||||
query: tg.isUndefined,
|
||||
answer: tg.isUndefined,
|
||||
},
|
||||
};
|
||||
|
||||
type GuardedType<T> = T extends (x: unknown) => x is infer T ? T : never;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
||||
import { IframeApiContribution, queryWorkadventure, sendToWorkadventure } from "./IframeApiContribution";
|
||||
import type { HasPlayerMovedEvent, HasPlayerMovedEventCallback } from "../Events/HasPlayerMovedEvent";
|
||||
import { Subject } from "rxjs";
|
||||
import { apiCallback } from "./registeredCallbacks";
|
||||
@ -82,6 +82,24 @@ export class WorkadventurePlayerCommands extends IframeApiContribution<Workadven
|
||||
}
|
||||
return userRoomToken;
|
||||
}
|
||||
|
||||
public setOutlineColor(red: number, green: number, blue: number): Promise<void> {
|
||||
return queryWorkadventure({
|
||||
type: "setPlayerOutline",
|
||||
data: {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public removeOutlineColor(): Promise<void> {
|
||||
return queryWorkadventure({
|
||||
type: "removePlayerOutline",
|
||||
data: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new WorkadventurePlayerCommands();
|
||||
|
@ -3,7 +3,10 @@
|
||||
import { banMessageVisibleStore, banMessageContentStore } from "../../Stores/TypeMessageStore/BanMessageStore";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
const text = $banMessageContentStore;
|
||||
let text: string;
|
||||
$: {
|
||||
text = $banMessageContentStore;
|
||||
}
|
||||
const NAME_BUTTON = "Ok";
|
||||
let nbSeconds = 10;
|
||||
let nameButton = "";
|
||||
|
@ -3,8 +3,11 @@
|
||||
import { textMessageContentStore, textMessageVisibleStore } from "../../Stores/TypeMessageStore/TextMessageStore";
|
||||
import { QuillDeltaToHtmlConverter } from "quill-delta-to-html";
|
||||
|
||||
let converter: QuillDeltaToHtmlConverter;
|
||||
$: {
|
||||
const content = JSON.parse($textMessageContentStore);
|
||||
const converter = new QuillDeltaToHtmlConverter(content.ops, { inlineStyles: true });
|
||||
converter = new QuillDeltaToHtmlConverter(content.ops, { inlineStyles: true });
|
||||
}
|
||||
const NAME_BUTTON = "Ok";
|
||||
|
||||
function closeTextMessage() {
|
||||
|
@ -18,6 +18,7 @@ export enum EventMessage {
|
||||
GROUP_DELETE = "group-delete",
|
||||
SET_PLAYER_DETAILS = "set-player-details", // Send the name and character to the server (on connect), receive back the id.
|
||||
ITEM_EVENT = "item-event",
|
||||
USER_DETAILS_UPDATED = "user-details-updated",
|
||||
|
||||
CONNECT_ERROR = "connect_error",
|
||||
CONNECTING_ERROR = "connecting_error",
|
||||
@ -64,6 +65,7 @@ export interface MessageUserJoined {
|
||||
visitCardUrl: string | null;
|
||||
companion: string | null;
|
||||
userUuid: string;
|
||||
outlineColor: number | undefined;
|
||||
}
|
||||
|
||||
export interface PositionInterface {
|
||||
@ -102,6 +104,12 @@ export interface ItemEventMessageInterface {
|
||||
parameters: unknown;
|
||||
}
|
||||
|
||||
export interface PlayerDetailsUpdatedMessageInterface {
|
||||
userId: number;
|
||||
outlineColor: number;
|
||||
removeOutlineColor: boolean;
|
||||
}
|
||||
|
||||
export interface RoomJoinedMessageInterface {
|
||||
//users: MessageUserPositionInterface[],
|
||||
//groups: GroupCreatedUpdatedMessageInterface[],
|
||||
|
@ -82,7 +82,7 @@ export class Room {
|
||||
const currentRoom = new Room(baseUrl);
|
||||
let instance: string = "global";
|
||||
if (currentRoom.isPublic) {
|
||||
instance = currentRoom.instance as string;
|
||||
instance = currentRoom.getInstance();
|
||||
}
|
||||
|
||||
baseUrl.pathname = "/_/" + instance + "/" + absoluteExitSceneUrl.host + absoluteExitSceneUrl.pathname;
|
||||
@ -104,9 +104,9 @@ export class Room {
|
||||
|
||||
const data = result.data;
|
||||
|
||||
if (isRoomRedirect(data.redirectUrl)) {
|
||||
if (isRoomRedirect(data)) {
|
||||
return {
|
||||
redirectUrl: data.redirectUrl as string,
|
||||
redirectUrl: data.redirectUrl,
|
||||
};
|
||||
} else if (isMapDetailsData(data)) {
|
||||
console.log("Map ", this.id, " resolves to URL ", data.mapUrl);
|
||||
|
@ -34,6 +34,7 @@ import {
|
||||
BanUserMessage,
|
||||
VariableMessage,
|
||||
ErrorMessage,
|
||||
PlayerDetailsUpdatedMessage,
|
||||
} from "../Messages/generated/messages_pb";
|
||||
|
||||
import type { UserSimplePeerInterface } from "../WebRtc/SimplePeer";
|
||||
@ -45,6 +46,7 @@ import {
|
||||
ItemEventMessageInterface,
|
||||
MessageUserJoined,
|
||||
OnConnectInterface,
|
||||
PlayerDetailsUpdatedMessageInterface,
|
||||
PlayGlobalMessageInterface,
|
||||
PositionInterface,
|
||||
RoomJoinedMessageInterface,
|
||||
@ -172,6 +174,9 @@ export class RoomConnection implements RoomConnection {
|
||||
} else if (subMessage.hasEmoteeventmessage()) {
|
||||
const emoteMessage = subMessage.getEmoteeventmessage() as EmoteEventMessage;
|
||||
emoteEventStream.fire(emoteMessage.getActoruserid(), emoteMessage.getEmote());
|
||||
} else if (subMessage.hasPlayerdetailsupdatedmessage()) {
|
||||
event = EventMessage.USER_DETAILS_UPDATED;
|
||||
payload = subMessage.getPlayerdetailsupdatedmessage();
|
||||
} else if (subMessage.hasErrormessage()) {
|
||||
const errorMessage = subMessage.getErrormessage() as ErrorMessage;
|
||||
console.error("An error occurred server side: " + errorMessage.getMessage());
|
||||
@ -276,7 +281,7 @@ export class RoomConnection implements RoomConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public emitPlayerDetailsMessage(userName: string, characterLayersSelected: BodyResourceDescriptionInterface[]) {
|
||||
/*public emitPlayerDetailsMessage(userName: string, characterLayersSelected: BodyResourceDescriptionInterface[]) {
|
||||
const message = new SetPlayerDetailsMessage();
|
||||
message.setName(userName);
|
||||
message.setCharacterlayersList(characterLayersSelected.map((characterLayer) => characterLayer.name));
|
||||
@ -284,6 +289,20 @@ export class RoomConnection implements RoomConnection {
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setSetplayerdetailsmessage(message);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}*/
|
||||
|
||||
public emitPlayerOutlineColor(color: number | null) {
|
||||
const message = new SetPlayerDetailsMessage();
|
||||
if (color === null) {
|
||||
message.setRemoveoutlinecolor(true);
|
||||
} else {
|
||||
message.setOutlinecolor(color);
|
||||
}
|
||||
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setSetplayerdetailsmessage(message);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
@ -404,6 +423,7 @@ export class RoomConnection implements RoomConnection {
|
||||
position: ProtobufClientUtils.toPointInterface(position),
|
||||
companion: companion ? companion.getName() : null,
|
||||
userUuid: message.getUseruuid(),
|
||||
outlineColor: message.getHasoutline() ? message.getOutlinecolor() : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@ -596,6 +616,20 @@ export class RoomConnection implements RoomConnection {
|
||||
});
|
||||
}
|
||||
|
||||
onPlayerDetailsUpdated(callback: (message: PlayerDetailsUpdatedMessageInterface) => void): void {
|
||||
this.onMessage(EventMessage.USER_DETAILS_UPDATED, (message: PlayerDetailsUpdatedMessage) => {
|
||||
const details = message.getDetails();
|
||||
if (details === undefined) {
|
||||
throw new Error("Malformed message. Missing details in PlayerDetailsUpdatedMessage");
|
||||
}
|
||||
callback({
|
||||
userId: message.getUserid(),
|
||||
outlineColor: details.getOutlinecolor(),
|
||||
removeOutlineColor: details.getRemoveoutlinecolor(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public uploadAudio(file: FormData) {
|
||||
return Axios.post(`${UPLOADER_URL}/upload-audio-message`, file)
|
||||
.then((res: { data: {} }) => {
|
||||
|
@ -13,7 +13,8 @@ import { isSilentStore } from "../../Stores/MediaStore";
|
||||
import { lazyLoadPlayerCharacterTextures, loadAllDefaultModels } from "./PlayerTexturesLoadingManager";
|
||||
import { TexturesHelper } from "../Helpers/TexturesHelper";
|
||||
import type { PictureStore } from "../../Stores/PictureStore";
|
||||
import { Writable, writable } from "svelte/store";
|
||||
import { Unsubscriber, Writable, writable } from "svelte/store";
|
||||
import { createColorStore } from "../../Stores/OutlineColorStore";
|
||||
|
||||
const playerNameY = -25;
|
||||
|
||||
@ -40,6 +41,8 @@ export abstract class Character extends Container {
|
||||
private emoteTween: Phaser.Tweens.Tween | null = null;
|
||||
scene: GameScene;
|
||||
private readonly _pictureStore: Writable<string | undefined>;
|
||||
private readonly outlineColorStore = createColorStore();
|
||||
private readonly outlineColorStoreUnsubscribe: Unsubscriber;
|
||||
|
||||
constructor(
|
||||
scene: GameScene,
|
||||
@ -97,18 +100,26 @@ export abstract class Character extends Container {
|
||||
});
|
||||
|
||||
this.on("pointerover", () => {
|
||||
this.getOutlinePlugin()?.add(this.playerName, {
|
||||
thickness: 2,
|
||||
outlineColor: 0xffff00,
|
||||
});
|
||||
this.scene.markDirty();
|
||||
this.outlineColorStore.pointerOver();
|
||||
});
|
||||
this.on("pointerout", () => {
|
||||
this.getOutlinePlugin()?.remove(this.playerName);
|
||||
this.scene.markDirty();
|
||||
this.outlineColorStore.pointerOut();
|
||||
});
|
||||
}
|
||||
|
||||
this.outlineColorStoreUnsubscribe = this.outlineColorStore.subscribe((color) => {
|
||||
if (color === undefined) {
|
||||
this.getOutlinePlugin()?.remove(this.playerName);
|
||||
} else {
|
||||
this.getOutlinePlugin()?.remove(this.playerName);
|
||||
this.getOutlinePlugin()?.add(this.playerName, {
|
||||
thickness: 2,
|
||||
outlineColor: color,
|
||||
});
|
||||
}
|
||||
this.scene.markDirty();
|
||||
});
|
||||
|
||||
scene.add.existing(this);
|
||||
|
||||
this.scene.physics.world.enableBody(this);
|
||||
@ -315,6 +326,7 @@ export abstract class Character extends Container {
|
||||
}
|
||||
}
|
||||
this.list.forEach((objectContaining) => objectContaining.destroy());
|
||||
this.outlineColorStoreUnsubscribe();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
@ -401,4 +413,12 @@ export abstract class Character extends Container {
|
||||
public get pictureStore(): PictureStore {
|
||||
return this._pictureStore;
|
||||
}
|
||||
|
||||
public setOutlineColor(color: number): void {
|
||||
this.outlineColorStore.setColor(color);
|
||||
}
|
||||
|
||||
public removeOutlineColor(): void {
|
||||
this.outlineColorStore.removeColor();
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ import type {
|
||||
MessageUserMovedInterface,
|
||||
MessageUserPositionInterface,
|
||||
OnConnectInterface,
|
||||
PlayerDetailsUpdatedMessageInterface,
|
||||
PointInterface,
|
||||
PositionInterface,
|
||||
RoomJoinedMessageInterface,
|
||||
@ -86,8 +87,11 @@ import GameObject = Phaser.GameObjects.GameObject;
|
||||
import DOMElement = Phaser.GameObjects.DOMElement;
|
||||
import Tileset = Phaser.Tilemaps.Tileset;
|
||||
import SpriteSheetFile = Phaser.Loader.FileTypes.SpriteSheetFile;
|
||||
import { deepCopy } from "deep-copy-ts";
|
||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||
import { MapStore } from "../../Stores/Utils/MapStore";
|
||||
import { SetPlayerDetailsMessage } from "../../Messages/generated/messages_pb";
|
||||
|
||||
export interface GameSceneInitInterface {
|
||||
initPosition: PointInterface | null;
|
||||
reconnecting: boolean;
|
||||
@ -123,6 +127,11 @@ interface DeleteGroupEventInterface {
|
||||
groupId: number;
|
||||
}
|
||||
|
||||
interface PlayerDetailsUpdatedInterface {
|
||||
type: "PlayerDetailsUpdated";
|
||||
details: PlayerDetailsUpdatedMessageInterface;
|
||||
}
|
||||
|
||||
export class GameScene extends DirtyScene {
|
||||
Terrains: Array<Phaser.Tilemaps.Tileset>;
|
||||
CurrentPlayer!: Player;
|
||||
@ -135,20 +144,14 @@ export class GameScene extends DirtyScene {
|
||||
groups: Map<number, Sprite>;
|
||||
circleTexture!: CanvasTexture;
|
||||
circleRedTexture!: CanvasTexture;
|
||||
pendingEvents: Queue<
|
||||
| InitUserPositionEventInterface
|
||||
| AddPlayerEventInterface
|
||||
| RemovePlayerEventInterface
|
||||
| UserMovedEventInterface
|
||||
| GroupCreatedUpdatedEventInterface
|
||||
| DeleteGroupEventInterface
|
||||
> = new Queue<
|
||||
pendingEvents = new Queue<
|
||||
| InitUserPositionEventInterface
|
||||
| AddPlayerEventInterface
|
||||
| RemovePlayerEventInterface
|
||||
| UserMovedEventInterface
|
||||
| GroupCreatedUpdatedEventInterface
|
||||
| DeleteGroupEventInterface
|
||||
| PlayerDetailsUpdatedInterface
|
||||
>();
|
||||
private initPosition: PositionInterface | null = null;
|
||||
private playersPositionInterpolator = new PlayersPositionInterpolator();
|
||||
@ -343,7 +346,10 @@ export class GameScene extends DirtyScene {
|
||||
private async onMapLoad(data: any): Promise<void> {
|
||||
// Triggered when the map is loaded
|
||||
// Load tiles attached to the map recursively
|
||||
this.mapFile = data.data;
|
||||
|
||||
// The map file can be modified by the scripting API and we don't want to tamper the Phaser cache (in case we come back on the map after visiting other maps)
|
||||
// So we are doing a deep copy
|
||||
this.mapFile = deepCopy(data.data);
|
||||
const url = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf("/"));
|
||||
this.mapFile.tilesets.forEach((tileset) => {
|
||||
if (typeof tileset.name === "undefined" || typeof tileset.image === "undefined") {
|
||||
@ -699,6 +705,7 @@ export class GameScene extends DirtyScene {
|
||||
visitCardUrl: message.visitCardUrl,
|
||||
companion: message.companion,
|
||||
userUuid: message.userUuid,
|
||||
outlineColor: message.outlineColor,
|
||||
};
|
||||
this.addPlayer(userMessage);
|
||||
});
|
||||
@ -752,6 +759,13 @@ export class GameScene extends DirtyScene {
|
||||
item.fire(message.event, message.state, message.parameters);
|
||||
});
|
||||
|
||||
this.connection.onPlayerDetailsUpdated((message) => {
|
||||
this.pendingEvents.enqueue({
|
||||
type: "PlayerDetailsUpdated",
|
||||
details: message,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Triggered when we receive the JWT token to connect to Jitsi
|
||||
*/
|
||||
@ -1333,6 +1347,21 @@ export class GameScene extends DirtyScene {
|
||||
iframeListener.registerAnswerer("removeActionMessage", (message) => {
|
||||
layoutManagerActionStore.removeAction(message.uuid);
|
||||
});
|
||||
|
||||
iframeListener.registerAnswerer("setPlayerOutline", (message) => {
|
||||
const normalizeColor = (color: number) => Math.min(Math.max(0, Math.round(color)), 255);
|
||||
const red = normalizeColor(message.red);
|
||||
const green = normalizeColor(message.green);
|
||||
const blue = normalizeColor(message.blue);
|
||||
const color = (red << 16) | (green << 8) | blue;
|
||||
this.CurrentPlayer.setOutlineColor(color);
|
||||
this.connection?.emitPlayerOutlineColor(color);
|
||||
});
|
||||
|
||||
iframeListener.registerAnswerer("removePlayerOutline", (message) => {
|
||||
this.CurrentPlayer.removeOutlineColor();
|
||||
this.connection?.emitPlayerOutlineColor(null);
|
||||
});
|
||||
}
|
||||
|
||||
private setPropertyLayer(
|
||||
@ -1455,6 +1484,7 @@ export class GameScene extends DirtyScene {
|
||||
iframeListener.unregisterAnswerer("removeActionMessage");
|
||||
iframeListener.unregisterAnswerer("openCoWebsite");
|
||||
iframeListener.unregisterAnswerer("getCoWebsites");
|
||||
iframeListener.unregisterAnswerer("setPlayerOutline");
|
||||
this.sharedVariablesManager?.close();
|
||||
this.embeddedWebsiteManager?.close();
|
||||
|
||||
@ -1709,6 +1739,12 @@ export class GameScene extends DirtyScene {
|
||||
case "DeleteGroupEvent":
|
||||
this.doDeleteGroup(event.groupId);
|
||||
break;
|
||||
case "PlayerDetailsUpdated":
|
||||
this.doUpdatePlayerDetails(event.details);
|
||||
break;
|
||||
default: {
|
||||
const tmp: never = event;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Let's move all users
|
||||
@ -1782,6 +1818,9 @@ export class GameScene extends DirtyScene {
|
||||
addPlayerData.companion,
|
||||
addPlayerData.companion !== null ? lazyLoadCompanionResource(this.load, addPlayerData.companion) : undefined
|
||||
);
|
||||
if (addPlayerData.outlineColor !== undefined) {
|
||||
player.setOutlineColor(addPlayerData.outlineColor);
|
||||
}
|
||||
this.MapPlayers.add(player);
|
||||
this.MapPlayersByKey.set(player.userId, player);
|
||||
player.updatePosition(addPlayerData.position);
|
||||
@ -1885,6 +1924,23 @@ export class GameScene extends DirtyScene {
|
||||
this.groups.delete(groupId);
|
||||
}
|
||||
|
||||
doUpdatePlayerDetails(message: PlayerDetailsUpdatedMessageInterface): void {
|
||||
const character = this.MapPlayersByKey.get(message.userId);
|
||||
if (character === undefined) {
|
||||
console.log(
|
||||
"Could not set new details to character with ID ",
|
||||
message.userId,
|
||||
". Did he/she left before te message was received?"
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (message.removeOutlineColor) {
|
||||
character.removeOutlineColor();
|
||||
} else {
|
||||
character.setOutlineColor(message.outlineColor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends to the server an event emitted by one of the ActionableItems.
|
||||
*/
|
||||
|
@ -8,4 +8,5 @@ export interface PlayerInterface {
|
||||
companion: string | null;
|
||||
userUuid: string;
|
||||
color?: string;
|
||||
outlineColor?: number;
|
||||
}
|
||||
|
@ -365,7 +365,9 @@ function applyCameraConstraints(currentStream: MediaStream | null, constraints:
|
||||
return;
|
||||
}
|
||||
for (const track of currentStream.getVideoTracks()) {
|
||||
toggleConstraints(track, constraints);
|
||||
toggleConstraints(track, constraints).catch((e) =>
|
||||
console.error("Error while setting new camera constraints:", e)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,19 +382,21 @@ function applyMicrophoneConstraints(
|
||||
return;
|
||||
}
|
||||
for (const track of currentStream.getAudioTracks()) {
|
||||
toggleConstraints(track, constraints);
|
||||
toggleConstraints(track, constraints).catch((e) =>
|
||||
console.error("Error while setting new audio constraints:", e)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleConstraints(track: MediaStreamTrack, constraints: MediaTrackConstraints | boolean): void {
|
||||
async function toggleConstraints(track: MediaStreamTrack, constraints: MediaTrackConstraints | boolean): Promise<void> {
|
||||
if (implementCorrectTrackBehavior) {
|
||||
track.enabled = constraints !== false;
|
||||
} else if (constraints === false) {
|
||||
track.stop();
|
||||
}
|
||||
// @ts-ignore
|
||||
|
||||
if (typeof constraints !== "boolean" && constraints !== true) {
|
||||
track.applyConstraints(constraints);
|
||||
return track.applyConstraints(constraints);
|
||||
}
|
||||
}
|
||||
|
||||
@ -484,7 +488,12 @@ export const localStreamStore = derived<Readable<MediaStreamConstraints>, LocalS
|
||||
type: "success",
|
||||
stream: null,
|
||||
});
|
||||
initStream(constraints);
|
||||
initStream(constraints).catch((e) => {
|
||||
set({
|
||||
type: "error",
|
||||
error: e instanceof Error ? e : new Error("An unknown error happened"),
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
//on bad navigators like chrome, we have to stop the tracks when we mute and reinstantiate the stream when we need to unmute
|
||||
@ -496,7 +505,12 @@ export const localStreamStore = derived<Readable<MediaStreamConstraints>, LocalS
|
||||
});
|
||||
} //we reemit the stream if it was muted just to be sure
|
||||
else if (constraints.audio /* && !oldConstraints.audio*/ || (!oldConstraints.video && constraints.video)) {
|
||||
initStream(constraints);
|
||||
initStream(constraints).catch((e) => {
|
||||
set({
|
||||
type: "error",
|
||||
error: e instanceof Error ? e : new Error("An unknown error happened"),
|
||||
});
|
||||
});
|
||||
}
|
||||
oldConstraints = {
|
||||
video: !!constraints.video,
|
||||
|
40
front/src/Stores/OutlineColorStore.ts
Normal file
40
front/src/Stores/OutlineColorStore.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
export function createColorStore() {
|
||||
const { subscribe, set } = writable<number | undefined>(undefined);
|
||||
|
||||
let color: number | undefined = undefined;
|
||||
let focused: boolean = false;
|
||||
|
||||
const updateColor = () => {
|
||||
if (focused) {
|
||||
set(0xffff00);
|
||||
} else {
|
||||
set(color);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
|
||||
pointerOver() {
|
||||
focused = true;
|
||||
updateColor();
|
||||
},
|
||||
|
||||
pointerOut() {
|
||||
focused = false;
|
||||
updateColor();
|
||||
},
|
||||
|
||||
setColor(newColor: number) {
|
||||
color = newColor;
|
||||
updateColor();
|
||||
},
|
||||
|
||||
removeColor() {
|
||||
color = undefined;
|
||||
updateColor();
|
||||
},
|
||||
};
|
||||
}
|
@ -98,7 +98,7 @@ export class SimplePeer {
|
||||
|
||||
private receiveWebrtcStart(user: UserSimplePeerInterface): void {
|
||||
this.Users.push(user);
|
||||
// Note: the clients array contain the list of all clients (even the ones we are already connected to in case a user joints a group)
|
||||
// Note: the clients array contain the list of all clients (even the ones we are already connected to in case a user joins a group)
|
||||
// So we can receive a request we already had before. (which will abort at the first line of createPeerConnection)
|
||||
// This would be symmetrical to the way we handle disconnection.
|
||||
|
||||
|
@ -1706,6 +1706,11 @@ dedent@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
|
||||
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
|
||||
|
||||
deep-copy-ts@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-copy-ts/-/deep-copy-ts-0.5.0.tgz#b9493d8e2bae85ef7d659c16eb707c13efb84499"
|
||||
integrity sha512-/3cgBcMkznRf5BM8wu6YWz3SQUkHzgh/v1TZFjevztLj9sMjFvNFBtpN4uUtPzw/rA/TldyD6c6LRL1zno4+YA==
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
|
||||
|
93
maps/tests/Outline/outline.json
Normal file
93
maps/tests/Outline/outline.json
Normal file
@ -0,0 +1,93 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":10,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"height":10,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"openWebsite",
|
||||
"type":"string",
|
||||
"value":"outline.php"
|
||||
},
|
||||
{
|
||||
"name":"openWebsiteAllowApi",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":342.082007343941,
|
||||
"id":1,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"Test:\nPlay with the colors and the limits in the form\n\nResult:\nThe outline should be displayed. A mouse over displays the yellow outline but the normal outline comes back on mouse out.\n\nTest:\nClick the remove outline\n\nResult:\nThe outline is removed\n\nTest:\nClick with many players\n\nResult:\nThe outline is correctly shared",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":274.96422378621,
|
||||
"x":35.7623688177162,
|
||||
"y":8.73391812865529
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":6,
|
||||
"nextobjectid":3,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":11,
|
||||
"firstgid":1,
|
||||
"image":"..\/tileset1.png",
|
||||
"imageheight":352,
|
||||
"imagewidth":352,
|
||||
"margin":0,
|
||||
"name":"tileset1",
|
||||
"spacing":0,
|
||||
"tilecount":121,
|
||||
"tileheight":32,
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":10
|
||||
}
|
36
maps/tests/Outline/outline.php
Normal file
36
maps/tests/Outline/outline.php
Normal file
@ -0,0 +1,36 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="<?php echo $_SERVER["FRONT_URL"] ?>/iframe_api.js"></script>
|
||||
<script>
|
||||
WA.onInit().then(() => {
|
||||
console.log('After WA init');
|
||||
const setOutlineButton = document.getElementById('setOutline');
|
||||
const removeOutlineButton = document.getElementById('removeOutline');
|
||||
const redField = document.getElementById('red');
|
||||
const greenField = document.getElementById('green');
|
||||
const blueField = document.getElementById('blue');
|
||||
|
||||
setOutlineButton.addEventListener('click', () => {
|
||||
console.log('SETTING OUTLINE');
|
||||
WA.player.setOutlineColor(parseInt(redField.value), parseInt(greenField.value), parseInt(blueField.value));
|
||||
});
|
||||
|
||||
removeOutlineButton.addEventListener('click', () => {
|
||||
console.log('REMOVING OUTLINE');
|
||||
WA.player.removeOutlineColor();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
red: <input type="text" id="red" value="0" /><br/>
|
||||
green: <input type="text" id="green" value="0" /><br/>
|
||||
blue: <input type="text" id="blue" value="0" /><br/>
|
||||
|
||||
<button id="setOutline">Set outline</button>
|
||||
|
||||
<button id="removeOutline">Remove outline</button>
|
||||
|
||||
</body>
|
||||
</html>
|
167
maps/tests/Properties/exitSceneUrl1.json
Normal file
167
maps/tests/Properties/exitSceneUrl1.json
Normal file
@ -0,0 +1,167 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":10,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"height":10,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
||||
"height":10,
|
||||
"id":7,
|
||||
"name":"walls",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":8,
|
||||
"name":"exit",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"exitSceneUrl",
|
||||
"type":"string",
|
||||
"value":"exitSceneUrl2.json"
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":9,
|
||||
"name":"from_exit2",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"startLayer",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":263.008397229317,
|
||||
"id":1,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"You are on Map 1\n\nTest:\nWalk through the exit.\n\nResult:\nYou should arrive to Map 2\n",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":249.954975648686,
|
||||
"x":35.2740564642832,
|
||||
"y":34.4372323693377
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":10,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":11,
|
||||
"firstgid":1,
|
||||
"image":"../tileset1.png",
|
||||
"imageheight":352,
|
||||
"imagewidth":352,
|
||||
"margin":0,
|
||||
"name":"tileset1",
|
||||
"spacing":0,
|
||||
"tilecount":121,
|
||||
"tileheight":32,
|
||||
"tiles":[
|
||||
{
|
||||
"id":16,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":17,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":18,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":19,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
}],
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":10
|
||||
}
|
149
maps/tests/Properties/exitSceneUrl2.json
Normal file
149
maps/tests/Properties/exitSceneUrl2.json
Normal file
@ -0,0 +1,149 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":10,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"height":10,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
||||
"height":10,
|
||||
"id":7,
|
||||
"name":"walls",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":8,
|
||||
"name":"exit",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"exitSceneUrl",
|
||||
"type":"string",
|
||||
"value":"exitSceneUrl1.json#from_exit2"
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":263.008397229317,
|
||||
"id":1,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":13,
|
||||
"text":"You are on Map 2\n\nTest:\nWalk back through the exit.\n\nResult:\nYou should arrive back to Map 1\n",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":249.954975648686,
|
||||
"x":35.2740564642832,
|
||||
"y":34.4372323693377
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":9,
|
||||
"nextobjectid":2,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":11,
|
||||
"firstgid":1,
|
||||
"image":"../tileset1.png",
|
||||
"imageheight":352,
|
||||
"imagewidth":352,
|
||||
"margin":0,
|
||||
"name":"tileset1",
|
||||
"spacing":0,
|
||||
"tilecount":121,
|
||||
"tileheight":32,
|
||||
"tiles":[
|
||||
{
|
||||
"id":16,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":17,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":18,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":19,
|
||||
"properties":[
|
||||
{
|
||||
"name":"collides",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
}],
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":10
|
||||
}
|
@ -64,6 +64,14 @@
|
||||
<a href="#" class="testLink" data-testmap="exit1.json" target="_blank">Test exits</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-exitSceneUrl"> Success <input type="radio" name="test-exitSceneUrl"> Failure <input type="radio" name="test-exitSceneUrl" checked> Pending
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="testLink" data-testmap="Properties/exitSceneUrl1.json" target="_blank">Test the (deprecated) exitSceneUrl property</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-start-tile-s1tos2"> Success <input type="radio" name="test-start-tile-s1tos2"> Failure <input type="radio" name="test-start-tile-s1tos2" checked> Pending
|
||||
@ -251,6 +259,14 @@
|
||||
<a href="#" class="testLink" data-testmap="ChangeLayerApi/change_layer_api.json" target="_blank">Testing scripting API for enters/leaves layer</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-outline-api"> Success <input type="radio" name="test-outline-api"> Failure <input type="radio" name="test-outline-api" checked> Pending
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="testLink" data-testmap="Outline/outline.json" target="_blank">Testing scripting API for outline on players</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2>CoWebsite</h2>
|
||||
<table class="table">
|
||||
|
@ -9,13 +9,13 @@ import { isNumber } from "generic-type-guard";
|
||||
|
||||
export const isMapDetailsData = new tg.IsInterface()
|
||||
.withProperties({
|
||||
roomSlug: tg.isOptional(tg.isString), // deprecated
|
||||
mapUrl: tg.isString,
|
||||
policy_type: isNumber, //isNumericEnum(GameRoomPolicyTypes),
|
||||
tags: tg.isArray(tg.isString),
|
||||
textures: tg.isArray(isCharacterTexture),
|
||||
contactPage: tg.isUnion(tg.isString, tg.isUndefined),
|
||||
authenticationMandatory: tg.isUnion(tg.isBoolean, tg.isUndefined),
|
||||
authenticationMandatory: tg.isUnion(tg.isNullable(tg.isBoolean), tg.isUndefined),
|
||||
roomSlug: tg.isNullable(tg.isString), // deprecated
|
||||
contactPage: tg.isNullable(tg.isString),
|
||||
group: tg.isNullable(tg.isString),
|
||||
})
|
||||
.withOptionalProperties({
|
||||
|
@ -47,8 +47,12 @@ message PingMessage {
|
||||
}
|
||||
|
||||
message SetPlayerDetailsMessage {
|
||||
string name = 1;
|
||||
repeated string characterLayers = 2;
|
||||
//string name = 1;
|
||||
//repeated string characterLayers = 2;
|
||||
|
||||
// TODO: switch to google.protobuf.Int32Value when we migrate to ts-proto
|
||||
uint32 outlineColor = 3;
|
||||
bool removeOutlineColor = 4;
|
||||
}
|
||||
|
||||
message UserMovesMessage {
|
||||
@ -150,6 +154,7 @@ message SubMessage {
|
||||
EmoteEventMessage emoteEventMessage = 7;
|
||||
VariableMessage variableMessage = 8;
|
||||
ErrorMessage errorMessage = 9;
|
||||
PlayerDetailsUpdatedMessage playerDetailsUpdatedMessage = 10;
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +181,8 @@ message UserJoinedMessage {
|
||||
CompanionMessage companion = 5;
|
||||
string visitCardUrl = 6;
|
||||
string userUuid = 7;
|
||||
uint32 outlineColor = 8;
|
||||
bool hasOutline = 9;
|
||||
}
|
||||
|
||||
message UserLeftMessage {
|
||||
@ -313,6 +320,8 @@ message UserJoinedZoneMessage {
|
||||
CompanionMessage companion = 6;
|
||||
string visitCardUrl = 7;
|
||||
string userUuid = 8;
|
||||
uint32 outlineColor = 9;
|
||||
bool hasOutline = 10;
|
||||
}
|
||||
|
||||
message UserLeftZoneMessage {
|
||||
@ -332,6 +341,10 @@ message GroupLeftZoneMessage {
|
||||
Zone toZone = 2;
|
||||
}
|
||||
|
||||
message PlayerDetailsUpdatedMessage {
|
||||
int32 userId = 1;
|
||||
SetPlayerDetailsMessage details = 2;
|
||||
}
|
||||
|
||||
message Zone {
|
||||
int32 x = 1;
|
||||
@ -384,6 +397,7 @@ message SubToPusherMessage {
|
||||
BanUserMessage banUserMessage = 8;
|
||||
EmoteEventMessage emoteEventMessage = 9;
|
||||
ErrorMessage errorMessage = 10;
|
||||
PlayerDetailsUpdatedMessage playerDetailsUpdatedMessage = 11;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,11 +60,11 @@ export class MapController extends BaseController {
|
||||
JSON.stringify({
|
||||
mapUrl,
|
||||
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
|
||||
roomSlug: "", // Deprecated
|
||||
roomSlug: null, // Deprecated
|
||||
group: null,
|
||||
tags: [],
|
||||
textures: [],
|
||||
contactPage: undefined,
|
||||
contactPage: null,
|
||||
authenticationMandatory: DISABLE_ANONYMOUS,
|
||||
} as MapDetailsData)
|
||||
);
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { App } from "../Server/sifrr.server";
|
||||
import { HttpRequest, HttpResponse } from "uWebSockets.js";
|
||||
const register = require("prom-client").register;
|
||||
const collectDefaultMetrics = require("prom-client").collectDefaultMetrics;
|
||||
import { register, collectDefaultMetrics } from "prom-client";
|
||||
|
||||
export class PrometheusController {
|
||||
constructor(private App: App) {
|
||||
collectDefaultMetrics({
|
||||
timeout: 10000,
|
||||
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5], // These are the default buckets.
|
||||
});
|
||||
|
||||
|
@ -16,6 +16,8 @@ import {
|
||||
EmoteEventMessage,
|
||||
CompanionMessage,
|
||||
ErrorMessage,
|
||||
PlayerDetailsUpdatedMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
} from "../Messages/generated/messages_pb";
|
||||
import { ClientReadableStream } from "grpc";
|
||||
import { PositionDispatcher } from "_Model/PositionDispatcher";
|
||||
@ -32,6 +34,7 @@ export interface ZoneEventListener {
|
||||
onGroupLeaves(groupId: number, listener: ExSocketInterface): void;
|
||||
onEmote(emoteMessage: EmoteEventMessage, listener: ExSocketInterface): void;
|
||||
onError(errorMessage: ErrorMessage, listener: ExSocketInterface): void;
|
||||
onPlayerDetailsUpdated(playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage, listener: ExSocketInterface): void;
|
||||
}
|
||||
|
||||
/*export type EntersCallback = (thing: Movable, listener: User) => void;
|
||||
@ -46,7 +49,8 @@ export class UserDescriptor {
|
||||
private characterLayers: CharacterLayerMessage[],
|
||||
private position: PositionMessage,
|
||||
private visitCardUrl: string | null,
|
||||
private companion?: CompanionMessage
|
||||
private companion?: CompanionMessage,
|
||||
private outlineColor?: number
|
||||
) {
|
||||
if (!Number.isInteger(this.userId)) {
|
||||
throw new Error("UserDescriptor.userId is not an integer: " + this.userId);
|
||||
@ -65,7 +69,8 @@ export class UserDescriptor {
|
||||
message.getCharacterlayersList(),
|
||||
position,
|
||||
message.getVisitcardurl(),
|
||||
message.getCompanion()
|
||||
message.getCompanion(),
|
||||
message.getHasoutline() ? message.getOutlinecolor() : undefined
|
||||
);
|
||||
}
|
||||
|
||||
@ -77,6 +82,14 @@ export class UserDescriptor {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public updateDetails(playerDetails: SetPlayerDetailsMessage) {
|
||||
if (playerDetails.getRemoveoutlinecolor()) {
|
||||
this.outlineColor = undefined;
|
||||
} else {
|
||||
this.outlineColor = playerDetails.getOutlinecolor();
|
||||
}
|
||||
}
|
||||
|
||||
public toUserJoinedMessage(): UserJoinedMessage {
|
||||
const userJoinedMessage = new UserJoinedMessage();
|
||||
|
||||
@ -89,6 +102,12 @@ export class UserDescriptor {
|
||||
}
|
||||
userJoinedMessage.setCompanion(this.companion);
|
||||
userJoinedMessage.setUseruuid(this.userUuid);
|
||||
if (this.outlineColor !== undefined) {
|
||||
userJoinedMessage.setOutlinecolor(this.outlineColor);
|
||||
userJoinedMessage.setHasoutline(true);
|
||||
} else {
|
||||
userJoinedMessage.setHasoutline(false);
|
||||
}
|
||||
|
||||
return userJoinedMessage;
|
||||
}
|
||||
@ -209,7 +228,7 @@ 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 unknown user "' + userId + '"');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -219,6 +238,27 @@ export class Zone {
|
||||
} else if (message.hasEmoteeventmessage()) {
|
||||
const emoteEventMessage = message.getEmoteeventmessage() as EmoteEventMessage;
|
||||
this.notifyEmote(emoteEventMessage);
|
||||
} else if (message.hasPlayerdetailsupdatedmessage()) {
|
||||
const playerDetailsUpdatedMessage =
|
||||
message.getPlayerdetailsupdatedmessage() as PlayerDetailsUpdatedMessage;
|
||||
|
||||
const userId = playerDetailsUpdatedMessage.getUserid();
|
||||
const userDescriptor = this.users.get(userId);
|
||||
|
||||
if (userDescriptor === undefined) {
|
||||
console.error('Unexpected details message received for unknown user "' + userId + '"');
|
||||
return;
|
||||
}
|
||||
|
||||
const details = playerDetailsUpdatedMessage.getDetails();
|
||||
if (details === undefined) {
|
||||
console.error('Unexpected details message without details received for user "' + userId + '"');
|
||||
return;
|
||||
}
|
||||
|
||||
userDescriptor.updateDetails(details);
|
||||
|
||||
this.notifyPlayerDetailsUpdated(playerDetailsUpdatedMessage);
|
||||
} else if (message.hasErrormessage()) {
|
||||
const errorMessage = message.getErrormessage() as ErrorMessage;
|
||||
this.notifyError(errorMessage);
|
||||
@ -308,6 +348,15 @@ export class Zone {
|
||||
}
|
||||
}
|
||||
|
||||
private notifyPlayerDetailsUpdated(playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage) {
|
||||
for (const listener of this.listeners) {
|
||||
if (listener.userId === playerDetailsUpdatedMessage.getUserid()) {
|
||||
continue;
|
||||
}
|
||||
this.socketListener.onPlayerDetailsUpdated(playerDetailsUpdatedMessage, listener);
|
||||
}
|
||||
}
|
||||
|
||||
private notifyError(errorMessage: ErrorMessage) {
|
||||
for (const listener of this.listeners) {
|
||||
this.socketListener.onError(errorMessage, listener);
|
||||
|
@ -1,4 +1,4 @@
|
||||
const EventEmitter = require("events");
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
const clientJoinEvent = "clientJoin";
|
||||
const clientLeaveEvent = "clientLeave";
|
||||
|
@ -34,7 +34,7 @@ import {
|
||||
VariableMessage,
|
||||
ErrorMessage,
|
||||
WorldFullMessage,
|
||||
PositionMessage,
|
||||
PlayerDetailsUpdatedMessage,
|
||||
} from "../Messages/generated/messages_pb";
|
||||
import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils";
|
||||
import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY, PUSHER_FORCE_ROOM_UPDATE } from "../Enum/EnvironmentVariable";
|
||||
@ -56,6 +56,7 @@ const debug = Debug("socket");
|
||||
interface AdminSocketRoomsList {
|
||||
[index: string]: number;
|
||||
}
|
||||
|
||||
interface AdminSocketUsersList {
|
||||
[index: string]: boolean;
|
||||
}
|
||||
@ -284,6 +285,16 @@ export class SocketManager implements ZoneEventListener {
|
||||
emitInBatch(listener, subMessage);
|
||||
}
|
||||
|
||||
onPlayerDetailsUpdated(
|
||||
playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage,
|
||||
listener: ExSocketInterface
|
||||
): void {
|
||||
const subMessage = new SubMessage();
|
||||
subMessage.setPlayerdetailsupdatedmessage(playerDetailsUpdatedMessage);
|
||||
|
||||
emitInBatch(listener, subMessage);
|
||||
}
|
||||
|
||||
onError(errorMessage: ErrorMessage, listener: ExSocketInterface): void {
|
||||
const subMessage = new SubMessage();
|
||||
subMessage.setErrormessage(errorMessage);
|
||||
|
@ -6,9 +6,11 @@ To run them locally:
|
||||
|
||||
```console
|
||||
$ npm install
|
||||
$ npm test
|
||||
$ ADMIN_API_TOKEN=123 npm test
|
||||
```
|
||||
|
||||
You'll need to adapt the `ADMIN_API_TOKEN` to the value you use in your `.env` file.
|
||||
|
||||
Alternatively, you can use docker-compose to run the tests:
|
||||
|
||||
```console
|
||||
|
565
tests/package-lock.json
generated
565
tests/package-lock.json
generated
@ -11,7 +11,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"dockerode": "^3.3.1",
|
||||
"testcafe": "^1.17.1"
|
||||
"testcafe": "^1.18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@ -2457,6 +2457,12 @@
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
@ -2955,6 +2961,15 @@
|
||||
"tar-stream": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.3.906",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.906.tgz",
|
||||
@ -3028,6 +3043,12 @@
|
||||
"stackframe": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-promise": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
@ -3177,12 +3198,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fp-ts": {
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.11.5.tgz",
|
||||
"integrity": "sha512-OqlwJq1BdpB83BZXTqI+dNcA6uYk6qk4u9Cgnt64Y+XS7dwdbp/mobx8S2KXf2AXH+scNmA/UVK3SEFHR3vHZA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@ -3502,6 +3543,27 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/io-ts": {
|
||||
"version": "2.2.16",
|
||||
"resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.16.tgz",
|
||||
"integrity": "sha512-y5TTSa6VP6le0hhmIyN0dqEXkrZeJLeC5KApJq6VLci3UEKF80lZ+KuoUs02RhBxNWlrqSNxzfI7otLX1Euv8Q==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"fp-ts": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/io-ts-types": {
|
||||
"version": "0.5.16",
|
||||
"resolved": "https://registry.npmjs.org/io-ts-types/-/io-ts-types-0.5.16.tgz",
|
||||
"integrity": "sha512-h9noYVfY9rlbmKI902SJdnV/06jgiT2chxG6lYDxaYNp88HscPi+SBCtmcU+m0E7WT5QSwt7sIMj93+qu0FEwQ==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"fp-ts": "^2.0.0",
|
||||
"io-ts": "^2.0.0",
|
||||
"monocle-ts": "^2.0.0",
|
||||
"newtype-ts": "^0.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ip": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||
@ -3676,6 +3738,16 @@
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/isomorphic-fetch": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz",
|
||||
"integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.1",
|
||||
"whatwg-fetch": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@ -3709,6 +3781,61 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken": {
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
|
||||
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jws": "^3.2.2",
|
||||
"lodash.includes": "^4.3.0",
|
||||
"lodash.isboolean": "^3.0.3",
|
||||
"lodash.isinteger": "^4.0.4",
|
||||
"lodash.isnumber": "^3.0.3",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.once": "^4.0.0",
|
||||
"ms": "^2.1.1",
|
||||
"semver": "^5.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4",
|
||||
"npm": ">=1.4.28"
|
||||
}
|
||||
},
|
||||
"node_modules/jwa": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"buffer-equal-constant-time": "1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jws": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jwa": "^1.4.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/linux-platform-info": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/linux-platform-info/-/linux-platform-info-0.0.3.tgz",
|
||||
@ -3743,6 +3870,48 @@
|
||||
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isboolean": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isinteger": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isnumber": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isstring": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.once": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/log-update-async-hook": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-update-async-hook/-/log-update-async-hook-2.0.2.tgz",
|
||||
@ -3921,6 +4090,15 @@
|
||||
"integrity": "sha512-KhKZRH21/+ihNRWrmdNFOyBptFi7nAWZFeFsRRpXkzgk/Yublb4fxyP0jU6EY1VDxUL/VUPdCmm/wAnpbfXdfw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/monocle-ts": {
|
||||
"version": "2.3.11",
|
||||
"resolved": "https://registry.npmjs.org/monocle-ts/-/monocle-ts-2.3.11.tgz",
|
||||
"integrity": "sha512-YJQdpDeKU0NNAecDjFgDDnDoivmf2nXsJZTRQdKh5jsPKG2lT/15dFnSuUcQoKB/VZN1z7jQ0B0bffbRFUtLmg==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"fp-ts": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -3952,6 +4130,28 @@
|
||||
"integrity": "sha512-4ug4BsuHxiVHoRUe1ud6rUFT3WUMmjXt1W0quL0CviZQANdan7D8kqN5/maw53hmAApY/jfzMRkC57BNNs60ZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/newtype-ts": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/newtype-ts/-/newtype-ts-0.3.4.tgz",
|
||||
"integrity": "sha512-lFJnWAt0oXX1j1ErNy9RU5+FPNtVyzugHW2MchaaMiOeeS9LEmqAAOqyHPFQ0Uw895jStSYGSCslrByzYxFJYQ==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"fp-ts": "^2.0.0",
|
||||
"monocle-ts": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.6",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
|
||||
"integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
|
||||
@ -4774,9 +4974,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/testcafe": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.17.1.tgz",
|
||||
"integrity": "sha512-G+IqL28PE9wzNKcLjLCjX3z3/KXpzNs0FNC63Y7dXcXx23qlx+yz+Abyh91CIzeiwtXDZX+xMXDYYLtPQLfhlQ==",
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.18.0.tgz",
|
||||
"integrity": "sha512-yM/d62TaJPzFri4LrCSvKlpDaBra3Ag4yvNyLKh0l0MJmctFz6jZpdWBkOPzuCQyQXE9rx3DWn8V0AFBZApCjA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.12.1",
|
||||
@ -4854,14 +5054,15 @@
|
||||
"semver": "^5.6.0",
|
||||
"source-map-support": "^0.5.16",
|
||||
"strip-bom": "^2.0.0",
|
||||
"testcafe-browser-tools": "2.0.16",
|
||||
"testcafe-hammerhead": "24.5.7",
|
||||
"testcafe-browser-tools": "2.0.19",
|
||||
"testcafe-hammerhead": "24.5.9",
|
||||
"testcafe-legacy-api": "5.1.2",
|
||||
"testcafe-reporter-dashboard": "0.2.5",
|
||||
"testcafe-reporter-json": "^2.1.0",
|
||||
"testcafe-reporter-list": "^2.1.0",
|
||||
"testcafe-reporter-minimal": "^2.1.0",
|
||||
"testcafe-reporter-spec": "^2.1.1",
|
||||
"testcafe-reporter-xunit": "^2.1.0",
|
||||
"testcafe-reporter-xunit": "^2.2.1",
|
||||
"time-limit-promise": "^1.0.2",
|
||||
"tmp": "0.0.28",
|
||||
"tree-kill": "^1.2.2",
|
||||
@ -4876,9 +5077,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/testcafe-browser-tools": {
|
||||
"version": "2.0.16",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-2.0.16.tgz",
|
||||
"integrity": "sha512-JljbS0FboABksIMEH1L7P4ZdI82AQ8saWb/7WsxkDCOtDuHID5ZSEb/w9tqLN1+4BQaCgS5veN3lWUnfb0saEA==",
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-2.0.19.tgz",
|
||||
"integrity": "sha512-MjFiT5EMUcNstAfAXM64mRdQrxjV5lEkDLFirCh/kjJ/TQ/XwdgIt0jG/VWU/CplVuqHTtw6JL4OIy7+O4iK1g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"array-find": "^1.0.0",
|
||||
@ -4886,6 +5087,7 @@
|
||||
"dedent": "^0.7.0",
|
||||
"del": "^5.1.0",
|
||||
"execa": "^3.3.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"graceful-fs": "^4.1.11",
|
||||
"linux-platform-info": "^0.0.3",
|
||||
"lodash": "^4.17.15",
|
||||
@ -5040,9 +5242,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/testcafe-hammerhead": {
|
||||
"version": "24.5.7",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-24.5.7.tgz",
|
||||
"integrity": "sha512-4pY6GQQaCZAlOolWB2vaYZ/MIpgtmOrZeh4BVbENkbh6DDiPeOxvC0K6yZS5JfINRau5S9mzuNkm2FS7G0urSA==",
|
||||
"version": "24.5.9",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-24.5.9.tgz",
|
||||
"integrity": "sha512-MESj4PhjiYAjgxmQMvszUbKLHgcZFhXNGIJY4G5Jrdn9/gf3ah3xfWQAdbQ86TVXy0z4ZNNQdU3TATdIBfIsQw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn-hammerhead": "0.5.0",
|
||||
@ -5168,6 +5370,24 @@
|
||||
"integrity": "sha1-DE/EHBAAxea5PUiwP4CDg3g06fY=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/testcafe-reporter-dashboard": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-dashboard/-/testcafe-reporter-dashboard-0.2.5.tgz",
|
||||
"integrity": "sha512-vbK8XrpbcFAEgnfWJOfqAnlmj/wt5pXXER/OSYI9RzSw+uwu8voLWbKcUAcnjltk0AM4c0wvI0DhjKmops2y2Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"es6-promise": "^4.2.8",
|
||||
"fp-ts": "^2.9.5",
|
||||
"io-ts": "^2.2.14",
|
||||
"io-ts-types": "^0.5.15",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"monocle-ts": "^2.3.5",
|
||||
"newtype-ts": "^0.3.4",
|
||||
"semver": "^5.6.0",
|
||||
"uuid": "3.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/testcafe-reporter-json": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-json/-/testcafe-reporter-json-2.2.0.tgz",
|
||||
@ -5196,9 +5416,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/testcafe-reporter-xunit": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz",
|
||||
"integrity": "sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM=",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.2.1.tgz",
|
||||
"integrity": "sha512-ge1msi8RyNVyK0QrsmC79zedV7jHasKpBPeOUZd/ORpbYLeYDnprjIeOuIukw0knnTieeYsOK29/ZD+UI7/tdw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/time-limit-promise": {
|
||||
@ -5277,6 +5497,12 @@
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
@ -5375,6 +5601,15 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unquote": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
|
||||
@ -5400,6 +5635,16 @@
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
|
||||
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==",
|
||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/webauth": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/webauth/-/webauth-1.1.0.tgz",
|
||||
@ -5409,6 +5654,28 @@
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/whatwg-fetch": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz",
|
||||
"integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@ -7240,6 +7507,12 @@
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=",
|
||||
"dev": true
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
@ -7646,6 +7919,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.906",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.906.tgz",
|
||||
@ -7709,6 +7991,12 @@
|
||||
"stackframe": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
|
||||
"dev": true
|
||||
},
|
||||
"escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
@ -7816,12 +8104,29 @@
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
|
||||
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA=="
|
||||
},
|
||||
"fp-ts": {
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.11.5.tgz",
|
||||
"integrity": "sha512-OqlwJq1BdpB83BZXTqI+dNcA6uYk6qk4u9Cgnt64Y+XS7dwdbp/mobx8S2KXf2AXH+scNmA/UVK3SEFHR3vHZA==",
|
||||
"dev": true
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"dev": true
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@ -8059,6 +8364,20 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"io-ts": {
|
||||
"version": "2.2.16",
|
||||
"resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.16.tgz",
|
||||
"integrity": "sha512-y5TTSa6VP6le0hhmIyN0dqEXkrZeJLeC5KApJq6VLci3UEKF80lZ+KuoUs02RhBxNWlrqSNxzfI7otLX1Euv8Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"io-ts-types": {
|
||||
"version": "0.5.16",
|
||||
"resolved": "https://registry.npmjs.org/io-ts-types/-/io-ts-types-0.5.16.tgz",
|
||||
"integrity": "sha512-h9noYVfY9rlbmKI902SJdnV/06jgiT2chxG6lYDxaYNp88HscPi+SBCtmcU+m0E7WT5QSwt7sIMj93+qu0FEwQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"ip": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||
@ -8185,6 +8504,16 @@
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||
"dev": true
|
||||
},
|
||||
"isomorphic-fetch": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz",
|
||||
"integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"node-fetch": "^2.6.1",
|
||||
"whatwg-fetch": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@ -8206,6 +8535,55 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"jsonwebtoken": {
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
|
||||
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jws": "^3.2.2",
|
||||
"lodash.includes": "^4.3.0",
|
||||
"lodash.isboolean": "^3.0.3",
|
||||
"lodash.isinteger": "^4.0.4",
|
||||
"lodash.isnumber": "^3.0.3",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.once": "^4.0.0",
|
||||
"ms": "^2.1.1",
|
||||
"semver": "^5.6.0"
|
||||
}
|
||||
},
|
||||
"jwa": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-equal-constant-time": "1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"jws": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jwa": "^1.4.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"linux-platform-info": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/linux-platform-info/-/linux-platform-info-0.0.3.tgz",
|
||||
@ -8237,6 +8615,48 @@
|
||||
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isboolean": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isinteger": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isnumber": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isstring": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.once": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=",
|
||||
"dev": true
|
||||
},
|
||||
"log-update-async-hook": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-update-async-hook/-/log-update-async-hook-2.0.2.tgz",
|
||||
@ -8380,6 +8800,13 @@
|
||||
"integrity": "sha512-KhKZRH21/+ihNRWrmdNFOyBptFi7nAWZFeFsRRpXkzgk/Yublb4fxyP0jU6EY1VDxUL/VUPdCmm/wAnpbfXdfw==",
|
||||
"dev": true
|
||||
},
|
||||
"monocle-ts": {
|
||||
"version": "2.3.11",
|
||||
"resolved": "https://registry.npmjs.org/monocle-ts/-/monocle-ts-2.3.11.tgz",
|
||||
"integrity": "sha512-YJQdpDeKU0NNAecDjFgDDnDoivmf2nXsJZTRQdKh5jsPKG2lT/15dFnSuUcQoKB/VZN1z7jQ0B0bffbRFUtLmg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -8405,6 +8832,22 @@
|
||||
"integrity": "sha512-4ug4BsuHxiVHoRUe1ud6rUFT3WUMmjXt1W0quL0CviZQANdan7D8kqN5/maw53hmAApY/jfzMRkC57BNNs60ZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"newtype-ts": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/newtype-ts/-/newtype-ts-0.3.4.tgz",
|
||||
"integrity": "sha512-lFJnWAt0oXX1j1ErNy9RU5+FPNtVyzugHW2MchaaMiOeeS9LEmqAAOqyHPFQ0Uw895jStSYGSCslrByzYxFJYQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.6",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
|
||||
"integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
|
||||
@ -9037,9 +9480,9 @@
|
||||
}
|
||||
},
|
||||
"testcafe": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.17.1.tgz",
|
||||
"integrity": "sha512-G+IqL28PE9wzNKcLjLCjX3z3/KXpzNs0FNC63Y7dXcXx23qlx+yz+Abyh91CIzeiwtXDZX+xMXDYYLtPQLfhlQ==",
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.18.0.tgz",
|
||||
"integrity": "sha512-yM/d62TaJPzFri4LrCSvKlpDaBra3Ag4yvNyLKh0l0MJmctFz6jZpdWBkOPzuCQyQXE9rx3DWn8V0AFBZApCjA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/core": "^7.12.1",
|
||||
@ -9117,14 +9560,15 @@
|
||||
"semver": "^5.6.0",
|
||||
"source-map-support": "^0.5.16",
|
||||
"strip-bom": "^2.0.0",
|
||||
"testcafe-browser-tools": "2.0.16",
|
||||
"testcafe-hammerhead": "24.5.7",
|
||||
"testcafe-browser-tools": "2.0.19",
|
||||
"testcafe-hammerhead": "24.5.9",
|
||||
"testcafe-legacy-api": "5.1.2",
|
||||
"testcafe-reporter-dashboard": "0.2.5",
|
||||
"testcafe-reporter-json": "^2.1.0",
|
||||
"testcafe-reporter-list": "^2.1.0",
|
||||
"testcafe-reporter-minimal": "^2.1.0",
|
||||
"testcafe-reporter-spec": "^2.1.1",
|
||||
"testcafe-reporter-xunit": "^2.1.0",
|
||||
"testcafe-reporter-xunit": "^2.2.1",
|
||||
"time-limit-promise": "^1.0.2",
|
||||
"tmp": "0.0.28",
|
||||
"tree-kill": "^1.2.2",
|
||||
@ -9133,9 +9577,9 @@
|
||||
}
|
||||
},
|
||||
"testcafe-browser-tools": {
|
||||
"version": "2.0.16",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-2.0.16.tgz",
|
||||
"integrity": "sha512-JljbS0FboABksIMEH1L7P4ZdI82AQ8saWb/7WsxkDCOtDuHID5ZSEb/w9tqLN1+4BQaCgS5veN3lWUnfb0saEA==",
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-2.0.19.tgz",
|
||||
"integrity": "sha512-MjFiT5EMUcNstAfAXM64mRdQrxjV5lEkDLFirCh/kjJ/TQ/XwdgIt0jG/VWU/CplVuqHTtw6JL4OIy7+O4iK1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-find": "^1.0.0",
|
||||
@ -9143,6 +9587,7 @@
|
||||
"dedent": "^0.7.0",
|
||||
"del": "^5.1.0",
|
||||
"execa": "^3.3.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"graceful-fs": "^4.1.11",
|
||||
"linux-platform-info": "^0.0.3",
|
||||
"lodash": "^4.17.15",
|
||||
@ -9266,9 +9711,9 @@
|
||||
}
|
||||
},
|
||||
"testcafe-hammerhead": {
|
||||
"version": "24.5.7",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-24.5.7.tgz",
|
||||
"integrity": "sha512-4pY6GQQaCZAlOolWB2vaYZ/MIpgtmOrZeh4BVbENkbh6DDiPeOxvC0K6yZS5JfINRau5S9mzuNkm2FS7G0urSA==",
|
||||
"version": "24.5.9",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-24.5.9.tgz",
|
||||
"integrity": "sha512-MESj4PhjiYAjgxmQMvszUbKLHgcZFhXNGIJY4G5Jrdn9/gf3ah3xfWQAdbQ86TVXy0z4ZNNQdU3TATdIBfIsQw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn-hammerhead": "0.5.0",
|
||||
@ -9378,6 +9823,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"testcafe-reporter-dashboard": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-dashboard/-/testcafe-reporter-dashboard-0.2.5.tgz",
|
||||
"integrity": "sha512-vbK8XrpbcFAEgnfWJOfqAnlmj/wt5pXXER/OSYI9RzSw+uwu8voLWbKcUAcnjltk0AM4c0wvI0DhjKmops2y2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es6-promise": "^4.2.8",
|
||||
"fp-ts": "^2.9.5",
|
||||
"io-ts": "^2.2.14",
|
||||
"io-ts-types": "^0.5.15",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"monocle-ts": "^2.3.5",
|
||||
"newtype-ts": "^0.3.4",
|
||||
"semver": "^5.6.0",
|
||||
"uuid": "3.3.3"
|
||||
}
|
||||
},
|
||||
"testcafe-reporter-json": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-json/-/testcafe-reporter-json-2.2.0.tgz",
|
||||
@ -9403,9 +9866,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"testcafe-reporter-xunit": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz",
|
||||
"integrity": "sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM=",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.2.1.tgz",
|
||||
"integrity": "sha512-ge1msi8RyNVyK0QrsmC79zedV7jHasKpBPeOUZd/ORpbYLeYDnprjIeOuIukw0knnTieeYsOK29/ZD+UI7/tdw==",
|
||||
"dev": true
|
||||
},
|
||||
"time-limit-promise": {
|
||||
@ -9468,6 +9931,12 @@
|
||||
"punycode": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
|
||||
"dev": true
|
||||
},
|
||||
"tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
@ -9538,6 +10007,12 @@
|
||||
"integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
|
||||
"dev": true
|
||||
},
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
},
|
||||
"unquote": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
|
||||
@ -9562,12 +10037,40 @@
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"dev": true
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
|
||||
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==",
|
||||
"dev": true
|
||||
},
|
||||
"webauth": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/webauth/-/webauth-1.1.0.tgz",
|
||||
"integrity": "sha1-ZHBPa4AmmGYFvDymKZUubib90QA=",
|
||||
"dev": true
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
|
||||
"dev": true
|
||||
},
|
||||
"whatwg-fetch": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz",
|
||||
"integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==",
|
||||
"dev": true
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"dockerode": "^3.3.1",
|
||||
"testcafe": "^1.17.1"
|
||||
"testcafe": "^1.18.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "testcafe"
|
||||
|
Loading…
Reference in New Issue
Block a user