Sharing outline color changes in real time

This commit is contained in:
David Négrier 2021-12-22 18:30:23 +01:00
parent 90f7287860
commit 482ba9690a
15 changed files with 268 additions and 56 deletions

View file

@ -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,
@ -56,10 +63,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 +87,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 +102,8 @@ export class GameRoom {
onEnters,
onMoves,
onLeaves,
onEmote
onEmote,
onPlayerDetailsUpdated
);
return gameRoom;
@ -180,6 +198,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();

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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
) {}
@ -106,4 +115,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);
}
}
}

View file

@ -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");
}

View file

@ -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;
}
client.name = playerDetails.name;
client.characterLayers = SocketManager.mergeCharacterLayersAndCustomTextures(playerDetails.characterLayers, client.textures);
}*/
handleSetPlayerDetails(room: GameRoom, user: User, playerDetailsMessage: SetPlayerDetailsMessage) {
room.updatePlayerDetails(user, playerDetailsMessage);
}
handleSilentMessage(room: GameRoom, user: User, silentMessage: SilentMessage) {
room.setSilent(user, silentMessage.getSilent());
@ -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();
@ -378,6 +371,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();
@ -572,7 +572,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());