This commit is contained in:
Ryan Barlow
2026-01-29 21:15:02 +00:00
parent db50603b71
commit 0803b71e81
6 changed files with 31 additions and 40 deletions
-29
View File
@@ -89,35 +89,6 @@ export type UpdateGameConfigIntent = z.infer<
export type Turn = z.infer<typeof TurnSchema>;
export type GameConfig = z.infer<typeof GameConfigSchema>;
const TICKS_PER_SECOND = 10;
const SPAWN_PHASE_TICKS = {
singleplayer: 100,
multiplayer: 300,
} as const;
export function spawnPhaseTurns(
configOrGameType:
| Pick<GameConfig, "gameType">
| GameType
| string
| undefined,
): number {
return (typeof configOrGameType === "object"
? configOrGameType?.gameType
: configOrGameType) === GameType.Singleplayer
? SPAWN_PHASE_TICKS.singleplayer
: SPAWN_PHASE_TICKS.multiplayer;
}
export function spawnPhaseSeconds(
configOrGameType:
| Pick<GameConfig, "gameType">
| GameType
| string
| undefined,
): number {
return spawnPhaseTurns(configOrGameType) / TICKS_PER_SECOND;
}
export type ClientMessage =
| ClientSendWinnerMessage
+3
View File
@@ -2,6 +2,7 @@ import { Colord } from "colord";
import { JWK } from "jose";
import {
Game,
GameType,
Gold,
Player,
PlayerInfo,
@@ -27,6 +28,8 @@ export interface ServerConfig {
turnstileSiteKey(): string;
turnstileSecretKey(): string;
turnIntervalMs(): number;
ticksPerSecond(): number;
spawnPhaseTicks(gameType: GameType): number;
gameCreationRate(): number;
numWorkers(): number;
workerIndex(gameID: GameID): number;
+9 -7
View File
@@ -4,6 +4,7 @@ import {
Difficulty,
Game,
GameMode,
GameType,
Gold,
Player,
PlayerInfo,
@@ -17,12 +18,7 @@ import {
import { TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import { UserSettings } from "../game/UserSettings";
import {
GameConfig,
GameID,
spawnPhaseTurns,
TeamCountConfig,
} from "../Schemas";
import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
import { NukeType } from "../StatsSchemas";
import { assertNever, sigmoid, simpleHash, within } from "../Util";
import { Config, GameEnv, NukeMagnitude, ServerConfig, Theme } from "./Config";
@@ -121,6 +117,12 @@ export abstract class DefaultServerConfig implements ServerConfig {
turnIntervalMs(): number {
return 100;
}
ticksPerSecond(): number {
return 1000 / this.turnIntervalMs();
}
spawnPhaseTicks(gameType: GameType): number {
return gameType === GameType.Singleplayer ? 100 : 300;
}
gameCreationRate(): number {
return 60 * 1000;
}
@@ -546,7 +548,7 @@ export class DefaultConfig implements Config {
return 3;
}
numSpawnPhaseTurns(): number {
return spawnPhaseTurns(this._gameConfig);
return this._serverConfig.spawnPhaseTicks(this._gameConfig.gameType);
}
numBots(): number {
return this.bots();
+11 -3
View File
@@ -1,6 +1,7 @@
import { z } from "zod";
import { GameInfo, spawnPhaseSeconds } from "../core/Schemas";
import { GameMode } from "../core/game/Game";
import { ServerConfig } from "../core/configuration/Config";
import { GameMode, GameType } from "../core/game/Game";
import { GameInfo } from "../core/Schemas";
export const PlayerInfoSchema = z.object({
clientID: z.string().optional(),
@@ -132,6 +133,7 @@ export function buildPreview(
workerPath: string,
lobby: GameInfo | null,
publicInfo: ExternalGameInfo | null,
serverConfig: ServerConfig,
): PreviewMeta {
const isFinished = !!publicInfo?.info?.end;
const isPrivate = lobby?.gameConfig?.gameType === "Private";
@@ -180,9 +182,15 @@ export function buildPreview(
const winner = parseWinner(publicInfo?.info?.winner, players);
const duration = publicInfo?.info?.duration;
const gameType = lobby?.gameConfig?.gameType ?? config.gameType;
const spawnPhaseSeconds =
serverConfig.spawnPhaseTicks(
gameType === GameType.Singleplayer
? GameType.Singleplayer
: GameType.Public,
) / serverConfig.ticksPerSecond();
const adjustedDuration =
typeof duration === "number"
? Math.max(0, duration - spawnPhaseSeconds(gameType))
? Math.max(0, duration - spawnPhaseSeconds)
: undefined;
// Normalize map name to match filesystem (lowercase, no spaces or special chars)
+1
View File
@@ -102,6 +102,7 @@ export function registerGamePreviewRoute(opts: {
config.workerPath(gameID),
lobby,
publicInfo,
config,
);
// Always serve HTML with meta tags for /game/:id route
+7 -1
View File
@@ -1,6 +1,6 @@
import { JWK } from "jose";
import { GameEnv, ServerConfig } from "../../src/core/configuration/Config";
import { PublicGameModifiers } from "../../src/core/game/Game";
import { GameType, PublicGameModifiers } from "../../src/core/game/Game";
import { GameID } from "../../src/core/Schemas";
export class TestServerConfig implements ServerConfig {
@@ -46,6 +46,12 @@ export class TestServerConfig implements ServerConfig {
turnIntervalMs(): number {
throw new Error("Method not implemented.");
}
ticksPerSecond(): number {
throw new Error("Method not implemented.");
}
spawnPhaseTicks(gameType: GameType): number {
throw new Error("Method not implemented.");
}
gameCreationRate(): number {
throw new Error("Method not implemented.");
}