Skip to content

Commit

Permalink
fix: guard against joining the lobby with an active game
Browse files Browse the repository at this point in the history
the lobby (only entry point for a game) checks whether the client
attempting to join has an active game open before allowing it to do so

the client still performs the same check independently but since this
is only a way to redirect the player to where they need to be

resolves virtualcommons/planning#62
  • Loading branch information
sgfost committed Dec 13, 2023
1 parent 10c2f64 commit 3f7f5e8
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 22 deletions.
18 changes: 18 additions & 0 deletions client/src/api/lobby/request.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Room } from "colyseus.js";
import { AjaxRequest } from "@port-of-mars/client/plugins/ajax";
import {
LobbyRequest,
AcceptInvitation,
Expand All @@ -7,8 +8,12 @@ import {
StartSoloWithBots,
SendLobbyChatMessage,
} from "@port-of-mars/shared/lobby/requests";
import { url } from "@port-of-mars/client/util";
import { GameType } from "@port-of-mars/shared/types";

export class LobbyRequestAPI {
constructor(public ajax: AjaxRequest) {}

room!: Room;

connect(room: Room) {
Expand All @@ -21,6 +26,19 @@ export class LobbyRequestAPI {
}
}

public async hasActiveGame(type?: GameType) {
try {
const params = type ? `?type=${type}` : "";
return await this.ajax.get(url(`/game/has-active${params}`), ({ data }) => {
return data;
});
} catch (e) {
console.log("Unable to query active game status");
console.log(e);
throw e;
}
}

public send(req: LobbyRequest) {
this.room.send(req.kind, req);
}
Expand Down
16 changes: 5 additions & 11 deletions client/src/views/FreePlayLobby.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { AccountAPI } from "@port-of-mars/client/api/account/request";
import { FREE_PLAY_LOBBY_NAME } from "@port-of-mars/shared/lobby";
import { GAME_PAGE, CONSENT_PAGE, MANUAL_PAGE } from "@port-of-mars/shared/routes";
import { Constants } from "@port-of-mars/shared/settings";
import { url } from "@port-of-mars/client/util";
import Countdown from "@port-of-mars/client/components/global/Countdown.vue";
import HelpPanel from "@port-of-mars/client/components/lobby/HelpPanel.vue";
import Messages from "@port-of-mars/client/components/global/Messages.vue";
Expand All @@ -41,7 +40,7 @@ import Messages from "@port-of-mars/client/components/global/Messages.vue";
})
export default class FreePlayLobby extends Vue {
@Inject() readonly $client!: Client;
@Provide() api: FreePlayLobbyRequestAPI = new FreePlayLobbyRequestAPI();
@Provide() api: FreePlayLobbyRequestAPI = new FreePlayLobbyRequestAPI(this.$ajax);
accountApi!: AccountAPI;
game = { name: GAME_PAGE };
Expand All @@ -55,7 +54,10 @@ export default class FreePlayLobby extends Vue {
async created() {
this.accountApi = new AccountAPI(this.$store, this.$ajax);
await this.checkCanPlay();
await this.rejoinIfActiveGame();
const hasActiveGame = await this.api.hasActiveGame("freeplay");
if (hasActiveGame) {
this.$router.push(this.game);
}
}
async checkCanPlay() {
Expand All @@ -67,14 +69,6 @@ export default class FreePlayLobby extends Vue {
}
}
async rejoinIfActiveGame() {
await this.$ajax.get(url("/game/has-active?type=freeplay"), ({ data, status }) => {
if (status === 200 && data === true) {
this.$router.push(this.game);
}
});
}
async createRoom() {
const room = await this.$client.create(FREE_PLAY_LOBBY_NAME);
await this.connectAndRedirect(room);
Expand Down
17 changes: 6 additions & 11 deletions client/src/views/TournamentLobby.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import {
MANUAL_PAGE,
TOURNAMENT_DASHBOARD_PAGE,
} from "@port-of-mars/shared/routes";
import { url } from "@port-of-mars/client/util";
import { Constants } from "@port-of-mars/shared/settings";
import Countdown from "@port-of-mars/client/components/global/Countdown.vue";
import HelpPanel from "@port-of-mars/client/components/lobby/HelpPanel.vue";
Expand All @@ -72,7 +71,7 @@ import LobbyChat from "@port-of-mars/client/components/lobby/LobbyChat.vue";
})
export default class TournamentLobby extends Vue {
@Inject() readonly $client!: Client;
@Provide() api: TournamentLobbyRequestAPI = new TournamentLobbyRequestAPI();
@Provide() api: TournamentLobbyRequestAPI = new TournamentLobbyRequestAPI(this.$ajax);
accountApi!: AccountAPI;
game = { name: GAME_PAGE };
Expand All @@ -95,7 +94,11 @@ export default class TournamentLobby extends Vue {
}
async created() {
await this.rejoinIfActiveGame();
const hasActiveGame = await this.api.hasActiveGame("tournament");
if (hasActiveGame) {
this.$router.push(this.game);
return;
}
try {
const room = await this.$client.joinOrCreate(TOURNAMENT_LOBBY_NAME);
applyLobbyResponses(room, this, "tournament");
Expand All @@ -105,14 +108,6 @@ export default class TournamentLobby extends Vue {
}
}
async rejoinIfActiveGame() {
await this.$ajax.get(url("/game/has-active?type=tournament"), ({ data, status }) => {
if (status === 200 && data === true) {
this.$router.push(this.game);
}
});
}
beforeDestroy() {
this.api.leave();
this.$tstore.commit("RESET_LOBBY_STATE");
Expand Down
13 changes: 13 additions & 0 deletions server/src/rooms/lobby/freeplay/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { FreePlayLobbyRoomState } from "@port-of-mars/server/rooms/lobby/freeplay/state";
import { LobbyClient } from "@port-of-mars/server/rooms/lobby/common/state";
import { LobbyRoom } from "@port-of-mars/server/rooms/lobby/common";
import { User } from "@port-of-mars/server/entity";

const logger = settings.logging.getLogger(__filename);

Expand Down Expand Up @@ -64,6 +65,18 @@ export class FreePlayLobbyRoom extends LobbyRoom<FreePlayLobbyRoomState> {
return getServices().settings.isFreePlayEnabled();
}

async canUserJoin(user: User) {
const services = getServices();
const activeGame = await services.game.getActiveGameRoomId(user.id, "freeplay");
if (activeGame) {
logger.warn(
`client ${user.username} attempted to join ${this.roomName} while in another game`
);
return false;
}
return true;
}

onAcceptInvitation(client: Client, message: AcceptInvitation): void {
logger.trace(`client ${client.auth.username} accepted invitation to join a game`);
this.state.setClientAccepted(client.auth.username);
Expand Down
7 changes: 7 additions & 0 deletions server/src/rooms/lobby/tournament/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ export class TournamentLobbyRoom extends LobbyRoom<TournamentLobbyRoomState> {

async canUserJoin(user: User) {
const services = getServices();
const activeGame = await services.game.getActiveGameRoomId(user.id, "tournament");
if (activeGame) {
logger.warn(
`client ${user.username} attempted to join ${this.roomName} while in another game`
);
return false;
}
const numberOfActiveParticipants = await services.game.getNumberOfActiveParticipants();
const maxConnections = await this.getMaxConnections();
return numberOfActiveParticipants < maxConnections && services.tournament.canPlayInRound(user);
Expand Down

0 comments on commit 3f7f5e8

Please sign in to comment.