0e4fb5d828
Create replay games when a match ends (win or draw) and include ReplayGameCode in the GameEnded payload; adjust deletion timing to keep the replay longer and clean up original games sooner. Update game deletion logic to only destroy non-running games and schedule immediate deletion for quick timeouts. Add optional local bot support (botPlayer2 flag) with automated random-delayed moves and a UI switch in the game creation menu; expose botPlayer2 in GameSettings and LocalMode defaults. Introduce RandomPlaceMessage utility to generate varied turn descriptions and integrate it into LocalGame and OnlineGame. Also include a minor whitespace fix in Game.cs.
96 lines
2.8 KiB
TypeScript
96 lines
2.8 KiB
TypeScript
import type { GameSettings } from '@/scripts/interfaces/GameSettings';
|
|
import GameConnection, {
|
|
type GameIdentifier,
|
|
type GameInformationDto,
|
|
type GameEnded,
|
|
} from '../signalR/GameConnection';
|
|
import { getRandomMovePhrase } from '@/scripts/utils/RandomPlaceMessage';
|
|
|
|
class LocalGame {
|
|
public player1: GameConnection;
|
|
public player2: GameConnection;
|
|
public currentDescription: string = 'Warte auf Spielaufbau ...';
|
|
private gameId: string = '';
|
|
private botGame = false;
|
|
|
|
public gameState: GameInformationDto | undefined;
|
|
public onGameStateChanged?: (gameState: GameInformationDto | undefined) => void;
|
|
public onGameEnded?: (gameEndedInfo: GameEnded) => void;
|
|
|
|
constructor() {
|
|
this.player1 = new GameConnection();
|
|
this.player2 = new GameConnection();
|
|
|
|
this.player1.onGameStarted = (gameInfo: GameInformationDto) => {
|
|
console.log('Game started for player 1', gameInfo);
|
|
this.gameState = gameInfo;
|
|
this.onGameStateChanged?.(this.gameState);
|
|
|
|
this.changePlaceDescription();
|
|
};
|
|
|
|
this.player1.onFieldUpdated = (currentState: GameInformationDto) => {
|
|
this.updateState(currentState);
|
|
this.changePlaceDescription();
|
|
};
|
|
|
|
this.player1.onGameCreated = (gameIdentifier: GameIdentifier) => {
|
|
this.gameId = gameIdentifier.gameId;
|
|
this.player2.joinGame(gameIdentifier.gameCode);
|
|
};
|
|
|
|
this.player2.onGameJoined = (gameIdentifier: GameIdentifier) => {
|
|
this.gameId = gameIdentifier.gameId;
|
|
};
|
|
|
|
this.player1.onGameEnded = (gameEndedInfo: GameEnded) => {
|
|
this.onGameEnded?.(gameEndedInfo);
|
|
};
|
|
}
|
|
|
|
async start(settings: GameSettings) {
|
|
await this.player1.connect(settings.playerName1);
|
|
await this.player2.connect(settings.playerName2 ?? 'Spieler 2');
|
|
|
|
this.botGame = settings.botPlayer2 ?? false;
|
|
|
|
await this.player1.createGame(settings.fieldSize);
|
|
}
|
|
|
|
async updateState(newState: GameInformationDto) {
|
|
if (this.gameState) {
|
|
this.gameState = newState;
|
|
this.onGameStateChanged?.(this.gameState);
|
|
}
|
|
}
|
|
|
|
async drop(index: number) {
|
|
if (this.gameState?.currentTurn == 1) {
|
|
this.player1.drop(this.gameId, index);
|
|
|
|
if (this.botGame) {
|
|
const randomDelay = Math.random() * 2000 + 1000;
|
|
setTimeout(() => {
|
|
const botIndex = Math.floor(Math.random() * this.gameState!.currentField.length);
|
|
this.player2.drop(this.gameId, botIndex);
|
|
}, randomDelay);
|
|
}
|
|
} else if(!this.botGame) {
|
|
this.player2.drop(this.gameId, index);
|
|
}
|
|
}
|
|
|
|
changePlaceDescription() {
|
|
const playerName =
|
|
this.gameState?.currentTurn == 1 ? this.player1.playerName : this.player2.playerName;
|
|
this.currentDescription = getRandomMovePhrase(playerName);
|
|
}
|
|
|
|
async disconnectAll() {
|
|
await this.player1.disconnect();
|
|
await this.player2.disconnect();
|
|
}
|
|
}
|
|
|
|
export default LocalGame;
|