add difficulties

This commit is contained in:
Evan
2024-10-23 21:08:24 -07:00
parent c08645a7fe
commit 56d4b924fa
15 changed files with 154 additions and 88 deletions
+28 -25
View File
@@ -1,18 +1,18 @@
import {Executor} from "../core/execution/ExecutionManager"; import { Executor } from "../core/execution/ExecutionManager";
import {Cell, MutableGame, PlayerEvent, PlayerID, MutablePlayer, TileEvent, Player, Game, BoatEvent, Tile, PlayerType, GameMap} from "../core/game/Game"; 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 { createGame } from "../core/game/GameImpl";
import {EventBus} from "../core/EventBus"; import { EventBus } from "../core/EventBus";
import {Config, getConfig} from "../core/configuration/Config"; import { Config, getConfig } from "../core/configuration/Config";
import {createRenderer, GameRenderer} from "./graphics/GameRenderer"; import { createRenderer, GameRenderer } from "./graphics/GameRenderer";
import {InputHandler, MouseUpEvent, ZoomEvent, DragEvent, MouseDownEvent} from "./InputHandler" import { InputHandler, MouseUpEvent, ZoomEvent, DragEvent, MouseDownEvent } from "./InputHandler"
import {ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, ClientMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn} from "../core/Schemas"; import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, ClientMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn } from "../core/Schemas";
import {loadTerrainMap, TerrainMap} from "../core/game/TerrainMapLoader"; import { loadTerrainMap, TerrainMap } from "../core/game/TerrainMapLoader";
import {and, bfs, dist, manhattanDist} from "../core/Util"; import { and, bfs, dist, manhattanDist } from "../core/Util";
import {WinCheckExecution} from "../core/execution/WinCheckExecution"; import { WinCheckExecution } from "../core/execution/WinCheckExecution";
import {SendAttackIntentEvent, SendSpawnIntentEvent, Transport} from "./Transport"; import { SendAttackIntentEvent, SendSpawnIntentEvent, Transport } from "./Transport";
import {createCanvas} from "./graphics/Utils"; import { createCanvas } from "./graphics/Utils";
import {DisplayMessageEvent, MessageType} from "./graphics/layers/EventsDisplay"; import { DisplayMessageEvent, MessageType } from "./graphics/layers/EventsDisplay";
import {v4 as uuidv4} from 'uuid'; import { v4 as uuidv4 } from 'uuid';
export interface LobbyConfig { export interface LobbyConfig {
@@ -21,13 +21,14 @@ export interface LobbyConfig {
gameID: GameID gameID: GameID
ip: string | null ip: string | null
map: GameMap | null map: GameMap | null
difficulty: Difficulty | null
} }
export interface GameConfig { export interface GameConfig {
map: GameMap map: GameMap
difficulty: Difficulty
clientID: ClientID, clientID: ClientID,
gameID: GameID, gameID: GameID,
ip: string | null,
} }
export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => void { export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => void {
@@ -35,11 +36,11 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v
const playerID = uuidv4() const playerID = uuidv4()
const eventBus = new EventBus() const eventBus = new EventBus()
const config = getConfig() 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 = () => { const onconnect = () => {
console.log('Joined game lobby!'); console.log('Joined game lobby!');
transport.joinGame(clientID, 0) transport.joinGame(0)
}; };
const onmessage = (message: ServerMessage) => { const onmessage = (message: ServerMessage) => {
if (message.type == "start") { if (message.type == "start") {
@@ -47,6 +48,7 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v
onjoin() onjoin()
const gameConfig = { const gameConfig = {
map: message.config?.gameMap || lobbyConfig.map, map: message.config?.gameMap || lobbyConfig.map,
difficulty: message.config?.difficulty || lobbyConfig.difficulty,
clientID: clientID, clientID: clientID,
gameID: lobbyConfig.gameID, gameID: lobbyConfig.gameID,
ip: lobbyConfig.ip, ip: lobbyConfig.ip,
@@ -71,14 +73,16 @@ export async function createClientGame(gameConfig: GameConfig, eventBus: EventBu
const canvas = createCanvas() const canvas = createCanvas()
let gameRenderer = createRenderer(canvas, game, eventBus, gameConfig.clientID) let gameRenderer = createRenderer(canvas, game, eventBus, gameConfig.clientID)
console.log(`creating private game got difficulty: ${gameConfig.difficulty}`)
return new GameRunner( return new GameRunner(
gameConfig.clientID, gameConfig,
gameConfig.ip,
eventBus, eventBus,
game, game,
gameRenderer, gameRenderer,
new InputHandler(canvas, eventBus), new InputHandler(canvas, eventBus),
new Executor(game, gameConfig.gameID), new Executor(game, gameConfig.difficulty, gameConfig.gameID),
transport, transport,
) )
} }
@@ -96,8 +100,7 @@ export class GameRunner {
private hasJoined = false private hasJoined = false
constructor( constructor(
private id: ClientID, private gameConfig: GameConfig,
private clientIP: string | null,
private eventBus: EventBus, private eventBus: EventBus,
private gs: Game, private gs: Game,
private renderer: GameRenderer, private renderer: GameRenderer,
@@ -122,7 +125,7 @@ export class GameRunner {
const onconnect = () => { const onconnect = () => {
console.log('Connected to game server!'); console.log('Connected to game server!');
this.transport.joinGame(this.clientIP, this.turns.length) this.transport.joinGame(this.turns.length)
}; };
const onmessage = (message: ServerMessage) => { const onmessage = (message: ServerMessage) => {
if (message.type == "start") { if (message.type == "start") {
@@ -170,7 +173,7 @@ export class GameRunner {
private playerEvent(event: PlayerEvent) { private playerEvent(event: PlayerEvent) {
console.log('received new player event!') console.log('received new player event!')
if (event.player.clientID() == this.id) { if (event.player.clientID() == this.gameConfig.clientID) {
console.log('setting name') console.log('setting name')
this.myPlayer = event.player this.myPlayer = event.player
} }
+30 -6
View File
@@ -1,12 +1,13 @@
import {LitElement, html, css} from 'lit'; import { LitElement, html, css } from 'lit';
import {customElement, property, state} from 'lit/decorators.js'; import { customElement, property, state } from 'lit/decorators.js';
import {GameMap} from '../core/game/Game'; import { Difficulty, GameMap } from '../core/game/Game';
import {Lobby} from '../core/Schemas'; import { Lobby } from '../core/Schemas';
@customElement('host-lobby-modal') @customElement('host-lobby-modal')
export class HostLobbyModal extends LitElement { export class HostLobbyModal extends LitElement {
@state() private isModalOpen = false; @state() private isModalOpen = false;
@state() private selectedMap: GameMap = GameMap.World; @state() private selectedMap: GameMap = GameMap.World;
@state() private selectedDiffculty: Difficulty = Difficulty.Medium;
@state() private lobbyId = 'a345d'; @state() private lobbyId = 'a345d';
@state() private copySuccess = false; @state() private copySuccess = false;
@@ -120,6 +121,18 @@ export class HostLobbyModal extends LitElement {
`)} `)}
</select> </select>
</div> </div>
<div>
<label for="map-select">Difficulty: </label>
<select id="map-select" @change=${this.handleDifficultyChange}>
${Object.entries(Difficulty)
.filter(([key]) => isNaN(Number(key)))
.map(([key, value]) => html`
<option value=${value} ?selected=${this.selectedDiffculty === value}>
${key}
</option>
`)}
</select>
</div>
<button @click=${this.startGame}>Start Game</button> <button @click=${this.startGame}>Start Game</button>
</div> </div>
</div> </div>
@@ -138,6 +151,7 @@ export class HostLobbyModal extends LitElement {
id: this.lobbyId, id: this.lobbyId,
}, },
map: this.selectedMap, map: this.selectedMap,
difficulty: this.selectedDiffculty,
}, },
bubbles: true, bubbles: true,
composed: true composed: true
@@ -155,15 +169,25 @@ export class HostLobbyModal extends LitElement {
private async handleMapChange(e: Event) { private async handleMapChange(e: Event) {
this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap; this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap;
console.log(`updating map to ${this.selectedMap}`) 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}`, { const response = await fetch(`/private_lobby/${this.lobbyId}`, {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({gameMap: this.selectedMap}) body: JSON.stringify({ gameMap: this.selectedMap, difficulty: this.selectedDiffculty })
}); });
} }
private async startGame() { private async startGame() {
console.log(`Starting private game with map: ${GameMap[this.selectedMap]}`); console.log(`Starting private game with map: ${GameMap[this.selectedMap]}`);
this.close(); this.close();
+7 -6
View File
@@ -1,14 +1,14 @@
import {GameRunner, joinLobby} from "./ClientGame"; import { GameRunner, joinLobby } from "./ClientGame";
import backgroundImage from '../../resources/images/TerrainMapFrontPage.png'; import backgroundImage from '../../resources/images/TerrainMapFrontPage.png';
import favicon from '../../resources/images/Favicon.png'; import favicon from '../../resources/images/Favicon.png';
import './PublicLobby'; import './PublicLobby';
import './UsernameInput'; import './UsernameInput';
import './styles.css'; import './styles.css';
import {UsernameInput} from "./UsernameInput"; import { UsernameInput } from "./UsernameInput";
import {SinglePlayerModal} from "./SinglePlayerModal"; import { SinglePlayerModal } from "./SinglePlayerModal";
import {HostLobbyModal as HostPrivateLobbyModal} from "./HostLobbyModal"; import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal";
import {JoinPrivateLobbyModal} from "./JoinPrivateLobbyModal"; import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal";
@@ -77,6 +77,7 @@ class Client {
gameID: lobby.id, gameID: lobby.id,
ip: clientIP, ip: clientIP,
map: event.detail.map, map: event.detail.map,
difficulty: event.detail.difficulty,
}, },
() => this.joinModal.close() () => this.joinModal.close()
); );
@@ -115,7 +116,7 @@ async function getClientIP(timeoutMs: number = 1000): Promise<string | null> {
throw new Error(`HTTP error! status: ${response.status}`); 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; return data.ip;
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
+6 -5
View File
@@ -1,7 +1,7 @@
import {LitElement, html, css} from 'lit'; import { LitElement, html, css } from 'lit';
import {customElement, state} from 'lit/decorators.js'; import { customElement, state } from 'lit/decorators.js';
import {Lobby} from "../core/Schemas"; import { Lobby } from "../core/Schemas";
import {GameMap} from '../core/game/Game'; import { Difficulty, GameMap } from '../core/game/Game';
@customElement('public-lobby') @customElement('public-lobby')
export class PublicLobby extends LitElement { export class PublicLobby extends LitElement {
@@ -113,13 +113,14 @@ export class PublicLobby extends LitElement {
lobby: lobby, lobby: lobby,
singlePlayer: false, singlePlayer: false,
map: GameMap.World, map: GameMap.World,
difficulty: Difficulty.Medium,
}, },
bubbles: true, bubbles: true,
composed: true composed: true
})); }));
} else { } else {
this.dispatchEvent(new CustomEvent('leave-lobby', { this.dispatchEvent(new CustomEvent('leave-lobby', {
detail: {lobby: this.currLobby}, detail: { lobby: this.currLobby },
bubbles: true, bubbles: true,
composed: true composed: true
})); }));
+21 -4
View File
@@ -1,11 +1,12 @@
import {LitElement, html, css} from 'lit'; import { LitElement, html, css } from 'lit';
import {customElement, property, state} from 'lit/decorators.js'; import { customElement, property, state } from 'lit/decorators.js';
import {GameMap} from '../core/game/Game'; import { Difficulty, GameMap } from '../core/game/Game';
@customElement('single-player-modal') @customElement('single-player-modal')
export class SinglePlayerModal extends LitElement { export class SinglePlayerModal extends LitElement {
@state() private isModalOpen = false; @state() private isModalOpen = false;
@state() private selectedMap: GameMap = GameMap.World; @state() private selectedMap: GameMap = GameMap.World;
@state() private selectedDifficulty: Difficulty = Difficulty.Medium;
static styles = css` static styles = css`
.modal-overlay { .modal-overlay {
@@ -87,6 +88,19 @@ export class SinglePlayerModal extends LitElement {
`)} `)}
</select> </select>
</div> </div>
<div>
<label for="map-select">Difficulty: </label>
<select id="map-select" @change=${this.handleDifficultyChange}>
${Object.entries(Difficulty)
.filter(([key]) => isNaN(Number(key)))
.map(([key, value]) => html`
<option value=${value} ?selected=${this.selectedDifficulty === value}>
${key}
</option>
`)}
</select>
</div>
<button @click=${this.startGame}>Start Game</button> <button @click=${this.startGame}>Start Game</button>
</div> </div>
</div> </div>
@@ -104,7 +118,9 @@ export class SinglePlayerModal extends LitElement {
private handleMapChange(e: Event) { private handleMapChange(e: Event) {
this.selectedMap = Number((e.target as HTMLSelectElement).value) as GameMap; 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() { private startGame() {
console.log(`Starting single player game with map: ${GameMap[this.selectedMap]}`); console.log(`Starting single player game with map: ${GameMap[this.selectedMap]}`);
this.dispatchEvent(new CustomEvent('join-lobby', { this.dispatchEvent(new CustomEvent('join-lobby', {
@@ -114,6 +130,7 @@ export class SinglePlayerModal extends LitElement {
id: "LOCAL", id: "LOCAL",
}, },
map: this.selectedMap, map: this.selectedMap,
difficulty: this.selectedDifficulty
}, },
bubbles: true, bubbles: true,
composed: true composed: true
+3 -2
View File
@@ -91,6 +91,7 @@ export class Transport {
private isLocal: boolean, private isLocal: boolean,
private eventBus: EventBus, private eventBus: EventBus,
private gameID: GameID, private gameID: GameID,
private clientIP: string | null,
private clientID: ClientID, private clientID: ClientID,
private playerID: PlayerID, private playerID: PlayerID,
private config: Config, private config: Config,
@@ -156,14 +157,14 @@ export class Transport {
} }
} }
joinGame(clientIP: string | null, numTurns: number) { joinGame(numTurns: number) {
this.sendMsg( this.sendMsg(
JSON.stringify( JSON.stringify(
ClientJoinMessageSchema.parse({ ClientJoinMessageSchema.parse({
type: "join", type: "join",
gameID: this.gameID, gameID: this.gameID,
clientID: this.clientID, clientID: this.clientID,
clientIP: clientIP, clientIP: this.clientIP,
lastTurn: numTurns lastTurn: numTurns
}) })
) )
+2 -2
View File
@@ -11,7 +11,7 @@
</script> </script>
<script> <script>
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
function gtag() {dataLayer.push(arguments);} function gtag() { dataLayer.push(arguments); }
gtag('js', new Date()); gtag('js', new Date());
gtag('config', 'AW-16702609763'); gtag('config', 'AW-16702609763');
@@ -28,7 +28,7 @@
</svg> </svg>
</a> </a>
<h1 class="text-7xl sm:text-5xl md:text-6xl lg:text-7xl mb-2">OpenFront.io</h1> <h1 class="text-7xl sm:text-5xl md:text-6xl lg:text-7xl mb-2">OpenFront.io</h1>
<h2 class="text-3xl sm:text-4xl md:text-5xl lg:text-6xl mb-4">(v0.7.1)</h2> <h2 class="text-3xl sm:text-4xl md:text-5xl lg:text-6xl mb-4">(v0.7.2)</h2>
<div class="flex justify-center items-start"> <div class="flex justify-center items-start">
<div class="w-full max-w-3xl p-4 space-y-4"> <div class="w-full max-w-3xl p-4 space-y-4">
<username-input></username-input> <username-input></username-input>
+4 -3
View File
@@ -1,5 +1,5 @@
import {z} from 'zod'; import { z } from 'zod';
import {GameMap, PlayerType} from './game/Game'; import { Difficulty, GameMap, PlayerType } from './game/Game';
export type GameID = string export type GameID = string
export type ClientID = string export type ClientID = string
@@ -53,7 +53,8 @@ export interface Lobby {
} }
const GameConfigSchema = z.object({ const GameConfigSchema = z.object({
gameMap: z.nativeEnum(GameMap) gameMap: z.nativeEnum(GameMap),
difficulty: z.nativeEnum(Difficulty)
}) })
const EmojiSchema = z.string().refine( const EmojiSchema = z.string().refine(
+8 -8
View File
@@ -1,8 +1,8 @@
import {Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile} from "../game/Game"; import { Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile } from "../game/Game";
import {GameID} from "../Schemas"; import { GameID } from "../Schemas";
import {simpleHash, within} from "../Util"; import { simpleHash, within } from "../Util";
import {Config, Theme} from "./Config"; import { Config, Theme } from "./Config";
import {pastelTheme} from "./PastelTheme"; import { pastelTheme } from "./PastelTheme";
@@ -55,9 +55,9 @@ export class DefaultConfig implements Config {
lobbyLifetime(): number { lobbyLifetime(): number {
return 120 * 1000 return 120 * 1000
} }
theme(): Theme {return pastelTheme;} theme(): Theme { return pastelTheme; }
attackLogic(attackTroops: number, attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): {attackerTroopLoss: number; defenderTroopLoss: number; tilesPerTickUsed: number} { attackLogic(attackTroops: number, attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): { attackerTroopLoss: number; defenderTroopLoss: number; tilesPerTickUsed: number } {
let mag = 0 let mag = 0
let speed = 0 let speed = 0
switch (tileToConquer.terrain()) { switch (tileToConquer.terrain()) {
@@ -125,7 +125,7 @@ export class DefaultConfig implements Config {
return 10000 return 10000
} }
if (playerInfo.playerType == PlayerType.FakeHuman) { if (playerInfo.playerType == PlayerType.FakeHuman) {
return 25000 return 2500 // start troops * strength * difficulty
} }
return 25000 return 25000
} }
+3 -3
View File
@@ -1,4 +1,4 @@
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType, Alliance, AllianceRequestReplyEvent} from "../game/Game"; import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType, Alliance, AllianceRequestReplyEvent, Difficulty} from "../game/Game";
import {AttackIntent, BoatAttackIntentSchema, GameID, Intent, Turn} from "../Schemas"; import {AttackIntent, BoatAttackIntentSchema, GameID, Intent, Turn} from "../Schemas";
import {AttackExecution} from "./AttackExecution"; import {AttackExecution} from "./AttackExecution";
import {SpawnExecution} from "./SpawnExecution"; import {SpawnExecution} from "./SpawnExecution";
@@ -26,7 +26,7 @@ export class Executor {
// private random = new PseudoRandom(999) // private random = new PseudoRandom(999)
private random: PseudoRandom = null private random: PseudoRandom = null
constructor(private gs: Game, private gameID: GameID) { constructor(private gs: Game, private difficulty: Difficulty, private gameID: GameID) {
// Add one to avoid id collisions with bots. // Add one to avoid id collisions with bots.
this.random = new PseudoRandom(simpleHash(gameID) + 1) this.random = new PseudoRandom(simpleHash(gameID) + 1)
} }
@@ -98,7 +98,7 @@ export class Executor {
this.random.nextID() this.random.nextID()
), ),
nation.cell, nation.cell,
nation.strength nation.strength * this.difficulty
)) ))
} }
return execs return execs
+14 -7
View File
@@ -1,12 +1,14 @@
import {Cell, Execution, MutableGame, MutablePlayer, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tile} from "../game/Game" import { Cell, Execution, MutableGame, MutablePlayer, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tile } from "../game/Game"
import {PseudoRandom} from "../PseudoRandom" import { PseudoRandom } from "../PseudoRandom"
import {and, bfs, dist, simpleHash} from "../Util"; import { and, bfs, dist, simpleHash } from "../Util";
import {AttackExecution} from "./AttackExecution"; import { AttackExecution } from "./AttackExecution";
import {BoatAttackExecution} from "./BoatAttackExecution"; import { BoatAttackExecution } from "./BoatAttackExecution";
import {SpawnExecution} from "./SpawnExecution"; import { SpawnExecution } from "./SpawnExecution";
export class FakeHumanExecution implements Execution { export class FakeHumanExecution implements Execution {
private firstMove = true
private active = true private active = true
private random: PseudoRandom; private random: PseudoRandom;
private attackRate: number private attackRate: number
@@ -56,6 +58,11 @@ export class FakeHumanExecution implements Execution {
this.player.setTroops(this.player.troops() * this.strength) this.player.setTroops(this.player.troops() * this.strength)
} }
} }
if (this.firstMove) {
this.firstMove = false
this.sendAttack(this.mg.terraNullius())
return
}
if (this.player.troops() < this.mg.config().maxTroops(this.player) / 4) { if (this.player.troops() < this.mg.config().maxTroops(this.player) / 4) {
return return
@@ -132,7 +139,7 @@ export class FakeHumanExecution implements Execution {
handleAllianceRequests() { handleAllianceRequests() {
for (const req of this.player.incomingAllianceRequests()) { for (const req of this.player.incomingAllianceRequests()) {
if (req.requestor().numTilesOwned() > this.player.numTilesOwned() * 2) { if (req.requestor().numTilesOwned() > this.player.numTilesOwned() * 2) {
req.accept() req.accept()
continue continue
} }
+15 -8
View File
@@ -1,10 +1,10 @@
import {info} from "console" import { info } from "console"
import {Config} from "../configuration/Config" import { Config } from "../configuration/Config"
import {GameEvent} from "../EventBus" import { GameEvent } from "../EventBus"
import {ClientID, GameID} from "../Schemas" import { ClientID, GameID } from "../Schemas"
import {DisplayMessageEvent, MessageType} from "../../client/graphics/layers/EventsDisplay" import { DisplayMessageEvent, MessageType } from "../../client/graphics/layers/EventsDisplay"
import {BreakAllianceExecution} from "../execution/alliance/BreakAllianceExecution" import { BreakAllianceExecution } from "../execution/alliance/BreakAllianceExecution"
import {DonateExecution} from "../execution/DonateExecution" import { DonateExecution } from "../execution/DonateExecution"
export type PlayerID = string export type PlayerID = string
export type Tick = number export type Tick = number
@@ -12,6 +12,13 @@ export type Currency = number
export const AllPlayers = "AllPlayers" as const; export const AllPlayers = "AllPlayers" as const;
export enum Difficulty {
Easy = 1,
Medium = 3,
Hard = 6,
Impossible = 12,
}
export enum GameMap { export enum GameMap {
World, World,
Europe Europe
@@ -45,7 +52,7 @@ export class Cell {
this.strRepr = `Cell[${this.x},${this.y}]` this.strRepr = `Cell[${this.x},${this.y}]`
} }
toString(): string {return this.strRepr} toString(): string { return this.strRepr }
} }
export enum TerrainType { export enum TerrainType {
+8 -8
View File
@@ -1,9 +1,9 @@
import {Config} from "../core/configuration/Config"; import { Config } from "../core/configuration/Config";
import {ClientID, GameConfig, GameID} from "../core/Schemas"; import { ClientID, GameConfig, GameID } from "../core/Schemas";
import {v4 as uuidv4} from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import {Client} from "./Client"; import { Client } from "./Client";
import {GamePhase, GameServer} from "./GameServer"; import { GamePhase, GameServer } from "./GameServer";
import {GameMap} from "../core/game/Game"; import { Difficulty, GameMap } from "../core/game/Game";
@@ -39,7 +39,7 @@ export class GameManager {
createPrivateGame(): string { createPrivateGame(): string {
const id = genSmallGameID() const id = genSmallGameID()
this.games.push(new GameServer(id, Date.now(), false, this.config, {gameMap: GameMap.World})) this.games.push(new GameServer(id, Date.now(), false, this.config, { gameMap: GameMap.World, difficulty: Difficulty.Medium }))
return id return id
} }
@@ -68,7 +68,7 @@ export class GameManager {
if (now > this.lastNewLobby + this.config.gameCreationRate()) { if (now > this.lastNewLobby + this.config.gameCreationRate()) {
this.lastNewLobby = now this.lastNewLobby = now
const id = uuidv4() const id = uuidv4()
lobbies.push(new GameServer(id, now, true, this.config, {gameMap: GameMap.World})) lobbies.push(new GameServer(id, now, true, this.config, { gameMap: GameMap.World, difficulty: Difficulty.Medium }))
} }
active.filter(g => !g.hasStarted() && g.isPublic).forEach(g => { active.filter(g => !g.hasStarted() && g.isPublic).forEach(g => {
+4
View File
@@ -30,12 +30,16 @@ export class GameServer {
public readonly isPublic: boolean, public readonly isPublic: boolean,
private config: Config, private config: Config,
private gameConfig: GameConfig, private gameConfig: GameConfig,
) { } ) { }
public updateGameConfig(gameConfig: GameConfig): void { public updateGameConfig(gameConfig: GameConfig): void {
if (gameConfig.gameMap != null) { if (gameConfig.gameMap != null) {
this.gameConfig.gameMap = gameConfig.gameMap this.gameConfig.gameMap = gameConfig.gameMap
} }
if(gameConfig.difficulty != null) {
this.gameConfig.difficulty = gameConfig.difficulty
}
} }
public addClient(client: Client, lastTurn: number) { public addClient(client: Client, lastTurn: number) {
+1 -1
View File
@@ -49,7 +49,7 @@ app.post('/start_private_lobby/:id', (req, res) => {
app.put('/private_lobby/:id', (req, res) => { app.put('/private_lobby/:id', (req, res) => {
const lobbyID = req.params.id const lobbyID = req.params.id
gm.updateGameConfig(lobbyID, {gameMap: req.body.gameMap}) gm.updateGameConfig(lobbyID, {gameMap: req.body.gameMap, difficulty: req.body.difficulty})
}); });
app.get('/lobby/:id/exists', (req, res) => { app.get('/lobby/:id/exists', (req, res) => {