diff --git a/src/client/ClientGame.ts b/src/client/ClientGame.ts index 4720571e2..062c2abba 100644 --- a/src/client/ClientGame.ts +++ b/src/client/ClientGame.ts @@ -1,18 +1,18 @@ -import {Executor} from "../core/execution/ExecutionManager"; -import {Cell, MutableGame, PlayerEvent, PlayerID, MutablePlayer, TileEvent, Player, Game, BoatEvent, Tile, PlayerType, GameMap} from "../core/game/Game"; -import {createGame} from "../core/game/GameImpl"; -import {EventBus} from "../core/EventBus"; -import {Config, getConfig} from "../core/configuration/Config"; -import {createRenderer, GameRenderer} from "./graphics/GameRenderer"; -import {InputHandler, MouseUpEvent, ZoomEvent, DragEvent, MouseDownEvent} from "./InputHandler" -import {ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, ClientMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn} from "../core/Schemas"; -import {loadTerrainMap, TerrainMap} from "../core/game/TerrainMapLoader"; -import {and, bfs, dist, manhattanDist} from "../core/Util"; -import {WinCheckExecution} from "../core/execution/WinCheckExecution"; -import {SendAttackIntentEvent, SendSpawnIntentEvent, Transport} from "./Transport"; -import {createCanvas} from "./graphics/Utils"; -import {DisplayMessageEvent, MessageType} from "./graphics/layers/EventsDisplay"; -import {v4 as uuidv4} from 'uuid'; +import { Executor } from "../core/execution/ExecutionManager"; +import { Cell, MutableGame, PlayerEvent, PlayerID, MutablePlayer, TileEvent, Player, Game, BoatEvent, Tile, PlayerType, GameMap, Difficulty } from "../core/game/Game"; +import { createGame } from "../core/game/GameImpl"; +import { EventBus } from "../core/EventBus"; +import { Config, getConfig } from "../core/configuration/Config"; +import { createRenderer, GameRenderer } from "./graphics/GameRenderer"; +import { InputHandler, MouseUpEvent, ZoomEvent, DragEvent, MouseDownEvent } from "./InputHandler" +import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, ClientMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn } from "../core/Schemas"; +import { loadTerrainMap, TerrainMap } from "../core/game/TerrainMapLoader"; +import { and, bfs, dist, manhattanDist } from "../core/Util"; +import { WinCheckExecution } from "../core/execution/WinCheckExecution"; +import { SendAttackIntentEvent, SendSpawnIntentEvent, Transport } from "./Transport"; +import { createCanvas } from "./graphics/Utils"; +import { DisplayMessageEvent, MessageType } from "./graphics/layers/EventsDisplay"; +import { v4 as uuidv4 } from 'uuid'; export interface LobbyConfig { @@ -21,13 +21,14 @@ export interface LobbyConfig { gameID: GameID ip: string | null map: GameMap | null + difficulty: Difficulty | null } export interface GameConfig { map: GameMap + difficulty: Difficulty clientID: ClientID, gameID: GameID, - ip: string | null, } export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => void { @@ -35,11 +36,11 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v const playerID = uuidv4() const eventBus = new EventBus() const config = getConfig() - const transport = new Transport(lobbyConfig.isLocal, eventBus, lobbyConfig.gameID, clientID, playerID, config, lobbyConfig.playerName) + const transport = new Transport(lobbyConfig.isLocal, eventBus, lobbyConfig.gameID, lobbyConfig.ip, clientID, playerID, config, lobbyConfig.playerName) const onconnect = () => { console.log('Joined game lobby!'); - transport.joinGame(clientID, 0) + transport.joinGame(0) }; const onmessage = (message: ServerMessage) => { if (message.type == "start") { @@ -47,6 +48,7 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v onjoin() const gameConfig = { map: message.config?.gameMap || lobbyConfig.map, + difficulty: message.config?.difficulty || lobbyConfig.difficulty, clientID: clientID, gameID: lobbyConfig.gameID, ip: lobbyConfig.ip, @@ -71,14 +73,16 @@ export async function createClientGame(gameConfig: GameConfig, eventBus: EventBu const canvas = createCanvas() let gameRenderer = createRenderer(canvas, game, eventBus, gameConfig.clientID) + + console.log(`creating private game got difficulty: ${gameConfig.difficulty}`) + return new GameRunner( - gameConfig.clientID, - gameConfig.ip, + gameConfig, eventBus, game, gameRenderer, new InputHandler(canvas, eventBus), - new Executor(game, gameConfig.gameID), + new Executor(game, gameConfig.difficulty, gameConfig.gameID), transport, ) } @@ -96,8 +100,7 @@ export class GameRunner { private hasJoined = false constructor( - private id: ClientID, - private clientIP: string | null, + private gameConfig: GameConfig, private eventBus: EventBus, private gs: Game, private renderer: GameRenderer, @@ -122,7 +125,7 @@ export class GameRunner { const onconnect = () => { console.log('Connected to game server!'); - this.transport.joinGame(this.clientIP, this.turns.length) + this.transport.joinGame(this.turns.length) }; const onmessage = (message: ServerMessage) => { if (message.type == "start") { @@ -170,7 +173,7 @@ export class GameRunner { private playerEvent(event: PlayerEvent) { console.log('received new player event!') - if (event.player.clientID() == this.id) { + if (event.player.clientID() == this.gameConfig.clientID) { console.log('setting name') this.myPlayer = event.player } diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index d8b13f12c..b2c09afd9 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -1,12 +1,13 @@ -import {LitElement, html, css} from 'lit'; -import {customElement, property, state} from 'lit/decorators.js'; -import {GameMap} from '../core/game/Game'; -import {Lobby} from '../core/Schemas'; +import { LitElement, html, css } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import { Difficulty, GameMap } from '../core/game/Game'; +import { Lobby } from '../core/Schemas'; @customElement('host-lobby-modal') export class HostLobbyModal extends LitElement { @state() private isModalOpen = false; @state() private selectedMap: GameMap = GameMap.World; + @state() private selectedDiffculty: Difficulty = Difficulty.Medium; @state() private lobbyId = 'a345d'; @state() private copySuccess = false; @@ -120,6 +121,18 @@ export class HostLobbyModal extends LitElement { `)} +
+ + +
@@ -138,6 +151,7 @@ export class HostLobbyModal extends LitElement { id: this.lobbyId, }, map: this.selectedMap, + difficulty: this.selectedDiffculty, }, bubbles: true, composed: true @@ -155,15 +169,25 @@ export class HostLobbyModal extends LitElement { private async handleMapChange(e: Event) { this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap; console.log(`updating map to ${this.selectedMap}`) + this.putGameConfig() + } + + private async handleDifficultyChange(e: Event) { + this.selectedDiffculty = Number((e.target as HTMLSelectElement).value) as Difficulty; + console.log(`updating difficulty to ${this.selectedDiffculty}`) + this.putGameConfig() + } + + private async putGameConfig() { const response = await fetch(`/private_lobby/${this.lobbyId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({gameMap: this.selectedMap}) + body: JSON.stringify({ gameMap: this.selectedMap, difficulty: this.selectedDiffculty }) }); - } + private async startGame() { console.log(`Starting private game with map: ${GameMap[this.selectedMap]}`); this.close(); diff --git a/src/client/Main.ts b/src/client/Main.ts index 55f7eb6bf..37fc6b05e 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -1,14 +1,14 @@ -import {GameRunner, joinLobby} from "./ClientGame"; +import { GameRunner, joinLobby } from "./ClientGame"; import backgroundImage from '../../resources/images/TerrainMapFrontPage.png'; import favicon from '../../resources/images/Favicon.png'; import './PublicLobby'; import './UsernameInput'; import './styles.css'; -import {UsernameInput} from "./UsernameInput"; -import {SinglePlayerModal} from "./SinglePlayerModal"; -import {HostLobbyModal as HostPrivateLobbyModal} from "./HostLobbyModal"; -import {JoinPrivateLobbyModal} from "./JoinPrivateLobbyModal"; +import { UsernameInput } from "./UsernameInput"; +import { SinglePlayerModal } from "./SinglePlayerModal"; +import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal"; +import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal"; @@ -77,6 +77,7 @@ class Client { gameID: lobby.id, ip: clientIP, map: event.detail.map, + difficulty: event.detail.difficulty, }, () => this.joinModal.close() ); @@ -115,7 +116,7 @@ async function getClientIP(timeoutMs: number = 1000): Promise { throw new Error(`HTTP error! status: ${response.status}`); } - const data: {ip: string} = await response.json(); + const data: { ip: string } = await response.json(); return data.ip; } catch (error) { if (error instanceof Error) { diff --git a/src/client/PublicLobby.ts b/src/client/PublicLobby.ts index 30e8610a0..06d360d06 100644 --- a/src/client/PublicLobby.ts +++ b/src/client/PublicLobby.ts @@ -1,7 +1,7 @@ -import {LitElement, html, css} from 'lit'; -import {customElement, state} from 'lit/decorators.js'; -import {Lobby} from "../core/Schemas"; -import {GameMap} from '../core/game/Game'; +import { LitElement, html, css } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { Lobby } from "../core/Schemas"; +import { Difficulty, GameMap } from '../core/game/Game'; @customElement('public-lobby') export class PublicLobby extends LitElement { @@ -113,13 +113,14 @@ export class PublicLobby extends LitElement { lobby: lobby, singlePlayer: false, map: GameMap.World, + difficulty: Difficulty.Medium, }, bubbles: true, composed: true })); } else { this.dispatchEvent(new CustomEvent('leave-lobby', { - detail: {lobby: this.currLobby}, + detail: { lobby: this.currLobby }, bubbles: true, composed: true })); diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts index a1ed2cc28..fc1ff9326 100644 --- a/src/client/SinglePlayerModal.ts +++ b/src/client/SinglePlayerModal.ts @@ -1,11 +1,12 @@ -import {LitElement, html, css} from 'lit'; -import {customElement, property, state} from 'lit/decorators.js'; -import {GameMap} from '../core/game/Game'; +import { LitElement, html, css } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import { Difficulty, GameMap } from '../core/game/Game'; @customElement('single-player-modal') export class SinglePlayerModal extends LitElement { @state() private isModalOpen = false; @state() private selectedMap: GameMap = GameMap.World; + @state() private selectedDifficulty: Difficulty = Difficulty.Medium; static styles = css` .modal-overlay { @@ -87,6 +88,19 @@ export class SinglePlayerModal extends LitElement { `)} +
+ + +
+ @@ -104,7 +118,9 @@ export class SinglePlayerModal extends LitElement { private handleMapChange(e: Event) { this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap; } - + private handleDifficultyChange(e: Event) { + this.selectedDifficulty = Number((e.target as HTMLSelectElement).value) as Difficulty; + } private startGame() { console.log(`Starting single player game with map: ${GameMap[this.selectedMap]}`); this.dispatchEvent(new CustomEvent('join-lobby', { @@ -114,6 +130,7 @@ export class SinglePlayerModal extends LitElement { id: "LOCAL", }, map: this.selectedMap, + difficulty: this.selectedDifficulty }, bubbles: true, composed: true diff --git a/src/client/Transport.ts b/src/client/Transport.ts index dfaa72d5f..e17bd68b9 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -91,6 +91,7 @@ export class Transport { private isLocal: boolean, private eventBus: EventBus, private gameID: GameID, + private clientIP: string | null, private clientID: ClientID, private playerID: PlayerID, private config: Config, @@ -156,14 +157,14 @@ export class Transport { } } - joinGame(clientIP: string | null, numTurns: number) { + joinGame(numTurns: number) { this.sendMsg( JSON.stringify( ClientJoinMessageSchema.parse({ type: "join", gameID: this.gameID, clientID: this.clientID, - clientIP: clientIP, + clientIP: this.clientIP, lastTurn: numTurns }) ) diff --git a/src/client/index.html b/src/client/index.html index a773c8457..25904dce2 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -11,7 +11,7 @@