Merge branch 'feature/game-achievements' of github.com:hydralauncher/hydra into feature/cloud-sync

This commit is contained in:
Chubby Granny Chaser
2024-10-20 18:16:02 +01:00
26 changed files with 599 additions and 436 deletions

View File

@@ -51,7 +51,7 @@ const getAchievementLocalUser = async (shop: string, objectId: string) => {
...achievementData,
unlocked: false,
unlockTime: null,
icon: icongray,
icongray: icongray,
} as UserAchievement;
})
.sort((a, b) => {
@@ -110,7 +110,7 @@ const getAchievementsRemoteUser = async (
...achievementData,
unlocked: false,
unlockTime: null,
icon: icongray,
icongray: icongray,
} as UserAchievement;
})
.sort((a, b) => {

View File

@@ -50,6 +50,7 @@ import "./user/unblock-user";
import "./user/get-user-friends";
import "./user/get-user-stats";
import "./user/report-user";
import "./user/get-compared-unlocked-achievements";
import "./profile/get-friend-requests";
import "./profile/get-me";
import "./profile/undo-friendship";

View File

@@ -0,0 +1,44 @@
import type { ComparedAchievements, GameShop } from "@types";
import { registerEvent } from "../register-event";
import { userPreferencesRepository } from "@main/repository";
import { HydraApi } from "@main/services";
const getComparedUnlockedAchievements = async (
_event: Electron.IpcMainInvokeEvent,
objectId: string,
shop: GameShop,
userId: string
) => {
const userPreferences = await userPreferencesRepository.findOne({
where: { id: 1 },
});
return HydraApi.get<ComparedAchievements>(
`/users/${userId}/games/achievements/compare`,
{
shop,
objectId,
language: userPreferences?.language || "en",
}
).then((achievements) => {
const sortedAchievements = achievements.achievements.sort((a, b) => {
if (a.otherUserStat.unlocked && !b.otherUserStat.unlocked) return -1;
if (!a.otherUserStat.unlocked && b.otherUserStat.unlocked) return 1;
if (a.otherUserStat.unlocked && b.otherUserStat.unlocked) {
return b.otherUserStat.unlockTime! - a.otherUserStat.unlockTime!;
}
return Number(a.hidden) - Number(b.hidden);
});
return {
...achievements,
achievements: sortedAchievements,
} as ComparedAchievements;
});
};
registerEvent(
"getComparedUnlockedAchievements",
getComparedUnlockedAchievements
);

View File

@@ -9,7 +9,7 @@ import {
getAlternativeObjectIds,
} from "./find-achivement-files";
import type { AchievementFile } from "@types";
import { achievementsLogger, logger } from "../logger";
import { achievementsLogger } from "../logger";
import { Cracker } from "@shared";
const fileStats: Map<string, number> = new Map();
@@ -55,8 +55,6 @@ const processAchievementFileDiff = async (
) => {
const unlockedAchievements = parseAchievementFile(file.filePath, file.type);
logger.log("Achievements from file", file.filePath, unlockedAchievements);
if (unlockedAchievements.length) {
return mergeAchievements(
game.objectID,
@@ -80,7 +78,7 @@ const compareFltFolder = async (game: Game, file: AchievementFile) => {
return;
}
logger.log("Detected change in FLT folder", file.filePath);
achievementsLogger.log("Detected change in FLT folder", file.filePath);
await processAchievementFileDiff(game, file);
} catch (err) {
achievementsLogger.error(err);
@@ -101,6 +99,13 @@ const compareFile = async (game: Game, file: AchievementFile) => {
if (!previousStat) {
if (currentStat.mtimeMs) {
achievementsLogger.log(
"First change in file",
file.filePath,
previousStat,
currentStat.mtimeMs
);
await processAchievementFileDiff(game, file);
return;
}
@@ -110,7 +115,7 @@ const compareFile = async (game: Game, file: AchievementFile) => {
return;
}
logger.log(
achievementsLogger.log(
"Detected change in file",
file.filePath,
previousStat,

View File

@@ -42,7 +42,9 @@ export const getGameAchievementData = async (
where: { objectId, shop },
})
.then((gameAchievements) => {
return JSON.parse(gameAchievements?.achievements || "[]");
return JSON.parse(
gameAchievements?.achievements || "[]"
) as AchievementData[];
});
});
};

View File

@@ -64,7 +64,13 @@ export const mergeAchievements = async (
localGameAchievement?.unlockedAchievements || "[]"
).filter((achievement) => achievement.name) as UnlockedAchievement[];
const newAchievements = achievements
const newAchievementsMap = new Map(
achievements.reverse().map((achievement) => {
return [achievement.name.toUpperCase(), achievement];
})
);
const newAchievements = [...newAchievementsMap.values()]
.filter((achievement) => {
return !unlockedAchievements.some((localAchievement) => {
return (
@@ -114,7 +120,7 @@ export const mergeAchievements = async (
const mergedLocalAchievements = unlockedAchievements.concat(newAchievements);
if (game?.remoteId) {
if (game.remoteId) {
return HydraApi.put(
"/profile/games/achievements",
{

View File

@@ -242,15 +242,23 @@ const processRld = (unlockedAchievements: any): UnlockedAchievement[] => {
const unlockedAchievement = unlockedAchievements[achievement];
if (unlockedAchievement?.State) {
newUnlockedAchievements.push({
name: achievement,
unlockTime:
new DataView(
new Uint8Array(
Buffer.from(unlockedAchievement.Time.toString(), "hex")
).buffer
).getUint32(0, true) * 1000,
});
const unlocked = new DataView(
new Uint8Array(
Buffer.from(unlockedAchievement.State.toString(), "hex")
).buffer
).getUint32(0, true);
if (unlocked === 1) {
newUnlockedAchievements.push({
name: achievement,
unlockTime:
new DataView(
new Uint8Array(
Buffer.from(unlockedAchievement.Time.toString(), "hex")
).buffer
).getUint32(0, true) * 1000,
});
}
}
}

View File

@@ -49,14 +49,14 @@ export const updateAllLocalUnlockedAchievements = async () => {
if (parsedAchievements.length) {
unlockedAchievements.push(...parsedAchievements);
}
achievementsLogger.log(
"Achievement file for",
game.title,
achievementFile.filePath,
parsedAchievements
);
achievementsLogger.log(
"Achievement file for",
game.title,
achievementFile.filePath,
parsedAchievements
);
}
}
mergeAchievements(game.objectID, "steam", unlockedAchievements, false);

View File

@@ -80,6 +80,10 @@ export class WindowManager {
this.mainWindow.webContents.session.webRequest.onBeforeSendHeaders(
(details, callback) => {
if (details.webContentsId !== this.mainWindow?.webContents.id) {
return callback(details);
}
const userAgent = new UserAgent();
callback({