Compare commits
268 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 51ea1b130b | |||
| d020b72f20 | |||
| f2ac952cd9 | |||
| 189d2388fb | |||
| 1c989a2402 | |||
| 959e60127d | |||
| 0faa0f1288 | |||
| 5ad25f58d5 | |||
| 8ace5e6a7a | |||
| 185d01e7b4 | |||
| 755e407372 | |||
| 4f123b69ef | |||
| 7e2334f8fc | |||
| 5be533ccfb | |||
| b8eafd5f9b | |||
| 3f3bb959c4 | |||
| f30cad74d7 | |||
| ede82393da | |||
| 9ee468af03 | |||
| c4d5db809b | |||
| 8ecc9d30b3 | |||
| ca722b2a18 | |||
| c219e9655d | |||
| a6c1ba9fee | |||
| 6e9ea1bd9a | |||
| 84f27d571b | |||
| 51549161cd | |||
| 198002238e | |||
| ae0ad4d2f6 | |||
| e470782bea | |||
| b440c1b9e9 | |||
| 163b95ff26 | |||
| 6fa3b95f32 | |||
| 773432a407 | |||
| 45bab6ccce | |||
| 748b75ef3b | |||
| 116e4d77fa | |||
| c1322c4ed7 | |||
| f2ecd34672 | |||
| 657a683d13 | |||
| 0f038ccdc2 | |||
| 6d38985581 | |||
| 0edee845d7 | |||
| 517db1d056 | |||
| 65bf528a11 | |||
| 07e32df91a | |||
| 05a4386479 | |||
| 8c242e607b | |||
| a721c16c85 | |||
| 0957080e22 | |||
| 3427cae437 | |||
| 33be4de2ff | |||
| d83507a865 | |||
| 44c63a63c6 | |||
| d299553d1e | |||
| 415d47a9e5 | |||
| 9b8f1a7c42 | |||
| 12a8a49ccb | |||
| 3cfc59982b | |||
| 5e1a021c3a | |||
| d6ba587db0 | |||
| 4075b2fcde | |||
| b1ee9f054d | |||
| 15ebe8e929 | |||
| 901137ada9 | |||
| ab07334cb8 | |||
| 7407b7dc83 | |||
| 46824eb3ed | |||
| 1c9289f989 | |||
| 64d6aa25e3 | |||
| 126024b70b | |||
| cb08374cbb | |||
| 22a217528c | |||
| e9f297f186 | |||
| 934f857f96 | |||
| 56dbeea691 | |||
| bff5123373 | |||
| a48db98001 | |||
| 850f39339a | |||
| f0cbb066e4 | |||
| 8fefefd5ac | |||
| 365818266c | |||
| 764eeff57a | |||
| e713782b9f | |||
| d8cfad32a6 | |||
| 86c73239c9 | |||
| 9af6c9a94a | |||
| 9ffa0db43e | |||
| 5cf80ec6f2 | |||
| 0ea355d75c | |||
| 044174c711 | |||
| 7562b07832 | |||
| 0196206ec1 | |||
| d54464401f | |||
| 969be1e816 | |||
| d91a95ec0b | |||
| 89066411b1 | |||
| 604dec8540 | |||
| 32f03eaaa2 | |||
| 22769da7c5 | |||
| 69e573a12c | |||
| 7f726537ff | |||
| 40b12c6285 | |||
| 28f0a4d8c6 | |||
| 6e9c6e6c9e | |||
| 281ae0bbc6 | |||
| aad4cb9a2e | |||
| cc0ec76d83 | |||
| 7b7cdd5559 | |||
| 4a2f7697f9 | |||
| cbab039ca4 | |||
| 576cd2dec5 | |||
| c02ac39184 | |||
| 5eda9463c4 | |||
| 41ef0164fd | |||
| c833df9884 | |||
| ba3cca79b4 | |||
| ad6d9b57f8 | |||
| d21271693e | |||
| 589c191ac2 | |||
| 6a326fd584 | |||
| 0f430293a5 | |||
| 61ad8ba75b | |||
| 0cea1cd89f | |||
| 6836f18e89 | |||
| 0093c3970c | |||
| 644a0c4e43 | |||
| c71c7a96e3 | |||
| 0e02e2e2b9 | |||
| 4537cbd539 | |||
| 0c185066f6 | |||
| 5d5985f305 | |||
| 744c3f18c7 | |||
| 2a52ae3644 | |||
| e822738a3b | |||
| d185614d3b | |||
| c1a6a43825 | |||
| b98e1ccdfa | |||
| 4797aab0aa | |||
| 0460a0dab3 | |||
| 9cd5c48831 | |||
| e0f597e252 | |||
| ebbe2963b1 | |||
| 541a14d2a7 | |||
| 169a6e99b0 | |||
| 3da5af354e | |||
| 031c9044a1 | |||
| 6d271d8c48 | |||
| 8bc37ef3f1 | |||
| d7f3936619 | |||
| 49358b7006 | |||
| 067b967da1 | |||
| 31e1ae2273 | |||
| 7237e49c7f | |||
| 501def3a94 | |||
| f2cd9a1174 | |||
| d0fee6aaca | |||
| 7c034550fb | |||
| 1e6f051f59 | |||
| 08bdc03745 | |||
| de0575aea4 | |||
| 487d0c1f8b | |||
| ac5a9b16e5 | |||
| e7f5e98fcd | |||
| a36ccb0c13 | |||
| 59b04ee33e | |||
| b42231b134 | |||
| 11661cc1da | |||
| d7c43a2ba9 | |||
| 14a65f1d69 | |||
| bc9ab121b9 | |||
| 0f0f7c1abb | |||
| 1d9a261bc5 | |||
| 9a3ebf2971 | |||
| e51ef0992c | |||
| d9f025e28b | |||
| b4efa9583e | |||
| 1b4b59fbf0 | |||
| 8394581544 | |||
| 159d478e94 | |||
| 90bb8f2c19 | |||
| 097b18e72f | |||
| 9b744fb1e2 | |||
| 31f1ee1549 | |||
| c540308c2c | |||
| 778b4f6ee6 | |||
| df057cf82e | |||
| 5f94190b68 | |||
| 7718d239b2 | |||
| b29c9515d3 | |||
| 535831c03a | |||
| b03b670d56 | |||
| 1fd185fe88 | |||
| 05154f577f | |||
| c62896f078 | |||
| 2403f02851 | |||
| b8262a941d | |||
| 8e8d608120 | |||
| c92ca87c4c | |||
| b02cd7fc77 | |||
| 86c1f5aa7b | |||
| cd5237aff3 | |||
| 5449792294 | |||
| 5c35eae53a | |||
| 61889c0b5b | |||
| 4cf242f683 | |||
| 3217addaa6 | |||
| 76ed1b09a1 | |||
| 9401f1cf4a | |||
| 6b4d919afe | |||
| e92efa0ada | |||
| 99a9f5b1de | |||
| 98bdbba23c | |||
| ddde1f8b8a | |||
| b951be9511 | |||
| b91d74f3a3 | |||
| 002b11d54c | |||
| 4e15d1c1b6 | |||
| 961e629de8 | |||
| 02ad4b9c68 | |||
| a981adede0 | |||
| 33bab3ea0e | |||
| 7dae25ce32 | |||
| 71f317dd37 | |||
| 8333e238a6 | |||
| 39f2a16c96 | |||
| 2c08f1e07c | |||
| f4560b9190 | |||
| f0f83e2b3b | |||
| 0776de8d79 | |||
| 504462258a | |||
| fdef870e83 | |||
| 7d58fec63b | |||
| c77f4a9448 | |||
| 37a3951f7b | |||
| e5599b78d8 | |||
| 2da329367f | |||
| 0b64722092 | |||
| fbec5a0e46 | |||
| e21b731e10 | |||
| 19998facc7 | |||
| c8017939da | |||
| 75100e6919 | |||
| 834dad0cc0 | |||
| f57926e41b | |||
| 57157b4553 | |||
| b2c1338650 | |||
| 1dde1b8916 | |||
| 7e9b8ec86d | |||
| ec0d2fb8c6 | |||
| 214ffc243d | |||
| d243475bf8 | |||
| 9872fcb856 | |||
| 29f7754ba9 | |||
| 9c440a0430 | |||
| aaf75278d0 | |||
| ae2cf08c7d | |||
| 4a0848fb41 | |||
| 76c863608e | |||
| 8963c08e64 | |||
| ba51e76691 | |||
| cb0faad418 | |||
| 00bf26081b | |||
| 385c403bee | |||
| 6c3a241481 | |||
| 34c0ad03d3 | |||
| 8c9846d751 | |||
| 0d7c160b24 |
@@ -40,6 +40,7 @@ const configuration: webpack.Configuration = {
|
||||
},
|
||||
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
parallel: true,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable import/no-import-module-exports */
|
||||
import "webpack-dev-server";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import path from 'path';
|
||||
import { copyFileSync, existsSync, readdirSync } from 'fs-extra';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const eternalsFolder = path.join(__dirname, '..', '..', 'externals');
|
||||
|
||||
// Get rust project folders from externals
|
||||
const rustProjects = readdirSync(eternalsFolder).filter(folder => existsSync(path.join(eternalsFolder, folder, 'Cargo.toml')));
|
||||
|
||||
// Build each rust project in release mode
|
||||
rustProjects.forEach(project => {
|
||||
console.log(`Building ${project}`);
|
||||
execSync(`cargo build --release`, {
|
||||
cwd: path.join(eternalsFolder, project),
|
||||
stdio: 'inherit',
|
||||
});
|
||||
});
|
||||
|
||||
// Copy the built files exe to the assests/scripts folder
|
||||
rustProjects.forEach(project => {
|
||||
// read the project name from Cargo.toml using toml parser
|
||||
const projectMetadata = execSync('cargo metadata --no-deps --format-version 1', {
|
||||
cwd: path.join(eternalsFolder, project),
|
||||
stdio: 'pipe',
|
||||
});
|
||||
const projectMetadataJson = JSON.parse(projectMetadata);
|
||||
const projectName = projectMetadataJson.packages[0].name;
|
||||
|
||||
const source = path.join(eternalsFolder, project, 'target', 'release', `${projectName}.exe`);
|
||||
const destination = path.join(__dirname, '..', '..', 'assets', 'scripts', `${projectName}.exe`);
|
||||
console.log(`Copying ${source} to ${destination}`);
|
||||
copyFileSync(source, destination);
|
||||
});
|
||||
@@ -1,17 +1,13 @@
|
||||
import rimraf from "rimraf";
|
||||
import process from "process";
|
||||
import webpackPaths from "../configs/webpack.paths";
|
||||
import { rimrafSync } from 'rimraf';
|
||||
import fs from 'fs';
|
||||
import webpackPaths from '../configs/webpack.paths';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const commandMap = {
|
||||
dist: webpackPaths.distPath,
|
||||
release: webpackPaths.releasePath,
|
||||
dll: webpackPaths.dllPath,
|
||||
};
|
||||
const foldersToRemove = [
|
||||
webpackPaths.distPath,
|
||||
webpackPaths.buildPath,
|
||||
webpackPaths.dllPath,
|
||||
];
|
||||
|
||||
args.forEach(x => {
|
||||
const pathToRemove = commandMap[x];
|
||||
if (pathToRemove !== undefined) {
|
||||
rimraf.sync(pathToRemove);
|
||||
}
|
||||
foldersToRemove.forEach((folder) => {
|
||||
if (fs.existsSync(folder)) rimrafSync(folder);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
import path from "path";
|
||||
import rimraf from "rimraf";
|
||||
import webpackPaths from "../configs/webpack.paths";
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { rimrafSync } from 'rimraf';
|
||||
import webpackPaths from '../configs/webpack.paths';
|
||||
|
||||
export default function deleteSourceMaps() {
|
||||
rimraf.sync(path.join(webpackPaths.distMainPath, "*.js.map"));
|
||||
rimraf.sync(path.join(webpackPaths.distRendererPath, "*.js.map"));
|
||||
if (fs.existsSync(webpackPaths.distMainPath))
|
||||
rimrafSync(path.join(webpackPaths.distMainPath, '*.js.map'), {
|
||||
glob: true,
|
||||
});
|
||||
if (fs.existsSync(webpackPaths.distRendererPath))
|
||||
rimrafSync(path.join(webpackPaths.distRendererPath, '*.js.map'), {
|
||||
glob: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
const { notarize } = require("electron-notarize");
|
||||
const { build } = require("../../package.json");
|
||||
const { notarize } = require('@electron/notarize');
|
||||
const { build } = require('../../package.json');
|
||||
|
||||
exports.default = async function notarizeMacos(context) {
|
||||
const { electronPlatformName, appOutDir } = context;
|
||||
if (electronPlatformName !== "darwin") {
|
||||
return;
|
||||
}
|
||||
const { electronPlatformName, appOutDir } = context;
|
||||
if (electronPlatformName !== 'darwin') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.env.CI !== "true") {
|
||||
console.warn("Skipping notarizing step. Packaging is not running in CI");
|
||||
return;
|
||||
}
|
||||
if (process.env.CI !== 'true') {
|
||||
console.warn('Skipping notarizing step. Packaging is not running in CI');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!("APPLE_ID" in process.env && "APPLE_ID_PASS" in process.env)) {
|
||||
console.warn("Skipping notarizing step. APPLE_ID and APPLE_ID_PASS env variables must be set");
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!('APPLE_ID' in process.env && 'APPLE_APP_SPECIFIC_PASSWORD' in process.env)
|
||||
) {
|
||||
console.warn(
|
||||
'Skipping notarizing step. APPLE_ID and APPLE_APP_SPECIFIC_PASSWORD env variables must be set',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const appName = context.packager.appInfo.productFilename;
|
||||
const appName = context.packager.appInfo.productFilename;
|
||||
|
||||
await notarize({
|
||||
appBundleId: build.appId,
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleId: process.env.APPLE_ID,
|
||||
appleIdPassword: process.env.APPLE_ID_PASS,
|
||||
});
|
||||
await notarize({
|
||||
appBundleId: build.appId,
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleId: process.env.APPLE_ID,
|
||||
appleIdPassword: process.env.APPLE_APP_SPECIFIC_PASSWORD,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -47,11 +47,6 @@ module.exports = {
|
||||
"import/no-cycle": "off",
|
||||
"prefer-promise-reject-errors": "off",
|
||||
"react/jsx-no-target-blank": "off",
|
||||
"@typescript-eslint/ban-types": ["error", {
|
||||
types: {
|
||||
Function: false,
|
||||
}
|
||||
}]
|
||||
"import/extensions": "off",
|
||||
"lines-between-class-members": "off",
|
||||
"no-throw-literal": "warn",
|
||||
@@ -64,15 +59,17 @@ module.exports = {
|
||||
"react/function-component-definition": "off",
|
||||
"jsx-a11y/control-has-associated-label": "off",
|
||||
"react/button-has-type": "off",
|
||||
"max-classes-per-file": "off",
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: "module",
|
||||
project: "./tsconfig.json",
|
||||
tsconfigRootDir: __dirname,
|
||||
createDefaultProgram: true,
|
||||
},
|
||||
globals: {
|
||||
JSX: true,
|
||||
NodeJS: true
|
||||
},
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
// See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
|
||||
@@ -86,4 +83,5 @@ module.exports = {
|
||||
"@typescript-eslint/parser": [".ts", ".tsx"],
|
||||
},
|
||||
},
|
||||
"plugins": ["@typescript-eslint"]
|
||||
};
|
||||
|
||||
@@ -15,5 +15,3 @@
|
||||
*.ttf binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
assets/scripts/* binary
|
||||
*.zip binary
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# This workflow will...
|
||||
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: "npm"
|
||||
- run: npm ci
|
||||
- run: npm run package
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-${{ matrix.os }}
|
||||
path: release
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
@@ -26,7 +26,6 @@ jobs:
|
||||
cache: "npm"
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
|
||||
- name: Unit tests
|
||||
run: npm run test:unit
|
||||
|
||||
- run: npm test
|
||||
# Currently typescript, eslint, and prettier are unhappy
|
||||
continue-on-error: true
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# This workflow will...
|
||||
|
||||
name: Realease Linux
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: "npm"
|
||||
- run: npm ci
|
||||
- run: npm run publish:linux
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release
|
||||
path: release
|
||||
@@ -29,4 +29,4 @@ npm-debug.log.*
|
||||
*.scss.d.ts
|
||||
|
||||
# externals
|
||||
externals/**/target/**
|
||||
externals/**/target/*
|
||||
|
||||
@@ -57,10 +57,12 @@
|
||||
<a href="https://discord.gg/uSqbHVpKdV"><img
|
||||
src="https://img.shields.io/badge/-DISCORD-5865f2?style=for-the-badge&logo=discord&logoColor=ffffff"
|
||||
alt="discord" /></a>
|
||||
<a href="https://www.patreon.com/bsmanager"><img
|
||||
src="https://img.shields.io/badge/-🥰%20Support%20BSM-EC4546?style=for-the-badge" alt="Donation" /></a>
|
||||
<a href="https://twitter.com/BSManager_"><img
|
||||
src="https://img.shields.io/badge/-Twitter-F5F8FA?style=for-the-badge&logo=Twitter" alt="Twitter" /></a>
|
||||
src="https://img.shields.io/badge/-Twitter-black?style=for-the-badge&logo=X" alt="Twitter" /></a>
|
||||
<a href="https://www.bsmanager.io">
|
||||
<img src="https://img.shields.io/badge/-WebSite-00649c?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPgogIDxnIGZpbGw9IiMzYjgyZmYiPgogICAgPHBhdGggZD0ibTYyNi43NSA0ODUuOTEgMjAuODIgMzUxLjk0YTM1LjIxIDM1LjIxIDAgMCAxLTE1LjQ5IDMxLjM2bC0xNDQuNzEgOTYuMTRoLS4wNmEzNS41NiAzNS41NiAwIDAgMS0xMS4zMSA0Ljc3IDM0Ljg1IDM0Ljg1IDAgMCAxLTIzLjUxLTIuODdMMTM2LjU4IDgwOS45YTExNS40NSAxMTUuNDUgMCAwIDEtNjMuNzUtOTYuNDlMNTIgMzYxLjQ2YTM1LjI2IDM1LjI2IDAgMCAxIDE1LjIzLTMxLjIxbDE0NS4wNS05Ni4zNmEzNS43MiAzNS43MiAwIDAgMSAxMS4yNy00LjcgMzQuODcgMzQuODcgMCAwIDEgMjMuNTEgMi44N0w1NjMgMzg5LjQyYTExNS40MSAxMTUuNDEgMCAwIDEgNjMuNzUgOTYuNDlaIi8+CiAgICA8cGF0aCBmaWx0ZXI9ImJyaWdodG5lc3MoMzAlKSIgZD0ibTYxMy43OCA0ODYuNjcgMjAuODIgMzUyYTIyLjM0IDIyLjM0IDAgMCAxLTMyLjI2IDIxLjMxTDI4Ni40IDcwMi41N0ExMDIuNDMgMTAyLjQzIDAgMCAxIDIyOS44MyA2MTdMMjA5IDI2NWEyMi4zNSAyMi4zNSAwIDAgMSAzMi4yNi0yMS4zMkw1NTcuMiA0MDEuMDVhMTAyLjQyIDEwMi40MiAwIDAgMSA1Ni41OCA4NS42MloiLz4KICA8L2c+CiAgPHBhdGggZD0iTTcxOC4yOSA3NzYuNDggNzAwIDgwNC4xOGMtNDAuNjMgMzkuNS04Ny4wNiA2Ny4yNS0xMzMuODEgOTAuNzUtODcuMzIgNDMuOS0yMDMuNjcgNzcuMTktMjQ5IDkwLjM0YTQ4IDQ4IDAgMCAxLTI2LjE3LjE2Yy02NC0xNy43Mi0xODguNjItNzItMjM2LjI4LTEyNS40OWE0LjIzIDQuMjMgMCAwIDEgNS4zLTYuNDVjMzUuNjQgMjAuODcgMTExLjIyIDU3LjY0IDE1Ni4zNyA3NC4yMiA0OS4xOCAxOC4wNiA4MS4yOSA4Ljc0IDkyLjI4LTMuMjZhNC43NyA0Ljc3IDAgMCAxIDcuMjQuMjFjMTkuNTEgMjQgMTA3LjI2IDQuNiAxNjYuNjQtMTMgNjQuMzQtMTkgMTg1Ljg1LTc2LjU2IDIzNS43Mi0xMzUuMThabS0xOTYuMiAxNTcuMzMtMTQ3LjQ1IDU1LjY4YTMuOTIgMy45MiAwIDAgMCAxLjQ0IDcuNThsNTQuNjItLjc3YTM1LjYzIDM1LjYzIDAgMCAwIDE5LTUuNzlsNzYtNDkuNTVhNCA0IDAgMCAwLTMuNjEtNy4xNVpNMjE4LjkyIDE5NS41NmMtMjEuMTQuMDctMzMuNTUgMzUuODYtMzMuMTYgODkuMDguMiAyOCAyLjU4IDkyLjc0IDQuNzkgMTQ3LjczLjIzIDUuNzEtOC4xOCA2LjQ4LTkgLjgxbC0zOC40Mi0yNzAuNzFhNC4zOCA0LjM4IDAgMCAxIDcuMTItNCA2My42MyA2My42MyAwIDAgMCAyMS45MyAxMS44NSA0LjYxIDQuNjEgMCAwIDAgNS45LTMuNzJjNC4yLTI3LjcgMTYuNjMtNTguNzQgMzcuMzUtODguNzRhNC4zNiA0LjM2IDAgMCAxIDcuNTYuNjljMTAuODYgMjMuODcgNDkgMTAzLjggOTMuMzQgMTUyLjc5YTQuNjUgNC42NSAwIDAgMS01LjYyIDcuMjJjLTM2LjU3LTE5LjM4LTgzLjAxLTQzLjAyLTkxLjc5LTQzWm0tMTUuNDcgMzg0LjhhNC41MSA0LjUxIDAgMCAxLTQuNDYtMy45MmwtMTMuODItMTA3LjI5YTQuNSA0LjUgMCAwIDEgOC45My0xLjE1bDEzLjgyIDEwNy4yOWE0LjUgNC41IDAgMCAxLTMuODkgNSAzLjg2IDMuODYgMCAwIDEtLjU4LjA3Wk01NzcuMDggNTQuNThjLTQ2Ljc5IDE1Ljg1LTExNS40NSA0MC41Ni0xNTguNzMgNjIuNzlhMzUuNSAzNS41IDAgMCAwLTE4LjU3IDI0LjUzYy0zLjk1IDE5LjQ5LTExIDU2LjA5LTE5IDEwNy4yNi0uNyA0LjQ4LTcuMzYgMy43OC03LjExLS43NWwxMC42Ni0xOTQuNzNhMy43OCAzLjc4IDAgMCAxIDcuNDYtLjY2bDMuNDkgMTQuODVhMi41NyAyLjU3IDAgMCAwIDQuNjkuNzdjNi4xOC0xMCAyMi4zNy0zMi43OSA1Ny4zMi02NWE0LjEzIDQuMTMgMCAwIDEgNi41NiA0LjcybC0zMi41NCA3Mi44OXM3OC43OC0xOS4zNyAxNDQtMzMuMDljNC4xMS0uODcgNS42OSA1LjA4IDEuNzcgNi40MloiIGZpbGw9IiNmZmYiIHN0cm9rZT0iYmxhY2siLz4KICA8ZyBmaWxsPSIjZjQ0Ij4KICAgIDxwYXRoIGZpbHRlcj0iYnJpZ2h0bmVzcyg2MCUpIHNhdHVyYXRlKDEyMCUpIiBkPSJtOTQ3LjA3IDQxMC4zNS01Ny43NSAzNDcuNzlhMzUuMTggMzUuMTggMCAwIDEtMjIuMDYgMjcuMTVsLTE2Mi40MyA2MS42NWgtLjA2YTM1LjUyIDM1LjUyIDAgMCAxLTEyLjA2IDIuMTEgMzQuODMgMzQuODMgMCAwIDEtMjIuMjktOGwtMjczLjE3LTIyMy41YTExNS40MyAxMTUuNDMgMCAwIDEtNDAuNzYtMTA4LjIybDU3Ljc1LTM0Ny44QTM1LjI1IDM1LjI1IDAgMCAxIDQzNiAxMzQuNDdsMTYyLjgzLTYxLjc5YTM1LjUxIDM1LjUxIDAgMCAxIDEyLTIuMDggMzQuODMgMzQuODMgMCAwIDEgMjIuMjkgOGwyNzMuMTkgMjIzLjUyYTExNS4zOCAxMTUuMzggMCAwIDEgNDAuNzYgMTA4LjIzWiIvPgogICAgPHBhdGggZD0iTTkzNC4yNSA0MDguMjIgODc2LjUgNzU2YTIyLjM0IDIyLjM0IDAgMCAxLTM2LjE4IDEzLjYzbC0yNzMuMTctMjIzLjVhMTAyLjQyIDEwMi40MiAwIDAgMS0zNi4xNy05Nmw1Ny43NS0zNDcuODNhMjIuMzQgMjIuMzQgMCAwIDEgMzYuMTgtMTMuNjNsMjczLjE3IDIyMy41MWExMDIuNDIgMTAyLjQyIDAgMCAxIDM2LjE3IDk2LjA0WiIvPgogIDwvZz4KICA8ZWxsaXBzZSBmaWxsPSIjZmZmIiBzdHJva2U9ImJsYWNrIiBjeD0iNzMyLjYxIiBjeT0iNDI5LjE2IiByeD0iNjIuODMiIHJ5PSIxMTAuNzMiIHRyYW5zZm9ybT0icm90YXRlKC0xNS40NSA3MzIuNzAzIDQyOS4xOTkpIi8+Cjwvc3ZnPg==" alt="Website" /></a>
|
||||
<a href="https://www.patreon.com/bsmanager"><img
|
||||
src="https://img.shields.io/badge/-🤍%20Support%20BSM-EC4546?style=for-the-badge" alt="Donation" /></a>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
@@ -287,13 +289,11 @@
|
||||
<div>
|
||||
<ul>
|
||||
<li><strong>via Oculus</strong>: For Oculus users, <a href="https://github.com/Zagrios/bs-manager">BSManager</a>
|
||||
uses authentication directly via the <a href="https://about.meta.com/fr/">META</a> website
|
||||
to retrieve the connection token, ensuring reliable and secure access to your account data.</li>
|
||||
requires you to retrieve a connection token by following the instructions in this guide: <a href="https://github.com/Zagrios/bs-manager/wiki/How-to-obtain-your-Oculus-Token">How to obtain your Oculus Token</a>. Once obtained, please insert it into the form.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<img height=450 src="https://github.com/Zagrios/bs-manager/assets/40648115/1e4a2f98-af16-45aa-821d-0c4e90e1e54b" />
|
||||
<img height=450 src="https://github.com/Zagrios/bs-manager/assets/40648115/3674e629-542d-4de3-b8db-b248f25126d7" />
|
||||
</div>
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 401 KiB |
@@ -733,7 +733,8 @@
|
||||
"ReleaseURL": "https://store.steampowered.com/news/app/620980/view/4161968170153497460",
|
||||
"ReleaseImg": "https://clan.akamai.steamstatic.com/images//32055887/f82d34c7582137a6748a28c5b02670ff4b235356.png",
|
||||
"ReleaseDate": "1717513346",
|
||||
"year": "2024"
|
||||
"year": "2024",
|
||||
"recommended": true
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.37.1",
|
||||
@@ -743,75 +744,5 @@
|
||||
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/039be718c1494f948257cd5b09f0082986484a58.png",
|
||||
"ReleaseDate": "1720710529",
|
||||
"year": "2024"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.37.2",
|
||||
"BSManifest": "6848299977215652352",
|
||||
"OculusBinaryId": "7438773609555687",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4349999161850643744",
|
||||
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/7c03af6d12fad23f1d439666d4be86b492d40003.png",
|
||||
"ReleaseDate": "1722945814",
|
||||
"year": "2024"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.37.3",
|
||||
"BSManifest": "5834150512217183366",
|
||||
"OculusBinaryId": "7553569971409383",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/6808965920900622902",
|
||||
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/a1c9a6737cc5182fca8cddc7c8088eda6dd4d82d.png",
|
||||
"ReleaseDate": "1724061712",
|
||||
"year": "2024"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.37.4",
|
||||
"BSManifest": "7585106640515547731",
|
||||
"OculusBinaryId": "7630971613669218",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4601078012425941968",
|
||||
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/23e6e6f219a56d2f9ea4a27b560c54ac1214aec3.png",
|
||||
"ReleaseDate": "1725548547",
|
||||
"year": "2024"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.37.5",
|
||||
"BSManifest": "3122533396458693889",
|
||||
"OculusBinaryId": "7685108391588873",
|
||||
"ReleaseDate": "1725628356",
|
||||
"year": "2024"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.38.0",
|
||||
"BSManifest": "3482902979520746178",
|
||||
"OculusBinaryId": "7834818833284494",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4669760442595134838",
|
||||
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/57cfa043407c091e67b7e0a8ae86fe5590deae33.png",
|
||||
"ReleaseDate": "1728399815",
|
||||
"year": "2024"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.39.0",
|
||||
"BSManifest": "5365094543246905054",
|
||||
"OculusBinaryId": "7978663688900007",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4451339035198095638",
|
||||
"ReleaseImg": "https://clan.cloudflare.steamstatic.com/images/32055887/fd8e2c783e46decdf5e10fed1e16f124616d9321.png",
|
||||
"ReleaseDate": "1731426932",
|
||||
"year": "2024"
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.39.1",
|
||||
"BSManifest": "2179614296547473280",
|
||||
"OculusBinaryId": "8189133517853022",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4451340304252928024",
|
||||
"ReleaseDate": "1732107748",
|
||||
"year": "2024",
|
||||
"recommended": true
|
||||
},
|
||||
{
|
||||
"BSVersion": "1.40.0",
|
||||
"BSManifest": "8455036253884215709",
|
||||
"OculusBinaryId": "8259984977434542",
|
||||
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/507314379973199787",
|
||||
"ReleaseImg": "https://clan.fastly.steamstatic.com/images/32055887/65df6b24c3b8a7f415080ac01394917cedabf9fc.png",
|
||||
"ReleaseDate": "1733846128",
|
||||
"year": "2024"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"1.5.0-alpha.1":{
|
||||
"htmlBody" :"<strong>BSManager continues to get better, thanks to your continued support and contributions!</strong><center>🎈🎉🎈</center><p>Note: This is an alpha release, encountering bugs is expected. Please file new issues for any bugs you find.</p><h2>Features</h2><ul><li>Added playlist support</li><li>Added Linux support (Thanks to @Insprill)</li><li>Added reset button to reset values when editing a Beat Saber version (Thanks to @Liborsaf)</li><li>Added a changelog modal</li></ul><h2>Fixes</h2><ul><li>Fixed an issue where switching between Beat Saber versions too quickly displayed mods for the wrong version</li><li>Fixed an issue where the launch window from a shortcut would never close</li><li>Advanced launch arguments are used even when the input field is closed</li><li>Fixed an issue where having many maps caused some maps to not have their information loaded</li></ul><h2>Other changes</h2><ul><li>.NET Framework is no longer required</li><li>Clear English translations for the Steam credentials popup (Thanks to @Aeywoo)</li><li>NSFW models are now blurred when browsing for models</li><li>When no mods are available for a Beat Saber version, the version number is now shown</li><li>Mods load faster</li><li>After a first full maps loading, maps load almost instantly</li><li>Improved performance in lists with lot of contents</li></ul>",
|
||||
"title" : "What's new ?",
|
||||
"timestamp" : 1721048400,
|
||||
"version" : "1.5.0-alpha.1"
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,6 @@
|
||||
{
|
||||
"username": "Falmil"
|
||||
},
|
||||
{
|
||||
"username": "K1Lc4m"
|
||||
},
|
||||
{
|
||||
"username": "Anonymously42",
|
||||
"type": "diamond",
|
||||
@@ -30,9 +27,6 @@
|
||||
"username": "Burt",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": "Ilnahro"
|
||||
},
|
||||
{
|
||||
"username": "Phil",
|
||||
"type": "gold"
|
||||
@@ -41,18 +35,10 @@
|
||||
"username": "Protocrush",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": "ServerMensch",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": "Karlito",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": "Cathery",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": ".sharkey"
|
||||
},
|
||||
@@ -74,9 +60,6 @@
|
||||
{
|
||||
"username": "Minescence"
|
||||
},
|
||||
{
|
||||
"username": "Finlay"
|
||||
},
|
||||
{
|
||||
"username": "mereknom"
|
||||
},
|
||||
@@ -89,5 +72,32 @@
|
||||
},
|
||||
{
|
||||
"username": "rhythmshade"
|
||||
}
|
||||
},
|
||||
{
|
||||
"username": "liborsaf"
|
||||
},
|
||||
{
|
||||
"username": "aatame3",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": "Joshua"
|
||||
},
|
||||
{
|
||||
"username": "Stuijvi",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": "_ monaka"
|
||||
},
|
||||
{
|
||||
"username": "Better_Axel"
|
||||
},
|
||||
{
|
||||
"username": "Riley",
|
||||
"type": "gold"
|
||||
},
|
||||
{
|
||||
"username": "Austin"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "Ablehnen",
|
||||
"apply": "Übernehmen",
|
||||
"copy": "Kopieren",
|
||||
"copied": "Kopiert!",
|
||||
"confirm": "Bestätigen",
|
||||
"choose-folder": "Ordner Wählen",
|
||||
"unknown": "Ein unbekannter Fehler ist aufgetreten ¯\\_(ツ)_/¯",
|
||||
"warning": "Achtung",
|
||||
"continue": "Weiter"
|
||||
"copied": "Kopiert!"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "Version Hinzufügen",
|
||||
@@ -37,8 +32,7 @@
|
||||
"desktop": "FPFC Modus",
|
||||
"desktop-description": "Auf diese Weise kannst du WASD und die Maus verwenden, um im Spiel durch das Menü zu navigieren. Dies erleichtert das Testen erheblich, da Du dein Headset nicht aufsetzen musst!",
|
||||
"debug": "Debug Modus",
|
||||
"debug-description": "Aktiviert das Ausgabeprotokollfenster für IPA. Dies zeigt die Debug-Konsole, welche die Mods verwenden.",
|
||||
"outdated-tippy": "Diese Version ist veraltet, und einige Mods oder Funktionen funktionieren möglicherweise nicht wie erwartet. Es wird empfohlen, die empfohlene Version ({recommendedVersion}) von Beat Saber zu verwenden, um die neuesten Funktionen und Fehlerbehebungen zu genießen.",
|
||||
"debug-description": "Aktiviert das Ausgabeprotokollfenster für IPA. Dies zeigt die Debug-Konsole, die Mods verwenden.",
|
||||
"advanced-launch": {
|
||||
"button": "Erweiterter Start",
|
||||
"placeholder": "Weitere Argumente Bspw: --revert; --nowait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "Neueste",
|
||||
"description": "Beschreibung",
|
||||
"dropdown": {
|
||||
"uninstall-all": "Alle deinstallieren",
|
||||
"unselect-all": "Alle abwählen"
|
||||
"uninstall-all": "Alle deinstallieren"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +190,10 @@
|
||||
"report-bug": "Fehler melden",
|
||||
"open-logs": "Protokolle öffnen"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 Neues im Changelog entdecken!",
|
||||
"not-founds": "😕 Hoppla, kein Changelog zu sehen!"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +238,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": ".NET 8 Benötigt"
|
||||
},
|
||||
"msg": {
|
||||
"401": "Steam scheint uns BeatSaber nicht herunterladen zu lassen 😢",
|
||||
"404": "Steam-Server können nicht kontaktiert werden.",
|
||||
@@ -266,11 +260,7 @@
|
||||
"LicenceError": "Die Liste der Lizenzen kann nicht abgerufen werden.",
|
||||
"RateLimitExceeded": "Du hast es zu oft versucht, warte eine Weile und versuche es später erneut.",
|
||||
"TokenRejected": "Ihr Anmeldetoken wurde abgelehnt 😕 Bitte versuchen Sie es erneut.",
|
||||
"AccessDenied": "Der Zugang zu Steam wurde verweigert.",
|
||||
"dotnet-required": ".NET 8 Runtime muss installiert sein, um eine Version von BeatSaber herunterzuladen. Lade es herunter, indem Du auf die Schaltfläche unten klickst."
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": ".NET 8 Herunterladen"
|
||||
"AccessDenied": "Der Zugang zu Steam wurde verweigert."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -387,20 +377,16 @@
|
||||
"BS_ALREADY_RUNNING": "Beat Saber läuft bereits",
|
||||
"EXE_NOT_FINDED": "Dateien Fehlen",
|
||||
"EXIT": "Abrupter Stop",
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculus-Bibliothek nicht gefunden",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Original Oculus-Version nicht gefunden"
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculus-Bibliothek nicht gefunden"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "Ein unbekannter Fehler ist aufgetreten.",
|
||||
"STEAM_NOT_RUNNING": "Steam muss laufen, um Beat Saber zu starten.",
|
||||
"OCULUS_NOT_RUNNING": "Oculus muss ausgeführt werden, um Beat Saber zu starten.",
|
||||
"BS_ALREADY_RUNNING": "Schließe Beat Saber, bevor du es erneut startest.",
|
||||
"EXE_NOT_FINDED": "Einige Dateien scheinen zu fehlen. Versuche, die Dateien zu überprüfen.",
|
||||
"EXIT": "Beat Saber stoppte abrupt. Versuche, die Dateien zu überprüfen.",
|
||||
"OCULUS_LIB_NOT_FOUND": "Überprüfe, ob die Oculus-Anwendung korrekt installiert ist und dass die Bibliotheken in Oculus richtig definiert sind.",
|
||||
"PROTON_NOT_SET": "Stellen Sie den Proton-Pfad in den Einstellungen ein.",
|
||||
"PROTON_NOT_FOUND": "Stellen Sie den Proton-Pfad in den Einstellungen ein.",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Beat Saber muss vor dem Öffnen über die Oculus-App installiert werden."
|
||||
"BS_ALREADY_RUNNING": "Schließe Beat Saber, bevor Du es erneut startest.",
|
||||
"EXE_NOT_FINDED": "Einige Dateien scheinen zu fehlen, versuche die Dateien zu überprüfen.",
|
||||
"EXIT": "Beat Saber stoppte abrupt, versuche die Dateien zu überprüfen.",
|
||||
"OCULUS_LIB_NOT_FOUND": "Überprüfe, ob die Oculus-Anwendung korrekt installiert ist und dass die Bibliotheken in Oculus richtig definiert sind."
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "Starte Steam"
|
||||
@@ -492,16 +478,6 @@
|
||||
"title": "Sicherung erstellt",
|
||||
"msg": "Das Freigeben des Ordners „UserData“ kann zu Fehlern führen. Bei Problemen trenne den Ordner, um die Sicherung wiederherzustellen"
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "Fehler beim Verknüpfen des Ordners",
|
||||
"msg": {
|
||||
"EPERM": "BSManager hat nicht die erforderlichen Berechtigungen, um den Ordner zu verknüpfen.",
|
||||
"EACCES": "BSManager hat nicht die erforderlichen Berechtigungen, um den Ordner zu verknüpfen.",
|
||||
"ENOSPC": "Die Festplatte ist voll, machen Sie Platz und versuchen Sie es erneut.",
|
||||
"LinkingNotSupported": "Ordnerverknüpfung wird auf diesem Dateisystem nicht unterstützt.",
|
||||
"UNKNOWN_ERROR": "Ein unbekannter Fehler ist beim Verknüpfen des Ordners aufgetreten."
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
@@ -512,14 +488,6 @@
|
||||
"error": {
|
||||
"msg": "Beim Erstellen der Verknüpfung ist ein Fehler aufgetreten."
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "Veraltete Version",
|
||||
"msg": "Diese Version von Beat Saber ist veraltet. Verwenden Sie die empfohlene Version, um die neuesten Funktionen und Fehlerbehebungen zu nutzen.",
|
||||
"actions": {
|
||||
"do-not-remind": "Nicht mehr daran erinnern",
|
||||
"ok": "Ok"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -719,12 +687,13 @@
|
||||
"stay": "Angemeldet bleiben",
|
||||
"connect-to-meta": "Mit Meta verbinden"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Sideloading aktivieren",
|
||||
"info-1": "Um Beat Saber starten zu können, muss die Möglichkeit aktiviert werden, Sideloading-Apps auszuführen. BSManager wird Administratorrechte anfordern, um diese Funktion automatisch zu aktivieren.",
|
||||
"info-2": "Die Sideloading-Funktion ermöglicht das Starten von Spielen, die sich außerhalb Ihres Oculus-Bibliotheksordners befinden.",
|
||||
"info-3": "Nachdem das Sideloading aktiviert wurde, bleibt die Funktion aktiv, und Sie werden nicht mehr aufgefordert, sie zu aktivieren.",
|
||||
"i-want-to-do-it-myself": "Ich möchte es selbst machen",
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Achtung",
|
||||
"body": {
|
||||
"must-be-installed-once": "Sie müssen Beat Saber mindestens einmal aus dem Oculus Store installiert haben, sonst könnte sich Beat Saber nach dem Start automatisch schließen.",
|
||||
"will-backup": "Um diese Version zu starten, wird der ursprüngliche Installationsordner von Beat Saber in Ihrer Oculus-Bibliothek umbenannt und beim Schließen von Beat Saber automatisch wiederhergestellt."
|
||||
},
|
||||
"not-remind-me": "Nicht mehr erinnern",
|
||||
"understood": "Verstanden"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
@@ -754,9 +723,6 @@
|
||||
},
|
||||
"launch-as-admin": "Als Administrator starten",
|
||||
"not-remind-me": "Nicht mehr erinnern"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "Die Version {outdatedVersion} ist veraltet, und einige Mods oder Funktionen funktionieren möglicherweise nicht mehr wie erwartet. Bitte lade die neueste empfohlene Version ({recommendedVersion}) von Beat Saber herunter, um die neuesten Funktionen und Fehlerbehebungen zu nutzen."
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -772,48 +738,48 @@
|
||||
"accuracy": "Präzision",
|
||||
"balanced": "Ausgeglichen",
|
||||
"challenge": "Herausforderung",
|
||||
"dance-style": "Tanz",
|
||||
"dancestyle": "Tanz",
|
||||
"fitness": "Fitness",
|
||||
"speed": "Geschwindigkeit",
|
||||
"tech": "Tech"
|
||||
},
|
||||
"map-styles": {
|
||||
"dance": "tanz",
|
||||
"swing": "swing",
|
||||
"nightcore": "nightcore",
|
||||
"folk-acoustic": "folk & akustisch",
|
||||
"kids-family": "kinder & familie",
|
||||
"ambient": "ambient",
|
||||
"funk-disco": "funk & disco",
|
||||
"jazz": "jazz",
|
||||
"soul": "soul",
|
||||
"speedcore": "speedcore",
|
||||
"punk": "punk",
|
||||
"rb": "r&b",
|
||||
"holiday": "urlaub",
|
||||
"vocaloid": "vocaloid",
|
||||
"j-rock": "j-rock",
|
||||
"trance": "trance",
|
||||
"drum-and-bass": "drum & bass",
|
||||
"comedy-meme": "komödie & meme",
|
||||
"instrumental": "instrumental",
|
||||
"hardcore": "hardcore",
|
||||
"k-pop": "k-pop",
|
||||
"indie": "indie",
|
||||
"techno": "techno",
|
||||
"house": "house",
|
||||
"video-game-soundtrack": "videospiel",
|
||||
"tv-movie-soundtrack": "TV & film",
|
||||
"alternative": "alternativ",
|
||||
"dubstep": "dubstep",
|
||||
"metal": "metal",
|
||||
"anime": "anime",
|
||||
"hip-hop-rap": "hip hop & rap",
|
||||
"j-pop": "j-pop",
|
||||
"rock": "rock",
|
||||
"pop": "pop",
|
||||
"electronic": "elektronisch",
|
||||
"classical-orchestral": "Klassisch & Orchestral"
|
||||
"dance": "Tanz",
|
||||
"swing": "Swing",
|
||||
"nightcore": "Nightcore",
|
||||
"folk": "Folk",
|
||||
"family": "Familie",
|
||||
"ambient": "umgebung",
|
||||
"funk": "Funk",
|
||||
"jazz": "Jazz",
|
||||
"soul": "Soul",
|
||||
"speedcore": "Speedcore",
|
||||
"punk": "Punk",
|
||||
"rb": "R&B",
|
||||
"holiday": "Urlaub",
|
||||
"vocaloid": "Vokaloid",
|
||||
"j-rock": "J-Rock",
|
||||
"trance": "Trance",
|
||||
"drumbass": "Basstrommel",
|
||||
"comedy": "Komödie",
|
||||
"instrumental": "Instrumental",
|
||||
"hardcore": "Hardcore",
|
||||
"k-pop": "K-Pop",
|
||||
"indie": "Indie",
|
||||
"techno": "Techno",
|
||||
"house": "House",
|
||||
"game": "Videospiele",
|
||||
"film": "Filme",
|
||||
"alt": "Alternativ",
|
||||
"dubstep": "Dubstep",
|
||||
"metal": "Metal",
|
||||
"anime": "Anime",
|
||||
"hiphop": "HipHop",
|
||||
"j-pop": "J-Pop",
|
||||
"rock": "Rock",
|
||||
"pop": "Pop",
|
||||
"electronic": "Elektronisch",
|
||||
"classical-orchestral": "Klassisch & Orchestra"
|
||||
},
|
||||
"map-specificities": {
|
||||
"automapper": "KI",
|
||||
@@ -997,6 +963,10 @@
|
||||
"go-to-mods": "Gehe zu Mods",
|
||||
"not-remind": "Erinnere mich nicht"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "Gebrochene Modelle",
|
||||
"desc": "Seit dem Update der Beat Saber Engine sind alle benutzerdefinierten Modellmods defekt und müssen aktualisiert werden. Sie wurden noch nicht aktualisiert."
|
||||
},
|
||||
"export-success": {
|
||||
"title": "Export abgeschlossen 🎉"
|
||||
}
|
||||
@@ -1028,6 +998,122 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "Fehler beim Erstellen der Playlist",
|
||||
"error-playlist-creation-desc": "Beim Erstellen der Playlist ist ein Fehler aufgetreten.",
|
||||
"playlist-created-title": "Playlist erstellt",
|
||||
"playlist-created-desc": "Die Playlist wurde erfolgreich erstellt. Sie können jetzt ihre Karten synchronisieren!",
|
||||
"download-playlist": "Playlist herunterladen",
|
||||
"synchronize-playlist": "Playlist synchronisieren",
|
||||
"synchronize-maps": "Karten synchronisieren",
|
||||
"error-playlists-synchronization-title": "Fehler bei der Synchronisierung der Playlists",
|
||||
"error-playlists-synchronization-desc": "Bei der Synchronisierung der Playlists ist ein Fehler aufgetreten.",
|
||||
"playlists-synchronized-title": "Playlists synchronisiert!",
|
||||
"playlists-synchronized-desc": "Playlists und ihre Karten wurden heruntergeladen.",
|
||||
"playlists-export-error-title": "Fehler beim Exportieren der Playlists",
|
||||
"playlists-export-error-desc": "Beim Exportieren der Playlists ist ein Fehler aufgetreten.",
|
||||
"playlists-exported-title": "Playlists exportiert!",
|
||||
"playlists-exported-desc": "Playlists wurden erfolgreich exportiert.",
|
||||
"playlists-with-maps-exported-desc": "Playlists und ihre Karten wurden erfolgreich exportiert.",
|
||||
"playlist-delete-error-title": "Fehler beim Löschen der Playlist",
|
||||
"playlist-delete-error-desc": "Beim Löschen der Playlist ist ein Fehler aufgetreten.",
|
||||
"playlists-deleted-title": "Playlists gelöscht!",
|
||||
"playlists-deleted-desc": "Playlists wurden erfolgreich gelöscht.",
|
||||
"edit-playlist": "Playlist bearbeiten",
|
||||
"playlist-edit-error-title": "Fehler beim Bearbeiten der Playlist",
|
||||
"playlist-edit-error-desc": "Beim Bearbeiten der Playlist ist ein Fehler aufgetreten.",
|
||||
"playlist-edited-title": "Playlist bearbeitet!",
|
||||
"playlist-edited-desc": "Die Playlist wurde erfolgreich geändert. Sie können jetzt ihre Karten synchronisieren!",
|
||||
"playlists-loading": "Playlists werden geladen...",
|
||||
"no-playlists": "Keine Playlists",
|
||||
"download-playlists": "Playlists herunterladen",
|
||||
"created-by": "Erstellt von",
|
||||
"stop-download": "Download stoppen",
|
||||
"cancel-download": "Download abbrechen",
|
||||
"open-file": "Datei öffnen",
|
||||
"link-playlists": "Playlists verknüpfen",
|
||||
"link-playlist-desc": "Das Verknüpfen von Playlists ermöglicht das Teilen von Playlists zwischen allen Versionen. Nach der Verknüpfung profitiert diese Version von geteilten Playlists",
|
||||
"link-playlist-info": "Das Hinzufügen und Löschen von Playlists wird ebenfalls geteilt",
|
||||
"keep-playlists": "Playlists behalten",
|
||||
"keep-playlists-tip": "Wenn Sie Playlists behalten, werden die Playlists von der aktuellen Version in den Ordner für geteilte Playlists verschoben. Andernfalls gehen sie verloren",
|
||||
"unlink-playlists": "Playlists trennen",
|
||||
"unlink-playlist-desc": "Achtung, das Trennen von Playlists verhindert die Nutzung geteilter Playlists für diese Version.",
|
||||
"unlink-keep-playlists-tip": "Wenn Sie Playlists behalten, wird eine Kopie der geteilten Playlists für die aktuelle Version erstellt. Andernfalls werden keine Playlists für diese Version behalten.",
|
||||
"delete-playlist-ask": "Playlist löschen?",
|
||||
"delete-playlists-ask": "Playlists löschen?",
|
||||
"delete-playlist-desc": "Sind Sie sicher, dass Sie die Playlist \"{playlistTitle}\" löschen möchten?",
|
||||
"delete-playlists-desc": "Sind Sie sicher, dass Sie {nb} Playlists löschen möchten?",
|
||||
"delete-maps": "Karten löschen",
|
||||
"delete-playlist-maps-tip": "Wenn aktiviert, werden alle Karten in der Playlist gelöscht",
|
||||
"delete-playlists-maps-tip": "Wenn aktiviert, werden alle Karten in den Playlists gelöscht",
|
||||
"export-playlist-ask": "Playlist exportieren?",
|
||||
"export-playlists-ask": "Playlists exportieren?",
|
||||
"export-playlist-desc": "Sind Sie sicher, dass Sie die Playlist \"{playlistTitle}\" exportieren möchten?",
|
||||
"export-playlists-desc": "Sind Sie sicher, dass Sie {nb} Playlists exportieren möchten?",
|
||||
"export-maps": "Karten exportieren",
|
||||
"export-playlist-maps-tip": "Wenn aktiviert, werden auch alle Karten in der Playlist exportiert",
|
||||
"export-playlists-maps-tip": "Wenn aktiviert, werden auch alle Karten in den Playlists exportiert",
|
||||
"export": "Exportieren",
|
||||
"need-clone-title": "Warnung",
|
||||
"need-clone-desc-1": "Diese Playlist wurde von einer externen Seite heruntergeladen und enthält einen Synchronisierungslink.",
|
||||
"need-clone-desc-2": "Um Ihre Änderungen während der Synchronisierung nicht zu verlieren, wird die Playlist dupliziert und ihr Synchronisierungslink entfernt.",
|
||||
"need-clone-desc-3": "Sie können dann, wenn Sie möchten, die ursprüngliche Playlist löschen.",
|
||||
"understood": "Ich verstehe",
|
||||
"synchronize-playlist-ask": "Playlist synchronisieren?",
|
||||
"synchronize-playlists-ask": "Playlists synchronisieren?",
|
||||
"synchronize-playlist-desc": "Sind Sie sicher, dass Sie die Playlist \"{playlistTitle}\" synchronisieren möchten?",
|
||||
"synchronize-playlists-desc": "Sind Sie sicher, dass Sie {nb} Playlists synchronisieren möchten?",
|
||||
"synchronize-playlist-tip": "Diese Aktion aktualisiert Playlists und lädt fehlende Karten herunter; es kann mehrere Minuten dauern.",
|
||||
"synchronize": "Synchronisieren",
|
||||
"curated": "Empfohlen",
|
||||
"verified-mapper": "Verifizierter Mapper",
|
||||
"empty-playlists": "Leere Playlists",
|
||||
"search-playlist": "Nach einer Playlist suchen",
|
||||
"no-playlists-found": "Keine Playlists gefunden",
|
||||
"error-occur-while-loading-playlists": "Beim Laden der Playlists ist ein Fehler aufgetreten",
|
||||
"error-occur-while-loading-playlist": "Beim Laden der Playlist ist ein Fehler aufgetreten",
|
||||
"loading-maps": "Karten werden geladen...",
|
||||
"no-maps-found-for-playlist": "Keine Karten für diese Playlist gefunden",
|
||||
"playlist-contain-no-maps": "Die Playlist enthält keine Karten",
|
||||
"no-map-installed-for-playlist": "Keine Karten für diese Playlist installiert",
|
||||
"playlist-is-waiting-to-download": "Die Playlist wartet auf den Download",
|
||||
"download-maps": "Karten herunterladen",
|
||||
"download-missing-maps": "Fehlende Karten herunterladen",
|
||||
"playlist-is-downloading": "Die Playlist wird heruntergeladen",
|
||||
"some-playlist-maps-are-missing": "Einige Karten in dieser Playlist fehlen",
|
||||
"create-a-playlist": "Eine Playlist erstellen",
|
||||
"synchronize-playlists": "Playlists synchronisieren",
|
||||
"export-playlists": "Playlists exportieren",
|
||||
"delete-playlists": "Playlists löschen",
|
||||
"choose-image": "Bild auswählen",
|
||||
"title": "Titel",
|
||||
"playlist-title": "Playlist-Titel",
|
||||
"description": "Beschreibung",
|
||||
"playlist-description": "Playlist-Beschreibung",
|
||||
"author": "Autor",
|
||||
"playlist-author": "Playlist-Autor",
|
||||
"save": "Speichern",
|
||||
"loading": "Wird geladen...",
|
||||
"installed": "Installiert",
|
||||
"no-map-found": "Keine Karte gefunden",
|
||||
"edit-playlist-shortcuts": "Halten Sie Shift oder Strg gedrückt, um mehrere Karten auszuwählen",
|
||||
"add-to-playlist": "Zur Playlist hinzufügen",
|
||||
"remove-from-playlist": "Aus Playlist entfernen",
|
||||
"playlist-is-empty": "Die Playlist ist leer",
|
||||
"continue": "Fortfahren",
|
||||
"nb-maps": "Anzahl der Karten",
|
||||
"nb-mappers": "Anzahl der Mapper",
|
||||
"duration": "Dauer",
|
||||
"nps": "Noten pro Sekunde",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "Startdatum — Enddatum",
|
||||
"all": "Alle",
|
||||
"last-24h": "Letzte 24h",
|
||||
"last-week": "Letzte Woche",
|
||||
"last-month": "Letzter Monat",
|
||||
"3-last-month": "Letzte 3 Monate"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
|
||||
"monthNames": ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "Refuse",
|
||||
"apply": "Apply",
|
||||
"copy": "Copy",
|
||||
"copied": "Copied!",
|
||||
"confirm": "Confirm",
|
||||
"choose-folder": "Choose folder",
|
||||
"unknown": "An unknown error occurred ¯\\_(ツ)_/¯",
|
||||
"warning": "Warning",
|
||||
"continue": "Continue"
|
||||
"copied": "Copied!"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "Add a version",
|
||||
@@ -38,7 +33,6 @@
|
||||
"desktop-description": "First Person Flying Controller mode allows you to use WASD and the mouse to navigate around the menu in game. This makes testing much easier, because you don't have to put on your headset!",
|
||||
"debug": "Debug Mode",
|
||||
"debug-description": "Enables the output log window for IPA. This will show the debug console that mods use.",
|
||||
"outdated-tippy": "This version is outdated, and some mods or features may no longer work as expected. Prefer using the recommended version ({recommendedVersion}) of Beat Saber to enjoy the latest features and bugfixes.",
|
||||
"advanced-launch": {
|
||||
"button": "Advanced launch",
|
||||
"placeholder": "Additional arguments ex: --revert; --nowait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "Latest",
|
||||
"description": "Description",
|
||||
"dropdown": {
|
||||
"uninstall-all": "Uninstall all",
|
||||
"unselect-all": "Unselect all"
|
||||
"uninstall-all": "Uninstall all"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,6 +134,11 @@
|
||||
"description": "Change the default folder for Beat Saber versions and other upcoming features.",
|
||||
"choose-folder": "Choose folder"
|
||||
},
|
||||
"proton-path": {
|
||||
"title": "Proton path",
|
||||
"description": "Change the path to the Proton binary",
|
||||
"choose-file": "Choose file"
|
||||
},
|
||||
"additional-content": {
|
||||
"title": "Additional content",
|
||||
"description": "Additional content that allows you to customize Beat Saber!",
|
||||
@@ -197,6 +195,10 @@
|
||||
"report-bug": "Report a bug",
|
||||
"open-logs": "Open logs"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 Check Out the Changelog!",
|
||||
"not-founds": "😕 Oops, No Changelog Here!"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +243,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": ".NET 8 Required"
|
||||
},
|
||||
"msg": {
|
||||
"401": "Steam doesn't seem to want to let us download Beat Saber 😢",
|
||||
"404": "Unable to contact Steam servers.",
|
||||
@@ -266,11 +265,7 @@
|
||||
"LicenceError": "Unable to get the list of licenses.",
|
||||
"RateLimitExceeded": "You've tried too many times, wait a while and try again later.",
|
||||
"TokenRejected": "Your login token has been rejected 😕 Please try again.",
|
||||
"AccessDenied": "Access to Steam has been denied.",
|
||||
"dotnet-required": ".NET 8 Runtime must be installed in order to download a version of Beat Saber. Download it by clicking the button below."
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": "Download .NET 8"
|
||||
"AccessDenied": "Access to Steam has been denied."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -386,9 +381,9 @@
|
||||
"OCULUS_NOT_RUNNING": "Oculus is not running",
|
||||
"BS_ALREADY_RUNNING": "Beat Saber already running",
|
||||
"EXE_NOT_FINDED": "Missing files",
|
||||
"PROTON_NOT_SET": "Proton path not set",
|
||||
"EXIT": "Abrupt stop",
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculus library not found",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Original Oculus version not found"
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculus library not found"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "An unknown error has occurred.",
|
||||
@@ -398,9 +393,7 @@
|
||||
"EXE_NOT_FINDED": "Some files seem to be missing, try to verify the files.",
|
||||
"EXIT": "BeatSaber stopped abruptly, tries to check the files.",
|
||||
"OCULUS_LIB_NOT_FOUND": "Check that the Oculus application is properly installed, and that the libraries are correctly defined in Oculus.",
|
||||
"PROTON_NOT_SET": "Set the Proton path in settings.",
|
||||
"PROTON_NOT_FOUND": "Set the Proton path in settings.",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Beat Saber must be installed from the Oculus app before opening."
|
||||
"PROTON_NOT_SET": "Set the Proton path in settings"
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "Launch Steam"
|
||||
@@ -492,16 +485,6 @@
|
||||
"title": "Backup created",
|
||||
"msg": "Sharing the 'UserData' folder can generate errors, in case of problems unlink the folder to restore the backup"
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "Error while linking folder",
|
||||
"msg": {
|
||||
"EPERM": "BSManager does not have the necessary permissions to link the folder.",
|
||||
"EACCES": "BSManager does not have the necessary permissions to link the folder.",
|
||||
"ENOSPC": "The disk is full, make some space and try again.",
|
||||
"UNKNOWN_ERROR":"An unknown error has occurred while linking the folder.",
|
||||
"LinkingNotSupported": "Folder linking is not supported on this file system."
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
@@ -512,14 +495,6 @@
|
||||
"error": {
|
||||
"msg": "An error occurred while creating the shortcut."
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "Version Outdated",
|
||||
"msg": "This Beat Saber version is outdated, use the recommended version to enjoy the latest features and bugfixes",
|
||||
"actions": {
|
||||
"do-not-remind": "Do not remind me",
|
||||
"ok": "Ok"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -579,8 +554,8 @@
|
||||
},
|
||||
"steam-credentials": {
|
||||
"title": "Steam Credentials",
|
||||
"p-1": "The credentials are only used to download the game because steam need to verify that you paid the game in order to be allowed to download it. They aren't saved and directly passed to DepotDownloader. If you don't want to enter your credentials you can follow this tutorial :",
|
||||
"p-2": "and then click on the gear icon in the top right corner and select \"Import a version\", select the folder where beat saber has been downloaded (If you follow the tutorial above you should have the correct location)"
|
||||
"p-1": "Your Steam credentials are only required to download versions of Beat Saber, we use DepotDownloader to achieve this which requires your Steam credentials to verify that you own the game within your library before allowing you to retrieve the game files, your credentials are not stored or saved and are passed directly to DepotDownloader. However, if you don't want to do that, you can follow this tutorial instead: ",
|
||||
"p-2": "Afterwards you can click on the gear icon in the top right corner and select \"Import a version\", then you can select the folder where Beat Saber was downloaded to. (If you followed the tutorial, you will have the right location)"
|
||||
},
|
||||
"bs-import-version": {
|
||||
"title": "Import a version",
|
||||
@@ -719,12 +694,13 @@
|
||||
"stay": "Remember me",
|
||||
"connect-to-meta": "Connect to Meta"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Enable Sideloading",
|
||||
"info-1": "In order to launch Beat Saber, the ability to run sideloaded apps must be enabled. BSManager will request administrator rights to enable this feature automatically.",
|
||||
"info-2": "The sideloaded apps feature allows launching games located outside your Oculus library folder.",
|
||||
"info-3": "After sideloading is activated, the feature will remain active, and you will no longer be prompted to enable it.",
|
||||
"i-want-to-do-it-myself": "I want to do it myself",
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Warning",
|
||||
"body": {
|
||||
"must-be-installed-once": "You must have installed Beat Saber at least once from the Oculus Store, otherwise Beat Saber might automatically close after launching.",
|
||||
"will-backup": "To launch this version, the original installation folder of Beat Saber located in your Oculus library will be renamed and will be automatically restored when Beat Saber is closed."
|
||||
},
|
||||
"not-remind-me": "Do not remind me",
|
||||
"understood": "Understood"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
@@ -754,9 +730,6 @@
|
||||
},
|
||||
"launch-as-admin": "Launch as Administrator",
|
||||
"not-remind-me": "Do not remind me"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "The version {outdatedVersion} is outdated, and some mods or features may no longer work as expected. Please download the latest recommended version ({recommendedVersion}) of Beat Saber to enjoy the latest features and bugfixes."
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -772,7 +745,7 @@
|
||||
"accuracy": "accuracy",
|
||||
"balanced": "balanced",
|
||||
"challenge": "challenge",
|
||||
"dance-style": "dance",
|
||||
"dancestyle": "dance",
|
||||
"fitness": "fitness",
|
||||
"speed": "speed",
|
||||
"tech": "tech"
|
||||
@@ -781,10 +754,10 @@
|
||||
"dance": "dance",
|
||||
"swing": "swing",
|
||||
"nightcore": "nightcore",
|
||||
"folk-acoustic": "folk & acoustic",
|
||||
"kids-family": "kids & family",
|
||||
"folk": "folk",
|
||||
"family": "family",
|
||||
"ambient": "ambient",
|
||||
"funk-disco": "funk & disco",
|
||||
"funk": "funk",
|
||||
"jazz": "jazz",
|
||||
"soul": "soul",
|
||||
"speedcore": "speedcore",
|
||||
@@ -794,21 +767,21 @@
|
||||
"vocaloid": "vocaloid",
|
||||
"j-rock": "j-rock",
|
||||
"trance": "trance",
|
||||
"drum-and-bass": "drum & bass",
|
||||
"comedy-meme": "comedy & meme",
|
||||
"drumbass": "drum & bass",
|
||||
"comedy": "comedy",
|
||||
"instrumental": "instrumental",
|
||||
"hardcore": "hardcore",
|
||||
"k-pop": "k-pop",
|
||||
"indie": "indie",
|
||||
"techno": "techno",
|
||||
"house": "house",
|
||||
"video-game-soundtrack": "video game",
|
||||
"tv-movie-soundtrack": "TV & film",
|
||||
"alternative": "alternative",
|
||||
"game": "video game",
|
||||
"film": "film",
|
||||
"alt": "alternative",
|
||||
"dubstep": "dubstep",
|
||||
"metal": "metal",
|
||||
"anime": "anime",
|
||||
"hip-hop-rap": "hip hop & rap",
|
||||
"hiphop": "hiphop",
|
||||
"j-pop": "j-pop",
|
||||
"rock": "rock",
|
||||
"pop": "pop",
|
||||
@@ -997,6 +970,10 @@
|
||||
"go-to-mods": "Go to mods",
|
||||
"not-remind": "Don't remind me"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "Broken models",
|
||||
"desc": "Since the Beat Saber engine update, all custom model mods have broken and need to be updated. They have not been updated yet."
|
||||
},
|
||||
"export-success": {
|
||||
"title": "Export completed 🎉"
|
||||
}
|
||||
@@ -1028,6 +1005,122 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "Error creating playlist",
|
||||
"error-playlist-creation-desc": "An error occurred while creating the playlist.",
|
||||
"playlist-created-title": "Playlist created",
|
||||
"playlist-created-desc": "The playlist has been successfully created. You can now sync its maps!",
|
||||
"download-playlist": "Download playlist",
|
||||
"synchronize-playlist": "Synchronize playlist",
|
||||
"synchronize-maps": "Synchronize maps",
|
||||
"error-playlists-synchronization-title": "Error synchronizing playlists",
|
||||
"error-playlists-synchronization-desc": "An error occurred while synchronizing playlists.",
|
||||
"playlists-synchronized-title": "Playlists synchronized!",
|
||||
"playlists-synchronized-desc": "Playlists and their maps have been downloaded.",
|
||||
"playlists-export-error-title": "Error exporting playlists",
|
||||
"playlists-export-error-desc": "An error occurred while exporting playlists.",
|
||||
"playlists-exported-title": "Playlists exported!",
|
||||
"playlists-exported-desc": "Playlists have been successfully exported.",
|
||||
"playlists-with-maps-exported-desc": "Playlists and their maps have been successfully exported.",
|
||||
"playlist-delete-error-title": "Error deleting playlist",
|
||||
"playlist-delete-error-desc": "An error occurred while deleting the playlist.",
|
||||
"playlists-deleted-title": "Playlists deleted!",
|
||||
"playlists-deleted-desc": "Playlists have been successfully deleted.",
|
||||
"edit-playlist": "Edit playlist",
|
||||
"playlist-edit-error-title": "Error editing playlist",
|
||||
"playlist-edit-error-desc": "An error occurred while editing the playlist.",
|
||||
"playlist-edited-title": "Playlist edited!",
|
||||
"playlist-edited-desc": "The playlist has been successfully modified. You can now sync its maps!",
|
||||
"playlists-loading": "Loading playlists...",
|
||||
"no-playlists": "No playlists",
|
||||
"download-playlists": "Download playlists",
|
||||
"created-by": "Created by",
|
||||
"stop-download": "Stop download",
|
||||
"cancel-download": "Cancel download",
|
||||
"open-file": "Open file",
|
||||
"link-playlists": "Link playlists",
|
||||
"link-playlist-desc": "Linking playlists allows sharing playlists between all versions. Once linked, this version will benefit from shared playlists",
|
||||
"link-playlist-info": "Adding and deleting playlists will also be shared",
|
||||
"keep-playlists": "Keep playlists",
|
||||
"keep-playlists-tip": "Keeping playlists will move the playlists from the current version to the shared playlists folder. Otherwise, they will be lost",
|
||||
"unlink-playlists": "Unlink playlists",
|
||||
"unlink-playlist-desc": "Warning, unlinking playlists will no longer allow the use of shared playlists for this version.",
|
||||
"unlink-keep-playlists-tip": "Keeping playlists will create a copy of shared playlists for the current version. Otherwise, no playlists will be kept for this version.",
|
||||
"delete-playlist-ask": "Delete playlist?",
|
||||
"delete-playlists-ask": "Delete playlists?",
|
||||
"delete-playlist-desc": "Are you sure you want to delete the playlist \"{playlistTitle}\"?",
|
||||
"delete-playlists-desc": "Are you sure you want to delete {nb} playlists?",
|
||||
"delete-maps": "Delete maps",
|
||||
"delete-playlist-maps-tip": "If enabled, all maps in the playlist will be deleted",
|
||||
"delete-playlists-maps-tip": "If enabled, all maps in the playlists will be deleted",
|
||||
"export-playlist-ask": "Export playlist?",
|
||||
"export-playlists-ask": "Export playlists?",
|
||||
"export-playlist-desc": "Are you sure you want to export the playlist \"{playlistTitle}\"?",
|
||||
"export-playlists-desc": "Are you sure you want to export {nb} playlists?",
|
||||
"export-maps": "Export maps",
|
||||
"export-playlist-maps-tip": "If enabled, all maps in the playlist will also be exported",
|
||||
"export-playlists-maps-tip": "If enabled, all maps in the playlists will also be exported",
|
||||
"export": "Export",
|
||||
"need-clone-title": "Warning",
|
||||
"need-clone-desc-1": "This playlist has been downloaded from an external site and contains a synchronization link.",
|
||||
"need-clone-desc-2": "To avoid losing your changes during synchronization, the playlist will be duplicated and its synchronization link removed.",
|
||||
"need-clone-desc-3": "You can then, if you wish, delete the original playlist.",
|
||||
"understood": "I understand",
|
||||
"synchronize-playlist-ask": "Synchronize playlist?",
|
||||
"synchronize-playlists-ask": "Synchronize playlists?",
|
||||
"synchronize-playlist-desc": "Are you sure you want to synchronize the playlist \"{playlistTitle}\"?",
|
||||
"synchronize-playlists-desc": "Are you sure you want to synchronize {nb} playlists?",
|
||||
"synchronize-playlist-tip": "This action updates playlists and downloads missing maps; it may take several minutes.",
|
||||
"synchronize": "Synchronize",
|
||||
"curated": "Recommended",
|
||||
"verified-mapper": "Verified mapper",
|
||||
"empty-playlists": "Empty playlists",
|
||||
"search-playlist": "Search for a playlist",
|
||||
"no-playlists-found": "No playlists found",
|
||||
"error-occur-while-loading-playlists": "An error occurred while loading playlists",
|
||||
"error-occur-while-loading-playlist": "An error occurred while loading the playlist",
|
||||
"loading-maps": "Loading maps...",
|
||||
"no-maps-found-for-playlist": "No maps found for this playlist",
|
||||
"playlist-contain-no-maps": "The playlist contains no maps",
|
||||
"no-map-installed-for-playlist": "No maps installed for this playlist",
|
||||
"playlist-is-waiting-to-download": "The playlist is waiting to download",
|
||||
"download-maps": "Download maps",
|
||||
"download-missing-maps": "Download missing maps",
|
||||
"playlist-is-downloading": "The playlist is downloading",
|
||||
"some-playlist-maps-are-missing": "Some maps in this playlist are missing",
|
||||
"create-a-playlist": "Create a playlist",
|
||||
"synchronize-playlists": "Synchronize playlists",
|
||||
"export-playlists": "Export playlists",
|
||||
"delete-playlists": "Delete playlists",
|
||||
"choose-image": "Choose an image",
|
||||
"title": "Title",
|
||||
"playlist-title": "Playlist title",
|
||||
"description": "Description",
|
||||
"playlist-description": "Playlist description",
|
||||
"author": "Author",
|
||||
"playlist-author": "Playlist author",
|
||||
"save": "Save",
|
||||
"loading": "Loading...",
|
||||
"installed": "Installed",
|
||||
"no-map-found": "No map found",
|
||||
"edit-playlist-shortcuts": "Hold Shift or Ctrl to select multiple maps",
|
||||
"add-to-playlist": "Add to playlist",
|
||||
"remove-from-playlist": "Remove from playlist",
|
||||
"playlist-is-empty": "The playlist is empty",
|
||||
"continue": "Continue",
|
||||
"nb-maps": "Number of maps",
|
||||
"nb-mappers": "Number of mappers",
|
||||
"duration": "Duration",
|
||||
"nps": "Notes per second",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "Start date — End date",
|
||||
"all": "All",
|
||||
"last-24h": "Last 24h",
|
||||
"last-week": "Last week",
|
||||
"last-month": "Last month",
|
||||
"3-last-month": "Last 3 months"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
||||
"monthNames": ["Jan", "Feb", "Mar", "Apr", "May", "June", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "Rechazar",
|
||||
"apply": "Aplicar",
|
||||
"copy": "Copiar",
|
||||
"copied": "¡Copiado!",
|
||||
"confirm": "Confirmar",
|
||||
"choose-folder": "Elige la carpeta",
|
||||
"unknown": "Se ha producido un error desconocido ¯\\_(ツ)_/¯",
|
||||
"warning": "Advertencia",
|
||||
"continue": "Continuar"
|
||||
"copied": "¡Copiado!"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "Agregar una versión",
|
||||
@@ -38,7 +33,6 @@
|
||||
"desktop-description": "El modo FPFC te permite usar WASD y el mouse para navegar por el menú en juego. Esto hace que las pruebas sean mucho más fáciles, ¡porque no tienes que ponerte las gafas VR!",
|
||||
"debug": "Modo Depuración",
|
||||
"debug-description": "Habilita la ventana de registro de salida para IPA. Esto mostrará la consola de depuración que usan los mods.",
|
||||
"outdated-tippy": "Esta versión está desactualizada, y algunos mods o funciones pueden no funcionar como se espera. Es mejor usar la versión recomendada ({recommendedVersion}) de Beat Saber para disfrutar de las últimas características y correcciones.",
|
||||
"advanced-launch": {
|
||||
"button": "Opciones avanzadas",
|
||||
"placeholder": "Argumentos adicionales ej: --revert; --no-wait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "Último",
|
||||
"description": "Descripción",
|
||||
"dropdown": {
|
||||
"uninstall-all": "Desinstalar todos",
|
||||
"unselect-all": "Deseleccionar todo"
|
||||
"uninstall-all": "Desinstalar todos"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +190,10 @@
|
||||
"report-bug": "Informar de un error",
|
||||
"open-logs": "Abrir los registros"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 ¡Descubre lo nuevo en el Changelog!",
|
||||
"not-founds": "😕 Uy, ¡Changelog no encontrado!"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +238,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": ".NET 8 Requerido"
|
||||
},
|
||||
"msg": {
|
||||
"401": "Parece que Steam no quiere dejarnos descargar Beat Saber 😢",
|
||||
"404": "No se puede contactar con los servidores de Steam",
|
||||
@@ -266,11 +260,7 @@
|
||||
"LicenceError": "No se puede obtener la lista de licencias.",
|
||||
"RateLimitExceeded": "Lo has intentado demasiadas veces, espera un poco y vuelve a intentarlo más tarde.",
|
||||
"TokenRejected": "Tu token de inicio de sesión ha sido rechazada 😕 Por favor, inténtalo de nuevo.",
|
||||
"AccessDenied": "El acceso a Steam ha sido denegado.",
|
||||
"dotnet-required": "Se debe instalar el tiempo de ejecución de .NET 8 para descargar una versión de Beat Saber. Descárgalo haciendo clic en el botón de abajo."
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": "Descargar .NET 8"
|
||||
"AccessDenied": "El acceso a Steam ha sido denegado."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -387,8 +377,7 @@
|
||||
"BS_ALREADY_RUNNING": "Beat Saber ya está en marcha",
|
||||
"EXE_NOT_FINDED": "Archivos no encontrados",
|
||||
"EXIT": "Parada abrupta",
|
||||
"OCULUS_LIB_NOT_FOUND": "Librería Oculus no encontrada",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "No se encontró la versión original de Oculus"
|
||||
"OCULUS_LIB_NOT_FOUND": "Librería Oculus no encontrada"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "Se ha producido un error desconocido.",
|
||||
@@ -397,10 +386,7 @@
|
||||
"BS_ALREADY_RUNNING": "Cierra Beat Saber antes de volver a iniciarlo.",
|
||||
"EXE_NOT_FINDED": "Parece que faltan algunos archivos, intenta verificar los archivos.",
|
||||
"EXIT": "Beat Saber se detuvo abruptamente, trata de verificar los archivos.",
|
||||
"OCULUS_LIB_NOT_FOUND": "Verifica que la aplicación Oculus esté correctamente instalada y que las librerías estén bien definidas en Oculus.",
|
||||
"PROTON_NOT_SET": "Establece la ruta de Proton en la configuración.",
|
||||
"PROTON_NOT_FOUND": "Establece la ruta de Proton en la configuración.",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Beat Saber debe instalarse desde la aplicación de Oculus antes de abrirlo."
|
||||
"OCULUS_LIB_NOT_FOUND": "Verifica que la aplicación Oculus esté correctamente instalada y que las librerías estén bien definidas en Oculus."
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "Iniciar Steam"
|
||||
@@ -492,16 +478,6 @@
|
||||
"title": "Backup creado",
|
||||
"msg": "Compartir la carpeta 'UserData' puede generar errores, en caso de problemas desvincula la carpeta para restaurar la copia de seguridad"
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "Error al enlazar la carpeta",
|
||||
"msg": {
|
||||
"EPERM": "BSManager no tiene los permisos necesarios para enlazar la carpeta.",
|
||||
"EACCES": "BSManager no tiene los permisos necesarios para enlazar la carpeta.",
|
||||
"ENOSPC": "El disco está lleno, libera espacio e inténtalo de nuevo.",
|
||||
"LinkingNotSupported": "El enlace de carpetas no es compatible con este sistema de archivos.",
|
||||
"UNKNOWN_ERROR": "Se ha producido un error desconocido al enlazar la carpeta."
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
@@ -512,14 +488,6 @@
|
||||
"error": {
|
||||
"msg": "Se produjo un error al crear el acceso directo."
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "Versión desactualizada",
|
||||
"msg": "Esta versión de Beat Saber está desactualizada. Usa la versión recomendada para disfrutar de las últimas características y correcciones.",
|
||||
"actions": {
|
||||
"do-not-remind": "No volver a recordármelo",
|
||||
"ok": "Ok"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -719,12 +687,13 @@
|
||||
"stay": "Recuérdame",
|
||||
"connect-to-meta": "Conectarse a Meta"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Habilitar Sideloading",
|
||||
"info-1": "Para poder iniciar Beat Saber, se debe habilitar la capacidad de ejecutar aplicaciones en sideloading. BSManager solicitará permisos de administrador para habilitar esta función automáticamente.",
|
||||
"info-2": "La función de sideloading permite iniciar juegos ubicados fuera de la carpeta de la biblioteca de Oculus.",
|
||||
"info-3": "Una vez que se active el sideloading, la función permanecerá activa y ya no se le pedirá que la habilite.",
|
||||
"i-want-to-do-it-myself": "Quiero hacerlo yo mismo",
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Atención",
|
||||
"body": {
|
||||
"must-be-installed-once": "Debes haber instalado Beat Saber al menos una vez desde la Oculus Store, de lo contrario, Beat Saber podría cerrarse automáticamente después de iniciar.",
|
||||
"will-backup": "Para lanzar esta versión, la carpeta de instalación original de Beat Saber ubicada en tu biblioteca de Oculus será renombrada y se restaurará automáticamente al cerrar Beat Saber."
|
||||
},
|
||||
"not-remind-me": "No volver a recordármelo",
|
||||
"understood": "Entendido"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
@@ -754,9 +723,6 @@
|
||||
},
|
||||
"launch-as-admin": "Iniciar como Administrador",
|
||||
"not-remind-me": "No volver a recordármelo"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "La versión {outdatedVersion} está obsoleta, y algunos mods o funciones pueden no funcionar como se espera. Por favor, descarga la última versión recomendada ({recommendedVersion}) de Beat Saber para disfrutar de las últimas funciones y correcciones de errores."
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -772,19 +738,19 @@
|
||||
"accuracy": "precisión",
|
||||
"balanced": "equilibrado",
|
||||
"challenge": "desafío",
|
||||
"dance-style": "baile",
|
||||
"dancestyle": "baile",
|
||||
"fitness": "fitness",
|
||||
"speed": "speed",
|
||||
"tech": "tech"
|
||||
},
|
||||
"map-styles": {
|
||||
"dance": "danza",
|
||||
"dance": "baile",
|
||||
"swing": "swing",
|
||||
"nightcore": "nightcore",
|
||||
"folk-acoustic": "folk & acústico",
|
||||
"kids-family": "niños & familia",
|
||||
"ambient": "ambiental",
|
||||
"funk-disco": "funk & disco",
|
||||
"folk": "folk",
|
||||
"family": "familia",
|
||||
"ambient": "ambiente",
|
||||
"funk": "funk",
|
||||
"jazz": "jazz",
|
||||
"soul": "soul",
|
||||
"speedcore": "speedcore",
|
||||
@@ -794,26 +760,26 @@
|
||||
"vocaloid": "vocaloid",
|
||||
"j-rock": "j-rock",
|
||||
"trance": "trance",
|
||||
"drum-and-bass": "drum & bass",
|
||||
"comedy-meme": "comedia & meme",
|
||||
"drumbass": "drum & bass",
|
||||
"comedy": "comedia",
|
||||
"instrumental": "instrumental",
|
||||
"hardcore": "hardcore",
|
||||
"k-pop": "k-pop",
|
||||
"indie": "indie",
|
||||
"techno": "techno",
|
||||
"techno": "tecno",
|
||||
"house": "house",
|
||||
"video-game-soundtrack": "videojuego",
|
||||
"tv-movie-soundtrack": "TV & cine",
|
||||
"alternative": "alternativo",
|
||||
"game": "videojuego",
|
||||
"film": "film",
|
||||
"alt": "alternativa",
|
||||
"dubstep": "dubstep",
|
||||
"metal": "metal",
|
||||
"anime": "anime",
|
||||
"hip-hop-rap": "hip hop & rap",
|
||||
"hiphop": "hiphop",
|
||||
"j-pop": "j-pop",
|
||||
"rock": "rock",
|
||||
"pop": "pop",
|
||||
"electronic": "electrónica",
|
||||
"classical-orchestral": "Clásica & Orquestal"
|
||||
"electronic": "electrónico",
|
||||
"classical-orchestral": "Clásico y orquestal"
|
||||
},
|
||||
"map-specificities": {
|
||||
"automapper": "IA",
|
||||
@@ -997,6 +963,10 @@
|
||||
"go-to-mods": "Ir a mods",
|
||||
"not-remind": "No volver a recordarme"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "Modelos rotos",
|
||||
"desc": "Desde la actualización del motor de Beat Saber, todos los mods de modelos personalizados se han roto y necesitan ser actualizados. Todavía no han sido actualizados."
|
||||
},
|
||||
"export-success": {
|
||||
"title": "Exportación completada 🎉"
|
||||
}
|
||||
@@ -1028,6 +998,122 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "Error al crear la lista de reproducción",
|
||||
"error-playlist-creation-desc": "Ocurrió un error al crear la lista de reproducción.",
|
||||
"playlist-created-title": "Lista de reproducción creada",
|
||||
"playlist-created-desc": "La lista de reproducción se ha creado con éxito. ¡Ahora puedes sincronizar sus mapas!",
|
||||
"download-playlist": "Descargar lista de reproducción",
|
||||
"synchronize-playlist": "Sincronizar lista de reproducción",
|
||||
"synchronize-maps": "Sincronizar mapas",
|
||||
"error-playlists-synchronization-title": "Error al sincronizar listas de reproducción",
|
||||
"error-playlists-synchronization-desc": "Ocurrió un error al sincronizar las listas de reproducción.",
|
||||
"playlists-synchronized-title": "¡Listas de reproducción sincronizadas!",
|
||||
"playlists-synchronized-desc": "Las listas de reproducción y sus mapas han sido descargados.",
|
||||
"playlists-export-error-title": "Error al exportar listas de reproducción",
|
||||
"playlists-export-error-desc": "Ocurrió un error al exportar las listas de reproducción.",
|
||||
"playlists-exported-title": "¡Listas de reproducción exportadas!",
|
||||
"playlists-exported-desc": "Las listas de reproducción se han exportado con éxito.",
|
||||
"playlists-with-maps-exported-desc": "Las listas de reproducción y sus mapas se han exportado con éxito.",
|
||||
"playlist-delete-error-title": "Error al eliminar la lista de reproducción",
|
||||
"playlist-delete-error-desc": "Ocurrió un error al eliminar la lista de reproducción.",
|
||||
"playlists-deleted-title": "¡Listas de reproducción eliminadas!",
|
||||
"playlists-deleted-desc": "Las listas de reproducción se han eliminado con éxito.",
|
||||
"edit-playlist": "Editar lista de reproducción",
|
||||
"playlist-edit-error-title": "Error al editar la lista de reproducción",
|
||||
"playlist-edit-error-desc": "Ocurrió un error al editar la lista de reproducción.",
|
||||
"playlist-edited-title": "¡Lista de reproducción editada!",
|
||||
"playlist-edited-desc": "La lista de reproducción se ha modificado con éxito. ¡Ahora puedes sincronizar sus mapas!",
|
||||
"playlists-loading": "Cargando listas de reproducción...",
|
||||
"no-playlists": "No hay listas de reproducción",
|
||||
"download-playlists": "Descargar listas de reproducción",
|
||||
"created-by": "Creado por",
|
||||
"stop-download": "Detener descarga",
|
||||
"cancel-download": "Cancelar descarga",
|
||||
"open-file": "Abrir archivo",
|
||||
"link-playlists": "Vincular listas de reproducción",
|
||||
"link-playlist-desc": "Vincular listas de reproducción permite compartirlas entre todas las versiones. Una vez vinculada, esta versión se beneficiará de las listas de reproducción compartidas",
|
||||
"link-playlist-info": "Añadir y eliminar listas de reproducción también se compartirá",
|
||||
"keep-playlists": "Mantener listas de reproducción",
|
||||
"keep-playlists-tip": "Mantener las listas de reproducción moverá las listas de la versión actual a la carpeta de listas compartidas. De lo contrario, se perderán",
|
||||
"unlink-playlists": "Desvincular listas de reproducción",
|
||||
"unlink-playlist-desc": "Advertencia, desvincular las listas de reproducción ya no permitirá el uso de listas compartidas para esta versión.",
|
||||
"unlink-keep-playlists-tip": "Mantener las listas de reproducción creará una copia de las listas compartidas para la versión actual. De lo contrario, no se mantendrán listas para esta versión.",
|
||||
"delete-playlist-ask": "¿Eliminar lista de reproducción?",
|
||||
"delete-playlists-ask": "¿Eliminar listas de reproducción?",
|
||||
"delete-playlist-desc": "¿Estás seguro de que quieres eliminar la lista de reproducción \"{playlistTitle}\"?",
|
||||
"delete-playlists-desc": "¿Estás seguro de que quieres eliminar {nb} listas de reproducción?",
|
||||
"delete-maps": "Eliminar mapas",
|
||||
"delete-playlist-maps-tip": "Si está activado, se eliminarán todos los mapas de la lista de reproducción",
|
||||
"delete-playlists-maps-tip": "Si está activado, se eliminarán todos los mapas de las listas de reproducción",
|
||||
"export-playlist-ask": "¿Exportar lista de reproducción?",
|
||||
"export-playlists-ask": "¿Exportar listas de reproducción?",
|
||||
"export-playlist-desc": "¿Estás seguro de que quieres exportar la lista de reproducción \"{playlistTitle}\"?",
|
||||
"export-playlists-desc": "¿Estás seguro de que quieres exportar {nb} listas de reproducción?",
|
||||
"export-maps": "Exportar mapas",
|
||||
"export-playlist-maps-tip": "Si está activado, también se exportarán todos los mapas de la lista de reproducción",
|
||||
"export-playlists-maps-tip": "Si está activado, también se exportarán todos los mapas de las listas de reproducción",
|
||||
"export": "Exportar",
|
||||
"need-clone-title": "Advertencia",
|
||||
"need-clone-desc-1": "Esta lista de reproducción se ha descargado de un sitio externo y contiene un enlace de sincronización.",
|
||||
"need-clone-desc-2": "Para evitar perder tus cambios durante la sincronización, la lista de reproducción se duplicará y se eliminará su enlace de sincronización.",
|
||||
"need-clone-desc-3": "Luego puedes, si lo deseas, eliminar la lista de reproducción original.",
|
||||
"understood": "Entendido",
|
||||
"synchronize-playlist-ask": "¿Sincronizar lista de reproducción?",
|
||||
"synchronize-playlists-ask": "¿Sincronizar listas de reproducción?",
|
||||
"synchronize-playlist-desc": "¿Estás seguro de que quieres sincronizar la lista de reproducción \"{playlistTitle}\"?",
|
||||
"synchronize-playlists-desc": "¿Estás seguro de que quieres sincronizar {nb} listas de reproducción?",
|
||||
"synchronize-playlist-tip": "Esta acción actualiza las listas de reproducción y descarga los mapas faltantes; puede tardar varios minutos.",
|
||||
"synchronize": "Sincronizar",
|
||||
"curated": "Recomendado",
|
||||
"verified-mapper": "Mapeador verificado",
|
||||
"empty-playlists": "Listas de reproducción vacías",
|
||||
"search-playlist": "Buscar una lista de reproducción",
|
||||
"no-playlists-found": "No se encontraron listas de reproducción",
|
||||
"error-occur-while-loading-playlists": "Ocurrió un error al cargar las listas de reproducción",
|
||||
"error-occur-while-loading-playlist": "Ocurrió un error al cargar la lista de reproducción",
|
||||
"loading-maps": "Cargando mapas...",
|
||||
"no-maps-found-for-playlist": "No se encontraron mapas para esta lista de reproducción",
|
||||
"playlist-contain-no-maps": "La lista de reproducción no contiene mapas",
|
||||
"no-map-installed-for-playlist": "No hay mapas instalados para esta lista de reproducción",
|
||||
"playlist-is-waiting-to-download": "La lista de reproducción está esperando para descargar",
|
||||
"download-maps": "Descargar mapas",
|
||||
"download-missing-maps": "Descargar mapas faltantes",
|
||||
"playlist-is-downloading": "La lista de reproducción se está descargando",
|
||||
"some-playlist-maps-are-missing": "Faltan algunos mapas en esta lista de reproducción",
|
||||
"create-a-playlist": "Crear una lista de reproducción",
|
||||
"synchronize-playlists": "Sincronizar listas de reproducción",
|
||||
"export-playlists": "Exportar listas de reproducción",
|
||||
"delete-playlists": "Eliminar listas de reproducción",
|
||||
"choose-image": "Elegir una imagen",
|
||||
"title": "Título",
|
||||
"playlist-title": "Título de la lista de reproducción",
|
||||
"description": "Descripción",
|
||||
"playlist-description": "Descripción de la lista de reproducción",
|
||||
"author": "Autor",
|
||||
"playlist-author": "Autor de la lista de reproducción",
|
||||
"save": "Guardar",
|
||||
"loading": "Cargando...",
|
||||
"installed": "Instalado",
|
||||
"no-map-found": "No se encontró ningún mapa",
|
||||
"edit-playlist-shortcuts": "Mantén presionado Shift o Ctrl para seleccionar múltiples mapas",
|
||||
"add-to-playlist": "Añadir a la lista de reproducción",
|
||||
"remove-from-playlist": "Quitar de la lista de reproducción",
|
||||
"playlist-is-empty": "La lista de reproducción está vacía",
|
||||
"continue": "Continuar",
|
||||
"nb-maps": "Número de mapas",
|
||||
"nb-mappers": "Número de mapeadores",
|
||||
"duration": "Duración",
|
||||
"nps": "Notas por segundo",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "Fecha de inicio — Fecha de fin",
|
||||
"all": "Todo",
|
||||
"last-24h": "Últimas 24h",
|
||||
"last-week": "Última semana",
|
||||
"last-month": "Último mes",
|
||||
"3-last-month": "Últimos 3 meses"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"],
|
||||
"monthNames": ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic", "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "Refuser",
|
||||
"apply": "Appliquer",
|
||||
"copy": "Copier",
|
||||
"copied": "Copié !",
|
||||
"confirm": "Confirmer",
|
||||
"choose-folder": "Choisir un dossier",
|
||||
"unknown": "Une erreur inconnue s'est produite ¯\\_(ツ)_/¯",
|
||||
"warning": "Attention",
|
||||
"continue": "Continuer"
|
||||
"copied": "Copié !"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "Ajouter une version",
|
||||
@@ -38,7 +33,6 @@
|
||||
"desktop-description": "Cela vous permet d'utiliser WASD et la souris pour naviguer dans le menu en jeu. Cela rend les tests beaucoup plus faciles, car vous n'avez pas à mettre votre casque!",
|
||||
"debug": "Mode Debug",
|
||||
"debug-description": "Active la fenêtre de log pour IPA. Cela affichera la console de débogage utilisée par les mods.",
|
||||
"outdated-tippy": "Cette version est obsolète et certains mods ou fonctionnalités peuvent ne plus fonctionner comme prévu. Préférez utiliser la version recommandée ({recommendedVersion}) de Beat Saber pour profiter des dernières fonctionnalités et correctifs.",
|
||||
"advanced-launch": {
|
||||
"button": "Lancement avancé",
|
||||
"placeholder": "Arguments supplémentaires ex: --revert; --nowait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "Récent",
|
||||
"description": "Description",
|
||||
"dropdown": {
|
||||
"uninstall-all": "Tout désinstaller",
|
||||
"unselect-all": "Tout désélectionner"
|
||||
"uninstall-all": "Tout désinstaller"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +190,10 @@
|
||||
"report-bug": "Signaler un bug",
|
||||
"open-logs": "Ouvrir les logs"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 Jetez un œil au Changelog !",
|
||||
"not-founds": "😕 Oups, Changelog introuvable !"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +238,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": ".NET 8 Requis"
|
||||
},
|
||||
"msg": {
|
||||
"401": "Steam ne semble pas vouloir nous laisser télécharger Beat Saber 😢",
|
||||
"404": "Impossible de contacter les serveurs de Steam.",
|
||||
@@ -266,11 +260,7 @@
|
||||
"LicenceError": "Impossible d'obtenir la liste des licences.",
|
||||
"RateLimitExceeded": "Tu as essayé trop de fois attends un peu et recommence plus tard.",
|
||||
"TokenRejected": "Votre token de connexion a été rejeté 😕 Veuillez réessayer.",
|
||||
"AccessDenied": "L'accès à Steam a été refusé.",
|
||||
"dotnet-required": ".NET 8 Runtime doit être installé pour pouvoir télécharger une version de Beat Saber. Télécharge-le en cliquant sur le bouton ci-dessous."
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": "Télécharger .NET 8"
|
||||
"AccessDenied": "L'accès à Steam a été refusé."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -387,8 +377,7 @@
|
||||
"BS_ALREADY_RUNNING": "Beat Saber est déjà lancé",
|
||||
"EXE_NOT_FINDED": "Fichiers manquants",
|
||||
"EXIT": "Arrêt brutal",
|
||||
"OCULUS_LIB_NOT_FOUND": "Librairie Oculus introuvable",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Version originale Oculus non trouvée"
|
||||
"OCULUS_LIB_NOT_FOUND": "Librairie Oculus introuvable"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "Une erreur inconnue s'est produite.",
|
||||
@@ -397,10 +386,7 @@
|
||||
"BS_ALREADY_RUNNING": "Ferme Beat Saber avant de le lancer à nouveau.",
|
||||
"EXE_NOT_FINDED": "Quelques fichiers semblent manquants. Essaye de vérifier les fichiers.",
|
||||
"EXIT": "Beat Saber s'est arrêté brusquement, essaye de vérifier les fichiers.",
|
||||
"OCULUS_LIB_NOT_FOUND": "Vérifie que l'application Oculus est correctement installée, et que les librairies sont bien définies dans Oculus.",
|
||||
"PROTON_NOT_SET": "Définissez le chemin de Proton dans les paramètres.",
|
||||
"PROTON_NOT_FOUND": "Définissez le chemin de Proton dans les paramètres.",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Beat Saber doit être installé depuis l'application Oculus avant de l'ouvrir."
|
||||
"OCULUS_LIB_NOT_FOUND": "Vérifie que l'application Oculus est correctement installée, et que les librairies sont bien définies dans Oculus."
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "Lancer Steam"
|
||||
@@ -492,18 +478,7 @@
|
||||
"title": "Sauvegarde créée",
|
||||
"msg": "Le partage du dossier 'UserData' peut générer des erreurs, en cas de soucis déliez le dossier pour restaurer la sauvegarde"
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "Erreur lors de la liaison du dossier",
|
||||
"msg": {
|
||||
"EPERM": "BSManager n'a pas les autorisations nécessaires pour lier le dossier.",
|
||||
"EACCES": "BSManager n'a pas les autorisations nécessaires pour lier le dossier.",
|
||||
"ENOSPC": "Le disque est plein, faites de la place et réessayez.",
|
||||
"LinkingNotSupported": "La liaison de dossier n'est pas supportée sur ce système de fichiers.",
|
||||
"UNKNOWN_ERROR": "Une erreur inconnue est survenue lors de la liaison du dossier."
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
"success": {
|
||||
@@ -513,14 +488,6 @@
|
||||
"error": {
|
||||
"msg": "Une erreur s'est produite lors de la création du raccourci."
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "Version obsolète",
|
||||
"msg": "Cette version de Beat Saber est obsolète. Utilisez la version recommandée pour profiter des dernières fonctionnalités et correctifs.",
|
||||
"actions": {
|
||||
"do-not-remind": "Ne plus me rappeler",
|
||||
"ok": "Ok"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -704,7 +671,7 @@
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
"title": "Créer un raccourci",
|
||||
"desc": "Créer un raccourci te permettra de démarrer Beat Saber avec les options choisies sans passer par BSManager.",
|
||||
"desc": "Créer un raccourci te permettra de démarrer Beat Saber avec les options choisi sans passé par BSManager.",
|
||||
"launch-options": "Options de lancement",
|
||||
"advanced-launch": "Lancement avancé",
|
||||
"valid-btn": "Créer le raccourci"
|
||||
@@ -720,12 +687,13 @@
|
||||
"stay": "Se souvenir de moi",
|
||||
"connect-to-meta": "Se connecter à Meta"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Activer le sideloading",
|
||||
"info-1": "Pour lancer Beat Saber, la possibilité d'exécuter des applications en sideloading doit être activée. BSManager demandera les droits administrateur pour activer cette fonctionnalité automatiquement.",
|
||||
"info-2": "La fonctionnalité de sideloading permet de lancer des jeux situés en dehors de votre dossier de bibliothèque Oculus.",
|
||||
"info-3": "Une fois le sideloading activé, la fonctionnalité restera active et vous ne serez plus invité à l’activer.",
|
||||
"i-want-to-do-it-myself": "Je veux le faire moi-même",
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Attention",
|
||||
"body": {
|
||||
"must-be-installed-once": "Vous devez avoir installé au moins une fois Beat Saber depuis l'Oculus Store, sinon Beat Saber pourrait se fermer automatiquement après son lancement.",
|
||||
"will-backup": "Afin de lancer cette version, le dossier d'installation original de Beat Saber se trouvant dans votre bibliothèque Oculus va être renommé et sera automatiquement restauré à l'arrêt de Beat Saber."
|
||||
},
|
||||
"not-remind-me": "Ne plus me rappeler",
|
||||
"understood": "J'ai compris"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
@@ -755,9 +723,6 @@
|
||||
},
|
||||
"launch-as-admin": "Lancer en administateur",
|
||||
"not-remind-me": "Ne plus me rappeler"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "La version {outdatedVersion} est obsolète, et certains mods ou fonctionnalités peuvent ne plus fonctionner comme prévu. Veuillez télécharger la dernière version recommandée ({recommendedVersion}) de Beat Saber pour profiter des dernières fonctionnalités et corrections de bugs."
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -773,48 +738,48 @@
|
||||
"accuracy": "précision",
|
||||
"balanced": "équilibrée",
|
||||
"challenge": "challenge",
|
||||
"dance-style": "dance",
|
||||
"dancestyle": "dance",
|
||||
"fitness": "fitness",
|
||||
"speed": "vitesse",
|
||||
"tech": "tech"
|
||||
},
|
||||
"map-styles": {
|
||||
"dance": "danse",
|
||||
"dance": "dance",
|
||||
"swing": "swing",
|
||||
"nightcore": "nightcore",
|
||||
"folk-acoustic": "folk & acoustique",
|
||||
"kids-family": "enfants & famille",
|
||||
"ambient": "ambiant",
|
||||
"funk-disco": "funk & disco",
|
||||
"folk": "folk",
|
||||
"family": "famille",
|
||||
"ambient": "ambiante",
|
||||
"funk": "funk",
|
||||
"jazz": "jazz",
|
||||
"soul": "soul",
|
||||
"speedcore": "speedcore",
|
||||
"punk": "punk",
|
||||
"rb": "r&b",
|
||||
"holiday": "vacances",
|
||||
"holiday": "vacance",
|
||||
"vocaloid": "vocaloid",
|
||||
"j-rock": "j-rock",
|
||||
"trance": "trance",
|
||||
"drum-and-bass": "drum & bass",
|
||||
"comedy-meme": "comédie & meme",
|
||||
"drumbass": "drum & bass",
|
||||
"comedy": "comédie",
|
||||
"instrumental": "instrumental",
|
||||
"hardcore": "hardcore",
|
||||
"k-pop": "k-pop",
|
||||
"indie": "indie",
|
||||
"indie": "indé",
|
||||
"techno": "techno",
|
||||
"house": "house",
|
||||
"video-game-soundtrack": "jeu vidéo",
|
||||
"tv-movie-soundtrack": "TV & film",
|
||||
"alternative": "alternatif",
|
||||
"game": "jeu vidéo",
|
||||
"film": "film",
|
||||
"alt": "alternative",
|
||||
"dubstep": "dubstep",
|
||||
"metal": "métal",
|
||||
"metal": "metal",
|
||||
"anime": "anime",
|
||||
"hip-hop-rap": "hip hop & rap",
|
||||
"hiphop": "hiphop",
|
||||
"j-pop": "j-pop",
|
||||
"rock": "rock",
|
||||
"pop": "pop",
|
||||
"electronic": "électronique",
|
||||
"classical-orchestral": "Classique & Orchestral"
|
||||
"classical-orchestral": "classique & orchestrale"
|
||||
},
|
||||
"map-specificities": {
|
||||
"automapper": "IA",
|
||||
@@ -841,7 +806,8 @@
|
||||
"bsr-code" : "Code BSR",
|
||||
"download" : "Télécharger la carte",
|
||||
"downloading" :"Téléchargement de la carte",
|
||||
"cancel-download" : "Annuler le téléchargement"
|
||||
"cancel-download" : "Annuler le téléchargement",
|
||||
"hightlight-difficulty" : "Surligner la difficulté"
|
||||
}
|
||||
},
|
||||
"models": {
|
||||
@@ -998,6 +964,10 @@
|
||||
"go-to-mods": "Aller aux mods",
|
||||
"not-remind": "Ne plus me rappeler"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "Modèles cassés",
|
||||
"desc": "Depuis la mise à jour du moteur Beat Saber, tous les mods de modèles personnalisés ne sont plus fonctionnels et doivent être mis à jour. Ils n'ont pas encore été mis à jour."
|
||||
},
|
||||
"export-success": {
|
||||
"title": "Export terminé 🎉"
|
||||
}
|
||||
@@ -1029,6 +999,122 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "Erreur lors de la création de la playlist",
|
||||
"error-playlist-creation-desc": "Une erreur est survenue lors de la création de la playlist.",
|
||||
"playlist-created-title": "Playlist créée",
|
||||
"playlist-created-desc": "La playlist a été créée avec succès. Tu peut maintenant synchroniser ses maps !",
|
||||
"download-playlist": "Télécharger la playlist",
|
||||
"synchronize-playlist": "Synchroniser la playlist",
|
||||
"synchronize-maps": "Synchroniser les maps",
|
||||
"error-playlists-synchronization-title": "Erreur lors de la synchronisation des playlists",
|
||||
"error-playlists-synchronization-desc": "Une erreur est survenue lors de la synchronisation des playlists.",
|
||||
"playlists-synchronized-title": "Playlists synchronisées !",
|
||||
"playlists-synchronized-desc": "Les playlists et leurs maps ont été téléchargées.",
|
||||
"playlists-export-error-title": "Erreur lors de l'exportation des playlists",
|
||||
"playlists-export-error-desc": "Une erreur est survenue lors de l'exportation des playlists.",
|
||||
"playlists-exported-title": "Playlists exportées !",
|
||||
"playlists-exported-desc": "Les playlists ont été exportées avec succès.",
|
||||
"playlists-with-maps-exported-desc": "Les playlists et leurs maps ont été exportées avec succès.",
|
||||
"playlist-delete-error-title": "Erreur lors de la suppression de la playlist",
|
||||
"playlist-delete-error-desc": "Une erreur est survenue lors de la suppression de la playlist.",
|
||||
"playlists-deleted-title": "Playlists supprimées !",
|
||||
"playlists-deleted-desc": "Les playlists ont été supprimées avec succès.",
|
||||
"edit-playlist": "Éditer la playlist",
|
||||
"playlist-edit-error-title": "Erreur lors de l'édition de la playlist",
|
||||
"playlist-edit-error-desc": "Une erreur est survenue lors de l'édition de la playlist.",
|
||||
"playlist-edited-title": "Playlist éditée !",
|
||||
"playlist-edited-desc": "La playlist a été modifiée avec succès. Tu peut maintenant synchroniser ses maps !",
|
||||
"playlists-loading": "Chargement des playlist...",
|
||||
"no-playlists": "Aucune playlist",
|
||||
"download-playlists": "Télécharger des playlists",
|
||||
"created-by": "Créée par",
|
||||
"stop-download": "Arrêter le téléchargement",
|
||||
"cancel-download": "Annuler le téléchargement",
|
||||
"open-file": "Ouvrir le fichier",
|
||||
"link-playlists": "Lier les playlists",
|
||||
"link-playlist-desc": "La liaison des playlists permet de partager les playlists entre toute les version. Une fois liée, cette version profitera des playlists partagées",
|
||||
"link-playlist-info": "L'ajout et la suppression de playlists sera également partagé",
|
||||
"keep-playlists": "Conserver les playlists",
|
||||
"keep-playlists-tip": "Conserver les playlists déplacera les playlists de la version actuelle dans le dossier des playlists partagées. Dans le cas contraire elles seront perdues",
|
||||
"unlink-playlists": "Délier les playlists",
|
||||
"unlink-playlist-desc": "Attention, délier les playlists ne permettra plus l'utilisation des playlists paratagées pour cette version.",
|
||||
"unlink-keep-playlists-tip": "Conserver les playlists créera une copie des playlists partagées pour la version actuelle. Dans le cas contraire, aucune playlist ne sera conservée pour cette version.",
|
||||
"delete-playlist-ask": "Supprimer la playlist ?",
|
||||
"delete-playlists-ask": "Supprimer les playlists ?",
|
||||
"delete-playlist-desc": "Es-tu sur de vouloir supprimer la playlist \"{playlistTitle}\" ?",
|
||||
"delete-playlists-desc": "Es-tu sur de vouloir supprimer {nb} playlists ?",
|
||||
"delete-maps": "Supprimer les maps",
|
||||
"delete-playlist-maps-tip": "Si activé, toutes les maps de la playlist seront supprimées",
|
||||
"delete-playlists-maps-tip": "Si activé, toutes les maps des playlists seront supprimées",
|
||||
"export-playlist-ask": "Exporter la playlist ?",
|
||||
"export-playlists-ask": "Exporter les playlists ?",
|
||||
"export-playlist-desc": "Es-tu sur de vouloir exporter la playlist \"{playlistTitle}\" ?",
|
||||
"export-playlists-desc": "Es-tu sur de vouloir exporter les {nb} playlists ?",
|
||||
"export-maps": "Exporter les maps",
|
||||
"export-playlist-maps-tip": "Si activé, toutes les maps de la playlist seront également exportées",
|
||||
"export-playlists-maps-tip": "Si activé, toutes les maps des playlists seront également exportées",
|
||||
"export": "Exporter",
|
||||
"need-clone-title": "Attention",
|
||||
"need-clone-desc-1": "Cette playlist a été téléchargée depuis un site externe et contient un lien de synchronisation.",
|
||||
"need-clone-desc-2": "Pour éviter de perdre vos modifications lors d'une synchronisation, la playlist va être dupliquée et son lien de synchronisation supprimé.",
|
||||
"need-clone-desc-3": "Vous pourrez ensuite, si vous le souhaitez, supprimer la playlist originale.",
|
||||
"understood": "J'ai compris",
|
||||
"synchronize-playlist-ask": "Synchroniser la playlist ?",
|
||||
"synchronize-playlists-ask": "Synchroniser les playlists ?",
|
||||
"synchronize-playlist-desc": "Es-tu sur de vouloir synchroniser la playlist \"{playlistTitle}\" ?",
|
||||
"synchronize-playlists-desc": "Es-tu sur de vouloir synchroniser les {nb} playlists ?",
|
||||
"synchronize-playlist-tip": "Cette action met à jour les playlists et télécharge les maps manquantes; cela peut durer plusieurs minutes.",
|
||||
"synchronize": "Synchroniser",
|
||||
"curated": "Recommandée",
|
||||
"verified-mapper": "Mapper vérifié",
|
||||
"empty-playlists": "Playlists vides",
|
||||
"search-playlist": "Rechercher une playlist",
|
||||
"no-playlists-found": "Aucune playlists trouvées",
|
||||
"error-occur-while-loading-playlists": "Une erreur est survenue lors du chargement des playlists",
|
||||
"error-occur-while-loading-playlist": "Une erreur est survenue lors du chargement de la playlist",
|
||||
"loading-maps":"Chargement des maps...",
|
||||
"no-maps-found-for-playlist":"Aucune map trouvée pour cette playlist",
|
||||
"playlist-contain-no-maps":"La playlist ne contient aucune map",
|
||||
"no-map-installed-for-playlist":"Aucune map installée pour cette playlist",
|
||||
"playlist-is-waiting-to-download":"La playlist est en attente de téléchargment",
|
||||
"download-maps": "Télécharger les maps",
|
||||
"download-missing-maps": "Télécharger les maps manquantes",
|
||||
"playlist-is-downloading":"La playlist est en cours de téléchargement",
|
||||
"some-playlist-maps-are-missing":"Certaines maps de cette playlist sont manquantes",
|
||||
"create-a-playlist": "Créer une playlist",
|
||||
"synchronize-playlists": "Synchroniser les playlists",
|
||||
"export-playlists": "Exporter les playlists",
|
||||
"delete-playlists": "Supprimer les playlists",
|
||||
"choose-image": "Choisir une image",
|
||||
"title": "Titre",
|
||||
"playlist-title": "Titre de la playlist",
|
||||
"description": "Description",
|
||||
"playlist-description": "Description de la playlist",
|
||||
"author": "Auteur",
|
||||
"playlist-author": "Auteur de la playlist",
|
||||
"save": "Enregistrer",
|
||||
"loading": "Chargement...",
|
||||
"installed": "Installée",
|
||||
"no-map-found": "Aucune map trouvée",
|
||||
"edit-playlist-shortcuts": "Maintenez Maj ou Ctrl pour sélectionner plusieurs maps",
|
||||
"add-to-playlist": "Ajouter à la playlist",
|
||||
"remove-from-playlist": "Retirer de la playlist",
|
||||
"playlist-is-empty": "La playlist est vide",
|
||||
"continue": "Continuer",
|
||||
"nb-maps": "Nombre de maps",
|
||||
"nb-mappers": "Nombre de mappers",
|
||||
"duration": "Durée",
|
||||
"nps": "Notes par secondes",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "Date début — Date fin",
|
||||
"all": "Tout",
|
||||
"last-24h": "Dernières 24h",
|
||||
"last-week": "Dernière semaine",
|
||||
"last-month": "Dernier mois",
|
||||
"3-last-month": "3 derniers mois"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
|
||||
"monthNames": ["Jan", "Fév", "Mar", "Avr", "Mai", "Jun", "Juil", "Aou", "Sept", "Oct", "Nov", "Déc", "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "拒否する",
|
||||
"apply": "適用",
|
||||
"copy": "コピー",
|
||||
"copied": "コピー済み!",
|
||||
"confirm": "確認",
|
||||
"choose-folder": "フォルダーを選択",
|
||||
"unknown": "不明なエラーが発生しました (´・ω・`)",
|
||||
"warning": "警告",
|
||||
"continue": "続ける"
|
||||
"copied": "コピー済み!"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "バージョンを追加",
|
||||
@@ -38,7 +33,6 @@
|
||||
"desktop-description": "ファーストパーソン・フライング・コントローラー・モードでは、WASDとマウスを使ってゲーム内のメニューを操作できます。ヘッドセットを装着する必要がないので、テストがより簡単になります!",
|
||||
"debug": "デバックモード",
|
||||
"debug-description": "IPAの出力ログウィンドウを有効にします。これはMODのデバッグコンソールを表示します。",
|
||||
"outdated-tippy": "このバージョンは古いため、一部のMODや機能が期待通りに動作しない可能性があります。最新の機能やバグ修正を楽しむには、推奨バージョン ({recommendedVersion}) のBeat Saberを使用することをお勧めします。",
|
||||
"advanced-launch": {
|
||||
"button": "高度な起動",
|
||||
"placeholder": "追加引数 例:--revert; --nowait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "最新",
|
||||
"description": "說明",
|
||||
"dropdown": {
|
||||
"uninstall-all": "全てアンインストールする",
|
||||
"unselect-all": "すべて選択解除"
|
||||
"uninstall-all": "全てアンインストールする"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +190,10 @@
|
||||
"report-bug": "バグを報告",
|
||||
"open-logs": "ログを表示"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 チェンジログを覗いてみて!",
|
||||
"not-founds": "😕 あれ、チェンジログが見当たらない!"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +238,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": ".NET 8が必要です!"
|
||||
},
|
||||
"msg": {
|
||||
"401": "SteamがBeat Saberのダウンロードを許可してくれないようだ。😢",
|
||||
"404": "Steamサーバーに接続できません。",
|
||||
@@ -266,11 +260,7 @@
|
||||
"LicenceError": "ライセンスリストを取得できません。",
|
||||
"RateLimitExceeded": "何度も試しているのでしばらくたって、もう一度お試しください。",
|
||||
"TokenRejected": "ログイントークンが拒否されました 😕 もう一度お試しください。",
|
||||
"AccessDenied": "Steamへのアクセスが拒否されました。",
|
||||
"dotnet-required": "Beat Saberをダウンロードするには、.NET 8 Runtimeがインストールされている必要があります。下のボタンをクリックしてダウンロードしてください。"
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": ".NET 8をダウンロード"
|
||||
"AccessDenied": "Steamへのアクセスが拒否されました。"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -387,8 +377,7 @@
|
||||
"BS_ALREADY_RUNNING": "Beat Saberはすでに起動しています",
|
||||
"EXE_NOT_FINDED": "ファイルが見つかりません",
|
||||
"EXIT": "緊急停止",
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculusライブラリが見つかりません",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "オリジナルのOculusバージョンが見つかりませんでした"
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculusライブラリが見つかりません"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "不明なエラーが発生しました。",
|
||||
@@ -397,10 +386,7 @@
|
||||
"BS_ALREADY_RUNNING": "再度起動する前にBeatSaberを閉じてください。",
|
||||
"EXE_NOT_FINDED": "いくつかのファイルが見つからないようです。",
|
||||
"EXIT": "BeatSaberが緊急停止したため、ファイルをチェックします。",
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculusアプリケーションが正しくインストールしていることと、Oculusライブラリが正しく定義されていることを確認してください。",
|
||||
"PROTON_NOT_SET": "設定でProtonのパスを設定してください。",
|
||||
"PROTON_NOT_FOUND": "設定でProtonのパスを設定してください。",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Beat Saberは、開く前にOculusアプリからインストールする必要があります。"
|
||||
"OCULUS_LIB_NOT_FOUND": "Oculusアプリケーションが正しくインストールしていることと、Oculusライブラリが正しく定義されていることを確認してください。"
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "Steamを起動"
|
||||
@@ -492,16 +478,6 @@
|
||||
"title": "バックアップを作成しました",
|
||||
"msg": "'UserData'フォルダを共有するとエラーが発生する可能性があります。問題が発生した場合は、フォルダをリンク解除してバックアップを復元してください。"
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "フォルダのリンク中にエラーが発生しました",
|
||||
"msg": {
|
||||
"EPERM": "BSManagerにはフォルダをリンクするための必要な権限がありません。",
|
||||
"EACCES": "BSManagerにはフォルダをリンクするための必要な権限がありません。",
|
||||
"ENOSPC": "ディスクがいっぱいです。空き容量を作ってもう一度試してください。",
|
||||
"LinkingNotSupported": "このファイルシステムではフォルダのリンクはサポートされていません。",
|
||||
"UNKNOWN_ERROR": "フォルダをリンク中に不明なエラーが発生しました。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
@@ -512,14 +488,6 @@
|
||||
"error": {
|
||||
"msg": "ショートカットの作成中にエラーが発生しました。"
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "バージョンが古い",
|
||||
"msg": "このBeat Saberのバージョンは古いため、推奨バージョンを使用して最新の機能やバグ修正をお楽しみください。",
|
||||
"actions": {
|
||||
"do-not-remind": "再度通知しない",
|
||||
"ok": "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -719,13 +687,14 @@
|
||||
"stay": "記憶する",
|
||||
"connect-to-meta": "Metaに接続する"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "サイドローディングを有効化",
|
||||
"info-1": "Beat Saberを起動するには、サイドローディングアプリを実行する機能を有効にする必要があります。BSManagerは、この機能を自動的に有効にするために管理者権限を要求します。",
|
||||
"info-2": "サイドローディング機能により、Oculusライブラリフォルダ外にあるゲームを起動できます。",
|
||||
"info-3": "サイドローディングを有効化すると、この機能はアクティブなままとなり、再度有効化を求められることはありません。",
|
||||
"i-want-to-do-it-myself": "自分でやりたい",
|
||||
"understood": "了解しました"
|
||||
"original-version-backup-oculus": {
|
||||
"title": "注意",
|
||||
"body": {
|
||||
"must-be-installed-once": "少なくとも一度はOculus StoreからBeat Saberをインストールしている必要があります。そうしないとBeat Saberは起動後に自動的に終了する可能性があります。",
|
||||
"will-backup": "このバージョンを起動するために、OculusライブラリにあるBeat Saberの元のインストールフォルダは名前が変更され、Beat Saberの終了時に自動的に復元されます。"
|
||||
},
|
||||
"not-remind-me": "二度と表示しないでください",
|
||||
"understood": "分かった"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Oculusトークン",
|
||||
@@ -754,9 +723,6 @@
|
||||
},
|
||||
"launch-as-admin": "管理者として起動",
|
||||
"not-remind-me": "Больше не напоминать"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "バージョン {outdatedVersion} は古いため、一部のモッドや機能が期待通りに動作しない場合があります。最新の機能やバグ修正を楽しむために、推奨される最新バージョンの Beat Saber ({recommendedVersion}) をダウンロードしてください。"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -781,39 +747,39 @@
|
||||
"dance": "ダンス",
|
||||
"swing": "スウィング",
|
||||
"nightcore": "ナイトコア",
|
||||
"folk-acoustic": "フォーク & アコースティック",
|
||||
"kids-family": "キッズ & ファミリー",
|
||||
"folk": "フォーク",
|
||||
"family": "ファミリー",
|
||||
"ambient": "アンビエント",
|
||||
"funk-disco": "ファンク & ディスコ",
|
||||
"funk": "ファンク",
|
||||
"jazz": "ジャズ",
|
||||
"soul": "ソウル",
|
||||
"speedcore": "スピードコア",
|
||||
"speedcore": "スピードコア ",
|
||||
"punk": "パンク",
|
||||
"rb": "r&b",
|
||||
"holiday": "ホリデー",
|
||||
"holiday": "休日",
|
||||
"vocaloid": "ボーカロイド",
|
||||
"j-rock": "J-ロック",
|
||||
"j-rock": "j-rock",
|
||||
"trance": "トランス",
|
||||
"drum-and-bass": "ドラム & ベース",
|
||||
"comedy-meme": "コメディ & ミーム",
|
||||
"instrumental": "インストゥルメンタル",
|
||||
"drumbass": "ドラムンベース",
|
||||
"comedy": "コメディ",
|
||||
"instrumental": "器楽",
|
||||
"hardcore": "ハードコア",
|
||||
"k-pop": "k-pop",
|
||||
"indie": "インディー",
|
||||
"techno": "テクノ",
|
||||
"house": "ハウス",
|
||||
"video-game-soundtrack": "ゲーム音楽",
|
||||
"tv-movie-soundtrack": "TV & 映画",
|
||||
"alternative": "オルタナティブ",
|
||||
"house": "家",
|
||||
"game": "ビデオゲーム",
|
||||
"film": "映画音楽",
|
||||
"alt": "オルタナティヴ",
|
||||
"dubstep": "ダブステップ",
|
||||
"metal": "メタル",
|
||||
"anime": "アニメ",
|
||||
"hip-hop-rap": "ヒップホップ & ラップ",
|
||||
"j-pop": "J-ポップ",
|
||||
"hiphop": "ヒップポップ",
|
||||
"j-pop": "j-pop",
|
||||
"rock": "ロック",
|
||||
"pop": "ポップ",
|
||||
"electronic": "エレクトロニック",
|
||||
"classical-orchestral": "クラシック & オーケストラ"
|
||||
"classical-orchestral": "Classical & Orchestral"
|
||||
},
|
||||
"map-specificities": {
|
||||
"automapper": "AI",
|
||||
@@ -997,6 +963,10 @@
|
||||
"go-to-mods": "Modインストーラーに移動",
|
||||
"not-remind": "二度と表示しないで"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "モデルが壊れています!",
|
||||
"desc": "Beat Saberのエンジンアップデート以来、すべてのカスタムモデルのMODが壊れており、更新が必要です。まだ更新されていません。"
|
||||
},
|
||||
"export-success": {
|
||||
"title": "エクスポート完了🎉"
|
||||
}
|
||||
@@ -1028,9 +998,125 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "プレイリストの作成エラー",
|
||||
"error-playlist-creation-desc": "プレイリストの作成中にエラーが発生しました。",
|
||||
"playlist-created-title": "プレイリストが作成されました",
|
||||
"playlist-created-desc": "プレイリストが正常に作成されました。今すぐマップを同期できます!",
|
||||
"download-playlist": "プレイリストをダウンロード",
|
||||
"synchronize-playlist": "プレイリストを同期",
|
||||
"synchronize-maps": "マップを同期",
|
||||
"error-playlists-synchronization-title": "プレイリストの同期エラー",
|
||||
"error-playlists-synchronization-desc": "プレイリストの同期中にエラーが発生しました。",
|
||||
"playlists-synchronized-title": "プレイリストが同期されました!",
|
||||
"playlists-synchronized-desc": "プレイリストとそのマップがダウンロードされました。",
|
||||
"playlists-export-error-title": "プレイリストのエクスポートエラー",
|
||||
"playlists-export-error-desc": "プレイリストのエクスポート中にエラーが発生しました。",
|
||||
"playlists-exported-title": "プレイリストがエクスポートされました!",
|
||||
"playlists-exported-desc": "プレイリストが正常にエクスポートされました。",
|
||||
"playlists-with-maps-exported-desc": "プレイリストとそのマップが正常にエクスポートされました。",
|
||||
"playlist-delete-error-title": "プレイリストの削除エラー",
|
||||
"playlist-delete-error-desc": "プレイリストの削除中にエラーが発生しました。",
|
||||
"playlists-deleted-title": "プレイリストが削除されました!",
|
||||
"playlists-deleted-desc": "プレイリストが正常に削除されました。",
|
||||
"edit-playlist": "プレイリストを編集",
|
||||
"playlist-edit-error-title": "プレイリストの編集エラー",
|
||||
"playlist-edit-error-desc": "プレイリストの編集中にエラーが発生しました。",
|
||||
"playlist-edited-title": "プレイリストが編集されました!",
|
||||
"playlist-edited-desc": "プレイリストが正常に変更されました。今すぐマップを同期できます!",
|
||||
"playlists-loading": "プレイリストを読み込み中...",
|
||||
"no-playlists": "プレイリストがありません",
|
||||
"download-playlists": "プレイリストをダウンロード",
|
||||
"created-by": "作成者",
|
||||
"stop-download": "ダウンロードを停止",
|
||||
"cancel-download": "ダウンロードをキャンセル",
|
||||
"open-file": "ファイルを開く",
|
||||
"link-playlists": "プレイリストをリンク",
|
||||
"link-playlist-desc": "プレイリストをリンクすると、すべてのバージョン間でプレイリストを共有できます。リンクすると、このバージョンは共有プレイリストの恩恵を受けます",
|
||||
"link-playlist-info": "プレイリストの追加と削除も共有されます",
|
||||
"keep-playlists": "プレイリストを保持",
|
||||
"keep-playlists-tip": "プレイリストを保持すると、現在のバージョンのプレイリストが共有プレイリストフォルダに移動されます。そうしない場合、それらは失われます",
|
||||
"unlink-playlists": "プレイリストのリンクを解除",
|
||||
"unlink-playlist-desc": "警告:プレイリストのリンクを解除すると、このバージョンでは共有プレイリストを使用できなくなります。",
|
||||
"unlink-keep-playlists-tip": "プレイリストを保持すると、現在のバージョン用に共有プレイリストのコピーが作成されます。そうしない場合、このバージョンのプレイリストは保持されません。",
|
||||
"delete-playlist-ask": "プレイリストを削除しますか?",
|
||||
"delete-playlists-ask": "プレイリストを削除しますか?",
|
||||
"delete-playlist-desc": "プレイリスト「{playlistTitle}」を削除してもよろしいですか?",
|
||||
"delete-playlists-desc": "{nb}個のプレイリストを削除してもよろしいですか?",
|
||||
"delete-maps": "マップを削除",
|
||||
"delete-playlist-maps-tip": "有効にすると、プレイリスト内のすべてのマップが削除されます",
|
||||
"delete-playlists-maps-tip": "有効にすると、プレイリスト内のすべてのマップが削除されます",
|
||||
"export-playlist-ask": "プレイリストをエクスポートしますか?",
|
||||
"export-playlists-ask": "プレイリストをエクスポートしますか?",
|
||||
"export-playlist-desc": "プレイリスト「{playlistTitle}」をエクスポートしてもよろしいですか?",
|
||||
"export-playlists-desc": "{nb}個のプレイリストをエクスポートしてもよろしいですか?",
|
||||
"export-maps": "マップをエクスポート",
|
||||
"export-playlist-maps-tip": "有効にすると、プレイリスト内のすべてのマップもエクスポートされます",
|
||||
"export-playlists-maps-tip": "有効にすると、プレイリスト内のすべてのマップもエクスポートされます",
|
||||
"export": "エクスポート",
|
||||
"need-clone-title": "警告",
|
||||
"need-clone-desc-1": "このプレイリストは外部サイトからダウンロードされ、同期リンクが含まれています。",
|
||||
"need-clone-desc-2": "同期中に変更を失わないようにするため、プレイリストが複製され、同期リンクが削除されます。",
|
||||
"need-clone-desc-3": "その後、必要に応じて元のプレイリストを削除できます。",
|
||||
"understood": "理解しました",
|
||||
"synchronize-playlist-ask": "プレイリストを同期しますか?",
|
||||
"synchronize-playlists-ask": "プレイリストを同期しますか?",
|
||||
"synchronize-playlist-desc": "プレイリスト「{playlistTitle}」を同期してもよろしいですか?",
|
||||
"synchronize-playlists-desc": "{nb}個のプレイリストを同期してもよろしいですか?",
|
||||
"synchronize-playlist-tip": "この操作はプレイリストを更新し、不足しているマップをダウンロードします。数分かかる場合があります。",
|
||||
"synchronize": "同期",
|
||||
"curated": "おすすめ",
|
||||
"verified-mapper": "認証済みマッパー",
|
||||
"empty-playlists": "空のプレイリスト",
|
||||
"search-playlist": "プレイリストを検索",
|
||||
"no-playlists-found": "プレイリストが見つかりません",
|
||||
"error-occur-while-loading-playlists": "プレイリストの読み込み中にエラーが発生しました",
|
||||
"error-occur-while-loading-playlist": "プレイリストの読み込み中にエラーが発生しました",
|
||||
"loading-maps": "マップを読み込み中...",
|
||||
"no-maps-found-for-playlist": "このプレイリストにマップが見つかりません",
|
||||
"playlist-contain-no-maps": "プレイリストにマップが含まれていません",
|
||||
"no-map-installed-for-playlist": "このプレイリストにインストールされたマップがありません",
|
||||
"playlist-is-waiting-to-download": "プレイリストはダウンロード待ちです",
|
||||
"download-maps": "マップをダウンロード",
|
||||
"download-missing-maps": "不足しているマップをダウンロード",
|
||||
"playlist-is-downloading": "プレイリストをダウンロード中です",
|
||||
"some-playlist-maps-are-missing": "このプレイリストの一部のマップが不足しています",
|
||||
"create-a-playlist": "プレイリストを作成",
|
||||
"synchronize-playlists": "プレイリストを同期",
|
||||
"export-playlists": "プレイリストをエクスポート",
|
||||
"delete-playlists": "プレイリストを削除",
|
||||
"choose-image": "画像を選択",
|
||||
"title": "タイトル",
|
||||
"playlist-title": "プレイリストのタイトル",
|
||||
"description": "説明",
|
||||
"playlist-description": "プレイリストの説明",
|
||||
"author": "作者",
|
||||
"playlist-author": "プレイリストの作者",
|
||||
"save": "保存",
|
||||
"loading": "読み込み中...",
|
||||
"installed": "インストール済み",
|
||||
"no-map-found": "マップが見つかりません",
|
||||
"edit-playlist-shortcuts": "ShiftキーまたはCtrlキーを押しながら複数のマップを選択",
|
||||
"add-to-playlist": "プレイリストに追加",
|
||||
"remove-from-playlist": "プレイリストから削除",
|
||||
"playlist-is-empty": "プレイリストが空です",
|
||||
"continue": "続ける",
|
||||
"nb-maps": "マップ数",
|
||||
"nb-mappers": "マッパー数",
|
||||
"duration": "継続時間",
|
||||
"nps": "1秒あたりの音符数",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "開始日 — 終了日",
|
||||
"all": "すべて",
|
||||
"last-24h": "過去24時間",
|
||||
"last-week": "先週",
|
||||
"last-month": "先月",
|
||||
"3-last-month": "過去3ヶ月"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
||||
"monthNames": ["Jan", "Feb", "Mar", "Apr", "May", "June", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
||||
"timeNames": ["a", "p", "am", "pm", "A", "P", "AM", "PM"]
|
||||
"dayNames": ["日", "月", "火", "水", "木", "金", "土", "日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
|
||||
"monthNames": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
|
||||
"timeNames": ["午前", "午後", "午前", "午後", "午前", "午後", "午前", "午後"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "Отказаться",
|
||||
"apply": "Применить",
|
||||
"copy": "Скопировать",
|
||||
"copied": "Скопировано!",
|
||||
"confirm": "Подтвердить",
|
||||
"choose-folder": "Изменить папку",
|
||||
"unknown": "Неизвестная ошибка ¯\\_(ツ)_/¯",
|
||||
"warning": "Внимание",
|
||||
"continue": "Продолжить"
|
||||
"copied": "Скопировано!"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "Добавить версию игры",
|
||||
@@ -38,7 +33,6 @@
|
||||
"desktop-description": "Режим Летающих контроллеров от первого лица(FPFC) позволит вам использовать меню с помощью WASD и мышки. Это облегчает тестирование модов, потому что вам не нужно подключать шлем!",
|
||||
"debug": "Режим отладки",
|
||||
"debug-description": "Включает окно логов для IPA. В окне будут отображаться логи модов.",
|
||||
"outdated-tippy": "Эта версия устарела, и некоторые моды или функции могут работать не так, как ожидалось. Рекомендуется использовать рекомендуемую версию ({recommendedVersion}) Beat Saber, чтобы воспользоваться последними функциями и исправлениями ошибок.",
|
||||
"advanced-launch": {
|
||||
"button": "Расширенный запуск",
|
||||
"placeholder": "Параметры запуска, например: --revert; --nowait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "Latest",
|
||||
"description": "Описание",
|
||||
"dropdown": {
|
||||
"uninstall-all": "Удалить всё",
|
||||
"unselect-all": "Снять все выделения"
|
||||
"uninstall-all": "Удалить всё"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +190,10 @@
|
||||
"report-bug": "Сообщить о баге",
|
||||
"open-logs": "Открыть логи"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 Изучаем Changelog!",
|
||||
"not-founds": "😕 Ой, Changelog нигде не видно!"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +238,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": "Требуется .NET 8"
|
||||
},
|
||||
"msg": {
|
||||
"401": "Похоже Steam не хочет, чтобы мы скачали Beat Saber 😢",
|
||||
"404": "Нет связи с серверами Steam.",
|
||||
@@ -266,11 +260,7 @@
|
||||
"LicenceError": "Не удалось проверить наличие лицензии.",
|
||||
"RateLimitExceeded": "Слишком много попыток, вернитесь позже и попробуйте снова.",
|
||||
"TokenRejected": "Ваш токен для входа был отклонен 😕 Пожалуйста, попробуйте снова.",
|
||||
"AccessDenied": "Доступ к Steam был отклонен.",
|
||||
"dotnet-required": "Среда запуска .NET 8 должна быть установлена, чтобы скачать Beat Saber. Скачайте её с помощью кнопки ниже."
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": "Скачать .NET 8"
|
||||
"AccessDenied": "Доступ к Steam был отклонен."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -387,8 +377,7 @@
|
||||
"BS_ALREADY_RUNNING": "Beat Saber уде запущен",
|
||||
"EXE_NOT_FINDED": "Отсутствуют файлы",
|
||||
"EXIT": "Вылет",
|
||||
"OCULUS_LIB_NOT_FOUND": "Библиотека Oculus не найдена",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Оригинальная версия Oculus не найдена"
|
||||
"OCULUS_LIB_NOT_FOUND": "Библиотека Oculus не найдена"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "Возникла неизвестная ошибка.",
|
||||
@@ -397,10 +386,7 @@
|
||||
"BS_ALREADY_RUNNING": "Закройте Beat Saber, чтобы запустить его.",
|
||||
"EXE_NOT_FINDED": "Некоторые файлы отсутствуют, пробуем их проверить.",
|
||||
"EXIT": "Beat Saber вылетел, пытаемся проверить файлы.",
|
||||
"OCULUS_LIB_NOT_FOUND": "Проверьте, правильно ли установлено приложение Oculus, и правильно ли определены библиотеки в Oculus.",
|
||||
"PROTON_NOT_SET": "Установите путь к Proton в настройках.",
|
||||
"PROTON_NOT_FOUND": "Установите путь к Proton в настройках.",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "Beat Saber должен быть установлен из приложения Oculus перед открытием."
|
||||
"OCULUS_LIB_NOT_FOUND": "Проверьте, правильно ли установлено приложение Oculus, и правильно ли определены библиотеки в Oculus."
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "Запустить Steam"
|
||||
@@ -492,16 +478,6 @@
|
||||
"title": "Бэкап создан",
|
||||
"msg": "Общая папка 'UserData' может создавать ошибки. В случае проблем отвяжите папку, чтобы восстановить бэкап."
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "Ошибка при связывании папки",
|
||||
"msg": {
|
||||
"EPERM": "BSManager не имеет необходимых прав для связывания папки.",
|
||||
"EACCES": "BSManager не имеет необходимых прав для связывания папки.",
|
||||
"ENOSPC": "Диск заполнен, освободите место и попробуйте снова.",
|
||||
"LinkingNotSupported": "Ссылки на папки не поддерживаются в этой файловой системе.",
|
||||
"UNKNOWN_ERROR": "Произошла неизвестная ошибка при связывании папки."
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
@@ -512,14 +488,6 @@
|
||||
"error": {
|
||||
"msg": "Ошибка создания ярлыка."
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "Устаревшая версия",
|
||||
"msg": "Эта версия Beat Saber устарела. Используйте рекомендуемую версию, чтобы воспользоваться последними функциями и исправлениями ошибок.",
|
||||
"actions": {
|
||||
"do-not-remind": "Больше не напоминать",
|
||||
"ok": "Ок"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -719,13 +687,14 @@
|
||||
"stay": "Запомнить меня",
|
||||
"connect-to-meta": "Подключиться к Meta"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Включить Sideloading",
|
||||
"info-1": "Чтобы запустить Beat Saber, необходимо включить возможность запуска приложений через sideloading. BSManager запросит права администратора для автоматического включения этой функции.",
|
||||
"info-2": "Функция sideloading позволяет запускать игры, расположенные за пределами папки библиотеки Oculus.",
|
||||
"info-3": "После активации сайдлоадинга функция останется активной, и вам больше не будет предложено её включить.",
|
||||
"i-want-to-do-it-myself": "Я хочу сделать это сам",
|
||||
"understood": "Понято"
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Внимание",
|
||||
"body": {
|
||||
"must-be-installed-once": "Вы должны были установить Beat Saber хотя бы один раз из Oculus Store, иначе Beat Saber может автоматически закрыться после запуска.",
|
||||
"will-backup": "Для запуска этой версии исходная папка установки Beat Saber, находящаяся в вашей библиотеке Oculus, будет переименована и автоматически восстановлена при выходе из Beat Saber."
|
||||
},
|
||||
"not-remind-me": "Больше не напоминать",
|
||||
"understood": "Понял"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Токен Oculus",
|
||||
@@ -753,9 +722,6 @@
|
||||
"info-3": "Обратите внимание, что не рекомендуется предоставлять права администратора Steam, так как это также влияет на установленные игры и моды, представляя угрозу безопасности."
|
||||
},
|
||||
"launch-as-admin": "Запустить от имени администратора"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "Версия {outdatedVersion} устарела, и некоторые моды или функции могут работать некорректно. Пожалуйста, скачайте последнюю рекомендуемую версию ({recommendedVersion}) Beat Saber, чтобы воспользоваться новейшими функциями и исправлениями ошибок."
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -771,7 +737,7 @@
|
||||
"accuracy": "точность",
|
||||
"balanced": "баланс",
|
||||
"challenge": "испытание",
|
||||
"dance-style": "танец",
|
||||
"dancestyle": "танец",
|
||||
"fitness": "фитнес",
|
||||
"speed": "скорость",
|
||||
"tech": "техника"
|
||||
@@ -780,36 +746,36 @@
|
||||
"dance": "танец",
|
||||
"swing": "свинг",
|
||||
"nightcore": "найткор",
|
||||
"folk-acoustic": "фолк и акустика",
|
||||
"kids-family": "дети и семья",
|
||||
"folk": "народные",
|
||||
"family": "семейные",
|
||||
"ambient": "эмбиент",
|
||||
"funk-disco": "фанк и диско",
|
||||
"funk": "фанк",
|
||||
"jazz": "джаз",
|
||||
"soul": "соул",
|
||||
"speedcore": "спидкор",
|
||||
"punk": "панк",
|
||||
"rb": "r&b",
|
||||
"holiday": "праздники",
|
||||
"vocaloid": "вокалоид",
|
||||
"rb": "ар-н-би",
|
||||
"holiday": "праздник",
|
||||
"vocaloid": "вокалоиды",
|
||||
"j-rock": "джей-рок",
|
||||
"trance": "транс",
|
||||
"drum-and-bass": "драм-н-бейс",
|
||||
"comedy-meme": "комедия и мемы",
|
||||
"instrumental": "инструментал",
|
||||
"drumbass": "драм-н-бейс",
|
||||
"comedy": "комедия",
|
||||
"instrumental": "инструментальные",
|
||||
"hardcore": "хардкор",
|
||||
"k-pop": "k-pop",
|
||||
"k-pop": "кей-поп",
|
||||
"indie": "инди",
|
||||
"techno": "техно",
|
||||
"house": "хаус",
|
||||
"video-game-soundtrack": "видеоигра",
|
||||
"tv-movie-soundtrack": "ТВ и кино",
|
||||
"alternative": "альтернатива",
|
||||
"dubstep": "дабстеп",
|
||||
"game": "видеоигры",
|
||||
"film": "фильмы",
|
||||
"alt": "альтернативные",
|
||||
"dubstep": "дапстеп",
|
||||
"metal": "метал",
|
||||
"anime": "аниме",
|
||||
"hip-hop-rap": "хип-хоп и рэп",
|
||||
"j-pop": "j-pop",
|
||||
"rock": "рок",
|
||||
"hiphop": "хипхоп",
|
||||
"j-pop": "джей-поп",
|
||||
"rock": "прк",
|
||||
"pop": "поп",
|
||||
"electronic": "электроника",
|
||||
"classical-orchestral": "Классика и Оркестр"
|
||||
@@ -996,6 +962,10 @@
|
||||
"go-to-mods": "Перейти к модам",
|
||||
"not-remind": "Больше не напоминать"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "Сломанные модели",
|
||||
"desc": "С момента обновления движка Beat Saber, все пользовательские модификации моделей сломались и требуют обновления. Они еще не были обновлены."
|
||||
},
|
||||
"export-success": {
|
||||
"title": "Экспорт завершен 🎉"
|
||||
}
|
||||
@@ -1027,6 +997,122 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "Ошибка при создании плейлиста",
|
||||
"error-playlist-creation-desc": "Произошла ошибка при создании плейлиста.",
|
||||
"playlist-created-title": "Плейлист создан",
|
||||
"playlist-created-desc": "Плейлист успешно создан. Теперь вы можете синхронизировать его карты!",
|
||||
"download-playlist": "Скачать плейлист",
|
||||
"synchronize-playlist": "Синхронизировать плейлист",
|
||||
"synchronize-maps": "Синхронизировать карты",
|
||||
"error-playlists-synchronization-title": "Ошибка синхронизации плейлистов",
|
||||
"error-playlists-synchronization-desc": "Произошла ошибка при синхронизации плейлистов.",
|
||||
"playlists-synchronized-title": "Плейлисты синхронизированы!",
|
||||
"playlists-synchronized-desc": "Плейлисты и их карты были загружены.",
|
||||
"playlists-export-error-title": "Ошибка экспорта плейлистов",
|
||||
"playlists-export-error-desc": "Произошла ошибка при экспорте плейлистов.",
|
||||
"playlists-exported-title": "Плейлисты экспортированы!",
|
||||
"playlists-exported-desc": "Плейлисты успешно экспортированы.",
|
||||
"playlists-with-maps-exported-desc": "Плейлисты и их карты успешно экспортированы.",
|
||||
"playlist-delete-error-title": "Ошибка удаления плейлиста",
|
||||
"playlist-delete-error-desc": "Произошла ошибка при удалении плейлиста.",
|
||||
"playlists-deleted-title": "Плейлисты удалены!",
|
||||
"playlists-deleted-desc": "Плейлисты успешно удалены.",
|
||||
"edit-playlist": "Редактировать плейлист",
|
||||
"playlist-edit-error-title": "Ошибка редактирования плейлиста",
|
||||
"playlist-edit-error-desc": "Произошла ошибка при редактировании плейлиста.",
|
||||
"playlist-edited-title": "Плейлист отредактирован!",
|
||||
"playlist-edited-desc": "Плейлист успешно изменен. Теперь вы можете синхронизировать его карты!",
|
||||
"playlists-loading": "Загрузка плейлистов...",
|
||||
"no-playlists": "Нет плейлистов",
|
||||
"download-playlists": "Скачать плейлисты",
|
||||
"created-by": "Создано",
|
||||
"stop-download": "Остановить загрузку",
|
||||
"cancel-download": "Отменить загрузку",
|
||||
"open-file": "Открыть файл",
|
||||
"link-playlists": "Связать плейлисты",
|
||||
"link-playlist-desc": "Связывание плейлистов позволяет делиться плейлистами между всеми версиями. После связывания эта версия будет иметь доступ к общим плейлистам",
|
||||
"link-playlist-info": "Добавление и удаление плейлистов также будет общим",
|
||||
"keep-playlists": "Сохранить плейлисты",
|
||||
"keep-playlists-tip": "Сохранение плейлистов переместит плейлисты из текущей версии в папку общих плейлистов. В противном случае они будут потеряны",
|
||||
"unlink-playlists": "Отвязать плейлисты",
|
||||
"unlink-playlist-desc": "Внимание, отвязка плейлистов больше не позволит использовать общие плейлисты для этой версии.",
|
||||
"unlink-keep-playlists-tip": "Сохранение плейлистов создаст копию общих плейлистов для текущей версии. В противном случае для этой версии не будут сохранены плейлисты.",
|
||||
"delete-playlist-ask": "Удалить плейлист?",
|
||||
"delete-playlists-ask": "Удалить плейлисты?",
|
||||
"delete-playlist-desc": "Вы уверены, что хотите удалить плейлист \"{playlistTitle}\"?",
|
||||
"delete-playlists-desc": "Вы уверены, что хотите удалить {nb} плейлистов?",
|
||||
"delete-maps": "Удалить карты",
|
||||
"delete-playlist-maps-tip": "Если включено, все карты в плейлисте будут удалены",
|
||||
"delete-playlists-maps-tip": "Если включено, все карты в плейлистах будут удалены",
|
||||
"export-playlist-ask": "Экспортировать плейлист?",
|
||||
"export-playlists-ask": "Экспортировать плейлисты?",
|
||||
"export-playlist-desc": "Вы уверены, что хотите экспортировать плейлист \"{playlistTitle}\"?",
|
||||
"export-playlists-desc": "Вы уверены, что хотите экспортировать {nb} плейлистов?",
|
||||
"export-maps": "Экспортировать карты",
|
||||
"export-playlist-maps-tip": "Если включено, все карты в плейлисте также будут экспортированы",
|
||||
"export-playlists-maps-tip": "Если включено, все карты в плейлистах также будут экспортированы",
|
||||
"export": "Экспорт",
|
||||
"need-clone-title": "Предупреждение",
|
||||
"need-clone-desc-1": "Этот плейлист был загружен с внешнего сайта и содержит ссылку для синхронизации.",
|
||||
"need-clone-desc-2": "Чтобы избежать потери ваших изменений во время синхронизации, плейлист будет дублирован, а его ссылка для синхронизации удалена.",
|
||||
"need-clone-desc-3": "Затем вы можете, если хотите, удалить оригинальный плейлист.",
|
||||
"understood": "Я понимаю",
|
||||
"synchronize-playlist-ask": "Синхронизировать плейлист?",
|
||||
"synchronize-playlists-ask": "Синхронизировать плейлисты?",
|
||||
"synchronize-playlist-desc": "Вы уверены, что хотите синхронизировать плейлист \"{playlistTitle}\"?",
|
||||
"synchronize-playlists-desc": "Вы уверены, что хотите синхронизировать {nb} плейлистов?",
|
||||
"synchronize-playlist-tip": "Это действие обновляет плейлисты и загружает отсутствующие карты; это может занять несколько минут.",
|
||||
"synchronize": "Синхронизировать",
|
||||
"curated": "Рекомендованные",
|
||||
"verified-mapper": "Проверенный маппер",
|
||||
"empty-playlists": "Пустые плейлисты",
|
||||
"search-playlist": "Поиск плейлиста",
|
||||
"no-playlists-found": "Плейлисты не найдены",
|
||||
"error-occur-while-loading-playlists": "Произошла ошибка при загрузке плейлистов",
|
||||
"error-occur-while-loading-playlist": "Произошла ошибка при загрузке плейлиста",
|
||||
"loading-maps": "Загрузка карт...",
|
||||
"no-maps-found-for-playlist": "Для этого плейлиста не найдено карт",
|
||||
"playlist-contain-no-maps": "Плейлист не содержит карт",
|
||||
"no-map-installed-for-playlist": "Для этого плейлиста не установлено карт",
|
||||
"playlist-is-waiting-to-download": "Плейлист ожидает загрузки",
|
||||
"download-maps": "Скачать карты",
|
||||
"download-missing-maps": "Скачать отсутствующие карты",
|
||||
"playlist-is-downloading": "Плейлист загружается",
|
||||
"some-playlist-maps-are-missing": "Некоторые карты в этом плейлисте отсутствуют",
|
||||
"create-a-playlist": "Создать плейлист",
|
||||
"synchronize-playlists": "Синхронизировать плейлисты",
|
||||
"export-playlists": "Экспортировать плейлисты",
|
||||
"delete-playlists": "Удалить плейлисты",
|
||||
"choose-image": "Выбрать изображение",
|
||||
"title": "Название",
|
||||
"playlist-title": "Название плейлиста",
|
||||
"description": "Описание",
|
||||
"playlist-description": "Описание плейлиста",
|
||||
"author": "Автор",
|
||||
"playlist-author": "Автор плейлиста",
|
||||
"save": "Сохранить",
|
||||
"loading": "Загрузка...",
|
||||
"installed": "Установлено",
|
||||
"no-map-found": "Карта не найдена",
|
||||
"edit-playlist-shortcuts": "Удерживайте Shift или Ctrl для выбора нескольких карт",
|
||||
"add-to-playlist": "Добавить в плейлист",
|
||||
"remove-from-playlist": "Удалить из плейлиста",
|
||||
"playlist-is-empty": "Плейлист пуст",
|
||||
"continue": "Продолжить",
|
||||
"nb-maps": "Количество карт",
|
||||
"nb-mappers": "Количество мапперов",
|
||||
"duration": "Продолжительность",
|
||||
"nps": "Нот в секунду",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "Дата начала — Дата окончания",
|
||||
"all": "Все",
|
||||
"last-24h": "Последние 24 часа",
|
||||
"last-week": "Последняя неделя",
|
||||
"last-month": "Последний месяц",
|
||||
"3-last-month": "Последние 3 месяца"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Воскресение", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"],
|
||||
"monthNames": ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авн", "Сен", "Окт", "Ноя", "Дек", "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "拒絕",
|
||||
"apply": "應用",
|
||||
"copy": "複製",
|
||||
"copied": "已複製!",
|
||||
"confirm": "確認",
|
||||
"choose-folder": "選擇文件夾",
|
||||
"unknown": "發生了一個錯誤 ¯\\_(ツ)_/¯",
|
||||
"warning": "警告",
|
||||
"continue": "繼續"
|
||||
"copied": "已複製!"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "新增版本",
|
||||
@@ -38,7 +33,6 @@
|
||||
"desktop-description": "第一人稱飛控模式允許你使用鍵盤 WASD 和滑鼠在遊戲中進行導航。你無需帶上頭顯即可進行測試!",
|
||||
"debug": "Debug 模式",
|
||||
"debug-description": "為 IPA 啟用輸出日誌窗口。 會顯示所用 Mod 的 debug 輸出",
|
||||
"outdated-tippy": "此版本已過時,某些模組或功能可能無法按預期運作。建議使用推薦版本的 Beat Saber ({recommendedVersion}),以享受最新功能和修復。",
|
||||
"advanced-launch": {
|
||||
"button": "高級啟動",
|
||||
"placeholder": "額外啟動參數,例如: --revert; --nowait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "最新",
|
||||
"description": "描述",
|
||||
"dropdown": {
|
||||
"uninstall-all": "全部移除",
|
||||
"unselect-all": "取消全選"
|
||||
"uninstall-all": "全部移除"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +190,10 @@
|
||||
"report-bug": "報告 bug",
|
||||
"open-logs": "打開日誌"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 探索更新日誌!",
|
||||
"not-founds": "😕 噢,找不到更新日誌!"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +238,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": "需要 .NET 8"
|
||||
},
|
||||
"msg": {
|
||||
"401": "Steam 似乎不想讓我們下載 Beat Saber😢",
|
||||
"404": "無法聯繫 Steam 伺服器。",
|
||||
@@ -266,11 +260,7 @@
|
||||
"LicenceError": "無法獲取許可證列表。",
|
||||
"RateLimitExceeded": "你已經嘗試了太多次,請稍等片刻,稍後再試。",
|
||||
"TokenRejected": "你的登錄令牌已被拒絕 😕 請重試。",
|
||||
"AccessDenied": "訪問 Steam 被拒絕。",
|
||||
"dotnet-required": "必須安裝 .NET 8 Runtime 才能下載 Beat Saber 版本。單擊下面的按鈕下載它。"
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": "下載 .NET 8"
|
||||
"AccessDenied": "訪問 Steam 被拒絕。"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -387,8 +377,7 @@
|
||||
"BS_ALREADY_RUNNING": "Beat Saber 已在運行",
|
||||
"EXE_NOT_FINDED": "缺少文件",
|
||||
"EXIT": "突然停止",
|
||||
"OCULUS_LIB_NOT_FOUND": "未找到 Oculus 庫",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "找不到原始Oculus版本"
|
||||
"OCULUS_LIB_NOT_FOUND": "未找到 Oculus 庫"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "發生未知錯誤。",
|
||||
@@ -397,10 +386,7 @@
|
||||
"BS_ALREADY_RUNNING": "再次啟動前請關閉 BeatSaber。",
|
||||
"EXE_NOT_FINDED": "某些文件似乎遺失了,嘗試驗證文件。",
|
||||
"EXIT": "BeatSaber 突然停止,請檢查文件。",
|
||||
"OCULUS_LIB_NOT_FOUND": "檢查 Oculus 應用是否正確安裝,以及庫是否在 Oculus 中正確定義。",
|
||||
"PROTON_NOT_SET": "在設定中設置Proton路徑。",
|
||||
"PROTON_NOT_FOUND": "在設定中設置Proton路徑。",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "在打開之前,必須從Oculus應用程式安裝Beat Saber。"
|
||||
"OCULUS_LIB_NOT_FOUND": "檢查 Oculus 應用是否正確安裝,以及庫是否在 Oculus 中正確定義。"
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "啟動 Steam"
|
||||
@@ -492,16 +478,6 @@
|
||||
"title": "備份已創建",
|
||||
"msg": "共享 “UserData” 文件夾可能會產生錯誤,如果出現問題,請取消關聯該文件夾以恢復備份"
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "連結文件夾時出錯",
|
||||
"msg": {
|
||||
"EPERM": "BSManager沒有必要的權限來連結文件夾。",
|
||||
"EACCES": "BSManager沒有必要的權限來連結文件夾。",
|
||||
"ENOSPC": "磁碟已滿,請騰出空間後再試。",
|
||||
"LinkingNotSupported": "該檔案系統不支援資料夾連結。",
|
||||
"UNKNOWN_ERROR": "連結文件夾時發生未知錯誤。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
@@ -512,14 +488,6 @@
|
||||
"error": {
|
||||
"msg": "創建捷徑時發生錯誤"
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "版本過時",
|
||||
"msg": "此 Beat Saber 版本已過時,請使用推薦版本以享受最新功能和修復。",
|
||||
"actions": {
|
||||
"do-not-remind": "不要再提醒我",
|
||||
"ok": "確定"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -719,13 +687,14 @@
|
||||
"stay": "記住我",
|
||||
"connect-to-meta": "連接到 Meta"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "啟用旁載",
|
||||
"info-1": "為了啟動 Beat Saber,必須啟用執行旁載應用程式的功能。BSManager 將請求管理員權限以自動啟用此功能。",
|
||||
"info-2": "旁載功能允許啟動位於 Oculus 資料庫資料夾之外的遊戲。",
|
||||
"info-3": "啟用 sideloading 後,此功能將保持啟用狀態,您將不再被提示啟用它。",
|
||||
"i-want-to-do-it-myself": "我想自己完成",
|
||||
"understood": "了解"
|
||||
"original-version-backup-oculus": {
|
||||
"title": "警告",
|
||||
"body": {
|
||||
"must-be-installed-once": "你必須至少從 Oculus 商店安裝過一次 BeatSaber,否則 BeatSaber 可能會在啟動後自動關閉。",
|
||||
"will-backup": "為了啟動這個版本,位於您的Oculus庫中的Beat Saber的原始安裝文件夾將被重新命名,並且在Beat Saber關閉時會自動恢復。"
|
||||
},
|
||||
"not-remind-me": "不再提醒我",
|
||||
"understood": "明白了"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Oculus令牌",
|
||||
@@ -754,9 +723,6 @@
|
||||
},
|
||||
"launch-as-admin": "以管理員身份啟動",
|
||||
"not-remind-me": "不再提醒我"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "版本 {outdatedVersion} 已過時,某些模組或功能可能無法正常運作。請下載最新推薦的 Beat Saber 版本 ({recommendedVersion}),以享受最新功能和修正。"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -772,48 +738,48 @@
|
||||
"accuracy": "精確度",
|
||||
"balanced": "平衡",
|
||||
"challenge": "挑戰",
|
||||
"dance-style": "舞蹈",
|
||||
"dancestyle": "舞蹈",
|
||||
"fitness": "健身",
|
||||
"speed": "速度",
|
||||
"tech": "技術"
|
||||
},
|
||||
"map-styles": {
|
||||
"dance": "舞蹈",
|
||||
"swing": "搖擺",
|
||||
"nightcore": "夜核",
|
||||
"folk-acoustic": "民謠 & 原聲",
|
||||
"kids-family": "兒童 & 家庭",
|
||||
"ambient": "氛圍音樂",
|
||||
"funk-disco": "放克 & 迪斯科",
|
||||
"jazz": "爵士",
|
||||
"soul": "靈魂",
|
||||
"speedcore": "極速核",
|
||||
"punk": "龐克",
|
||||
"rb": "r&b",
|
||||
"holiday": "假日",
|
||||
"vocaloid": "聲庫",
|
||||
"j-rock": "日式搖滾",
|
||||
"trance": "迷幻",
|
||||
"drum-and-bass": "鼓 & 貝斯",
|
||||
"comedy-meme": "喜劇 & 表情包",
|
||||
"instrumental": "純音樂",
|
||||
"hardcore": "硬核",
|
||||
"k-pop": "k-pop",
|
||||
"indie": "獨立",
|
||||
"techno": "電子舞曲",
|
||||
"house": "浩室音樂",
|
||||
"video-game-soundtrack": "遊戲音樂",
|
||||
"tv-movie-soundtrack": "電視 & 電影",
|
||||
"alternative": "另類",
|
||||
"dubstep": "電音鼓",
|
||||
"metal": "金屬",
|
||||
"anime": "動漫",
|
||||
"hip-hop-rap": "嘻哈 & 說唱",
|
||||
"j-pop": "日式流行",
|
||||
"rock": "搖滾",
|
||||
"pop": "流行",
|
||||
"electronic": "電子",
|
||||
"classical-orchestral": "古典 & 管弦樂"
|
||||
"dance": "Dance",
|
||||
"swing": "Swing",
|
||||
"nightcore": "Nightcore",
|
||||
"folk": "Folk",
|
||||
"family": "Family",
|
||||
"ambient": "Ambient",
|
||||
"funk": "Funk",
|
||||
"jazz": "Jazz",
|
||||
"soul": "Soul",
|
||||
"speedcore": "Speedcore",
|
||||
"punk": "Punk",
|
||||
"rb": "R&B",
|
||||
"holiday": "Holiday",
|
||||
"vocaloid": "Vocaloid",
|
||||
"j-rock": "J-rock",
|
||||
"trance": "Trance",
|
||||
"drumbass": "Drum & Bass",
|
||||
"comedy": "Comedy",
|
||||
"instrumental": "Instrumental",
|
||||
"hardcore": "Hardcore",
|
||||
"k-pop": "K-pop",
|
||||
"indie": "Indie",
|
||||
"techno": "Techno",
|
||||
"house": "House",
|
||||
"game": "Video game",
|
||||
"film": "Film",
|
||||
"alt": "Alternative",
|
||||
"dubstep": "Dubstep",
|
||||
"metal": "Metal",
|
||||
"anime": "Anime",
|
||||
"hiphop": "Hiphop",
|
||||
"j-pop": "J-pop",
|
||||
"rock": "Rock",
|
||||
"pop": "Pop",
|
||||
"electronic": "Electronic",
|
||||
"classical-orchestral": "Classical & Orchestral"
|
||||
},
|
||||
"map-specificities": {
|
||||
"automapper": "AI",
|
||||
@@ -997,6 +963,10 @@
|
||||
"go-to-mods": "前往 Mod 頁",
|
||||
"not-remind": "不再提醒我"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "已損壞的模型",
|
||||
"desc": "自從Beat Saber引擎更新以來,所有自定義模型的MOD都已損壞,需要更新。它們還沒有被更新。"
|
||||
},
|
||||
"export-success": {
|
||||
"title": "導出成功 🎉"
|
||||
}
|
||||
@@ -1028,6 +998,122 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "建立播放清單時發生錯誤",
|
||||
"error-playlist-creation-desc": "建立播放清單時發生錯誤。",
|
||||
"playlist-created-title": "播放清單已建立",
|
||||
"playlist-created-desc": "播放清單已成功建立。您現在可以同步其地圖了!",
|
||||
"download-playlist": "下載播放清單",
|
||||
"synchronize-playlist": "同步播放清單",
|
||||
"synchronize-maps": "同步地圖",
|
||||
"error-playlists-synchronization-title": "同步播放清單時發生錯誤",
|
||||
"error-playlists-synchronization-desc": "同步播放清單時發生錯誤。",
|
||||
"playlists-synchronized-title": "播放清單已同步!",
|
||||
"playlists-synchronized-desc": "播放清單及其地圖已下載。",
|
||||
"playlists-export-error-title": "匯出播放清單時發生錯誤",
|
||||
"playlists-export-error-desc": "匯出播放清單時發生錯誤。",
|
||||
"playlists-exported-title": "播放清單已匯出!",
|
||||
"playlists-exported-desc": "播放清單已成功匯出。",
|
||||
"playlists-with-maps-exported-desc": "播放清單及其地圖已成功匯出。",
|
||||
"playlist-delete-error-title": "刪除播放清單時發生錯誤",
|
||||
"playlist-delete-error-desc": "刪除播放清單時發生錯誤。",
|
||||
"playlists-deleted-title": "播放清單已刪除!",
|
||||
"playlists-deleted-desc": "播放清單已成功刪除。",
|
||||
"edit-playlist": "編輯播放清單",
|
||||
"playlist-edit-error-title": "編輯播放清單時發生錯誤",
|
||||
"playlist-edit-error-desc": "編輯播放清單時發生錯誤。",
|
||||
"playlist-edited-title": "播放清單已編輯!",
|
||||
"playlist-edited-desc": "播放清單已成功修改。您現在可以同步其地圖了!",
|
||||
"playlists-loading": "正在載入播放清單...",
|
||||
"no-playlists": "沒有播放清單",
|
||||
"download-playlists": "下載播放清單",
|
||||
"created-by": "建立者",
|
||||
"stop-download": "停止下載",
|
||||
"cancel-download": "取消下載",
|
||||
"open-file": "開啟檔案",
|
||||
"link-playlists": "連結播放清單",
|
||||
"link-playlist-desc": "連結播放清單允許在所有版本之間共享播放清單。一旦連結,此版本將受益於共享播放清單",
|
||||
"link-playlist-info": "新增和刪除播放清單也將被共享",
|
||||
"keep-playlists": "保留播放清單",
|
||||
"keep-playlists-tip": "保留播放清單將把當前版本的播放清單移動到共享播放清單資料夾。否則,它們將遺失",
|
||||
"unlink-playlists": "取消連結播放清單",
|
||||
"unlink-playlist-desc": "警告,取消連結播放清單將不再允許此版本使用共享播放清單。",
|
||||
"unlink-keep-playlists-tip": "保留播放清單將為當前版本建立共享播放清單的副本。否則,此版本將不保留任何播放清單。",
|
||||
"delete-playlist-ask": "刪除播放清單?",
|
||||
"delete-playlists-ask": "刪除播放清單?",
|
||||
"delete-playlist-desc": "您確定要刪除播放清單 \"{playlistTitle}\" 嗎?",
|
||||
"delete-playlists-desc": "您確定要刪除 {nb} 個播放清單嗎?",
|
||||
"delete-maps": "刪除地圖",
|
||||
"delete-playlist-maps-tip": "如果啟用,播放清單中的所有地圖都將被刪除",
|
||||
"delete-playlists-maps-tip": "如果啟用,播放清單中的所有地圖都將被刪除",
|
||||
"export-playlist-ask": "匯出播放清單?",
|
||||
"export-playlists-ask": "匯出播放清單?",
|
||||
"export-playlist-desc": "您確定要匯出播放清單 \"{playlistTitle}\" 嗎?",
|
||||
"export-playlists-desc": "您確定要匯出 {nb} 個播放清單嗎?",
|
||||
"export-maps": "匯出地圖",
|
||||
"export-playlist-maps-tip": "如果啟用,播放清單中的所有地圖也將被匯出",
|
||||
"export-playlists-maps-tip": "如果啟用,播放清單中的所有地圖也將被匯出",
|
||||
"export": "匯出",
|
||||
"need-clone-title": "警告",
|
||||
"need-clone-desc-1": "此播放清單已從外部網站下載,並包含同步連結。",
|
||||
"need-clone-desc-2": "為避免在同步過程中遺失更改,播放清單將被複製,並刪除其同步連結。",
|
||||
"need-clone-desc-3": "然後,如果您願意,可以刪除原始播放清單。",
|
||||
"understood": "我明白了",
|
||||
"synchronize-playlist-ask": "同步播放清單?",
|
||||
"synchronize-playlists-ask": "同步播放清單?",
|
||||
"synchronize-playlist-desc": "您確定要同步播放清單 \"{playlistTitle}\" 嗎?",
|
||||
"synchronize-playlists-desc": "您確定要同步 {nb} 個播放清單嗎?",
|
||||
"synchronize-playlist-tip": "此操作更新播放清單並下載缺失的地圖;可能需要幾分鐘。",
|
||||
"synchronize": "同步",
|
||||
"curated": "精選",
|
||||
"verified-mapper": "已驗證的製圖者",
|
||||
"empty-playlists": "空播放清單",
|
||||
"search-playlist": "搜尋播放清單",
|
||||
"no-playlists-found": "未找到播放清單",
|
||||
"error-occur-while-loading-playlists": "載入播放清單時發生錯誤",
|
||||
"error-occur-while-loading-playlist": "載入播放清單時發生錯誤",
|
||||
"loading-maps": "正在載入地圖...",
|
||||
"no-maps-found-for-playlist": "未找到此播放清單的地圖",
|
||||
"playlist-contain-no-maps": "播放清單不包含地圖",
|
||||
"no-map-installed-for-playlist": "此播放清單沒有已安裝的地圖",
|
||||
"playlist-is-waiting-to-download": "播放清單正在等待下載",
|
||||
"download-maps": "下載地圖",
|
||||
"download-missing-maps": "下載缺失的地圖",
|
||||
"playlist-is-downloading": "播放清單正在下載",
|
||||
"some-playlist-maps-are-missing": "此播放清單中的一些地圖缺失",
|
||||
"create-a-playlist": "建立播放清單",
|
||||
"synchronize-playlists": "同步播放清單",
|
||||
"export-playlists": "匯出播放清單",
|
||||
"delete-playlists": "刪除播放清單",
|
||||
"choose-image": "選擇圖片",
|
||||
"title": "標題",
|
||||
"playlist-title": "播放清單標題",
|
||||
"description": "描述",
|
||||
"playlist-description": "播放清單描述",
|
||||
"author": "作者",
|
||||
"playlist-author": "播放清單作者",
|
||||
"save": "儲存",
|
||||
"loading": "載入中...",
|
||||
"installed": "已安裝",
|
||||
"no-map-found": "未找到地圖",
|
||||
"edit-playlist-shortcuts": "按住 Shift 或 Ctrl 選擇多個地圖",
|
||||
"add-to-playlist": "新增到播放清單",
|
||||
"remove-from-playlist": "從播放清單中移除",
|
||||
"playlist-is-empty": "播放清單為空",
|
||||
"continue": "繼續",
|
||||
"nb-maps": "地圖數量",
|
||||
"nb-mappers": "製圖者數量",
|
||||
"duration": "持續時間",
|
||||
"nps": "每秒音符數",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "開始日期 — 結束日期",
|
||||
"all": "全部",
|
||||
"last-24h": "最近24小時",
|
||||
"last-week": "上週",
|
||||
"last-month": "上個月",
|
||||
"3-last-month": "最近3個月"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["週日", "週一", "週二", "週三", "週四", "週五", "週六", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
|
||||
"monthNames": ["1 月", "2 月", "3 月", "4 月", "5 月", "6 月", "7 月", "8 月", "9 月", "10 月", "11 月", "12 月", "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
"refuse": "拒绝",
|
||||
"apply": "应用",
|
||||
"copy": "复制",
|
||||
"copied": "已复制!",
|
||||
"confirm": "确认",
|
||||
"choose-folder": "选择文件夹",
|
||||
"Unknown": "发生了一个错误 ¯\\_(ツ)_/¯",
|
||||
"warning": "警告",
|
||||
"continue": "继续"
|
||||
"copied": "已复制!"
|
||||
},
|
||||
"nav-bar": {
|
||||
"add-version": "添加版本",
|
||||
@@ -38,7 +33,6 @@
|
||||
"desktop-description": "第一人称飞控模式允许你使用键盘 WASD 和鼠标在游戏中进行导航。你无需带上头显即可进行测试!",
|
||||
"debug": "Debug 模式",
|
||||
"debug-description": "为 IPA 启用输出日志窗口。 会显示所用 Mod 的 debug 输出",
|
||||
"outdated-tippy": "此版本已过时,某些模组或功能可能无法按预期运行。建议使用推荐版本的 Beat Saber ({recommendedVersion}),以享受最新功能和修复。",
|
||||
"advanced-launch": {
|
||||
"button": "高级启动",
|
||||
"placeholder": "额外启动参数,例如: --revert; --nowait"
|
||||
@@ -88,8 +82,7 @@
|
||||
"latest": "最新",
|
||||
"description": "描述",
|
||||
"dropdown": {
|
||||
"uninstall-all": "全部卸载",
|
||||
"unselect-all": "取消全选"
|
||||
"uninstall-all": "全部卸载"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +190,10 @@
|
||||
"report-bug": "报告 bug",
|
||||
"open-logs": "打开日志"
|
||||
}
|
||||
},
|
||||
"changelogs": {
|
||||
"open" : "🚀 探索更新日志!",
|
||||
"not-founds": "😕 哎呀,找不到更新日志!"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -241,9 +238,6 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"titles": {
|
||||
"dotnet-required": "需要 .NET 8"
|
||||
},
|
||||
"msg": {
|
||||
"401": "Steam 似乎不想让我们下载 Beat Saber😢",
|
||||
"404": "无法联系 Steam 服务器。",
|
||||
@@ -266,11 +260,7 @@
|
||||
"LicenceError": "无法获取许可证列表。",
|
||||
"RateLimitExceeded": "你已经尝试了太多次,请稍等片刻,稍后再试。",
|
||||
"TokenRejected": "你的登录令牌已被拒绝 😕 请重试。",
|
||||
"AccessDenied": "访问 Steam 被拒绝。",
|
||||
"dotnet-required": "必须安装 .NET 8 Runtime 才能下载 Beat Saber 版本。单击下面的按钮下载它。"
|
||||
},
|
||||
"actions": {
|
||||
"download-dotnet": "下载 .NET 8"
|
||||
"AccessDenied": "访问 Steam 被拒绝。"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -387,8 +377,7 @@
|
||||
"BS_ALREADY_RUNNING": "Beat Saber 已在运行",
|
||||
"EXE_NOT_FINDED": "缺少文件",
|
||||
"EXIT": "突然停止",
|
||||
"OCULUS_LIB_NOT_FOUND": "未找到 Oculus 库",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "未找到原始Oculus版本"
|
||||
"OCULUS_LIB_NOT_FOUND": "未找到 Oculus 库"
|
||||
},
|
||||
"msg": {
|
||||
"UNKNOWN_ERROR": "发生未知错误。",
|
||||
@@ -397,10 +386,7 @@
|
||||
"BS_ALREADY_RUNNING": "再次启动前请关闭 BeatSaber。",
|
||||
"EXE_NOT_FINDED": "某些文件似乎丢失了,尝试验证文件。",
|
||||
"EXIT": "BeatSaber 突然停止,请检查文件。",
|
||||
"OCULUS_LIB_NOT_FOUND": "检查 Oculus 应用是否正确安装,以及库是否在 Oculus 中正确定义。",
|
||||
"PROTON_NOT_SET": "在设置中设置Proton路径。",
|
||||
"PROTON_NOT_FOUND": "在设置中设置Proton路径。",
|
||||
"ORIGINAL_OCULUS_NOT_INSTALLED": "在打开之前,必须从Oculus应用程序安装Beat Saber。"
|
||||
"OCULUS_LIB_NOT_FOUND": "检查 Oculus 应用是否正确安装,以及库是否在 Oculus 中正确定义。"
|
||||
},
|
||||
"actions": {
|
||||
"STEAM_NOT_RUNNING": "启动 Steam"
|
||||
@@ -492,16 +478,6 @@
|
||||
"title": "备份已创建",
|
||||
"msg": "共享 “UserData” 文件夹可能会产生错误,如果出现问题,请取消关联该文件夹以恢复备份"
|
||||
}
|
||||
},
|
||||
"linking-error": {
|
||||
"title": "链接文件夹时出错",
|
||||
"msg": {
|
||||
"EPERM": "BSManager没有必要的权限来链接文件夹。",
|
||||
"EACCES": "BSManager没有必要的权限来链接文件夹。",
|
||||
"ENOSPC": "磁盘已满,请腾出空间后再试。",
|
||||
"LinkingNotSupported": "该文件系统不支持文件夹链接。",
|
||||
"UNKNOWN_ERROR": "链接文件夹时发生未知错误。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-launch-shortcut": {
|
||||
@@ -512,14 +488,6 @@
|
||||
"error": {
|
||||
"msg": "创建快捷方式时发生错误"
|
||||
}
|
||||
},
|
||||
"bs-version-oudated": {
|
||||
"title": "版本过时",
|
||||
"msg": "此 Beat Saber 版本已过时,请使用推荐版本以享受最新功能和修复。",
|
||||
"actions": {
|
||||
"do-not-remind": "不再提醒",
|
||||
"ok": "确定"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
@@ -719,12 +687,13 @@
|
||||
"stay": "记住我",
|
||||
"connect-to-meta": "连接到 Meta"
|
||||
},
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "启用旁加载",
|
||||
"info-1": "为了启动 Beat Saber,必须启用运行旁加载应用程序的功能。BSManager 将请求管理员权限以自动启用此功能。",
|
||||
"info-2": "旁加载功能允许启动位于 Oculus 库文件夹之外的游戏。",
|
||||
"info-3": "激活 sideloading 后,该功能将保持激活状态,您将不再被提示启用它。",
|
||||
"i-want-to-do-it-myself": "我想自己完成",
|
||||
"original-version-backup-oculus": {
|
||||
"title": "警告",
|
||||
"body": {
|
||||
"must-be-installed-once": "你必须至少从 Oculus 商店安装过一次 BeatSaber,否则 BeatSaber 可能会在启动后自动关闭。",
|
||||
"will-backup": "为了启动这个版本,位于您的Oculus库中的Beat Saber的原始安装文件夹将被重命名,并且在Beat Saber关闭时会自动恢复。"
|
||||
},
|
||||
"not-remind-me": "不再提醒我",
|
||||
"understood": "明白了"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
@@ -754,9 +723,6 @@
|
||||
},
|
||||
"launch-as-admin": "以管理员身份启动",
|
||||
"not-remind-me": "不再提醒我"
|
||||
},
|
||||
"bs-version-outdated": {
|
||||
"body": "版本 {outdatedVersion} 已过时,某些模组或功能可能无法正常工作。请下载最新推荐的 Beat Saber 版本 ({recommendedVersion}),以享受最新功能和修复。"
|
||||
}
|
||||
},
|
||||
"maps": {
|
||||
@@ -772,48 +738,48 @@
|
||||
"accuracy": "精确度",
|
||||
"balanced": "平衡",
|
||||
"challenge": "挑战",
|
||||
"dance-style": "舞蹈",
|
||||
"dancestyle": "舞蹈",
|
||||
"fitness": "健身",
|
||||
"speed": "速度",
|
||||
"tech": "技术"
|
||||
},
|
||||
"map-styles": {
|
||||
"dance": "舞蹈",
|
||||
"swing": "摇摆",
|
||||
"nightcore": "夜核",
|
||||
"folk-acoustic": "民谣 & 原声",
|
||||
"kids-family": "儿童 & 家庭",
|
||||
"ambient": "氛围音乐",
|
||||
"funk-disco": "放克 & 迪斯科",
|
||||
"jazz": "爵士",
|
||||
"soul": "灵魂",
|
||||
"speedcore": "极速核",
|
||||
"punk": "朋克",
|
||||
"dance": "dance",
|
||||
"swing": "swing",
|
||||
"nightcore": "nightcore",
|
||||
"folk": "folk",
|
||||
"family": "family",
|
||||
"ambient": "ambient",
|
||||
"funk": "funk",
|
||||
"jazz": "jazz",
|
||||
"soul": "soul",
|
||||
"speedcore": "speedcore",
|
||||
"punk": "punk",
|
||||
"rb": "r&b",
|
||||
"holiday": "假日",
|
||||
"vocaloid": "声库",
|
||||
"j-rock": "日式摇滚",
|
||||
"trance": "迷幻",
|
||||
"drum-and-bass": "鼓 & 贝斯",
|
||||
"comedy-meme": "喜剧 & 表情包",
|
||||
"instrumental": "纯音乐",
|
||||
"hardcore": "硬核",
|
||||
"holiday": "holiday",
|
||||
"vocaloid": "vocaloid",
|
||||
"j-rock": "j-rock",
|
||||
"trance": "trance",
|
||||
"drumbass": "drum & bass",
|
||||
"comedy": "comedy",
|
||||
"instrumental": "instrumental",
|
||||
"hardcore": "hardcore",
|
||||
"k-pop": "k-pop",
|
||||
"indie": "独立",
|
||||
"techno": "电子舞曲",
|
||||
"house": "浩室音乐",
|
||||
"video-game-soundtrack": "游戏音乐",
|
||||
"tv-movie-soundtrack": "电视 & 电影",
|
||||
"alternative": "另类",
|
||||
"dubstep": "电音鼓",
|
||||
"metal": "金属",
|
||||
"anime": "动漫",
|
||||
"hip-hop-rap": "嘻哈 & 说唱",
|
||||
"j-pop": "日式流行",
|
||||
"rock": "摇滚",
|
||||
"pop": "流行",
|
||||
"electronic": "电子",
|
||||
"classical-orchestral": "古典 & 管弦乐"
|
||||
"indie": "indie",
|
||||
"techno": "techno",
|
||||
"house": "house",
|
||||
"game": "video game",
|
||||
"film": "film",
|
||||
"alt": "alternative",
|
||||
"dubstep": "dubstep",
|
||||
"metal": "metal",
|
||||
"anime": "anime",
|
||||
"hiphop": "hiphop",
|
||||
"j-pop": "j-pop",
|
||||
"rock": "rock",
|
||||
"pop": "pop",
|
||||
"electronic": "electronic",
|
||||
"classical-orchestral": "Classical & Orchestral"
|
||||
},
|
||||
"map-specificities": {
|
||||
"automapper": "AI",
|
||||
@@ -997,6 +963,10 @@
|
||||
"go-to-mods": "前往 Mod 页",
|
||||
"not-remind": "不再提醒我"
|
||||
},
|
||||
"prevent-for-models-breaks": {
|
||||
"title": "已损坏的模型",
|
||||
"desc": "自从Beat Saber引擎更新以来,所有自定义模型的MOD都已损坏,需要更新。它们还没有被更新。"
|
||||
},
|
||||
"export-success": {
|
||||
"title": "导出成功 🎉"
|
||||
}
|
||||
@@ -1028,6 +998,122 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
"error-playlist-creation-title": "创建播放列表时出错",
|
||||
"error-playlist-creation-desc": "创建播放列表时发生错误。",
|
||||
"playlist-created-title": "播放列表已创建",
|
||||
"playlist-created-desc": "播放列表已成功创建。您现在可以同步其地图了!",
|
||||
"download-playlist": "下载播放列表",
|
||||
"synchronize-playlist": "同步播放列表",
|
||||
"synchronize-maps": "同步地图",
|
||||
"error-playlists-synchronization-title": "同步播放列表时出错",
|
||||
"error-playlists-synchronization-desc": "同步播放列表时发生错误。",
|
||||
"playlists-synchronized-title": "播放列表已同步!",
|
||||
"playlists-synchronized-desc": "播放列表及其地图已下载。",
|
||||
"playlists-export-error-title": "导出播放列表时出错",
|
||||
"playlists-export-error-desc": "导出播放列表时发生错误。",
|
||||
"playlists-exported-title": "播放列表已导出!",
|
||||
"playlists-exported-desc": "播放列表已成功导出。",
|
||||
"playlists-with-maps-exported-desc": "播放列表及其地图已成功导出。",
|
||||
"playlist-delete-error-title": "删除播放列表时出错",
|
||||
"playlist-delete-error-desc": "删除播放列表时发生错误。",
|
||||
"playlists-deleted-title": "播放列表已删除!",
|
||||
"playlists-deleted-desc": "播放列表已成功删除。",
|
||||
"edit-playlist": "编辑播放列表",
|
||||
"playlist-edit-error-title": "编辑播放列表时出错",
|
||||
"playlist-edit-error-desc": "编辑播放列表时发生错误。",
|
||||
"playlist-edited-title": "播放列表已编辑!",
|
||||
"playlist-edited-desc": "播放列表已成功修改。您现在可以同步其地图了!",
|
||||
"playlists-loading": "正在加载播放列表...",
|
||||
"no-playlists": "没有播放列表",
|
||||
"download-playlists": "下载播放列表",
|
||||
"created-by": "创建者",
|
||||
"stop-download": "停止下载",
|
||||
"cancel-download": "取消下载",
|
||||
"open-file": "打开文件",
|
||||
"link-playlists": "链接播放列表",
|
||||
"link-playlist-desc": "链接播放列表允许在所有版本之间共享播放列表。一旦链接,此版本将受益于共享播放列表",
|
||||
"link-playlist-info": "添加和删除播放列表也将被共享",
|
||||
"keep-playlists": "保留播放列表",
|
||||
"keep-playlists-tip": "保留播放列表将把当前版本的播放列表移动到共享播放列表文件夹。否则,它们将丢失",
|
||||
"unlink-playlists": "取消链接播放列表",
|
||||
"unlink-playlist-desc": "警告,取消链接播放列表将不再允许此版本使用共享播放列表。",
|
||||
"unlink-keep-playlists-tip": "保留播放列表将为当前版本创建共享播放列表的副本。否则,此版本将不保留任何播放列表。",
|
||||
"delete-playlist-ask": "删除播放列表?",
|
||||
"delete-playlists-ask": "删除播放列表?",
|
||||
"delete-playlist-desc": "您确定要删除播放列表 \"{playlistTitle}\" 吗?",
|
||||
"delete-playlists-desc": "您确定要删除 {nb} 个播放列表吗?",
|
||||
"delete-maps": "删除地图",
|
||||
"delete-playlist-maps-tip": "如果启用,播放列表中的所有地图都将被删除",
|
||||
"delete-playlists-maps-tip": "如果启用,播放列表中的所有地图都将被删除",
|
||||
"export-playlist-ask": "导出播放列表?",
|
||||
"export-playlists-ask": "导出播放列表?",
|
||||
"export-playlist-desc": "您确定要导出播放列表 \"{playlistTitle}\" 吗?",
|
||||
"export-playlists-desc": "您确定要导出 {nb} 个播放列表吗?",
|
||||
"export-maps": "导出地图",
|
||||
"export-playlist-maps-tip": "如果启用,播放列表中的所有地图也将被导出",
|
||||
"export-playlists-maps-tip": "如果启用,播放列表中的所有地图也将被导出",
|
||||
"export": "导出",
|
||||
"need-clone-title": "警告",
|
||||
"need-clone-desc-1": "此播放列表已从外部站点下载,并包含同步链接。",
|
||||
"need-clone-desc-2": "为避免在同步过程中丢失更改,播放列表将被复制,并删除其同步链接。",
|
||||
"need-clone-desc-3": "然后,如果您愿意,可以删除原始播放列表。",
|
||||
"understood": "我明白了",
|
||||
"synchronize-playlist-ask": "同步播放列表?",
|
||||
"synchronize-playlists-ask": "同步播放列表?",
|
||||
"synchronize-playlist-desc": "您确定要同步播放列表 \"{playlistTitle}\" 吗?",
|
||||
"synchronize-playlists-desc": "您确定要同步 {nb} 个播放列表吗?",
|
||||
"synchronize-playlist-tip": "此操作更新播放列表并下载缺失的地图;可能需要几分钟。",
|
||||
"synchronize": "同步",
|
||||
"curated": "推荐",
|
||||
"verified-mapper": "已验证的制图者",
|
||||
"empty-playlists": "空播放列表",
|
||||
"search-playlist": "搜索播放列表",
|
||||
"no-playlists-found": "未找到播放列表",
|
||||
"error-occur-while-loading-playlists": "加载播放列表时发生错误",
|
||||
"error-occur-while-loading-playlist": "加载播放列表时发生错误",
|
||||
"loading-maps": "正在加载地图...",
|
||||
"no-maps-found-for-playlist": "未找到此播放列表的地图",
|
||||
"playlist-contain-no-maps": "播放列表不包含地图",
|
||||
"no-map-installed-for-playlist": "此播放列表没有已安装的地图",
|
||||
"playlist-is-waiting-to-download": "播放列表正在等待下载",
|
||||
"download-maps": "下载地图",
|
||||
"download-missing-maps": "下载缺失的地图",
|
||||
"playlist-is-downloading": "播放列表正在下载",
|
||||
"some-playlist-maps-are-missing": "此播放列表中的一些地图缺失",
|
||||
"create-a-playlist": "创建播放列表",
|
||||
"synchronize-playlists": "同步播放列表",
|
||||
"export-playlists": "导出播放列表",
|
||||
"delete-playlists": "删除播放列表",
|
||||
"choose-image": "选择图片",
|
||||
"title": "标题",
|
||||
"playlist-title": "播放列表标题",
|
||||
"description": "描述",
|
||||
"playlist-description": "播放列表描述",
|
||||
"author": "作者",
|
||||
"playlist-author": "播放列表作者",
|
||||
"save": "保存",
|
||||
"loading": "加载中...",
|
||||
"installed": "已安装",
|
||||
"no-map-found": "未找到地图",
|
||||
"edit-playlist-shortcuts": "按住 Shift 或 Ctrl 选择多个地图",
|
||||
"add-to-playlist": "添加到播放列表",
|
||||
"remove-from-playlist": "从播放列表中移除",
|
||||
"playlist-is-empty": "播放列表为空",
|
||||
"continue": "继续",
|
||||
"nb-maps": "地图数量",
|
||||
"nb-mappers": "制图者数量",
|
||||
"duration": "持续时间",
|
||||
"nps": "每秒音符数",
|
||||
"date-picker": {
|
||||
"start-date-end-date": "开始日期 — 结束日期",
|
||||
"all": "全部",
|
||||
"last-24h": "最近24小时",
|
||||
"last-week": "上周",
|
||||
"last-month": "上个月",
|
||||
"3-last-month": "最近3个月"
|
||||
}
|
||||
},
|
||||
"dateformat": {
|
||||
"dayNames": ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
|
||||
"monthNames": ["1 月", "2 月", "3 月", "4 月", "5 月", "6 月", "7 月", "8 月", "9 月", "10 月", "11 月", "12 月", "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package song_details_cache_v1;
|
||||
|
||||
message SongDetailsCache {
|
||||
repeated SongDetails songs = 1;
|
||||
uint32 lastUpdated = 2;
|
||||
uint32 total = 3;
|
||||
UploadersList uploaders = 4;
|
||||
repeated string difficultyLabels = 5;
|
||||
}
|
||||
|
||||
message UploadersList {
|
||||
repeated string names = 1;
|
||||
repeated uint32 ids = 2;
|
||||
}
|
||||
|
||||
message SongDetails {
|
||||
uint32 idInt = 1;
|
||||
repeated uint32 hashIndices = 2;
|
||||
string name = 3;
|
||||
uint32 duration = 4;
|
||||
UploaderRef uploaderRef = 5;
|
||||
uint32 uploadedAt = 6;
|
||||
repeated MapTag tags = 7;
|
||||
bool ranked = 8;
|
||||
bool qualified = 9;
|
||||
bool curated = 10;
|
||||
bool blRanked = 11;
|
||||
bool blQualified = 12;
|
||||
uint32 upVotes = 13;
|
||||
uint32 downVotes = 14;
|
||||
uint32 downloads = 15;
|
||||
bool automapper = 16;
|
||||
repeated Difficulty difficulties = 17;
|
||||
}
|
||||
|
||||
message Difficulty {
|
||||
DifficultyLabel difficulty = 1;
|
||||
DifficultyCharacteristic characteristic = 2;
|
||||
uint32 labelIndex = 3;
|
||||
uint32 starsT100 = 4;
|
||||
uint32 starsBlT100 = 5;
|
||||
uint32 njsT100 = 6;
|
||||
uint32 npsT100 = 7;
|
||||
int32 offsetT100 = 8;
|
||||
bool chroma = 9;
|
||||
bool cinema = 10;
|
||||
bool me = 11;
|
||||
bool ne = 12;
|
||||
uint32 bombs = 13;
|
||||
uint32 notes = 14;
|
||||
uint32 obstacles = 15;
|
||||
}
|
||||
|
||||
message UploaderRef {
|
||||
uint32 uploader_ref_index = 1;
|
||||
bool verified = 2;
|
||||
}
|
||||
|
||||
enum DifficultyLabel {
|
||||
UNKNOWN_LABEL = 0; // Default value for undefined/unknown labels
|
||||
EASY = 1;
|
||||
NORMAL = 2;
|
||||
HARD = 3;
|
||||
EXPERT = 4;
|
||||
EXPERT_PLUS = 5;
|
||||
}
|
||||
|
||||
enum DifficultyCharacteristic {
|
||||
UNKNOWN_CHARACTERISTIC = 0; // Default value for undefined/unknown characteristics
|
||||
STANDARD = 1;
|
||||
ONE_SABER = 2;
|
||||
NO_ARROWS = 3;
|
||||
LAWLESS = 4;
|
||||
LIGHTSHOW = 5;
|
||||
LEGACY = 6;
|
||||
NINETY_DEGREE = 7;
|
||||
THREESIXTY_DEGREE = 8;
|
||||
}
|
||||
|
||||
enum MapTag {
|
||||
UNKNOWN_TAG = 0; // Default value for undefined/unknown tags
|
||||
DANCE = 1;
|
||||
SWING = 2;
|
||||
NIGHTCORE = 3;
|
||||
FOLK = 4;
|
||||
FAMILY = 5;
|
||||
AMBIENT = 6;
|
||||
FUNK = 7;
|
||||
JAZZ = 8;
|
||||
SOUL = 9;
|
||||
SPEEDCORE = 10;
|
||||
PUNK = 11;
|
||||
RB = 12;
|
||||
HOLIDAY = 13;
|
||||
VOCALOID = 14;
|
||||
J_ROCK = 15;
|
||||
TRANCE = 16;
|
||||
DRUMBASS = 17;
|
||||
COMEDY = 18;
|
||||
INSTRUMENTAL = 19;
|
||||
HARDCORE = 20;
|
||||
K_POP = 21;
|
||||
INDIE = 22;
|
||||
TECHNO = 23;
|
||||
HOUSE = 24;
|
||||
GAME = 25;
|
||||
FILM = 26;
|
||||
ALT = 27;
|
||||
DUBSTEP = 28;
|
||||
METAL = 29;
|
||||
ANIME = 30;
|
||||
HIPHOP = 31;
|
||||
J_POP = 32;
|
||||
ROCK = 33;
|
||||
POP = 34;
|
||||
ELECTRONIC = 35;
|
||||
CLASSICAL_ORCHESTRAL = 36;
|
||||
ACCURACY = 37;
|
||||
BALANCED = 38;
|
||||
CHALLENGE = 39;
|
||||
DANCESTYLE = 40;
|
||||
FITNESS = 41;
|
||||
SPEED = 42;
|
||||
TECH = 43;
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v8.0/win-x64",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v8.0": {},
|
||||
".NETCoreApp,Version=v8.0/win-x64": {
|
||||
"DepotDownloader/2.7.3": {
|
||||
"dependencies": {
|
||||
"Microsoft.Windows.CsWin32": "0.3.106",
|
||||
"SteamKit2": "3.0.0-Beta.4",
|
||||
"protobuf-net": "3.2.30"
|
||||
},
|
||||
"runtime": {
|
||||
"DepotDownloader.dll": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/5.0.0": {},
|
||||
"Microsoft.Win32.Registry/5.0.0": {
|
||||
"dependencies": {
|
||||
"System.Security.AccessControl": "5.0.0",
|
||||
"System.Security.Principal.Windows": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32/0.3.106": {
|
||||
"dependencies": {
|
||||
"Microsoft.Windows.SDK.Win32Docs": "0.1.42-alpha",
|
||||
"Microsoft.Windows.SDK.Win32Metadata": "60.0.34-preview",
|
||||
"Microsoft.Windows.WDK.Win32Metadata": "0.11.4-experimental"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs/0.1.42-alpha": {},
|
||||
"Microsoft.Windows.SDK.Win32Metadata/60.0.34-preview": {},
|
||||
"Microsoft.Windows.WDK.Win32Metadata/0.11.4-experimental": {
|
||||
"dependencies": {
|
||||
"Microsoft.Windows.SDK.Win32Metadata": "60.0.34-preview"
|
||||
}
|
||||
},
|
||||
"protobuf-net/3.2.30": {
|
||||
"dependencies": {
|
||||
"protobuf-net.Core": "3.2.30"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net6.0/protobuf-net.dll": {
|
||||
"assemblyVersion": "3.0.0.0",
|
||||
"fileVersion": "3.2.30.709"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protobuf-net.Core/3.2.30": {
|
||||
"dependencies": {
|
||||
"System.Collections.Immutable": "7.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net6.0/protobuf-net.Core.dll": {
|
||||
"assemblyVersion": "3.0.0.0",
|
||||
"fileVersion": "3.2.30.709"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SteamKit2/3.0.0-Beta.4": {
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.Registry": "5.0.0",
|
||||
"System.IO.Hashing": "8.0.0",
|
||||
"protobuf-net": "3.2.30"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net8.0/SteamKit2.dll": {
|
||||
"assemblyVersion": "3.0.0.0",
|
||||
"fileVersion": "3.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Collections.Immutable/7.0.0": {},
|
||||
"System.IO.Hashing/8.0.0": {
|
||||
"runtime": {
|
||||
"lib/net8.0/System.IO.Hashing.dll": {
|
||||
"assemblyVersion": "8.0.0.0",
|
||||
"fileVersion": "8.0.23.53103"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Security.AccessControl/5.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "5.0.0",
|
||||
"System.Security.Principal.Windows": "5.0.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Principal.Windows/5.0.0": {}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"DepotDownloader/2.7.3": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==",
|
||||
"path": "microsoft.netcore.platforms/5.0.0",
|
||||
"hashPath": "microsoft.netcore.platforms.5.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Win32.Registry/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
|
||||
"path": "microsoft.win32.registry/5.0.0",
|
||||
"hashPath": "microsoft.win32.registry.5.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Windows.CsWin32/0.3.106": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Mx5fK7uN6fwLR4wUghs6//HonAnwPBNmC2oonyJVhCUlHS/r6SUS3NkBc3+gaQiv+0/9bqdj1oSCKQFkNI+21Q==",
|
||||
"path": "microsoft.windows.cswin32/0.3.106",
|
||||
"hashPath": "microsoft.windows.cswin32.0.3.106.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs/0.1.42-alpha": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Z/9po23gUA9aoukirh2ItMU2ZS9++Js9Gdds9fu5yuMojDrmArvY2y+tq9985tR3cxFxpZO1O35Wjfo0khj5HA==",
|
||||
"path": "microsoft.windows.sdk.win32docs/0.1.42-alpha",
|
||||
"hashPath": "microsoft.windows.sdk.win32docs.0.1.42-alpha.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Metadata/60.0.34-preview": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-TA3DUNi4CTeo+ItTXBnGZFt2159XOGSl0UOlG5vjDj4WHqZjhwYyyUnzOtrbCERiSaP2Hzg7otJNWwOSZgutyA==",
|
||||
"path": "microsoft.windows.sdk.win32metadata/60.0.34-preview",
|
||||
"hashPath": "microsoft.windows.sdk.win32metadata.60.0.34-preview.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Windows.WDK.Win32Metadata/0.11.4-experimental": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-bf5MCmUyZf0gBlYQjx9UpRAZWBkRndyt9XicR+UNLvAUAFTZQbu6YaX/sNKZlR98Grn0gydfh/yT4I3vc0AIQA==",
|
||||
"path": "microsoft.windows.wdk.win32metadata/0.11.4-experimental",
|
||||
"hashPath": "microsoft.windows.wdk.win32metadata.0.11.4-experimental.nupkg.sha512"
|
||||
},
|
||||
"protobuf-net/3.2.30": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-C/UTlmxEJHAHpqm8xQK1UyJKaIynVCSNG4mVrbLgnZ7ccH28nN49O8iMJvKEodTgVbnimvy+3mIiAdW6mATwnw==",
|
||||
"path": "protobuf-net/3.2.30",
|
||||
"hashPath": "protobuf-net.3.2.30.nupkg.sha512"
|
||||
},
|
||||
"protobuf-net.Core/3.2.30": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-v2ZxxYrz+X212ukSx+uqkLuPu414bvmSAnTyf+PBUKR9ENJxO4P/csorA/27456MCp1JNoMssDj/f91RDiwBfQ==",
|
||||
"path": "protobuf-net.core/3.2.30",
|
||||
"hashPath": "protobuf-net.core.3.2.30.nupkg.sha512"
|
||||
},
|
||||
"SteamKit2/3.0.0-Beta.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-gDLccGTbvg5RzqQE75uqL3z2Z0F8MTOnier97DdbBGi9F6DDbZQvquHf0INOAEyN7S5Ku+CgaKnkm409UD7avA==",
|
||||
"path": "steamkit2/3.0.0-beta.4",
|
||||
"hashPath": "steamkit2.3.0.0-beta.4.nupkg.sha512"
|
||||
},
|
||||
"System.Collections.Immutable/7.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==",
|
||||
"path": "system.collections.immutable/7.0.0",
|
||||
"hashPath": "system.collections.immutable.7.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.IO.Hashing/8.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ne1843evDugl0md7Fjzy6QjJrzsjh46ZKbhf8GwBXb5f/gw97J4bxMs0NQKifDuThh/f0bZ0e62NPl1jzTuRqA==",
|
||||
"path": "system.io.hashing/8.0.0",
|
||||
"hashPath": "system.io.hashing.8.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Security.AccessControl/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
|
||||
"path": "system.security.accesscontrol/5.0.0",
|
||||
"hashPath": "system.security.accesscontrol.5.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Security.Principal.Windows/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==",
|
||||
"path": "system.security.principal.windows/5.0.0",
|
||||
"hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net8.0",
|
||||
"rollForward": "LatestMajor",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "8.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 945 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 442 KiB After Width: | Height: | Size: 442 KiB |
|
Before Width: | Height: | Size: 31 KiB |
@@ -1,11 +0,0 @@
|
||||
Enabling Oculus sideloading allows games located outside if your Oculus library to be played on your Oculus Quest.
|
||||
|
||||
- **Step 1:** Start the regedit application by pressing `Win + R` and typing `regedit` in the dialog box.
|
||||
- **Step 2:** Navigate to `HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Oculus VR, LLC\Oculus`.
|
||||
- **Step 3:** Right-click on the right panel and select `New > DWORD (32-bit) Value`.
|
||||
- **Step 4:** Name the new value `AllowDevSideloaded` and set the value to `1`.
|
||||
|
||||
You should end up with something like this:
|
||||

|
||||
|
||||
After completing these steps, you should be able to start Beat Saber from BSManager and play it on your Oculus Quest. If you are still having issues, please join our [Discord](https://discord.gg/uSqbHVpKdV) server for further assistance.
|
||||
@@ -2,52 +2,6 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6ea2a48c204030ee31a7d7fc72c93294c92fe87ecb1789881c9543516e1a0d"
|
||||
dependencies = [
|
||||
"value-bag",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.76"
|
||||
@@ -66,12 +20,6 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.195"
|
||||
@@ -92,112 +40,13 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_fmt"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "start_beat_saber_admin"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"simplelog",
|
||||
"winres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6dc0f9830c49db20e73273ffae9b5240f63c42e515af1da1fceefb69fceafd8"
|
||||
|
||||
[[package]]
|
||||
name = "sval_buffer"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "429922f7ad43c0ef8fd7309e14d750e38899e32eb7e8da656ea169dd28ee212f"
|
||||
dependencies = [
|
||||
"sval",
|
||||
"sval_ref",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_dynamic"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f16ff5d839396c11a30019b659b0976348f3803db0626f736764c473b50ff4"
|
||||
dependencies = [
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_fmt"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c01c27a80b6151b0557f9ccbe89c11db571dc5f68113690c1e028d7e974bae94"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_json"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0deef63c70da622b2a8069d8600cf4b05396459e665862e7bdb290fd6cf3f155"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_nested"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a39ce5976ae1feb814c35d290cf7cf8cd4f045782fe1548d6bc32e21f6156e9f"
|
||||
dependencies = [
|
||||
"sval",
|
||||
"sval_buffer",
|
||||
"sval_ref",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_ref"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb7c6ee3751795a728bc9316a092023529ffea1783499afbc5c66f5fabebb1fa"
|
||||
dependencies = [
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_serde"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a5572d0321b68109a343634e3a5d576bf131b82180c6c442dee06349dfc652a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"sval",
|
||||
"sval_nested",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.48"
|
||||
@@ -209,37 +58,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
@@ -249,54 +67,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
|
||||
dependencies = [
|
||||
"value-bag-serde1",
|
||||
"value-bag-sval2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "value-bag-serde1"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb773bd36fd59c7ca6e336c94454d9c66386416734817927ac93d81cb3c5b0b"
|
||||
dependencies = [
|
||||
"erased-serde",
|
||||
"serde",
|
||||
"serde_fmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "value-bag-sval2"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53a916a702cac43a88694c97657d449775667bcd14b70419441d05b7fea4a83a"
|
||||
dependencies = [
|
||||
"sval",
|
||||
"sval_buffer",
|
||||
"sval_dynamic",
|
||||
"sval_fmt",
|
||||
"sval_json",
|
||||
"sval_ref",
|
||||
"sval_serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winres"
|
||||
version = "0.1.12"
|
||||
|
||||
@@ -4,10 +4,6 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
simplelog = { version = "0.12.2", default-features = false }
|
||||
log = "0.4.24"
|
||||
|
||||
[build-dependencies]
|
||||
winres = "0.1.12"
|
||||
|
||||
@@ -15,7 +11,6 @@ winres = "0.1.12"
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
panic = "abort"
|
||||
|
||||
[package.metadata.winres]
|
||||
FileDescription = "Start Beat Saber as Admin"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "1.77.0"
|
||||
@@ -1,10 +1,5 @@
|
||||
|
||||
use std::{process::Command, path::Path};
|
||||
use std::env::current_exe;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use log::{error, info, LevelFilter};
|
||||
use simplelog::{CombinedLogger, Config, WriteLogger};
|
||||
|
||||
const EXECUTABLE_NAME: &str = "Beat Saber.exe";
|
||||
const AUTORIZED_ARGS: [&str; 8] = [
|
||||
@@ -19,37 +14,18 @@ const AUTORIZED_ARGS: [&str; 8] = [
|
||||
];
|
||||
|
||||
fn main() {
|
||||
|
||||
let default_log_file_path = current_exe().unwrap().with_file_name("bs-admin-start.log");
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
let log_file_path: PathBuf = if let Some(pos) = args.iter().position(|arg| arg == "--log-path") {
|
||||
if let Some(log_path) = args.get(pos + 1) {
|
||||
PathBuf::from(log_path)
|
||||
} else {
|
||||
default_log_file_path
|
||||
}
|
||||
} else {
|
||||
default_log_file_path
|
||||
};
|
||||
|
||||
CombinedLogger::init(
|
||||
vec![
|
||||
WriteLogger::new(LevelFilter::Info, Config::default(), File::create(log_file_path).unwrap()),
|
||||
]
|
||||
).unwrap();
|
||||
|
||||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
let executable_path = Path::new(&args[1]);
|
||||
|
||||
if executable_path.file_name().unwrap() != EXECUTABLE_NAME {
|
||||
return error!("Executable path is not Beat Saber.exe.");
|
||||
eprintln!("Executable path is not Beat Saber.exe.");
|
||||
return;
|
||||
}
|
||||
|
||||
if !executable_path.exists() || !executable_path.is_file() {
|
||||
return error!("Executable path is not valid.");
|
||||
eprintln!("Executable path is not valid.");
|
||||
return;
|
||||
}
|
||||
|
||||
let mut command = Command::new(executable_path);
|
||||
@@ -67,11 +43,5 @@ fn main() {
|
||||
|
||||
command.env("SteamAppId", "620980");
|
||||
|
||||
let res = command.spawn();
|
||||
|
||||
if let Err(e) = res {
|
||||
return error!("Failed to start Beat Saber ({}): {}", executable_path.display(), e);
|
||||
}
|
||||
|
||||
info!("Beat Saber started ({})", executable_path.display());
|
||||
let _ = command.spawn();
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
@@ -1,390 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6ea2a48c204030ee31a7d7fc72c93294c92fe87ecb1789881c9543516e1a0d"
|
||||
dependencies = [
|
||||
"value-bag",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "oculus-allow-dev-sideloaded"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"simplelog",
|
||||
"winreg",
|
||||
"winres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_fmt"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6dc0f9830c49db20e73273ffae9b5240f63c42e515af1da1fceefb69fceafd8"
|
||||
|
||||
[[package]]
|
||||
name = "sval_buffer"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "429922f7ad43c0ef8fd7309e14d750e38899e32eb7e8da656ea169dd28ee212f"
|
||||
dependencies = [
|
||||
"sval",
|
||||
"sval_ref",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_dynamic"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f16ff5d839396c11a30019b659b0976348f3803db0626f736764c473b50ff4"
|
||||
dependencies = [
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_fmt"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c01c27a80b6151b0557f9ccbe89c11db571dc5f68113690c1e028d7e974bae94"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_json"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0deef63c70da622b2a8069d8600cf4b05396459e665862e7bdb290fd6cf3f155"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_nested"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a39ce5976ae1feb814c35d290cf7cf8cd4f045782fe1548d6bc32e21f6156e9f"
|
||||
dependencies = [
|
||||
"sval",
|
||||
"sval_buffer",
|
||||
"sval_ref",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_ref"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb7c6ee3751795a728bc9316a092023529ffea1783499afbc5c66f5fabebb1fa"
|
||||
dependencies = [
|
||||
"sval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sval_serde"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a5572d0321b68109a343634e3a5d576bf131b82180c6c442dee06349dfc652a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"sval",
|
||||
"sval_nested",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
|
||||
dependencies = [
|
||||
"value-bag-serde1",
|
||||
"value-bag-sval2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "value-bag-serde1"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb773bd36fd59c7ca6e336c94454d9c66386416734817927ac93d81cb3c5b0b"
|
||||
dependencies = [
|
||||
"erased-serde",
|
||||
"serde",
|
||||
"serde_fmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "value-bag-sval2"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53a916a702cac43a88694c97657d449775667bcd14b70419441d05b7fea4a83a"
|
||||
dependencies = [
|
||||
"sval",
|
||||
"sval_buffer",
|
||||
"sval_dynamic",
|
||||
"sval_fmt",
|
||||
"sval_json",
|
||||
"sval_ref",
|
||||
"sval_serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winres"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
|
||||
dependencies = [
|
||||
"toml",
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
extern crate winres;
|
||||
|
||||
fn main() {
|
||||
if cfg!(target_os = "windows") {
|
||||
let mut res = winres::WindowsResource::new();
|
||||
res.set_manifest(r#"
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
"#);
|
||||
res.set_icon("./icon.ico");
|
||||
res.compile().unwrap();
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "1.77.0"
|
||||
@@ -1,48 +0,0 @@
|
||||
use std::env::current_exe;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use simplelog::{CombinedLogger, Config, LevelFilter, WriteLogger};
|
||||
use winreg::enums::HKEY_LOCAL_MACHINE;
|
||||
use winreg::RegKey;
|
||||
use log::{error, info};
|
||||
|
||||
const REG_PATH: &str = "SOFTWARE\\Wow6432Node\\Oculus VR, LLC\\Oculus";
|
||||
|
||||
fn main() {
|
||||
|
||||
let default_log_file_path = current_exe().unwrap().with_file_name("oculus-allow-dev-sideloaded.log");
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
let log_file_path: PathBuf = if let Some(pos) = args.iter().position(|arg| arg == "--log-path") {
|
||||
if let Some(log_path) = args.get(pos + 1) {
|
||||
PathBuf::from(log_path)
|
||||
} else {
|
||||
default_log_file_path
|
||||
}
|
||||
} else {
|
||||
default_log_file_path
|
||||
};
|
||||
|
||||
CombinedLogger::init(
|
||||
vec![
|
||||
WriteLogger::new(LevelFilter::Info, Config::default(), File::create(log_file_path).unwrap()),
|
||||
]
|
||||
).unwrap();
|
||||
|
||||
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
|
||||
|
||||
info!("Opening or creating subkey ({})...", REG_PATH);
|
||||
let (key, _) = match hklm.create_subkey(REG_PATH) {
|
||||
Ok(res) => res,
|
||||
Err(err) => return error!("Unable to create subkey ({}) : {}", REG_PATH, err.to_string())
|
||||
};
|
||||
|
||||
info!("Setting value AllowDevSideloaded = 1 in {REG_PATH}...");
|
||||
let res = key.set_value("AllowDevSideloaded", &1u32);
|
||||
|
||||
if let Err(err) = res {
|
||||
return error!("Unable to set value AllowDevSideloaded = 1 in {REG_PATH} : {}", err.to_string());
|
||||
}
|
||||
|
||||
info!("AllowDevSideloaded = 1 has been successfully set in {REG_PATH}");
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
@@ -0,0 +1,281 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oculus_symlink_cleaner"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sysinfo",
|
||||
"winres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.30.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6746919caf9f2a85bff759535664c060109f21975c5ac2e8652e60102bd4d196"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"ntapi",
|
||||
"once_cell",
|
||||
"rayon",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
|
||||
[[package]]
|
||||
name = "winres"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
|
||||
dependencies = [
|
||||
"toml",
|
||||
]
|
||||
@@ -1,24 +1,22 @@
|
||||
[package]
|
||||
name = "oculus-allow-dev-sideloaded"
|
||||
name = "oculus_symlink_cleaner"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
winres = "0.1.12"
|
||||
|
||||
|
||||
[dependencies]
|
||||
winreg = "0.52.0"
|
||||
simplelog = { version = "0.12.2", default-features = false }
|
||||
log = "0.4.24"
|
||||
|
||||
[package.metadata.winres]
|
||||
FileDescription = "Enable Sideloaded Apps"
|
||||
LegalCopyright = "Copyright © 2024 Zagrios"
|
||||
CompanyName = "Zagrios"
|
||||
sysinfo = "0.30.6"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
panic = "abort"
|
||||
|
||||
[package.metadata.winres]
|
||||
FileDescription = "Clean Oculus Symlink after Beat Saber ends"
|
||||
LegalCopyright = "Copyright © 2024 Zagrios"
|
||||
CompanyName = "Zagrios"
|
||||
@@ -0,0 +1,9 @@
|
||||
extern crate winres;
|
||||
|
||||
fn main() {
|
||||
if cfg!(target_os = "windows") {
|
||||
let mut res = winres::WindowsResource::new();
|
||||
res.set_icon("./icon.ico");
|
||||
res.compile().unwrap();
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
@@ -0,0 +1,78 @@
|
||||
use sysinfo::{Pid, ProcessRefreshKind, System};
|
||||
use std::{env, thread, time::Duration, fs};
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
const BEAT_SABER_OCULUS_FOLDER_NAME: &str = "hyperbolic-magnetism-beat-saber";
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 3 {
|
||||
eprintln!("Usage: {} <pid> <path_to_directory>", args[0]);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let pid: Pid = Pid::from_str(&args[1]).expect("Invalid pid");
|
||||
let directory_path = Path::new(&args[2]);
|
||||
|
||||
if directory_path.file_name() != Some(OsStr::new(BEAT_SABER_OCULUS_FOLDER_NAME)) {
|
||||
eprintln!("Directory name is not {}", BEAT_SABER_OCULUS_FOLDER_NAME);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// we want to monitor only processes
|
||||
let mut system = System::new_with_specifics(sysinfo::RefreshKind::new().with_processes(ProcessRefreshKind::everything()));
|
||||
|
||||
loop {
|
||||
system.refresh_processes();
|
||||
let process = system.process(pid);
|
||||
|
||||
match process {
|
||||
Some(_) => {
|
||||
println!("Process {} is still running.", pid);
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
},
|
||||
None => {
|
||||
println!("Process {} has stopped, deleting directory {:?}", pid, directory_path);
|
||||
match delete_dir_if_is_symlink(directory_path) {
|
||||
Ok(_) => {
|
||||
println!("Directory {:?} deleted successfully.", directory_path);
|
||||
if let Err(e) = rename_specific_backup_directory(directory_path.parent().unwrap()) {
|
||||
eprintln!("Failed to rename backup directory: {}", e);
|
||||
}
|
||||
},
|
||||
Err(e) => eprintln!("Failed to delete directory {:?}: {}", directory_path, e),
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_dir_if_is_symlink(path: &Path) -> Result<(), Box<dyn std::error::Error>>{
|
||||
match path.symlink_metadata()?.file_type().is_symlink() {
|
||||
true => {
|
||||
fs::remove_dir_all(path)?;
|
||||
Ok(())
|
||||
},
|
||||
false => {
|
||||
eprintln!("Path {:?} is not a symlink.", path);
|
||||
Err("Path is not a symlink.".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_specific_backup_directory(parent_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let backup_dir_name = format!("{}.bsmbak", BEAT_SABER_OCULUS_FOLDER_NAME);
|
||||
let backup_path = parent_path.join(&backup_dir_name);
|
||||
if backup_path.exists() && backup_path.is_dir() {
|
||||
let new_path = parent_path.join(BEAT_SABER_OCULUS_FOLDER_NAME);
|
||||
fs::rename(&backup_path, &new_path)?;
|
||||
println!("Renamed {:?} to {:?}", backup_path, new_path);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("Backup directory {:?} does not exist or is not a directory.", backup_path).into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import type { Config } from "jest";
|
||||
|
||||
const config: Config = {
|
||||
// testURL: "http://localhost/",
|
||||
// testEnvironment: "jsdom",
|
||||
transform: {
|
||||
"\\.(ts|tsx|js|jsx)$": "ts-jest",
|
||||
},
|
||||
moduleNameMapper: {
|
||||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/.erb/mocks/fileMock.js",
|
||||
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
|
||||
},
|
||||
moduleFileExtensions: ["js", "jsx", "ts", "tsx", "json"],
|
||||
moduleDirectories: ["node_modules", "src"],
|
||||
testPathIgnorePatterns: ["release/app/dist"],
|
||||
setupFiles: ["./.erb/scripts/check-build-exists.ts"],
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -1,21 +1,25 @@
|
||||
{
|
||||
"name": "bs-manager",
|
||||
"description": "Manage maps, mods and more for Beat Saber",
|
||||
"main": "./src/main/main.ts",
|
||||
"version": "1.5.0-alpha.1",
|
||||
"scripts": {
|
||||
"build-rust-scripts": "node -r esbuild-register ./.erb/scripts/build-rust-scripts.js",
|
||||
"build": "concurrently \"npm run build:main\" \"npm run build:renderer\"",
|
||||
"build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts",
|
||||
"build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
|
||||
"build:dll": "cross-env NODE_ENV=development webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts",
|
||||
"build:main": "cross-env NODE_ENV=production webpack --config ./.erb/configs/webpack.config.main.prod.ts",
|
||||
"build:renderer": "cross-env NODE_ENV=production webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
|
||||
"postinstall": "node -r esbuild-register .erb/scripts/check-native-dep.js && electron-builder install-app-deps && npm run build:dll",
|
||||
"rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
|
||||
"lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never",
|
||||
"postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts && opencollective-postinstall",
|
||||
"start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer",
|
||||
"start:main": "cross-env NODE_ENV=development electronmon -r ts-node/register/transpile-only ./src/main/main.ts",
|
||||
"start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts",
|
||||
"start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts",
|
||||
"package": "node -r esbuild-register ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never && npm run build:dll",
|
||||
"start": "node -r esbuild-register ./.erb/scripts/check-port-in-use.js && npm run start:renderer",
|
||||
"start:main": "cross-env NODE_ENV=development NODE_OPTIONS=\"--loader esbuild-register/loader -r esbuild-register\" electronmon .",
|
||||
"start:preload": "cross-env NODE_ENV=development webpack --config ./.erb/configs/webpack.config.preload.dev.ts",
|
||||
"start:renderer": "cross-env NODE_ENV=development webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts",
|
||||
"test": "jest",
|
||||
"test:unit": "jest ./src/__tests__/unit",
|
||||
"publish": "npm run build && electron-builder -c.win.certificateSha1=206941d969c4fa8a0e04d9427def361e13b02fd0 --publish always --win --x64"
|
||||
"publish": "npm run build && electron-builder -c.win.certificateSha1=842a817a51e2a1d360fcd62f54bf5f9193e919e1 --publish always --win --x64",
|
||||
"publish:linux": "npm run build && electron-builder --publish always --linux --x64"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
@@ -33,10 +37,9 @@
|
||||
},
|
||||
"build": {
|
||||
"extraResources": [
|
||||
"./assets/favicon.ico",
|
||||
"./assets/jsons/bs-versions.json",
|
||||
"./assets/jsons/patreons.json",
|
||||
"./assets/scripts/**"
|
||||
"./assets/proto/song_details_cache_v1.proto"
|
||||
],
|
||||
"productName": "BSManager",
|
||||
"appId": "org.erb.BSManager",
|
||||
@@ -48,49 +51,27 @@
|
||||
],
|
||||
"afterSign": ".erb/scripts/notarize.js",
|
||||
"afterPack": ".erb/scripts/after-pack.js",
|
||||
"mac": {
|
||||
"target": {
|
||||
"target": "default",
|
||||
"arch": [
|
||||
"arm64",
|
||||
"x64"
|
||||
]
|
||||
},
|
||||
"type": "distribution",
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "assets/entitlements.mac.plist",
|
||||
"entitlementsInherit": "assets/entitlements.mac.plist",
|
||||
"gatekeeperAssess": false
|
||||
},
|
||||
"dmg": {
|
||||
"contents": [
|
||||
{
|
||||
"x": 130,
|
||||
"y": 220
|
||||
},
|
||||
{
|
||||
"x": 410,
|
||||
"y": 220,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
}
|
||||
]
|
||||
},
|
||||
"win": {
|
||||
"signingHashAlgorithms": [
|
||||
"sha256"
|
||||
],
|
||||
"target": [
|
||||
"nsis",
|
||||
"nsis-web"
|
||||
],
|
||||
"icon": "assets/favicon.ico"
|
||||
"icon": "./build/icons/win/favicon.ico",
|
||||
"extraResources": [
|
||||
"./build/icons/win",
|
||||
"./assets/scripts/*.exe"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"target": [
|
||||
"AppImage"
|
||||
],
|
||||
"category": "Development"
|
||||
"icon": "./build/icons/png",
|
||||
"category": "Utility;Game;",
|
||||
"extraResources": [
|
||||
"./build/icons/png",
|
||||
"./assets/scripts/DepotDownloader"
|
||||
]
|
||||
},
|
||||
"directories": {
|
||||
"app": "release/app",
|
||||
@@ -100,7 +81,15 @@
|
||||
"publish": {
|
||||
"provider": "github",
|
||||
"owner": "Zagrios"
|
||||
}
|
||||
},
|
||||
"fileAssociations": [
|
||||
{
|
||||
"ext": "bplist",
|
||||
"description": "Beat Saber Playlist (BSManager)",
|
||||
"icon": "./assets/bsm_file.ico",
|
||||
"role": "Viewer"
|
||||
}
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -123,142 +112,181 @@
|
||||
"beat-saber"
|
||||
],
|
||||
"homepage": "https://github.com/Zagrios/bs-manager#readme",
|
||||
"jest": {
|
||||
"testURL": "http://localhost/",
|
||||
"testEnvironment": "jsdom",
|
||||
"transform": {
|
||||
"\\.(ts|tsx|js|jsx)$": "ts-jest"
|
||||
},
|
||||
"moduleNameMapper": {
|
||||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/.erb/mocks/fileMock.js",
|
||||
"\\.(css|less|sass|scss)$": "identity-obj-proxy"
|
||||
},
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"jsx",
|
||||
"ts",
|
||||
"tsx",
|
||||
"json"
|
||||
],
|
||||
"moduleDirectories": [
|
||||
"node_modules",
|
||||
"src"
|
||||
],
|
||||
"testPathIgnorePatterns": [
|
||||
"release/app/dist"
|
||||
],
|
||||
"setupFiles": [
|
||||
"./.erb/scripts/check-build-exists.ts"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron/rebuild": "^3.2.13",
|
||||
"@electron/fuses": "^1.7.0",
|
||||
"@electron/notarize": "^2.3.0",
|
||||
"@electron/rebuild": "^3.6.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "0.5.5",
|
||||
"@teamsupercell/typings-for-css-modules-loader": "^2.5.1",
|
||||
"@teamsupercell/typings-for-css-modules-loader": "^2.5.2",
|
||||
"@testing-library/jest-dom": "^6.4.1",
|
||||
"@testing-library/react": "^13.3.0",
|
||||
"@types/archiver": "^5.3.1",
|
||||
"@testing-library/react": "^14.2.0",
|
||||
"@types/archiver": "^6.0.2",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/crypto-js": "^4.2.1",
|
||||
"@types/dateformat": "^5.0.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/got": "^9.6.12",
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/node": "^20",
|
||||
"@types/node": "20.11.15",
|
||||
"@types/node-fetch": "^2.6.3",
|
||||
"@types/pako": "^2.0.1",
|
||||
"@types/react": "^18.0.33",
|
||||
"@types/react-beautiful-dnd": "^13.1.8",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/react-outside-click-handler": "^1.3.1",
|
||||
"@types/react-test-renderer": "^17.0.2",
|
||||
"@types/react-test-renderer": "^18.0.7",
|
||||
"@types/react-virtualized-auto-sizer": "^1.0.1",
|
||||
"@types/react-window": "^1.8.5",
|
||||
"@types/recursive-readdir": "^2.2.1",
|
||||
"@types/terser-webpack-plugin": "^5.0.4",
|
||||
"@types/to-ico": "^1.1.1",
|
||||
"@types/use-double-click": "^1.0.1",
|
||||
"@types/use-double-click": "^1.0.4",
|
||||
"@types/webpack-bundle-analyzer": "^4.4.2",
|
||||
"@types/webpack-env": "^1.18.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.34.0",
|
||||
"@typescript-eslint/parser": "^5.34.0",
|
||||
"autoprefixer": "^10.4.8",
|
||||
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
||||
"@typescript-eslint/parser": "^6.20.0",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"browserslist-config-erb": "^0.0.3",
|
||||
"chalk": "^4.1.2",
|
||||
"concurrently": "^7.2.2",
|
||||
"core-js": "^3.24.1",
|
||||
"concurrently": "^8.2.2",
|
||||
"core-js": "^3.36.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^4.1.0",
|
||||
"detect-port": "^1.3.0",
|
||||
"electron": "^27.1.3",
|
||||
"electron-builder": "^24.9.1",
|
||||
"css-loader": "^6.10.0",
|
||||
"css-minimizer-webpack-plugin": "^6.0.0",
|
||||
"detect-port": "^1.5.1",
|
||||
"electron": "^28.2.4",
|
||||
"electron-builder": "^24.13.3",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-notarize": "^1.2.1",
|
||||
"electronmon": "^2.0.2",
|
||||
"eslint": "^8.22.0",
|
||||
"esbuild": "^0.20.1",
|
||||
"esbuild-register": "^3.5.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-erb": "^4.0.3",
|
||||
"eslint-import-resolver-typescript": "^2.7.1",
|
||||
"eslint-import-resolver-webpack": "^0.13.2",
|
||||
"eslint-plugin-compat": "^4.0.2",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-config-erb": "^4.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-import-resolver-webpack": "^0.13.8",
|
||||
"eslint-plugin-compat": "^4.2.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jest": "^27.6.3",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
"eslint-plugin-react": "^7.30.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^29.7.0",
|
||||
"lint-staged": "^12.5.0",
|
||||
"mini-css-extract-plugin": "^2.6.1",
|
||||
"lint-staged": "^15.2.1",
|
||||
"mini-css-extract-plugin": "^2.7.7",
|
||||
"opencollective-postinstall": "^2.0.3",
|
||||
"postcss": "^8.4.16",
|
||||
"postcss-loader": "^6.2.1",
|
||||
"prettier": "^2.7.1",
|
||||
"postcss": "^8.4.33",
|
||||
"postcss-loader": "^8.1.0",
|
||||
"prettier": "^3.2.4",
|
||||
"ps-scrollbar-tailwind": "0.0.1",
|
||||
"react-refresh": "^0.12.0",
|
||||
"react-refresh-typescript": "^2.0.7",
|
||||
"react-refresh": "^0.14.0",
|
||||
"react-test-renderer": "^18.2.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass": "^1.54.5",
|
||||
"sass-loader": "^12.6.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"tailwind-scrollbar": "^2.0.1",
|
||||
"tailwindcss": "^3.4.15",
|
||||
"terser-webpack-plugin": "^5.3.5",
|
||||
"rimraf": "^5.0.5",
|
||||
"sass": "^1.70.0",
|
||||
"sass-loader": "^14.1.0",
|
||||
"style-loader": "^3.3.4",
|
||||
"tailwind-scrollbar": "^3.1.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-loader": "^9.3.0",
|
||||
"ts-node": "^10.8.2",
|
||||
"typescript": "^4.7.4",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.3.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-bundle-analyzer": "^4.6.1",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-dev-server": "^4.10.0",
|
||||
"webpack-merge": "^5.8.0"
|
||||
"webpack": "^5.90.3",
|
||||
"webpack-bundle-analyzer": "^4.10.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^4.15.1",
|
||||
"webpack-merge": "^5.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/fuses": "^1.6.2",
|
||||
"@internationalized/date": "^3.5.4",
|
||||
"@nextui-org/date-picker": "^2.0.7",
|
||||
"@nextui-org/react": "^2.3.6",
|
||||
"@node-steam/vdf": "^2.2.0",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
"@nextui-org/react": "^2.3.6",
|
||||
"archiver": "^6.0.1",
|
||||
"clsx": "^2.1.1",
|
||||
"color": "^4.2.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dateformat": "^5.0.3",
|
||||
"dompurify": "^3.0.9",
|
||||
"dot-prop": "^8.0.2",
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-updater": "^6.1.7",
|
||||
"electron-updater": "^6.2.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"framer-motion": "^11.2.6",
|
||||
"fs-extra": "^11.2.0",
|
||||
"got": "^14.4.1",
|
||||
"history": "^5.3.0",
|
||||
"is-elevated": "^3.0.0",
|
||||
"is-elevated": "^4.0.0",
|
||||
"jszip": "^3.10.1",
|
||||
"md5-file": "^5.0.0",
|
||||
"node-abi": "^3.65.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"node-fetch": "^3.3.2",
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"pako": "^2.1.0",
|
||||
"ps-list": "^7.2.0",
|
||||
"protobufjs": "^7.3.2",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"query-process": "^0.0.3",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-range": "^1.8.14",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-virtualized-auto-sizer": "^1.0.12",
|
||||
"react-window": "^1.8.8",
|
||||
"react-router-dom": "^6.24.1",
|
||||
"react-virtualized-auto-sizer": "^1.0.24",
|
||||
"react-window": "^1.8.10",
|
||||
"recursive-readdir": "^2.2.3",
|
||||
"rfdc": "^1.3.0",
|
||||
"rxjs": "^7.8.0",
|
||||
"rfdc": "^1.3.1",
|
||||
"rxjs": "^7.8.1",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"semver": "^7.5.4",
|
||||
"serialize-error": "^8.1.0",
|
||||
"semver": "^7.6.2",
|
||||
"serialize-error": "^11.0.3",
|
||||
"striptags": "^4.0.0-alpha.4",
|
||||
"tailwind-merge": "^2.4.0",
|
||||
"tailwind-scrollbar-hide": "^1.1.7",
|
||||
"tailwindcss-scoped-groups": "^2.0.0",
|
||||
"tippy.js": "^6.3.7",
|
||||
"to-ico": "^1.1.5",
|
||||
"use-double-click": "^1.0.5",
|
||||
"use-fit-text": "^2.4.0",
|
||||
"yauzl": "^3.2.0"
|
||||
"use-fit-text": "^2.4.0"
|
||||
},
|
||||
"devEngines": {
|
||||
"node": ">=14.x",
|
||||
"npm": ">=7.x"
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"collective": {
|
||||
"url": "https://www.patreon.com/bsmanager"
|
||||
@@ -295,6 +323,6 @@
|
||||
"logLevel": "quiet"
|
||||
},
|
||||
"volta": {
|
||||
"node": "20.18.0"
|
||||
"node": "20.11.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bs-manager",
|
||||
"version": "1.4.18",
|
||||
"version": "1.5.0-alpha.1",
|
||||
"description": "BSManager",
|
||||
"main": "./dist/main/main.js",
|
||||
"author": {
|
||||
@@ -9,15 +9,18 @@
|
||||
"url": "https://github.com/Zagrios/bs-manager"
|
||||
},
|
||||
"scripts": {
|
||||
"electron-rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js",
|
||||
"link-modules": "node -r ts-node/register ../../.erb/scripts/link-modules.ts",
|
||||
"electron-rebuild": "node -r esbuild-register ../../.erb/scripts/electron-rebuild.js",
|
||||
"link-modules": "node -r esbuild-register ../../.erb/scripts/link-modules.ts",
|
||||
"postinstall": "npm run electron-rebuild && npm run link-modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"@resvg/resvg-js": "2.6.2",
|
||||
"ps-list": "^7.2.0",
|
||||
"query-process": "^0.0.3",
|
||||
"regedit-rs": "^1.0.2",
|
||||
"sharp": "^0.32.6"
|
||||
"regedit-rs": "^1.0.2"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"volta": {
|
||||
"node": "20.11.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import "@testing-library/jest-dom";
|
||||
import { render } from "@testing-library/react";
|
||||
import App from "../renderer/windows/App";
|
||||
|
||||
describe("App", () => {
|
||||
it("should render", () => {
|
||||
expect(render(<App />)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,329 +0,0 @@
|
||||
import path from "path";
|
||||
import { mkdir, pathExistsSync, readFile, rm } from "fs-extra";
|
||||
import { BsmZipExtractor } from "main/models/bsm-zip-extractor.class";
|
||||
|
||||
const TEST_FOLDER = path.resolve(__dirname, "..", "assets", "zip");
|
||||
const STANDARD_ZIP = path.join(TEST_FOLDER, "standard.zip");
|
||||
const WINDOWS_LEGACY_MAP_ZIP = path.join(TEST_FOLDER, "windows_legacy.zip");
|
||||
const SUBFOLDERS_ZIP = path.join(TEST_FOLDER, "subfolders.zip");
|
||||
const MANIFEST_ZIP = path.join(TEST_FOLDER, "manifest.zip");
|
||||
const EMPTY_ZIP = path.join(TEST_FOLDER, "empty.zip");
|
||||
const UNICODE_ZIP = path.join(TEST_FOLDER, "unicode.zip");
|
||||
const DESTINATION_FOLDER = path.join(TEST_FOLDER, "out");
|
||||
|
||||
describe("Test BsmZipExtractor class", () => {
|
||||
let zip: BsmZipExtractor;
|
||||
|
||||
beforeAll(async () => {
|
||||
if (pathExistsSync(DESTINATION_FOLDER)) {
|
||||
await rm(DESTINATION_FOLDER, { recursive: true, force: true });
|
||||
}
|
||||
await mkdir(DESTINATION_FOLDER);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (zip) {
|
||||
zip.close();
|
||||
}
|
||||
if (pathExistsSync(DESTINATION_FOLDER)) {
|
||||
await rm(DESTINATION_FOLDER, { recursive: true, force: true });
|
||||
}
|
||||
await mkdir(DESTINATION_FOLDER);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (pathExistsSync(DESTINATION_FOLDER)) {
|
||||
await rm(DESTINATION_FOLDER, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("Extract standard zip", async () => {
|
||||
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
const res = await zip.extract(DESTINATION_FOLDER);
|
||||
|
||||
expect(res.sort()).toEqual([
|
||||
"file_1.2.txt",
|
||||
"file_1.3.txt",
|
||||
"folder_1.1/",
|
||||
"folder_1.1/file_2.1.txt",
|
||||
"folder_1.1/file_2.2.txt",
|
||||
].sort())
|
||||
|
||||
for (const file of [
|
||||
"file_1.2.txt",
|
||||
"file_1.3.txt",
|
||||
]) {
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, file)))
|
||||
.toBe(true);
|
||||
}
|
||||
|
||||
const SUBFOLDER_PATH = path.join(DESTINATION_FOLDER, "folder_1.1");
|
||||
for (const file of [
|
||||
"file_2.1.txt",
|
||||
"file_2.2.txt",
|
||||
]) {
|
||||
expect(pathExistsSync(path.join(SUBFOLDER_PATH, file)))
|
||||
.toBe(true);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
it("Extract map zips using back slashes", async () => {
|
||||
|
||||
zip = await BsmZipExtractor.fromPath(WINDOWS_LEGACY_MAP_ZIP);
|
||||
const res = await zip.extract(DESTINATION_FOLDER);
|
||||
|
||||
expect(res.sort()).toEqual([
|
||||
"BPMInfo.dat",
|
||||
"cover.jpg",
|
||||
"ExpertLegacy.dat",
|
||||
"ExpertPlusLawless.dat",
|
||||
"ExpertPlusLegacy.dat",
|
||||
"ExpertPlusStandard.dat",
|
||||
"ExpertStandard.dat",
|
||||
"Info.dat",
|
||||
"song.egg",
|
||||
"pfp/",
|
||||
"pfp/galaxyCompressed.jpg",
|
||||
"pfp/gojiCompressed.jpg",
|
||||
].sort());
|
||||
|
||||
// Expect all the files to exists
|
||||
for (const file of [
|
||||
"BPMInfo.dat",
|
||||
"cover.jpg",
|
||||
"ExpertLegacy.dat",
|
||||
"ExpertPlusLawless.dat",
|
||||
"ExpertPlusLegacy.dat",
|
||||
"ExpertPlusStandard.dat",
|
||||
"ExpertStandard.dat",
|
||||
"Info.dat",
|
||||
"song.egg",
|
||||
]) {
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, file)))
|
||||
.toBe(true);
|
||||
}
|
||||
|
||||
const SUBFOLDER_PATH = path.join(DESTINATION_FOLDER, "pfp");
|
||||
for (const file of [
|
||||
"galaxyCompressed.jpg",
|
||||
"gojiCompressed.jpg",
|
||||
]) {
|
||||
expect(pathExistsSync(path.join(SUBFOLDER_PATH, file)))
|
||||
.toBe(true);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
it("Read Zip with multiple subfolders", async () => {
|
||||
|
||||
const zip = await BsmZipExtractor.fromPath(SUBFOLDERS_ZIP);
|
||||
const res = await zip.extract(DESTINATION_FOLDER);
|
||||
|
||||
expect(res.sort()).toEqual([
|
||||
"1/",
|
||||
"1/2/",
|
||||
"1/2/3/",
|
||||
"1/2/3/4/",
|
||||
"1/2/3/4/5.txt",
|
||||
].sort());
|
||||
|
||||
for (const folder of [
|
||||
"1/",
|
||||
"1/2/",
|
||||
"1/2/3/",
|
||||
"1/2/3/4/",
|
||||
]) {
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, folder)))
|
||||
.toBe(true);
|
||||
}
|
||||
|
||||
const file = "1/2/3/4/5.txt";
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, file)))
|
||||
.toBe(true);
|
||||
});
|
||||
|
||||
it("Read manifest.json from zip file", async () => {
|
||||
|
||||
const zipBuffer = await readFile(MANIFEST_ZIP);
|
||||
zip = await BsmZipExtractor.fromBuffer(zipBuffer);
|
||||
const buffer = await (await zip.findEntry(entry => entry.fileName === "manifest.json")).read();
|
||||
const manifest = JSON.parse(buffer.toString());
|
||||
expect(manifest).toBeTruthy();
|
||||
|
||||
// Check some of the fields if they are correct
|
||||
expect(manifest.appId).toBe("some-app-id");
|
||||
expect(manifest.canonicalName).toBe("some-canonical-name");
|
||||
expect(manifest.isCore).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
it("Should find an entry using findEntry", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
const entry = await zip.findEntry(entry => entry.fileName === "file_1.2.txt");
|
||||
|
||||
expect(entry).toBeTruthy();
|
||||
expect(entry.fileName).toBe("file_1.2.txt");
|
||||
|
||||
const contentBuffer = await entry.read();
|
||||
const content = contentBuffer.toString();
|
||||
|
||||
expect(content).toContain("This is file 1.2"); // Assurez-vous que le contenu correspond
|
||||
});
|
||||
|
||||
it("Should filter entries using filterEntries", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
const entries = await zip.filterEntries(entry => !entry.isDirectory && entry.fileName.startsWith("folder_1.1/"));
|
||||
|
||||
expect(entries.length).toBe(2);
|
||||
const fileNames = entries.map(entry => entry.fileName).sort();
|
||||
|
||||
expect(fileNames).toEqual([
|
||||
"folder_1.1/file_2.1.txt",
|
||||
"folder_1.1/file_2.2.txt",
|
||||
]);
|
||||
});
|
||||
|
||||
it("Should get an entry by file name using getEntry", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
const entry = await zip.getEntry("file_1.3.txt");
|
||||
|
||||
expect(entry).toBeTruthy();
|
||||
expect(entry.fileName).toBe("file_1.3.txt");
|
||||
|
||||
const contentBuffer = await entry.read();
|
||||
const content = contentBuffer.toString();
|
||||
|
||||
expect(content).toContain("This is file 1.3"); // Assurez-vous que le contenu correspond
|
||||
});
|
||||
|
||||
it("Should extract only specified entries using entriesNames option", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
const res = await zip.extract(DESTINATION_FOLDER, { entriesNames: ["file_1.2.txt", "folder_1.1/file_2.1.txt"] });
|
||||
|
||||
expect(res.sort()).toEqual([
|
||||
"file_1.2.txt",
|
||||
"folder_1.1/",
|
||||
"folder_1.1/file_2.1.txt",
|
||||
].sort());
|
||||
|
||||
for (const file of [
|
||||
"file_1.2.txt",
|
||||
"folder_1.1/file_2.1.txt",
|
||||
]) {
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, file)))
|
||||
.toBe(true);
|
||||
}
|
||||
|
||||
// Vérifiez que les autres fichiers ne sont pas extraits
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, "file_1.3.txt")))
|
||||
.toBe(false);
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, "folder_1.1/file_2.2.txt")))
|
||||
.toBe(false);
|
||||
});
|
||||
|
||||
it("Should not extract any files if abortToken is already aborted", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
const abortController = new AbortController();
|
||||
|
||||
// Abortez avant d'appeler extract
|
||||
abortController.abort();
|
||||
|
||||
const res = await zip.extract(DESTINATION_FOLDER, { abortToken: abortController });
|
||||
|
||||
expect(res.length).toBe(0);
|
||||
|
||||
// Vérifiez qu'aucun fichier n'a été extrait
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, "file_1.2.txt")))
|
||||
.toBe(false);
|
||||
});
|
||||
|
||||
|
||||
it("Should throw an error when opening a non-existent zip file", async () => {
|
||||
await expect(BsmZipExtractor.fromPath("non_existent.zip"))
|
||||
.rejects
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
it("Should handle empty zip file correctly", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(EMPTY_ZIP);
|
||||
const entries = [];
|
||||
|
||||
for await (const entry of zip.entries()) {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
expect(entries.length).toBe(0);
|
||||
|
||||
const res = await zip.extract(DESTINATION_FOLDER);
|
||||
expect(res.length).toBe(0);
|
||||
});
|
||||
|
||||
it("Should return the same entries on multiple calls to entries()", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
|
||||
const entries1 = [];
|
||||
for await (const entry of zip.entries()) {
|
||||
entries1.push(entry);
|
||||
}
|
||||
|
||||
expect(entries1.length).toBe(5); // Basé sur le contenu de STANDARD_ZIP
|
||||
|
||||
const entries2 = [];
|
||||
for await (const entry of zip.entries()) {
|
||||
entries2.push(entry);
|
||||
}
|
||||
|
||||
expect(entries2.length).toBe(5);
|
||||
expect(entries2.map(e => e.fileName).sort()).toEqual(entries1.map(e => e.fileName).sort());
|
||||
});
|
||||
|
||||
it("Should not be able to read entries after zip is closed", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(STANDARD_ZIP);
|
||||
|
||||
zip.close();
|
||||
|
||||
await expect(zip.entries().next()).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("Should handle zip file from buffer", async () => {
|
||||
const zipBuffer = await readFile(STANDARD_ZIP);
|
||||
zip = await BsmZipExtractor.fromBuffer(zipBuffer);
|
||||
|
||||
const entries = [];
|
||||
for await (const entry of zip.entries()) {
|
||||
entries.push(entry.fileName);
|
||||
}
|
||||
|
||||
expect(entries.sort()).toEqual([
|
||||
"file_1.2.txt",
|
||||
"file_1.3.txt",
|
||||
"folder_1.1/",
|
||||
"folder_1.1/file_2.1.txt",
|
||||
"folder_1.1/file_2.2.txt",
|
||||
].sort());
|
||||
});
|
||||
|
||||
it("Should read and extract files with Unicode filenames", async () => {
|
||||
zip = await BsmZipExtractor.fromPath(UNICODE_ZIP);
|
||||
|
||||
const entries = [];
|
||||
for await (const entry of zip.entries()) {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
expect(entries.map(e => e.fileName)).toContain("こんにちは.txt"); // "Bonjour" en japonais
|
||||
|
||||
const res = await zip.extract(DESTINATION_FOLDER);
|
||||
expect(res).toContain("こんにちは.txt");
|
||||
expect(pathExistsSync(path.join(DESTINATION_FOLDER, "こんにちは.txt")))
|
||||
.toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it("Should throw an error when reading a corrupted zip file", async () => {
|
||||
const CORRUPTED_ZIP = path.join(TEST_FOLDER, "corrupted.zip");
|
||||
await expect(BsmZipExtractor.fromPath(CORRUPTED_ZIP)).rejects.toThrow(/.*[Error: Invalid comment length].*/)
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import { app } from "electron";
|
||||
import { constants } from "http2";
|
||||
import path from "path";
|
||||
|
||||
export const BS_EXECUTABLE = "Beat Saber.exe";
|
||||
@@ -10,5 +11,8 @@ export const APP_NAME = "BSManager";
|
||||
|
||||
export const STEAMVR_APP_ID = "250820";
|
||||
|
||||
export const IMAGE_CACHE_FOLDER = "imagescache";
|
||||
export const IMAGE_CACHE_PATH = path.join(app.getPath("userData"), IMAGE_CACHE_FOLDER);
|
||||
export const CACHE_PATH = path.join(app.getPath("userData"), "CachedData");
|
||||
|
||||
export const IMAGE_CACHE_PATH = path.join(CACHE_PATH, "imagescache");
|
||||
|
||||
export const HTTP_STATUS_CODES = constants;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CopyOptions, MoveOptions, copy, createReadStream, ensureDir, move, pathExists, pathExistsSync, realpath, stat, symlink } from "fs-extra";
|
||||
import { CopyOptions, copy, createReadStream, ensureDir, move, pathExists, pathExistsSync, realpath, stat, symlink } from "fs-extra";
|
||||
import { access, mkdir, rm, readdir, unlink, lstat, readlink } from "fs/promises";
|
||||
import path from "path";
|
||||
import { Observable, concatMap, from } from "rxjs";
|
||||
@@ -7,7 +7,6 @@ import { BsmException } from "shared/models/bsm-exception.model";
|
||||
import crypto from "crypto";
|
||||
import { execSync } from "child_process";
|
||||
import { tryit } from "../../shared/helpers/error.helpers";
|
||||
import { CustomError } from "../../shared/models/exceptions/custom-error.class"
|
||||
|
||||
export async function pathExist(path: string): Promise<boolean> {
|
||||
try {
|
||||
@@ -78,37 +77,37 @@ export async function getFilesInFolder(folderPath: string): Promise<string[]> {
|
||||
|
||||
return dirEntries.filter(entry => entry.isFile()).map(file => path.join(folderPath, file.name));
|
||||
}
|
||||
export function moveFolderContent(src: string, dest: string, option?: MoveOptions): Observable<Progression> {
|
||||
|
||||
export function moveFolderContent(src: string, dest: string): Observable<Progression> {
|
||||
const progress: Progression = { current: 0, total: 0 };
|
||||
return new Observable<Progression>(subscriber => {
|
||||
subscriber.next(progress);
|
||||
(async () => {
|
||||
const srcExist = await pathExists(src);
|
||||
const srcExist = await pathExist(src);
|
||||
|
||||
if (!srcExist) {
|
||||
return subscriber.complete();
|
||||
}
|
||||
|
||||
await ensureFolderExist(dest);
|
||||
ensureFolderExist(dest);
|
||||
|
||||
const files = await readdir(src, { encoding: "utf-8", withFileTypes: true });
|
||||
const files = await readdir(src, { encoding: "utf-8" });
|
||||
progress.total = files.length;
|
||||
|
||||
for(const file of files){
|
||||
const srcFullPath = path.join(src, file.name);
|
||||
const destFullPath = path.join(dest, file.name);
|
||||
|
||||
const srcChilds = file.isDirectory() ? await readdir(srcFullPath, { encoding: "utf-8", recursive: true }) : [];
|
||||
const allChildsAlreadyExist = srcChilds.every(child => pathExistsSync(path.join(destFullPath, child)));
|
||||
|
||||
if(file.isFile() || !allChildsAlreadyExist){
|
||||
await move(srcFullPath, destFullPath, option);
|
||||
const promises = files.map(async file => {
|
||||
const srcFullPath = path.join(src, file);
|
||||
const destFullPath = path.join(dest, file);
|
||||
if (await pathExist(destFullPath)) {
|
||||
progress.current++;
|
||||
return subscriber.next(progress);
|
||||
}
|
||||
|
||||
await move(srcFullPath, destFullPath);
|
||||
progress.current++;
|
||||
subscriber.next(progress);
|
||||
}
|
||||
})().catch(err => subscriber.error(CustomError.fromError(err, err?.code))).finally(() => subscriber.complete());
|
||||
});
|
||||
|
||||
Promise.allSettled(promises).then(() => subscriber.complete());
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -218,13 +217,27 @@ export function rxCopy(src: string, dest: string, option?: CopyOptions): Observa
|
||||
|
||||
export async function ensurePathNotAlreadyExist(path: string): Promise<string> {
|
||||
let destPath = path;
|
||||
let folderExist = await pathExist(destPath);
|
||||
let folderExist = await pathExists(destPath);
|
||||
let i = 0;
|
||||
|
||||
while (folderExist) {
|
||||
i++;
|
||||
destPath = `${path} (${i})`;
|
||||
folderExist = await pathExist(destPath);
|
||||
folderExist = await pathExists(destPath);
|
||||
}
|
||||
|
||||
return destPath;
|
||||
}
|
||||
|
||||
export function ensurePathNotAlreadyExistSync(path: string): string {
|
||||
let destPath = path;
|
||||
let folderExist = pathExistsSync(destPath);
|
||||
let i = 0;
|
||||
|
||||
while (folderExist) {
|
||||
i++;
|
||||
destPath = `${path} (${i})`;
|
||||
folderExist = pathExistsSync(destPath);
|
||||
}
|
||||
|
||||
return destPath;
|
||||
@@ -245,9 +258,23 @@ export function resolveGUIDPath(guidPath: string): string {
|
||||
return path.join(driveLetter, path.relative(guidVolume, guidPath));
|
||||
}
|
||||
|
||||
export interface Progression<T = unknown> {
|
||||
export function getUniqueFileNamePath(filePath: string): string {
|
||||
const { dir, name, ext } = path.parse(filePath);
|
||||
let i = 0;
|
||||
let newFileName = `${name}${ext}`;
|
||||
|
||||
while (pathExistsSync(path.join(dir, newFileName))) {
|
||||
i++;
|
||||
newFileName = `${name} (${i})${ext}`;
|
||||
}
|
||||
|
||||
return path.join(dir, newFileName);
|
||||
}
|
||||
|
||||
export interface Progression<T = unknown, D = unknown> {
|
||||
total: number;
|
||||
current: number;
|
||||
diff?: number;
|
||||
data?: T;
|
||||
extra?: D;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import JSZip from "jszip";
|
||||
import { pathExist } from "./fs.helpers";
|
||||
import path from "path";
|
||||
import { mkdir, writeFile } from "fs/promises";
|
||||
|
||||
export async function extractZip(zip: JSZip, dest: string): Promise<string[]> {
|
||||
if (!(await pathExist(dest))) {
|
||||
throw new Error(`Path ${dest} does not exist`);
|
||||
}
|
||||
const files: string[] = [];
|
||||
|
||||
for (const [relativePath, entry] of Object.entries(zip.files)) {
|
||||
if (entry.dir) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = await entry.async("nodebuffer");
|
||||
const outPath = path.join(dest, relativePath);
|
||||
const outDir = path.dirname(outPath);
|
||||
|
||||
await mkdir(outDir, { recursive: true });
|
||||
await writeFile(outPath, content);
|
||||
|
||||
files.push(outPath);
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
@@ -1,63 +1,30 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { SearchParams } from "shared/models/maps/beat-saver.model";
|
||||
import { BeatSaverService } from "../services/thrid-party/beat-saver/beat-saver.service";
|
||||
import log from "electron-log";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
|
||||
ipcMain.on("bsv-search-map", async (event, request: IpcRequest<SearchParams>) => {
|
||||
const utlis = UtilsService.getInstance();
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on("bsv-search-map", (args, reply) => {
|
||||
const bsvService = BeatSaverService.getInstance();
|
||||
|
||||
bsvService
|
||||
.searchMaps(request.args)
|
||||
.then(maps => {
|
||||
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
|
||||
})
|
||||
.catch(e => {
|
||||
utlis.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
reply(from(bsvService.searchMaps(args)));
|
||||
});
|
||||
|
||||
ipcMain.on("bsv-get-map-details-from-hashs", async (event, request: IpcRequest<string[]>) => {
|
||||
const utlis = UtilsService.getInstance();
|
||||
ipc.on("bsv-get-map-details-from-hashs", (args, reply) => {
|
||||
const bsvService = BeatSaverService.getInstance();
|
||||
|
||||
bsvService
|
||||
.getMapDetailsFromHashs(request.args)
|
||||
.then(maps => {
|
||||
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
|
||||
})
|
||||
.catch(e => {
|
||||
log.error(e);
|
||||
utlis.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
reply(from(bsvService.getMapDetailsFromHashs(args)));
|
||||
});
|
||||
|
||||
ipcMain.on("bsv-get-map-details-by-id", async (event, request: IpcRequest<string>) => {
|
||||
const utlis = UtilsService.getInstance();
|
||||
ipc.on("bsv-get-map-details-by-id", (args, reply) => {
|
||||
const bsvService = BeatSaverService.getInstance();
|
||||
|
||||
bsvService
|
||||
.getMapDetailsById(request.args)
|
||||
.then(maps => {
|
||||
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
|
||||
})
|
||||
.catch(e => {
|
||||
utlis.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
reply(from(bsvService.getMapDetailsById(args)));
|
||||
});
|
||||
|
||||
ipcMain.on("bsv-get-playlist-details-by-id", async (event, request: IpcRequest<string>) => {
|
||||
const utlis = UtilsService.getInstance();
|
||||
ipc.on("bsv-search-playlist", (args, reply) => {
|
||||
const bsvService = BeatSaverService.getInstance();
|
||||
|
||||
bsvService
|
||||
.getPlaylistPage(request.args)
|
||||
.then(maps => {
|
||||
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
|
||||
})
|
||||
.catch(e => {
|
||||
utlis.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
reply(from(bsvService.searchPlaylists(args)));
|
||||
});
|
||||
|
||||
ipc.on("bsv-get-playlist-details-by-id", (args, reply) => {
|
||||
const bsvService = BeatSaverService.getInstance();
|
||||
reply(from(bsvService.getPlaylistDetailsById(args.id, args.page)));
|
||||
});
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
|
||||
import { LaunchOption } from "shared/models/bs-launch";
|
||||
import { BSLauncherService } from "../services/bs-launcher/bs-launcher.service"
|
||||
import { IpcService } from '../services/ipc.service';
|
||||
import { from } from "rxjs";
|
||||
import { SteamLauncherService } from "../services/bs-launcher/steam-launcher.service";
|
||||
import { OculusLauncherService } from "../services/bs-launcher/oculus-launcher.service";
|
||||
import { SteamService } from "../services/steam.service";
|
||||
import log from "electron-log";
|
||||
import isElevated from "is-elevated";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on<LaunchOption>('bs-launch.launch', (req, reply) => {
|
||||
ipc.on('bs-launch.launch', (args, reply) => {
|
||||
const bsLauncher = BSLauncherService.getInstance();
|
||||
reply(bsLauncher.launch(req.args));
|
||||
reply(bsLauncher.launch(args));
|
||||
});
|
||||
|
||||
ipc.on<boolean>("bs-launch.need-start-as-admin", (_, reply) => {
|
||||
ipc.on("bs-launch.need-start-as-admin", (_, reply) => {
|
||||
const steam = SteamService.getInstance();
|
||||
reply(from(isElevated().then(elevated => {
|
||||
if(elevated){ return false; }
|
||||
@@ -27,13 +25,12 @@ ipc.on<boolean>("bs-launch.need-start-as-admin", (_, reply) => {
|
||||
})));
|
||||
});
|
||||
|
||||
ipc.on<LaunchOption>("create-launch-shortcut", (req, reply) => {
|
||||
ipc.on("create-launch-shortcut", (args, reply) => {
|
||||
const bsLauncher = BSLauncherService.getInstance();
|
||||
reply(from(bsLauncher.createLaunchShortcut(req.args)));
|
||||
reply(from(bsLauncher.createLaunchShortcut(args)));
|
||||
});
|
||||
|
||||
|
||||
ipc.on<void>("bs-launch.restore-steamvr", (_, reply) => {
|
||||
ipc.on("bs-launch.restore-steamvr", (_, reply) => {
|
||||
const steamLauncher = SteamLauncherService.getInstance();
|
||||
reply(from(steamLauncher.restoreSteamVR()));
|
||||
});
|
||||
|
||||
@@ -1,119 +1,83 @@
|
||||
import { LocalMapsManagerService } from "../services/additional-content/local-maps-manager.service";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
|
||||
import { BsvMapDetail } from "shared/models/maps";
|
||||
import { LocalMapsManagerService } from "../services/additional-content/maps/local-maps-manager.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
import log from "electron-log"
|
||||
import { from, of, throwError } from "rxjs";
|
||||
import { tryit } from "shared/helpers/error.helpers";
|
||||
import { SongDetailsCacheService } from "main/services/additional-content/maps/song-details-cache.service";
|
||||
import { SongDetails } from "shared/models/maps";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on("load-version-maps", async (request: IpcRequest<BSVersion>, reply) => {
|
||||
ipc.on("load-version-maps", (args, reply) => {
|
||||
const localMaps = LocalMapsManagerService.getInstance();
|
||||
reply(localMaps.getMaps(request.args));
|
||||
reply(localMaps.getMaps(args));
|
||||
});
|
||||
|
||||
ipc.on("verion-have-maps-linked", async (request: IpcRequest<BSVersion>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("delete-maps", (args, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
|
||||
utils.ipcSend<boolean>(request.responceChannel, { success: true, data: await maps.versionIsLinked(request.args) });
|
||||
reply(maps.deleteMaps(args));
|
||||
});
|
||||
|
||||
ipc.on("link-version-maps", async (request: IpcRequest<{ version: BSVersion; keepMaps: boolean }>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("export-maps", async (args, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
|
||||
maps.linkVersionMaps(request.args.version, request.args.keepMaps)
|
||||
.then(() => {
|
||||
utils.ipcSend<void>(request.responceChannel, { success: true });
|
||||
})
|
||||
.catch(err => {
|
||||
utils.ipcSend<void>(request.responceChannel, { success: true, error: err });
|
||||
});
|
||||
reply(await maps.exportMaps(args.version, args.maps, args.outPath));
|
||||
});
|
||||
|
||||
ipc.on("unlink-version-maps", async (request: IpcRequest<{ version: BSVersion; keepMaps: boolean }>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("download-map", async (args, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
|
||||
maps.unlinkVersionMaps(request.args.version, request.args.keepMaps)
|
||||
.then(() => {
|
||||
utils.ipcSend<void>(request.responceChannel, { success: true });
|
||||
})
|
||||
.catch(err => {
|
||||
utils.ipcSend<void>(request.responceChannel, { success: true, error: err });
|
||||
});
|
||||
reply(from(maps.downloadMap(args.map, args.version)));
|
||||
});
|
||||
|
||||
ipc.on("delete-maps", async (request: IpcRequest<BsmLocalMap[]>, reply) => {
|
||||
ipc.on("one-click-install-map", (args, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
reply(maps.deleteMaps(request.args));
|
||||
reply(from(maps.oneClickDownloadMap(args)))
|
||||
});
|
||||
|
||||
ipc.on("export-maps", async (request: IpcRequest<{ version: BSVersion; maps: BsmLocalMap[]; outPath: string }>, reply) => {
|
||||
ipc.on("register-maps-deep-link", (_, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
reply(await maps.exportMaps(request.args.version, request.args.maps, request.args.outPath));
|
||||
});
|
||||
const { error, result } = tryit(() => maps.enableDeepLinks());
|
||||
|
||||
ipc.on("download-map", async (request: IpcRequest<{ map: BsvMapDetail; version: BSVersion }>, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
reply(from(maps.downloadMap(request.args.map, request.args.version)));
|
||||
});
|
||||
|
||||
ipc.on("one-click-install-map", async (request: IpcRequest<BsvMapDetail>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
|
||||
maps.oneClickDownloadMap(request.args)
|
||||
.then(() => {
|
||||
utils.ipcSend(request.responceChannel, { success: true });
|
||||
})
|
||||
.catch(err => {
|
||||
log.error(err);
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: err });
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on("register-maps-deep-link", async (request: IpcRequest<void>) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
|
||||
try {
|
||||
const res = maps.enableDeepLinks();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
if(error) {
|
||||
return reply(throwError(() => error));
|
||||
}
|
||||
|
||||
reply(of(result));
|
||||
});
|
||||
|
||||
ipc.on("unregister-maps-deep-link", async (request: IpcRequest<void>) => {
|
||||
ipc.on("unregister-maps-deep-link", (_, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
const { error, result } = tryit(() => maps.disableDeepLinks());
|
||||
|
||||
try {
|
||||
const res = maps.disableDeepLinks();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
if(error) {
|
||||
return reply(throwError(() => error));
|
||||
}
|
||||
|
||||
reply(of(result));
|
||||
});
|
||||
|
||||
ipc.on("is-map-deep-links-enabled", async (request: IpcRequest<void>) => {
|
||||
ipc.on("is-map-deep-links-enabled", (_, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
const { error, result } = tryit(() => maps.isDeepLinksEnabled());
|
||||
|
||||
try {
|
||||
const res = maps.isDeepLinksEnabled();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
if(error) {
|
||||
return reply(throwError(() => error));
|
||||
}
|
||||
|
||||
reply(of(result));
|
||||
});
|
||||
|
||||
ipc.on("get-version-maps-path", async (req: IpcRequest<BSVersion>, reply) => {
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
reply(from(maps.getMapsFolderPath(req.args)));
|
||||
});
|
||||
ipc.on("get-maps-info-from-cache", (args, reply) => {
|
||||
const songsCache = SongDetailsCacheService.getInstance();
|
||||
|
||||
const res = (args ?? []).reduce((acc, hash) => {
|
||||
const songDetails = songsCache.getSongDetails(hash);
|
||||
|
||||
if(songDetails){
|
||||
acc.push(songDetails);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [] as SongDetails[]);
|
||||
|
||||
reply(of(res));
|
||||
|
||||
})
|
||||
|
||||
@@ -1,82 +1,45 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { MSModel, MSModelType } from "shared/models/models/model-saber.model";
|
||||
import { LocalModelsManagerService } from "../services/additional-content/local-models-manager.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import { BsmLocalModel } from "shared/models/models/bsm-local-model.interface";
|
||||
import { ModelDownload } from "renderer/services/models-management/models-downloader.service";
|
||||
import { from, of } from "rxjs";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipcMain.on("one-click-install-model", async (event, request: IpcRequest<MSModel>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("one-click-install-model", (args, reply) => {
|
||||
const models = LocalModelsManagerService.getInstance();
|
||||
|
||||
models
|
||||
.oneClickDownloadModel(request.args)
|
||||
.then(() => {
|
||||
utils.ipcSend(request.responceChannel, { success: true });
|
||||
})
|
||||
.catch(e => {
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
reply(from(models.oneClickDownloadModel(args)));
|
||||
});
|
||||
|
||||
ipcMain.on("register-models-deep-link", async (event, request: IpcRequest<void>) => {
|
||||
ipc.on("register-models-deep-link", (_, reply) => {
|
||||
const models = LocalModelsManagerService.getInstance();
|
||||
reply(of(models.enableDeepLinks()));
|
||||
});
|
||||
|
||||
ipc.on("unregister-models-deep-link", (_, reply) => {
|
||||
const models = LocalModelsManagerService.getInstance();
|
||||
reply(of(models.disableDeepLinks()));
|
||||
});
|
||||
|
||||
ipc.on("is-models-deep-links-enabled", (_, reply) => {
|
||||
const maps = LocalModelsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
|
||||
try {
|
||||
const res = maps.enableDeepLinks();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
}
|
||||
reply(of(maps.isDeepLinksEnabled()));
|
||||
});
|
||||
|
||||
ipcMain.on("unregister-models-deep-link", async (event, request: IpcRequest<void>) => {
|
||||
const maps = LocalModelsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
|
||||
try {
|
||||
const res = maps.disableDeepLinks();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on("is-models-deep-links-enabled", async (event, request: IpcRequest<void>) => {
|
||||
const maps = LocalModelsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
|
||||
try {
|
||||
const res = maps.isDeepLinksEnabled();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
}
|
||||
});
|
||||
|
||||
ipc.on<ModelDownload>("download-model", async (req, reply) => {
|
||||
ipc.on("download-model", (args, reply) => {
|
||||
const models = LocalModelsManagerService.getInstance();
|
||||
reply(models.downloadModel(req.args.model, req.args.version));
|
||||
reply(models.downloadModel(args.model, args.version));
|
||||
});
|
||||
|
||||
ipc.on<{ version: BSVersion; type: MSModelType }>("get-version-models", async (req, reply) => {
|
||||
ipc.on("get-version-models", (args, reply) => {
|
||||
const models = LocalModelsManagerService.getInstance();
|
||||
const res = await models.getModels(req.args.type, req.args.version);
|
||||
reply(res);
|
||||
reply(from(models.getModels(args.type, args.version)));
|
||||
});
|
||||
|
||||
ipc.on<{ version: BSVersion; models: BsmLocalModel[]; outPath: string }>("export-models", async (req, reply) => {
|
||||
ipc.on("export-models", (args, reply) => {
|
||||
const models = LocalModelsManagerService.getInstance();
|
||||
reply(models.exportModels(req.args.outPath, req.args.version, req.args.models));
|
||||
reply(models.exportModels(args.outPath, args.version, args.models));
|
||||
});
|
||||
|
||||
ipc.on<BsmLocalModel[]>("delete-models", async (req, reply) => {
|
||||
ipc.on("delete-models", (args, reply) => {
|
||||
const models = LocalModelsManagerService.getInstance();
|
||||
reply(models.deleteModels(req.args));
|
||||
reply(models.deleteModels(args));
|
||||
});
|
||||
|
||||
@@ -1,67 +1,30 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { BsModsManagerService } from "../services/mods/bs-mods-manager.service";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { BbmFullMod } from "shared/models/mods/mod.interface";
|
||||
import { InstallModsResult } from "shared/models/mods";
|
||||
import log from "electron-log";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on<BSVersion>("get-available-mods", (req, reply) => {
|
||||
ipc.on("get-available-mods", (args, reply) => {
|
||||
const modsManager = BsModsManagerService.getInstance();
|
||||
reply(from(modsManager.getAvailableMods(req.args)));
|
||||
reply(from(modsManager.getAvailableMods(args)));
|
||||
});
|
||||
|
||||
ipc.on<BSVersion>("get-installed-mods", (req, reply) => {
|
||||
ipc.on("get-installed-mods", (args, reply) => {
|
||||
const modsManager = BsModsManagerService.getInstance();
|
||||
reply(from(modsManager.getInstalledMods(req.args)));
|
||||
reply(from(modsManager.getInstalledMods(args)));
|
||||
});
|
||||
|
||||
ipcMain.on("install-mods", (event, request: IpcRequest<{ mods: BbmFullMod[]; version: BSVersion }>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("install-mods", (args, reply) => {
|
||||
const modsManager = BsModsManagerService.getInstance();
|
||||
|
||||
modsManager
|
||||
.installMods(request.args.mods, request.args.version)
|
||||
.then(nbInstalled => {
|
||||
utils.ipcSend<InstallModsResult>(request.responceChannel, { success: true, data: nbInstalled });
|
||||
})
|
||||
.catch(err => {
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: err });
|
||||
log.error("ipc", "install-mods", err, request);
|
||||
});
|
||||
reply(from(modsManager.installMods(args.mods, args.version)));
|
||||
});
|
||||
|
||||
ipcMain.on("uninstall-mods", (event, request: IpcRequest<{ mods: BbmFullMod[]; version: BSVersion }>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("uninstall-mods", (args, reply) => {
|
||||
const modsManager = BsModsManagerService.getInstance();
|
||||
|
||||
modsManager
|
||||
.uninstallMods(request.args.mods, request.args.version)
|
||||
.then(nbInstalled => {
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: nbInstalled });
|
||||
})
|
||||
.catch(err => {
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: err });
|
||||
log.error("ipc", "uninstall-mods", err, request);
|
||||
});
|
||||
reply(from(modsManager.uninstallMods(args.mods, args.version)));
|
||||
});
|
||||
|
||||
ipcMain.on("uninstall-all-mods", (event, request: IpcRequest<BSVersion>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("uninstall-all-mods", (args, reply) => {
|
||||
const modsManager = BsModsManagerService.getInstance();
|
||||
|
||||
modsManager
|
||||
.uninstallAllMods(request.args)
|
||||
.then(nbInstalled => {
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: nbInstalled });
|
||||
})
|
||||
.catch(err => {
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: err });
|
||||
log.error("ipc", "uninstall-all-mods", err, request);
|
||||
});
|
||||
reply(from(modsManager.uninstallAllMods(args)));
|
||||
});
|
||||
|
||||
@@ -1,48 +1,75 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { LocalPlaylistsManagerService } from "../services/additional-content/local-playlists-manager.service";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from, lastValueFrom, mergeMap, of } from "rxjs";
|
||||
import { LocalMapsManagerService } from "../services/additional-content/maps/local-maps-manager.service";
|
||||
import { Progression } from "main/helpers/fs.helpers";
|
||||
import { isValidUrl } from "shared/helpers/url.helpers";
|
||||
import { pathToFileURL } from "url";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on<string>("one-click-install-playlist", (req, reply) => {
|
||||
ipc.on("one-click-install-playlist", (args, reply) => {
|
||||
const mapsManager = LocalPlaylistsManagerService.getInstance();
|
||||
reply(mapsManager.oneClickInstallPlaylist(req.args));
|
||||
reply(mapsManager.oneClickInstallPlaylist(args));
|
||||
});
|
||||
|
||||
ipcMain.on("register-playlists-deep-link", async (event, request: IpcRequest<void>) => {
|
||||
ipc.on("register-playlists-deep-link", (args, reply) => {
|
||||
const maps = LocalPlaylistsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
|
||||
try {
|
||||
const res = maps.enableDeepLinks();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
}
|
||||
reply(of(maps.enableDeepLinks()));
|
||||
});
|
||||
|
||||
ipcMain.on("unregister-playlists-deep-link", async (event, request: IpcRequest<void>) => {
|
||||
ipc.on("unregister-playlists-deep-link", (args, reply) => {
|
||||
const maps = LocalPlaylistsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
|
||||
try {
|
||||
const res = maps.disableDeepLinks();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
}
|
||||
reply(of(maps.disableDeepLinks()));
|
||||
});
|
||||
|
||||
ipcMain.on("is-playlists-deep-links-enabled", async (event, request: IpcRequest<void>) => {
|
||||
ipc.on("is-playlists-deep-links-enabled", (args, reply) => {
|
||||
const maps = LocalPlaylistsManagerService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
|
||||
try {
|
||||
const res = maps.isDeepLinksEnabled();
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
} catch (e) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
}
|
||||
reply(of(maps.isDeepLinksEnabled()));
|
||||
});
|
||||
|
||||
ipc.on("download-playlist", (args, reply) => {
|
||||
const playlists = LocalPlaylistsManagerService.getInstance();
|
||||
|
||||
const downloadUrl = isValidUrl(args.downloadSource) ? args.downloadSource : pathToFileURL(args.downloadSource).href;
|
||||
|
||||
return reply(playlists.downloadPlaylist({
|
||||
bpListUrl: downloadUrl,
|
||||
version: args.version,
|
||||
ignoreSongsHashs: args.ignoreSongsHashs,
|
||||
dest: args.dest
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
ipc.on("get-version-playlists-details", (args, reply) => {
|
||||
const playlists = LocalPlaylistsManagerService.getInstance();
|
||||
reply(playlists.getVersionPlaylistsDetails(args));
|
||||
});
|
||||
|
||||
ipc.on("delete-playlist", (args, reply) => {
|
||||
const playlists = LocalPlaylistsManagerService.getInstance();
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
reply(playlists.deletePlaylistFile(args.bpList).pipe(mergeMap(() => {
|
||||
if(args.deleteMaps){
|
||||
return maps.deleteMapsFromHashs(args.version, args.bpList.songs.map(s => s.hash));
|
||||
}
|
||||
return of({ current: 0, total: 0 } as Progression);
|
||||
})));
|
||||
});
|
||||
|
||||
ipc.on("export-playlists", (args, reply) => {
|
||||
const playlists = LocalPlaylistsManagerService.getInstance();
|
||||
reply(playlists.exportPlaylists(args));
|
||||
});
|
||||
|
||||
ipc.on("install-playlist-file", (args, reply) => {
|
||||
const playlists = LocalPlaylistsManagerService.getInstance();
|
||||
|
||||
const promise = async () => {
|
||||
const playlist = await lastValueFrom(playlists.writeBPListFile({ bpList: args.bplist, version: args.version, dest: args.dest}));
|
||||
return playlists.getLocalBPListDetails(playlist);
|
||||
}
|
||||
|
||||
reply(from(promise()));
|
||||
})
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import { BSLocalVersionService } from "../services/bs-local-version.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on<BSVersion>("bs.uninstall", (req, reply) => {
|
||||
ipc.on("bs.uninstall", (args, reply) => {
|
||||
const bsLocalVersionService = BSLocalVersionService.getInstance();
|
||||
|
||||
reply(from(bsLocalVersionService.deleteVersion(req.args)));
|
||||
reply(from(bsLocalVersionService.deleteVersion(args)));
|
||||
});
|
||||
|
||||
@@ -1,47 +1,42 @@
|
||||
import { BsOculusDownloaderService } from "../../services/bs-version-download/bs-oculus-downloader.service";
|
||||
import { BsSteamDownloaderService, DownloadInfo, DownloadSteamInfo } from "../../services/bs-version-download/bs-steam-downloader.service";
|
||||
import { BsSteamDownloaderService } from "../../services/bs-version-download/bs-steam-downloader.service";
|
||||
import { InstallationLocationService } from "../../services/installation-location.service";
|
||||
import { IpcService } from "../../services/ipc.service";
|
||||
import { from, of } from "rxjs";
|
||||
import { BSLocalVersionService, ImportVersionOptions } from "../../services/bs-local-version.service";
|
||||
import { BSLocalVersionService } from "../../services/bs-local-version.service";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on<ImportVersionOptions>("import-version", (req, reply) => {
|
||||
ipc.on("import-version", (args, reply) => {
|
||||
const versionManager = BSLocalVersionService.getInstance();
|
||||
reply(versionManager.importVersion(req.args));
|
||||
reply(versionManager.importVersion(args));
|
||||
});
|
||||
|
||||
// #region Steam
|
||||
|
||||
ipc.on("is-dotnet-installed", (_, reply) => {
|
||||
const installer = BsSteamDownloaderService.getInstance();
|
||||
reply(from(installer.isDotNetInstalled()));
|
||||
});
|
||||
|
||||
ipc.on("bs-download.installation-folder", (_, reply) => {
|
||||
const installLocation = InstallationLocationService.getInstance();
|
||||
reply(from(installLocation.installationDirectory()));
|
||||
});
|
||||
|
||||
ipc.on<string>("bs-download.set-installation-folder", (req, reply) => {
|
||||
ipc.on("bs-download.set-installation-folder", (args, reply) => {
|
||||
const installerService = InstallationLocationService.getInstance();
|
||||
reply(from(installerService.setInstallationDirectory(req.args)));
|
||||
reply(from(installerService.setInstallationDirectory(args)));
|
||||
});
|
||||
|
||||
ipc.on<DownloadSteamInfo>("auto-download-bs-version", (req, reply) => {
|
||||
ipc.on("auto-download-bs-version", (args, reply) => {
|
||||
const bsInstaller = BsSteamDownloaderService.getInstance();
|
||||
reply(bsInstaller.autoDownloadBsVersion(req.args));
|
||||
reply(bsInstaller.autoDownloadBsVersion(args));
|
||||
});
|
||||
|
||||
ipc.on<DownloadSteamInfo>("download-bs-version", (req, reply) => {
|
||||
ipc.on("download-bs-version", (args, reply) => {
|
||||
const bsInstaller = BsSteamDownloaderService.getInstance();
|
||||
reply(bsInstaller.downloadBsVersion(req.args))
|
||||
reply(bsInstaller.downloadBsVersion(args))
|
||||
});
|
||||
|
||||
ipc.on<DownloadSteamInfo>("download-bs-version-qr", (req, reply) => {
|
||||
ipc.on("download-bs-version-qr", (args, reply) => {
|
||||
const bsInstaller = BsSteamDownloaderService.getInstance();
|
||||
reply(bsInstaller.downloadBsVersionWithQRCode(req.args))
|
||||
reply(bsInstaller.downloadBsVersionWithQRCode(args))
|
||||
});
|
||||
|
||||
ipc.on("stop-download-bs-version", (_, reply) => {
|
||||
@@ -49,23 +44,18 @@ ipc.on("stop-download-bs-version", (_, reply) => {
|
||||
reply(of(bsInstaller.stopDownload()));
|
||||
});
|
||||
|
||||
ipc.on<string>("send-input-bs-download", (req, reply) => {
|
||||
ipc.on("send-input-bs-download", (args, reply) => {
|
||||
const bsInstaller = BsSteamDownloaderService.getInstance();
|
||||
reply(of(bsInstaller.sendInput(req.args)));
|
||||
reply(of(bsInstaller.sendInput(args)));
|
||||
});
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Oculus
|
||||
|
||||
ipc.on<DownloadInfo>("bs-oculus-download", async (req, reply) => {
|
||||
ipc.on("bs-oculus-download", async (args, reply) => {
|
||||
const oculusDownloader = BsOculusDownloaderService.getInstance();
|
||||
reply(oculusDownloader.downloadVersion(req.args));
|
||||
});
|
||||
|
||||
ipc.on<DownloadInfo>("bs-oculus-auto-download", async (req, reply) => {
|
||||
const oculusDownloader = BsOculusDownloaderService.getInstance();
|
||||
reply(oculusDownloader.autoDownloadVersion(req.args));
|
||||
reply(oculusDownloader.downloadVersion(args));
|
||||
});
|
||||
|
||||
ipc.on("bs-oculus-stop-download", async (_, reply) => {
|
||||
@@ -73,14 +63,4 @@ ipc.on("bs-oculus-stop-download", async (_, reply) => {
|
||||
reply(of(oculusDownloader.stopDownload()));
|
||||
});
|
||||
|
||||
ipc.on("bs-oculus-has-auth-token", async (_, reply) => {
|
||||
const oculusDownloader = BsOculusDownloaderService.getInstance();
|
||||
reply(from(oculusDownloader.getAuthToken().then(token => !!token)));
|
||||
});
|
||||
|
||||
ipc.on("bs-oculus-clear-auth-token", async (_, reply) => {
|
||||
const oculusDownloader = BsOculusDownloaderService.getInstance();
|
||||
reply(from(oculusDownloader.clearAuthToken()));
|
||||
});
|
||||
|
||||
// #endregion
|
||||
|
||||
@@ -1,173 +1,69 @@
|
||||
import { ipcMain, shell } from "electron";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { shell } from "electron";
|
||||
import { BSVersionLibService } from "../services/bs-version-lib.service";
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { BSLocalVersionService } from "../services/bs-local-version.service";
|
||||
import { BsmException } from "shared/models/bsm-exception.model";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
import path from "path";
|
||||
import { pathExist } from "../helpers/fs.helpers";
|
||||
import { FolderLinkerService, LinkOptions } from "../services/folder-linker.service";
|
||||
import { LocalMapsManagerService } from "../services/additional-content/local-maps-manager.service";
|
||||
import { readJSON, writeJSON } from "fs-extra";
|
||||
import log from "electron-log";
|
||||
import { VersionLinkerAction } from "renderer/services/version-folder-linker.service";
|
||||
import { pathExists } from "fs-extra";
|
||||
import { VersionFolderLinkerService } from "../services/version-folder-linker.service";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipcMain.on("bs-version.get-version-dict", (_event, req: IpcRequest<void>) => {
|
||||
BSVersionLibService.getInstance()
|
||||
.getAvailableVersions()
|
||||
.then(versions => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: true, data: versions });
|
||||
})
|
||||
.catch(() => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false });
|
||||
});
|
||||
ipc.on("bs-version.get-version-dict", (_, reply) => {
|
||||
const versionsLib = BSVersionLibService.getInstance();
|
||||
reply(from(versionsLib.getAvailableVersions()));
|
||||
});
|
||||
|
||||
ipcMain.on("bs-version.installed-versions", async (_event, req: IpcRequest<void>) => {
|
||||
BSLocalVersionService.getInstance()
|
||||
.getInstalledVersions()
|
||||
.then(versions => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: true, data: versions });
|
||||
})
|
||||
.catch(() => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false });
|
||||
});
|
||||
ipc.on("bs-version.installed-versions", (_, reply) => {
|
||||
const versions = BSLocalVersionService.getInstance();
|
||||
reply(from(versions.getInstalledVersions()));
|
||||
});
|
||||
|
||||
ipcMain.on("bs-version.open-folder", async (_event, req: IpcRequest<BSVersion>) => {
|
||||
const localVersionService = BSLocalVersionService.getInstance();
|
||||
const versionFolder = await localVersionService.getVersionPath(req.args);
|
||||
if (!(await pathExist(versionFolder))) return;
|
||||
shell.openPath(versionFolder);
|
||||
});
|
||||
|
||||
ipcMain.on("bs-version.edit", async (__event, req: IpcRequest<{ version: BSVersion; name: string; color: string }>) => {
|
||||
BSLocalVersionService.getInstance()
|
||||
.editVersion(req.args.version, req.args.name, req.args.color)
|
||||
.then(res => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: !!res, data: res });
|
||||
})
|
||||
.catch((error: BsmException) => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false, error });
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("bs-version.clone", async (_event, req: IpcRequest<{ version: BSVersion; name: string; color: string }>) => {
|
||||
BSLocalVersionService.getInstance()
|
||||
.cloneVersion(req.args.version, req.args.name, req.args.color)
|
||||
.then(res => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: !!res, data: res });
|
||||
})
|
||||
.catch((error: BsmException) => {
|
||||
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false, error });
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on("get-version-full-path", async (req: IpcRequest<BSVersion>, reply) => {
|
||||
const localVersions = BSLocalVersionService.getInstance();
|
||||
reply(from(localVersions.getVersionPath(req.args)));
|
||||
});
|
||||
|
||||
ipc.on("relative-version-path-to-full", async (req: IpcRequest<{ version: BSVersion; relative: string }>, reply) => {
|
||||
path.isAbsolute(req.args.relative) && reply(from(Promise.resolve(req.args.relative)));
|
||||
|
||||
const localVersions = BSLocalVersionService.getInstance();
|
||||
const promise = localVersions
|
||||
.getVersionPath(req.args.version)
|
||||
.catch(() => null)
|
||||
.then(versionPath => {
|
||||
return path.join(versionPath, req.args.relative);
|
||||
});
|
||||
ipc.on("bs-version.open-folder", (args, reply) => {
|
||||
const versions = BSLocalVersionService.getInstance();
|
||||
const promise = versions.getVersionPath(args).then(versionFolder => {
|
||||
if(!versionFolder || !pathExists(versionFolder)) return;
|
||||
shell.openPath(versionFolder);
|
||||
})
|
||||
reply(from(promise));
|
||||
});
|
||||
|
||||
ipc.on("full-version-path-to-relative", async (req: IpcRequest<{ version: BSVersion; fullPath: string }>, reply) => {
|
||||
ipc.on("bs-version.edit", (args, reply) => {
|
||||
const versions = BSLocalVersionService.getInstance();
|
||||
reply(from(versions.editVersion(args.version, args.name, args.color)));
|
||||
});
|
||||
|
||||
ipc.on("bs-version.clone", (args, reply) => {
|
||||
const versions = BSLocalVersionService.getInstance();
|
||||
reply(from(versions.cloneVersion(args.version, args.name, args.color)));
|
||||
});
|
||||
|
||||
ipc.on("get-version-full-path", (args, reply) => {
|
||||
const localVersions = BSLocalVersionService.getInstance();
|
||||
const promise = localVersions
|
||||
.getVersionPath(req.args.version)
|
||||
.catch(() => null)
|
||||
.then(versionPath => {
|
||||
return path.relative(versionPath, req.args.fullPath);
|
||||
});
|
||||
reply(from(promise));
|
||||
reply(from(localVersions.getVersionPath(args)));
|
||||
});
|
||||
|
||||
ipc.on("get-linked-folders", async (req: IpcRequest<{ version: BSVersion; options?: { relative?: boolean } }>, reply) => {
|
||||
ipc.on("full-version-path-to-relative", (args, reply) => {
|
||||
const localVersions = BSLocalVersionService.getInstance();
|
||||
reply(from(localVersions.getVersionPath(args.version).then(versionPath => path.relative(versionPath, args.fullPath))));
|
||||
});
|
||||
|
||||
ipc.on("get-linked-folders", (args, reply) => {
|
||||
const versionLinker = VersionFolderLinkerService.getInstance();
|
||||
reply(from(versionLinker.getLinkedFolders(req.args.version, req.args.options)));
|
||||
reply(from(versionLinker.getLinkedFolders(args.version, args.options)));
|
||||
});
|
||||
|
||||
ipc.on("link-folder", async (req: IpcRequest<{ folder: string; options?: LinkOptions }>, reply) => {
|
||||
req.args.options ??= {};
|
||||
|
||||
const linker = FolderLinkerService.getInstance();
|
||||
|
||||
const relativeMapsFolder = path.join(LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
|
||||
|
||||
if (req.args.folder.includes(relativeMapsFolder)) {
|
||||
return reply(from(linker.linkFolder(req.args.folder, { keepContents: req.args.options?.keepContents, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER })));
|
||||
}
|
||||
|
||||
if (req.args.folder.includes("UserData")) {
|
||||
req.args.options = { ...req.args.options, backup: true };
|
||||
}
|
||||
|
||||
const res = from(linker.linkFolder(req.args.folder, req.args.options));
|
||||
|
||||
const jsonIPAPath = path.join(req.args.folder, "Beat Saber IPA.json");
|
||||
|
||||
if (!(await pathExist(jsonIPAPath))) {
|
||||
return reply(res);
|
||||
}
|
||||
|
||||
await res.toPromise();
|
||||
|
||||
try {
|
||||
const ipaData = (await readJSON(jsonIPAPath)) ?? ({} as any);
|
||||
ipaData.YeetMods = false;
|
||||
await writeJSON(jsonIPAPath, ipaData, { spaces: 4 });
|
||||
} catch (e) {
|
||||
log.error("Disable YeetMods", e);
|
||||
}
|
||||
|
||||
reply(res);
|
||||
});
|
||||
|
||||
ipc.on("link-version-folder-action", async (req: IpcRequest<VersionLinkerAction>, reply) => {
|
||||
ipc.on("link-version-folder-action", (args, reply) => {
|
||||
const versionLinker = VersionFolderLinkerService.getInstance();
|
||||
reply(from(versionLinker.doAction(req.args)));
|
||||
reply(from(versionLinker.doAction(args)));
|
||||
});
|
||||
|
||||
ipc.on("is-version-folder-linked", async (req: IpcRequest<{ version: BSVersion; relativeFolder: string }>, reply) => {
|
||||
ipc.on("is-version-folder-linked", (args, reply) => {
|
||||
const versionLinker = VersionFolderLinkerService.getInstance();
|
||||
reply(from(versionLinker.isFolderLinked(req.args.version, req.args.relativeFolder)));
|
||||
reply(from(versionLinker.isFolderLinked(args.version, args.relativeFolder)));
|
||||
});
|
||||
|
||||
ipc.on("unlink-folder", async (req: IpcRequest<{ folder: string; options?: LinkOptions }>, reply) => {
|
||||
req.args.options ??= {};
|
||||
|
||||
const linker = FolderLinkerService.getInstance();
|
||||
|
||||
const relativeMapsFolder = path.join(LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
|
||||
|
||||
if (req.args.folder.includes(relativeMapsFolder)) {
|
||||
return reply(from(linker.unlinkFolder(req.args.folder, { ...req.args.options, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER })));
|
||||
}
|
||||
|
||||
if (req.args.folder.includes("UserData")) {
|
||||
req.args.options = { ...req.args.options, backup: true };
|
||||
}
|
||||
|
||||
reply(from(linker.unlinkFolder(req.args.folder, req.args.options)));
|
||||
});
|
||||
|
||||
ipc.on("relink-all-versions-folders", async (req: IpcRequest<void>, reply) => {
|
||||
ipc.on("relink-all-versions-folders", (_, reply) => {
|
||||
const versionLinker = VersionFolderLinkerService.getInstance();
|
||||
reply(from(versionLinker.relinkAllVersionsFolders()));
|
||||
});
|
||||
|
||||
@@ -12,4 +12,3 @@ import "./bs-playlist-ipcs";
|
||||
import "./model-saber.ipcs";
|
||||
import "./bs-model-ipcs";
|
||||
import "./bs-version-download/bs-download-ipcs";
|
||||
import "./oculus.ipcs";
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { AutoUpdaterService } from "../services/auto-updater.service";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
import { from, of } from "rxjs";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipcMain.on("download-update", async (event, request: IpcRequest<void>) => {
|
||||
ipc.on("download-update", (_, reply) => {
|
||||
const updaterService = AutoUpdaterService.getInstance();
|
||||
const utilsService = UtilsService.getInstance();
|
||||
|
||||
updaterService
|
||||
.downloadUpdate()
|
||||
.then(res => utilsService.ipcSend(request.responceChannel, { success: res }))
|
||||
.catch(() => utilsService.ipcSend(request.responceChannel, { success: false }));
|
||||
reply(from(updaterService.downloadUpdate()));
|
||||
});
|
||||
|
||||
ipc.on("check-update", (_, reply) => {
|
||||
@@ -22,7 +14,7 @@ ipc.on("check-update", (_, reply) => {
|
||||
reply(from(updaterService.isUpdateAvailable()));
|
||||
});
|
||||
|
||||
ipcMain.on("install-update", async (event, request: IpcRequest<void>) => {
|
||||
ipc.on("install-update", (_, reply) => {
|
||||
const updaterService = AutoUpdaterService.getInstance();
|
||||
updaterService.quitAndInstall();
|
||||
reply(of(updaterService.quitAndInstall()));
|
||||
});
|
||||
|
||||
@@ -1,26 +1,15 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { ModelSaberService } from "../services/thrid-party/model-saber/model-saber.service";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { MSGetQuery } from "shared/models/models/model-saber.model";
|
||||
import { from } from "rxjs";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipcMain.on("ms-get-model-by-id", async (event, request: IpcRequest<string | number>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("ms-get-model-by-id", (args, reply) => {
|
||||
const ms = ModelSaberService.getInstance();
|
||||
|
||||
ms.getModelById(request.args)
|
||||
.then(model => {
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: model });
|
||||
})
|
||||
.catch(e => {
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
reply(from(ms.getModelById(args)));
|
||||
});
|
||||
|
||||
ipc.on<MSGetQuery>("search-models", async (req, reply) => {
|
||||
ipc.on("search-models", async (args, reply) => {
|
||||
const ms = ModelSaberService.getInstance();
|
||||
reply(ms.searchModels(req.args));
|
||||
reply(ms.searchModels(args));
|
||||
});
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { OculusService } from "../services/oculus.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on("is-oculus-sideloaded-apps-enabled", (_, reply) => {
|
||||
const oculusService = OculusService.getInstance();
|
||||
reply(from(oculusService.isSideLoadedAppsEnabled()));
|
||||
});
|
||||
|
||||
ipc.on("enable-oculus-sideloaded-apps", (_, reply) => {
|
||||
const oculusService = OculusService.getInstance();
|
||||
reply(from(oculusService.enableSideloadedApps()));
|
||||
});
|
||||
@@ -1,59 +1,64 @@
|
||||
import { ipcMain, shell, dialog, app, BrowserWindow } from "electron";
|
||||
import { UtilsService } from "../services/utils.service";
|
||||
import { IpcRequest } from "shared/models/ipc";
|
||||
import { SystemNotificationOptions } from "shared/models/notification/system-notification.model";
|
||||
import { shell, dialog, app, BrowserWindow } from "electron";
|
||||
import { NotificationService } from "../services/notification.service";
|
||||
import { SteamService } from "../services/steam.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from, of } from "rxjs";
|
||||
import { readFileSync } from "fs-extra";
|
||||
|
||||
// TODO IMPROVE WINDOW CONTROL BY USING WINDOW SERVICE
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipcMain.on("new-window", async (event, request: IpcRequest<string>) => {
|
||||
shell.openExternal(request.args);
|
||||
ipc.on("new-window", (args, reply) => {
|
||||
reply(from(shell.openExternal(args)));
|
||||
});
|
||||
|
||||
ipc.on<string>("choose-folder", async (req, reply) => {
|
||||
reply(from(dialog.showOpenDialog({ properties: ["openDirectory"], defaultPath: req.args ?? "" })));
|
||||
ipc.on("choose-folder", (args, reply) => {
|
||||
reply(from(dialog.showOpenDialog({ properties: ["openDirectory"], defaultPath: args ?? "" })));
|
||||
});
|
||||
|
||||
ipcMain.on("window.progression", async (event, request: IpcRequest<number>) => {
|
||||
BrowserWindow.fromWebContents(event.sender)?.setProgressBar(request.args / 100);
|
||||
ipc.on<string>("choose-file", async (args, reply) => {
|
||||
reply(from(dialog.showOpenDialog({ properties: ["openFile"], defaultPath: args ?? "" })));
|
||||
});
|
||||
|
||||
ipcMain.on("save-file", async (event, request: IpcRequest<{ filename?: string; filters?: Electron.FileFilter[] }>) => {
|
||||
dialog.showSaveDialog({ properties: ["showOverwriteConfirmation"], defaultPath: request.args.filename, filters: request.args.filters }).then(res => {
|
||||
const utils = UtilsService.getInstance();
|
||||
ipc.on("window.progression",(args, reply, sender) => {
|
||||
BrowserWindow.fromWebContents(sender)?.setProgressBar(args / 100);
|
||||
reply(of(undefined));
|
||||
});
|
||||
|
||||
ipc.on("save-file", (args, reply) => {
|
||||
reply(from(dialog.showSaveDialog({ properties: ["showOverwriteConfirmation"], defaultPath: args.filename, filters: args.filters }).then(res => {
|
||||
if (res.canceled || !res.filePath) {
|
||||
utils.ipcSend(request.responceChannel, { success: false });
|
||||
throw new Error("No file path selected");
|
||||
}
|
||||
UtilsService.getInstance().ipcSend(request.responceChannel, { success: true, data: res.filePath });
|
||||
});
|
||||
return res.filePath;
|
||||
})));
|
||||
});
|
||||
|
||||
ipc.on("current-version", (_, reply) => {
|
||||
reply(of(app.getVersion()));
|
||||
});
|
||||
|
||||
ipcMain.on("open-logs", async (event, request: IpcRequest<void>) => {
|
||||
shell.openPath(app.getPath("logs"));
|
||||
ipc.on("open-logs", (_, reply) => {
|
||||
reply(from(shell.openPath(app.getPath("logs"))));
|
||||
});
|
||||
|
||||
ipcMain.on("notify-system", async (event, request: IpcRequest<SystemNotificationOptions>) => {
|
||||
NotificationService.getInstance().notify(request.args);
|
||||
ipc.on("notify-system", (args, reply) => {
|
||||
const systemNotification = NotificationService.getInstance();
|
||||
reply(of(systemNotification.notify(args)));
|
||||
});
|
||||
|
||||
ipcMain.on("open-steam", async (event, request: IpcRequest<void>) => {
|
||||
const steam = SteamService.getInstance();
|
||||
const utils = UtilsService.getInstance();
|
||||
steam
|
||||
.openSteam()
|
||||
.then(res => {
|
||||
utils.ipcSend(request.responceChannel, { success: true, data: res });
|
||||
})
|
||||
.catch(e => {
|
||||
utils.ipcSend(request.responceChannel, { success: false, error: e });
|
||||
});
|
||||
ipc.on("view-path-in-explorer", (args, reply) => {
|
||||
reply(of(shell.showItemInFolder(args)));
|
||||
});
|
||||
|
||||
ipc.on("choose-image", (args, reply) => {
|
||||
reply(from(dialog.showOpenDialog({ properties: ["openFile", "multiSelections"], filters: [{ name: "Images", extensions: ["jpg", "png", "jpeg"] }] }).then(res => {
|
||||
if (res.canceled || !res.filePaths) {
|
||||
return [];
|
||||
}
|
||||
if(args.base64){
|
||||
return res.filePaths.map(path => Buffer.from(readFileSync(path)).toString("base64"));
|
||||
}
|
||||
return res.filePaths;
|
||||
})));
|
||||
});
|
||||
|
||||