mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-13 11:42:10 +00:00
feat: start watching new achievements only after finishing sync
This commit is contained in:
parent
bb65d77fc6
commit
c6fda9b4d8
4 changed files with 109 additions and 98 deletions
|
@ -1,4 +1,4 @@
|
||||||
import { gameRepository } from "@main/repository";
|
import { gameAchievementRepository, gameRepository } from "@main/repository";
|
||||||
import { parseAchievementFile } from "./parse-achievement-file";
|
import { parseAchievementFile } from "./parse-achievement-file";
|
||||||
import { Game } from "@main/entity";
|
import { Game } from "@main/entity";
|
||||||
import { mergeAchievements } from "./merge-achievements";
|
import { mergeAchievements } from "./merge-achievements";
|
||||||
|
@ -9,10 +9,11 @@ import {
|
||||||
findAllAchievementFiles,
|
findAllAchievementFiles,
|
||||||
getAlternativeObjectIds,
|
getAlternativeObjectIds,
|
||||||
} from "./find-achivement-files";
|
} from "./find-achivement-files";
|
||||||
import type { AchievementFile } from "@types";
|
import type { AchievementFile, UnlockedAchievement } from "@types";
|
||||||
import { achievementsLogger } from "../logger";
|
import { achievementsLogger } from "../logger";
|
||||||
import { Cracker } from "@shared";
|
import { Cracker } from "@shared";
|
||||||
import { IsNull, Not } from "typeorm";
|
import { IsNull, Not } from "typeorm";
|
||||||
|
import { getGameAchievementData } from "./get-game-achievement-data";
|
||||||
|
|
||||||
const fileStats: Map<string, number> = new Map();
|
const fileStats: Map<string, number> = new Map();
|
||||||
const fltFiles: Map<string, Set<string>> = new Map();
|
const fltFiles: Map<string, Set<string>> = new Map();
|
||||||
|
@ -72,30 +73,6 @@ const watchAchievementsWithWine = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const watchAchievements = async () => {
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
return watchAchievementsWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
watchAchievementsWithWine();
|
|
||||||
};
|
|
||||||
|
|
||||||
const processAchievementFileDiff = async (
|
|
||||||
game: Game,
|
|
||||||
file: AchievementFile
|
|
||||||
) => {
|
|
||||||
const unlockedAchievements = parseAchievementFile(file.filePath, file.type);
|
|
||||||
|
|
||||||
if (unlockedAchievements.length) {
|
|
||||||
return mergeAchievements(
|
|
||||||
game.objectID,
|
|
||||||
game.shop,
|
|
||||||
unlockedAchievements,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const compareFltFolder = async (game: Game, file: AchievementFile) => {
|
const compareFltFolder = async (game: Game, file: AchievementFile) => {
|
||||||
try {
|
try {
|
||||||
const currentAchievements = new Set(readdirSync(file.filePath));
|
const currentAchievements = new Set(readdirSync(file.filePath));
|
||||||
|
@ -156,3 +133,104 @@ const compareFile = (game: Game, file: AchievementFile) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const processAchievementFileDiff = async (
|
||||||
|
game: Game,
|
||||||
|
file: AchievementFile
|
||||||
|
) => {
|
||||||
|
const unlockedAchievements = parseAchievementFile(file.filePath, file.type);
|
||||||
|
|
||||||
|
if (unlockedAchievements.length) {
|
||||||
|
return mergeAchievements(
|
||||||
|
game.objectID,
|
||||||
|
game.shop,
|
||||||
|
unlockedAchievements,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export class AchievementWatcherManager {
|
||||||
|
private static hasFinishedMergingWithRemote = false;
|
||||||
|
|
||||||
|
public static watchAchievements = async () => {
|
||||||
|
if (!this.hasFinishedMergingWithRemote) return;
|
||||||
|
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
return watchAchievementsWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
watchAchievementsWithWine();
|
||||||
|
};
|
||||||
|
|
||||||
|
public static preSearchAchievements = async () => {
|
||||||
|
const games = await gameRepository.find({
|
||||||
|
where: {
|
||||||
|
isDeleted: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const gameAchievementFilesMap = findAllAchievementFiles();
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
games.map(async (game) => {
|
||||||
|
gameAchievementRepository
|
||||||
|
.findOne({
|
||||||
|
where: { objectId: game.objectID, shop: "steam" },
|
||||||
|
})
|
||||||
|
.then((localAchievements) => {
|
||||||
|
if (!localAchievements || !localAchievements.achievements) {
|
||||||
|
getGameAchievementData(game.objectID, "steam");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const gameAchievementFiles: AchievementFile[] = [];
|
||||||
|
const unlockedAchievements: UnlockedAchievement[] = [];
|
||||||
|
|
||||||
|
for (const objectId of getAlternativeObjectIds(game.objectID)) {
|
||||||
|
gameAchievementFiles.push(
|
||||||
|
...(gameAchievementFilesMap.get(objectId) || [])
|
||||||
|
);
|
||||||
|
|
||||||
|
gameAchievementFiles.push(
|
||||||
|
...findAchievementFileInExecutableDirectory(game)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const achievementFile of gameAchievementFiles) {
|
||||||
|
const parsedAchievements = parseAchievementFile(
|
||||||
|
achievementFile.filePath,
|
||||||
|
achievementFile.type
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const currentStat = fs.statSync(achievementFile.filePath);
|
||||||
|
fileStats.set(achievementFile.filePath, currentStat.mtimeMs);
|
||||||
|
} catch {
|
||||||
|
fileStats.set(achievementFile.filePath, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedAchievements.length) {
|
||||||
|
unlockedAchievements.push(...parsedAchievements);
|
||||||
|
|
||||||
|
achievementsLogger.log(
|
||||||
|
"Achievement file for",
|
||||||
|
game.title,
|
||||||
|
achievementFile.filePath,
|
||||||
|
parsedAchievements
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await mergeAchievements(
|
||||||
|
game.objectID,
|
||||||
|
"steam",
|
||||||
|
unlockedAchievements,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this.hasFinishedMergingWithRemote = true;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,79 +1,12 @@
|
||||||
import { gameAchievementRepository, gameRepository } from "@main/repository";
|
|
||||||
import {
|
import {
|
||||||
findAllAchievementFiles,
|
|
||||||
findAchievementFiles,
|
findAchievementFiles,
|
||||||
findAchievementFileInExecutableDirectory,
|
findAchievementFileInExecutableDirectory,
|
||||||
getAlternativeObjectIds,
|
|
||||||
} from "./find-achivement-files";
|
} from "./find-achivement-files";
|
||||||
import { parseAchievementFile } from "./parse-achievement-file";
|
import { parseAchievementFile } from "./parse-achievement-file";
|
||||||
import { mergeAchievements } from "./merge-achievements";
|
import { mergeAchievements } from "./merge-achievements";
|
||||||
import type { AchievementFile, UnlockedAchievement } from "@types";
|
import type { UnlockedAchievement } from "@types";
|
||||||
import { getGameAchievementData } from "./get-game-achievement-data";
|
|
||||||
import { achievementsLogger } from "../logger";
|
|
||||||
import { Game } from "@main/entity";
|
import { Game } from "@main/entity";
|
||||||
|
|
||||||
export const updateAllLocalUnlockedAchievements = async () => {
|
|
||||||
const games = await gameRepository.find({
|
|
||||||
where: {
|
|
||||||
isDeleted: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (games.length === 0) return;
|
|
||||||
|
|
||||||
const gameAchievementFilesMap = findAllAchievementFiles();
|
|
||||||
|
|
||||||
for (const game of games) {
|
|
||||||
gameAchievementRepository
|
|
||||||
.findOne({
|
|
||||||
where: { objectId: game.objectID, shop: "steam" },
|
|
||||||
})
|
|
||||||
.then((localAchievements) => {
|
|
||||||
if (!localAchievements || !localAchievements.achievements) {
|
|
||||||
getGameAchievementData(game.objectID, "steam");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const gameAchievementFiles: AchievementFile[] = [];
|
|
||||||
const unlockedAchievements: UnlockedAchievement[] = [];
|
|
||||||
|
|
||||||
for (const objectId of getAlternativeObjectIds(game.objectID)) {
|
|
||||||
gameAchievementFiles.push(
|
|
||||||
...(gameAchievementFilesMap.get(objectId) || [])
|
|
||||||
);
|
|
||||||
|
|
||||||
gameAchievementFiles.push(
|
|
||||||
...findAchievementFileInExecutableDirectory(game)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const achievementFile of gameAchievementFiles) {
|
|
||||||
const parsedAchievements = parseAchievementFile(
|
|
||||||
achievementFile.filePath,
|
|
||||||
achievementFile.type
|
|
||||||
);
|
|
||||||
|
|
||||||
if (parsedAchievements.length) {
|
|
||||||
unlockedAchievements.push(...parsedAchievements);
|
|
||||||
|
|
||||||
achievementsLogger.log(
|
|
||||||
"Achievement file for",
|
|
||||||
game.title,
|
|
||||||
achievementFile.filePath,
|
|
||||||
parsedAchievements
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await mergeAchievements(
|
|
||||||
game.objectID,
|
|
||||||
"steam",
|
|
||||||
unlockedAchievements,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateLocalUnlockedAchivements = async (game: Game) => {
|
export const updateLocalUnlockedAchivements = async (game: Game) => {
|
||||||
const gameAchievementFiles = findAchievementFiles(game);
|
const gameAchievementFiles = findAchievementFiles(game);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { IsNull } from "typeorm";
|
||||||
import { HydraApi } from "../hydra-api";
|
import { HydraApi } from "../hydra-api";
|
||||||
import { mergeWithRemoteGames } from "./merge-with-remote-games";
|
import { mergeWithRemoteGames } from "./merge-with-remote-games";
|
||||||
import { WindowManager } from "../window-manager";
|
import { WindowManager } from "../window-manager";
|
||||||
import { updateAllLocalUnlockedAchievements } from "../achievements/update-local-unlocked-achivements";
|
import { AchievementWatcherManager } from "../achievements/AchievementWatcherManager";
|
||||||
|
|
||||||
export const uploadGamesBatch = async () => {
|
export const uploadGamesBatch = async () => {
|
||||||
const games = await gameRepository.find({
|
const games = await gameRepository.find({
|
||||||
|
@ -29,7 +29,7 @@ export const uploadGamesBatch = async () => {
|
||||||
|
|
||||||
await mergeWithRemoteGames();
|
await mergeWithRemoteGames();
|
||||||
|
|
||||||
await updateAllLocalUnlockedAchievements();
|
await AchievementWatcherManager.preSearchAchievements();
|
||||||
|
|
||||||
if (WindowManager.mainWindow)
|
if (WindowManager.mainWindow)
|
||||||
WindowManager.mainWindow.webContents.send("on-library-batch-complete");
|
WindowManager.mainWindow.webContents.send("on-library-batch-complete");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { sleep } from "@main/helpers";
|
import { sleep } from "@main/helpers";
|
||||||
import { DownloadManager } from "./download";
|
import { DownloadManager } from "./download";
|
||||||
import { watchProcesses } from "./process-watcher";
|
import { watchProcesses } from "./process-watcher";
|
||||||
import { watchAchievements } from "./achievements/achievement-watcher";
|
import { AchievementWatcherManager } from "./achievements/AchievementWatcherManager";
|
||||||
|
|
||||||
export const startMainLoop = async () => {
|
export const startMainLoop = async () => {
|
||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
@ -9,7 +9,7 @@ export const startMainLoop = async () => {
|
||||||
await Promise.allSettled([
|
await Promise.allSettled([
|
||||||
watchProcesses(),
|
watchProcesses(),
|
||||||
DownloadManager.watchDownloads(),
|
DownloadManager.watchDownloads(),
|
||||||
watchAchievements(),
|
AchievementWatcherManager.watchAchievements(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await sleep(1500);
|
await sleep(1500);
|
||||||
|
|
Loading…
Reference in a new issue