Merge branch 'master' into bugfix/leaderboard-filtering

This commit is contained in:
MathieuG-P
2024-12-27 21:17:43 +01:00
committed by GitHub
163 changed files with 6474 additions and 2564 deletions
+1
View File
@@ -17,6 +17,7 @@ export interface BSVersion extends PartialBSVersion {
color?: string; // TODO : Should be in metadata
OculusBinaryId?: string;
metadata?: BSVersionMetadata;
path?: string;
recommended?: boolean;
}
+3 -3
View File
@@ -12,8 +12,8 @@ export function isOculusTokenValid(token: string, logger?: (...args: unknown[])
logger?.("Token contains %. Token most likely comes from an uri and won't work");
return false;
}
if(!token.startsWith("FRL")){
logger?.("Tokens must start with 'FRL'.");
if(!token.startsWith("FRL") && !token.startsWith("OC") ){
logger?.("Tokens must start with 'FRL' or 'OC'.");
return false;
}
if(token.includes("|")){
@@ -33,4 +33,4 @@ export function isOculusTokenValid(token: string, logger?: (...args: unknown[])
return true;
}
}
+8
View File
@@ -0,0 +1,8 @@
import { coerce, lt, valid } from "semver";
import { tryit } from "./error.helpers";
export function safeLt(a: string, b: string): boolean {
const { result } = tryit(() => lt(valid(coerce(a)), valid(coerce(b))));
return result ?? false;
}
+5
View File
@@ -11,3 +11,8 @@ export function findHashInString(str: string, algorithm: keyof typeof HashAlgori
const match = regex.exec(str);
return match ? match[0] : undefined;
}
export function escapeRegExp(str: string): string {
// Regex taken from lodash escapeRegExp function
return str.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&');
}
@@ -15,12 +15,15 @@ export enum BSLaunchError{
BS_EXIT_ERROR = "EXIT",
OCULUS_LIB_NOT_FOUND = "OCULUS_LIB_NOT_FOUND",
PROTON_NOT_SET = "PROTON_NOT_SET",
PROTON_NOT_FOUND = "PROTON_NOT_FOUND",
UNKNOWN_ERROR = "UNKNOWN_ERROR",
ORIGINAL_OCULUS_NOT_INSTALLED = "ORIGINAL_OCULUS_NOT_INSTALLED"
}
export enum BSLaunchEvent{
STEAM_LAUNCHING = "STEAM_LAUNCHING",
STEAM_LAUNCHED = "STEAM_LAUNCHED",
SKIPPING_STEAM_LAUNCH = "SKIPPING_STEAM_LAUNCH",
BS_LAUNCHING = "BS_LAUNCHING",
}
@@ -1,11 +1,19 @@
import { BSVersion } from "shared/bs-version.interface";
export const LaunchMods = {
OCULUS: "oculus",
FPFC: "fpfc",
DEBUG: "debug",
SKIP_STEAM: "skip_steam",
EDITOR: "editor",
PROTON_LOGS: "proton_logs",
} as const;
export type LaunchMod = typeof LaunchMods[keyof typeof LaunchMods];
export interface LaunchOption {
version: BSVersion,
oculus?: boolean,
desktop?: boolean,
debug?: boolean,
launchMods?: LaunchMod[],
additionalArgs?: string[],
admin?: boolean,
protonPath?: string,
admin?: boolean
}
@@ -2,7 +2,6 @@ export enum DepotDownloaderEventType {
Error = "Error",
Warning = "Warning",
Info = "Info",
}
export interface DepotDownloaderEvent<T = unknown> {
@@ -27,6 +26,8 @@ export enum DepotDownloaderInfoEvent {
}
export enum DepotDownloaderErrorEvent {
ExeNotFoundWindows = "ExeNotFoundWindows",
ExeNotFoundLinux = "ExeNotFoundLinux",
Password = "Password",
InvalidCredentials = "InvalidCredentials",
NoManifest = "NoManifest",
@@ -66,4 +67,4 @@ export interface DepotDownloaderArgsOptions {
dir: string,
validate?: boolean,
qr?: boolean,
}
}
+18 -8
View File
@@ -6,7 +6,7 @@ import { BsvMapDetail, SongDetails } from "shared/models/maps";
import { BsmLocalMap, BsmLocalMapsProgress, DeleteMapsProgress } from "shared/models/maps/bsm-local-map.interface";
import { BsvPlaylist, BsvPlaylistPage, PlaylistSearchParams, SearchParams } from "../maps/beat-saver.model";
import { ImportVersionOptions } from "main/services/bs-local-version.service";
import { DownloadInfo, DownloadSteamInfo } from "main/services/bs-version-download/bs-steam-downloader.service";
import { DownloadSteamInfo } from "main/services/bs-version-download/bs-steam-downloader.service";
import { DepotDownloaderEvent } from "../bs-version-download/depot-downloader.model";
import { MSGetQuery, MSModel, MSModelType } from "../models/model-saber.model";
import { ModelDownload } from "renderer/services/models-management/models-downloader.service";
@@ -20,6 +20,8 @@ import { Supporter } from "../supporters";
import { AppWindow } from "../window-manager/app-window.model";
import { LocalBPList, LocalBPListsDetails } from "../playlists/local-playlist.models";
import { StaticConfigGetIpcRequestResponse, StaticConfigKeys, StaticConfigSetIpcRequest } from "main/services/static-configuration.service";
import { ExternalMod } from "../mods/mod.interface";
import { OculusDownloadInfo } from "main/services/bs-version-download/bs-oculus-downloader.service";
export type IpcReplier<T> = (data: Observable<T>) => void;
@@ -32,8 +34,11 @@ export interface IpcChannelMapping {
"download-bs-version-qr": { request: DownloadSteamInfo, response: DepotDownloaderEvent};
"stop-download-bs-version": { request: void, response: void};
"send-input-bs-download": { request: string, response: boolean};
"bs-oculus-download": { request: DownloadInfo, response: Progression<BSVersion>};
"bs-oculus-download": { request: OculusDownloadInfo, response: Progression<BSVersion>};
"bs-oculus-stop-download": { request: void, response: void};
"login-with-meta": { request: boolean, response: string };
"delete-meta-session": { request: void, response: void };
"meta-session-exists": { request: void, response: boolean };
/* ** beat-saver-ipcs ** */
"bsv-search-map": {request: SearchParams, response: BsvMapDetail[]};
@@ -78,11 +83,12 @@ export interface IpcChannelMapping {
"delete-models": { request: BsmLocalModel[], response: Progression<BsmLocalModel[]> };
/* ** bs-mods-ipcs ** */
"get-available-mods": { request: BSVersion, response: Mod[] };
"get-installed-mods": { request: BSVersion, response: Mod[] };
"install-mods": { request: { mods: Mod[]; version: BSVersion }, response: Progression };
"uninstall-mods": { request: { mods: Mod[]; version: BSVersion }, response: Progression };
"uninstall-all-mods": { request: BSVersion, response: Progression };
"bs-mods.get-available-mods": { request: BSVersion, response: Mod[] };
"bs-mods.get-installed-mods": { request: BSVersion, response: Mod[] };
"bs-mods.import-mods": { request: { paths: string[]; version: BSVersion; }, response: Progression<ExternalMod> };
"bs-mods.install-mods": { request: { mods: Mod[]; version: BSVersion }, response: Progression };
"bs-mods.uninstall-mods": { request: { mods: Mod[]; version: BSVersion }, response: Progression };
"bs-mods.uninstall-all-mods": { request: BSVersion, response: Progression };
/* ** bs-playlist-ipcs ** */
"one-click-install-playlist": { request: string, response: Progression<DownloadPlaylistProgressionData> };
@@ -111,6 +117,7 @@ export interface IpcChannelMapping {
"link-version-folder-action": { request: VersionLinkerAction, response: void };
"is-version-folder-linked": { request: { version: BSVersion; relativeFolder: string }, response: boolean };
"relink-all-versions-folders": { request: void, response: void };
"get-shared-folder": { request: void, response: string };
/* ** launcher-ipcs ** */
"download-update": { request: void, response: Progression };
@@ -124,7 +131,7 @@ export interface IpcChannelMapping {
/* ** os-controls-ipcs ** */
"new-window": { request: string, response: void };
"open-dialog": { request: OpenDialogOptions, response: OpenDialogReturnValue };
"choose-folder": { request: string, response: OpenDialogReturnValue };
"choose-folder": { request: { defaultPath?: string, parent?: "home", showHidden?: boolean }, response: OpenDialogReturnValue };
"choose-file": { request: string, response: OpenDialogReturnValue }
"choose-image": { request: { multiple?: boolean, base64?: boolean }, response: string[] }
"window.progression": { request: number, response: void };
@@ -150,6 +157,9 @@ export interface IpcChannelMapping {
"static-configuration.get": StaticConfigGetIpcRequestResponse<StaticConfigKeys>;
"static-configuration.set": StaticConfigSetIpcRequest<StaticConfigKeys>;
/* ** linux.ipcs ** */
"linux.verify-proton-folder": { request: void, response: boolean };
/* ** OTHERS (if your IPC channel is not in a "-ipcs" file, put it here) ** */
"shortcut-launch-options": { request: void, response: LaunchOption };
}
@@ -1,8 +1,9 @@
import { SongDetailDiffCharactertistic, SongDiffName } from "../song-details-cache/song-details-cache.model";
import { RawMapInfoDataV2 } from "./raw-map-info-v2.model";
import { RawMapInfoDataV3 } from "./raw-map-info-v3.model";
import { RawMapInfoDataV4 } from "./raw-map-info-v4.model";
export type AnyRawMapInfo = RawMapInfoDataV2 | RawMapInfoDataV4;
export type AnyRawMapInfo = RawMapInfoDataV2 | RawMapInfoDataV3 | RawMapInfoDataV4;
// interfaces/mapInfo.ts
export interface MapInfo {
@@ -1,7 +1,7 @@
import { SongDetailDiffCharactertistic, SongDiffName } from "../song-details-cache/song-details-cache.model";
export interface RawMapInfoDataV2 {
_version: string;
_version: `2.${number}.${number}`;
_songName: string;
_songSubName: string;
_songAuthorName: string;
@@ -0,0 +1,39 @@
import { SongDetailDiffCharactertistic, SongDiffName } from "../song-details-cache/song-details-cache.model";
export interface RawMapInfoDataV3 {
_version: `3.${number}.${number}`;
_songName: string;
_songSubName: string;
_songAuthorName: string;
_levelAuthorName: string;
_beatsPerMinute: number;
_songTimeOffset: number;
_shuffle: number;
_shufflePeriod: number;
_previewStartTime: number;
_previewDuration: number;
_songFilename: string;
_coverImageFilename: string;
_environmentName: string;
_environmentNames?: string[];
_allDirectionsEnvironmentName: string;
_difficultyBeatmapSets: RawDifficultySetV3[];
}
interface RawDifficultySetV3 {
_beatmapCharacteristicName: SongDetailDiffCharactertistic;
_difficultyBeatmaps: RawMapDifficultyV3[];
}
interface RawMapDifficultyV3 {
_difficulty: SongDiffName;
_difficultyRank: number;
_beatmapFilename: string;
_noteJumpMovementSpeed: number;
_noteJumpStartBeatOffset: number;
_beatmapColorSchemeIdx?: number;
_environmentNameIdx?: number;
_customData?: {
_difficultyLabel?: string;
}
}
@@ -2,7 +2,7 @@ import { SongDetailDiffCharactertistic, SongDiffName } from "../song-details-cac
// interfaces/version4.ts
export interface RawMapInfoDataV4 {
version: string;
version: `4.${number}.${number}`;
song: {
title: string;
subTitle: string;
+6
View File
@@ -34,3 +34,9 @@ export interface FileHashes {
hash: string;
file: string;
}
// Any mods that are not supported in beatmods
export interface ExternalMod {
name: string;
files: string[];
}
+11 -1
View File
@@ -1,5 +1,6 @@
import { MapDifficulty, MapInfo, AnyRawMapInfo } from "shared/models/maps/info/map-info.model";
import { RawMapInfoDataV2 } from "shared/models/maps/info/raw-map-info-v2.model";
import { RawMapInfoDataV3 } from "shared/models/maps/info/raw-map-info-v3.model";
import { RawMapInfoDataV4 } from "shared/models/maps/info/raw-map-info-v4.model";
function parseVersion2(data: RawMapInfoDataV2): MapInfo {
@@ -34,6 +35,11 @@ function parseVersion2(data: RawMapInfoDataV2): MapInfo {
};
}
function parseVersion3(data: RawMapInfoDataV3): MapInfo {
// It's the same treatment as the version 2
return parseVersion2(data as unknown as RawMapInfoDataV2)
}
function parseVersion4(data: RawMapInfoDataV4): MapInfo {
return {
version: data.version,
@@ -64,7 +70,7 @@ function parseVersion4(data: RawMapInfoDataV4): MapInfo {
}
export function parseMapInfoDat(info: AnyRawMapInfo): MapInfo | never {
const version = (info as RawMapInfoDataV2)?._version || (info as RawMapInfoDataV4)?.version;
const version = (info as RawMapInfoDataV2)?._version || (info as RawMapInfoDataV3)?._version || (info as RawMapInfoDataV4)?.version;
if(!version) {
throw new Error('Cannot determine info.dat version');
@@ -74,6 +80,10 @@ export function parseMapInfoDat(info: AnyRawMapInfo): MapInfo | never {
return parseVersion2(info as RawMapInfoDataV2);
}
if (version.startsWith('3.')) {
return parseVersion3(info as RawMapInfoDataV3);
}
if (version.startsWith('4.')) {
return parseVersion4(info as RawMapInfoDataV4);
}