Refactoring following code to make a distinction beween followed and following users.

Also, moving sending messages to the User class.
This commit is contained in:
David Négrier 2021-12-17 18:26:17 +01:00 committed by PizZaKatZe
parent fd9cb09de6
commit cd805fab31
4 changed files with 63 additions and 33 deletions

View File

@ -125,7 +125,6 @@ export class GameRoom {
joinRoomMessage.getIpaddress(), joinRoomMessage.getIpaddress(),
position, position,
false, false,
[],
this.positionNotifier, this.positionNotifier,
socket, socket,
joinRoomMessage.getTagList(), joinRoomMessage.getTagList(),
@ -228,7 +227,7 @@ export class GameRoom {
this.leaveGroup(user); this.leaveGroup(user);
} }
}; };
const users = user.group.getUsers().filter((u) => u.following.length === 0); const users = user.group.getUsers().filter((u) => !u.hasFollowers() && !u.following);
users.forEach((foreignUser) => leaveIfOutOfRadius(foreignUser)); users.forEach((foreignUser) => leaveIfOutOfRadius(foreignUser));
} }
} }

View File

@ -152,4 +152,16 @@ export class Group implements Movable {
get getSize() { get getSize() {
return this.users.size; return this.users.size;
} }
/**
* A group can have at most one person leading the way in it.
*/
get leader(): User|undefined {
for (const user of this.users) {
if (user.hasFollowers()) {
return user;
}
}
return undefined;
}
} }

View File

@ -6,7 +6,7 @@ import { PositionNotifier } from "_Model/PositionNotifier";
import { ServerDuplexStream } from "grpc"; import { ServerDuplexStream } from "grpc";
import { import {
BatchMessage, BatchMessage,
CompanionMessage, CompanionMessage, FollowAbortMessage, FollowConfirmationMessage,
PusherToBackMessage, PusherToBackMessage,
ServerToClientMessage, ServerToClientMessage,
SubMessage, SubMessage,
@ -18,6 +18,8 @@ export type UserSocket = ServerDuplexStream<PusherToBackMessage, ServerToClientM
export class User implements Movable { export class User implements Movable {
public listenedZones: Set<Zone>; public listenedZones: Set<Zone>;
public group?: Group; public group?: Group;
private _following: User|undefined;
private followedBy: Set<User> = new Set<User>();
public constructor( public constructor(
public id: number, public id: number,
@ -25,7 +27,6 @@ export class User implements Movable {
public readonly IPAddress: string, public readonly IPAddress: string,
private position: PointInterface, private position: PointInterface,
public silent: boolean, public silent: boolean,
public following: number[],
private positionNotifier: PositionNotifier, private positionNotifier: PositionNotifier,
public readonly socket: UserSocket, public readonly socket: UserSocket,
public readonly tags: string[], public readonly tags: string[],
@ -49,19 +50,43 @@ export class User implements Movable {
this.positionNotifier.updatePosition(this, position, oldPosition); this.positionNotifier.updatePosition(this, position, oldPosition);
} }
public addFollower(userId: number): void { public addFollower(follower: User): void {
if (this.following.includes(userId)) { this.followedBy.add(follower);
return; follower._following = this;
}
this.following.push(userId); const message = new FollowConfirmationMessage();
message.setFollower(follower.id);
message.setLeader(this.id);
const clientMessage = new ServerToClientMessage();
clientMessage.setFollowconfirmationmessage(message);
this.socket.write(clientMessage);
} }
public delFollower(userId: number): void { public delFollower(follower: User): void {
const idx = this.following.indexOf(userId); this.followedBy.delete(follower);
if (idx === -1) { follower._following = undefined;
return;
const message = new FollowAbortMessage();
message.setFollower(follower.id);
message.setLeader(this.id);
const clientMessage = new ServerToClientMessage();
clientMessage.setFollowabortmessage(message);
this.socket.write(clientMessage);
follower.socket.write(clientMessage);
}
public hasFollowers(): boolean {
return this.followedBy.size !== 0;
}
get following(): User | undefined {
return this._following;
}
public stopLeading(): void {
for (const follower of this.followedBy) {
this.delFollower(follower);
} }
this.following.splice(idx, 1);
} }
private batchedMessages: BatchMessage = new BatchMessage(); private batchedMessages: BatchMessage = new BatchMessage();

View File

@ -844,34 +844,28 @@ export class SocketManager {
} }
handleFollowConfirmationMessage(room: GameRoom, user: User, message: FollowConfirmationMessage) { handleFollowConfirmationMessage(room: GameRoom, user: User, message: FollowConfirmationMessage) {
const clientMessage = new ServerToClientMessage();
clientMessage.setFollowconfirmationmessage(message);
const leader = room.getUserById(message.getLeader()); const leader = room.getUserById(message.getLeader());
leader?.socket.write(clientMessage); if (!leader) {
console.info('Could not find user "', message.getLeader(), '" while handling a follow confirmation in room "', room.roomUrl,'". Maybe the user just left.');
return;
}
leader?.addFollower(user.id); // By security, we look at the group leader. If the group leader is NOT the leader in the message, everybody should
user.addFollower(message.getLeader()); // stop following the group leader (to avoid having 2 group leaders)
if (user?.group?.leader && user?.group?.leader !== leader) {
user?.group?.leader?.stopLeading();
}
leader.addFollower(user);
} }
handleFollowAbortMessage(room: GameRoom, user: User, message: FollowAbortMessage) { handleFollowAbortMessage(room: GameRoom, user: User, message: FollowAbortMessage) {
const clientMessage = new ServerToClientMessage();
clientMessage.setFollowabortmessage(message);
if (user.id === message.getLeader()) { if (user.id === message.getLeader()) {
// Forward message user?.group?.leader?.stopLeading();
room.sendToOthersInGroupIncludingUser(user, clientMessage);
// Update followers
user.group?.getUsers().forEach((user) => {
user.following = [];
});
} else { } else {
// Forward message // Forward message
const leader = room.getUserById(message.getLeader()); const leader = room.getUserById(message.getLeader());
leader?.socket.write(clientMessage); leader?.delFollower(user);
// Update followers
leader?.delFollower(user.id);
user.following = [];
} }
} }
} }