Add game restart and disconnect support

Prevent handling disconnects for games already ended; add a disconnect() method on the SignalR connection and a LocalGame.disconnectAll() helper. Update GameEndedMenu to emit a restart event and adjust displayed messages/labels. Wire a restart() handler in LocalMode that disconnects all players then restarts the game.
This commit is contained in:
Jonas
2026-03-08 12:47:21 +01:00
parent 919bb71f19
commit bb3c482728
5 changed files with 27 additions and 8 deletions
+1 -1
View File
@@ -120,7 +120,7 @@ public class GameManager(IGameRepository gameRepository, IHubContext<GameHubSock
public Task DisconnectedPlayer(string playerConnectionId) public Task DisconnectedPlayer(string playerConnectionId)
{ {
var game = gameRepository.GetOneByConnectionId(playerConnectionId); var game = gameRepository.GetOneByConnectionId(playerConnectionId);
if (game == null) if (game == null || game.State == GameState.Ended)
return Task.CompletedTask; return Task.CompletedTask;
var player = game.GetPlayerByConnectionId(playerConnectionId); var player = game.GetPlayerByConnectionId(playerConnectionId);
+8 -6
View File
@@ -2,16 +2,18 @@
import { computed } from 'vue' import { computed } from 'vue'
import type { GameEnded } from '@/scripts/logic/signalR/GameConnection' import type { GameEnded } from '@/scripts/logic/signalR/GameConnection'
defineEmits(["restartGame"]);
const props = defineProps<{ gameEndedInformation: GameEnded | null }>() const props = defineProps<{ gameEndedInformation: GameEnded | null }>()
const message = computed(() => { const message = computed(() => {
switch (props.gameEndedInformation?.method) { switch (props.gameEndedInformation?.method) {
case "PlayerDisconnected": case "PlayerDisconnected":
return `Bei Spieler ${props.gameEndedInformation.player?.name} ist die Verbindung abgebrochen` return `Bei dem Spieler ${props.gameEndedInformation.player?.name} ist die Verbindung abgebrochen :(`
case "Draw": case "Draw":
return "Das Spielfeld ist voll und es ist ein Unentschieden" return "Das Spielfeld ist voll und es ist ein Unentschieden"
case "Win": case "Win":
return `Spieler ${props.gameEndedInformation.player?.name} hat gewonnen!` return `${props.gameEndedInformation.player?.name} hat gewonnen!`
default: default:
return "" return ""
} }
@@ -20,15 +22,15 @@ const message = computed(() => {
<template> <template>
<v-sheet width="100%" class="text-centered pa-2 w-75" rounded> <v-sheet width="100%" class="text-centered pa-2 w-75" rounded>
<h1 class="text-center">Spiel Beendet</h1> <h1 class="text-center">{{ message}}</h1>
<h3 class="test-center">{{ message }}</h3> <h3 class="text-center">Spiele erneut oder beende das Spiel</h3>
<v-divider class="mb-4"></v-divider> <v-divider class="mb-4"></v-divider>
<div class="d-flex align-center justify-space-evenly ma-4 w-100"> <div class="d-flex align-center justify-space-evenly ma-4 w-100">
<v-btn color="red" @click="$router.push('/')" rounded="xl"> <v-btn color="red" @click="$router.push('/')" rounded="xl">
Abbrechen Abbrechen
</v-btn> </v-btn>
<v-btn color="primary" @click="$emit('createGame')" rounded="xl"> <v-btn color="primary" @click="$emit('restartGame')" rounded="xl">
Spiel Starten Spiel Neustarten
</v-btn> </v-btn>
</div> </div>
</v-sheet> </v-sheet>
+8 -1
View File
@@ -40,6 +40,13 @@ async function startGame() {
currentState.value = CurrentState.Game; currentState.value = CurrentState.Game;
} }
async function restart(){
await game.value.disconnectAll();
startGame();
}
</script> </script>
<template> <template>
@@ -49,7 +56,7 @@ async function startGame() {
<v-container class="d-flex align-center justify-center fill-height" <v-container class="d-flex align-center justify-center fill-height"
v-else-if="currentState === CurrentState.EndScreen"> v-else-if="currentState === CurrentState.EndScreen">
<GameEndedMenu :game-ended-information="gameEndedInformation"></GameEndedMenu> <GameEndedMenu :game-ended-information="gameEndedInformation" @restart-game="restart"></GameEndedMenu>
</v-container> </v-container>
<div id="game" v-else> <div id="game" v-else>
@@ -73,6 +73,11 @@ class LocalGame {
this.gameState?.currentTurn == 1 ? this.player1.playerName : this.player2.playerName; this.gameState?.currentTurn == 1 ? this.player1.playerName : this.player2.playerName;
this.currentDescription = `${playerName} ist dran mit setzen!`; this.currentDescription = `${playerName} ist dran mit setzen!`;
} }
async disconnectAll(){
await this.player1.disconnect();
await this.player2.disconnect();
}
} }
export default LocalGame; export default LocalGame;
@@ -83,6 +83,11 @@ class GameConnection {
console.log('Connected'); console.log('Connected');
} }
async disconnect() {
await this.connection.stop();
console.log('Disconnected');
}
async createGame(gFs: FieldSize) { async createGame(gFs: FieldSize) {
await this.connection.invoke('CreateGame', this.playerName, gFs); await this.connection.invoke('CreateGame', this.playerName, gFs);
} }