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 {
|
||||
user.group?.updatePosition();
|
||||
user.group?.searchForNearbyUsers();
|
||||
|
||||
if (user.silent) {
|
||||
return;
|
||||
@ -206,6 +207,7 @@ export class GameRoom {
|
||||
const group: Group = new Group(
|
||||
this.roomUrl,
|
||||
[user, closestUser],
|
||||
this.groupRadius,
|
||||
this.connectCallback,
|
||||
this.disconnectCallback,
|
||||
this.positionNotifier
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { ConnectCallback, DisconnectCallback } from "./GameRoom";
|
||||
import { ConnectCallback, DisconnectCallback, GameRoom } from "./GameRoom";
|
||||
import { User } from "./User";
|
||||
import { PositionInterface } from "_Model/PositionInterface";
|
||||
import { Movable } from "_Model/Movable";
|
||||
import { PositionNotifier } from "_Model/PositionNotifier";
|
||||
import { gaugeManager } from "../Services/GaugeManager";
|
||||
import { MAX_PER_GROUP } from "../Enum/EnvironmentVariable";
|
||||
import type { Zone } from "../Model/Zone";
|
||||
|
||||
export class Group implements Movable {
|
||||
private static nextId: number = 1;
|
||||
@ -13,13 +13,14 @@ export class Group implements Movable {
|
||||
private users: Set<User>;
|
||||
private x!: number;
|
||||
private y!: number;
|
||||
private hasEditedGauge: boolean = false;
|
||||
private wasDestroyed: boolean = false;
|
||||
private roomId: string;
|
||||
private currentZone: Zone | null = null;
|
||||
|
||||
constructor(
|
||||
roomId: string,
|
||||
users: User[],
|
||||
private groupRadius: number,
|
||||
private connectCallback: ConnectCallback,
|
||||
private disconnectCallback: DisconnectCallback,
|
||||
private positionNotifier: PositionNotifier
|
||||
@ -28,13 +29,6 @@ export class Group implements Movable {
|
||||
this.users = new Set<User>();
|
||||
this.id = 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) => {
|
||||
this.join(user);
|
||||
@ -85,9 +79,22 @@ export class Group implements Movable {
|
||||
this.y = y;
|
||||
|
||||
if (oldX === undefined) {
|
||||
this.positionNotifier.enter(this);
|
||||
this.currentZone = this.positionNotifier.enter(this);
|
||||
} 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.
|
||||
*/
|
||||
destroy(): void {
|
||||
if (this.hasEditedGauge) gaugeManager.decNbGroupsPerRoomGauge(this.roomId);
|
||||
for (const user of this.users) {
|
||||
this.leave(user);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import { EmoteCallback, EntersCallback, LeavesCallback, MovesCallback, Zone } fr
|
||||
import { Movable } from "_Model/Movable";
|
||||
import { PositionInterface } from "_Model/PositionInterface";
|
||||
import { ZoneSocket } from "../RoomManager";
|
||||
import { User } from "_Model/User";
|
||||
import { User } from "../Model/User";
|
||||
import { EmoteEventMessage } from "../Messages/generated/messages_pb";
|
||||
|
||||
interface ZoneDescriptor {
|
||||
@ -20,6 +20,17 @@ interface ZoneDescriptor {
|
||||
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 {
|
||||
// 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 zoneDesc = this.getZoneDescriptorFromCoordinates(position.x, position.y);
|
||||
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
||||
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?
|
||||
const oldZoneDesc = this.getZoneDescriptorFromCoordinates(oldPosition.x, oldPosition.y);
|
||||
const newZoneDesc = this.getZoneDescriptorFromCoordinates(newPosition.x, newPosition.y);
|
||||
@ -62,9 +74,11 @@ export class PositionNotifier {
|
||||
|
||||
// Enter new zone
|
||||
newZone.enter(thing, oldZone, newPosition);
|
||||
return newZone;
|
||||
} else {
|
||||
const zone = this.getZone(oldZoneDesc.i, oldZoneDesc.j);
|
||||
zone.move(thing, newPosition);
|
||||
return zone;
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,4 +120,16 @@ export class PositionNotifier {
|
||||
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
||||
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.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();
|
||||
|
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