FIX: if a conversion group move to another user, this user will be added to the group
This commit is contained in:
parent
900c53f499
commit
5255847452
@ -181,6 +181,7 @@ export class GameRoom {
|
|||||||
|
|
||||||
private updateUserGroup(user: User): void {
|
private updateUserGroup(user: User): void {
|
||||||
user.group?.updatePosition();
|
user.group?.updatePosition();
|
||||||
|
user.group?.searchForNearbyUsers();
|
||||||
|
|
||||||
if (user.silent) {
|
if (user.silent) {
|
||||||
return;
|
return;
|
||||||
@ -206,6 +207,7 @@ export class GameRoom {
|
|||||||
const group: Group = new Group(
|
const group: Group = new Group(
|
||||||
this.roomUrl,
|
this.roomUrl,
|
||||||
[user, closestUser],
|
[user, closestUser],
|
||||||
|
this.groupRadius,
|
||||||
this.connectCallback,
|
this.connectCallback,
|
||||||
this.disconnectCallback,
|
this.disconnectCallback,
|
||||||
this.positionNotifier
|
this.positionNotifier
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { ConnectCallback, DisconnectCallback } from "./GameRoom";
|
import { ConnectCallback, DisconnectCallback, GameRoom } from "./GameRoom";
|
||||||
import { User } from "./User";
|
import { User } from "./User";
|
||||||
import { PositionInterface } from "_Model/PositionInterface";
|
import { PositionInterface } from "_Model/PositionInterface";
|
||||||
import { Movable } from "_Model/Movable";
|
import { Movable } from "_Model/Movable";
|
||||||
import { PositionNotifier } from "_Model/PositionNotifier";
|
import { PositionNotifier } from "_Model/PositionNotifier";
|
||||||
import { gaugeManager } from "../Services/GaugeManager";
|
|
||||||
import { MAX_PER_GROUP } from "../Enum/EnvironmentVariable";
|
import { MAX_PER_GROUP } from "../Enum/EnvironmentVariable";
|
||||||
|
import type { Zone } from "../Model/Zone";
|
||||||
|
|
||||||
export class Group implements Movable {
|
export class Group implements Movable {
|
||||||
private static nextId: number = 1;
|
private static nextId: number = 1;
|
||||||
@ -13,13 +13,14 @@ export class Group implements Movable {
|
|||||||
private users: Set<User>;
|
private users: Set<User>;
|
||||||
private x!: number;
|
private x!: number;
|
||||||
private y!: number;
|
private y!: number;
|
||||||
private hasEditedGauge: boolean = false;
|
|
||||||
private wasDestroyed: boolean = false;
|
private wasDestroyed: boolean = false;
|
||||||
private roomId: string;
|
private roomId: string;
|
||||||
|
private currentZone: Zone | null = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
users: User[],
|
users: User[],
|
||||||
|
private groupRadius: number,
|
||||||
private connectCallback: ConnectCallback,
|
private connectCallback: ConnectCallback,
|
||||||
private disconnectCallback: DisconnectCallback,
|
private disconnectCallback: DisconnectCallback,
|
||||||
private positionNotifier: PositionNotifier
|
private positionNotifier: PositionNotifier
|
||||||
@ -28,13 +29,6 @@ export class Group implements Movable {
|
|||||||
this.users = new Set<User>();
|
this.users = new Set<User>();
|
||||||
this.id = Group.nextId;
|
this.id = Group.nextId;
|
||||||
Group.nextId++;
|
Group.nextId++;
|
||||||
//we only send a event for prometheus metrics if the group lives more than 5 seconds
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!this.wasDestroyed) {
|
|
||||||
this.hasEditedGauge = true;
|
|
||||||
gaugeManager.incNbGroupsPerRoomGauge(roomId);
|
|
||||||
}
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
users.forEach((user: User) => {
|
users.forEach((user: User) => {
|
||||||
this.join(user);
|
this.join(user);
|
||||||
@ -85,9 +79,22 @@ export class Group implements Movable {
|
|||||||
this.y = y;
|
this.y = y;
|
||||||
|
|
||||||
if (oldX === undefined) {
|
if (oldX === undefined) {
|
||||||
this.positionNotifier.enter(this);
|
this.currentZone = this.positionNotifier.enter(this);
|
||||||
} else {
|
} else {
|
||||||
this.positionNotifier.updatePosition(this, { x, y }, { x: oldX, y: oldY });
|
this.currentZone = this.positionNotifier.updatePosition(this, { x, y }, { x: oldX, y: oldY });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchForNearbyUsers(): void {
|
||||||
|
if (!this.currentZone) return;
|
||||||
|
|
||||||
|
for (const user of this.positionNotifier.getAllUsersInSquareAroundZone(this.currentZone)) {
|
||||||
|
if (user.group || this.isFull()) return; //we ignore users that are already in a group.
|
||||||
|
const distance = GameRoom.computeDistanceBetweenPositions(user.getPosition(), this.getPosition());
|
||||||
|
if (distance < this.groupRadius) {
|
||||||
|
this.join(user);
|
||||||
|
this.updatePosition();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +133,6 @@ export class Group implements Movable {
|
|||||||
* Usually used when there is only one user left.
|
* Usually used when there is only one user left.
|
||||||
*/
|
*/
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
if (this.hasEditedGauge) gaugeManager.decNbGroupsPerRoomGauge(this.roomId);
|
|
||||||
for (const user of this.users) {
|
for (const user of this.users) {
|
||||||
this.leave(user);
|
this.leave(user);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import { EmoteCallback, EntersCallback, LeavesCallback, MovesCallback, Zone } fr
|
|||||||
import { Movable } from "_Model/Movable";
|
import { Movable } from "_Model/Movable";
|
||||||
import { PositionInterface } from "_Model/PositionInterface";
|
import { PositionInterface } from "_Model/PositionInterface";
|
||||||
import { ZoneSocket } from "../RoomManager";
|
import { ZoneSocket } from "../RoomManager";
|
||||||
import { User } from "_Model/User";
|
import { User } from "../Model/User";
|
||||||
import { EmoteEventMessage } from "../Messages/generated/messages_pb";
|
import { EmoteEventMessage } from "../Messages/generated/messages_pb";
|
||||||
|
|
||||||
interface ZoneDescriptor {
|
interface ZoneDescriptor {
|
||||||
@ -20,6 +20,17 @@ interface ZoneDescriptor {
|
|||||||
j: number;
|
j: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function* getNearbyDescriptorsMatrix(middleZoneDescriptor: ZoneDescriptor): Generator<ZoneDescriptor> {
|
||||||
|
for (let n = 0; n < 9; n++) {
|
||||||
|
const i = middleZoneDescriptor.i + ((n % 3) - 1);
|
||||||
|
const j = middleZoneDescriptor.j + (Math.floor(n / 3) - 1);
|
||||||
|
|
||||||
|
if (i >= 0 && j >= 0) {
|
||||||
|
yield { i, j };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PositionNotifier {
|
export class PositionNotifier {
|
||||||
// TODO: we need a way to clean the zones if no one is in the zone and no one listening (to free memory!)
|
// TODO: we need a way to clean the zones if no one is in the zone and no one listening (to free memory!)
|
||||||
|
|
||||||
@ -41,14 +52,15 @@ export class PositionNotifier {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public enter(thing: Movable): void {
|
public enter(thing: Movable): Zone {
|
||||||
const position = thing.getPosition();
|
const position = thing.getPosition();
|
||||||
const zoneDesc = this.getZoneDescriptorFromCoordinates(position.x, position.y);
|
const zoneDesc = this.getZoneDescriptorFromCoordinates(position.x, position.y);
|
||||||
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
||||||
zone.enter(thing, null, position);
|
zone.enter(thing, null, position);
|
||||||
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updatePosition(thing: Movable, newPosition: PositionInterface, oldPosition: PositionInterface): void {
|
public updatePosition(thing: Movable, newPosition: PositionInterface, oldPosition: PositionInterface): Zone {
|
||||||
// Did we change zone?
|
// Did we change zone?
|
||||||
const oldZoneDesc = this.getZoneDescriptorFromCoordinates(oldPosition.x, oldPosition.y);
|
const oldZoneDesc = this.getZoneDescriptorFromCoordinates(oldPosition.x, oldPosition.y);
|
||||||
const newZoneDesc = this.getZoneDescriptorFromCoordinates(newPosition.x, newPosition.y);
|
const newZoneDesc = this.getZoneDescriptorFromCoordinates(newPosition.x, newPosition.y);
|
||||||
@ -62,9 +74,11 @@ export class PositionNotifier {
|
|||||||
|
|
||||||
// Enter new zone
|
// Enter new zone
|
||||||
newZone.enter(thing, oldZone, newPosition);
|
newZone.enter(thing, oldZone, newPosition);
|
||||||
|
return newZone;
|
||||||
} else {
|
} else {
|
||||||
const zone = this.getZone(oldZoneDesc.i, oldZoneDesc.j);
|
const zone = this.getZone(oldZoneDesc.i, oldZoneDesc.j);
|
||||||
zone.move(thing, newPosition);
|
zone.move(thing, newPosition);
|
||||||
|
return zone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,4 +120,16 @@ export class PositionNotifier {
|
|||||||
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
||||||
zone.emitEmoteEvent(emoteEventMessage);
|
zone.emitEmoteEvent(emoteEventMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public *getAllUsersInSquareAroundZone(zone: Zone): Generator<User> {
|
||||||
|
const zoneDescriptor = this.getZoneDescriptorFromCoordinates(zone.x, zone.y);
|
||||||
|
for (const d of getNearbyDescriptorsMatrix(zoneDescriptor)) {
|
||||||
|
const zone = this.getZone(d.i, d.j);
|
||||||
|
for (const thing of zone.getThings()) {
|
||||||
|
if (thing instanceof User) {
|
||||||
|
yield thing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,15 +52,6 @@ class GaugeManager {
|
|||||||
this.nbClientsGauge.dec();
|
this.nbClientsGauge.dec();
|
||||||
this.nbClientsPerRoomGauge.dec({ room: roomId });
|
this.nbClientsPerRoomGauge.dec({ room: roomId });
|
||||||
}
|
}
|
||||||
|
|
||||||
incNbGroupsPerRoomGauge(roomId: string): void {
|
|
||||||
this.nbGroupsPerRoomCounter.inc({ room: roomId });
|
|
||||||
this.nbGroupsPerRoomGauge.inc({ room: roomId });
|
|
||||||
}
|
|
||||||
|
|
||||||
decNbGroupsPerRoomGauge(roomId: string): void {
|
|
||||||
this.nbGroupsPerRoomGauge.dec({ room: roomId });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const gaugeManager = new GaugeManager();
|
export const gaugeManager = new GaugeManager();
|
||||||
|
67
back/tests/getNearbyDescriptorsMatrixTest.ts
Normal file
67
back/tests/getNearbyDescriptorsMatrixTest.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import "jasmine";
|
||||||
|
import { getNearbyDescriptorsMatrix } from "../src/Model/PositionNotifier";
|
||||||
|
|
||||||
|
describe("getNearbyDescriptorsMatrix", () => {
|
||||||
|
it("should create a matrix of coordinates in a square around the parameter", () => {
|
||||||
|
const matrix = [];
|
||||||
|
for (const d of getNearbyDescriptorsMatrix({ i: 1, j: 1 })) {
|
||||||
|
matrix.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{ i: 0, j: 0 },
|
||||||
|
{ i: 1, j: 0 },
|
||||||
|
{ i: 2, j: 0 },
|
||||||
|
{ i: 0, j: 1 },
|
||||||
|
{ i: 1, j: 1 },
|
||||||
|
{ i: 2, j: 1 },
|
||||||
|
{ i: 0, j: 2 },
|
||||||
|
{ i: 1, j: 2 },
|
||||||
|
{ i: 2, j: 2 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a matrix of coordinates in a square around the parameter bis", () => {
|
||||||
|
const matrix = [];
|
||||||
|
for (const d of getNearbyDescriptorsMatrix({ i: 8, j: 3 })) {
|
||||||
|
matrix.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{ i: 7, j: 2 },
|
||||||
|
{ i: 8, j: 2 },
|
||||||
|
{ i: 9, j: 2 },
|
||||||
|
{ i: 7, j: 3 },
|
||||||
|
{ i: 8, j: 3 },
|
||||||
|
{ i: 9, j: 3 },
|
||||||
|
{ i: 7, j: 4 },
|
||||||
|
{ i: 8, j: 4 },
|
||||||
|
{ i: 9, j: 4 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not create a matrix with negative coordinates", () => {
|
||||||
|
const matrix = [];
|
||||||
|
for (const d of getNearbyDescriptorsMatrix({ i: 0, j: 0 })) {
|
||||||
|
matrix.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{ i: 0, j: 0 },
|
||||||
|
{ i: 1, j: 0 },
|
||||||
|
{ i: 0, j: 1 },
|
||||||
|
{ i: 1, j: 1 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*it("should not create a matrix with coordinates bigger than its dimmensions", () => {
|
||||||
|
const matrix = getNearbyDescriptorsMatrix({i: 4, j: 4}, 5, 5);
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{i: 3,j: 3},
|
||||||
|
{i: 4,j: 3},
|
||||||
|
{i: 3,j: 4},
|
||||||
|
{i: 4,j: 4},
|
||||||
|
])
|
||||||
|
});*/
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user