enable pause on replay

This commit is contained in:
evan
2025-05-11 09:47:45 -07:00
parent 6530456d38
commit ec323d2c1f
9 changed files with 56 additions and 13 deletions
+13
View File
@@ -112,6 +112,7 @@ export async function createClientGame(
const config = await getConfig(
lobbyConfig.gameStartInfo.config,
userSettings,
lobbyConfig.gameRecord != null,
);
let gameMap: TerrainMapData | null = null;
@@ -170,6 +171,8 @@ export class ClientGameRunner {
private lastMessageTime: number = 0;
private connectionCheckInterval: NodeJS.Timeout | null = null;
private turnsExecuted = 0;
constructor(
private lobby: LobbyConfig,
private eventBus: EventBus,
@@ -218,6 +221,14 @@ export class ClientGameRunner {
public start() {
consolex.log("starting client game");
setInterval(() => {
if (this.lobby.gameRecord) {
if (this.turnsExecuted == this.turnsSeen) {
this.transport.endTurn();
}
}
}, 10);
this.isActive = true;
this.lastMessageTime = Date.now();
setTimeout(() => {
@@ -242,6 +253,8 @@ export class ClientGameRunner {
this.stop(true);
return;
}
this.turnsExecuted++;
gu.updates[GameUpdateType.Hash].forEach((hu: HashUpdate) => {
this.eventBus.emit(new SendHashEvent(hu.tick, hu.hash));
});
+13 -6
View File
@@ -16,7 +16,11 @@ import { LobbyConfig } from "./ClientGameRunner";
import { getPersistentIDFromCookie } from "./Main";
export class LocalServer {
// All turns from the game record on replay.
private allTurns: Turn[] = [];
private turns: Turn[] = [];
private intents: Intent[] = [];
private startedAt: number;
@@ -35,7 +39,7 @@ export class LocalServer {
start() {
this.startedAt = Date.now();
if (!this.lobbyConfig.gameRecord) {
if (this.lobbyConfig.gameRecord == null) {
this.endTurnIntervalID = setInterval(
() => this.endTurn(),
this.lobbyConfig.serverConfig.turnIntervalMs(),
@@ -43,15 +47,15 @@ export class LocalServer {
}
this.clientConnect();
if (this.lobbyConfig.gameRecord) {
this.turns = decompressGameRecord(this.lobbyConfig.gameRecord).turns;
console.log(`loaded turns: ${JSON.stringify(this.turns)}`);
this.allTurns = decompressGameRecord(this.lobbyConfig.gameRecord).turns;
console.log(`loaded turns: ${JSON.stringify(this.allTurns)}`);
}
this.clientMessage(
ServerStartGameMessageSchema.parse({
type: "start",
gameID: this.lobbyConfig.gameStartInfo.gameID,
gameStartInfo: this.lobbyConfig.gameStartInfo,
turns: this.turns,
turns: [],
}),
);
}
@@ -90,7 +94,7 @@ export class LocalServer {
return;
}
// If we are replaying a game then verify hash.
const archivedHash = this.turns[clientMsg.turnNumber].hash;
const archivedHash = this.allTurns[clientMsg.turnNumber].hash;
if (!archivedHash) {
console.warn(
`no archived hash found for turn ${clientMsg.turnNumber}, client hash: ${clientMsg.hash}`,
@@ -121,10 +125,13 @@ export class LocalServer {
}
}
private endTurn() {
public endTurn() {
if (this.paused) {
return;
}
if (this.allTurns) {
this.intents = this.allTurns[this.turns.length].intents;
}
const pastTurn: Turn = {
turnNumber: this.turns.length,
gameID: this.lobbyConfig.gameStartInfo.gameID,
+6
View File
@@ -313,6 +313,12 @@ export class Transport {
this.connect(this.onconnect, this.onmessage);
}
public endTurn() {
if (this.isLocal) {
this.localServer.endTurn();
}
}
private onSendLogEvent(event: SendLogEvent) {
this.sendMsg(
JSON.stringify(
+2 -1
View File
@@ -122,7 +122,8 @@ export class OptionsMenu extends LitElement implements Layer {
init() {
console.log("init called from OptionsMenu");
this.showPauseButton =
this.game.config().gameConfig().gameType == GameType.Singleplayer;
this.game.config().gameConfig().gameType == GameType.Singleplayer ||
this.game.config().isReplay();
this.isVisible = true;
this.requestUpdate();
}
+1
View File
@@ -136,6 +136,7 @@ export interface Config {
defaultNukeSpeed(): number;
nukeDeathFactor(humans: number, tilesOwned: number): number;
structureMinDist(): number;
isReplay(): boolean;
}
export interface Theme {
+3 -2
View File
@@ -12,15 +12,16 @@ export let cachedSC: ServerConfig = null;
export async function getConfig(
gameConfig: GameConfig,
userSettings: UserSettings | null = null,
isReplay: boolean = false,
): Promise<Config> {
const sc = await getServerConfigFromClient();
switch (sc.env()) {
case GameEnv.Dev:
return new DevConfig(sc, gameConfig, userSettings);
return new DevConfig(sc, gameConfig, userSettings, isReplay);
case GameEnv.Preprod:
case GameEnv.Prod:
consolex.log("using prod config");
return new DefaultConfig(sc, gameConfig, userSettings);
return new DefaultConfig(sc, gameConfig, userSettings, isReplay);
default:
throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`);
}
+4
View File
@@ -151,7 +151,11 @@ export class DefaultConfig implements Config {
private _serverConfig: ServerConfig,
private _gameConfig: GameConfig,
private _userSettings: UserSettings,
private _isReplay: boolean,
) {}
isReplay(): boolean {
return this._isReplay;
}
samHittingChance(): number {
return 0.8;
+8 -3
View File
@@ -6,7 +6,7 @@ import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
export class DevServerConfig extends DefaultServerConfig {
r2Bucket(): string {
return "openfront-staging";
return "openfront-prod";
}
adminToken(): string {
return "WARNING_DEV_ADMIN_KEY_DO_NOT_USE_IN_PRODUCTION";
@@ -44,8 +44,13 @@ export class DevServerConfig extends DefaultServerConfig {
}
export class DevConfig extends DefaultConfig {
constructor(sc: ServerConfig, gc: GameConfig, us: UserSettings) {
super(sc, gc, us);
constructor(
sc: ServerConfig,
gc: GameConfig,
us: UserSettings,
isReplay: boolean,
) {
super(sc, gc, us, isReplay);
}
// numSpawnPhaseTurns(): number {
+6 -1
View File
@@ -32,7 +32,12 @@ export async function setup(mapName: string, _gameConfig: GameConfig = {}) {
instantBuild: false,
..._gameConfig,
};
const config = new TestConfig(serverConfig, gameConfig, new UserSettings());
const config = new TestConfig(
serverConfig,
gameConfig,
new UserSettings(),
false,
);
// Create and return the game
return createGame([], [], gameMap, miniGameMap, config);