Resolve conflit with GameScene.ts
This commit is contained in:
commit
fa4d917729
@ -3,7 +3,6 @@ const GROUP_RADIUS = process.env.GROUP_RADIUS ? Number(process.env.GROUP_RADIUS)
|
||||
const ALLOW_ARTILLERY = process.env.ALLOW_ARTILLERY ? process.env.ALLOW_ARTILLERY == 'true' : false;
|
||||
const ADMIN_API_URL = process.env.ADMIN_API_URL || '';
|
||||
const ADMIN_API_TOKEN = process.env.ADMIN_API_TOKEN || 'myapitoken';
|
||||
const MAX_USERS_PER_ROOM = parseInt(process.env.MAX_USERS_PER_ROOM || '') || 600;
|
||||
const CPU_OVERHEAT_THRESHOLD = Number(process.env.CPU_OVERHEAT_THRESHOLD) || 80;
|
||||
const JITSI_URL : string|undefined = (process.env.JITSI_URL === '') ? undefined : process.env.JITSI_URL;
|
||||
const JITSI_ISS = process.env.JITSI_ISS || '';
|
||||
@ -19,7 +18,6 @@ export {
|
||||
ADMIN_API_TOKEN,
|
||||
HTTP_PORT,
|
||||
GRPC_PORT,
|
||||
MAX_USERS_PER_ROOM,
|
||||
GROUP_RADIUS,
|
||||
ALLOW_ARTILLERY,
|
||||
CPU_OVERHEAT_THRESHOLD,
|
||||
|
@ -7,7 +7,6 @@ import {PositionNotifier} from "./PositionNotifier";
|
||||
import {Movable} from "_Model/Movable";
|
||||
import {extractDataFromPrivateRoomId, extractRoomSlugPublicRoomId, isRoomAnonymous} from "./RoomIdentifier";
|
||||
import {arrayIntersect} from "../Services/ArrayHelper";
|
||||
import {MAX_USERS_PER_ROOM} from "../Enum/EnvironmentVariable";
|
||||
import {JoinRoomMessage} from "../Messages/generated/messages_pb";
|
||||
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
|
||||
import {ZoneSocket} from "src/RoomManager";
|
||||
@ -116,8 +115,6 @@ export class GameRoom {
|
||||
this.nextUserId++;
|
||||
this.users.set(user.id, user);
|
||||
this.usersByUuid.set(user.uuid, user);
|
||||
// Let's call update position to trigger the join / leave room
|
||||
//this.updatePosition(socket, userPosition);
|
||||
this.updateUserGroup(user);
|
||||
|
||||
// Notify admins
|
||||
@ -149,10 +146,6 @@ export class GameRoom {
|
||||
}
|
||||
}
|
||||
|
||||
get isFull(): boolean {
|
||||
return this.users.size >= MAX_USERS_PER_ROOM;
|
||||
}
|
||||
|
||||
public isEmpty(): boolean {
|
||||
return this.users.size === 0 && this.admins.size === 0;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ const roomManager: IRoomManagerServer = {
|
||||
},
|
||||
ban(call: ServerUnaryCall<BanMessage>, callback: sendUnaryData<EmptyMessage>): void {
|
||||
// FIXME Work in progress
|
||||
socketManager.banUser(call.request.getRoomid(), call.request.getRecipientuuid(), 'foo bar TODO change this');
|
||||
socketManager.banUser(call.request.getRoomid(), call.request.getRecipientuuid(), call.request.getMessage());
|
||||
|
||||
callback(null, new EmptyMessage());
|
||||
},
|
||||
|
@ -690,7 +690,7 @@ export class SocketManager {
|
||||
public sendAdminMessage(roomId: string, recipientUuid: string, message: string): void {
|
||||
const room = this.rooms.get(roomId);
|
||||
if (!room) {
|
||||
console.error("In sendAdminMessage, could not find room with id '" + roomId + "'. Maybe the room was closed a few milliseconds ago and there was a race condition?");
|
||||
console.error("In sendAdminMessage, could not find room with id '" + roomId + "'. Maybe the room was closed a few milliseconds ago and there was a race condition?");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -704,10 +704,10 @@ export class SocketManager {
|
||||
sendUserMessage.setMessage(message);
|
||||
sendUserMessage.setType('ban'); //todo: is the type correct?
|
||||
|
||||
const subToPusherMessage = new SubToPusherMessage();
|
||||
subToPusherMessage.setSendusermessage(sendUserMessage);
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setSendusermessage(sendUserMessage);
|
||||
|
||||
recipient.socket.write(subToPusherMessage);
|
||||
recipient.socket.write(serverToClientMessage);
|
||||
}
|
||||
|
||||
public banUser(roomId: string, recipientUuid: string, message: string): void {
|
||||
@ -726,16 +726,15 @@ export class SocketManager {
|
||||
// Let's leave the room now.
|
||||
room.leave(recipient);
|
||||
|
||||
const sendUserMessage = new SendUserMessage();
|
||||
sendUserMessage.setMessage(message);
|
||||
sendUserMessage.setType('banned');
|
||||
const banUserMessage = new BanUserMessage();
|
||||
banUserMessage.setMessage(message);
|
||||
banUserMessage.setType('banned');
|
||||
|
||||
const subToPusherMessage = new SubToPusherMessage();
|
||||
subToPusherMessage.setSendusermessage(sendUserMessage);
|
||||
|
||||
recipient.socket.write(subToPusherMessage);
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setBanusermessage(banUserMessage);
|
||||
|
||||
// Let's close the connection when the user is banned.
|
||||
recipient.socket.write(serverToClientMessage);
|
||||
recipient.socket.end();
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,10 @@ export class TypeMessageExt implements TypeMessageInterface{
|
||||
}
|
||||
}
|
||||
}
|
||||
export class Ban extends TypeMessageExt {
|
||||
}
|
||||
|
||||
export class Message extends TypeMessageExt {}
|
||||
|
||||
export class Ban extends TypeMessageExt {}
|
||||
|
||||
export class Banned extends TypeMessageExt {
|
||||
showMessage(message: string){
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {Subject} from "rxjs";
|
||||
import {SendUserMessage} from "../Messages/generated/messages_pb";
|
||||
import {BanUserMessage, SendUserMessage} from "../Messages/generated/messages_pb";
|
||||
|
||||
export enum AdminMessageEventTypes {
|
||||
admin = 'message',
|
||||
@ -23,7 +23,7 @@ class AdminMessagesService {
|
||||
this.messageStream.subscribe((event) => console.log('message', event))
|
||||
}
|
||||
|
||||
onSendusermessage(message: SendUserMessage) {
|
||||
onSendusermessage(message: SendUserMessage|BanUserMessage) {
|
||||
this._messageStream.next({
|
||||
type: message.getType() as unknown as AdminMessageEventTypes,
|
||||
text: message.getMessage(),
|
||||
|
@ -6,11 +6,22 @@ import {GameConnexionTypes, urlManager} from "../Url/UrlManager";
|
||||
import {localUserStore} from "./LocalUserStore";
|
||||
import {LocalUser} from "./LocalUser";
|
||||
import {Room} from "./Room";
|
||||
import {Subject} from "rxjs";
|
||||
|
||||
export enum ConnexionMessageEventTypes {
|
||||
worldFull = 1,
|
||||
}
|
||||
|
||||
export interface ConnexionMessageEvent {
|
||||
type: ConnexionMessageEventTypes,
|
||||
}
|
||||
|
||||
class ConnectionManager {
|
||||
private localUser!:LocalUser;
|
||||
|
||||
private connexionType?: GameConnexionTypes
|
||||
|
||||
public _connexionMessageStream:Subject<ConnexionMessageEvent> = new Subject();
|
||||
/**
|
||||
* Tries to login to the node server and return the starting map url to be loaded
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {PlayerAnimationNames} from "../Phaser/Player/Animation";
|
||||
import {PlayerAnimationDirections} from "../Phaser/Player/Animation";
|
||||
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||
import {SignalData} from "simple-peer";
|
||||
import {RoomConnection} from "./RoomConnection";
|
||||
@ -42,14 +42,6 @@ export interface PointInterface {
|
||||
moving: boolean;
|
||||
}
|
||||
|
||||
export class Point implements PointInterface{
|
||||
constructor(public x : number, public y : number, public direction : string = PlayerAnimationNames.WalkDown, public moving : boolean = false) {
|
||||
if(x === null || y === null){
|
||||
throw Error("position x and y cannot be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface MessageUserPositionInterface {
|
||||
userId: number;
|
||||
name: string;
|
||||
@ -80,20 +72,10 @@ export interface GroupCreatedUpdatedMessageInterface {
|
||||
groupSize: number
|
||||
}
|
||||
|
||||
export interface WebRtcStartMessageInterface {
|
||||
roomId: string,
|
||||
clients: UserSimplePeerInterface[]
|
||||
}
|
||||
|
||||
export interface WebRtcDisconnectMessageInterface {
|
||||
userId: number
|
||||
}
|
||||
|
||||
export interface WebRtcSignalSentMessageInterface {
|
||||
receiverId: number,
|
||||
signal: SignalData
|
||||
}
|
||||
|
||||
export interface WebRtcSignalReceivedMessageInterface {
|
||||
userId: number,
|
||||
signal: SignalData,
|
||||
@ -113,11 +95,6 @@ export interface ViewportInterface {
|
||||
bottom: number,
|
||||
}
|
||||
|
||||
export interface BatchedMessageInterface {
|
||||
event: string,
|
||||
payload: unknown
|
||||
}
|
||||
|
||||
export interface ItemEventMessageInterface {
|
||||
itemId: number,
|
||||
event: string,
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
SendJitsiJwtMessage,
|
||||
CharacterLayerMessage,
|
||||
PingMessage,
|
||||
SendUserMessage
|
||||
SendUserMessage, BanUserMessage
|
||||
} from "../Messages/generated/messages_pb"
|
||||
|
||||
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||
@ -43,6 +43,7 @@ import {
|
||||
} from "./ConnexionModels";
|
||||
import {BodyResourceDescriptionInterface} from "../Phaser/Entity/PlayerTextures";
|
||||
import {adminMessagesService} from "./AdminMessagesService";
|
||||
import {connectionManager, ConnexionMessageEventTypes} from "./ConnectionManager";
|
||||
|
||||
const manualPingDelay = 20000;
|
||||
|
||||
@ -101,7 +102,7 @@ export class RoomConnection implements RoomConnection {
|
||||
}
|
||||
|
||||
// If we are not connected yet (if a JoinRoomMessage was not sent), we need to retry.
|
||||
if (this.userId === null) {
|
||||
if (this.userId === null && !this.closed) {
|
||||
this.dispatch(EventMessage.CONNECTING_ERROR, event);
|
||||
}
|
||||
});
|
||||
@ -156,7 +157,8 @@ export class RoomConnection implements RoomConnection {
|
||||
} as RoomJoinedMessageInterface
|
||||
});
|
||||
} else if (message.hasErrormessage()) {
|
||||
console.error(EventMessage.MESSAGE_ERROR, message.getErrormessage()?.getMessage());
|
||||
connectionManager._connexionMessageStream.next({type: ConnexionMessageEventTypes.worldFull}); //todo: generalize this behavior to all messages
|
||||
this.closed = true;
|
||||
} else if (message.hasWebrtcsignaltoclientmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_SIGNAL, message.getWebrtcsignaltoclientmessage());
|
||||
} else if (message.hasWebrtcscreensharingsignaltoclientmessage()) {
|
||||
@ -175,6 +177,8 @@ export class RoomConnection implements RoomConnection {
|
||||
this.dispatch(EventMessage.START_JITSI_ROOM, message.getSendjitsijwtmessage());
|
||||
} else if (message.hasSendusermessage()) {
|
||||
adminMessagesService.onSendusermessage(message.getSendusermessage() as SendUserMessage);
|
||||
} else if (message.hasBanusermessage()) {
|
||||
adminMessagesService.onSendusermessage(message.getSendusermessage() as BanUserMessage);
|
||||
} else {
|
||||
throw new Error('Unknown message received');
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {PlayerAnimationNames} from "../Player/Animation";
|
||||
import {PlayerAnimationDirections, PlayerAnimationTypes} from "../Player/Animation";
|
||||
import {SpeechBubble} from "./SpeechBubble";
|
||||
import BitmapText = Phaser.GameObjects.BitmapText;
|
||||
import Container = Phaser.GameObjects.Container;
|
||||
@ -10,8 +10,7 @@ interface AnimationData {
|
||||
frameRate: number;
|
||||
repeat: number;
|
||||
frameModel: string; //todo use an enum
|
||||
frameStart: number;
|
||||
frameEnd: number;
|
||||
frames : number[]
|
||||
}
|
||||
|
||||
export abstract class Character extends Container {
|
||||
@ -19,7 +18,7 @@ export abstract class Character extends Container {
|
||||
private readonly playerName: BitmapText;
|
||||
public PlayerValue: string;
|
||||
public sprites: Map<string, Sprite>;
|
||||
private lastDirection: string = PlayerAnimationNames.WalkDown;
|
||||
private lastDirection: PlayerAnimationDirections = PlayerAnimationDirections.Down;
|
||||
//private teleportation: Sprite;
|
||||
private invisible: boolean;
|
||||
|
||||
@ -28,7 +27,7 @@ export abstract class Character extends Container {
|
||||
y: number,
|
||||
texturesPromise: Promise<string[]>,
|
||||
name: string,
|
||||
direction: string,
|
||||
direction: PlayerAnimationDirections,
|
||||
moving: boolean,
|
||||
frame?: string | number
|
||||
) {
|
||||
@ -81,7 +80,7 @@ export abstract class Character extends Container {
|
||||
this.getPlayerAnimations(texture).forEach(d => {
|
||||
this.scene.anims.create({
|
||||
key: d.key,
|
||||
frames: this.scene.anims.generateFrameNumbers(d.frameModel, {start: d.frameStart, end: d.frameEnd}),
|
||||
frames: this.scene.anims.generateFrameNumbers(d.frameModel, {frames: d.frames}),
|
||||
frameRate: d.frameRate,
|
||||
repeat: d.repeat
|
||||
});
|
||||
@ -96,37 +95,57 @@ export abstract class Character extends Container {
|
||||
|
||||
private getPlayerAnimations(name: string): AnimationData[] {
|
||||
return [{
|
||||
key: `${name}-${PlayerAnimationNames.WalkDown}`,
|
||||
key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`,
|
||||
frameModel: name,
|
||||
frameStart: 0,
|
||||
frameEnd: 2,
|
||||
frames: [0, 1, 2, 1],
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
}, {
|
||||
key: `${name}-${PlayerAnimationNames.WalkLeft}`,
|
||||
key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`,
|
||||
frameModel: name,
|
||||
frameStart: 3,
|
||||
frameEnd: 5,
|
||||
frames: [3, 4, 5, 4],
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
}, {
|
||||
key: `${name}-${PlayerAnimationNames.WalkRight}`,
|
||||
key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`,
|
||||
frameModel: name,
|
||||
frameStart: 6,
|
||||
frameEnd: 8,
|
||||
frames: [6, 7, 8, 7],
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
}, {
|
||||
key: `${name}-${PlayerAnimationNames.WalkUp}`,
|
||||
key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`,
|
||||
frameModel: name,
|
||||
frameStart: 9,
|
||||
frameEnd: 11,
|
||||
frames: [9, 10, 11, 10],
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
},{
|
||||
key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`,
|
||||
frameModel: name,
|
||||
frames: [1],
|
||||
frameRate: 10,
|
||||
repeat: 1
|
||||
}, {
|
||||
key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`,
|
||||
frameModel: name,
|
||||
frames: [4],
|
||||
frameRate: 10,
|
||||
repeat: 1
|
||||
}, {
|
||||
key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`,
|
||||
frameModel: name,
|
||||
frames: [7],
|
||||
frameRate: 10,
|
||||
repeat: 1
|
||||
}, {
|
||||
key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`,
|
||||
frameModel: name,
|
||||
frames: [10],
|
||||
frameRate: 10,
|
||||
repeat: 1
|
||||
}];
|
||||
}
|
||||
|
||||
protected playAnimation(direction : string, moving: boolean): void {
|
||||
protected playAnimation(direction : PlayerAnimationDirections, moving: boolean): void {
|
||||
if (this.invisible) return;
|
||||
for (const [texture, sprite] of this.sprites.entries()) {
|
||||
if (!sprite.anims) {
|
||||
@ -134,10 +153,9 @@ export abstract class Character extends Container {
|
||||
return;
|
||||
}
|
||||
if (moving && (!sprite.anims.currentAnim || sprite.anims.currentAnim.key !== direction)) {
|
||||
sprite.play(texture+'-'+direction, true);
|
||||
sprite.play(texture+'-'+direction+'-'+PlayerAnimationTypes.Walk, true);
|
||||
} else if (!moving) {
|
||||
sprite.anims.play(texture + '-' + direction, true);
|
||||
sprite.anims.stop();
|
||||
sprite.anims.play(texture + '-' + direction + '-'+PlayerAnimationTypes.Idle, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,17 +175,17 @@ export abstract class Character extends Container {
|
||||
|
||||
// up or down animations are prioritized over left and right
|
||||
if (body.velocity.y < 0) { //moving up
|
||||
this.lastDirection = PlayerAnimationNames.WalkUp;
|
||||
this.playAnimation(PlayerAnimationNames.WalkUp, true);
|
||||
this.lastDirection = PlayerAnimationDirections.Up;
|
||||
this.playAnimation(PlayerAnimationDirections.Up, true);
|
||||
} else if (body.velocity.y > 0) { //moving down
|
||||
this.lastDirection = PlayerAnimationNames.WalkDown;
|
||||
this.playAnimation(PlayerAnimationNames.WalkDown, true);
|
||||
this.lastDirection = PlayerAnimationDirections.Down;
|
||||
this.playAnimation(PlayerAnimationDirections.Down, true);
|
||||
} else if (body.velocity.x > 0) { //moving right
|
||||
this.lastDirection = PlayerAnimationNames.WalkRight;
|
||||
this.playAnimation(PlayerAnimationNames.WalkRight, true);
|
||||
this.lastDirection = PlayerAnimationDirections.Right;
|
||||
this.playAnimation(PlayerAnimationDirections.Right, true);
|
||||
} else if (body.velocity.x < 0) { //moving left
|
||||
this.lastDirection = PlayerAnimationNames.WalkLeft;
|
||||
this.playAnimation(PlayerAnimationNames.WalkLeft, true);
|
||||
this.lastDirection = PlayerAnimationDirections.Left;
|
||||
this.playAnimation(PlayerAnimationDirections.Left, true);
|
||||
}
|
||||
|
||||
this.setDepth(this.y);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {GameScene} from "../Game/GameScene";
|
||||
import {PointInterface} from "../../Connexion/ConnexionModels";
|
||||
import {Character} from "../Entity/Character";
|
||||
import {PlayerAnimationDirections} from "../Player/Animation";
|
||||
|
||||
/**
|
||||
* Class representing the sprite of a remote player (a player that plays on another computer)
|
||||
@ -15,22 +16,17 @@ export class RemotePlayer extends Character {
|
||||
y: number,
|
||||
name: string,
|
||||
texturesPromise: Promise<string[]>,
|
||||
direction: string,
|
||||
direction: PlayerAnimationDirections,
|
||||
moving: boolean
|
||||
) {
|
||||
super(Scene, x, y, texturesPromise, name, direction, moving, 1);
|
||||
|
||||
//set data
|
||||
this.userId = userId;
|
||||
|
||||
//todo: implement on click action
|
||||
/*this.playerName.setInteractive();
|
||||
this.playerName.on('pointerup', () => {
|
||||
});*/
|
||||
}
|
||||
|
||||
updatePosition(position: PointInterface): void {
|
||||
this.playAnimation(position.direction, position.moving);
|
||||
this.playAnimation(position.direction as PlayerAnimationDirections, position.moving);
|
||||
this.setX(position.x);
|
||||
this.setY(position.y);
|
||||
|
||||
|
@ -3,27 +3,17 @@ import {
|
||||
GroupCreatedUpdatedMessageInterface,
|
||||
MessageUserJoined,
|
||||
MessageUserMovedInterface,
|
||||
MessageUserPositionInterface, OnConnectInterface,
|
||||
MessageUserPositionInterface,
|
||||
OnConnectInterface,
|
||||
PointInterface,
|
||||
PositionInterface,
|
||||
RoomJoinedMessageInterface
|
||||
} from "../../Connexion/ConnexionModels";
|
||||
import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player";
|
||||
import {
|
||||
DEBUG_MODE,
|
||||
JITSI_PRIVATE_MODE,
|
||||
POSITION_DELAY,
|
||||
RESOLUTION,
|
||||
ZOOM_LEVEL
|
||||
} from "../../Enum/EnvironmentVariable";
|
||||
import {
|
||||
ITiledMap,
|
||||
ITiledMapLayer,
|
||||
ITiledMapLayerProperty, ITiledMapObject,
|
||||
ITiledTileSet
|
||||
} from "../Map/ITiledMap";
|
||||
import {DEBUG_MODE, JITSI_PRIVATE_MODE, POSITION_DELAY, RESOLUTION, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable";
|
||||
import {ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapObject, ITiledTileSet} from "../Map/ITiledMap";
|
||||
import {AddPlayerInterface} from "./AddPlayerInterface";
|
||||
import {PlayerAnimationNames} from "../Player/Animation";
|
||||
import {PlayerAnimationDirections} from "../Player/Animation";
|
||||
import {PlayerMovement} from "./PlayerMovement";
|
||||
import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator";
|
||||
import {RemotePlayer} from "../Entity/RemotePlayer";
|
||||
@ -41,11 +31,6 @@ import {
|
||||
TRIGGER_WEBSITE_PROPERTIES,
|
||||
WEBSITE_MESSAGE_PROPERTIES
|
||||
} from "../../WebRtc/LayoutManager";
|
||||
import Texture = Phaser.Textures.Texture;
|
||||
import Sprite = Phaser.GameObjects.Sprite;
|
||||
import CanvasTexture = Phaser.Textures.CanvasTexture;
|
||||
import GameObject = Phaser.GameObjects.GameObject;
|
||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||
import {GameMap} from "./GameMap";
|
||||
import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager";
|
||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
@ -54,7 +39,7 @@ import {ActionableItem} from "../Items/ActionableItem";
|
||||
import {UserInputManager} from "../UserInput/UserInputManager";
|
||||
import {UserMovedMessage} from "../../Messages/generated/messages_pb";
|
||||
import {ProtobufClientUtils} from "../../Network/ProtobufClientUtils";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import {connectionManager, ConnexionMessageEvent, ConnexionMessageEventTypes} from "../../Connexion/ConnectionManager";
|
||||
import {RoomConnection} from "../../Connexion/RoomConnection";
|
||||
import {GlobalMessageManager} from "../../Administration/GlobalMessageManager";
|
||||
import {userMessageManager} from "../../Administration/UserMessageManager";
|
||||
@ -72,6 +57,12 @@ import {TextureError} from "../../Exception/TextureError";
|
||||
import {addLoader} from "../Components/Loader";
|
||||
import {ErrorSceneName} from "../Reconnecting/ErrorScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import Texture = Phaser.Textures.Texture;
|
||||
import Sprite = Phaser.GameObjects.Sprite;
|
||||
import CanvasTexture = Phaser.Textures.CanvasTexture;
|
||||
import GameObject = Phaser.GameObjects.GameObject;
|
||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||
import {Subscription} from "rxjs";
|
||||
import {iframeListener} from "../../Api/IframeListener";
|
||||
import DOMElement = Phaser.GameObjects.DOMElement;
|
||||
import Tween = Phaser.Tweens.Tween;
|
||||
@ -161,11 +152,12 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
// The item that can be selected by pressing the space key.
|
||||
private outlinedItem: ActionableItem|null = null;
|
||||
public userInputManager!: UserInputManager;
|
||||
private isReconnecting: boolean = false;
|
||||
private isReconnecting: boolean|undefined = undefined;
|
||||
private startLayerName!: string | null;
|
||||
private openChatIcon!: OpenChatIcon;
|
||||
private playerName!: string;
|
||||
private characterLayers!: string[];
|
||||
private messageSubscription: Subscription|null = null;
|
||||
private popUpElements : Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
||||
private objectLayerPopUp! : ITiledMapObject;
|
||||
|
||||
@ -300,25 +292,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// import(/* webpackIgnore: true */ scriptUrl).then(result => {
|
||||
//
|
||||
// result.default.preload(this.load);
|
||||
//
|
||||
// this.load.start(); // Let's manually start the loader because the import might be over AFTER the loading ends.
|
||||
// this.load.on('complete', () => {
|
||||
// // FIXME: the factory might fail because the resources might not be loaded yet...
|
||||
// // We would need to add a loader ended event in addition to the createPromise
|
||||
// this.createPromise.then(() => {
|
||||
// result.default.create(this);
|
||||
//
|
||||
// for (let object of objectsOfType) {
|
||||
// // TODO: we should pass here a factory to create sprites (maybe?)
|
||||
// let objectSprite = result.default.factory(this, object);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
// Now, let's load the script, if any
|
||||
@ -344,6 +317,8 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
urlManager.pushRoomIdToUrl(this.room);
|
||||
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
||||
|
||||
this.messageSubscription = connectionManager._connexionMessageStream.subscribe((event) => this.onConnexionMessage(event))
|
||||
|
||||
const playerName = gameManager.getPlayerName();
|
||||
if (!playerName) {
|
||||
throw 'playerName is not set';
|
||||
@ -414,13 +389,13 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
this.scene.launch(ReconnectingSceneName);
|
||||
}, 0);
|
||||
} else if (this.connection === undefined) {
|
||||
// Let's wait 0.5 seconds before printing the "connecting" screen to avoid blinking
|
||||
// Let's wait 1 second before printing the "connecting" screen to avoid blinking
|
||||
setTimeout(() => {
|
||||
if (this.connection === undefined) {
|
||||
this.scene.sleep();
|
||||
this.scene.launch(ReconnectingSceneName);
|
||||
}
|
||||
}, 500);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
this.createPromiseResolve();
|
||||
@ -583,8 +558,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
|
||||
//init user position and play trigger to check layers properties
|
||||
this.gameMap.setPosition(this.CurrentPlayer.x, this.CurrentPlayer.y);
|
||||
|
||||
return this.connection;
|
||||
});
|
||||
}
|
||||
|
||||
@ -622,29 +595,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
this.circleRedTexture.refresh();
|
||||
}
|
||||
|
||||
private playAudio(url: string|number|boolean|undefined, loop=false): void {
|
||||
if (url === undefined) {
|
||||
audioManager.unloadAudio();
|
||||
} else {
|
||||
const audioPath = url as string;
|
||||
let realAudioPath = '';
|
||||
|
||||
if (audioPath.indexOf('://') > 0) {
|
||||
// remote file or stream
|
||||
realAudioPath = audioPath;
|
||||
} else {
|
||||
// local file, include it relative to map directory
|
||||
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/'));
|
||||
realAudioPath = mapDirUrl + '/' + url;
|
||||
}
|
||||
|
||||
audioManager.loadAudio(realAudioPath);
|
||||
|
||||
if (loop) {
|
||||
audioManager.loop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private safeParseJSONstring(jsonString: string|undefined, propertyName: string) {
|
||||
try {
|
||||
@ -725,11 +675,11 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
}
|
||||
});
|
||||
this.gameMap.onPropertyChange('playAudio', (newValue, oldValue) => {
|
||||
this.playAudio(newValue);
|
||||
newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl());
|
||||
});
|
||||
|
||||
this.gameMap.onPropertyChange('playAudioLoop', (newValue, oldValue) => {
|
||||
this.playAudio(newValue, true);
|
||||
newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl());
|
||||
});
|
||||
|
||||
this.gameMap.onPropertyChange('zone', (newValue, oldValue) => {
|
||||
@ -813,6 +763,10 @@ ${escapedMessage}
|
||||
});
|
||||
}
|
||||
|
||||
private getMapDirUrl(): string {
|
||||
return this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/'));
|
||||
}
|
||||
|
||||
private onMapExit(exitKey: string) {
|
||||
const {roomId, hash} = Room.getIdFromIdentifier(exitKey, this.MapUrlFile, this.instance);
|
||||
if (!roomId) throw new Error('Could not find the room from its exit key: '+exitKey);
|
||||
@ -844,14 +798,11 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
this.stopJitsi();
|
||||
this.playAudio(undefined);
|
||||
audioManager.unloadAudio();
|
||||
// We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map.
|
||||
if(this.connection) {
|
||||
this.connection.closeConnection();
|
||||
}
|
||||
if(this.simplePeer) {
|
||||
this.simplePeer.unregister();
|
||||
}
|
||||
this.connection?.closeConnection();
|
||||
this.simplePeer?.unregister();
|
||||
this.messageSubscription?.unsubscribe();
|
||||
}
|
||||
|
||||
private removeAllRemotePlayers(): void {
|
||||
@ -1025,7 +976,7 @@ ${escapedMessage}
|
||||
this.startY,
|
||||
this.playerName,
|
||||
texturesPromise,
|
||||
PlayerAnimationNames.WalkDown,
|
||||
PlayerAnimationDirections.Down,
|
||||
false,
|
||||
this.userInputManager
|
||||
);
|
||||
@ -1074,16 +1025,16 @@ ${escapedMessage}
|
||||
let x = event.x;
|
||||
let y = event.y;
|
||||
switch (event.direction) {
|
||||
case PlayerAnimationNames.WalkUp:
|
||||
case PlayerAnimationDirections.Up:
|
||||
y -= 32;
|
||||
break;
|
||||
case PlayerAnimationNames.WalkDown:
|
||||
case PlayerAnimationDirections.Down:
|
||||
y += 32;
|
||||
break;
|
||||
case PlayerAnimationNames.WalkLeft:
|
||||
case PlayerAnimationDirections.Left:
|
||||
x -= 32;
|
||||
break;
|
||||
case PlayerAnimationNames.WalkRight:
|
||||
case PlayerAnimationDirections.Right:
|
||||
x += 32;
|
||||
break;
|
||||
default:
|
||||
@ -1219,7 +1170,7 @@ ${escapedMessage}
|
||||
addPlayerData.position.y,
|
||||
addPlayerData.name,
|
||||
texturesPromise,
|
||||
addPlayerData.position.direction,
|
||||
addPlayerData.position.direction as PlayerAnimationDirections,
|
||||
addPlayerData.position.moving
|
||||
);
|
||||
this.MapPlayers.add(player);
|
||||
@ -1394,21 +1345,34 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
public stopJitsi(): void {
|
||||
this.connection.setSilent(false);
|
||||
this.connection?.setSilent(false);
|
||||
jitsiFactory.stop();
|
||||
mediaManager.showGameOverlay();
|
||||
|
||||
mediaManager.removeTriggerCloseJitsiFrameButton('close-jisi');
|
||||
}
|
||||
|
||||
//todo: into onConnexionMessage
|
||||
private bannedUser(){
|
||||
this.cleanupClosingScene();
|
||||
this.userInputManager.clearAllKeys();
|
||||
this.scene.start(ErrorSceneName, {
|
||||
title: 'Banned',
|
||||
subTitle: 'You was banned of WorkAdventure',
|
||||
message: 'If you want more information, you can contact us: workadventure@thecodingmachine.com'
|
||||
subTitle: 'You were banned from WorkAdventure',
|
||||
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
|
||||
});
|
||||
}
|
||||
|
||||
private onConnexionMessage(event: ConnexionMessageEvent) {
|
||||
if (event.type === ConnexionMessageEventTypes.worldFull) {
|
||||
this.cleanupClosingScene();
|
||||
this.scene.stop(ReconnectingSceneName);
|
||||
this.userInputManager.clearAllKeys();
|
||||
this.scene.start(ErrorSceneName, {
|
||||
title: 'Connection rejected',
|
||||
subTitle: 'The world you are trying to join is full. Try again later.',
|
||||
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,8 +104,7 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
||||
gamePError.innerText = '';
|
||||
gamePError.style.display = 'none';
|
||||
const gameTextArea = this.getChildByID('gameReportInput') as HTMLInputElement;
|
||||
const gameIdUserReported = this.getChildByID('idUserReported') as HTMLInputElement;
|
||||
if(!gameTextArea || !gameTextArea.value ){
|
||||
if(!gameTextArea || !gameTextArea.value){
|
||||
gamePError.innerText = 'Report message cannot to be empty.';
|
||||
gamePError.style.display = 'block';
|
||||
return;
|
||||
@ -116,4 +115,4 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
|
||||
export enum PlayerAnimationNames {
|
||||
WalkDown = 'down',
|
||||
WalkLeft = 'left',
|
||||
WalkUp = 'up',
|
||||
WalkRight = 'right',
|
||||
export enum PlayerAnimationDirections {
|
||||
Down = 'down',
|
||||
Left = 'left',
|
||||
Up = 'up',
|
||||
Right = 'right',
|
||||
}
|
||||
export enum PlayerAnimationTypes {
|
||||
Walk = 'walk',
|
||||
Idle = 'idle',
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {PlayerAnimationNames} from "./Animation";
|
||||
import {PlayerAnimationDirections} from "./Animation";
|
||||
import {GameScene} from "../Game/GameScene";
|
||||
import {UserInputEvent, UserInputManager} from "../UserInput/UserInputManager";
|
||||
import {Character} from "../Entity/Character";
|
||||
@ -11,7 +11,7 @@ export interface CurrentGamerInterface extends Character{
|
||||
}
|
||||
|
||||
export class Player extends Character implements CurrentGamerInterface {
|
||||
private previousDirection: string = PlayerAnimationNames.WalkDown;
|
||||
private previousDirection: string = PlayerAnimationDirections.Down;
|
||||
private wasMoving: boolean = false;
|
||||
|
||||
constructor(
|
||||
@ -20,7 +20,7 @@ export class Player extends Character implements CurrentGamerInterface {
|
||||
y: number,
|
||||
name: string,
|
||||
texturesPromise: Promise<string[]>,
|
||||
direction: string,
|
||||
direction: PlayerAnimationDirections,
|
||||
moving: boolean,
|
||||
private userInputManager: UserInputManager
|
||||
) {
|
||||
@ -43,20 +43,20 @@ export class Player extends Character implements CurrentGamerInterface {
|
||||
let y = 0;
|
||||
if (activeEvents.get(UserInputEvent.MoveUp)) {
|
||||
y = - moveAmount;
|
||||
direction = PlayerAnimationNames.WalkUp;
|
||||
direction = PlayerAnimationDirections.Up;
|
||||
moving = true;
|
||||
} else if (activeEvents.get(UserInputEvent.MoveDown)) {
|
||||
y = moveAmount;
|
||||
direction = PlayerAnimationNames.WalkDown;
|
||||
direction = PlayerAnimationDirections.Down;
|
||||
moving = true;
|
||||
}
|
||||
if (activeEvents.get(UserInputEvent.MoveLeft)) {
|
||||
x = -moveAmount;
|
||||
direction = PlayerAnimationNames.WalkLeft;
|
||||
direction = PlayerAnimationDirections.Left;
|
||||
moving = true;
|
||||
} else if (activeEvents.get(UserInputEvent.MoveRight)) {
|
||||
x = moveAmount;
|
||||
direction = PlayerAnimationNames.WalkRight;
|
||||
direction = PlayerAnimationDirections.Right;
|
||||
moving = true;
|
||||
}
|
||||
if (x !== 0 || y !== 0) {
|
||||
|
@ -38,6 +38,25 @@ class AudioManager {
|
||||
HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_volume').value = '' + this.volume;
|
||||
}
|
||||
|
||||
public playAudio(url: string|number|boolean, mapDirUrl: string, loop=false): void {
|
||||
const audioPath = url as string;
|
||||
let realAudioPath = '';
|
||||
|
||||
if (audioPath.indexOf('://') > 0) {
|
||||
// remote file or stream
|
||||
realAudioPath = audioPath;
|
||||
} else {
|
||||
// local file, include it relative to map directory
|
||||
realAudioPath = mapDirUrl + '/' + url;
|
||||
}
|
||||
|
||||
this.loadAudio(realAudioPath);
|
||||
|
||||
if (loop) {
|
||||
this.loop();
|
||||
}
|
||||
}
|
||||
|
||||
private close(): void {
|
||||
this.audioPlayerCtrl.classList.remove('loading');
|
||||
this.audioPlayerCtrl.classList.add('hidden');
|
||||
@ -75,7 +94,7 @@ class AudioManager {
|
||||
}
|
||||
|
||||
|
||||
public loadAudio(url: string): void {
|
||||
private loadAudio(url: string): void {
|
||||
this.load();
|
||||
|
||||
/* Solution 1, remove whole audio player */
|
||||
@ -125,7 +144,7 @@ class AudioManager {
|
||||
this.open();
|
||||
}
|
||||
|
||||
public loop(): void {
|
||||
private loop(): void {
|
||||
if (this.audioPlayerElem !== undefined) {
|
||||
this.audioPlayerElem.loop = true;
|
||||
}
|
||||
|
@ -350,6 +350,7 @@ message AdminMessage {
|
||||
string message = 1;
|
||||
string recipientUuid = 2;
|
||||
string roomId = 3;
|
||||
string type = 4;
|
||||
}
|
||||
|
||||
// A message sent by an administrator to everyone in a specific room
|
||||
@ -366,6 +367,8 @@ message AdminGlobalMessage {
|
||||
message BanMessage {
|
||||
string recipientUuid = 1;
|
||||
string roomId = 2;
|
||||
string type = 3;
|
||||
string message = 4;
|
||||
}
|
||||
|
||||
message EmptyMessage {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {CharacterLayer, ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix import by "_Model/.."
|
||||
import {GameRoomPolicyTypes} from "../Model/PusherRoom";
|
||||
import {GameRoomPolicyTypes, PusherRoom} from "../Model/PusherRoom";
|
||||
import {PointInterface} from "../Model/Websocket/PointInterface";
|
||||
import {
|
||||
SetPlayerDetailsMessage,
|
||||
@ -20,7 +20,7 @@ import {parse} from "query-string";
|
||||
import {jwtTokenManager} from "../Services/JWTTokenManager";
|
||||
import {adminApi, CharacterTexture, FetchMemberDataByUuidResponse} from "../Services/AdminApi";
|
||||
import {SocketManager, socketManager} from "../Services/SocketManager";
|
||||
import {emitInBatch} from "../Services/IoSocketHelpers";
|
||||
import {emitError, emitInBatch} from "../Services/IoSocketHelpers";
|
||||
import {ADMIN_API_TOKEN, ADMIN_API_URL, SOCKET_IDLE_TIMER} from "../Enum/EnvironmentVariable";
|
||||
import {Zone} from "_Model/Zone";
|
||||
import {ExAdminSocketInterface} from "_Model/Websocket/ExAdminSocketInterface";
|
||||
@ -76,10 +76,10 @@ export class IoSocketController {
|
||||
if(message.event === 'user-message') {
|
||||
const messageToEmit = (message.message as { message: string, type: string, userUuid: string });
|
||||
if(messageToEmit.type === 'banned'){
|
||||
socketManager.emitBan(messageToEmit.userUuid, messageToEmit.message, messageToEmit.type);
|
||||
socketManager.emitBan(messageToEmit.userUuid, messageToEmit.message, messageToEmit.type, ws.roomId as string);
|
||||
}
|
||||
if(messageToEmit.type === 'ban') {
|
||||
socketManager.emitSendUserMessage(messageToEmit.userUuid, messageToEmit.message, messageToEmit.type);
|
||||
socketManager.emitSendUserMessage(messageToEmit.userUuid, messageToEmit.message, messageToEmit.type, ws.roomId as string);
|
||||
}
|
||||
}
|
||||
}catch (err) {
|
||||
@ -108,7 +108,6 @@ export class IoSocketController {
|
||||
maxBackpressure: 65536, // Maximum 64kB of data in the buffer.
|
||||
//idleTimeout: 10,
|
||||
upgrade: (res, req, context) => {
|
||||
//console.log('An Http connection wants to become WebSocket, URL: ' + req.getUrl() + '!');
|
||||
(async () => {
|
||||
/* Keep track of abortions */
|
||||
const upgradeAborted = {aborted: false};
|
||||
@ -156,12 +155,9 @@ export class IoSocketController {
|
||||
const userUuid = await jwtTokenManager.getUserUuidFromToken(token, IPAddress, roomId);
|
||||
|
||||
let memberTags: string[] = [];
|
||||
let memberMessages: unknown;
|
||||
let memberTextures: CharacterTexture[] = [];
|
||||
const room = await socketManager.getOrCreateRoom(roomId);
|
||||
// TODO: make sure the room isFull is ported in the back part.
|
||||
/*if(room.isFull){
|
||||
throw new Error('Room is full');
|
||||
}*/
|
||||
if (ADMIN_API_URL) {
|
||||
try {
|
||||
let userData : FetchMemberDataByUuidResponse = {
|
||||
@ -172,15 +168,26 @@ export class IoSocketController {
|
||||
anonymous: true
|
||||
};
|
||||
try {
|
||||
userData = await adminApi.fetchMemberDataByUuid(userUuid);
|
||||
userData = await adminApi.fetchMemberDataByUuid(userUuid, roomId);
|
||||
}catch (err){
|
||||
if (err?.response?.status == 404) {
|
||||
// If we get an HTTP 404, the token is invalid. Let's perform an anonymous login!
|
||||
console.warn('Cannot find user with uuid "'+userUuid+'". Performing an anonymous login instead.');
|
||||
} else if(err?.response?.status == 403) {
|
||||
// If we get an HTTP 404, the world is full. We need to broadcast a special error to the client.
|
||||
// we finish immediatly the upgrade then we will close the socket as soon as it starts opening.
|
||||
res.upgrade({
|
||||
rejected: true,
|
||||
}, websocketKey,
|
||||
websocketProtocol,
|
||||
websocketExtensions,
|
||||
context);
|
||||
return;
|
||||
}else{
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
memberMessages = userData.messages;
|
||||
memberTags = userData.tags;
|
||||
memberTextures = userData.textures;
|
||||
if (!room.anonymous && room.policyType === GameRoomPolicyTypes.USE_TAGS_POLICY && (userData.anonymous === true || !room.canAccess(memberTags))) {
|
||||
@ -215,6 +222,7 @@ export class IoSocketController {
|
||||
roomId,
|
||||
name,
|
||||
characterLayers: characterLayerObjs,
|
||||
messages: memberMessages,
|
||||
tags: memberTags,
|
||||
textures: memberTextures,
|
||||
position: {
|
||||
@ -241,7 +249,6 @@ export class IoSocketController {
|
||||
console.log(e.message);
|
||||
res.writeStatus("401 Unauthorized").end(e.message);
|
||||
} else {
|
||||
console.log(e);
|
||||
res.writeStatus("500 Internal Server Error").end('An error occurred');
|
||||
}
|
||||
return;
|
||||
@ -250,32 +257,30 @@ export class IoSocketController {
|
||||
},
|
||||
/* Handlers */
|
||||
open: (ws) => {
|
||||
if(ws.rejected === true) {
|
||||
emitError(ws, 'World is full');
|
||||
ws.close();
|
||||
}
|
||||
|
||||
// Let's join the room
|
||||
const client = this.initClient(ws); //todo: into the upgrade instead?
|
||||
socketManager.handleJoinRoom(client);
|
||||
|
||||
//get data information and show messages
|
||||
if (ADMIN_API_URL) {
|
||||
adminApi.fetchMemberDataByUuid(client.userUuid).then((res: FetchMemberDataByUuidResponse) => {
|
||||
if (!res.messages) {
|
||||
return;
|
||||
if (client.messages && Array.isArray(client.messages)) {
|
||||
client.messages.forEach((c: unknown) => {
|
||||
const messageToSend = c as { type: string, message: string };
|
||||
|
||||
const sendUserMessage = new SendUserMessage();
|
||||
sendUserMessage.setType(messageToSend.type);
|
||||
sendUserMessage.setMessage(messageToSend.message);
|
||||
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setSendusermessage(sendUserMessage);
|
||||
|
||||
if (!client.disconnecting) {
|
||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||
}
|
||||
res.messages.forEach((c: unknown) => {
|
||||
const messageToSend = c as { type: string, message: string };
|
||||
|
||||
const sendUserMessage = new SendUserMessage();
|
||||
sendUserMessage.setType(messageToSend.type);
|
||||
sendUserMessage.setMessage(messageToSend.message);
|
||||
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setSendusermessage(sendUserMessage);
|
||||
|
||||
if (!client.disconnecting) {
|
||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||
}
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.error('fetchMemberDataByUuid => err', err);
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -340,6 +345,7 @@ export class IoSocketController {
|
||||
}
|
||||
client.disconnecting = false;
|
||||
|
||||
client.messages = ws.messages;
|
||||
client.name = ws.name;
|
||||
client.tags = ws.tags;
|
||||
client.textures = ws.textures;
|
||||
|
@ -36,6 +36,7 @@ export interface ExSocketInterface extends WebSocket, Identificable {
|
||||
batchedMessages: BatchMessage;
|
||||
batchTimeout: NodeJS.Timeout|null;
|
||||
disconnecting: boolean,
|
||||
messages: unknown,
|
||||
tags: string[],
|
||||
textures: CharacterTexture[],
|
||||
backConnection: BackConnection,
|
||||
|
@ -58,12 +58,12 @@ class AdminApi {
|
||||
return res.data;
|
||||
}
|
||||
|
||||
async fetchMemberDataByUuid(uuid: string): Promise<FetchMemberDataByUuidResponse> {
|
||||
async fetchMemberDataByUuid(uuid: string, roomId: string): Promise<FetchMemberDataByUuidResponse> {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject('No admin backoffice set!');
|
||||
}
|
||||
const res = await Axios.get(ADMIN_API_URL+'/api/membership/'+uuid,
|
||||
{ headers: {"Authorization" : `${ADMIN_API_TOKEN}`} }
|
||||
const res = await Axios.get(ADMIN_API_URL+'/api/room/access',
|
||||
{ params: {uuid, roomId}, headers: {"Authorization" : `${ADMIN_API_TOKEN}`} }
|
||||
)
|
||||
return res.data;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
||||
import {BatchMessage, ErrorMessage, ServerToClientMessage, SubMessage} from "../Messages/generated/messages_pb";
|
||||
import {WebSocket} from "uWebSockets.js";
|
||||
|
||||
export function emitInBatch(socket: ExSocketInterface, payload: SubMessage): void {
|
||||
socket.batchedMessages.addPayload(payload);
|
||||
@ -20,7 +21,7 @@ export function emitInBatch(socket: ExSocketInterface, payload: SubMessage): voi
|
||||
}
|
||||
}
|
||||
|
||||
export function emitError(Client: ExSocketInterface, message: string): void {
|
||||
export function emitError(Client: WebSocket, message: string): void {
|
||||
const errorMessage = new ErrorMessage();
|
||||
errorMessage.setMessage(message);
|
||||
|
||||
|
@ -4,7 +4,6 @@ import {
|
||||
GroupDeleteMessage,
|
||||
ItemEventMessage,
|
||||
PlayGlobalMessage,
|
||||
PositionMessage,
|
||||
RoomJoinedMessage,
|
||||
ServerToClientMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
@ -23,23 +22,17 @@ import {
|
||||
AdminPusherToBackMessage,
|
||||
ServerToAdminClientMessage,
|
||||
SendUserMessage,
|
||||
BanUserMessage, UserJoinedRoomMessage, UserLeftRoomMessage
|
||||
BanUserMessage, UserJoinedRoomMessage, UserLeftRoomMessage, AdminMessage, BanMessage
|
||||
} from "../Messages/generated/messages_pb";
|
||||
import {PointInterface} from "../Model/Websocket/PointInterface";
|
||||
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
|
||||
import {cpuTracker} from "./CpuTracker";
|
||||
import {GROUP_RADIUS, JITSI_ISS, MINIMUM_DISTANCE, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable";
|
||||
import {Movable} from "../Model/Movable";
|
||||
import {PositionInterface} from "../Model/PositionInterface";
|
||||
import {JITSI_ISS, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable";
|
||||
import {adminApi, CharacterTexture} from "./AdminApi";
|
||||
import Direction = PositionMessage.Direction;
|
||||
import {emitError, emitInBatch} from "./IoSocketHelpers";
|
||||
import Jwt from "jsonwebtoken";
|
||||
import {JITSI_URL} from "../Enum/EnvironmentVariable";
|
||||
import {clientEventsEmitter} from "./ClientEventsEmitter";
|
||||
import {gaugeManager} from "./GaugeManager";
|
||||
import {apiClientRepository} from "./ApiClientRepository";
|
||||
import {ServiceError} from "grpc";
|
||||
import {GroupDescriptor, UserDescriptor, ZoneEventListener} from "_Model/Zone";
|
||||
import Debug from "debug";
|
||||
import {ExAdminSocketInterface} from "_Model/Websocket/ExAdminSocketInterface";
|
||||
@ -271,31 +264,6 @@ export class SocketManager implements ZoneEventListener {
|
||||
pusherToBackMessage.setItemeventmessage(itemEventMessage);
|
||||
|
||||
client.backConnection.write(pusherToBackMessage);
|
||||
|
||||
/*const itemEvent = ProtobufUtils.toItemEvent(itemEventMessage);
|
||||
|
||||
try {
|
||||
const world = this.Worlds.get(ws.roomId);
|
||||
if (!world) {
|
||||
console.error("Could not find world with id '", ws.roomId, "'");
|
||||
return;
|
||||
}
|
||||
|
||||
const subMessage = new SubMessage();
|
||||
subMessage.setItemeventmessage(itemEventMessage);
|
||||
|
||||
// Let's send the event without using the SocketIO room.
|
||||
for (const user of world.getUsers().values()) {
|
||||
const client = this.searchClientByIdOrFail(user.id);
|
||||
//client.emit(SocketIoEvent.ITEM_EVENT, itemEvent);
|
||||
emitInBatch(client, subMessage);
|
||||
}
|
||||
|
||||
world.setItemState(itemEvent.itemId, itemEvent.state);
|
||||
} catch (e) {
|
||||
console.error('An error occurred on "item_event"');
|
||||
console.error(e);
|
||||
}*/
|
||||
}
|
||||
|
||||
async handleReportMessage(client: ExSocketInterface, reportPlayerMessage: ReportPlayerMessage) {
|
||||
@ -317,25 +285,6 @@ export class SocketManager implements ZoneEventListener {
|
||||
pusherToBackMessage.setWebrtcsignaltoservermessage(data);
|
||||
|
||||
socket.backConnection.write(pusherToBackMessage);
|
||||
|
||||
|
||||
//send only at user
|
||||
/*const client = this.sockets.get(data.getReceiverid());
|
||||
if (client === undefined) {
|
||||
console.warn("While exchanging a WebRTC signal: client with id ", data.getReceiverid(), " does not exist. This might be a race condition.");
|
||||
return;
|
||||
}
|
||||
|
||||
const webrtcSignalToClient = new WebRtcSignalToClientMessage();
|
||||
webrtcSignalToClient.setUserid(socket.userId);
|
||||
webrtcSignalToClient.setSignal(data.getSignal());
|
||||
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setWebrtcsignaltoclientmessage(webrtcSignalToClient);
|
||||
|
||||
if (!client.disconnecting) {
|
||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||
}*/
|
||||
}
|
||||
|
||||
emitScreenSharing(socket: ExSocketInterface, data: WebRtcSignalToServerMessage): void {
|
||||
@ -343,24 +292,6 @@ export class SocketManager implements ZoneEventListener {
|
||||
pusherToBackMessage.setWebrtcscreensharingsignaltoservermessage(data);
|
||||
|
||||
socket.backConnection.write(pusherToBackMessage);
|
||||
|
||||
//send only at user
|
||||
/*const client = this.sockets.get(data.getReceiverid());
|
||||
if (client === undefined) {
|
||||
console.warn("While exchanging a WEBRTC_SCREEN_SHARING signal: client with id ", data.getReceiverid(), " does not exist. This might be a race condition.");
|
||||
return;
|
||||
}
|
||||
|
||||
const webrtcSignalToClient = new WebRtcSignalToClientMessage();
|
||||
webrtcSignalToClient.setUserid(socket.userId);
|
||||
webrtcSignalToClient.setSignal(data.getSignal());
|
||||
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setWebrtcscreensharingsignaltoclientmessage(webrtcSignalToClient);
|
||||
|
||||
if (!client.disconnecting) {
|
||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||
}*/
|
||||
}
|
||||
|
||||
private searchClientByIdOrFail(userId: number): ExSocketInterface {
|
||||
@ -408,17 +339,7 @@ export class SocketManager implements ZoneEventListener {
|
||||
//check and create new world for a room
|
||||
let world = this.Worlds.get(roomId)
|
||||
if(world === undefined){
|
||||
world = new PusherRoom(
|
||||
roomId,
|
||||
this
|
||||
/* (user: User, group: Group) => this.joinWebRtcRoom(user, group),
|
||||
(user: User, group: Group) => this.disConnectedUser(user, group),
|
||||
MINIMUM_DISTANCE,
|
||||
GROUP_RADIUS,
|
||||
(thing: Movable, listener: User) => this.onRoomEnter(thing, listener),
|
||||
(thing: Movable, position:PositionInterface, listener:User) => this.onClientMove(thing, position, listener),
|
||||
(thing: Movable, listener:User) => this.onClientLeave(thing, listener)*/
|
||||
);
|
||||
world = new PusherRoom(roomId, this);
|
||||
if (!world.anonymous) {
|
||||
const data = await adminApi.fetchMapDetails(world.organizationSlug, world.worldSlug, world.roomSlug)
|
||||
world.tags = data.tags
|
||||
@ -429,60 +350,6 @@ export class SocketManager implements ZoneEventListener {
|
||||
return Promise.resolve(world)
|
||||
}
|
||||
|
||||
/* private joinRoom(client : ExSocketInterface, position: PointInterface): PusherRoom {
|
||||
|
||||
const roomId = client.roomId;
|
||||
client.position = position;
|
||||
|
||||
const world = this.Worlds.get(roomId)
|
||||
if(world === undefined){
|
||||
throw new Error('Could not find room for ID: '+client.roomId)
|
||||
}
|
||||
|
||||
// Dispatch groups position to newly connected user
|
||||
world.getGroups().forEach((group: Group) => {
|
||||
this.emitCreateUpdateGroupEvent(client, group);
|
||||
});
|
||||
//join world
|
||||
world.join(client, client.position);
|
||||
clientEventsEmitter.emitClientJoin(client.userUuid, client.roomId);
|
||||
console.log(new Date().toISOString() + ' A user joined (', this.sockets.size, ' connected users)');
|
||||
return world;
|
||||
}
|
||||
|
||||
private onClientMove(thing: Movable, position:PositionInterface, listener:User): void {
|
||||
const clientListener = this.searchClientByIdOrFail(listener.id);
|
||||
if (thing instanceof User) {
|
||||
const clientUser = this.searchClientByIdOrFail(thing.id);
|
||||
|
||||
const userMovedMessage = new UserMovedMessage();
|
||||
userMovedMessage.setUserid(clientUser.userId);
|
||||
userMovedMessage.setPosition(ProtobufUtils.toPositionMessage(clientUser.position));
|
||||
|
||||
const subMessage = new SubMessage();
|
||||
subMessage.setUsermovedmessage(userMovedMessage);
|
||||
|
||||
clientListener.emitInBatch(subMessage);
|
||||
//console.log("Sending USER_MOVED event");
|
||||
} else if (thing instanceof Group) {
|
||||
this.emitCreateUpdateGroupEvent(clientListener, thing);
|
||||
} else {
|
||||
console.error('Unexpected type for Movable.');
|
||||
}
|
||||
}
|
||||
|
||||
private onClientLeave(thing: Movable, listener:User) {
|
||||
const clientListener = this.searchClientByIdOrFail(listener.id);
|
||||
if (thing instanceof User) {
|
||||
const clientUser = this.searchClientByIdOrFail(thing.id);
|
||||
this.emitUserLeftEvent(clientListener, clientUser.userId);
|
||||
} else if (thing instanceof Group) {
|
||||
this.emitDeleteGroupEvent(clientListener, thing.getId());
|
||||
} else {
|
||||
console.error('Unexpected type for Movable.');
|
||||
}
|
||||
}*/
|
||||
|
||||
emitPlayGlobalMessage(client: ExSocketInterface, playglobalmessage: PlayGlobalMessage) {
|
||||
const pusherToBackMessage = new PusherToBackMessage();
|
||||
pusherToBackMessage.setPlayglobalmessage(playglobalmessage);
|
||||
@ -505,90 +372,94 @@ export class SocketManager implements ZoneEventListener {
|
||||
|
||||
|
||||
public handleQueryJitsiJwtMessage(client: ExSocketInterface, queryJitsiJwtMessage: QueryJitsiJwtMessage) {
|
||||
const room = queryJitsiJwtMessage.getJitsiroom();
|
||||
const tag = queryJitsiJwtMessage.getTag(); // FIXME: this is not secure. We should load the JSON for the current room and check rights associated to room instead.
|
||||
try {
|
||||
const room = queryJitsiJwtMessage.getJitsiroom();
|
||||
const tag = queryJitsiJwtMessage.getTag(); // FIXME: this is not secure. We should load the JSON for the current room and check rights associated to room instead.
|
||||
|
||||
if (SECRET_JITSI_KEY === '') {
|
||||
throw new Error('You must set the SECRET_JITSI_KEY key to the secret to generate JWT tokens for Jitsi.');
|
||||
if (SECRET_JITSI_KEY === '') {
|
||||
throw new Error('You must set the SECRET_JITSI_KEY key to the secret to generate JWT tokens for Jitsi.');
|
||||
}
|
||||
|
||||
// Let's see if the current client has
|
||||
const isAdmin = client.tags.includes(tag);
|
||||
|
||||
const jwt = Jwt.sign({
|
||||
"aud": "jitsi",
|
||||
"iss": JITSI_ISS,
|
||||
"sub": JITSI_URL,
|
||||
"room": room,
|
||||
"moderator": isAdmin
|
||||
}, SECRET_JITSI_KEY, {
|
||||
expiresIn: '1d',
|
||||
algorithm: "HS256",
|
||||
header:
|
||||
{
|
||||
"alg": "HS256",
|
||||
"typ": "JWT"
|
||||
}
|
||||
});
|
||||
|
||||
const sendJitsiJwtMessage = new SendJitsiJwtMessage();
|
||||
sendJitsiJwtMessage.setJitsiroom(room);
|
||||
sendJitsiJwtMessage.setJwt(jwt);
|
||||
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setSendjitsijwtmessage(sendJitsiJwtMessage);
|
||||
|
||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||
} catch (e) {
|
||||
console.error('An error occured while generating the Jitsi JWT token: ', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's see if the current client has
|
||||
const isAdmin = client.tags.includes(tag);
|
||||
public async emitSendUserMessage(userUuid: string, message: string, type: string, roomId: string) {
|
||||
/*const client = this.searchClientByUuid(userUuid);
|
||||
if(client) {
|
||||
const adminMessage = new SendUserMessage();
|
||||
adminMessage.setMessage(message);
|
||||
adminMessage.setType(type);
|
||||
const pusherToBackMessage = new PusherToBackMessage();
|
||||
pusherToBackMessage.setSendusermessage(adminMessage);
|
||||
client.backConnection.write(pusherToBackMessage);
|
||||
return;
|
||||
}*/
|
||||
|
||||
const jwt = Jwt.sign({
|
||||
"aud": "jitsi",
|
||||
"iss": JITSI_ISS,
|
||||
"sub": JITSI_URL,
|
||||
"room": room,
|
||||
"moderator": isAdmin
|
||||
}, SECRET_JITSI_KEY, {
|
||||
expiresIn: '1d',
|
||||
algorithm: "HS256",
|
||||
header:
|
||||
{
|
||||
"alg": "HS256",
|
||||
"typ": "JWT"
|
||||
}
|
||||
const backConnection = await apiClientRepository.getClient(roomId);
|
||||
const backAdminMessage = new AdminMessage();
|
||||
backAdminMessage.setMessage(message);
|
||||
backAdminMessage.setRoomid(roomId);
|
||||
backAdminMessage.setRecipientuuid(userUuid);
|
||||
backAdminMessage.setType(type);
|
||||
backConnection.sendAdminMessage(backAdminMessage, (error) => {
|
||||
if (error !== null) {
|
||||
console.error('Error while sending admin message', error);
|
||||
}
|
||||
});
|
||||
|
||||
const sendJitsiJwtMessage = new SendJitsiJwtMessage();
|
||||
sendJitsiJwtMessage.setJitsiroom(room);
|
||||
sendJitsiJwtMessage.setJwt(jwt);
|
||||
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setSendjitsijwtmessage(sendJitsiJwtMessage);
|
||||
|
||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||
}
|
||||
|
||||
public emitSendUserMessage(userUuid: string, message: string, type: string): void {
|
||||
const client = this.searchClientByUuid(userUuid);
|
||||
if(!client){
|
||||
throw Error('client not found');
|
||||
}
|
||||
public async emitBan(userUuid: string, message: string, type: string, roomId: string) {
|
||||
/*const client = this.searchClientByUuid(userUuid);
|
||||
if(client) {
|
||||
const banUserMessage = new BanUserMessage();
|
||||
banUserMessage.setMessage(message);
|
||||
banUserMessage.setType(type);
|
||||
const pusherToBackMessage = new PusherToBackMessage();
|
||||
pusherToBackMessage.setBanusermessage(banUserMessage);
|
||||
client.backConnection.write(pusherToBackMessage);
|
||||
return;
|
||||
}*/
|
||||
|
||||
const adminMessage = new SendUserMessage();
|
||||
adminMessage.setMessage(message);
|
||||
adminMessage.setType(type);
|
||||
const pusherToBackMessage = new PusherToBackMessage();
|
||||
pusherToBackMessage.setSendusermessage(adminMessage);
|
||||
client.backConnection.write(pusherToBackMessage);
|
||||
|
||||
/*const backConnection = await apiClientRepository.getClient(client.roomId);
|
||||
const adminMessage = new AdminMessage();
|
||||
adminMessage.setMessage(message);
|
||||
adminMessage.setRoomid(client.roomId);
|
||||
adminMessage.setRecipientuuid(client.userUuid);
|
||||
backConnection.sendAdminMessage(adminMessage, (error) => {
|
||||
const backConnection = await apiClientRepository.getClient(roomId);
|
||||
const banMessage = new BanMessage();
|
||||
banMessage.setMessage(message);
|
||||
banMessage.setRoomid(roomId);
|
||||
banMessage.setRecipientuuid(userUuid);
|
||||
banMessage.setType(type);
|
||||
backConnection.ban(banMessage, (error) => {
|
||||
if (error !== null) {
|
||||
console.error('Error while sending admin message', error);
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
public emitBan(userUuid: string, message: string, type: string): void {
|
||||
const client = this.searchClientByUuid(userUuid);
|
||||
if(!client){
|
||||
throw Error('client not found');
|
||||
}
|
||||
|
||||
const banUserMessage = new BanUserMessage();
|
||||
banUserMessage.setMessage(message);
|
||||
banUserMessage.setType(type);
|
||||
const pusherToBackMessage = new PusherToBackMessage();
|
||||
pusherToBackMessage.setBanusermessage(banUserMessage);
|
||||
client.backConnection.write(pusherToBackMessage);
|
||||
|
||||
/*const backConnection = await apiClientRepository.getClient(client.roomId);
|
||||
const adminMessage = new AdminMessage();
|
||||
adminMessage.setMessage(message);
|
||||
adminMessage.setRoomid(client.roomId);
|
||||
adminMessage.setRecipientuuid(client.userUuid);
|
||||
backConnection.sendAdminMessage(adminMessage, (error) => {
|
||||
if (error !== null) {
|
||||
console.error('Error while sending admin message', error);
|
||||
}
|
||||
});*/
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user