Merge pull request #1094 from hydralauncher/feat/refactor-achievements-files

feat: refactor achievements file
This commit is contained in:
Zamitto 2024-10-23 21:52:27 -03:00 committed by GitHub
commit 7d79048a25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 69 additions and 35 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "hydralauncher", "name": "hydralauncher",
"version": "3.0.1", "version": "3.0.2",
"description": "Hydra", "description": "Hydra",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "Los Broxas", "author": "Los Broxas",

View File

@ -242,10 +242,18 @@ export class AchievementWatcherManager {
? await this.preSearchAchievementsWindows() ? await this.preSearchAchievementsWindows()
: await this.preSearchAchievementsWithWine(); : await this.preSearchAchievementsWithWine();
const totalNewGamesWithAchievements = newAchievementsCount.filter(
(achievements) => achievements
).length;
const totalNewAchievements = newAchievementsCount.reduce(
(acc, val) => acc + val,
0
);
WindowManager.notificationWindow?.webContents.send( WindowManager.notificationWindow?.webContents.send(
"on-combined-achievements-unlocked", "on-combined-achievements-unlocked",
newAchievementsCount.filter((achievements) => achievements).length, totalNewGamesWithAchievements,
newAchievementsCount.reduce((acc, val) => acc + val, 0) totalNewAchievements
); );
this.hasFinishedMergingWithRemote = true; this.hasFinishedMergingWithRemote = true;

View File

@ -79,11 +79,11 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(publicDocuments, "Steam", "CODEX"), folderPath: path.join(publicDocuments, "Steam", "CODEX"),
fileLocation: ["achievements.ini"], fileLocation: ["<objectId>", "achievements.ini"],
}, },
{ {
folderPath: path.join(appData, "Steam", "CODEX"), folderPath: path.join(appData, "Steam", "CODEX"),
fileLocation: ["achievements.ini"], fileLocation: ["<objectId>", "achievements.ini"],
}, },
]; ];
} }
@ -92,7 +92,7 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(publicDocuments, "Steam", "RUNE"), folderPath: path.join(publicDocuments, "Steam", "RUNE"),
fileLocation: ["achievements.ini"], fileLocation: ["<objectId>", "achievements.ini"],
}, },
]; ];
} }
@ -101,11 +101,11 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(publicDocuments, "OnlineFix"), folderPath: path.join(publicDocuments, "OnlineFix"),
fileLocation: ["Stats", "Achievements.ini"], fileLocation: ["<objectId>", "Stats", "Achievements.ini"],
}, },
{ {
folderPath: path.join(publicDocuments, "OnlineFix"), folderPath: path.join(publicDocuments, "OnlineFix"),
fileLocation: ["Achievements.ini"], fileLocation: ["<objectId>", "Achievements.ini"],
}, },
]; ];
} }
@ -114,11 +114,11 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(appData, "Goldberg SteamEmu Saves"), folderPath: path.join(appData, "Goldberg SteamEmu Saves"),
fileLocation: ["achievements.json"], fileLocation: ["<objectId>", "achievements.json"],
}, },
{ {
folderPath: path.join(appData, "GSE Saves"), folderPath: path.join(appData, "GSE Saves"),
fileLocation: ["achievements.json"], fileLocation: ["<objectId>", "achievements.json"],
}, },
]; ];
} }
@ -131,19 +131,19 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(programData, "RLD!"), folderPath: path.join(programData, "RLD!"),
fileLocation: ["achievements.ini"], fileLocation: ["<objectId>", "achievements.ini"],
}, },
{ {
folderPath: path.join(programData, "Steam", "Player"), folderPath: path.join(programData, "Steam", "Player"),
fileLocation: ["stats", "achievements.ini"], fileLocation: ["<objectId>", "stats", "achievements.ini"],
}, },
{ {
folderPath: path.join(programData, "Steam", "RLD!"), folderPath: path.join(programData, "Steam", "RLD!"),
fileLocation: ["stats", "achievements.ini"], fileLocation: ["<objectId>", "stats", "achievements.ini"],
}, },
{ {
folderPath: path.join(programData, "Steam", "dodi"), folderPath: path.join(programData, "Steam", "dodi"),
fileLocation: ["stats", "achievements.ini"], fileLocation: ["<objectId>", "stats", "achievements.ini"],
}, },
]; ];
} }
@ -152,11 +152,16 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(appData, "EMPRESS", "remote"), folderPath: path.join(appData, "EMPRESS", "remote"),
fileLocation: ["achievements.json"], fileLocation: ["<objectId>", "achievements.json"],
}, },
{ {
folderPath: path.join(publicDocuments, "EMPRESS", "remote"), folderPath: path.join(publicDocuments, "EMPRESS"),
fileLocation: ["achievements.json"], fileLocation: [
"<objectId>",
"remote",
"<objectId>",
"achievements.json",
],
}, },
]; ];
} }
@ -165,15 +170,15 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(documents, "SKIDROW"), folderPath: path.join(documents, "SKIDROW"),
fileLocation: ["SteamEmu", "UserStats", "achiev.ini"], fileLocation: ["<objectId>", "SteamEmu", "UserStats", "achiev.ini"],
}, },
{ {
folderPath: path.join(documents, "Player"), folderPath: path.join(documents, "Player"),
fileLocation: ["SteamEmu", "UserStats", "achiev.ini"], fileLocation: ["<objectId>", "SteamEmu", "UserStats", "achiev.ini"],
}, },
{ {
folderPath: path.join(localAppData, "SKIDROW"), folderPath: path.join(localAppData, "SKIDROW"),
fileLocation: ["SteamEmu", "UserStats", "achiev.ini"], fileLocation: ["<objectId>", "SteamEmu", "UserStats", "achiev.ini"],
}, },
]; ];
} }
@ -182,7 +187,7 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(appData, "CreamAPI"), folderPath: path.join(appData, "CreamAPI"),
fileLocation: ["stats", "CreamAPI.Achievements.cfg"], fileLocation: ["<objectId>", "stats", "CreamAPI.Achievements.cfg"],
}, },
]; ];
} }
@ -191,7 +196,7 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(appData, "SmartSteamEmu"), folderPath: path.join(appData, "SmartSteamEmu"),
fileLocation: ["User", "Achievements.ini"], fileLocation: ["<objectId>", "User", "Achievements.ini"],
}, },
]; ];
} }
@ -213,11 +218,11 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(appData, "RLE"), folderPath: path.join(appData, "RLE"),
fileLocation: ["achievements.ini"], fileLocation: ["<objectId>", "achievements.ini"],
}, },
{ {
folderPath: path.join(appData, "RLE"), folderPath: path.join(appData, "RLE"),
fileLocation: ["Achievements.ini"], fileLocation: ["<objectId>", "Achievements.ini"],
}, },
]; ];
} }
@ -226,7 +231,7 @@ const getPathFromCracker = (cracker: Cracker) => {
return [ return [
{ {
folderPath: path.join(appData, ".1911"), folderPath: path.join(appData, ".1911"),
fileLocation: ["achievement"], fileLocation: ["<objectId>", "achievement"],
}, },
]; ];
} }
@ -253,8 +258,7 @@ export const findAchievementFiles = (game: Game) => {
const filePath = path.join( const filePath = path.join(
game.winePrefixPath ?? "", game.winePrefixPath ?? "",
folderPath, folderPath,
objectId, ...mapFileLocationWithObjectId(fileLocation, objectId)
...fileLocation
); );
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
@ -303,6 +307,15 @@ export const findAchievementFileInExecutableDirectory = (
]; ];
}; };
const mapFileLocationWithObjectId = (
fileLocation: string[],
objectId: string
) => {
return fileLocation.map((location) =>
location.replace("<objectId>", objectId)
);
};
export const findAllAchievementFiles = () => { export const findAllAchievementFiles = () => {
const gameAchievementFiles = new Map<string, AchievementFile[]>(); const gameAchievementFiles = new Map<string, AchievementFile[]>();
@ -315,7 +328,10 @@ export const findAllAchievementFiles = () => {
const objectIds = fs.readdirSync(folderPath); const objectIds = fs.readdirSync(folderPath);
for (const objectId of objectIds) { for (const objectId of objectIds) {
const filePath = path.join(folderPath, objectId, ...fileLocation); const filePath = path.join(
folderPath,
...mapFileLocationWithObjectId(fileLocation, objectId)
);
if (!fs.existsSync(filePath)) continue; if (!fs.existsSync(filePath)) continue;

View File

@ -65,6 +65,11 @@ export const parseAchievementFile = (
return processCreamAPI(parsed); return processCreamAPI(parsed);
} }
if (type === Cracker.empress) {
const parsed = jsonParse(filePath);
return processGoldberg(parsed);
}
if (type === Cracker.razor1911) { if (type === Cracker.razor1911) {
return processRazor1911(filePath); return processRazor1911(filePath);
} }
@ -118,7 +123,7 @@ const jsonParse = (filePath: string) => {
const processRazor1911 = (filePath: string): UnlockedAchievement[] => { const processRazor1911 = (filePath: string): UnlockedAchievement[] => {
try { try {
const fileContent = readFileSync(filePath, "utf-8"); const fileContent = readFileSync(filePath, "utf-8");
achievementsLogger.log("processing file", filePath, fileContent);
const lines = const lines =
fileContent.charCodeAt(0) === 0xfeff fileContent.charCodeAt(0) === 0xfeff
? fileContent.slice(1).split(/[\r\n]+/) ? fileContent.slice(1).split(/[\r\n]+/)
@ -136,7 +141,7 @@ const processRazor1911 = (filePath: string): UnlockedAchievement[] => {
}); });
} }
} }
achievementsLogger.log("processing file", achievements);
return achievements; return achievements;
} catch (err) { } catch (err) {
achievementsLogger.error(`Error processing ${filePath}`, err); achievementsLogger.error(`Error processing ${filePath}`, err);

View File

@ -77,6 +77,8 @@ export function useDate() {
}, },
formatDate: (date: number | Date | string): string => { formatDate: (date: number | Date | string): string => {
if (isNaN(new Date(date).getDate())) return "N/A";
const locale = getDateLocale(); const locale = getDateLocale();
return format(date, locale == enUS ? "MM/dd/yyyy" : "dd/MM/yyyy"); return format(date, locale == enUS ? "MM/dd/yyyy" : "dd/MM/yyyy");
}, },

View File

@ -18,7 +18,7 @@ export const panel = recipe({
position: "sticky", position: "sticky",
overflow: "hidden", overflow: "hidden",
top: "0", top: "0",
zIndex: "1", zIndex: "2",
}, },
variants: { variants: {
stuck: { stuck: {

View File

@ -1,8 +1,7 @@
import { format } from "date-fns";
import { useContext } from "react"; import { useContext } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useDownload } from "@renderer/hooks"; import { useDate, useDownload } from "@renderer/hooks";
import { HeroPanelActions } from "./hero-panel-actions"; import { HeroPanelActions } from "./hero-panel-actions";
import * as styles from "./hero-panel.css"; import * as styles from "./hero-panel.css";
@ -17,6 +16,8 @@ export interface HeroPanelProps {
export function HeroPanel({ isHeaderStuck }: HeroPanelProps) { export function HeroPanel({ isHeaderStuck }: HeroPanelProps) {
const { t } = useTranslation("game_details"); const { t } = useTranslation("game_details");
const { formatDate } = useDate();
const { game, repacks, gameColor } = useContext(gameDetailsContext); const { game, repacks, gameColor } = useContext(gameDetailsContext);
const { lastPacket } = useDownload(); const { lastPacket } = useDownload();
@ -29,7 +30,9 @@ export function HeroPanel({ isHeaderStuck }: HeroPanelProps) {
const [latestRepack] = repacks; const [latestRepack] = repacks;
if (latestRepack) { if (latestRepack) {
const lastUpdate = format(latestRepack.uploadDate!, "dd/MM/yyyy"); const lastUpdate = latestRepack.uploadDate
? formatDate(latestRepack.uploadDate!)
: "";
const repacksCount = repacks.length; const repacksCount = repacks.length;
return ( return (

View File

@ -126,7 +126,7 @@ export function Sidebar() {
<div <div
style={{ style={{
position: "absolute", position: "absolute",
zIndex: 2, zIndex: 1,
inset: 0, inset: 0,
width: "100%", width: "100%",
height: "100%", height: "100%",