mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 16:04:36 +00:00
Unified WinnerSchema (#856)
## Description: Refactor various types across the project to use WinnerSchema. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com>
This commit is contained in:
@@ -7,11 +7,12 @@ import {
|
||||
GameStartInfo,
|
||||
PlayerRecord,
|
||||
ServerMessage,
|
||||
Winner,
|
||||
} from "../core/Schemas";
|
||||
import { createGameRecord } from "../core/Util";
|
||||
import { ServerConfig } from "../core/configuration/Config";
|
||||
import { getConfig } from "../core/configuration/ConfigLoader";
|
||||
import { Cell, Team, UnitType } from "../core/game/Game";
|
||||
import { Cell, UnitType } from "../core/game/Game";
|
||||
import { TileRef } from "../core/game/GameMap";
|
||||
import {
|
||||
ErrorUpdate,
|
||||
@@ -186,6 +187,13 @@ export class ClientGameRunner {
|
||||
this.lastMessageTime = Date.now();
|
||||
}
|
||||
|
||||
private getWinner(update: WinUpdate): Winner {
|
||||
if (update.winner[0] !== "player") return update.winner;
|
||||
const clientId = this.gameView.playerBySmallID(update.winner[1]).clientID();
|
||||
if (clientId === null) return;
|
||||
return ["player", clientId];
|
||||
}
|
||||
|
||||
private saveGame(update: WinUpdate) {
|
||||
if (this.myPlayer === null) {
|
||||
return;
|
||||
@@ -199,14 +207,7 @@ export class ClientGameRunner {
|
||||
stats: update.allPlayersStats[this.lobby.clientID],
|
||||
},
|
||||
];
|
||||
let winner: ClientID | Team | null = null;
|
||||
if (update.winnerType === "player") {
|
||||
winner = this.gameView
|
||||
.playerBySmallID(update.winner as number)
|
||||
.clientID();
|
||||
} else {
|
||||
winner = update.winner as Team;
|
||||
}
|
||||
const winner = this.getWinner(update);
|
||||
|
||||
if (this.lobby.gameStartInfo === undefined) {
|
||||
throw new Error("missing gameStartInfo");
|
||||
@@ -220,7 +221,6 @@ export class ClientGameRunner {
|
||||
startTime(),
|
||||
Date.now(),
|
||||
winner,
|
||||
update.winnerType,
|
||||
);
|
||||
endGame(record);
|
||||
}
|
||||
|
||||
@@ -193,8 +193,7 @@ export class LocalServer {
|
||||
this.turns,
|
||||
this.startedAt,
|
||||
Date.now(),
|
||||
this.winner?.winner ?? null,
|
||||
this.winner?.winnerType ?? null,
|
||||
this.winner?.winner,
|
||||
);
|
||||
if (!saveFullGame) {
|
||||
// Clear turns because beacon only supports up to 64kb
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
GameType,
|
||||
PlayerID,
|
||||
PlayerType,
|
||||
Team,
|
||||
Tick,
|
||||
UnitType,
|
||||
} from "../core/game/Game";
|
||||
@@ -14,7 +13,6 @@ import { PlayerView } from "../core/game/GameView";
|
||||
import {
|
||||
AllPlayersStats,
|
||||
ClientHashMessage,
|
||||
ClientID,
|
||||
ClientIntentMessage,
|
||||
ClientJoinMessage,
|
||||
ClientLogMessage,
|
||||
@@ -23,6 +21,7 @@ import {
|
||||
Intent,
|
||||
ServerMessage,
|
||||
ServerMessageSchema,
|
||||
Winner,
|
||||
} from "../core/Schemas";
|
||||
import { LobbyConfig } from "./ClientGameRunner";
|
||||
import { LocalServer } from "./LocalServer";
|
||||
@@ -142,9 +141,8 @@ export class SendSetTargetTroopRatioEvent implements GameEvent {
|
||||
|
||||
export class SendWinnerEvent implements GameEvent {
|
||||
constructor(
|
||||
public readonly winner: ClientID | Team,
|
||||
public readonly winner: Winner,
|
||||
public readonly allPlayersStats: AllPlayersStats,
|
||||
public readonly winnerType: "player" | "team",
|
||||
) {}
|
||||
}
|
||||
export class SendHashEvent implements GameEvent {
|
||||
@@ -537,7 +535,6 @@ export class Transport {
|
||||
type: "winner",
|
||||
winner: event.winner,
|
||||
allPlayersStats: event.allPlayersStats,
|
||||
winnerType: event.winnerType,
|
||||
} satisfies ClientSendWinnerMessage;
|
||||
this.sendMsg(JSON.stringify(msg));
|
||||
} else {
|
||||
|
||||
@@ -2,9 +2,8 @@ import { LitElement, css, html } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { translateText } from "../../../client/Utils";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { Team } from "../../../core/game/Game";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
import { SendWinnerEvent } from "../../Transport";
|
||||
import { Layer } from "./Layer";
|
||||
|
||||
@@ -185,26 +184,23 @@ export class WinModal extends LitElement implements Layer {
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
const winUpdates = updates !== null ? updates[GameUpdateType.Win] : [];
|
||||
winUpdates.forEach((wu) => {
|
||||
if (wu.winnerType === "team") {
|
||||
this.eventBus.emit(
|
||||
new SendWinnerEvent(wu.winner as Team, wu.allPlayersStats, "team"),
|
||||
);
|
||||
if (wu.winner === this.game.myPlayer()?.team()) {
|
||||
if (wu.winner[0] === "team") {
|
||||
this.eventBus.emit(new SendWinnerEvent(wu.winner, wu.allPlayersStats));
|
||||
if (wu.winner[1] === this.game.myPlayer()?.team()) {
|
||||
this._title = translateText("win_modal.your_team");
|
||||
} else {
|
||||
this._title = translateText("win_modal.other_team", {
|
||||
team: wu.winner,
|
||||
team: wu.winner[1],
|
||||
});
|
||||
}
|
||||
this.show();
|
||||
} else {
|
||||
const winner = this.game.playerBySmallID(
|
||||
wu.winner as number,
|
||||
) as PlayerView;
|
||||
const winner = this.game.playerBySmallID(wu.winner[1]);
|
||||
if (!winner.isPlayer()) return;
|
||||
const winnerClient = winner.clientID();
|
||||
if (winnerClient !== null) {
|
||||
this.eventBus.emit(
|
||||
new SendWinnerEvent(winnerClient, wu.allPlayersStats, "player"),
|
||||
new SendWinnerEvent(["player", winnerClient], wu.allPlayersStats),
|
||||
);
|
||||
}
|
||||
if (
|
||||
|
||||
+10
-4
@@ -391,11 +391,18 @@ export const ServerMessageSchema = z.union([
|
||||
|
||||
// Client
|
||||
|
||||
export const WinnerSchema = z
|
||||
.union([
|
||||
z.tuple([z.literal("player"), ID]),
|
||||
z.tuple([z.literal("team"), SafeString]),
|
||||
])
|
||||
.optional();
|
||||
export type Winner = z.infer<typeof WinnerSchema>;
|
||||
|
||||
export const ClientSendWinnerSchema = z.object({
|
||||
type: z.literal("winner"),
|
||||
winner: z.union([ID, TeamSchema]).nullable(),
|
||||
winner: WinnerSchema,
|
||||
allPlayersStats: AllPlayersStatsSchema,
|
||||
winnerType: z.enum(["player", "team"]),
|
||||
});
|
||||
|
||||
export const ClientHashSchema = z.object({
|
||||
@@ -451,8 +458,7 @@ export const GameEndInfoSchema = GameStartInfoSchema.extend({
|
||||
end: z.number(),
|
||||
duration: z.number().nonnegative(),
|
||||
num_turns: z.number(),
|
||||
winner: z.union([ID, SafeString]).nullable().optional(),
|
||||
winnerType: z.enum(["player", "team"]).nullable().optional(),
|
||||
winner: WinnerSchema,
|
||||
});
|
||||
export type GameEndInfo = z.infer<typeof GameEndInfoSchema>;
|
||||
|
||||
|
||||
+3
-5
@@ -1,15 +1,15 @@
|
||||
import DOMPurify from "dompurify";
|
||||
import { customAlphabet } from "nanoid";
|
||||
import twemoji from "twemoji";
|
||||
import { Cell, Team, Unit } from "./game/Game";
|
||||
import { Cell, Unit } from "./game/Game";
|
||||
import { GameMap, TileRef } from "./game/GameMap";
|
||||
import {
|
||||
ClientID,
|
||||
GameConfig,
|
||||
GameID,
|
||||
GameRecord,
|
||||
PlayerRecord,
|
||||
Turn,
|
||||
Winner,
|
||||
} from "./Schemas";
|
||||
|
||||
import {
|
||||
@@ -191,8 +191,7 @@ export function createGameRecord(
|
||||
allTurns: Turn[],
|
||||
start: number,
|
||||
end: number,
|
||||
winner: ClientID | Team | null,
|
||||
winnerType: "player" | "team" | null,
|
||||
winner: Winner,
|
||||
): GameRecord {
|
||||
const duration = Math.floor((end - start) / 1000);
|
||||
const version = "v0.0.2";
|
||||
@@ -211,7 +210,6 @@ export function createGameRecord(
|
||||
duration,
|
||||
num_turns,
|
||||
winner,
|
||||
winnerType,
|
||||
},
|
||||
version,
|
||||
gitCommit,
|
||||
|
||||
@@ -594,8 +594,10 @@ export class GameImpl implements Game {
|
||||
setWinner(winner: Player | Team, allPlayersStats: AllPlayersStats): void {
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Win,
|
||||
winner: typeof winner === "string" ? winner : winner.smallID(),
|
||||
winnerType: typeof winner === "string" ? "team" : "player",
|
||||
winner:
|
||||
typeof winner === "string"
|
||||
? ["team", winner]
|
||||
: ["player", winner.smallID()],
|
||||
allPlayersStats,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -178,8 +178,7 @@ export interface WinUpdate {
|
||||
type: GameUpdateType.Win;
|
||||
allPlayersStats: AllPlayersStats;
|
||||
// Player id or team name.
|
||||
winner: number | Team;
|
||||
winnerType: "player" | "team";
|
||||
winner: ["player", number] | ["team", Team];
|
||||
}
|
||||
|
||||
export interface HashUpdate {
|
||||
|
||||
@@ -562,8 +562,7 @@ export class GameServer {
|
||||
this.turns,
|
||||
this._startTime ?? 0,
|
||||
Date.now(),
|
||||
this.winner?.winner ?? null,
|
||||
this.winner?.winnerType ?? null,
|
||||
this.winner?.winner,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user