Merge branch 'main' into patterned-territory

This commit is contained in:
Aotumuri
2025-05-23 07:59:39 +09:00
committed by GitHub
25 changed files with 193 additions and 116 deletions
+18 -34
View File
@@ -1,6 +1,6 @@
import { S3 } from "@aws-sdk/client-s3";
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
import { GameID, GameRecord } from "../core/Schemas";
import { AnalyticsRecord, GameID, GameRecord } from "../core/Schemas";
import { logger } from "./Logger";
const config = getServerConfigFromServer();
@@ -30,12 +30,12 @@ export async function archive(gameRecord: GameRecord) {
// Archive full game if there are turns
if (gameRecord.turns.length > 0) {
log.info(
`${gameRecord.id}: game has more than zero turns, attempting to write to full game to R2`,
`${gameRecord.info.gameID}: game has more than zero turns, attempting to write to full game to R2`,
);
await archiveFullGameToR2(gameRecord);
}
} catch (error) {
log.error(`${gameRecord.id}: Final archive error: ${error}`, {
log.error(`${gameRecord.info.gameID}: Final archive error: ${error}`, {
message: error?.message || error,
stack: error?.stack,
name: error?.name,
@@ -46,29 +46,16 @@ export async function archive(gameRecord: GameRecord) {
async function archiveAnalyticsToR2(gameRecord: GameRecord) {
// Create analytics data object
const analyticsData = {
id: gameRecord.id,
env: config.env(),
start_time: new Date(gameRecord.startTimestampMS).toISOString(),
end_time: new Date(gameRecord.endTimestampMS).toISOString(),
duration_seconds: gameRecord.durationSeconds,
number_turns: gameRecord.num_turns,
game_mode: gameRecord.gameStartInfo.config.gameType,
winner: gameRecord.winner,
difficulty: gameRecord.gameStartInfo.config.difficulty,
mapType: gameRecord.gameStartInfo.config.gameMap,
players: gameRecord.players.map((p) => ({
username: p.username,
ip: p.ip,
persistentID: p.persistentID,
clientID: p.clientID,
stats: p.stats,
})),
const { info, version, gitCommit } = gameRecord;
const analyticsData: AnalyticsRecord = {
info,
version,
gitCommit,
};
try {
// Store analytics data using just the game ID as the key
const analyticsKey = `${gameRecord.id}.json`;
const analyticsKey = `${info.gameID}.json`;
await r2.putObject({
Bucket: bucket,
@@ -77,17 +64,14 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) {
ContentType: "application/json",
});
log.info(`${gameRecord.id}: successfully wrote game analytics to R2`);
log.info(`${info.gameID}: successfully wrote game analytics to R2`);
} catch (error) {
log.error(
`${gameRecord.id}: Error writing game analytics to R2: ${error}`,
{
message: error?.message || error,
stack: error?.stack,
name: error?.name,
...(error && typeof error === "object" ? error : {}),
},
);
log.error(`${info.gameID}: Error writing game analytics to R2: ${error}`, {
message: error?.message || error,
stack: error?.stack,
name: error?.name,
...(error && typeof error === "object" ? error : {}),
});
throw error;
}
}
@@ -110,11 +94,11 @@ async function archiveFullGameToR2(gameRecord: GameRecord) {
ContentType: "application/json",
});
} catch (error) {
log.error(`error saving game ${gameRecord.id}`);
log.error(`error saving game ${gameRecord.info.gameID}`);
throw error;
}
log.info(`${gameRecord.id}: game record successfully written to R2`);
log.info(`${gameRecord.info.gameID}: game record successfully written to R2`);
}
export async function readGameRecord(
+2 -2
View File
@@ -394,7 +394,7 @@ export class GameServer {
);
}
return {
ip: ipAnonymize(client.ip),
playerID: client.playerID,
clientID: client.clientID,
username: client.username,
persistentID: client.persistentID,
@@ -404,7 +404,7 @@ export class GameServer {
archive(
createGameRecord(
this.id,
this.gameStartInfo,
this.gameStartInfo.config,
playerRecords,
this.turns,
this._startTime ?? 0,
-2
View File
@@ -242,14 +242,12 @@ export function startWorker() {
"/api/archive_singleplayer_game",
gatekeeper.httpHandler(LimiterType.Post, async (req, res) => {
const gameRecord: GameRecord = req.body;
const clientIP = req.ip || req.socket.remoteAddress || "unknown";
if (!gameRecord) {
log.info("game record not found in request");
res.status(404).json({ error: "Game record not found" });
return;
}
gameRecord.players.forEach((p) => (p.ip = clientIP));
archive(gameRecord);
res.json({
success: true,