diff --git a/back/src/Model/GameRoom.ts b/back/src/Model/GameRoom.ts index 7d7b24a5..b55c6079 100644 --- a/back/src/Model/GameRoom.ts +++ b/back/src/Model/GameRoom.ts @@ -418,7 +418,7 @@ export class GameRoom { }); this.groups.forEach((group: Group) => { - if (group.isFull()) { + if (group.isFull() || group.isLocked()) { return; } const distance = GameRoom.computeDistanceBetweenPositions(user.getPosition(), group.getPosition()); diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts index 65e15c40..a960e7b3 100644 --- a/back/src/Model/Group.ts +++ b/back/src/Model/Group.ts @@ -14,6 +14,7 @@ export class Group implements Movable { private x!: number; private y!: number; private wasDestroyed: boolean = false; + private locked: boolean = false; private roomId: string; private currentZone: Zone | null = null; /** @@ -141,6 +142,10 @@ export class Group implements Movable { return this.users.size >= MAX_PER_GROUP; } + isLocked(): boolean { + return this.locked; + } + isEmpty(): boolean { return this.users.size <= 1; } @@ -167,6 +172,10 @@ export class Group implements Movable { this.disconnectCallback(user, this); } + lock(lock: boolean = true): void { + this.locked = lock; + } + /** * Let's kick everybody out. * Usually used when there is only one user left. diff --git a/back/src/RoomManager.ts b/back/src/RoomManager.ts index d375fbd8..b5e27982 100644 --- a/back/src/RoomManager.ts +++ b/back/src/RoomManager.ts @@ -29,6 +29,7 @@ import { WebRtcSignalToServerMessage, WorldFullWarningToRoomMessage, ZoneMessage, + LockGroupMessage, } from "./Messages/generated/messages_pb"; import { sendUnaryData, ServerDuplexStream, ServerUnaryCall, ServerWritableStream } from "grpc"; import { socketManager } from "./Services/SocketManager"; @@ -135,6 +136,11 @@ const roomManager: IRoomManagerServer = { user, message.getFollowabortmessage() as FollowAbortMessage ); + } else if (message.hasLockgroupmessage()) { + socketManager.handleLockGroupMessage( + user, + message.getLockgroupmessage() as LockGroupMessage + ); } else if (message.hasSendusermessage()) { const sendUserMessage = message.getSendusermessage(); socketManager.handleSendUserMessage(user, sendUserMessage as SendUserMessage); @@ -148,6 +154,8 @@ const roomManager: IRoomManagerServer = { user, setPlayerDetailsMessage as SetPlayerDetailsMessage ); + } else if (message.hasLockgroupmessage()) { + console.log("===== GOT LOCK GROUP MESSAGE FROM CLIENT ====="); } else { throw new Error("Unhandled message type"); } diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts index c396893d..af0ec6cf 100644 --- a/back/src/Services/SocketManager.ts +++ b/back/src/Services/SocketManager.ts @@ -39,6 +39,7 @@ import { SetPlayerDetailsMessage, PlayerDetailsUpdatedMessage, GroupUsersUpdateMessage, + LockGroupMessage, } from "../Messages/generated/messages_pb"; import { User, UserSocket } from "../Model/User"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; @@ -404,6 +405,7 @@ export class SocketManager { groupUpdateMessage.setPosition(pointMessage); groupUpdateMessage.setGroupsize(group.getSize); groupUpdateMessage.setFromzone(this.toProtoZone(fromZone)); + groupUpdateMessage.setLocked(group.isLocked()); const subMessage = new SubToPusherMessage(); subMessage.setGroupupdatezonemessage(groupUpdateMessage); @@ -889,6 +891,11 @@ export class SocketManager { leader?.delFollower(user); } } + + handleLockGroupMessage(user: User, message: LockGroupMessage) { + console.log(`lock group: ${message.getLock()}`); + user.group?.lock(message.getLock()); + } } export const socketManager = new SocketManager(); diff --git a/front/src/Connexion/ConnexionModels.ts b/front/src/Connexion/ConnexionModels.ts index 3d8893a2..04282abc 100644 --- a/front/src/Connexion/ConnexionModels.ts +++ b/front/src/Connexion/ConnexionModels.ts @@ -45,6 +45,7 @@ export interface GroupCreatedUpdatedMessageInterface { position: PositionInterface; groupId: number; groupSize: number; + locked: boolean; } export interface GroupUsersUpdateMessageInterface { diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 95c91cd5..0f932901 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -636,6 +636,7 @@ export class RoomConnection implements RoomConnection { groupId: message.groupId, position: position, groupSize: message.groupSize, + locked: message.locked, }; } @@ -851,6 +852,20 @@ export class RoomConnection implements RoomConnection { this.socket.send(bytes); } + public emitLockGroup(groupId: number, lock: boolean = true): void { + const bytes = ClientToServerMessageTsProto.encode({ + message: { + $case: "lockGroupMessage", + lockGroupMessage: { + groupId, + lock, + }, + }, + }).finish(); + + this.socket.send(bytes); + } + public getAllTags(): string[] { return this.tags; } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 0a44cea3..c0d82d24 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -718,6 +718,16 @@ export class GameScene extends DirtyScene { e ) ); + + this.input.keyboard.on("keydown-L", (event: Event) => { + console.log("group locked"); + this.connection?.emitLockGroup(1, true); + }); + + this.input.keyboard.on("keydown-U", (event: Event) => { + console.log("group unlocked"); + this.connection?.emitLockGroup(1, false); + }); } /** @@ -782,6 +792,7 @@ export class GameScene extends DirtyScene { this.connection.groupUpdateMessageStream.subscribe( (groupPositionMessage: GroupCreatedUpdatedMessageInterface) => { + console.log(groupPositionMessage); this.shareGroupPosition(groupPositionMessage); } ); @@ -1809,8 +1820,13 @@ ${escapedMessage} break; } case "GroupCreatedUpdatedEvent": + console.log("CREATE OR UPDATE GROUP"); this.doShareGroupPosition(event.event); break; + // TODO: CALL THIS ON GROUP LOCK CHANGE + // case "GroupCreatedUpdatedEvent": + // this.doShareGroupPosition(event.event); + // break; case "DeleteGroupEvent": this.doDeleteGroup(event.groupId); break; @@ -1985,7 +2001,9 @@ ${escapedMessage} this, Math.round(groupPositionMessage.position.x), Math.round(groupPositionMessage.position.y), - groupPositionMessage.groupSize === MAX_PER_GROUP ? "circleSprite-red" : "circleSprite-white" + groupPositionMessage.groupSize === MAX_PER_GROUP || groupPositionMessage.locked + ? "circleSprite-red" + : "circleSprite-white" ); sprite.setDisplayOrigin(48, 48); this.add.existing(sprite); diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 5c9c95b7..4ccaed4b 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -98,6 +98,11 @@ message FollowAbortMessage { int32 follower = 2; } +message LockGroupMessage { + int32 groupId = 1; + bool lock = 2; +} + message ClientToServerMessage { oneof message { UserMovesMessage userMovesMessage = 2; @@ -116,6 +121,7 @@ message ClientToServerMessage { FollowRequestMessage followRequestMessage = 15; FollowConfirmationMessage followConfirmationMessage = 16; FollowAbortMessage followAbortMessage = 17; + LockGroupMessage lockGroupMessage = 18; } } @@ -172,6 +178,7 @@ message SubMessage { VariableMessage variableMessage = 8; ErrorMessage errorMessage = 9; PlayerDetailsUpdatedMessage playerDetailsUpdatedMessage = 10; + LockGroupMessage lockGroupMessage = 11; } } @@ -184,6 +191,7 @@ message GroupUpdateMessage { int32 groupId = 1; PointMessage position = 2; int32 groupSize = 3; + bool locked = 4; } message GroupDeleteMessage { @@ -316,6 +324,7 @@ message ServerToClientMessage { FollowConfirmationMessage followConfirmationMessage = 22; FollowAbortMessage followAbortMessage = 23; GroupUsersUpdateMessage groupUsersUpdateMessage = 24; + LockGroupMessage lockGroupMessage = 25; } } @@ -358,6 +367,7 @@ message GroupUpdateZoneMessage { PointMessage position = 2; int32 groupSize = 3; Zone fromZone = 4; + bool locked = 5; } message GroupLeftZoneMessage { @@ -403,6 +413,7 @@ message PusherToBackMessage { FollowRequestMessage followRequestMessage = 16; FollowConfirmationMessage followConfirmationMessage = 17; FollowAbortMessage followAbortMessage = 18; + LockGroupMessage lockGroupMessage = 19; } } diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 6db53403..617da341 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -21,6 +21,7 @@ import { FollowConfirmationMessage, FollowAbortMessage, VariableMessage, + LockGroupMessage, } from "../Messages/generated/messages_pb"; import { UserMovesMessage } from "../Messages/generated/messages_pb"; import { TemplatedApp } from "uWebSockets.js"; @@ -494,6 +495,8 @@ export class IoSocketController { ); } else if (message.hasFollowabortmessage()) { socketManager.handleFollowAbort(client, message.getFollowabortmessage() as FollowAbortMessage); + } else if (message.hasLockgroupmessage()) { + socketManager.handleLockGroup(client, message.getLockgroupmessage() as LockGroupMessage); } /* Ok is false if backpressure was built up, wait for drain */ diff --git a/pusher/src/Model/Zone.ts b/pusher/src/Model/Zone.ts index 2132ff39..1bf1090a 100644 --- a/pusher/src/Model/Zone.ts +++ b/pusher/src/Model/Zone.ts @@ -32,6 +32,7 @@ export interface ZoneEventListener { onGroupEnters(group: GroupDescriptor, listener: ExSocketInterface): void; onGroupMoves(group: GroupDescriptor, listener: ExSocketInterface): void; onGroupLeaves(groupId: number, listener: ExSocketInterface): void; + // onGroupLock(groupId: number, listener: ExSocketInterface): void; onEmote(emoteMessage: EmoteEventMessage, listener: ExSocketInterface): void; onError(errorMessage: ErrorMessage, listener: ExSocketInterface): void; onPlayerDetailsUpdated(playerDetailsUpdatedMessage: PlayerDetailsUpdatedMessage, listener: ExSocketInterface): void; @@ -123,19 +124,25 @@ export class UserDescriptor { } export class GroupDescriptor { - private constructor(public readonly groupId: number, private groupSize: number, private position: PointMessage) {} + private constructor( + public readonly groupId: number, + private groupSize: number, + private position: PointMessage, + private locked: boolean + ) {} public static createFromGroupUpdateZoneMessage(message: GroupUpdateZoneMessage): GroupDescriptor { const position = message.getPosition(); if (position === undefined) { throw new Error("Missing position"); } - return new GroupDescriptor(message.getGroupid(), message.getGroupsize(), position); + return new GroupDescriptor(message.getGroupid(), message.getGroupsize(), position, message.getLocked()); } public update(groupDescriptor: GroupDescriptor) { this.groupSize = groupDescriptor.groupSize; this.position = groupDescriptor.position; + this.locked = groupDescriptor.locked; } public toGroupUpdateMessage(): GroupUpdateMessage { @@ -146,6 +153,7 @@ export class GroupDescriptor { groupUpdateMessage.setGroupid(this.groupId); groupUpdateMessage.setGroupsize(this.groupSize); groupUpdateMessage.setPosition(this.position); + groupUpdateMessage.setLocked(this.locked); return groupUpdateMessage; } @@ -238,6 +246,9 @@ export class Zone { } else if (message.hasEmoteeventmessage()) { const emoteEventMessage = message.getEmoteeventmessage() as EmoteEventMessage; this.notifyEmote(emoteEventMessage); + } else if (message.hasEmoteeventmessage()) { + const emoteEventMessage = message.getEmoteeventmessage() as EmoteEventMessage; + this.notifyEmote(emoteEventMessage); } else if (message.hasPlayerdetailsupdatedmessage()) { const playerDetailsUpdatedMessage = message.getPlayerdetailsupdatedmessage() as PlayerDetailsUpdatedMessage; diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 30fe761f..b1006bf8 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -38,6 +38,7 @@ import { ErrorMessage, WorldFullMessage, PlayerDetailsUpdatedMessage, + LockGroupMessage, } from "../Messages/generated/messages_pb"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; @@ -292,6 +293,12 @@ export class SocketManager implements ZoneEventListener { client.backConnection.write(pusherToBackMessage); } + handleLockGroup(client: ExSocketInterface, message: LockGroupMessage): void { + const pusherToBackMessage = new PusherToBackMessage(); + pusherToBackMessage.setLockgroupmessage(message); + client.backConnection.write(pusherToBackMessage); + } + onEmote(emoteMessage: EmoteEventMessage, listener: ExSocketInterface): void { const subMessage = new SubMessage(); subMessage.setEmoteeventmessage(emoteMessage);