mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 11:50:42 +00:00
Refactor: Split config into Config and ServerConfig
This commit is contained in:
@@ -2,7 +2,6 @@ import { Executor } from "../core/execution/ExecutionManager";
|
||||
import { Cell, MutableGame, PlayerEvent, PlayerID, MutablePlayer, TileEvent, Player, Game, UnitEvent, Tile, PlayerType, GameMap, Difficulty, GameType } 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, ClientMessageSchema, GameConfig, GameID, Intent, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn } from "../core/Schemas";
|
||||
@@ -14,6 +13,7 @@ import { createCanvas } from "./Utils";
|
||||
import { DisplayMessageEvent, MessageType } from "./graphics/layers/EventsDisplay";
|
||||
import { WorkerClient } from "../core/worker/WorkerClient";
|
||||
import { consolex, initRemoteSender } from "../core/Consolex";
|
||||
import { getConfig, getServerConfig } from "../core/configuration/Config";
|
||||
|
||||
export interface LobbyConfig {
|
||||
playerName: () => string
|
||||
@@ -32,7 +32,7 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v
|
||||
|
||||
consolex.log(`joinging lobby: gameID: ${lobbyConfig.gameID}, clientID: ${lobbyConfig.clientID}, persistentID: ${lobbyConfig.persistentID}`)
|
||||
|
||||
const config = getConfig()
|
||||
const serverConfig = getServerConfig()
|
||||
|
||||
let gameConfig: GameConfig = null
|
||||
if (lobbyConfig.gameType == GameType.Singleplayer) {
|
||||
@@ -47,7 +47,7 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v
|
||||
lobbyConfig,
|
||||
gameConfig,
|
||||
eventBus,
|
||||
config,
|
||||
serverConfig,
|
||||
)
|
||||
|
||||
const onconnect = () => {
|
||||
@@ -70,11 +70,11 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v
|
||||
|
||||
|
||||
export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: GameConfig, eventBus: EventBus, transport: Transport): Promise<GameRunner> {
|
||||
const config = getConfig()
|
||||
const config = getConfig(gameConfig)
|
||||
|
||||
const terrainMap = await loadTerrainMap(gameConfig.gameMap);
|
||||
|
||||
let game = createGame(terrainMap.map, terrainMap.miniMap, eventBus, config, gameConfig)
|
||||
let game = createGame(terrainMap.map, terrainMap.miniMap, eventBus, config)
|
||||
|
||||
const worker = new WorkerClient(game, gameConfig.gameMap)
|
||||
consolex.log('going to init path finder')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Config } from "../core/configuration/Config";
|
||||
import { Config, ServerConfig } from "../core/configuration/Config";
|
||||
import { consolex } from "../core/Consolex";
|
||||
import { ClientID, ClientMessage, ClientMessageSchema, GameConfig, GameID, GameRecordSchema, Intent, PlayerRecord, ServerMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn } from "../core/Schemas";
|
||||
import { CreateGameRecord, generateID } from "../core/Util";
|
||||
@@ -16,7 +16,7 @@ export class LocalServer {
|
||||
|
||||
|
||||
constructor(
|
||||
private config: Config,
|
||||
private serverConfig: ServerConfig,
|
||||
private gameConfig: GameConfig,
|
||||
private lobbyConfig: LobbyConfig,
|
||||
private clientConnect: () => void,
|
||||
@@ -26,7 +26,7 @@ export class LocalServer {
|
||||
|
||||
start() {
|
||||
this.startedAt = Date.now()
|
||||
this.endTurnIntervalID = setInterval(() => this.endTurn(), this.config.turnIntervalMs());
|
||||
this.endTurnIntervalID = setInterval(() => this.endTurn(), this.serverConfig.turnIntervalMs());
|
||||
this.clientConnect()
|
||||
this.clientMessage(ServerStartGameMessageSchema.parse({
|
||||
type: "start",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Config } from "../core/configuration/Config"
|
||||
import { Config, ServerConfig } from "../core/configuration/Config"
|
||||
import { SendLogEvent } from "../core/Consolex"
|
||||
import { EventBus, GameEvent } from "../core/EventBus"
|
||||
import { AllianceRequest, AllPlayers, Cell, GameType, Player, PlayerID, PlayerType, Tile, UnitType } from "../core/game/Game"
|
||||
@@ -104,7 +104,7 @@ export class Transport {
|
||||
// gameConfig only set on private games
|
||||
private gameConfig: GameConfig | null,
|
||||
private eventBus: EventBus,
|
||||
private config: Config,
|
||||
private serverConfig: ServerConfig,
|
||||
) {
|
||||
this.isLocal = lobbyConfig.gameType == GameType.Singleplayer
|
||||
|
||||
@@ -154,7 +154,7 @@ export class Transport {
|
||||
}
|
||||
|
||||
private connectLocal(onconnect: () => void, onmessage: (message: ServerMessage) => void) {
|
||||
this.localServer = new LocalServer(this.config, this.gameConfig, this.lobbyConfig, onconnect, onmessage)
|
||||
this.localServer = new LocalServer(this.serverConfig, this.gameConfig, this.lobbyConfig, onconnect, onmessage)
|
||||
this.localServer.start()
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ export class UILayer implements Layer {
|
||||
const barHeight = 15;
|
||||
const barBackgroundWidth = this.transformHandler.width();
|
||||
|
||||
const ratio = this.game.ticks() / this.game.config().numSpawnPhaseTurns(this.game.gameConfig().gameType)
|
||||
const ratio = this.game.ticks() / this.game.config().numSpawnPhaseTurns(this.game.config().gameConfig().gameType)
|
||||
|
||||
// Draw bar background
|
||||
context.fillStyle = 'rgba(0, 0, 0, 0.5)';
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
import { Difficulty, GameType, Gold, Player, PlayerID, PlayerInfo, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game";
|
||||
import { Colord, colord } from "colord";
|
||||
import { devConfig } from "./DevConfig";
|
||||
import { GameID } from "../Schemas";
|
||||
import { preprodConfig } from "./PreprodConfig";
|
||||
import { prodConfig } from "./ProdConfig";
|
||||
import { consolex } from "../Consolex";
|
||||
import { GameConfig } from "../Schemas";
|
||||
import { DefaultConfig } from "./DefaultConfig";
|
||||
import { DevConfig, DevServerConfig } from "./DevConfig";
|
||||
|
||||
export enum GameEnv {
|
||||
Dev,
|
||||
Prod
|
||||
}
|
||||
export function getConfig(gameConfig: GameConfig): Config {
|
||||
const sc = getServerConfig()
|
||||
switch (process.env.GAME_ENV) {
|
||||
case 'dev':
|
||||
return new DevConfig(sc, gameConfig)
|
||||
case 'preprod':
|
||||
case 'prod':
|
||||
consolex.log('using prod config')
|
||||
return new DefaultConfig(sc, gameConfig)
|
||||
default:
|
||||
throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`)
|
||||
}
|
||||
}
|
||||
|
||||
export function getConfig(): Config {
|
||||
export function getServerConfig(): ServerConfig {
|
||||
switch (process.env.GAME_ENV) {
|
||||
case 'dev':
|
||||
consolex.log('using dev config')
|
||||
return devConfig
|
||||
return new DevServerConfig()
|
||||
case 'preprod':
|
||||
consolex.log('using preprod config')
|
||||
return preprodConfig
|
||||
@@ -27,17 +41,17 @@ export function getConfig(): Config {
|
||||
}
|
||||
}
|
||||
|
||||
export function getGameEnv(): GameEnv {
|
||||
return GameEnv.Prod
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
discordBotSecret(): string
|
||||
theme(): Theme;
|
||||
percentageTilesOwnedToWin(): number
|
||||
export interface ServerConfig {
|
||||
turnIntervalMs(): number
|
||||
gameCreationRate(): number
|
||||
lobbyLifetime(): number
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
serverConfig(): ServerConfig
|
||||
gameConfig(): GameConfig
|
||||
theme(): Theme;
|
||||
percentageTilesOwnedToWin(): number
|
||||
numBots(): number
|
||||
spawnNPCs(): boolean
|
||||
numSpawnPhaseTurns(gameType: GameType): number
|
||||
|
||||
@@ -1,13 +1,35 @@
|
||||
import { Difficulty, GameType, Gold, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game";
|
||||
import { GameID } from "../Schemas";
|
||||
import { GameConfig } from "../Schemas";
|
||||
import { assertNever, distSort, manhattanDist, simpleHash, within } from "../Util";
|
||||
import { Config, Theme } from "./Config";
|
||||
import { Config, ServerConfig, Theme } from "./Config";
|
||||
import { pastelTheme } from "./PastelTheme";
|
||||
|
||||
export abstract class DefaultServerConfig implements ServerConfig {
|
||||
turnIntervalMs(): number {
|
||||
return 100
|
||||
}
|
||||
gameCreationRate(): number {
|
||||
return 10 * 60 * 1000
|
||||
}
|
||||
lobbyLifetime(): number {
|
||||
return 10 * 120 * 1000
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export abstract class DefaultConfig implements Config {
|
||||
abstract discordBotSecret(): string
|
||||
export class DefaultConfig implements Config {
|
||||
|
||||
constructor(private _serverConfig: ServerConfig, private _gameConfig: GameConfig) {
|
||||
|
||||
}
|
||||
|
||||
gameConfig(): GameConfig {
|
||||
return this._gameConfig
|
||||
}
|
||||
|
||||
serverConfig(): ServerConfig {
|
||||
return this._serverConfig
|
||||
}
|
||||
|
||||
difficultyModifier(difficulty: Difficulty): number {
|
||||
switch (difficulty) {
|
||||
@@ -162,15 +184,6 @@ export abstract class DefaultConfig implements Config {
|
||||
numBots(): number {
|
||||
return 400
|
||||
}
|
||||
turnIntervalMs(): number {
|
||||
return 100
|
||||
}
|
||||
gameCreationRate(): number {
|
||||
return 10 * 60 * 1000
|
||||
}
|
||||
lobbyLifetime(): number {
|
||||
return 10 * 120 * 1000
|
||||
}
|
||||
theme(): Theme { return pastelTheme; }
|
||||
|
||||
attackLogic(attackTroops: number, attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): { attackerTroopLoss: number; defenderTroopLoss: number; tilesPerTickUsed: number } {
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
import { GameType, Player, PlayerInfo, UnitInfo, UnitType } from "../game/Game";
|
||||
import { DefaultConfig } from "./DefaultConfig";
|
||||
import { GameConfig } from "../Schemas";
|
||||
import { ServerConfig } from "./Config";
|
||||
import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
|
||||
|
||||
export const devConfig = new class extends DefaultConfig {
|
||||
discordBotSecret(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
unitInfo(type: UnitType): UnitInfo {
|
||||
const info = super.unitInfo(type)
|
||||
const oldCost = info.cost
|
||||
info.cost = (p: Player) => oldCost(p) / 10000
|
||||
return info
|
||||
}
|
||||
|
||||
percentageTilesOwnedToWin(): number {
|
||||
return 95
|
||||
}
|
||||
export class DevServerConfig extends DefaultServerConfig {
|
||||
numSpawnPhaseTurns(gameType: GameType): number {
|
||||
return gameType == GameType.Singleplayer ? 40 : 200
|
||||
// return 100
|
||||
@@ -25,6 +14,24 @@ export const devConfig = new class extends DefaultConfig {
|
||||
lobbyLifetime(): number {
|
||||
return 10 * 1000
|
||||
}
|
||||
}
|
||||
|
||||
export class DevConfig extends DefaultConfig {
|
||||
|
||||
constructor(sc: ServerConfig, gc: GameConfig) {
|
||||
super(sc, gc);
|
||||
}
|
||||
|
||||
unitInfo(type: UnitType): UnitInfo {
|
||||
const info = super.unitInfo(type)
|
||||
const oldCost = info.cost
|
||||
info.cost = (p: Player) => oldCost(p) / 10000
|
||||
return info
|
||||
}
|
||||
|
||||
percentageTilesOwnedToWin(): number {
|
||||
return 95
|
||||
}
|
||||
// tradeShipSpawnRate(): number {
|
||||
// return 10
|
||||
// }
|
||||
@@ -39,4 +46,4 @@ export const devConfig = new class extends DefaultConfig {
|
||||
// return false
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { DefaultConfig } from "./DefaultConfig";
|
||||
import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
|
||||
|
||||
export const preprodConfig = new class extends DefaultConfig {
|
||||
discordBotSecret(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
export const preprodConfig = new class extends DefaultServerConfig {
|
||||
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
import { DefaultConfig } from "./DefaultConfig";
|
||||
import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
|
||||
|
||||
export const prodConfig = new class extends DefaultConfig {
|
||||
discordBotSecret(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
export const prodConfig = new class extends DefaultServerConfig {
|
||||
|
||||
}
|
||||
@@ -126,7 +126,7 @@ export class Executor {
|
||||
this.random.nextID()
|
||||
),
|
||||
nation.cell,
|
||||
nation.strength * this.gs.config().difficultyModifier(this.gs.gameConfig().difficulty)
|
||||
nation.strength * this.gs.config().difficultyModifier(this.gs.config().gameConfig().difficulty)
|
||||
))
|
||||
}
|
||||
return execs
|
||||
|
||||
@@ -314,7 +314,6 @@ export interface Game {
|
||||
addExecution(...exec: Execution[]): void
|
||||
nations(): Nation[]
|
||||
config(): Config
|
||||
gameConfig(): GameConfig
|
||||
displayMessage(message: string, type: MessageType, playerID: PlayerID | null): void
|
||||
units(...types: UnitType[]): Unit[]
|
||||
unitInfo(type: UnitType): UnitInfo
|
||||
|
||||
@@ -13,8 +13,8 @@ import { DisplayMessageEvent, MessageType } from "../../client/graphics/layers/E
|
||||
import { UnitImpl } from "./UnitImpl";
|
||||
import { consolex } from "../Consolex";
|
||||
|
||||
export function createGame(terrainMap: TerrainMapImpl, miniMap: TerrainMap, eventBus: EventBus, config: Config, gameConfig: GameConfig): Game {
|
||||
return new GameImpl(terrainMap, miniMap, eventBus, config, gameConfig)
|
||||
export function createGame(terrainMap: TerrainMapImpl, miniMap: TerrainMap, eventBus: EventBus, config: Config): Game {
|
||||
return new GameImpl(terrainMap, miniMap, eventBus, config)
|
||||
}
|
||||
|
||||
export type CellString = string
|
||||
@@ -45,7 +45,6 @@ export class GameImpl implements MutableGame {
|
||||
private _miniMap: TerrainMap,
|
||||
public eventBus: EventBus,
|
||||
private _config: Config,
|
||||
private _gameConfig: GameConfig,
|
||||
) {
|
||||
this._terraNullius = new TerraNulliusImpl(this)
|
||||
this._width = _terrainMap.width();
|
||||
@@ -67,10 +66,6 @@ export class GameImpl implements MutableGame {
|
||||
))
|
||||
}
|
||||
|
||||
gameConfig(): GameConfig {
|
||||
return this._gameConfig
|
||||
}
|
||||
|
||||
addFallout(tile: Tile) {
|
||||
const ti = tile as TileImpl
|
||||
if (tile.hasOwner()) {
|
||||
@@ -149,7 +144,7 @@ export class GameImpl implements MutableGame {
|
||||
}
|
||||
|
||||
inSpawnPhase(): boolean {
|
||||
return this._ticks <= this.config().numSpawnPhaseTurns(this._gameConfig.gameType)
|
||||
return this._ticks <= this.config().numSpawnPhaseTurns(this.config().gameConfig().gameType)
|
||||
}
|
||||
|
||||
ticks(): number {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Config } from "../core/configuration/Config";
|
||||
import { Config, ServerConfig } from "../core/configuration/Config";
|
||||
import { ClientID, GameConfig, GameID } from "../core/Schemas";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Client } from "./Client";
|
||||
@@ -14,7 +14,7 @@ export class GameManager {
|
||||
|
||||
private games: GameServer[] = []
|
||||
|
||||
constructor(private config: Config) { }
|
||||
constructor(private config: ServerConfig) { }
|
||||
|
||||
public game(id: GameID): GameServer | null {
|
||||
return this.games.find(g => g.id == id)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ClientID, ClientMessage, ClientMessageSchema, GameConfig, GameRecordSchema, Intent, PlayerRecord, ServerPingMessageSchema, ServerStartGameMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn } from "../core/Schemas";
|
||||
import { Config } from "../core/configuration/Config";
|
||||
import { Config, ServerConfig } from "../core/configuration/Config";
|
||||
import { Client } from "./Client";
|
||||
import WebSocket from 'ws';
|
||||
import { slog } from "./StructuredLog";
|
||||
@@ -35,7 +35,7 @@ export class GameServer {
|
||||
public readonly id: string,
|
||||
public readonly createdAt: number,
|
||||
public readonly isPublic: boolean,
|
||||
private config: Config,
|
||||
private config: ServerConfig,
|
||||
private gameConfig: GameConfig,
|
||||
|
||||
) { }
|
||||
|
||||
@@ -5,7 +5,7 @@ import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { GameManager } from './GameManager';
|
||||
import { ClientMessage, ClientMessageSchema, GameRecord, GameRecordSchema, LogSeverity } from '../core/Schemas';
|
||||
import { getConfig } from '../core/configuration/Config';
|
||||
import { getConfig, getServerConfig } from '../core/configuration/Config';
|
||||
import { slog } from './StructuredLog';
|
||||
import { Client } from './Client';
|
||||
import { GamePhase, GameServer } from './GameServer';
|
||||
@@ -23,7 +23,7 @@ const wss = new WebSocketServer({ server });
|
||||
app.use(express.static(path.join(__dirname, '../../out')));
|
||||
app.use(express.json())
|
||||
|
||||
const gm = new GameManager(getConfig())
|
||||
const gm = new GameManager(getServerConfig())
|
||||
|
||||
const bot = new DiscordBot();
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user