FEATURE: added the possibility toplay emotes

This commit is contained in:
kharhamel 2021-03-31 11:21:06 +02:00
parent b57a9957a3
commit a1d52b4265
23 changed files with 286 additions and 72 deletions

View file

@ -2,12 +2,12 @@ import {PointInterface} from "./Websocket/PointInterface";
import {Group} from "./Group";
import {User, UserSocket} from "./User";
import {PositionInterface} from "_Model/PositionInterface";
import {EntersCallback, LeavesCallback, MovesCallback} from "_Model/Zone";
import {EmoteCallback, EntersCallback, LeavesCallback, MovesCallback} from "_Model/Zone";
import {PositionNotifier} from "./PositionNotifier";
import {Movable} from "_Model/Movable";
import {extractDataFromPrivateRoomId, extractRoomSlugPublicRoomId, isRoomAnonymous} from "./RoomIdentifier";
import {arrayIntersect} from "../Services/ArrayHelper";
import {JoinRoomMessage} from "../Messages/generated/messages_pb";
import {EmoteEventMessage, JoinRoomMessage} from "../Messages/generated/messages_pb";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
import {ZoneSocket} from "src/RoomManager";
import {Admin} from "../Model/Admin";
@ -51,8 +51,9 @@ export class GameRoom {
groupRadius: number,
onEnters: EntersCallback,
onMoves: MovesCallback,
onLeaves: LeavesCallback)
{
onLeaves: LeavesCallback,
onEmote: EmoteCallback,
) {
this.roomId = roomId;
if (isRoomAnonymous(roomId)) {
@ -74,7 +75,7 @@ export class GameRoom {
this.minDistance = minDistance;
this.groupRadius = groupRadius;
// A zone is 10 sprites wide.
this.positionNotifier = new PositionNotifier(320, 320, onEnters, onMoves, onLeaves);
this.positionNotifier = new PositionNotifier(320, 320, onEnters, onMoves, onLeaves, onEmote);
}
public getGroups(): Group[] {
@ -325,4 +326,8 @@ export class GameRoom {
this.versionNumber++
return this.versionNumber;
}
public emitEmoteEvent(user: User, emoteEventMessage: EmoteEventMessage) {
this.positionNotifier.emitEmoteEvent(user, emoteEventMessage);
}
}

View file

@ -8,10 +8,12 @@
* 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 {EntersCallback, LeavesCallback, MovesCallback, Zone} from "./Zone";
import {EmoteCallback, EntersCallback, LeavesCallback, MovesCallback, 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";
interface ZoneDescriptor {
i: number;
@ -24,7 +26,7 @@ export class PositionNotifier {
private zones: Zone[][] = [];
constructor(private zoneWidth: number, private zoneHeight: number, private onUserEnters: EntersCallback, private onUserMoves: MovesCallback, private onUserLeaves: LeavesCallback) {
constructor(private zoneWidth: number, private zoneHeight: number, private onUserEnters: EntersCallback, private onUserMoves: MovesCallback, private onUserLeaves: LeavesCallback, private onEmote: EmoteCallback) {
}
private getZoneDescriptorFromCoordinates(x: number, y: number): ZoneDescriptor {
@ -77,7 +79,7 @@ export class PositionNotifier {
let zone = this.zones[j][i];
if (zone === undefined) {
zone = new Zone(this.onUserEnters, this.onUserMoves, this.onUserLeaves, i, j);
zone = new Zone(this.onUserEnters, this.onUserMoves, this.onUserLeaves, this.onEmote, i, j);
this.zones[j][i] = zone;
}
return zone;
@ -93,4 +95,11 @@ export class PositionNotifier {
const zone = this.getZone(x, y);
zone.removeListener(call);
}
public emitEmoteEvent(user: User, emoteEventMessage: EmoteEventMessage) {
const zoneDesc = this.getZoneDescriptorFromCoordinates(user.getPosition().x, user.getPosition().y);
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
zone.emitEmoteEvent(emoteEventMessage);
}
}

View file

@ -3,21 +3,19 @@ import {PositionInterface} from "_Model/PositionInterface";
import {Movable} from "./Movable";
import {Group} from "./Group";
import {ZoneSocket} from "../RoomManager";
import {EmoteEventMessage} 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 class Zone {
private things: Set<Movable> = new Set<Movable>();
private listeners: Set<ZoneSocket> = new Set<ZoneSocket>();
/**
* @param x For debugging purpose only
* @param y For debugging purpose only
*/
constructor(private onEnters: EntersCallback, private onMoves: MovesCallback, private onLeaves: LeavesCallback, public readonly x: number, public readonly y: number) {
}
constructor(private onEnters: EntersCallback, private onMoves: MovesCallback, private onLeaves: LeavesCallback, private onEmote: EmoteCallback, public readonly x: number, public readonly y: number) { }
/**
* A user/thing leaves the zone
@ -41,9 +39,7 @@ export class Zone {
*/
private notifyLeft(thing: Movable, newZone: Zone|null) {
for (const listener of this.listeners) {
//if (listener !== thing && (newZone === null || !listener.listenedZones.has(newZone))) {
this.onLeaves(thing, newZone, listener);
//}
this.onLeaves(thing, newZone, listener);
}
}
@ -57,15 +53,6 @@ export class Zone {
*/
private notifyEnter(thing: Movable, oldZone: Zone|null, position: PositionInterface) {
for (const listener of this.listeners) {
/*if (listener === thing) {
continue;
}
if (oldZone === null || !listener.listenedZones.has(oldZone)) {
this.onEnters(thing, listener);
} else {
this.onMoves(thing, position, listener);
}*/
this.onEnters(thing, oldZone, listener);
}
}
@ -85,28 +72,6 @@ export class Zone {
}
}
/*public startListening(listener: User): void {
for (const thing of this.things) {
if (thing !== listener) {
this.onEnters(thing, listener);
}
}
this.listeners.add(listener);
listener.listenedZones.add(this);
}
public stopListening(listener: User): void {
for (const thing of this.things) {
if (thing !== listener) {
this.onLeaves(thing, listener);
}
}
this.listeners.delete(listener);
listener.listenedZones.delete(this);
}*/
public getThings(): Set<Movable> {
return this.things;
}
@ -119,4 +84,11 @@ export class Zone {
public removeListener(socket: ZoneSocket): void {
this.listeners.delete(socket);
}
public emitEmoteEvent(emoteEventMessage: EmoteEventMessage) {
for (const listener of this.listeners) {
this.onEmote(emoteEventMessage, listener);
}
}
}

View file

@ -5,6 +5,7 @@ import {
AdminPusherToBackMessage,
AdminRoomMessage,
BanMessage,
EmotePromptMessage,
EmptyMessage,
ItemEventMessage,
JoinRoomMessage,
@ -71,6 +72,8 @@ const roomManager: IRoomManagerServer = {
socketManager.emitPlayGlobalMessage(room, message.getPlayglobalmessage() as PlayGlobalMessage);
} else if (message.hasQueryjitsijwtmessage()){
socketManager.handleQueryJitsiJwtMessage(user, message.getQueryjitsijwtmessage() as QueryJitsiJwtMessage);
} else if (message.hasEmotepromptmessage()){
socketManager.handleEmoteEventMessage(room, user, message.getEmotepromptmessage() as EmotePromptMessage);
}else if (message.hasSendusermessage()) {
const sendUserMessage = message.getSendusermessage();
if(sendUserMessage !== undefined) {

View file

@ -26,7 +26,8 @@ import {
GroupLeftZoneMessage,
WorldFullWarningMessage,
UserLeftZoneMessage,
BanUserMessage, RefreshRoomMessage,
EmoteEventMessage,
BanUserMessage, RefreshRoomMessage, EmotePromptMessage,
} from "../Messages/generated/messages_pb";
import {User, UserSocket} from "../Model/User";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
@ -73,6 +74,9 @@ export class SocketManager {
clientEventsEmitter.registerToClientLeave((clientUUid: string, roomId: string) => {
gaugeManager.decNbClientPerRoomGauge(roomId);
});
//zoneMessageStream.stream.subscribe(myMessage);
}
public async handleJoinRoom(socket: UserSocket, joinRoomMessage: JoinRoomMessage): Promise<{ room: GameRoom; user: User }> {
@ -263,7 +267,8 @@ export class SocketManager {
GROUP_RADIUS,
(thing: Movable, fromZone: Zone|null, listener: ZoneSocket) => this.onZoneEnter(thing, fromZone, listener),
(thing: Movable, position:PositionInterface, listener: ZoneSocket) => this.onClientMove(thing, position, listener),
(thing: Movable, newZone: Zone|null, listener: ZoneSocket) => this.onClientLeave(thing, newZone, listener)
(thing: Movable, newZone: Zone|null, listener: ZoneSocket) => this.onClientLeave(thing, newZone, listener),
(emoteEventMessage:EmoteEventMessage, listener: ZoneSocket) => this.onEmote(emoteEventMessage, listener),
);
gaugeManager.incNbRoomGauge();
this.rooms.set(roomId, world);
@ -339,6 +344,14 @@ export class SocketManager {
}
}
private onEmote(emoteEventMessage: EmoteEventMessage, client: ZoneSocket) {
const subMessage = new SubToPusherMessage();
subMessage.setEmoteeventmessage(emoteEventMessage);
emitZoneMessage(subMessage, client);
}
private emitCreateUpdateGroupEvent(client: ZoneSocket, fromZone: Zone|null, group: Group): void {
const position = group.getPosition();
const pointMessage = new PointMessage();
@ -751,6 +764,13 @@ export class SocketManager {
recipient.socket.write(clientMessage);
});
}
handleEmoteEventMessage(room: GameRoom, user: User, emotePromptMessage: EmotePromptMessage) {
const emoteEventMessage = new EmoteEventMessage();
emoteEventMessage.setEmote(emotePromptMessage.getEmote());
emoteEventMessage.setActoruserid(user.id);
room.emitEmoteEvent(user, emoteEventMessage);
}
}
export const socketManager = new SocketManager();

View file

@ -5,6 +5,7 @@ import {Group} from "../src/Model/Group";
import {User, UserSocket} from "_Model/User";
import {JoinRoomMessage, PositionMessage} from "../src/Messages/generated/messages_pb";
import Direction = PositionMessage.Direction;
import {EmoteCallback} from "_Model/Zone";
function createMockUser(userId: number): User {
return {
@ -33,6 +34,8 @@ function createJoinRoomMessage(uuid: string, x: number, y: number): JoinRoomMess
return joinRoomMessage;
}
const emote: EmoteCallback = (emoteEventMessage, listener): void => {}
describe("GameRoom", () => {
it("should connect user1 and user2", () => {
let connectCalledNumber: number = 0;
@ -43,7 +46,8 @@ describe("GameRoom", () => {
}
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {}, emote);
@ -72,7 +76,7 @@ describe("GameRoom", () => {
}
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {}, emote);
const user1 = world.join(createMockUserSocket(), createJoinRoomMessage('1', 100, 100));
@ -101,7 +105,7 @@ describe("GameRoom", () => {
disconnectCallNumber++;
}
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {}, emote);
const user1 = world.join(createMockUserSocket(), createJoinRoomMessage('1', 100, 100));

View file

@ -23,7 +23,7 @@ describe("PositionNotifier", () => {
moveTriggered = true;
}, (thing: Movable) => {
leaveTriggered = true;
});
}, () => {});
const user1 = new User(1, 'test', '10.0.0.2', {
x: 500,
@ -98,7 +98,7 @@ describe("PositionNotifier", () => {
moveTriggered = true;
}, (thing: Movable) => {
leaveTriggered = true;
});
}, () => {});
const user1 = new User(1, 'test', '10.0.0.2', {
x: 500,